@descryy/runtime-external-service-observation 0.2.0 → 0.3.1
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/collector-version.d.ts +1 -8
- package/dist/collector-version.d.ts.map +1 -1
- package/dist/collector-version.js +1 -8
- package/dist/collector-version.js.map +1 -1
- package/dist/fetch-instrumentation.d.ts +26 -51
- package/dist/fetch-instrumentation.d.ts.map +1 -1
- package/dist/fetch-instrumentation.js +64 -90
- package/dist/fetch-instrumentation.js.map +1 -1
- package/dist/header-correlation.d.ts +6 -13
- package/dist/header-correlation.d.ts.map +1 -1
- package/dist/header-correlation.js +6 -13
- package/dist/header-correlation.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/dist/request-collector.d.ts +20 -43
- package/dist/request-collector.d.ts.map +1 -1
- package/dist/request-collector.js +76 -58
- package/dist/request-collector.js.map +1 -1
- package/dist/request-line-parser.d.ts +18 -15
- package/dist/request-line-parser.d.ts.map +1 -1
- package/dist/request-line-parser.js +32 -24
- package/dist/request-line-parser.js.map +1 -1
- package/dist/request-marker.d.ts +22 -35
- package/dist/request-marker.d.ts.map +1 -1
- package/dist/request-marker.js +18 -27
- package/dist/request-marker.js.map +1 -1
- package/dist/service-identity.d.ts +5 -17
- package/dist/service-identity.d.ts.map +1 -1
- package/dist/service-identity.js +5 -17
- package/dist/service-identity.js.map +1 -1
- package/package.json +9 -4
|
@@ -1,47 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ExternalRequestCollector
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* failure reported as evidence rather than swallowed — but for a different
|
|
8
|
-
* marker on the same stream.
|
|
2
|
+
* `ExternalRequestCollector`: translates `fetch-instrumentation.ts`'s
|
|
3
|
+
* captured requests into `EXTERNAL_REQUEST` Evidence. Same shape as
|
|
4
|
+
* `DatabaseQueryCollector` (RT-141) — `ProcessOutputSource` in, `Evidence`
|
|
5
|
+
* out, failures reported as evidence — for a different marker on the same
|
|
6
|
+
* stream.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* (`service-identity.ts`), and `graphNodeId` is always null — no resolver
|
|
15
|
-
* from a captured hostname to any graph node exists (nothing in the 15
|
|
16
|
-
* canonical node types names an external service). All real §18 rows, left
|
|
17
|
-
* open rather than guessed at, matching `DatabaseQueryCollector`'s own
|
|
18
|
-
* disclosure of the same shape of gap.
|
|
8
|
+
* Does NOT: capture request/response bodies (preload never reads either
|
|
9
|
+
* stream), classify providers beyond hostname (`service-identity.ts`), or
|
|
10
|
+
* set `graphNodeId` (no resolver from a hostname to any of the 15 canonical
|
|
11
|
+
* node types exists). Disclosed gaps, matching `DatabaseQueryCollector`'s own.
|
|
19
12
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* `
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* the preload that writes it runs inside the calling process, so the stack
|
|
26
|
-
* was always available — nobody had captured it. It is captured now
|
|
27
|
-
* (`fetch-instrumentation.ts`), and this collector attaches it.
|
|
28
|
-
*
|
|
29
|
-
* Parsing it is **not** this package's job. V8's `Error.stack` format is one
|
|
30
|
-
* language's, and this collector observes the marker protocol, which is not.
|
|
31
|
-
* So a `StackTraceParser` is an option, supplied by whoever knows which
|
|
32
|
-
* runtime is being observed — `RuntimeAdapter.stackTraceParser` is exactly
|
|
33
|
-
* that value, already on the seam. Omitted, this collector behaves exactly as
|
|
34
|
-
* it did before the capture existed and **says so** in `capabilities()`:
|
|
35
|
-
* `stackCapture: unavailable`, with the reason. A half-wired capability that
|
|
36
|
-
* quietly reports nothing is the failure mode this project's honest-
|
|
37
|
-
* degradation rule exists to prevent.
|
|
13
|
+
* `stackTrace` is parsed via an injected `StackTraceParser` — parsing V8's
|
|
14
|
+
* format is not this package's job, so the observed runtime's own parser
|
|
15
|
+
* (`RuntimeAdapter.stackTraceParser`) is supplied by the caller. Omitted,
|
|
16
|
+
* `capabilities()` reports `stackCapture: unavailable` with the reason
|
|
17
|
+
* rather than silently reporting nothing.
|
|
38
18
|
*/
|
|
39
19
|
import { fileURLToPath } from "node:url";
|
|
40
|
-
import { parseRequestLine } from "./request-line-parser.js";
|
|
20
|
+
import { parseRequestLine, parseFetchBindingFailureLine } from "./request-line-parser.js";
|
|
41
21
|
import { extractServiceIdentity } from "./service-identity.js";
|
|
42
22
|
import { extractHeaderCorrelationIds } from "./header-correlation.js";
|
|
43
23
|
import { COLLECTOR_VERSION } from "./collector-version.js";
|
|
44
|
-
/** Absolute path to the compiled preload, for
|
|
24
|
+
/** Absolute path to the compiled preload, for `node --import <this> <app>`. Never imported directly — loaded by Node in the observed process. */
|
|
45
25
|
export const FETCH_PRELOAD_MODULE_PATH = fileURLToPath(new URL("./fetch-instrumentation.js", import.meta.url));
|
|
46
26
|
const EVENT_TYPE = "EXTERNAL_REQUEST";
|
|
47
27
|
function computeCapabilities(hasStackParser) {
|
|
@@ -52,15 +32,12 @@ function computeCapabilities(hasStackParser) {
|
|
|
52
32
|
consoleObservation: status,
|
|
53
33
|
networkObservation: status,
|
|
54
34
|
backendLogAccess: status,
|
|
55
|
-
// Real HTTP headers, structurally read (Headers/Request,
|
|
56
|
-
//
|
|
57
|
-
// BrowserNetworkCollector already makes for its own captured requests.
|
|
35
|
+
// Real HTTP headers, structurally read (Headers/Request), same claim
|
|
36
|
+
// strength BrowserNetworkCollector makes for its own captured requests.
|
|
58
37
|
distributedTrace: { availability: "available", reason: null },
|
|
59
38
|
sourceMapping: status,
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
// only when a parser was actually supplied to turn it into frames --
|
|
63
|
-
// capturing text nothing can read is not a capability.
|
|
39
|
+
// Claimed only when a parser was actually supplied — capturing text
|
|
40
|
+
// nothing can read is not a capability.
|
|
64
41
|
stackCapture: hasStackParser
|
|
65
42
|
? { availability: "available", reason: null }
|
|
66
43
|
: {
|
|
@@ -77,24 +54,23 @@ export function createExternalRequestCollector(options) {
|
|
|
77
54
|
const capabilities = computeCapabilities(options.stackTraceParser !== undefined);
|
|
78
55
|
let consumeLoopDone;
|
|
79
56
|
let consumptionFailure = null;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
*/
|
|
57
|
+
// C-F6: set once FETCH_BINDING_FAILURE_MARKER is seen — the preload found
|
|
58
|
+
// no real `globalThis.fetch`, so no call was ever observed. Before this,
|
|
59
|
+
// capabilities() kept reporting "available" regardless.
|
|
60
|
+
let bindingFailure = null;
|
|
61
|
+
/** `null` for nothing captured, no parser, or a parser that refused the text — passed through rather than softened. */
|
|
86
62
|
async function parseStack(request) {
|
|
87
63
|
if (request.stack === null || options.stackTraceParser === undefined)
|
|
88
64
|
return null;
|
|
89
65
|
return await options.stackTraceParser.parse(request.stack);
|
|
90
66
|
}
|
|
91
|
-
async function emitCapturedRequest(request, context) {
|
|
67
|
+
async function emitCapturedRequest(request, context, preExisting) {
|
|
92
68
|
const { traceId, requestId } = extractHeaderCorrelationIds(request.requestHeaders);
|
|
93
69
|
const stackTrace = await parseStack(request);
|
|
94
70
|
context.emit({
|
|
95
71
|
timestamp: new Date().toISOString(),
|
|
96
72
|
source: "backend-process",
|
|
97
|
-
service: options.service ?? null,
|
|
73
|
+
service: options.source.serviceName ?? options.service ?? null,
|
|
98
74
|
process: options.source.processId,
|
|
99
75
|
eventType: EVENT_TYPE,
|
|
100
76
|
payload: {
|
|
@@ -110,23 +86,54 @@ export function createExternalRequestCollector(options) {
|
|
|
110
86
|
traceId,
|
|
111
87
|
requestId,
|
|
112
88
|
correlationId: null,
|
|
113
|
-
// No resolver from a
|
|
114
|
-
//
|
|
89
|
+
// No resolver from a hostname to a graph node exists — none of the
|
|
90
|
+
// 15 canonical node types names an external service.
|
|
115
91
|
graphNodeId: null,
|
|
116
92
|
sourceLocation: null,
|
|
117
93
|
stackTrace,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
94
|
+
confidence: 1, // a real captured call, real timing — not probabilistic
|
|
95
|
+
redactionStatus: "pending-redaction",
|
|
96
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
97
|
+
// RT-N3: this capture came from a line the source itself marked as
|
|
98
|
+
// pre-existing (e.g. an attach-mode target's log content from before
|
|
99
|
+
// attach) -- see `ProcessOutputLine.preExisting`.
|
|
100
|
+
...(preExisting ? { preExisting: true } : {}),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function emitBindingFailure(reason, context) {
|
|
104
|
+
bindingFailure = reason;
|
|
105
|
+
context.emit({
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
source: "backend-process",
|
|
108
|
+
service: options.source.serviceName ?? options.service ?? null,
|
|
109
|
+
process: options.source.processId,
|
|
110
|
+
eventType: "COLLECTOR_ERROR",
|
|
111
|
+
payload: {
|
|
112
|
+
raw: `external request collector for process "${options.source.processId}": the fetch preload could not bind -- ${reason}. No outbound call in this process can be observed.`,
|
|
113
|
+
collectorId: `external-request-collector:${options.source.processId}`,
|
|
114
|
+
error: reason,
|
|
115
|
+
},
|
|
116
|
+
traceId: null,
|
|
117
|
+
requestId: null,
|
|
118
|
+
correlationId: null,
|
|
119
|
+
graphNodeId: null,
|
|
120
|
+
sourceLocation: null,
|
|
121
|
+
stackTrace: null,
|
|
122
|
+
confidence: 1, // our own failure to bind, not an inference about the app
|
|
121
123
|
redactionStatus: "pending-redaction",
|
|
122
124
|
collectorVersion: COLLECTOR_VERSION,
|
|
123
125
|
});
|
|
124
126
|
}
|
|
125
127
|
async function consume(context) {
|
|
126
128
|
for await (const line of options.source.lines) {
|
|
129
|
+
const binding = parseFetchBindingFailureLine(line.text);
|
|
130
|
+
if (binding !== null) {
|
|
131
|
+
emitBindingFailure(binding.reason, context);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
127
134
|
const request = parseRequestLine(line.text);
|
|
128
135
|
if (request !== null)
|
|
129
|
-
await emitCapturedRequest(request, context);
|
|
136
|
+
await emitCapturedRequest(request, context, line.preExisting === true);
|
|
130
137
|
}
|
|
131
138
|
}
|
|
132
139
|
return {
|
|
@@ -139,7 +146,7 @@ export function createExternalRequestCollector(options) {
|
|
|
139
146
|
context.emit({
|
|
140
147
|
timestamp: new Date().toISOString(),
|
|
141
148
|
source: "backend-process",
|
|
142
|
-
service: options.service ?? null,
|
|
149
|
+
service: options.source.serviceName ?? options.service ?? null,
|
|
143
150
|
process: options.source.processId,
|
|
144
151
|
eventType: "COLLECTOR_ERROR",
|
|
145
152
|
payload: {
|
|
@@ -168,6 +175,17 @@ export function createExternalRequestCollector(options) {
|
|
|
168
175
|
await consumeLoopDone;
|
|
169
176
|
},
|
|
170
177
|
capabilities() {
|
|
178
|
+
// Binding failure takes priority — externalServiceObservation was
|
|
179
|
+
// never real for this process, worse than "stopped early" below.
|
|
180
|
+
if (bindingFailure !== null) {
|
|
181
|
+
return {
|
|
182
|
+
...capabilities,
|
|
183
|
+
externalServiceObservation: {
|
|
184
|
+
availability: "unavailable",
|
|
185
|
+
reason: `the fetch preload never bound a real globalThis.fetch (${bindingFailure}) -- no outbound call in this process was observed.`,
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
171
189
|
if (consumptionFailure === null)
|
|
172
190
|
return capabilities;
|
|
173
191
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-collector.js","sourceRoot":"","sources":["../src/request-collector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"request-collector.js","sourceRoot":"","sources":["../src/request-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reads one process-output line for the `REQUEST_MARKER` prefix.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* patch the parsing process's own `globalThis.fetch`. See `request-marker.ts`
|
|
7
|
-
* for the measurement. Everything else — the application's own real
|
|
8
|
-
* stdout/stderr — is not this parser's concern and is left alone; an
|
|
9
|
-
* external-request collector does not also try to be a log collector.
|
|
2
|
+
* Reads one process-output line for the `REQUEST_MARKER` prefix. The
|
|
3
|
+
* marker comes from `request-marker.ts`, never `fetch-instrumentation.ts`
|
|
4
|
+
* — importing the emitter would patch the parsing process's own fetch.
|
|
5
|
+
* Everything else (the app's real stdout/stderr) is left alone.
|
|
10
6
|
*/
|
|
11
|
-
import { REQUEST_MARKER, type CapturedRequest } from "./request-marker.ts";
|
|
7
|
+
import { REQUEST_MARKER, FETCH_BINDING_FAILURE_MARKER, type CapturedRequest } from "./request-marker.ts";
|
|
12
8
|
/**
|
|
13
|
-
* `null` for a non-matching line
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* never guessed at, the same distinction `parseQueryLine`
|
|
17
|
-
* (`@descryy/runtime-database-observation`) makes.
|
|
9
|
+
* `null` for a non-matching line AND for a marker-prefixed line that fails
|
|
10
|
+
* to parse — malformed is refused, never guessed at, same as
|
|
11
|
+
* `parseQueryLine` (`@descryy/runtime-database-observation`).
|
|
18
12
|
*/
|
|
19
13
|
export declare function parseRequestLine(line: string): CapturedRequest | null;
|
|
14
|
+
/**
|
|
15
|
+
* C-F6: recognises the preload's disclosure that it found no real
|
|
16
|
+
* `globalThis.fetch`. `null` for every other line. A malformed line past
|
|
17
|
+
* the marker prefix still counts as a binding failure (the marker itself is
|
|
18
|
+
* the fact that matters) with a generic reason substituted.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseFetchBindingFailureLine(line: string): {
|
|
21
|
+
readonly reason: string;
|
|
22
|
+
} | null;
|
|
20
23
|
export type { CapturedRequest };
|
|
21
|
-
export { REQUEST_MARKER };
|
|
24
|
+
export { REQUEST_MARKER, FETCH_BINDING_FAILURE_MARKER };
|
|
22
25
|
//# sourceMappingURL=request-line-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-line-parser.d.ts","sourceRoot":"","sources":["../src/request-line-parser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"request-line-parser.d.ts","sourceRoot":"","sources":["../src/request-line-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,4BAA4B,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAmBzG;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAarE;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS7F;AAED,YAAY,EAAE,eAAe,EAAE,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,4BAA4B,EAAE,CAAC"}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reads one process-output line for the `REQUEST_MARKER` prefix.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* patch the parsing process's own `globalThis.fetch`. See `request-marker.ts`
|
|
7
|
-
* for the measurement. Everything else — the application's own real
|
|
8
|
-
* stdout/stderr — is not this parser's concern and is left alone; an
|
|
9
|
-
* external-request collector does not also try to be a log collector.
|
|
2
|
+
* Reads one process-output line for the `REQUEST_MARKER` prefix. The
|
|
3
|
+
* marker comes from `request-marker.ts`, never `fetch-instrumentation.ts`
|
|
4
|
+
* — importing the emitter would patch the parsing process's own fetch.
|
|
5
|
+
* Everything else (the app's real stdout/stderr) is left alone.
|
|
10
6
|
*/
|
|
11
|
-
import { REQUEST_MARKER } from "./request-marker.js";
|
|
7
|
+
import { REQUEST_MARKER, FETCH_BINDING_FAILURE_MARKER } from "./request-marker.js";
|
|
12
8
|
function isCapturedRequest(value) {
|
|
13
9
|
if (typeof value !== "object" || value === null)
|
|
14
10
|
return false;
|
|
@@ -23,22 +19,17 @@ function isCapturedRequest(value) {
|
|
|
23
19
|
return false;
|
|
24
20
|
if (typeof v.requestHeaders !== "object" || v.requestHeaders === null)
|
|
25
21
|
return false;
|
|
26
|
-
// `stack` is the one field allowed to be absent
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// "no stack was captured" already means everywhere downstream. Anything
|
|
30
|
-
// present but not a string is malformed and refused, same as every other
|
|
31
|
-
// field here.
|
|
22
|
+
// `stack` is the one field allowed to be absent (a pre-capture marker
|
|
23
|
+
// line genuinely carries none) — normalised to `null` below. Present but
|
|
24
|
+
// not a string is malformed and refused like every other field.
|
|
32
25
|
if (v.stack !== undefined && v.stack !== null && typeof v.stack !== "string")
|
|
33
26
|
return false;
|
|
34
27
|
return Object.values(v.requestHeaders).every((value) => typeof value === "string");
|
|
35
28
|
}
|
|
36
29
|
/**
|
|
37
|
-
* `null` for a non-matching line
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* never guessed at, the same distinction `parseQueryLine`
|
|
41
|
-
* (`@descryy/runtime-database-observation`) makes.
|
|
30
|
+
* `null` for a non-matching line AND for a marker-prefixed line that fails
|
|
31
|
+
* to parse — malformed is refused, never guessed at, same as
|
|
32
|
+
* `parseQueryLine` (`@descryy/runtime-database-observation`).
|
|
42
33
|
*/
|
|
43
34
|
export function parseRequestLine(line) {
|
|
44
35
|
if (!line.startsWith(`${REQUEST_MARKER} `))
|
|
@@ -53,10 +44,27 @@ export function parseRequestLine(line) {
|
|
|
53
44
|
}
|
|
54
45
|
if (!isCapturedRequest(parsed))
|
|
55
46
|
return null;
|
|
56
|
-
// Absent `stack` becomes
|
|
57
|
-
//
|
|
58
|
-
// are the same fact and only one of them is representable downstream.
|
|
47
|
+
// Absent `stack` becomes explicit `null` — "missing" and "not captured"
|
|
48
|
+
// are the same fact downstream.
|
|
59
49
|
return { ...parsed, stack: parsed.stack ?? null };
|
|
60
50
|
}
|
|
61
|
-
|
|
51
|
+
/**
|
|
52
|
+
* C-F6: recognises the preload's disclosure that it found no real
|
|
53
|
+
* `globalThis.fetch`. `null` for every other line. A malformed line past
|
|
54
|
+
* the marker prefix still counts as a binding failure (the marker itself is
|
|
55
|
+
* the fact that matters) with a generic reason substituted.
|
|
56
|
+
*/
|
|
57
|
+
export function parseFetchBindingFailureLine(line) {
|
|
58
|
+
if (!line.startsWith(`${FETCH_BINDING_FAILURE_MARKER} `))
|
|
59
|
+
return null;
|
|
60
|
+
const json = line.slice(FETCH_BINDING_FAILURE_MARKER.length + 1);
|
|
61
|
+
try {
|
|
62
|
+
const parsed = JSON.parse(json);
|
|
63
|
+
return { reason: typeof parsed.reason === "string" ? parsed.reason : "no real globalThis.fetch was found to instrument" };
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return { reason: "no real globalThis.fetch was found to instrument" };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export { REQUEST_MARKER, FETCH_BINDING_FAILURE_MARKER };
|
|
62
70
|
//# sourceMappingURL=request-line-parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-line-parser.js","sourceRoot":"","sources":["../src/request-line-parser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"request-line-parser.js","sourceRoot":"","sources":["../src/request-line-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,4BAA4B,EAAwB,MAAM,qBAAqB,CAAC;AAIzG,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5E,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACrF,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACpE,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,OAAO,CAAC,CAAC,cAAc,KAAK,QAAQ,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACpF,sEAAsE;IACtE,yEAAyE;IACzE,gEAAgE;IAChE,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3F,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,cAAyC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;AAChH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,cAAc,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,wEAAwE;IACxE,gCAAgC;IAChC,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAY;IACvD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,4BAA4B,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC;QACxD,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,kDAAkD,EAAE,CAAC;IAC5H,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,kDAAkD,EAAE,CAAC;IACxE,CAAC;AACH,CAAC;AAGD,OAAO,EAAE,cAAc,EAAE,4BAA4B,EAAE,CAAC"}
|
package/dist/request-marker.d.ts
CHANGED
|
@@ -1,50 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The wire vocabulary shared by
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* everywhere else. `request-line-parser.ts` needed nothing from it but the
|
|
10
|
-
* string `"DESCRY_EXTERNAL_REQUEST"`, and importing a string is still
|
|
11
|
-
* importing a module: the patch and the stdout writer came along, through the
|
|
12
|
-
* package index, into every consumer.
|
|
13
|
-
*
|
|
14
|
-
* **This is `query-marker.ts`'s defect, one package over, and it was still
|
|
15
|
-
* open.** `@descryy/runtime-database-observation` found the identical shape,
|
|
16
|
-
* measured it into `@descryy/mcp`'s JSON-RPC transport — 14,906 marker lines
|
|
17
|
-
* in one `analyze` call — and carved the vocabulary out. Nothing did the same
|
|
18
|
-
* here, and nothing noticed, because nothing outside this repository imports
|
|
19
|
-
* this package yet. `observe_runtime` consuming this collector is precisely
|
|
20
|
-
* the change that would have noticed.
|
|
21
|
-
*
|
|
22
|
-
* So: the emitter imports the vocabulary, the parser imports the vocabulary,
|
|
23
|
-
* and neither imports the other. Anything added here must stay a constant or
|
|
24
|
-
* a type. A function with a module-scope effect would rebuild the same trap
|
|
25
|
-
* one file over.
|
|
2
|
+
* The wire vocabulary shared by both halves of external-service observation:
|
|
3
|
+
* marker prefix + shape. Must stay free of side effects — a function with a
|
|
4
|
+
* module-scope effect (like `fetch-instrumentation.ts`'s fetch patch) would
|
|
5
|
+
* leak into every consumer that only needs the vocabulary. This is
|
|
6
|
+
* `query-marker.ts`'s defect (measured: 14,906 marker lines through
|
|
7
|
+
* `@descryy/mcp`'s JSON-RPC transport in one `analyze` call), carved out
|
|
8
|
+
* here before anything hit it the same way.
|
|
26
9
|
*/
|
|
27
10
|
export declare const REQUEST_MARKER = "DESCRY_EXTERNAL_REQUEST";
|
|
11
|
+
/**
|
|
12
|
+
* C-F6: written once, by `fetch-instrumentation.ts`, when `globalThis.fetch`
|
|
13
|
+
* wasn't a real function at preload time — a distinct line from
|
|
14
|
+
* `REQUEST_MARKER`, since nothing was actually observed. Without this, a
|
|
15
|
+
* missing real `fetch` would surface as an ordinary failure indistinguishable
|
|
16
|
+
* from a real network error, and `capabilities()` would claim "available"
|
|
17
|
+
* when zero calls were ever seen.
|
|
18
|
+
*/
|
|
19
|
+
export declare const FETCH_BINDING_FAILURE_MARKER = "DESCRY_EXTERNAL_REQUEST_FETCH_BINDING_FAILED";
|
|
28
20
|
export interface CapturedRequest {
|
|
29
21
|
readonly url: string;
|
|
30
22
|
readonly method: string;
|
|
31
23
|
readonly requestHeaders: Readonly<Record<string, string>>;
|
|
32
|
-
/** `null` only when `success` is `false`
|
|
24
|
+
/** `null` only when `success` is `false` — the call never resolved to a response. */
|
|
33
25
|
readonly status: number | null;
|
|
34
26
|
readonly durationMs: number;
|
|
35
|
-
/** `true` iff `fetch` resolved rather than threw.
|
|
27
|
+
/** `true` iff `fetch` resolved rather than threw. A 4xx/5xx status is still `success: true` — fetch doesn't reject on one. */
|
|
36
28
|
readonly success: boolean;
|
|
37
29
|
readonly error: string | null;
|
|
38
30
|
/**
|
|
39
|
-
* The
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Raw text on purpose: parsing V8's format is
|
|
45
|
-
* `@descryy/runtime-adapter-typescript`'s job and belongs in the observing
|
|
46
|
-
* process, the same read-here/interpret-there split every marker in this
|
|
47
|
-
* repository already uses.
|
|
31
|
+
* The application's own stack at the `fetch` call, raw and unparsed, with
|
|
32
|
+
* the preload's wrapper frames removed. `null` if the runtime produced no
|
|
33
|
+
* stack. Raw text on purpose — parsing V8's format belongs in the
|
|
34
|
+
* observing process (`@descryy/runtime-adapter-typescript`), not here.
|
|
48
35
|
*/
|
|
49
36
|
readonly stack: string | null;
|
|
50
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-marker.d.ts","sourceRoot":"","sources":["../src/request-marker.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"request-marker.d.ts","sourceRoot":"","sources":["../src/request-marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,eAAO,MAAM,cAAc,4BAA8C,CAAC;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,iDAAmE,CAAC;AAE7G,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8HAA8H;IAC9H,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B"}
|
package/dist/request-marker.js
CHANGED
|
@@ -1,32 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The wire vocabulary shared by
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* everywhere else. `request-line-parser.ts` needed nothing from it but the
|
|
10
|
-
* string `"DESCRY_EXTERNAL_REQUEST"`, and importing a string is still
|
|
11
|
-
* importing a module: the patch and the stdout writer came along, through the
|
|
12
|
-
* package index, into every consumer.
|
|
13
|
-
*
|
|
14
|
-
* **This is `query-marker.ts`'s defect, one package over, and it was still
|
|
15
|
-
* open.** `@descryy/runtime-database-observation` found the identical shape,
|
|
16
|
-
* measured it into `@descryy/mcp`'s JSON-RPC transport — 14,906 marker lines
|
|
17
|
-
* in one `analyze` call — and carved the vocabulary out. Nothing did the same
|
|
18
|
-
* here, and nothing noticed, because nothing outside this repository imports
|
|
19
|
-
* this package yet. `observe_runtime` consuming this collector is precisely
|
|
20
|
-
* the change that would have noticed.
|
|
21
|
-
*
|
|
22
|
-
* So: the emitter imports the vocabulary, the parser imports the vocabulary,
|
|
23
|
-
* and neither imports the other. Anything added here must stay a constant or
|
|
24
|
-
* a type. A function with a module-scope effect would rebuild the same trap
|
|
25
|
-
* one file over.
|
|
2
|
+
* The wire vocabulary shared by both halves of external-service observation:
|
|
3
|
+
* marker prefix + shape. Must stay free of side effects — a function with a
|
|
4
|
+
* module-scope effect (like `fetch-instrumentation.ts`'s fetch patch) would
|
|
5
|
+
* leak into every consumer that only needs the vocabulary. This is
|
|
6
|
+
* `query-marker.ts`'s defect (measured: 14,906 marker lines through
|
|
7
|
+
* `@descryy/mcp`'s JSON-RPC transport in one `analyze` call), carved out
|
|
8
|
+
* here before anything hit it the same way.
|
|
26
9
|
*/
|
|
27
10
|
import { RESERVED_MARKER_PREFIX } from "@descryy/runtime-contracts";
|
|
28
|
-
// Derived
|
|
29
|
-
//
|
|
30
|
-
// come back as the application's own log output.
|
|
11
|
+
// Derived from `RESERVED_MARKER_PREFIX`, which the backend log collector
|
|
12
|
+
// skips on — a marker not using it would look like app log output.
|
|
31
13
|
export const REQUEST_MARKER = `${RESERVED_MARKER_PREFIX}EXTERNAL_REQUEST`;
|
|
14
|
+
/**
|
|
15
|
+
* C-F6: written once, by `fetch-instrumentation.ts`, when `globalThis.fetch`
|
|
16
|
+
* wasn't a real function at preload time — a distinct line from
|
|
17
|
+
* `REQUEST_MARKER`, since nothing was actually observed. Without this, a
|
|
18
|
+
* missing real `fetch` would surface as an ordinary failure indistinguishable
|
|
19
|
+
* from a real network error, and `capabilities()` would claim "available"
|
|
20
|
+
* when zero calls were ever seen.
|
|
21
|
+
*/
|
|
22
|
+
export const FETCH_BINDING_FAILURE_MARKER = `${RESERVED_MARKER_PREFIX}EXTERNAL_REQUEST_FETCH_BINDING_FAILED`;
|
|
32
23
|
//# sourceMappingURL=request-marker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-marker.js","sourceRoot":"","sources":["../src/request-marker.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"request-marker.js","sourceRoot":"","sources":["../src/request-marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,yEAAyE;AACzE,mEAAmE;AACnE,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,sBAAsB,kBAAkB,CAAC;AAE1E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,sBAAsB,uCAAuC,CAAC"}
|
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A captured request's "service identity"
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `payment provider` / etc. (§18's own "Potential integrations" list) —
|
|
8
|
-
* that would be a lookup table of well-known hosts this project has no
|
|
9
|
-
* source of truth for, guessed rather than read off anything the
|
|
10
|
-
* application declared. The hostname is a real, observed fact; a provider
|
|
11
|
-
* label would not be. If a consumer wants a friendlier name for a known
|
|
12
|
-
* host, that is a later, disclosed classification step layered on top of
|
|
13
|
-
* this, not something this function silently does.
|
|
14
|
-
*
|
|
15
|
-
* `null` for a URL that does not parse — refused rather than guessed, the
|
|
16
|
-
* same shape `extractTargetTable`
|
|
17
|
-
* (`@descryy/runtime-database-observation`) refuses a SQL statement it does
|
|
18
|
-
* not recognise.
|
|
2
|
+
* A captured request's "service identity" is its URL's hostname, nothing
|
|
3
|
+
* more. Never classified into "Stripe" / "payment provider" etc — no
|
|
4
|
+
* source of truth for that, and a guessed label isn't an observed fact.
|
|
5
|
+
* `null` for a URL that doesn't parse — refused rather than guessed, same
|
|
6
|
+
* as `extractTargetTable` (`@descryy/runtime-database-observation`).
|
|
19
7
|
*/
|
|
20
8
|
export declare function extractServiceIdentity(url: string): string | null;
|
|
21
9
|
//# sourceMappingURL=service-identity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-identity.d.ts","sourceRoot":"","sources":["../src/service-identity.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"service-identity.d.ts","sourceRoot":"","sources":["../src/service-identity.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMjE"}
|
package/dist/service-identity.js
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A captured request's "service identity"
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `payment provider` / etc. (§18's own "Potential integrations" list) —
|
|
8
|
-
* that would be a lookup table of well-known hosts this project has no
|
|
9
|
-
* source of truth for, guessed rather than read off anything the
|
|
10
|
-
* application declared. The hostname is a real, observed fact; a provider
|
|
11
|
-
* label would not be. If a consumer wants a friendlier name for a known
|
|
12
|
-
* host, that is a later, disclosed classification step layered on top of
|
|
13
|
-
* this, not something this function silently does.
|
|
14
|
-
*
|
|
15
|
-
* `null` for a URL that does not parse — refused rather than guessed, the
|
|
16
|
-
* same shape `extractTargetTable`
|
|
17
|
-
* (`@descryy/runtime-database-observation`) refuses a SQL statement it does
|
|
18
|
-
* not recognise.
|
|
2
|
+
* A captured request's "service identity" is its URL's hostname, nothing
|
|
3
|
+
* more. Never classified into "Stripe" / "payment provider" etc — no
|
|
4
|
+
* source of truth for that, and a guessed label isn't an observed fact.
|
|
5
|
+
* `null` for a URL that doesn't parse — refused rather than guessed, same
|
|
6
|
+
* as `extractTargetTable` (`@descryy/runtime-database-observation`).
|
|
19
7
|
*/
|
|
20
8
|
export function extractServiceIdentity(url) {
|
|
21
9
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-identity.js","sourceRoot":"","sources":["../src/service-identity.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"service-identity.js","sourceRoot":"","sources":["../src/service-identity.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descryy/runtime-external-service-observation",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "External service observation (plan
|
|
5
|
+
"description": "External service observation (plan §18, checklist §18): real EXTERNAL_REQUEST capture via client instrumentation, never parsed application logs. Client #1 is the global fetch.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/descryhq-wq/descry-runtime.git",
|
|
10
|
+
"directory": "packages/external-service-observation"
|
|
11
|
+
},
|
|
7
12
|
"engines": {
|
|
8
13
|
"node": ">=22.5"
|
|
9
14
|
},
|
|
@@ -24,8 +29,8 @@
|
|
|
24
29
|
"build": "tsc -b"
|
|
25
30
|
},
|
|
26
31
|
"dependencies": {
|
|
27
|
-
"@descryy/runtime-contracts": "0.
|
|
28
|
-
"@descryy/runtime-backend-observation": "0.
|
|
32
|
+
"@descryy/runtime-contracts": "0.3.1",
|
|
33
|
+
"@descryy/runtime-backend-observation": "0.3.1"
|
|
29
34
|
},
|
|
30
35
|
"devDependencies": {
|
|
31
36
|
"@descryy/runtime-controller": "*",
|