@vyuhlabs/dxkit 2.19.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/dist/allowlist/categories.d.ts.map +1 -1
- package/dist/allowlist/categories.js +4 -0
- package/dist/allowlist/categories.js.map +1 -1
- package/dist/allowlist/hint.d.ts.map +1 -1
- package/dist/allowlist/hint.js +6 -0
- package/dist/allowlist/hint.js.map +1 -1
- package/dist/analyzers/flow/config.d.ts +37 -0
- package/dist/analyzers/flow/config.d.ts.map +1 -0
- package/dist/analyzers/flow/config.js +84 -0
- package/dist/analyzers/flow/config.js.map +1 -0
- package/dist/analyzers/flow/contract.d.ts +93 -0
- package/dist/analyzers/flow/contract.d.ts.map +1 -0
- package/dist/analyzers/flow/contract.js +176 -0
- package/dist/analyzers/flow/contract.js.map +1 -0
- package/dist/analyzers/flow/gate.d.ts +64 -0
- package/dist/analyzers/flow/gate.d.ts.map +1 -0
- package/dist/analyzers/flow/gate.js +84 -0
- package/dist/analyzers/flow/gate.js.map +1 -0
- package/dist/analyzers/flow/gather.d.ts +11 -0
- package/dist/analyzers/flow/gather.d.ts.map +1 -1
- package/dist/analyzers/flow/gather.js +10 -9
- package/dist/analyzers/flow/gather.js.map +1 -1
- package/dist/analyzers/flow/model.d.ts +12 -0
- package/dist/analyzers/flow/model.d.ts.map +1 -1
- package/dist/analyzers/flow/model.js +25 -3
- package/dist/analyzers/flow/model.js.map +1 -1
- package/dist/analyzers/tools/fingerprint.d.ts +32 -0
- package/dist/analyzers/tools/fingerprint.d.ts.map +1 -1
- package/dist/analyzers/tools/fingerprint.js +37 -1
- package/dist/analyzers/tools/fingerprint.js.map +1 -1
- package/dist/baseline/check-renderers.d.ts +21 -0
- package/dist/baseline/check-renderers.d.ts.map +1 -1
- package/dist/baseline/check-renderers.js +93 -3
- package/dist/baseline/check-renderers.js.map +1 -1
- package/dist/baseline/check.d.ts +18 -0
- package/dist/baseline/check.d.ts.map +1 -1
- package/dist/baseline/check.js +21 -2
- package/dist/baseline/check.js.map +1 -1
- package/dist/baseline/entry-to-located.d.ts.map +1 -1
- package/dist/baseline/entry-to-located.js +7 -0
- package/dist/baseline/entry-to-located.js.map +1 -1
- package/dist/baseline/finding-identity.d.ts.map +1 -1
- package/dist/baseline/finding-identity.js +5 -0
- package/dist/baseline/finding-identity.js.map +1 -1
- package/dist/baseline/flow-gate-check.d.ts +60 -0
- package/dist/baseline/flow-gate-check.d.ts.map +1 -0
- package/dist/baseline/flow-gate-check.js +171 -0
- package/dist/baseline/flow-gate-check.js.map +1 -0
- package/dist/baseline/migrate.d.ts.map +1 -1
- package/dist/baseline/migrate.js +3 -0
- package/dist/baseline/migrate.js.map +1 -1
- package/dist/baseline/producers/index.d.ts.map +1 -1
- package/dist/baseline/producers/index.js +9 -0
- package/dist/baseline/producers/index.js.map +1 -1
- package/dist/baseline/show.js +2 -0
- package/dist/baseline/show.js.map +1 -1
- package/dist/baseline/types.d.ts +32 -2
- package/dist/baseline/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +46 -13
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/graph-adapter.d.ts.map +1 -1
- package/dist/dashboard/graph-adapter.js +1 -4
- package/dist/dashboard/graph-adapter.js.map +1 -1
- package/dist/explore/flow-graph.d.ts +62 -0
- package/dist/explore/flow-graph.d.ts.map +1 -0
- package/dist/explore/flow-graph.js +194 -0
- package/dist/explore/flow-graph.js.map +1 -0
- package/dist/explore/flow-view.d.ts +33 -0
- package/dist/explore/flow-view.d.ts.map +1 -0
- package/dist/explore/flow-view.js +85 -0
- package/dist/explore/flow-view.js.map +1 -0
- package/dist/explore/load.d.ts.map +1 -1
- package/dist/explore/load.js +16 -3
- package/dist/explore/load.js.map +1 -1
- package/dist/explore/queries.d.ts +92 -1
- package/dist/explore/queries.d.ts.map +1 -1
- package/dist/explore/queries.js +142 -0
- package/dist/explore/queries.js.map +1 -1
- package/dist/explore/types.d.ts +56 -3
- package/dist/explore/types.d.ts.map +1 -1
- package/dist/explore/types.js +10 -2
- package/dist/explore/types.js.map +1 -1
- package/dist/flow-cli.d.ts +32 -0
- package/dist/flow-cli.d.ts.map +1 -1
- package/dist/flow-cli.js +168 -21
- package/dist/flow-cli.js.map +1 -1
- package/dist/languages/index.d.ts +21 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +41 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/loop/policy.d.ts +4 -1
- package/dist/loop/policy.d.ts.map +1 -1
- package/dist/loop/policy.js +3 -0
- package/dist/loop/policy.js.map +1 -1
- package/dist/loop/stop-gate.d.ts.map +1 -1
- package/dist/loop/stop-gate.js +8 -2
- package/dist/loop/stop-gate.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/D;8EAC8E;AAC9E,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,eAAe,CAAC;AAExD,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B;;sEAEkE;IAClE,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,EAAE,SAAS,eAAe,EAAE,CAAC;IAClD,yDAAyD;IACzD,QAAQ,CAAC,YAAY,EAAE,SAAS,eAAe,EAAE,CAAC;IAClD;uDACmD;IACnD,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,mCAAmC;IACnC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC;6EACyE;IACzE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,iBAAiB,EAAE,CAwCxE;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,GAAG,OAAO,CAE9E;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAMtE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The integration-breakage gate — pure evaluation core.
|
|
4
|
+
*
|
|
5
|
+
* Answers "does this diff NET-NEW break a UI→API integration?" from a base↔HEAD
|
|
6
|
+
* contract comparison, with no running system. One algorithm covers both
|
|
7
|
+
* directions (CLAUDE.md design §6):
|
|
8
|
+
* - a FRONTEND PR that adds a call to an endpoint no backend serves, and
|
|
9
|
+
* - a BACKEND PR that removes/renames a route a frontend still calls,
|
|
10
|
+
* because both reduce to "a consumed binding whose (method, path) is not in the
|
|
11
|
+
* served set". The diff makes it net-new: a binding already broken BEFORE the
|
|
12
|
+
* PR (present at base and unresolved against the base served set) is
|
|
13
|
+
* grandfathered; only a binding the PR NEWLY breaks is surfaced.
|
|
14
|
+
*
|
|
15
|
+
* Pure over its inputs — the ref-based gather (base worktree via
|
|
16
|
+
* `withRefWorktree`, Rule 11) and the guardrail wiring live above this module;
|
|
17
|
+
* here we only diff two already-materialized contract sides. Identity is the
|
|
18
|
+
* flow-binding fingerprint (line-independent (method, path, file), Rule 9),
|
|
19
|
+
* computed through the canonical helper so an emitted finding shares one
|
|
20
|
+
* identity contract with the baseline + allowlist.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.evaluateFlowGate = evaluateFlowGate;
|
|
24
|
+
exports.flowGateBlocks = flowGateBlocks;
|
|
25
|
+
exports.describeBrokenIntegration = describeBrokenIntegration;
|
|
26
|
+
const fingerprint_1 = require("../tools/fingerprint");
|
|
27
|
+
const contract_1 = require("./contract");
|
|
28
|
+
/** The flow-binding identity tuple as a map key (method, path, file). */
|
|
29
|
+
function identityKey(b) {
|
|
30
|
+
return `${b.method}\0${b.path}\0${b.file}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Evaluate the gate. Returns every NET-NEW broken integration, most-severe
|
|
34
|
+
* (block before warn) first, then by location for stable output. Empty when the
|
|
35
|
+
* diff breaks nothing new.
|
|
36
|
+
*/
|
|
37
|
+
function evaluateFlowGate(inputs) {
|
|
38
|
+
const blockThreshold = inputs.blockThreshold ?? 1;
|
|
39
|
+
const baseByIdentity = new Map();
|
|
40
|
+
for (const b of inputs.baseConsumed)
|
|
41
|
+
baseByIdentity.set(identityKey(b), b);
|
|
42
|
+
const out = [];
|
|
43
|
+
for (const b of inputs.headConsumed) {
|
|
44
|
+
const key = (0, contract_1.contractKey)(b.method, b.path);
|
|
45
|
+
if (inputs.headServed.has(key))
|
|
46
|
+
continue; // resolves at HEAD → not broken
|
|
47
|
+
// Broken at HEAD. Was the SAME binding already broken at base? (present at
|
|
48
|
+
// base AND unresolved against the base served set) → grandfathered.
|
|
49
|
+
const base = baseByIdentity.get(identityKey(b));
|
|
50
|
+
const brokenBefore = base !== undefined && !inputs.baseServed.has(key);
|
|
51
|
+
if (brokenBefore)
|
|
52
|
+
continue;
|
|
53
|
+
// Net-new. `route-removed` when the binding existed at base and WAS served
|
|
54
|
+
// then (the PR removed the route); otherwise the call itself is new or
|
|
55
|
+
// never resolved (`no-route`).
|
|
56
|
+
const reason = base !== undefined && inputs.baseServed.has(key) ? 'route-removed' : 'no-route';
|
|
57
|
+
out.push({
|
|
58
|
+
id: (0, fingerprint_1.computeFlowBindingFingerprint)(b.method, b.path, b.file),
|
|
59
|
+
method: b.method,
|
|
60
|
+
path: b.path,
|
|
61
|
+
file: b.file,
|
|
62
|
+
line: b.line,
|
|
63
|
+
confidence: b.confidence,
|
|
64
|
+
reason,
|
|
65
|
+
verdict: b.confidence >= blockThreshold ? 'block' : 'warn',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
out.sort((a, z) => Number(z.verdict === 'block') - Number(a.verdict === 'block') ||
|
|
69
|
+
a.file.localeCompare(z.file) ||
|
|
70
|
+
a.path.localeCompare(z.path));
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/** Does the gate result block? True when any finding's verdict is `block`. */
|
|
74
|
+
function flowGateBlocks(findings) {
|
|
75
|
+
return findings.some((f) => f.verdict === 'block');
|
|
76
|
+
}
|
|
77
|
+
/** Human-readable one-liner for a broken integration (report + Stop-gate). */
|
|
78
|
+
function describeBrokenIntegration(f) {
|
|
79
|
+
const what = f.reason === 'route-removed'
|
|
80
|
+
? `removed ${f.method} ${f.path} still called by`
|
|
81
|
+
: `${f.method} ${f.path} matches no served route —`;
|
|
82
|
+
return `net-new broken integration: ${what} ${f.file}:${f.line}`;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../../src/analyzers/flow/gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,17 @@ export interface GatherFlowOptions {
|
|
|
18
18
|
readonly specs?: readonly string[];
|
|
19
19
|
/** Host-helper prefixes to strip during URL normalization (per-app config). */
|
|
20
20
|
readonly stripUrlPrefixes?: readonly string[];
|
|
21
|
+
/**
|
|
22
|
+
* Relabel every extracted call / route `file` relative to this directory.
|
|
23
|
+
* Off by default (files keep their scanned absolute path — the M2 map/trace
|
|
24
|
+
* display form). The flow-binding identity contract (Rule 9) requires an
|
|
25
|
+
* environment-INDEPENDENT locator, so the gate and `flow refresh` set this to
|
|
26
|
+
* the repo root: a binding gathered from the working tree and the same file
|
|
27
|
+
* gathered from a detached worktree then share one relative `file`, and the
|
|
28
|
+
* committed `consumed.json` carries repo-relative paths that mean the same
|
|
29
|
+
* thing on any machine.
|
|
30
|
+
*/
|
|
31
|
+
readonly relativeTo?: string;
|
|
21
32
|
}
|
|
22
33
|
/** Walk + extract + assemble. Files that don't parse are skipped, never fatal. */
|
|
23
34
|
export declare function gatherFlowModel(opts: GatherFlowOptions): Promise<FlowModel>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/gather.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzD,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/gather.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzD,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAgBD,kFAAkF;AAClF,wBAAsB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,CAgBjF"}
|
|
@@ -21,14 +21,15 @@ const model_1 = require("./model");
|
|
|
21
21
|
const spec_source_1 = require("./spec-source");
|
|
22
22
|
/** Extensions of packs that can contribute flow (httpFlow + a grammar). */
|
|
23
23
|
function flowExtensions() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
return (0, languages_1.allFlowSourceExtensions)(languages_1.LANGUAGES);
|
|
25
|
+
}
|
|
26
|
+
/** Relabel a file surface's call/route paths relative to `base`. */
|
|
27
|
+
function relabelFileFlow(flow, base) {
|
|
28
|
+
const rel = (f) => (0, path_1.relative)(base, f);
|
|
29
|
+
return {
|
|
30
|
+
calls: flow.calls.map((c) => ({ ...c, file: rel(c.file) })),
|
|
31
|
+
routes: flow.routes.map((r) => ({ ...r, file: rel(r.file) })),
|
|
32
|
+
};
|
|
32
33
|
}
|
|
33
34
|
/** Walk + extract + assemble. Files that don't parse are skipped, never fatal. */
|
|
34
35
|
async function gatherFlowModel(opts) {
|
|
@@ -39,7 +40,7 @@ async function gatherFlowModel(opts) {
|
|
|
39
40
|
for (const rel of (0, walk_source_files_1.walkSourceFiles)(root, { extensions })) {
|
|
40
41
|
const flow = await (0, extract_1.extractFileFlow)((0, path_1.join)(root, rel), config);
|
|
41
42
|
if (flow)
|
|
42
|
-
fileFlows.push(flow);
|
|
43
|
+
fileFlows.push(opts.relativeTo ? relabelFileFlow(flow, opts.relativeTo) : flow);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
// Served side = extracted routes UNION spec routes (dedup is implicit: the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gather.js","sourceRoot":"","sources":["../../../src/analyzers/flow/gather.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;
|
|
1
|
+
{"version":3,"file":"gather.js","sourceRoot":"","sources":["../../../src/analyzers/flow/gather.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AA6CH,0CAgBC;AA3DD,+BAAsC;AACtC,+CAAqE;AACrE,kEAA6D;AAC7D,uCAA2D;AAC3D,mCAAyD;AACzD,+CAAkD;AAuBlD,2EAA2E;AAC3E,SAAS,cAAc;IACrB,OAAO,IAAA,mCAAuB,EAAC,qBAAS,CAAC,CAAC;AAC5C,CAAC;AAED,oEAAoE;AACpE,SAAS,eAAe,CAAC,IAAc,EAAE,IAAY;IACnD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,IAAA,eAAQ,EAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED,kFAAkF;AAC3E,KAAK,UAAU,eAAe,CAAC,IAAuB;IAC3D,MAAM,MAAM,GAAoB,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC5E,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,SAAS,GAAe,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,IAAA,mCAAe,EAAC,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAe,EAAC,IAAA,WAAI,EAAC,IAAI,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;YAC5D,IAAI,IAAI;gBAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,+BAAiB,EAAC,IAAI,CAAC,CAAC,CAAC;IACjF,OAAO,IAAA,sBAAc,EAAC,CAAC,GAAG,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -39,11 +39,23 @@ export interface FlowModel {
|
|
|
39
39
|
readonly routes: readonly RouteEndpoint[];
|
|
40
40
|
readonly bindings: readonly FlowBinding[];
|
|
41
41
|
}
|
|
42
|
+
/** A path made up entirely of `{var}` segments carries no static signal. One
|
|
43
|
+
* source of truth (Rule 2) for both the join's confidence and the gate's
|
|
44
|
+
* confidence gating (a placeholder-only path is too generic to block on). */
|
|
45
|
+
export declare function isPlaceholderOnlyPath(path: string): boolean;
|
|
42
46
|
/**
|
|
43
47
|
* Bind each client call to the route it targets, on the normalized
|
|
44
48
|
* `(method, path)` key. Routes are indexed once; each call resolves in O(1).
|
|
45
49
|
*/
|
|
46
50
|
export declare function joinFlow(calls: readonly ClientCall[], routes: readonly RouteEndpoint[]): FlowBinding[];
|
|
51
|
+
/**
|
|
52
|
+
* Dedup served routes to one per distinct `(method, path)` — the canonical
|
|
53
|
+
* "what this repo serves" set. A route surfaced by both a spec and static
|
|
54
|
+
* extraction collapses to one, spec winning (authoritative handler +
|
|
55
|
+
* provenance). One source of truth (Rule 2) for the graph overlay's endpoint
|
|
56
|
+
* nodes AND the served contract snapshot.
|
|
57
|
+
*/
|
|
58
|
+
export declare function dedupeServedRoutes(routes: readonly RouteEndpoint[]): RouteEndpoint[];
|
|
47
59
|
/** Flatten per-file surfaces into one model + its bindings. */
|
|
48
60
|
export declare function buildFlowModel(fileFlows: readonly FileFlow[]): FlowModel;
|
|
49
61
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAmB,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,kBAAkB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnF,mEAAmE;AACnE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAED,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC3C;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAmB,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,kBAAkB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnF,mEAAmE;AACnE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAED,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC3C;AAED;;8EAE8E;AAC9E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,MAAM,EAAE,SAAS,aAAa,EAAE,GAC/B,WAAW,EAAE,CAaf;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,EAAE,CAUpF;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,CAIxE;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CAOpB;AAED,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CAUvD"}
|
|
@@ -16,13 +16,17 @@
|
|
|
16
16
|
* the I/O); this module just structures + joins.
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.isPlaceholderOnlyPath = isPlaceholderOnlyPath;
|
|
19
20
|
exports.joinFlow = joinFlow;
|
|
21
|
+
exports.dedupeServedRoutes = dedupeServedRoutes;
|
|
20
22
|
exports.buildFlowModel = buildFlowModel;
|
|
21
23
|
exports.extractFlowModel = extractFlowModel;
|
|
22
24
|
exports.summarize = summarize;
|
|
23
25
|
const extract_1 = require("./extract");
|
|
24
|
-
/** A path made up entirely of `{var}` segments carries no static signal.
|
|
25
|
-
|
|
26
|
+
/** A path made up entirely of `{var}` segments carries no static signal. One
|
|
27
|
+
* source of truth (Rule 2) for both the join's confidence and the gate's
|
|
28
|
+
* confidence gating (a placeholder-only path is too generic to block on). */
|
|
29
|
+
function isPlaceholderOnlyPath(path) {
|
|
26
30
|
return /^(\/\{var\})+$/.test(path);
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
@@ -39,12 +43,30 @@ function joinFlow(calls, routes) {
|
|
|
39
43
|
const route = routeIndex.get(`${call.method} ${call.path}`) ?? null;
|
|
40
44
|
if (!route)
|
|
41
45
|
return { call, route: null, confidence: 0, reason: 'no-route' };
|
|
42
|
-
if (
|
|
46
|
+
if (isPlaceholderOnlyPath(call.path)) {
|
|
43
47
|
return { call, route, confidence: 0.3, reason: 'placeholder-only' };
|
|
44
48
|
}
|
|
45
49
|
return { call, route, confidence: 1, reason: 'exact' };
|
|
46
50
|
});
|
|
47
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Dedup served routes to one per distinct `(method, path)` — the canonical
|
|
54
|
+
* "what this repo serves" set. A route surfaced by both a spec and static
|
|
55
|
+
* extraction collapses to one, spec winning (authoritative handler +
|
|
56
|
+
* provenance). One source of truth (Rule 2) for the graph overlay's endpoint
|
|
57
|
+
* nodes AND the served contract snapshot.
|
|
58
|
+
*/
|
|
59
|
+
function dedupeServedRoutes(routes) {
|
|
60
|
+
const byKey = new Map();
|
|
61
|
+
for (const route of routes) {
|
|
62
|
+
const key = `${route.method} ${route.path}`;
|
|
63
|
+
const existing = byKey.get(key);
|
|
64
|
+
if (!existing || (existing.via !== 'spec' && route.via === 'spec')) {
|
|
65
|
+
byKey.set(key, route);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return [...byKey.values()];
|
|
69
|
+
}
|
|
48
70
|
/** Flatten per-file surfaces into one model + its bindings. */
|
|
49
71
|
function buildFlowModel(fileFlows) {
|
|
50
72
|
const calls = fileFlows.flatMap((f) => f.calls);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/analyzers/flow/model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/analyzers/flow/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -212,6 +212,38 @@ export declare const SECRET_CANONICAL_RULE = "canonical:secret";
|
|
|
212
212
|
* matched content (or, for code, its enclosing symbol) changes.
|
|
213
213
|
*/
|
|
214
214
|
export declare function computeContentFingerprint(canonicalRule: string, file: string, contentAnchor: string): string;
|
|
215
|
+
/**
|
|
216
|
+
* Tool-independent canonical rule for a flow binding — a UI call site's
|
|
217
|
+
* dependency on a served `(method, path)`. Every flow binding shares this
|
|
218
|
+
* constant (like secrets share `SECRET_CANONICAL_RULE`) because the finding is
|
|
219
|
+
* intrinsic ("this component depends on this endpoint"), never a per-tool
|
|
220
|
+
* classification.
|
|
221
|
+
*/
|
|
222
|
+
export declare const FLOW_BINDING_CANONICAL_RULE = "canonical:flow-binding";
|
|
223
|
+
/**
|
|
224
|
+
* Durable identity for a flow binding (the `flow-binding` kind — the unit the
|
|
225
|
+
* integration gate grandfathers). A binding IS "this consumer file depends on
|
|
226
|
+
* this `(method, path)`", so identity is exactly that triple — and nothing
|
|
227
|
+
* else. It is fully LINE-INDEPENDENT by construction (no line, no line-window
|
|
228
|
+
* bucket), which is strictly more robust than the v1 line-window scheme: the
|
|
229
|
+
* call can move anywhere in the file, be reformatted, or gain siblings above
|
|
230
|
+
* it, and the binding keeps its identity. Motion within a file simply is not a
|
|
231
|
+
* change to which endpoint the file depends on.
|
|
232
|
+
*
|
|
233
|
+
* Hashes only inputs dxkit derives itself (Rule 9) — the NORMALIZED join key
|
|
234
|
+
* (`GET`, `/articles/{var}`, never a tool's raw URL capture) and the consuming
|
|
235
|
+
* file dxkit read from its own AST pass — so a committed baseline keeps
|
|
236
|
+
* matching when the scan moves to CI. Multiple calls to the same endpoint from
|
|
237
|
+
* one file collapse to one identity, which is correct: the file depends on the
|
|
238
|
+
* endpoint once, however many call sites express it. A pure file rename is
|
|
239
|
+
* relocated by the matcher's whole-file rename pass (the file locator in
|
|
240
|
+
* `entryToLocated`), not by the hash.
|
|
241
|
+
*
|
|
242
|
+
* Deliberately NOT the graph's enclosing symbol: that would couple identity to
|
|
243
|
+
* graphify, and the flow layer is graphify-independent by design. Reusing
|
|
244
|
+
* `computeContentFingerprint` keeps every SHA-1 scheme in this one module.
|
|
245
|
+
*/
|
|
246
|
+
export declare function computeFlowBindingFingerprint(method: string, path: string, file: string): string;
|
|
215
247
|
/**
|
|
216
248
|
* HMAC-SHA256 of a detected secret value, keyed by a per-repo salt.
|
|
217
249
|
* The output is 16-char lowercase hex (first 8 bytes of the 32-byte
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GAAG,MAAM,CAST;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GAAG,MAAM,CAGT;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAGT;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,IAAI,CAIlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,GAAG,MAAM,EAAE,CAMrF;AAID;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAmBzD,CAAC;AAEH,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhG;AAwCD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,qDAAqD;AACrD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,GACpB,MAAM,CAGR;AAID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtE"}
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/fingerprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* repo scale. Producers may render either inline interchangeably.
|
|
36
36
|
*/
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.SECRET_CANONICAL_RULE = exports.CODE_FINGERPRINT_LINE_WINDOW = exports.CANONICAL_RULE_MAP = void 0;
|
|
38
|
+
exports.FLOW_BINDING_CANONICAL_RULE = exports.SECRET_CANONICAL_RULE = exports.CODE_FINGERPRINT_LINE_WINDOW = exports.CANONICAL_RULE_MAP = void 0;
|
|
39
39
|
exports.canonicalAdvisoryId = canonicalAdvisoryId;
|
|
40
40
|
exports.computeFingerprint = computeFingerprint;
|
|
41
41
|
exports.computeFingerprintV1 = computeFingerprintV1;
|
|
@@ -50,6 +50,7 @@ exports.codeContentAnchor = codeContentAnchor;
|
|
|
50
50
|
exports.codeContentAnchorFromHash = codeContentAnchorFromHash;
|
|
51
51
|
exports.secretContentAnchor = secretContentAnchor;
|
|
52
52
|
exports.computeContentFingerprint = computeContentFingerprint;
|
|
53
|
+
exports.computeFlowBindingFingerprint = computeFlowBindingFingerprint;
|
|
53
54
|
exports.computeSecretHmac = computeSecretHmac;
|
|
54
55
|
const crypto_1 = require("crypto");
|
|
55
56
|
/**
|
|
@@ -322,6 +323,41 @@ function computeContentFingerprint(canonicalRule, file, contentAnchor) {
|
|
|
322
323
|
const input = `${canonicalRule}\0${file}\0${contentAnchor}`;
|
|
323
324
|
return (0, crypto_1.createHash)('sha1').update(input).digest('hex').slice(0, 16);
|
|
324
325
|
}
|
|
326
|
+
// ─── Flow-binding identity (the integration gate, Rule 9) ─────────────────────
|
|
327
|
+
/**
|
|
328
|
+
* Tool-independent canonical rule for a flow binding — a UI call site's
|
|
329
|
+
* dependency on a served `(method, path)`. Every flow binding shares this
|
|
330
|
+
* constant (like secrets share `SECRET_CANONICAL_RULE`) because the finding is
|
|
331
|
+
* intrinsic ("this component depends on this endpoint"), never a per-tool
|
|
332
|
+
* classification.
|
|
333
|
+
*/
|
|
334
|
+
exports.FLOW_BINDING_CANONICAL_RULE = 'canonical:flow-binding';
|
|
335
|
+
/**
|
|
336
|
+
* Durable identity for a flow binding (the `flow-binding` kind — the unit the
|
|
337
|
+
* integration gate grandfathers). A binding IS "this consumer file depends on
|
|
338
|
+
* this `(method, path)`", so identity is exactly that triple — and nothing
|
|
339
|
+
* else. It is fully LINE-INDEPENDENT by construction (no line, no line-window
|
|
340
|
+
* bucket), which is strictly more robust than the v1 line-window scheme: the
|
|
341
|
+
* call can move anywhere in the file, be reformatted, or gain siblings above
|
|
342
|
+
* it, and the binding keeps its identity. Motion within a file simply is not a
|
|
343
|
+
* change to which endpoint the file depends on.
|
|
344
|
+
*
|
|
345
|
+
* Hashes only inputs dxkit derives itself (Rule 9) — the NORMALIZED join key
|
|
346
|
+
* (`GET`, `/articles/{var}`, never a tool's raw URL capture) and the consuming
|
|
347
|
+
* file dxkit read from its own AST pass — so a committed baseline keeps
|
|
348
|
+
* matching when the scan moves to CI. Multiple calls to the same endpoint from
|
|
349
|
+
* one file collapse to one identity, which is correct: the file depends on the
|
|
350
|
+
* endpoint once, however many call sites express it. A pure file rename is
|
|
351
|
+
* relocated by the matcher's whole-file rename pass (the file locator in
|
|
352
|
+
* `entryToLocated`), not by the hash.
|
|
353
|
+
*
|
|
354
|
+
* Deliberately NOT the graph's enclosing symbol: that would couple identity to
|
|
355
|
+
* graphify, and the flow layer is graphify-independent by design. Reusing
|
|
356
|
+
* `computeContentFingerprint` keeps every SHA-1 scheme in this one module.
|
|
357
|
+
*/
|
|
358
|
+
function computeFlowBindingFingerprint(method, path, file) {
|
|
359
|
+
return computeContentFingerprint(exports.FLOW_BINDING_CANONICAL_RULE, file, `${method} ${path}`);
|
|
360
|
+
}
|
|
325
361
|
// ─── Secret HMAC primitive ───────────────────────────────────────────────────
|
|
326
362
|
/**
|
|
327
363
|
* HMAC-SHA256 of a detected secret value, keyed by a per-repo salt.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../../src/analyzers/tools/fingerprint.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;;;AAeH,kDAYC;AAYD,gDAOC;AAYD,oDAOC;AAYD,8CAIC;AAYD,kDAMC;AAqCD,4CAEC;AAqBD,sCAEC;AAQD,wDAGC;AA+CD,sCAEC;AAGD,4BAEC;AAUD,8CAEC;AAYD,8DAMC;AAqBD,kDAEC;AAwBD,8DAOC;AA6BD,8CAEC;
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../../src/analyzers/tools/fingerprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -115,6 +115,27 @@ export interface GuardrailJsonPayload {
|
|
|
115
115
|
};
|
|
116
116
|
readonly reasons: ReadonlyArray<MatchReason>;
|
|
117
117
|
}>;
|
|
118
|
+
/** The flow integration gate — net-new UI→API breakages from the base↔HEAD
|
|
119
|
+
* contract diff. Absent in committed modes (the gate runs only ref-based).
|
|
120
|
+
* When present but `ran` is false, `skipped` says why (e.g. no flow-surface
|
|
121
|
+
* change, no served-side truth). */
|
|
122
|
+
readonly flowGate?: {
|
|
123
|
+
readonly ran: boolean;
|
|
124
|
+
readonly skipped?: string;
|
|
125
|
+
readonly mode: string;
|
|
126
|
+
readonly blocks: boolean;
|
|
127
|
+
readonly warns: boolean;
|
|
128
|
+
readonly findings: ReadonlyArray<{
|
|
129
|
+
readonly id: string;
|
|
130
|
+
readonly method: string;
|
|
131
|
+
readonly path: string;
|
|
132
|
+
readonly file: string;
|
|
133
|
+
readonly line: number;
|
|
134
|
+
readonly confidence: number;
|
|
135
|
+
readonly reason: string;
|
|
136
|
+
readonly verdict: 'block' | 'warn';
|
|
137
|
+
}>;
|
|
138
|
+
};
|
|
118
139
|
}
|
|
119
140
|
export declare function renderJson(result: GuardrailCheckResult): GuardrailJsonPayload;
|
|
120
141
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-renderers.d.ts","sourceRoot":"","sources":["../../src/baseline/check-renderers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAkB,aAAa,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"check-renderers.d.ts","sourceRoot":"","sources":["../../src/baseline/check-renderers.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,6 +64,7 @@ exports.renderConsole = renderConsole;
|
|
|
64
64
|
exports.renderJson = renderJson;
|
|
65
65
|
exports.renderMarkdown = renderMarkdown;
|
|
66
66
|
const logger = __importStar(require("../logger"));
|
|
67
|
+
const gate_1 = require("../analyzers/flow/gate");
|
|
67
68
|
// ─── Shared verdict predicates ────────────────────────────────────────────
|
|
68
69
|
/**
|
|
69
70
|
* Whether a pair was accepted by an active allowlist entry. Such a
|
|
@@ -146,6 +147,7 @@ function renderConsole(result) {
|
|
|
146
147
|
lines.push(...formatPairLines(p, ' '));
|
|
147
148
|
lines.push('');
|
|
148
149
|
}
|
|
150
|
+
lines.push(...formatFlowGate(result.flowGate));
|
|
149
151
|
// Always show a summary footer — sets expectations for what
|
|
150
152
|
// happens next (exit code, what to read on a fail).
|
|
151
153
|
lines.push(logger.bold('Summary'));
|
|
@@ -168,13 +170,40 @@ function renderConsole(result) {
|
|
|
168
170
|
}
|
|
169
171
|
return lines.join('\n');
|
|
170
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Console lines for the flow integration gate. Silent unless the gate produced
|
|
175
|
+
* findings — a skipped or clean gate adds no noise. Blocking breakages are
|
|
176
|
+
* grouped separately from warnings so the actionable set surfaces first.
|
|
177
|
+
*/
|
|
178
|
+
function formatFlowGate(flow) {
|
|
179
|
+
if (!flow || flow.findings.length === 0)
|
|
180
|
+
return [];
|
|
181
|
+
const out = [];
|
|
182
|
+
const blocking = flow.findings.filter((f) => f.verdict === 'block');
|
|
183
|
+
const warning = flow.findings.filter((f) => f.verdict === 'warn');
|
|
184
|
+
if (blocking.length > 0) {
|
|
185
|
+
out.push(logger.bold(`Flow breakage — blocking (${blocking.length})`));
|
|
186
|
+
for (const f of blocking)
|
|
187
|
+
out.push(` ${(0, gate_1.describeBrokenIntegration)(f)}`);
|
|
188
|
+
out.push('');
|
|
189
|
+
}
|
|
190
|
+
if (warning.length > 0) {
|
|
191
|
+
out.push(logger.bold(`Flow breakage — warning (${warning.length})`));
|
|
192
|
+
for (const f of warning)
|
|
193
|
+
out.push(` ${(0, gate_1.describeBrokenIntegration)(f)}`);
|
|
194
|
+
out.push('');
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
171
198
|
function verdictBanner(result) {
|
|
199
|
+
const flow = result.flowGate?.findings ?? [];
|
|
172
200
|
if (result.blocks) {
|
|
173
|
-
const count = result.pairs.filter(isBlocking).length;
|
|
201
|
+
const count = result.pairs.filter(isBlocking).length + flow.filter((f) => f.verdict === 'block').length;
|
|
174
202
|
return logger.bold(`Guardrail BLOCKED — ${count} new regression${count === 1 ? '' : 's'}`);
|
|
175
203
|
}
|
|
176
204
|
if (result.warns) {
|
|
177
|
-
const count = result.pairs.filter((p) => p.classification.warns).length
|
|
205
|
+
const count = result.pairs.filter((p) => p.classification.warns).length +
|
|
206
|
+
flow.filter((f) => f.verdict === 'warn').length;
|
|
178
207
|
return logger.bold(`Guardrail PASSED — ${count} warning${count === 1 ? '' : 's'}`);
|
|
179
208
|
}
|
|
180
209
|
return logger.bold('Guardrail PASSED');
|
|
@@ -332,6 +361,27 @@ function renderJson(result) {
|
|
|
332
361
|
: {}),
|
|
333
362
|
reasons: p.classification.reasons,
|
|
334
363
|
})),
|
|
364
|
+
...(result.flowGate !== undefined
|
|
365
|
+
? {
|
|
366
|
+
flowGate: {
|
|
367
|
+
ran: result.flowGate.ran,
|
|
368
|
+
...(result.flowGate.skipped !== undefined ? { skipped: result.flowGate.skipped } : {}),
|
|
369
|
+
mode: result.flowGate.mode,
|
|
370
|
+
blocks: result.flowGate.blocks,
|
|
371
|
+
warns: result.flowGate.warns,
|
|
372
|
+
findings: result.flowGate.findings.map((f) => ({
|
|
373
|
+
id: f.id,
|
|
374
|
+
method: f.method,
|
|
375
|
+
path: f.path,
|
|
376
|
+
file: f.file,
|
|
377
|
+
line: f.line,
|
|
378
|
+
confidence: f.confidence,
|
|
379
|
+
reason: f.reason,
|
|
380
|
+
verdict: f.verdict,
|
|
381
|
+
})),
|
|
382
|
+
},
|
|
383
|
+
}
|
|
384
|
+
: {}),
|
|
335
385
|
};
|
|
336
386
|
}
|
|
337
387
|
// ─── Markdown renderer ────────────────────────────────────────────────────
|
|
@@ -355,7 +405,10 @@ function renderMarkdown(result) {
|
|
|
355
405
|
const verdict = result.blocks ? 'BLOCKED' : result.warns ? 'PASSED (with warnings)' : 'PASSED';
|
|
356
406
|
lines.push(`## Guardrail: ${verdict}`);
|
|
357
407
|
lines.push('');
|
|
358
|
-
|
|
408
|
+
const flow = result.flowGate?.findings ?? [];
|
|
409
|
+
const flowBlocking = flow.filter((f) => f.verdict === 'block').length;
|
|
410
|
+
const flowWarning = flow.filter((f) => f.verdict === 'warn').length;
|
|
411
|
+
lines.push(summarySentence(result, blocking.length + flowBlocking, warning.length + flowWarning, resolved.length));
|
|
359
412
|
lines.push('');
|
|
360
413
|
if (result.refExcludedKinds.length > 0) {
|
|
361
414
|
const detail = result.refExcludedKinds.map((e) => `${e.currentCount} ${e.kind}`).join(', ');
|
|
@@ -373,6 +426,7 @@ function renderMarkdown(result) {
|
|
|
373
426
|
lines.push(markdownPairRow(p));
|
|
374
427
|
lines.push('');
|
|
375
428
|
}
|
|
429
|
+
lines.push(...markdownFlowGate(result.flowGate));
|
|
376
430
|
if (suppressed.length > 0) {
|
|
377
431
|
lines.push('<details>');
|
|
378
432
|
lines.push(`<summary>Suppressed by allowlist (${suppressed.length})</summary>`);
|
|
@@ -437,6 +491,42 @@ function renderMarkdown(result) {
|
|
|
437
491
|
`_dxkit_: ${escapeMd(result.current.analysisMeta.dxkitVersion)}`);
|
|
438
492
|
return lines.join('\n');
|
|
439
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* Markdown for the flow integration gate. Blocking breakages render as a
|
|
496
|
+
* top-level table (they fail the PR); warnings collapse into a `<details>`.
|
|
497
|
+
* Silent when the gate produced no findings.
|
|
498
|
+
*/
|
|
499
|
+
function markdownFlowGate(flow) {
|
|
500
|
+
if (!flow || flow.findings.length === 0)
|
|
501
|
+
return [];
|
|
502
|
+
const out = [];
|
|
503
|
+
const blocking = flow.findings.filter((f) => f.verdict === 'block');
|
|
504
|
+
const warning = flow.findings.filter((f) => f.verdict === 'warn');
|
|
505
|
+
const row = (f) => `| ${escapeMd(`${f.method} ${f.path}`)} | ${escapeMd(f.reason)} | ` +
|
|
506
|
+
`${escapeMd(`${f.file}:${f.line}`)} | ${f.confidence.toFixed(2)} |`;
|
|
507
|
+
if (blocking.length > 0) {
|
|
508
|
+
out.push('### Broken integrations');
|
|
509
|
+
out.push('');
|
|
510
|
+
out.push('| Endpoint | Reason | Consumer | Confidence |');
|
|
511
|
+
out.push('|---|---|---|---|');
|
|
512
|
+
for (const f of blocking)
|
|
513
|
+
out.push(row(f));
|
|
514
|
+
out.push('');
|
|
515
|
+
}
|
|
516
|
+
if (warning.length > 0) {
|
|
517
|
+
out.push('<details>');
|
|
518
|
+
out.push(`<summary>Integration warnings (${warning.length})</summary>`);
|
|
519
|
+
out.push('');
|
|
520
|
+
out.push('| Endpoint | Reason | Consumer | Confidence |');
|
|
521
|
+
out.push('|---|---|---|---|');
|
|
522
|
+
for (const f of warning)
|
|
523
|
+
out.push(row(f));
|
|
524
|
+
out.push('');
|
|
525
|
+
out.push('</details>');
|
|
526
|
+
out.push('');
|
|
527
|
+
}
|
|
528
|
+
return out;
|
|
529
|
+
}
|
|
440
530
|
/** Append ` (ref: <ref>)` to the mode label when running ref-based,
|
|
441
531
|
* so PR reviewers see WHICH ref the diff anchored to. Empty for
|
|
442
532
|
* committed modes. */
|