@descryy/runtime-graph-correlator 0.0.0 → 0.2.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.
@@ -0,0 +1,190 @@
1
+ /**
2
+ * **A caller in one process, a route in another, joined without a browser.**
3
+ *
4
+ * This is the arrow `observe-runtime`'s own header records as unreachable:
5
+ * *"a backend-only run resolves both kinds of node and writes no edge... the
6
+ * arrow is currently reachable only from a browser-driven run."* That was a
7
+ * true statement about one collector, not about the wire. `NETWORK_REQUEST`
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.
14
+ *
15
+ * ## The two ends, and why neither is inferred
16
+ *
17
+ * **The caller** is `EXTERNAL_REQUEST` evidence from the calling process,
18
+ * carrying the stack the observed application's own `fetch` call site had at
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`.
22
+ *
23
+ * **The callee** is `NETWORK_REQUEST` evidence observed *at the other
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 |
42
+ * | --- | --- |
43
+ * | `correlation-id` | both observations carry the same non-null `traceId` or `requestId`, within one execution — the application propagated an id and both sides read it back |
44
+ * | `run-owned-authority` | the outbound URL's authority is a listening post **Descry itself bound** for the named callee service in this run, and that callee independently observed the same method and path |
45
+ *
46
+ * `correlation-id` is preferred whenever it is available. It is the rule
47
+ * `correlateBackendEvidence` (`@descryy/runtime-backend-observation`) already
48
+ * applies to backend evidence, applied here to the same fields; this module
49
+ * does not call that function because it needs a *join decision*, not a
50
+ * `Correlation` record with a fresh UUID, and importing it would put an
51
+ * unpublished-scope package into a published one's dependency list for no
52
+ * gain.
53
+ *
54
+ * `run-owned-authority` exists because requiring `correlation-id` alone
55
+ * would make this whole mechanism conditional on the application under test
56
+ * already propagating trace headers — which the UAT workspace did not, and
57
+ * which is the sort of precondition that turns a capability into a
58
+ * disclosure. It is not a weaker guess: the authority is not matched against
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.
88
+ */
89
+ import type { IRNode, RuntimeEdgeObservation } from "@descryy/ir";
90
+ import { type RuntimeConfirmationResult, type SqlDriver } from "@descryy/core";
91
+ import { type Evidence } from "@descryy/runtime-contracts";
92
+ /** How the caller-side and callee-side observations were shown to be one exchange. Always named in the result; never collapsed into a number. */
93
+ export type CrossServiceJoin = {
94
+ readonly kind: "correlation-id";
95
+ /** Which id carried it. `trace-id` is checked first, exactly as `correlateBackendEvidence` orders them. */
96
+ readonly idKind: "trace-id" | "request-id";
97
+ readonly id: string;
98
+ } | {
99
+ readonly kind: "run-owned-authority";
100
+ /** `host:port` as the outbound URL named it. */
101
+ readonly authority: string;
102
+ /** The callee service the caller declared that authority belongs to. */
103
+ readonly service: string;
104
+ };
105
+ export type CrossServiceCallResolution = {
106
+ readonly outcome: "observed";
107
+ /** The `FUNCTION` (or `CLASS`) node the outbound call's own stack resolved to, in the calling repo. */
108
+ readonly callerNode: IRNode;
109
+ /** The `API_ENDPOINT` node the callee's own inbound observation resolved to. */
110
+ readonly endpointNode: IRNode;
111
+ /** The callee-side observation this was joined to — so a reader can audit the pair, not just the conclusion. */
112
+ readonly inbound: Evidence;
113
+ readonly join: CrossServiceJoin;
114
+ readonly reason: string;
115
+ } | {
116
+ /** Named separately from every other refusal because it is the one that says "this capability is not wired here", not "this call could not be resolved". */
117
+ readonly outcome: "no-stack";
118
+ readonly reason: string;
119
+ } | {
120
+ readonly outcome: "caller-unresolved";
121
+ readonly reason: string;
122
+ } | {
123
+ readonly outcome: "endpoint-unresolved";
124
+ readonly reason: string;
125
+ } | {
126
+ readonly outcome: "unjoined";
127
+ readonly reason: string;
128
+ };
129
+ export interface ObservedCrossServiceCallInput {
130
+ /** `EXTERNAL_REQUEST` evidence from the **calling** process, with `stackTrace` set by `ExternalRequestCollector`'s parser. */
131
+ readonly outbound: Evidence;
132
+ /**
133
+ * Every inbound observation from this run's other observed processes —
134
+ * `InboundProxy`'s `NETWORK_REQUEST` items. Passed as a list rather than a
135
+ * single pre-picked item on purpose: choosing which inbound observation
136
+ * corresponds to this outbound call **is** the join, and a caller that had
137
+ * already chosen would be making the precision decision this module exists
138
+ * to make.
139
+ */
140
+ readonly inbound: readonly Evidence[];
141
+ /** The repository the calling process's source belongs to. `FUNCTION` is repo-scoped and there is no honest default (see `symbol.ts`). */
142
+ readonly callerRepo: string;
143
+ /** The calling repository's absolute root, so an absolute frame path can be translated exactly rather than suffix-matched. */
144
+ readonly callerRepoRoot?: string;
145
+ /**
146
+ * `host:port` → callee service name, for every listening post **this run
147
+ * bound itself** (an `InboundProxy`'s own ephemeral port, the value
148
+ * `InstrumentedExecutionResult`'s `proxyPorts` already reports). Declared
149
+ * by the orchestrating caller, never discovered by this module: a hostname
150
+ * this module recognised on its own would be a lookup table standing in
151
+ * for evidence.
152
+ *
153
+ * Omitted means the `run-owned-authority` join is simply unavailable and
154
+ * only `correlation-id` can join — a disclosed reduction in recall, not a
155
+ * silent one.
156
+ */
157
+ readonly observedAuthorities?: Readonly<Record<string, string>>;
158
+ }
159
+ /**
160
+ * Resolve one observed outbound call against the route it reached in another
161
+ * observed process. Returns `observed` only when both ends resolved to real
162
+ * nodes **and** the two observations were shown to be one exchange.
163
+ */
164
+ export declare function resolveObservedCrossServiceCall(driver: SqlDriver, input: ObservedCrossServiceCallInput): CrossServiceCallResolution;
165
+ export interface ConfirmObservedCrossServiceCallInput extends ObservedCrossServiceCallInput {
166
+ /** The run that witnessed this. Becomes `edges.observed_by_run` and `observed_edges.run_id`. */
167
+ readonly runId: string;
168
+ /** The commit the observed application was built from, so a later reader can tell whether the code moved under the observation. */
169
+ readonly commitSha: string;
170
+ }
171
+ export interface ConfirmObservedCrossServiceCallOutcome {
172
+ /** The underlying resolution, unchanged and always present -- including when it produced no observation. */
173
+ readonly resolution: CrossServiceCallResolution;
174
+ /** What was sent to the graph. Empty when the resolution observed nothing. */
175
+ readonly observations: readonly RuntimeEdgeObservation[];
176
+ /** Core's own result, passed through whole -- refusals and `staleR4` included. */
177
+ readonly confirmation: RuntimeConfirmationResult;
178
+ }
179
+ /**
180
+ * Resolve one observed cross-service call and, when it genuinely observed
181
+ * something, record it as R4 evidence against the graph.
182
+ *
183
+ * The `USES_API` edge this writes is the one a static adapter structurally
184
+ * cannot produce when the target URL is assembled at runtime — the caller in
185
+ * the fixture this was proven against builds it from an environment
186
+ * variable — so this is `applyRuntimeObservations`' "recall gap closed" case
187
+ * far more often than its promotion case.
188
+ */
189
+ export declare function confirmObservedCrossServiceCall(driver: SqlDriver, input: ConfirmObservedCrossServiceCallInput): ConfirmObservedCrossServiceCallOutcome;
190
+ //# sourceMappingURL=cross-service-call.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-service-call.d.ts","sourceRoot":"","sources":["../src/cross-service-call.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * **A caller in one process, a route in another, joined without a browser.**
3
+ *
4
+ * This is the arrow `observe-runtime`'s own header records as unreachable:
5
+ * *"a backend-only run resolves both kinds of node and writes no edge... the
6
+ * arrow is currently reachable only from a browser-driven run."* That was a
7
+ * true statement about one collector, not about the wire. `NETWORK_REQUEST`
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.
14
+ *
15
+ * ## The two ends, and why neither is inferred
16
+ *
17
+ * **The caller** is `EXTERNAL_REQUEST` evidence from the calling process,
18
+ * carrying the stack the observed application's own `fetch` call site had at
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`.
22
+ *
23
+ * **The callee** is `NETWORK_REQUEST` evidence observed *at the other
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 |
42
+ * | --- | --- |
43
+ * | `correlation-id` | both observations carry the same non-null `traceId` or `requestId`, within one execution — the application propagated an id and both sides read it back |
44
+ * | `run-owned-authority` | the outbound URL's authority is a listening post **Descry itself bound** for the named callee service in this run, and that callee independently observed the same method and path |
45
+ *
46
+ * `correlation-id` is preferred whenever it is available. It is the rule
47
+ * `correlateBackendEvidence` (`@descryy/runtime-backend-observation`) already
48
+ * applies to backend evidence, applied here to the same fields; this module
49
+ * does not call that function because it needs a *join decision*, not a
50
+ * `Correlation` record with a fresh UUID, and importing it would put an
51
+ * unpublished-scope package into a published one's dependency list for no
52
+ * gain.
53
+ *
54
+ * `run-owned-authority` exists because requiring `correlation-id` alone
55
+ * would make this whole mechanism conditional on the application under test
56
+ * already propagating trace headers — which the UAT workspace did not, and
57
+ * which is the sort of precondition that turns a capability into a
58
+ * disclosure. It is not a weaker guess: the authority is not matched against
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.
88
+ */
89
+ import { applyRuntimeObservations, } from "@descryy/core";
90
+ import { primaryFrameLocation } from "@descryy/runtime-contracts";
91
+ import { resolveEndpointNode } from "./endpoint.js";
92
+ import { resolveSymbolNode } from "./symbol.js";
93
+ function payloadString(evidence, key) {
94
+ const value = evidence.payload?.[key];
95
+ return typeof value === "string" ? value : null;
96
+ }
97
+ function payloadBoolean(evidence, key) {
98
+ const value = evidence.payload?.[key];
99
+ return typeof value === "boolean" ? value : null;
100
+ }
101
+ /** Path without its query string. A query is not part of a route's identity, and `resolveEndpointNode` matches segment-wise against a template that never contains one. */
102
+ function pathOnly(path) {
103
+ const cut = path.indexOf("?");
104
+ return cut === -1 ? path : path.slice(0, cut);
105
+ }
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
+ */
112
+ function correlationJoin(a, b) {
113
+ if (a.executionId !== b.executionId)
114
+ return null;
115
+ if (a.traceId !== null && a.traceId === b.traceId) {
116
+ return { kind: "correlation-id", idKind: "trace-id", id: a.traceId };
117
+ }
118
+ if (a.requestId !== null && a.requestId === b.requestId) {
119
+ return { kind: "correlation-id", idKind: "request-id", id: a.requestId };
120
+ }
121
+ return null;
122
+ }
123
+ function describeOutbound(outbound) {
124
+ const url = payloadString(outbound, "url");
125
+ const method = payloadString(outbound, "method");
126
+ if (url === null || method === null)
127
+ return null;
128
+ let parsed;
129
+ try {
130
+ parsed = new URL(url);
131
+ }
132
+ catch {
133
+ return null;
134
+ }
135
+ return { authority: parsed.host, path: pathOnly(parsed.pathname), method: method.toUpperCase() };
136
+ }
137
+ /** Same method, same path — the minimum for two observations to be describing one exchange at all, checked for both join kinds rather than only the weaker one. */
138
+ function describesSameExchange(target, inbound) {
139
+ const method = payloadString(inbound, "method");
140
+ const path = payloadString(inbound, "path");
141
+ if (method === null || path === null)
142
+ return false;
143
+ return method.toUpperCase() === target.method && pathOnly(path) === target.path;
144
+ }
145
+ function joinFor(input, target) {
146
+ const sameExchange = input.inbound.filter((candidate) => candidate.eventType === "NETWORK_REQUEST" && describesSameExchange(target, candidate));
147
+ // Preferred join first, over the whole candidate set -- an id that both
148
+ // sides carry is a stronger statement than an authority this run bound,
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.
151
+ for (const candidate of sameExchange) {
152
+ const join = correlationJoin(input.outbound, candidate);
153
+ if (join !== null)
154
+ return { inbound: candidate, join };
155
+ }
156
+ const service = input.observedAuthorities?.[target.authority];
157
+ if (service === undefined) {
158
+ return {
159
+ reason: `No inbound observation shares a trace or request id with this outbound ${target.method} ${target.path}, ` +
160
+ `and "${target.authority}" is not among the authorities this run declared it bound ` +
161
+ `(${Object.keys(input.observedAuthorities ?? {}).join(", ") || "none declared"}). ` +
162
+ "Joining on method and path alone would pair two observations that merely look alike.",
163
+ };
164
+ }
165
+ // The outbound call must have reached something. `success` is
166
+ // `fetch`-resolved-rather-than-threw and `status` is the real response
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.
170
+ if (payloadBoolean(input.outbound, "success") !== true) {
171
+ return {
172
+ reason: `The outbound ${target.method} ${target.path} to "${target.authority}" did not resolve to a response ` +
173
+ "(`success` is not true), so it reached no route -- whatever the callee observed in the same window " +
174
+ "was some other client's request.",
175
+ };
176
+ }
177
+ const matching = sameExchange.filter((candidate) => candidate.service === service);
178
+ if (matching.length === 0) {
179
+ return {
180
+ reason: `"${target.authority}" is declared as service "${service}", but that service observed no inbound ` +
181
+ `${target.method} ${target.path} in this run. A call Descry saw leave and never saw arrive is a gap, ` +
182
+ "not an edge.",
183
+ };
184
+ }
185
+ return {
186
+ inbound: matching[0],
187
+ join: { kind: "run-owned-authority", authority: target.authority, service },
188
+ };
189
+ }
190
+ /**
191
+ * Resolve one observed outbound call against the route it reached in another
192
+ * observed process. Returns `observed` only when both ends resolved to real
193
+ * nodes **and** the two observations were shown to be one exchange.
194
+ */
195
+ export function resolveObservedCrossServiceCall(driver, input) {
196
+ if (input.outbound.eventType !== "EXTERNAL_REQUEST") {
197
+ return {
198
+ outcome: "no-stack",
199
+ reason: `Evidence "${input.outbound.evidenceId}" is a ${input.outbound.eventType}, not an EXTERNAL_REQUEST. ` +
200
+ "Only an outbound call captured at its own call site can name a caller.",
201
+ };
202
+ }
203
+ const location = primaryFrameLocation(input.outbound.stackTrace);
204
+ if (location === null || location.file === null || location.functionName === null) {
205
+ return {
206
+ outcome: "no-stack",
207
+ reason: "The outbound call carried no usable call-site stack (none captured, or its site of interest names " +
208
+ "neither a file nor a function). Without a stack the observation names an endpoint and no caller, " +
209
+ "which is the state this whole mechanism exists to leave behind -- reported, not worked around.",
210
+ };
211
+ }
212
+ const target = describeOutbound(input.outbound);
213
+ if (target === null) {
214
+ return {
215
+ outcome: "unjoined",
216
+ reason: "The outbound observation carries no parseable url/method pair, so there is nothing to match a callee " +
217
+ "observation against.",
218
+ };
219
+ }
220
+ const joined = joinFor(input, target);
221
+ if (!("join" in joined))
222
+ return { outcome: "unjoined", reason: joined.reason };
223
+ const inboundMethod = payloadString(joined.inbound, "method") ?? target.method;
224
+ const inboundPath = pathOnly(payloadString(joined.inbound, "path") ?? target.path);
225
+ const endpoint = resolveEndpointNode(driver, inboundMethod, inboundPath);
226
+ if (endpoint.outcome !== "resolved") {
227
+ return {
228
+ outcome: "endpoint-unresolved",
229
+ reason: `The route ${inboundMethod} ${inboundPath} the call actually reached did not resolve to one API_ENDPOINT: ${endpoint.reason}`,
230
+ };
231
+ }
232
+ const resolved = resolveSymbolNode(driver, location.line === null
233
+ ? { file: location.file, symbolName: location.functionName }
234
+ : { file: location.file, symbolName: location.functionName, line: location.line }, input.callerRepo, input.callerRepoRoot === undefined ? {} : { repoRoot: input.callerRepoRoot });
235
+ if (resolved.outcome !== "resolved") {
236
+ return {
237
+ outcome: "caller-unresolved",
238
+ reason: `The call site "${location.functionName}" (${location.file}) did not resolve to one node in repo ` +
239
+ `"${input.callerRepo}": ${resolved.outcome}. An edge needs a caller this graph actually holds.`,
240
+ };
241
+ }
242
+ return {
243
+ outcome: "observed",
244
+ callerNode: resolved.node,
245
+ endpointNode: endpoint.node,
246
+ inbound: joined.inbound,
247
+ join: joined.join,
248
+ reason: `"${resolved.node.name}" issued a real outbound ${target.method} ${target.path}, and ${joined.join.kind === "correlation-id"
249
+ ? `the process serving "${endpoint.node.name}" observed the same request under ${joined.join.idKind} "${joined.join.id}"`
250
+ : `service "${joined.join.service}" -- whose listening post at "${joined.join.authority}" this run bound itself -- independently observed that request arriving`}. Two processes, two independent observations, one exchange, no browser involved.`,
251
+ };
252
+ }
253
+ const EMPTY = {
254
+ promoted: [], created: [], confirmed: [], contradictions: [], staleR4: [], refused: [],
255
+ };
256
+ /**
257
+ * Resolve one observed cross-service call and, when it genuinely observed
258
+ * something, record it as R4 evidence against the graph.
259
+ *
260
+ * The `USES_API` edge this writes is the one a static adapter structurally
261
+ * cannot produce when the target URL is assembled at runtime — the caller in
262
+ * the fixture this was proven against builds it from an environment
263
+ * variable — so this is `applyRuntimeObservations`' "recall gap closed" case
264
+ * far more often than its promotion case.
265
+ */
266
+ export function confirmObservedCrossServiceCall(driver, input) {
267
+ const resolution = resolveObservedCrossServiceCall(driver, input);
268
+ if (resolution.outcome !== "observed") {
269
+ // Deliberately not a call with an empty list: an `adapter_runs` row
270
+ // would be minted for a run that witnessed nothing, which reads in the
271
+ // ledger exactly like a run that observed and found nothing to say.
272
+ // Those are different statements. (`confirm-observed-caller.ts`'s own
273
+ // reasoning, unchanged.)
274
+ return { resolution, observations: [], confirmation: EMPTY };
275
+ }
276
+ const observations = [
277
+ {
278
+ from: resolution.callerNode.id,
279
+ to: resolution.endpointNode.id,
280
+ edgeType: "USES_API",
281
+ held: true,
282
+ detail: `A call-site stack captured on a real outbound HTTP request resolved to ${resolution.callerNode.name} ` +
283
+ `(${resolution.callerNode.file ?? "unknown file"}), and the request was independently observed arriving ` +
284
+ `at ${resolution.endpointNode.name} in another process of the same run (join: ${resolution.join.kind}).`,
285
+ },
286
+ ];
287
+ return {
288
+ resolution,
289
+ observations,
290
+ confirmation: applyRuntimeObservations(driver, {
291
+ runId: input.runId,
292
+ commitSha: input.commitSha,
293
+ observations,
294
+ }),
295
+ };
296
+ }
297
+ //# sourceMappingURL=cross-service-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-service-call.js","sourceRoot":"","sources":["../src/cross-service-call.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AAGH,OAAO,EACL,wBAAwB,GAGzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAiB,MAAM,4BAA4B,CAAC;AAEjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAsEhD,SAAS,aAAa,CAAC,QAAkB,EAAE,GAAW;IACpD,MAAM,KAAK,GAAI,QAAQ,CAAC,OAA0C,EAAE,CAAC,GAAG,CAAC,CAAC;IAC1E,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,SAAS,cAAc,CAAC,QAAkB,EAAE,GAAW;IACrD,MAAM,KAAK,GAAI,QAAQ,CAAC,OAA0C,EAAE,CAAC,GAAG,CAAC,CAAC;IAC1E,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnD,CAAC;AAED,2KAA2K;AAC3K,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,CAAW,EAAE,CAAW;IAC/C,IAAI,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QAClD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IACvE,CAAC;IACD,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC;QACxD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAQD,SAAS,gBAAgB,CAAC,QAAkB;IAC1C,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACjD,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;AACnG,CAAC;AAED,mKAAmK;AACnK,SAAS,qBAAqB,CAAC,MAAsB,EAAE,OAAiB;IACtE,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC;AAClF,CAAC;AAED,SAAS,OAAO,CACd,KAAoC,EACpC,MAAsB;IAEtB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CACvC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,KAAK,iBAAiB,IAAI,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC,CACrG,CAAC;IAEF,wEAAwE;IACxE,wEAAwE;IACxE,oEAAoE;IACpE,8DAA8D;IAC9D,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACxD,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,mBAAmB,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;YACL,MAAM,EACJ,0EAA0E,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,IAAI;gBAC1G,QAAQ,MAAM,CAAC,SAAS,4DAA4D;gBACpF,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,KAAK;gBACnF,sFAAsF;SACzF,CAAC;IACJ,CAAC;IAED,8DAA8D;IAC9D,uEAAuE;IACvE,qEAAqE;IACrE,qEAAqE;IACrE,6CAA6C;IAC7C,IAAI,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;QACvD,OAAO;YACL,MAAM,EACJ,gBAAgB,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,QAAQ,MAAM,CAAC,SAAS,kCAAkC;gBACtG,qGAAqG;gBACrG,kCAAkC;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IACnF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,MAAM,EACJ,IAAI,MAAM,CAAC,SAAS,6BAA6B,OAAO,0CAA0C;gBAClG,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,uEAAuE;gBACtG,cAAc;SACjB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAE;QACrB,IAAI,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE;KAC5E,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAAiB,EACjB,KAAoC;IAEpC,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,kBAAkB,EAAE,CAAC;QACpD,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,MAAM,EACJ,aAAa,KAAK,CAAC,QAAQ,CAAC,UAAU,UAAU,KAAK,CAAC,QAAQ,CAAC,SAAS,6BAA6B;gBACrG,wEAAwE;SAC3E,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACjE,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QAClF,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,MAAM,EACJ,oGAAoG;gBACpG,mGAAmG;gBACnG,gGAAgG;SACnG,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,MAAM,EACJ,uGAAuG;gBACvG,sBAAsB;SACzB,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IAE/E,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC;IAC/E,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IACzE,IAAI,QAAQ,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,qBAAqB;YAC9B,MAAM,EAAE,aAAa,aAAa,IAAI,WAAW,mEAAmE,QAAQ,CAAC,MAAM,EAAE;SACtI,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,CAChC,MAAM,EACN,QAAQ,CAAC,IAAI,KAAK,IAAI;QACpB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,YAAY,EAAE;QAC5D,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EACnF,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,CAC7E,CAAC;IACF,IAAI,QAAQ,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,mBAAmB;YAC5B,MAAM,EACJ,kBAAkB,QAAQ,CAAC,YAAY,MAAM,QAAQ,CAAC,IAAI,wCAAwC;gBAClG,IAAI,KAAK,CAAC,UAAU,MAAM,QAAQ,CAAC,OAAO,qDAAqD;SAClG,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,QAAQ,CAAC,IAAI;QACzB,YAAY,EAAE,QAAQ,CAAC,IAAI;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EACJ,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,4BAA4B,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,SAC5E,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB;YACnC,CAAC,CAAC,wBAAwB,QAAQ,CAAC,IAAI,CAAC,IAAI,qCAAqC,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG;YACzH,CAAC,CAAC,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO,iCAAiC,MAAM,CAAC,IAAI,CAAC,SAAS,yEAC3F,mFAAmF;KACtF,CAAC;AACJ,CAAC;AAkBD,MAAM,KAAK,GAA8B;IACvC,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;CACvF,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAAiB,EACjB,KAA2C;IAE3C,MAAM,UAAU,GAAG,+BAA+B,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClE,IAAI,UAAU,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACtC,oEAAoE;QACpE,uEAAuE;QACvE,oEAAoE;QACpE,sEAAsE;QACtE,yBAAyB;QACzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC/D,CAAC;IAED,MAAM,YAAY,GAAsC;QACtD;YACE,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE;YAC9B,EAAE,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE;YAC9B,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,IAAI;YACV,MAAM,EACJ,0EAA0E,UAAU,CAAC,UAAU,CAAC,IAAI,GAAG;gBACvG,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,IAAI,cAAc,yDAAyD;gBACzG,MAAM,UAAU,CAAC,YAAY,CAAC,IAAI,8CAA8C,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI;SAC3G;KACF,CAAC;IAEF,OAAO;QACL,UAAU;QACV,YAAY;QACZ,YAAY,EAAE,wBAAwB,CAAC,MAAM,EAAE;YAC7C,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY;SACb,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Resolving a captured query's target table name (a real, observed string —
3
- * `extractTargetTable`, `@descryhq-wq/runtime-database-observation`) to the
3
+ * `extractTargetTable`, `@descryy/runtime-database-observation`) to the
4
4
  * `DATABASE_TABLE` node it names — the §10/§18 join `DatabaseQueryCollector`
5
5
  * disclosed as missing since RT-141: real query capture, `graphNodeId`
6
6
  * always null.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Resolving a captured query's target table name (a real, observed string —
3
- * `extractTargetTable`, `@descryhq-wq/runtime-database-observation`) to the
3
+ * `extractTargetTable`, `@descryy/runtime-database-observation`) to the
4
4
  * `DATABASE_TABLE` node it names — the §10/§18 join `DatabaseQueryCollector`
5
5
  * disclosed as missing since RT-141: real query capture, `graphNodeId`
6
6
  * always null.
@@ -50,7 +50,7 @@ export declare function resolveEndpointNode(driver: SqlDriver, method: string, o
50
50
  * this path exist under a different method" needs the method filter removed
51
51
  * entirely, not relaxed.
52
52
  *
53
- * Built for one caller (`@descryhq-wq/runtime-openapi-observation`'s "wrong
53
+ * Built for one caller (`@descryy/runtime-openapi-observation`'s "wrong
54
54
  * method" vs "undocumented" distinction, checklist §15): a request whose
55
55
  * exact method+path resolves to nothing is a different fact from one whose
56
56
  * path resolves under some *other* method — the first says the operation
package/dist/endpoint.js CHANGED
@@ -84,7 +84,7 @@ export function resolveEndpointNode(driver, method, observedPath, options = {})
84
84
  * this path exist under a different method" needs the method filter removed
85
85
  * entirely, not relaxed.
86
86
  *
87
- * Built for one caller (`@descryhq-wq/runtime-openapi-observation`'s "wrong
87
+ * Built for one caller (`@descryy/runtime-openapi-observation`'s "wrong
88
88
  * method" vs "undocumented" distinction, checklist §15): a request whose
89
89
  * exact method+path resolves to nothing is a different fact from one whose
90
90
  * path resolves under some *other* method — the first says the operation
package/dist/index.d.ts CHANGED
@@ -15,5 +15,6 @@ export { resolveEndpointFromLogText, findEndpointMentions, type LogEndpointResol
15
15
  export { resolveFrontendCallers, type FrontendCallerResolution } from "./frontend-caller.ts";
16
16
  export { resolveObservedFrontendCaller, type ObservedFrontendCallerResolution } from "./observed-frontend-caller.ts";
17
17
  export { resolveDatabaseTableNode, type DatabaseTableResolution } from "./database-table.ts";
18
+ export { resolveObservedCrossServiceCall, confirmObservedCrossServiceCall, type CrossServiceJoin, type CrossServiceCallResolution, type ObservedCrossServiceCallInput, type ConfirmObservedCrossServiceCallInput, type ConfirmObservedCrossServiceCallOutcome, } from "./cross-service-call.ts";
18
19
  export { confirmObservedFrontendCaller, type ConfirmObservedCallerInput, type ConfirmObservedCallerOutcome, } from "./confirm-observed-caller.ts";
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,6BAA6B,EAAE,KAAK,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EACL,6BAA6B,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,GAClC,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,6BAA6B,EAAE,KAAK,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,6BAA6B,EAClC,KAAK,oCAAoC,EACzC,KAAK,sCAAsC,GAC5C,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,GAClC,MAAM,8BAA8B,CAAC"}
package/dist/index.js CHANGED
@@ -15,5 +15,6 @@ export { resolveEndpointFromLogText, findEndpointMentions, } from "./log-endpoin
15
15
  export { resolveFrontendCallers } from "./frontend-caller.js";
16
16
  export { resolveObservedFrontendCaller } from "./observed-frontend-caller.js";
17
17
  export { resolveDatabaseTableNode } from "./database-table.js";
18
+ export { resolveObservedCrossServiceCall, confirmObservedCrossServiceCall, } from "./cross-service-call.js";
18
19
  export { confirmObservedFrontendCaller, } from "./confirm-observed-caller.js";
19
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAA2B,MAAM,eAAe,CAAC;AACzG,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,GAKpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GAGrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAiC,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,6BAA6B,EAAyC,MAAM,+BAA+B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAgC,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EACL,6BAA6B,GAG9B,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAA2B,MAAM,eAAe,CAAC;AACzG,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,GAKpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GAGrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAiC,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,6BAA6B,EAAyC,MAAM,+BAA+B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAgC,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,GAMhC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,GAG9B,MAAM,8BAA8B,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@descryy/runtime-graph-correlator",
3
- "version": "0.0.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
- "description": "Resolves runtime evidence to descry-core graph nodes and builds the observed graph path between them. Deliverable of the correlation/graph-integration row — depends on @descryy/runtime-contracts, @descryy/core and @descryy/ir; consumes the graph, does not modify it.",
5
+ "description": "Resolves runtime evidence to descry-core graph nodes and builds the observed graph path between them. Deliverable of the correlation/graph-integration row \u2014 depends on @descryy/runtime-contracts, @descryy/core and @descryy/ir; consumes the graph, does not modify it.",
6
6
  "license": "UNLICENSED",
7
7
  "engines": {
8
8
  "node": ">=22.5"
@@ -24,8 +24,8 @@
24
24
  "build": "tsc -b"
25
25
  },
26
26
  "dependencies": {
27
- "@descryy/runtime-contracts": "*",
28
- "@descryy/core": "^0.1.0",
29
- "@descryy/ir": "^0.1.0"
27
+ "@descryy/runtime-contracts": "0.2.0",
28
+ "@descryy/core": "0.3.0",
29
+ "@descryy/ir": "0.3.0"
30
30
  }
31
31
  }