@descryy/runtime-graph-correlator 0.3.0 → 0.4.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/LICENSE +6 -0
- package/dist/confirm-observed-caller.d.ts +27 -62
- package/dist/confirm-observed-caller.d.ts.map +1 -1
- package/dist/confirm-observed-caller.js +25 -60
- package/dist/confirm-observed-caller.js.map +1 -1
- package/dist/cross-service-call.d.ts +42 -104
- package/dist/cross-service-call.d.ts.map +1 -1
- package/dist/cross-service-call.js +42 -107
- package/dist/cross-service-call.js.map +1 -1
- package/dist/database-table.d.ts +8 -20
- package/dist/database-table.d.ts.map +1 -1
- package/dist/database-table.js +8 -20
- package/dist/database-table.js.map +1 -1
- package/dist/endpoint.d.ts +19 -43
- package/dist/endpoint.d.ts.map +1 -1
- package/dist/endpoint.js +20 -45
- package/dist/endpoint.js.map +1 -1
- package/dist/frontend-caller.d.ts +15 -37
- package/dist/frontend-caller.d.ts.map +1 -1
- package/dist/frontend-caller.js +15 -37
- package/dist/frontend-caller.js.map +1 -1
- package/dist/index.d.ts +5 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/log-endpoint.d.ts +14 -35
- package/dist/log-endpoint.d.ts.map +1 -1
- package/dist/log-endpoint.js +15 -41
- package/dist/log-endpoint.js.map +1 -1
- package/dist/observed-frontend-caller.d.ts +20 -44
- package/dist/observed-frontend-caller.d.ts.map +1 -1
- package/dist/observed-frontend-caller.js +21 -51
- package/dist/observed-frontend-caller.js.map +1 -1
- package/dist/symbol.d.ts +44 -124
- package/dist/symbol.d.ts.map +1 -1
- package/dist/symbol.js +48 -130
- package/dist/symbol.js.map +1 -1
- package/package.json +9 -4
|
@@ -1,90 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* A caller in one process, a route in another, joined without a browser.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* evidence carrying a call-site stack came from exactly one place —
|
|
9
|
-
* `@descryhq-wq/runtime-browser`'s `fetch()` initiator capture — and every
|
|
10
|
-
* backend collector set `stackTrace: null`, `ExternalRequestCollector`
|
|
11
|
-
* included, *because the preload never captured one*. It does now
|
|
12
|
-
* (`fetch-instrumentation.ts`), and this file is what turns that capture
|
|
13
|
-
* into an edge.
|
|
4
|
+
* Closes the gap `observe-runtime` noted as unreachable: backend-only runs resolved both node kinds but
|
|
5
|
+
* wrote no edge, since `NETWORK_REQUEST` stacks only came from `runtime-browser`'s `fetch()` capture and
|
|
6
|
+
* every backend collector set `stackTrace: null`. `fetch-instrumentation.ts` now captures one
|
|
7
|
+
* backend-side too; this file turns it into an edge.
|
|
14
8
|
*
|
|
15
|
-
*
|
|
9
|
+
* **Two ends, neither inferred.** Caller: `EXTERNAL_REQUEST` evidence carrying the outbound stack,
|
|
10
|
+
* resolved to a `FUNCTION` via `resolveSymbolNode`. Callee: `NETWORK_REQUEST` evidence from
|
|
11
|
+
* `InboundProxy` at the other process, resolved to an `API_ENDPOINT` via `resolveEndpointNode`
|
|
12
|
+
* (workspace-scoped, DEC-054). Both come from the observation; nothing here pairs attributions that
|
|
13
|
+
* merely co-occur.
|
|
16
14
|
*
|
|
17
|
-
* **The
|
|
18
|
-
*
|
|
19
|
-
* the moment it called. Its site of interest (`primaryFrameLocation`, the
|
|
20
|
-
* identical rule every other stack-to-evidence join here already uses)
|
|
21
|
-
* resolves to a `FUNCTION` node via `resolveSymbolNode`.
|
|
15
|
+
* **The join, which is the precision question.** Two observations of one exchange must be shown to be
|
|
16
|
+
* the same exchange. Two joins accepted, each named in the result, never averaged:
|
|
22
17
|
*
|
|
23
|
-
*
|
|
24
|
-
* process* — `InboundProxy`'s own capture of a request arriving. Its
|
|
25
|
-
* `method`/`path` resolve to an `API_ENDPOINT` node via
|
|
26
|
-
* `resolveEndpointNode`. `API_ENDPOINT` is workspace-scoped, not repo-scoped
|
|
27
|
-
* (DEC-054, and `endpoint.ts`'s own header), so there is no "which repo's
|
|
28
|
-
* route" question to answer and no repo filter to invent.
|
|
29
|
-
*
|
|
30
|
-
* Both ends come from the observation. Nothing here pairs up attributions
|
|
31
|
-
* that merely co-occur in a run — the exact manufacture `observe-runtime`'s
|
|
32
|
-
* header rules out — because a pair of co-occurring observations is not a
|
|
33
|
-
* witnessed relationship.
|
|
34
|
-
*
|
|
35
|
-
* ## The join, which is the whole precision question
|
|
36
|
-
*
|
|
37
|
-
* Two observations of one HTTP exchange, from two processes, have to be
|
|
38
|
-
* shown to be the *same* exchange. Two joins are accepted and each one is
|
|
39
|
-
* named in the result, never averaged into a single confidence number:
|
|
40
|
-
*
|
|
41
|
-
* | join | what it rests on |
|
|
18
|
+
* | join | rests on |
|
|
42
19
|
* | --- | --- |
|
|
43
|
-
* | `correlation-id` | both observations carry the same non-null `traceId`
|
|
44
|
-
* | `run-owned-authority` | the outbound
|
|
45
|
-
*
|
|
46
|
-
* `correlation-id` is preferred
|
|
47
|
-
* `
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* a hostname this module recognises, it is matched against a `host:port`
|
|
60
|
-
* **the caller declares Descry allocated for that service in this run**
|
|
61
|
-
* (`observedAuthorities`). Declared, never inferred — the same discipline
|
|
62
|
-
* RT-032 already applies to service start order. A call that reached a port
|
|
63
|
-
* Descry itself bound for service B, answered successfully, and shows up in
|
|
64
|
-
* B's own independent inbound observation of the same method and path, is a
|
|
65
|
-
* call that reached that route.
|
|
66
|
-
*
|
|
67
|
-
* Both joins additionally require what `correlateBackendEvidence` requires:
|
|
68
|
-
* one `executionId`. Evidence from two runs is never joined on a bare
|
|
69
|
-
* identifier.
|
|
70
|
-
*
|
|
71
|
-
* ## What is refused, and why refusal is the point
|
|
72
|
-
*
|
|
73
|
-
* No stack, an unresolvable frame, an ambiguous symbol, an unresolvable or
|
|
74
|
-
* ambiguous endpoint, an outbound call that reached nothing, an authority
|
|
75
|
-
* nobody declared, no matching inbound observation — every one of these
|
|
76
|
-
* returns a named refusal with a reason and **no edge**. Rule 2, stated in
|
|
77
|
-
* the plan that asked for this file: *"a wrong cross-repo edge corrupts diff
|
|
78
|
-
* scoping, impact scores and root-cause traversal in every layer above it.
|
|
79
|
-
* If the join is uncertain, omit the edge and disclose."*
|
|
80
|
-
*
|
|
81
|
-
* ## What this does not do
|
|
82
|
-
*
|
|
83
|
-
* - **No denial arrow.** Identical reasoning to
|
|
84
|
-
* `confirm-observed-caller.ts`: a run establishes that a call happened and
|
|
85
|
-
* can never establish that one did not.
|
|
86
|
-
* - **It does not judge a finding** (RT-027), decide staleness, or invent a
|
|
87
|
-
* node — core's refusals pass through whole.
|
|
20
|
+
* | `correlation-id` | both observations carry the same non-null `traceId`/`requestId` in one execution |
|
|
21
|
+
* | `run-owned-authority` | the outbound authority is a listening post Descry itself bound for the named callee, independently confirmed by that callee's own observation of the same method+path |
|
|
22
|
+
*
|
|
23
|
+
* `correlation-id` is preferred — same rule as `correlateBackendEvidence`, reimplemented rather than
|
|
24
|
+
* imported (needs a join decision, not a fresh `Correlation` record; avoids an unpublished-scope dependency).
|
|
25
|
+
* `run-owned-authority` exists because `correlation-id` alone requires the app under test to propagate
|
|
26
|
+
* trace headers, which the UAT workspace did not — the authority is matched against a `host:port` the
|
|
27
|
+
* caller declares Descry allocated for that service (`observedAuthorities`), declared never inferred
|
|
28
|
+
* (RT-032's discipline). Both joins require one shared `executionId` — never joined across runs.
|
|
29
|
+
*
|
|
30
|
+
* **Refusal is the point.** No stack, unresolvable frame/symbol/endpoint, a call that reached nothing, an
|
|
31
|
+
* undeclared authority, no matching inbound — every one is a named refusal, no edge (rule 2: a wrong
|
|
32
|
+
* cross-repo edge corrupts diff scoping, impact and root-cause traversal above it).
|
|
33
|
+
*
|
|
34
|
+
* **No denial arrow** — same reasoning as `confirm-observed-caller.ts`: can establish a call happened,
|
|
35
|
+
* never that it didn't. Also doesn't judge a finding (RT-027), decide staleness, or invent a node.
|
|
88
36
|
*/
|
|
89
37
|
import { applyRuntimeObservations, } from "@descryy/core";
|
|
90
38
|
import { primaryFrameLocation } from "@descryy/runtime-contracts";
|
|
@@ -103,12 +51,7 @@ function pathOnly(path) {
|
|
|
103
51
|
const cut = path.indexOf("?");
|
|
104
52
|
return cut === -1 ? path : path.slice(0, cut);
|
|
105
53
|
}
|
|
106
|
-
/**
|
|
107
|
-
* The same rule `correlateBackendEvidence` applies — one execution, a
|
|
108
|
-
* non-null id, equal on both sides, `traceId` before `requestId` — reading
|
|
109
|
-
* the same canonical `Evidence` fields. See this module's header for why the
|
|
110
|
-
* function itself is not imported.
|
|
111
|
-
*/
|
|
54
|
+
/** Same rule `correlateBackendEvidence` applies (one execution, non-null id equal on both sides, `traceId` before `requestId`) — see header for why that function itself isn't imported. */
|
|
112
55
|
function correlationJoin(a, b) {
|
|
113
56
|
if (a.executionId !== b.executionId)
|
|
114
57
|
return null;
|
|
@@ -144,10 +87,8 @@ function describesSameExchange(target, inbound) {
|
|
|
144
87
|
}
|
|
145
88
|
function joinFor(input, target) {
|
|
146
89
|
const sameExchange = input.inbound.filter((candidate) => candidate.eventType === "NETWORK_REQUEST" && describesSameExchange(target, candidate));
|
|
147
|
-
// Preferred join first
|
|
148
|
-
//
|
|
149
|
-
// and checking it first means the stronger one is never passed over
|
|
150
|
-
// because a weaker one happened to match earlier in the list.
|
|
90
|
+
// Preferred join checked first over the whole candidate set -- an id both sides carry is
|
|
91
|
+
// stronger than a bound authority; check first so it's never passed over for a weaker match.
|
|
151
92
|
for (const candidate of sameExchange) {
|
|
152
93
|
const join = correlationJoin(input.outbound, candidate);
|
|
153
94
|
if (join !== null)
|
|
@@ -162,11 +103,8 @@ function joinFor(input, target) {
|
|
|
162
103
|
"Joining on method and path alone would pair two observations that merely look alike.",
|
|
163
104
|
};
|
|
164
105
|
}
|
|
165
|
-
// The outbound call must have reached something
|
|
166
|
-
//
|
|
167
|
-
// code, both captured by the preload before the call returned to the
|
|
168
|
-
// application: a call that threw reached no route, whatever else was
|
|
169
|
-
// observed at the callee in the same window.
|
|
106
|
+
// The outbound call must have reached something -- `success` is fetch-resolved-rather-than-threw,
|
|
107
|
+
// captured by the preload before return: a call that threw reached no route regardless of what the callee saw.
|
|
170
108
|
if (payloadBoolean(input.outbound, "success") !== true) {
|
|
171
109
|
return {
|
|
172
110
|
reason: `The outbound ${target.method} ${target.path} to "${target.authority}" did not resolve to a response ` +
|
|
@@ -255,22 +193,19 @@ const EMPTY = {
|
|
|
255
193
|
};
|
|
256
194
|
/**
|
|
257
195
|
* Resolve one observed cross-service call and, when it genuinely observed
|
|
258
|
-
* something, record it as R4 evidence
|
|
196
|
+
* something, record it as R4 evidence.
|
|
259
197
|
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
* far more often than its promotion case.
|
|
198
|
+
* Writes the `USES_API` edge a static adapter structurally cannot produce
|
|
199
|
+
* when the target URL is assembled at runtime (the fixture this was proven
|
|
200
|
+
* against builds it from an env var) — so this is `applyRuntimeObservations`'
|
|
201
|
+
* "recall gap closed" case far more often than its promotion case.
|
|
265
202
|
*/
|
|
266
203
|
export function confirmObservedCrossServiceCall(driver, input) {
|
|
267
204
|
const resolution = resolveObservedCrossServiceCall(driver, input);
|
|
268
205
|
if (resolution.outcome !== "observed") {
|
|
269
|
-
// Deliberately not
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
// Those are different statements. (`confirm-observed-caller.ts`'s own
|
|
273
|
-
// reasoning, unchanged.)
|
|
206
|
+
// Deliberately not an empty-list call -- an `adapter_runs` row would then
|
|
207
|
+
// read like a run that observed and found nothing to say (same
|
|
208
|
+
// reasoning as confirm-observed-caller.ts).
|
|
274
209
|
return { resolution, observations: [], confirmation: EMPTY };
|
|
275
210
|
}
|
|
276
211
|
const observations = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-service-call.js","sourceRoot":"","sources":["../src/cross-service-call.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cross-service-call.js","sourceRoot":"","sources":["../src/cross-service-call.ts"],"names":[],"mappings":"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"}
|
package/dist/database-table.d.ts
CHANGED
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* disclosed as missing since RT-141: real query capture, `graphNodeId`
|
|
6
|
-
* always null.
|
|
2
|
+
* Resolves a captured query's target table name (`extractTargetTable`, `@descryy/runtime-database-
|
|
3
|
+
* observation`) to the `DATABASE_TABLE` node — the join `DatabaseQueryCollector` disclosed missing
|
|
4
|
+
* since RT-141: real query capture, `graphNodeId` always null.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* carries no repository at all for a bare table name — the observed
|
|
14
|
-
* process's own source may not even be one of the repos this graph indexed
|
|
15
|
-
* — so taking a `repo` filter here would be inventing a constraint the
|
|
16
|
-
* caller has no way to satisfy.
|
|
17
|
-
*
|
|
18
|
-
* **Unlike an endpoint, a table name is not a template.** No segment
|
|
19
|
-
* matching, no `{param}` — `DATABASE_TABLE.name` is the bare table name
|
|
20
|
-
* (`adapter-sql`'s `extract.ts`: `name: table.table`), so this is a plain
|
|
21
|
-
* equality match against every candidate, the simpler half of
|
|
22
|
-
* `resolveEndpointNode`'s own two-part job.
|
|
6
|
+
* `DATABASE_TABLE` is workspace-scoped, not repo-scoped (`adapter-sql`, DEC-054) — a migration can
|
|
7
|
+
* live in one repo and the reading service in another, and a runtime observation carries no repo
|
|
8
|
+
* for a bare table name, so no `repo` filter here (same reason `resolveEndpointNode` has none).
|
|
9
|
+
* Table names aren't templated like endpoints (no `{param}`), so this is a plain equality match —
|
|
10
|
+
* simpler than `resolveEndpointNode`'s two-part job.
|
|
23
11
|
*/
|
|
24
12
|
import type { IRNode } from "@descryy/ir";
|
|
25
13
|
import { type SqlDriver } from "@descryy/core";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-table.d.ts","sourceRoot":"","sources":["../src/database-table.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"database-table.d.ts","sourceRoot":"","sources":["../src/database-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvG,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,uBAAuB,CA+BzB"}
|
package/dist/database-table.js
CHANGED
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* disclosed as missing since RT-141: real query capture, `graphNodeId`
|
|
6
|
-
* always null.
|
|
2
|
+
* Resolves a captured query's target table name (`extractTargetTable`, `@descryy/runtime-database-
|
|
3
|
+
* observation`) to the `DATABASE_TABLE` node — the join `DatabaseQueryCollector` disclosed missing
|
|
4
|
+
* since RT-141: real query capture, `graphNodeId` always null.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* carries no repository at all for a bare table name — the observed
|
|
14
|
-
* process's own source may not even be one of the repos this graph indexed
|
|
15
|
-
* — so taking a `repo` filter here would be inventing a constraint the
|
|
16
|
-
* caller has no way to satisfy.
|
|
17
|
-
*
|
|
18
|
-
* **Unlike an endpoint, a table name is not a template.** No segment
|
|
19
|
-
* matching, no `{param}` — `DATABASE_TABLE.name` is the bare table name
|
|
20
|
-
* (`adapter-sql`'s `extract.ts`: `name: table.table`), so this is a plain
|
|
21
|
-
* equality match against every candidate, the simpler half of
|
|
22
|
-
* `resolveEndpointNode`'s own two-part job.
|
|
6
|
+
* `DATABASE_TABLE` is workspace-scoped, not repo-scoped (`adapter-sql`, DEC-054) — a migration can
|
|
7
|
+
* live in one repo and the reading service in another, and a runtime observation carries no repo
|
|
8
|
+
* for a bare table name, so no `repo` filter here (same reason `resolveEndpointNode` has none).
|
|
9
|
+
* Table names aren't templated like endpoints (no `{param}`), so this is a plain equality match —
|
|
10
|
+
* simpler than `resolveEndpointNode`'s two-part job.
|
|
23
11
|
*/
|
|
24
12
|
import { nodesOfType } from "@descryy/core";
|
|
25
13
|
export function resolveDatabaseTableNode(driver, tableName, options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-table.js","sourceRoot":"","sources":["../src/database-table.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"database-table.js","sourceRoot":"","sources":["../src/database-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,WAAW,EAAkB,MAAM,eAAe,CAAC;AAO5D,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,SAAiB,EACjB,UAAuC,EAAE;IAEzC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAEhE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,WAAW;YACpB,MAAM,EACJ,iCAAiC,SAAS,IAAI;gBAC9C,CAAC,SAAS;oBACR,CAAC,CAAC,uFAAuF;wBACvF,oCAAoC;oBACtC,CAAC,CAAC,uFAAuF;wBACvF,6DAA6D,CAAC;SACrE,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,WAAW;YACpB,UAAU,EAAE,OAAO;YACnB,MAAM,EACJ,GAAG,OAAO,CAAC,MAAM,oCAAoC,SAAS,MAAM;gBACpE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAI,CAAC,CAAC,KAAK,CAAC,MAA6B,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAClG,uFAAuF;gBACvF,yFAAyF;gBACzF,mBAAmB;SACtB,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAC;AACpD,CAAC"}
|
package/dist/endpoint.d.ts
CHANGED
|
@@ -1,31 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* runtime evidence actually support those links").
|
|
2
|
+
* Resolves observed HTTP evidence (method + literal path) to the `API_ENDPOINT` node it was served
|
|
3
|
+
* by (plan §12/§25). `API_ENDPOINT` is workspace-scoped, not repo-scoped (DEC-054), and the one join
|
|
4
|
+
* node two repos mint identically with no shared code (DEC-115) — so there's no "wrong repository"
|
|
5
|
+
* version to pick, and this file takes no `repo`/`scope` parameter.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* "
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* inventing a filter with nothing behind it to filter on.
|
|
15
|
-
*
|
|
16
|
-
* What this file *does* have to solve, that a bare identity hash cannot: a
|
|
17
|
-
* real request's URL is a literal (`/orders/5`), while the route that served
|
|
18
|
-
* it may have been minted from a parameterised template
|
|
19
|
-
* (`/orders/{param}`, per `normaliseEndpointPath`). Those hash to different
|
|
20
|
-
* ids, so resolution here is a segment-wise match against every candidate's
|
|
21
|
-
* *name*, not a single `getNode` by a computed id. That is also what makes
|
|
22
|
-
* "similar endpoint" (plan §38's own negative-control name) a real,
|
|
23
|
-
* representable outcome here rather than a hypothetical: a literal route
|
|
24
|
-
* (`GET /orders/active`) and a parameterised one (`GET /orders/{param}`) can
|
|
25
|
-
* both legitimately match one observed request, and this resolver reports
|
|
26
|
-
* that as `ambiguous` rather than guessing which one actually served it —
|
|
27
|
-
* the same discipline `resolveOneNode` (descry-core's MCP lookup) applies to
|
|
28
|
-
* a name search, one layer down at the network-evidence layer instead.
|
|
7
|
+
* A request's URL is a literal (`/orders/5`); the route that served it may be a parameterised
|
|
8
|
+
* template (`/orders/{param}`, `normaliseEndpointPath`), which hashes to a different id — so this
|
|
9
|
+
* matches segment-wise against every candidate's *name*, not a single `getNode` by computed id.
|
|
10
|
+
* That also makes "similar endpoint" (plan §38) a real outcome: a literal route and a parameterised
|
|
11
|
+
* one can both match one request, and this resolver reports `ambiguous` rather than guessing which
|
|
12
|
+
* served it — same discipline `resolveOneNode` applies one layer down.
|
|
29
13
|
*/
|
|
30
14
|
import { type IRNode } from "@descryy/ir";
|
|
31
15
|
import { type SqlDriver } from "@descryy/core";
|
|
@@ -44,25 +28,17 @@ export declare function resolveEndpointNode(driver: SqlDriver, method: string, o
|
|
|
44
28
|
readonly limit?: number;
|
|
45
29
|
}): EndpointResolution;
|
|
46
30
|
/**
|
|
47
|
-
* Every `API_ENDPOINT` whose path shape matches `observedPath`,
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* this path exist under a different method" needs the method filter removed
|
|
51
|
-
* entirely, not relaxed.
|
|
31
|
+
* Every `API_ENDPOINT` whose path shape matches `observedPath`, regardless of method —
|
|
32
|
+
* `resolveEndpointNode` filters by method first, so this exists for "does this path exist under a
|
|
33
|
+
* different method."
|
|
52
34
|
*
|
|
53
|
-
* Built for
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* was never declared, the second says it was declared and the request used
|
|
58
|
-
* the wrong verb. Conflating them would report "undocumented" for a request
|
|
59
|
-
* a contract-reading person would call a client bug, not a documentation
|
|
60
|
-
* gap.
|
|
35
|
+
* Built for `@descryy/runtime-openapi-observation`'s "wrong method" vs "undocumented" distinction
|
|
36
|
+
* (checklist §15): exact method+path resolving to nothing means the operation was never declared;
|
|
37
|
+
* resolving under some other method means it was declared and the request used the wrong verb.
|
|
38
|
+
* Conflating them would call a client bug a documentation gap.
|
|
61
39
|
*
|
|
62
|
-
* Ambiguity
|
|
63
|
-
*
|
|
64
|
-
* means for its own question, the same "refuse rather than rank" split
|
|
65
|
-
* `resolveEndpointNode` already uses for its own single-method case.
|
|
40
|
+
* Ambiguity isn't resolved here either — every shape-matching node across methods is returned, and
|
|
41
|
+
* the caller decides what "more than one" means.
|
|
66
42
|
*/
|
|
67
43
|
export declare function resolveEndpointNodesByPath(driver: SqlDriver, observedPath: string, options?: {
|
|
68
44
|
readonly limit?: number;
|
package/dist/endpoint.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAYvG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,kBAAkB,CA2CpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAapE"}
|
package/dist/endpoint.js
CHANGED
|
@@ -1,37 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* runtime evidence actually support those links").
|
|
2
|
+
* Resolves observed HTTP evidence (method + literal path) to the `API_ENDPOINT` node it was served
|
|
3
|
+
* by (plan §12/§25). `API_ENDPOINT` is workspace-scoped, not repo-scoped (DEC-054), and the one join
|
|
4
|
+
* node two repos mint identically with no shared code (DEC-115) — so there's no "wrong repository"
|
|
5
|
+
* version to pick, and this file takes no `repo`/`scope` parameter.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* "
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* inventing a filter with nothing behind it to filter on.
|
|
15
|
-
*
|
|
16
|
-
* What this file *does* have to solve, that a bare identity hash cannot: a
|
|
17
|
-
* real request's URL is a literal (`/orders/5`), while the route that served
|
|
18
|
-
* it may have been minted from a parameterised template
|
|
19
|
-
* (`/orders/{param}`, per `normaliseEndpointPath`). Those hash to different
|
|
20
|
-
* ids, so resolution here is a segment-wise match against every candidate's
|
|
21
|
-
* *name*, not a single `getNode` by a computed id. That is also what makes
|
|
22
|
-
* "similar endpoint" (plan §38's own negative-control name) a real,
|
|
23
|
-
* representable outcome here rather than a hypothetical: a literal route
|
|
24
|
-
* (`GET /orders/active`) and a parameterised one (`GET /orders/{param}`) can
|
|
25
|
-
* both legitimately match one observed request, and this resolver reports
|
|
26
|
-
* that as `ambiguous` rather than guessing which one actually served it —
|
|
27
|
-
* the same discipline `resolveOneNode` (descry-core's MCP lookup) applies to
|
|
28
|
-
* a name search, one layer down at the network-evidence layer instead.
|
|
7
|
+
* A request's URL is a literal (`/orders/5`); the route that served it may be a parameterised
|
|
8
|
+
* template (`/orders/{param}`, `normaliseEndpointPath`), which hashes to a different id — so this
|
|
9
|
+
* matches segment-wise against every candidate's *name*, not a single `getNode` by computed id.
|
|
10
|
+
* That also makes "similar endpoint" (plan §38) a real outcome: a literal route and a parameterised
|
|
11
|
+
* one can both match one request, and this resolver reports `ambiguous` rather than guessing which
|
|
12
|
+
* served it — same discipline `resolveOneNode` applies one layer down.
|
|
29
13
|
*/
|
|
30
14
|
import { endpointQsp, normaliseEndpointPath } from "@descryy/ir";
|
|
31
15
|
import { nodesOfType } from "@descryy/core";
|
|
32
16
|
function pathSegments(path) {
|
|
33
|
-
//
|
|
34
|
-
// on "/" after the method prefix is stripped, same shape either side.
|
|
17
|
+
// qualified path is "METHOD /normalised/path" -- split after the method prefix, same shape either side.
|
|
35
18
|
return normaliseEndpointPath(path).split("/");
|
|
36
19
|
}
|
|
37
20
|
function segmentsMatch(templateSegments, observedSegments) {
|
|
@@ -78,25 +61,17 @@ export function resolveEndpointNode(driver, method, observedPath, options = {})
|
|
|
78
61
|
return { outcome: "resolved", node: matches[0] };
|
|
79
62
|
}
|
|
80
63
|
/**
|
|
81
|
-
* Every `API_ENDPOINT` whose path shape matches `observedPath`,
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* this path exist under a different method" needs the method filter removed
|
|
85
|
-
* entirely, not relaxed.
|
|
64
|
+
* Every `API_ENDPOINT` whose path shape matches `observedPath`, regardless of method —
|
|
65
|
+
* `resolveEndpointNode` filters by method first, so this exists for "does this path exist under a
|
|
66
|
+
* different method."
|
|
86
67
|
*
|
|
87
|
-
* Built for
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* was never declared, the second says it was declared and the request used
|
|
92
|
-
* the wrong verb. Conflating them would report "undocumented" for a request
|
|
93
|
-
* a contract-reading person would call a client bug, not a documentation
|
|
94
|
-
* gap.
|
|
68
|
+
* Built for `@descryy/runtime-openapi-observation`'s "wrong method" vs "undocumented" distinction
|
|
69
|
+
* (checklist §15): exact method+path resolving to nothing means the operation was never declared;
|
|
70
|
+
* resolving under some other method means it was declared and the request used the wrong verb.
|
|
71
|
+
* Conflating them would call a client bug a documentation gap.
|
|
95
72
|
*
|
|
96
|
-
* Ambiguity
|
|
97
|
-
*
|
|
98
|
-
* means for its own question, the same "refuse rather than rank" split
|
|
99
|
-
* `resolveEndpointNode` already uses for its own single-method case.
|
|
73
|
+
* Ambiguity isn't resolved here either — every shape-matching node across methods is returned, and
|
|
74
|
+
* the caller decides what "more than one" means.
|
|
100
75
|
*/
|
|
101
76
|
export function resolveEndpointNodesByPath(driver, observedPath, options = {}) {
|
|
102
77
|
const observedSegments = pathSegments(observedPath);
|
package/dist/endpoint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,36 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* First leg of the path: Frontend FUNCTION -> API_ENDPOINT -> API_ROUTE -> Backend FUNCTION
|
|
3
|
+
* (RUNTIME-CHECKLIST.md §11 covered only the last three). `adapter-typescript` already emits
|
|
4
|
+
* `USES_API` from caller to endpoint, read from source — nothing correlated it until this.
|
|
4
5
|
*
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* **Structural claim, not an observation.** `USES_API` says this function contains a call to that
|
|
7
|
+
* endpoint, not that it issued the request just observed. When several components call one
|
|
8
|
+
* endpoint, the graph names all of them and the browser saw one; nothing in a `NETWORK_REQUEST`
|
|
9
|
+
* says which (Playwright's initiator chain could narrow it; the network collector doesn't capture
|
|
10
|
+
* it today — disclosed gap, §6).
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* central lie this project exists not to tell.**
|
|
15
|
-
*
|
|
16
|
-
* `USES_API` says *this function contains a call to that endpoint*. It does
|
|
17
|
-
* **not** say this function issued the request that was just observed. When
|
|
18
|
-
* three components call one endpoint, the graph names all three and the
|
|
19
|
-
* browser saw one — and nothing in a `NETWORK_REQUEST` says which. Playwright
|
|
20
|
-
* exposes an initiator chain that could narrow it; the network collector
|
|
21
|
-
* does not capture it today (§6 records that as a gap), and until it does,
|
|
22
|
-
* *which* caller ran is not something this repo knows.
|
|
23
|
-
*
|
|
24
|
-
* So the outcome vocabulary says so at the type level: a single caller is
|
|
25
|
-
* `sole-structural-caller`, never `resolved`. A reader who sees `resolved`
|
|
26
|
-
* elsewhere in this package is looking at an observation; here they are
|
|
27
|
-
* looking at the only candidate the code admits, which is a different and
|
|
28
|
-
* weaker fact even when it happens to be right.
|
|
29
|
-
*
|
|
30
|
-
* **Consequence for reliability, per the architecture's resolution cap:** a
|
|
31
|
-
* finding whose path rests on this leg is capped by the `USES_API` edge's
|
|
32
|
-
* own resolution, exactly as any other structural hop is. Extending the
|
|
33
|
-
* path does not upgrade the evidence.
|
|
12
|
+
* So a single caller is `sole-structural-caller`, never `resolved` — a weaker fact than an
|
|
13
|
+
* observation even when it happens to be right. A finding resting on this leg is capped by
|
|
14
|
+
* `USES_API`'s own resolution level; extending the path doesn't upgrade the evidence.
|
|
34
15
|
*/
|
|
35
16
|
import { type SqlDriver } from "@descryy/core";
|
|
36
17
|
import type { IRNode } from "@descryy/ir";
|
|
@@ -55,13 +36,10 @@ export type FrontendCallerResolution =
|
|
|
55
36
|
/**
|
|
56
37
|
* Every frontend function the graph says calls this endpoint.
|
|
57
38
|
*
|
|
58
|
-
* Ambiguity is returned
|
|
59
|
-
* `
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* both are timing and locality standing in for causality, which §27's own
|
|
63
|
-
* rule forbids in one sentence: *similarity must never be treated as
|
|
64
|
-
* causality*.
|
|
39
|
+
* Ambiguity is returned, not ranked — same as `resolveSymbolNode` and
|
|
40
|
+
* `resolveEndpointNode`. Preferring the most-recently-loaded file or the
|
|
41
|
+
* nearest line would be timing/locality standing in for causality, which
|
|
42
|
+
* §27 forbids.
|
|
65
43
|
*/
|
|
66
44
|
export declare function resolveFrontendCallers(driver: SqlDriver, endpointNodeId: string): FrontendCallerResolution;
|
|
67
45
|
//# sourceMappingURL=frontend-caller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend-caller.d.ts","sourceRoot":"","sources":["../src/frontend-caller.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"frontend-caller.d.ts","sourceRoot":"","sources":["../src/frontend-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,MAAM,wBAAwB;AAClC,sIAAsI;AACpI;IAAE,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAChG,8HAA8H;GAC5H;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACpG,oIAAoI;GAClI;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,GAAG,wBAAwB,CA2C1G"}
|