mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-11-12 08:41:34 +00:00
* fix(routes): scope inline Express handlers and report api_impact lower bound Inline Express handlers are anonymous Function nodes named by position, but the route facts only recorded a handler name for bare identifiers. Routes with inline handlers therefore had no handlerSymbolId: every route in a file got the union of its handlers' response keys and every flow starting there. Record the positional name for inline handlers, read response keys from the resolved handler when a file registers several routes, and let processes link exactly by handlerSymbolId as they already do for named handlers. Count, per route, the files that pass its URL to a callee not proven to be a fetch wrapper (excluding proven consumers and the route's own file). The count is stored as Route.unverifiedConsumers; api_impact reports epistemic: 'lower-bound' with that count when it is non-zero. Older indexes without the column fall back to the previous query. Closes #3488 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(routes): match unverified consumers once per URL Memoize route matching per distinct fetch URL, skip the proven-consumer scan when no unproven call matches a route, and build the Route query's optional columns from a list instead of two booleans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(group): keep inline handlers attributed to their registrar Inline Express handlers now carry their positional Function name in the route facts so ingestion can resolve a handlerSymbolId. Group HTTP contracts read the same facts, but that name is a graph identity rather than a symbol name the contract lookup can match, so the provider lost its enclosing-registrar attribution. Ignore the name for inline handlers there. Rebaseline the two bench guards the branch moved: - emit-persistence: route.csv gains the header-only unverifiedConsumers field; stripping it restores the prior fingerprint exactly. - receiver-resolution: the new fixture's req.query.path read on an untyped inline-handler parameter adds one receiver-unresolved read (191 -> 192). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
71 lines
2.6 KiB
TypeScript
71 lines
2.6 KiB
TypeScript
/**
|
|
* Real-LadybugDB round trip for Spring Actuator Route evidence (#2418).
|
|
* Pins the schema, CSV, COPY, and graph-read projections that must agree for
|
|
* runtime-confirmed markers to survive beyond the in-memory ingestion graph.
|
|
*/
|
|
import fs from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { expect, it } from 'vitest';
|
|
import { getNodeQuery } from '../../src/server/api.js';
|
|
import { streamAllCSVsToDisk } from '../../src/core/lbug/csv-generator.js';
|
|
import { generateId } from '../../src/lib/utils.js';
|
|
import { buildTestGraph } from '../helpers/test-graph.js';
|
|
import { withTestLbugDB } from '../helpers/test-indexed-db.js';
|
|
|
|
const ROUTE_ID = generateId('Route', 'GET /runtime-confirmed');
|
|
|
|
withTestLbugDB('route-runtime-evidence-roundtrip', (handle) => {
|
|
it('persists and projects Route runtime evidence through CSV→COPY→query', async () => {
|
|
const adapter = await import('../../src/core/lbug/lbug-adapter.js');
|
|
const graph = buildTestGraph([
|
|
{
|
|
id: ROUTE_ID,
|
|
label: 'Route',
|
|
name: '/runtime-confirmed',
|
|
filePath: 'RuntimeController.java',
|
|
extra: {
|
|
method: 'GET',
|
|
responseKeys: [],
|
|
errorKeys: [],
|
|
middleware: [],
|
|
runtimeConfirmed: true,
|
|
runtimeSource: 'spring-actuator',
|
|
runtimeStatus: 'runtime-confirmed',
|
|
unverifiedConsumers: 3,
|
|
},
|
|
},
|
|
]);
|
|
|
|
const csvDir = path.join(handle.tmpHandle.dbPath, 'csv-runtime-evidence');
|
|
const repoDir = path.join(handle.tmpHandle.dbPath, 'repo-runtime-evidence');
|
|
await fs.mkdir(repoDir, { recursive: true });
|
|
await streamAllCSVsToDisk(graph, repoDir, csvDir);
|
|
|
|
const routeCsv = await fs.readFile(path.join(csvDir, 'route.csv'), 'utf8');
|
|
expect(routeCsv.split('\n')[0]).toContain(
|
|
'runtimeConfirmed,runtimeSource,runtimeStatus,unverifiedConsumers',
|
|
);
|
|
expect(routeCsv).toContain('spring-actuator');
|
|
|
|
const routeCsvPath = path.join(csvDir, 'route.csv').replace(/\\/g, '/');
|
|
await adapter.executeQuery(adapter.getCopyQuery('Route', routeCsvPath));
|
|
|
|
const rows = (await adapter.executeQuery(getNodeQuery('Route', false))) as Record<
|
|
string,
|
|
unknown
|
|
>[];
|
|
expect(rows).toContainEqual(
|
|
expect.objectContaining({
|
|
id: ROUTE_ID,
|
|
runtimeConfirmed: true,
|
|
runtimeSource: 'spring-actuator',
|
|
runtimeStatus: 'runtime-confirmed',
|
|
}),
|
|
);
|
|
expect(
|
|
await adapter.executeQuery(
|
|
`MATCH (n:Route) WHERE n.id = '${ROUTE_ID}' RETURN n.unverifiedConsumers AS unverifiedConsumers`,
|
|
),
|
|
).toEqual([{ unverifiedConsumers: 3 }]);
|
|
});
|
|
});
|