@descryy/runtime-contracts 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/capability.d.ts +20 -66
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +6 -14
- package/dist/capability.js.map +1 -1
- package/dist/collector.d.ts +34 -86
- package/dist/collector.d.ts.map +1 -1
- package/dist/collector.js +12 -33
- package/dist/collector.js.map +1 -1
- package/dist/correlation.d.ts +10 -42
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +8 -28
- package/dist/correlation.js.map +1 -1
- package/dist/evidence.d.ts +112 -206
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +62 -138
- package/dist/evidence.js.map +1 -1
- package/dist/execution.d.ts +103 -213
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +6 -14
- package/dist/execution.js.map +1 -1
- package/dist/runtime-event.d.ts +13 -31
- package/dist/runtime-event.d.ts.map +1 -1
- package/dist/runtime-event.js +81 -218
- package/dist/runtime-event.js.map +1 -1
- package/dist/source-root.d.ts +33 -60
- package/dist/source-root.d.ts.map +1 -1
- package/dist/source-root.js +23 -44
- package/dist/source-root.js.map +1 -1
- package/package.json +6 -1
package/dist/runtime-event.js
CHANGED
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Runtime Event vocabulary.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* document was available in this repo and guessed at a vocabulary that did
|
|
8
|
-
* not match it; this replaces that guess.
|
|
9
|
-
*
|
|
10
|
-
* This vocabulary is DELIBERATELY INDEPENDENT of the Graph Engine's 15 node
|
|
11
|
-
* types / 15 edge types (descry-core CLAUDE.md, DEC-061) — plan §14 states
|
|
12
|
-
* this explicitly. A runtime event is an observation, not a graph fact, and
|
|
13
|
-
* this list may grow or change on its own schedule. If a runtime need ever
|
|
14
|
-
* looks like it wants a new *graph* node or edge type, that is out of scope
|
|
15
|
-
* here — stop and raise it (plan principle 12). The graph vocabulary is
|
|
16
|
-
* frozen; this one is not.
|
|
2
|
+
* Runtime Event vocabulary, per §14. Deliberately independent of the
|
|
3
|
+
* Graph Engine's 15 node/15 edge types (DEC-061) — a runtime event is an
|
|
4
|
+
* observation, not a graph fact, and can grow on its own schedule. A need
|
|
5
|
+
* that looks like a new graph node/edge type is out of scope here — the
|
|
6
|
+
* graph vocabulary is frozen, this one is not.
|
|
17
7
|
*/
|
|
18
8
|
export const RUNTIME_EVENT_TYPES = [
|
|
19
9
|
"PROCESS_STARTED",
|
|
@@ -23,32 +13,13 @@ export const RUNTIME_EVENT_TYPES = [
|
|
|
23
13
|
"NAVIGATION",
|
|
24
14
|
"CLICK",
|
|
25
15
|
"INPUT",
|
|
26
|
-
/**
|
|
27
|
-
* Beyond plan §14's printed 19 — same standing as `COLLECTOR_ERROR` below,
|
|
28
|
-
* which that list also predates. §5 had no honest type for "an image was
|
|
29
|
-
* captured": not `INPUT`, not `CLICK`, not nothing. Landed together with
|
|
30
|
-
* its one emitter (`BrowserActionCollector.screenshot()`, RT-061) in the
|
|
31
|
-
* same change, per RT-053's own lesson — a declared-but-dead type with no
|
|
32
|
-
* annotation is the mistake, not a type existing at all, but the safest
|
|
33
|
-
* way not to repeat it is to not create one ahead of its wiring.
|
|
34
|
-
*/
|
|
16
|
+
/** Beyond plan §14's printed 19: no honest type existed for "an image was captured." Landed with its one emitter (`BrowserActionCollector.screenshot()`, RT-061), not ahead of it. */
|
|
35
17
|
"SCREENSHOT",
|
|
36
18
|
/**
|
|
37
|
-
* Video evidence
|
|
38
|
-
* `
|
|
39
|
-
* `
|
|
40
|
-
*
|
|
41
|
-
* to a finding alongside screenshots/logs). Same standing as `SCREENSHOT`
|
|
42
|
-
* immediately above and the same discipline: landed together with its one
|
|
43
|
-
* emitter (`BrowserActionCollector.captureVideo()`, `browser-session.ts`'s
|
|
44
|
-
* new `recordVideo` option), not ahead of it.
|
|
45
|
-
*
|
|
46
|
-
* `source: "browser-dom"`, the same source `SCREENSHOT` already uses --
|
|
47
|
-
* see `evidence.ts`'s `EVIDENCE_SOURCES` list for why this did NOT get a
|
|
48
|
-
* new source of its own. Every entry in that list names a domain being
|
|
49
|
-
* *watched*; a kind of captured artifact (an image, a video) is not a
|
|
50
|
-
* domain, which is exactly `SCREENSHOT`'s own precedent applied here
|
|
51
|
-
* rather than re-litigated.
|
|
19
|
+
* Video evidence, landed with its one emitter
|
|
20
|
+
* (`BrowserActionCollector.captureVideo()`), same discipline as
|
|
21
|
+
* `SCREENSHOT`. Uses `source: "browser-dom"`, not a new source — a
|
|
22
|
+
* captured-artifact kind isn't a watched domain (see `EVIDENCE_SOURCES`).
|
|
52
23
|
*/
|
|
53
24
|
"VIDEO",
|
|
54
25
|
"CONSOLE_MESSAGE",
|
|
@@ -59,213 +30,105 @@ export const RUNTIME_EVENT_TYPES = [
|
|
|
59
30
|
"EXCEPTION",
|
|
60
31
|
"STACK_TRACE",
|
|
61
32
|
/**
|
|
62
|
-
* §17
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* never from printed prose.
|
|
66
|
-
*
|
|
67
|
-
* The annotation this comment replaces said *"Nothing emits these three,
|
|
68
|
-
* on purpose, not yet"* and asked to be removed "when §17 lands and one
|
|
69
|
-
* of these three actually gets emitted somewhere." §17 landed in RT-073
|
|
70
|
-
* and the comment outlived it by four entries — noted because the
|
|
71
|
-
* mechanism this file exists to guard against is a claim that stops
|
|
72
|
-
* being true and nothing forcing it to be re-read.
|
|
73
|
-
*
|
|
74
|
-
* ## `TEST_SKIPPED` is the fourth, and it exists because the other three
|
|
75
|
-
* made a skipped test unsayable
|
|
33
|
+
* §17. All four emitted by `packages/test-runner` for node:test,
|
|
34
|
+
* Jest and Vitest, each read from the runner's own structured reporter
|
|
35
|
+
* API, never printed prose.
|
|
76
36
|
*
|
|
77
|
-
*
|
|
37
|
+
* `TEST_SKIPPED` exists because the other three make a skipped test
|
|
38
|
+
* unsayable. Measured across runners (RT-124):
|
|
78
39
|
*
|
|
79
40
|
* | runner | `test.skip` | `test.todo` |
|
|
80
41
|
* | --- | --- | --- |
|
|
81
|
-
* | node:test | `test:pass`
|
|
42
|
+
* | node:test | `test:pass` w/ `skip: true` | `test:pass` w/ `todo: true` |
|
|
82
43
|
* | Vitest 4 | `state: "skipped"` | `state: "skipped"` |
|
|
83
|
-
* | Jest 30 | omitted from `onTestCaseResult`
|
|
84
|
-
*
|
|
85
|
-
* node:test
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* **Landed with its producers in the same change**, deliberately. §3's
|
|
99
|
-
* warning is about `DATABASE_QUERY`/`EXTERNAL_REQUEST` sitting declared
|
|
100
|
-
* and dead below; a type merged "ready for the producers next week" is
|
|
101
|
-
* that same shape regardless of intent.
|
|
102
|
-
*
|
|
103
|
-
* Consumers were checked before this was added rather than after: the
|
|
104
|
-
* only `eventType` branching outside `test-runner` is
|
|
105
|
-
* `evidence-package`'s two **allowlists** (`NETWORK_EVENTS`,
|
|
106
|
-
* `BACKEND_LOG_EVENTS`), and `composeFinding` does not read `eventType`
|
|
107
|
-
* at all. So nothing treats "not passed" as evidence of a problem, and a
|
|
108
|
-
* disabled test cannot be read as a failing one. A future
|
|
109
|
-
* `!== "TEST_PASSED"` would reintroduce exactly that.
|
|
110
|
-
*
|
|
111
|
-
* ## Why there is no `TEST_ABORTED` (RT-129)
|
|
112
|
-
*
|
|
113
|
-
* JUnit reports **four** outcomes, not three: `aborted` (a failed
|
|
114
|
-
* assumption — ran real code, bailed on a precondition) is distinct from
|
|
115
|
-
* `skipped` (`@Disabled` — never ran). Measured by Lane A (RT-088),
|
|
116
|
-
* along with the fact that JUnit's own XML collapses them into one bare
|
|
117
|
-
* `<skipped>` element while its `TestExecutionListener` keeps them apart.
|
|
118
|
-
*
|
|
119
|
-
* The distinction is real and did **not** get a type. The test applied:
|
|
120
|
-
* **does collapsing it change the answer to "was this code covered?"**
|
|
121
|
-
* Skipped-vs-passed does, oppositely, which is why the fourth member
|
|
122
|
-
* above exists. Skipped-vs-aborted does not — every one of them answers
|
|
123
|
-
* `notRun`, carries a location and a qualified name, and is not a
|
|
124
|
-
* failure, so no consumer routes differently. What differs is the
|
|
125
|
-
* *explanation*, and an explanation belongs in the payload.
|
|
126
|
-
*
|
|
127
|
-
* So `TEST_SKIPPED`'s payload carries `skipReason`
|
|
128
|
-
* (`test-runner`'s `SkipReason`): a closed, runner-agnostic vocabulary
|
|
129
|
-
* of `disabled` / `not-implemented` / `precondition-unmet` /
|
|
130
|
-
* `unspecified`. `unspecified` is a real answer, not a fallback — Vitest
|
|
131
|
-
* cannot tell `.skip` from `.todo`, and saying so beats guessing.
|
|
132
|
-
*
|
|
133
|
-
* This also repaired RT-124's own silent collapse: node:test **does**
|
|
134
|
-
* distinguish `skip` from `todo`, and the first version of this type
|
|
135
|
-
* threw that away.
|
|
44
|
+
* | Jest 30 | omitted from `onTestCaseResult` | `status: "todo"` |
|
|
45
|
+
*
|
|
46
|
+
* node:test reports a skip as a pass event — without a fourth member
|
|
47
|
+
* the translator mapped it to `TEST_PASSED`. A counter was tried first
|
|
48
|
+
* (RT-123) but can't carry `sourceLocation`/`qualifiedName`, so "this
|
|
49
|
+
* function's test is disabled" isn't expressible as a finding.
|
|
50
|
+
*
|
|
51
|
+
* No `TEST_ABORTED`: JUnit's `aborted` (failed assumption) is distinct
|
|
52
|
+
* from `skipped` (`@Disabled`, RT-088/RT-129), but both answer `notRun`
|
|
53
|
+
* and neither is a failure, so no consumer routes differently — the
|
|
54
|
+
* difference is explanation, not type. `TEST_SKIPPED`'s payload carries
|
|
55
|
+
* `skipReason` (`disabled`/`not-implemented`/`precondition-unmet`/
|
|
56
|
+
* `unspecified`) instead; `unspecified` is a real answer since Vitest
|
|
57
|
+
* can't tell `.skip` from `.todo`.
|
|
136
58
|
*/
|
|
137
59
|
"TEST_STARTED",
|
|
138
60
|
"TEST_PASSED",
|
|
139
61
|
"TEST_FAILED",
|
|
140
62
|
"TEST_SKIPPED",
|
|
141
63
|
/**
|
|
142
|
-
* `DATABASE_QUERY`
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* (RT-146) — same `--import`-preload mechanism, a different global.
|
|
149
|
-
* Neither is derived from logs. What §18 still does not have: a
|
|
150
|
-
* transaction-boundary concept for queries, graph correlation for either
|
|
151
|
-
* (no resolver from a table name or a hostname to a graph node exists),
|
|
152
|
-
* and provider classification for external requests (a captured
|
|
153
|
-
* hostname, never a guessed provider name) — real, disclosed gaps, not
|
|
154
|
-
* silent ones.
|
|
64
|
+
* §18. `DATABASE_QUERY` via `DatabaseQueryCollector`'s real `node:sqlite`
|
|
65
|
+
* instrumentation (RT-141); `EXTERNAL_REQUEST` via `ExternalRequestCollector`'s
|
|
66
|
+
* real global-`fetch` instrumentation (RT-146). Neither derived from logs.
|
|
67
|
+
* Disclosed gaps: no transaction-boundary concept, no graph correlation
|
|
68
|
+
* (table name / hostname to graph node), no provider classification for
|
|
69
|
+
* external requests (hostname captured, never a guessed provider).
|
|
155
70
|
*/
|
|
156
71
|
"DATABASE_QUERY",
|
|
157
72
|
"EXTERNAL_REQUEST",
|
|
158
73
|
/**
|
|
159
|
-
* The observer failed, not the observed system
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* Without this type there was no way to state that at all. A collector
|
|
167
|
-
* whose consumption loop threw mid-stream logged to the console and
|
|
168
|
-
* resolved `stop()` cleanly, so a run that lost half its backend output
|
|
169
|
-
* was indistinguishable from a run where the backend printed half as
|
|
170
|
-
* much. That is precisely the confusion between *found nothing* and
|
|
171
|
-
* *stopped looking* that the five report categories exist to prevent.
|
|
74
|
+
* The observer failed, not the observed system (§17: "a collector
|
|
75
|
+
* failure must not be mistaken for an application success or absence of
|
|
76
|
+
* failure"). Without it, a collector whose consumption loop threw
|
|
77
|
+
* mid-stream logged to console and resolved `stop()` cleanly — a run
|
|
78
|
+
* that lost half its backend output was indistinguishable from one
|
|
79
|
+
* where the backend just printed less.
|
|
172
80
|
*/
|
|
173
81
|
"COLLECTOR_ERROR",
|
|
174
82
|
/**
|
|
175
|
-
* `
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* change -- same "not declared ahead of its wiring" discipline
|
|
180
|
-
* `SCREENSHOT`'s own comment states above. Not `COLLECTOR_ERROR`: this is
|
|
181
|
-
* not the observer failing, it is a real structural fact the runtime
|
|
182
|
-
* established about the project it is executing (the lockfile-declared
|
|
183
|
-
* version of a dependency does not match what is actually installed),
|
|
184
|
-
* the same "a genuinely new kind of fact gets its own type" precedent
|
|
185
|
-
* `DATABASE_QUERY`/`EXTERNAL_REQUEST` already set for §18 above. Payload
|
|
186
|
-
* carries `name`/`declaredVersion`/`resolvedVersion`, mirroring
|
|
187
|
-
* `DependencyVersionMismatch`'s own shape.
|
|
83
|
+
* `checkDependencyVersions`: lockfile-declared dependency version vs.
|
|
84
|
+
* what's actually installed. Not `COLLECTOR_ERROR` — nothing failed to
|
|
85
|
+
* observe, this is a structural fact about the project. Payload carries
|
|
86
|
+
* `name`/`declaredVersion`/`resolvedVersion`.
|
|
188
87
|
*/
|
|
189
88
|
"DEPENDENCY_VERSION_MISMATCH",
|
|
190
89
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* emitter, not a `COLLECTOR_ERROR` because nothing failed to observe.
|
|
194
|
-
* Payload carries `declaredVersion`/`declaredSource`/`observedVersion`,
|
|
195
|
-
* mirroring `EnvironmentVersionCheckResult`'s own shape.
|
|
90
|
+
* `checkEnvironmentVersion`, same standing as `DEPENDENCY_VERSION_MISMATCH`.
|
|
91
|
+
* Payload carries `declaredVersion`/`declaredSource`/`observedVersion`.
|
|
196
92
|
*/
|
|
197
93
|
"ENVIRONMENT_VERSION_MISMATCH",
|
|
198
94
|
/**
|
|
199
|
-
* RT-225: `BrowserNetworkCollector`'s WebSocket lifecycle listener
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* `
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* `
|
|
213
|
-
*
|
|
214
|
-
* `
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* has no honest HTTP-shaped answer: `NETWORK_RESPONSE` means "a response
|
|
225
|
-
* with a status arrived," which forcing a close into it would fabricate.
|
|
226
|
-
* Measured, not assumed (`websocket-intercept-gap.test.ts`): Playwright's
|
|
227
|
-
* public `WebSocket.on("close")` carries no code or reason at all --
|
|
228
|
-
* identical for a clean server-initiated 1000 close and a raw abrupt TCP
|
|
229
|
-
* termination. So this type does not claim "normal" vs "abnormal"
|
|
230
|
-
* either; it states only that the socket closed, and says so in its own
|
|
231
|
-
* payload rather than guessing. Emitted only when no `socketerror` was
|
|
232
|
-
* already reported for the same socket, so a failed connection is never
|
|
233
|
-
* double-reported once as `HTTP_ERROR` and again as `WEBSOCKET_CLOSED`.
|
|
234
|
-
*
|
|
235
|
-
* Deliberately outside `signal-channel.ts`'s `CHANNEL_BY_EVENT_TYPE`
|
|
236
|
-
* table (§5.2 of the ratified `ai-governance-spec.md`, a separate,
|
|
237
|
-
* already-settled ruling this change does not reopen) -- falls through to
|
|
238
|
-
* `null`/no-signal there, which is that table's own documented "fail
|
|
239
|
-
* closed" default for a type it has not ruled on, and is the honest
|
|
240
|
-
* answer for a fact this thin: "the socket closed" carries far less on
|
|
241
|
-
* its own than a real request/response/error triple does.
|
|
242
|
-
*
|
|
243
|
-
* Per-message frame traffic (`framesent`/`framereceived`) is not
|
|
244
|
-
* captured as evidence at all -- out of scope here, disclosed rather than
|
|
245
|
-
* silently dropped, in `browser-network-collector.ts`'s own module
|
|
246
|
-
* comment. Neither is `EventSource`/SSE, which shares the same
|
|
247
|
-
* uncovered shape (the RT-PENDING note above flagged it as unmeasured;
|
|
248
|
-
* still unmeasured after this change).
|
|
95
|
+
* RT-225: `BrowserNetworkCollector`'s WebSocket lifecycle listener.
|
|
96
|
+
* Before this, a WS connection fired none of
|
|
97
|
+
* `NETWORK_REQUEST`/`NETWORK_RESPONSE`/`HTTP_ERROR` — those are wired to
|
|
98
|
+
* `request`/`requestfinished`/`requestfailed` only, and Playwright
|
|
99
|
+
* surfaces WebSocket traffic through a separate event stream.
|
|
100
|
+
*
|
|
101
|
+
* A connection attempt reuses `NETWORK_REQUEST`; a connection failure
|
|
102
|
+
* (`socketerror`) reuses `HTTP_ERROR` with `status: null` — same "no
|
|
103
|
+
* usable response" convention as a refused `fetch()`. Forcing WS fields
|
|
104
|
+
* into the HTTP shape would fabricate a method/status, but the event
|
|
105
|
+
* itself is the same fact under a different protocol, so reuse keeps
|
|
106
|
+
* this in the existing network signal channel.
|
|
107
|
+
*
|
|
108
|
+
* `WEBSOCKET_CLOSED` is the one new fact: a close has no honest
|
|
109
|
+
* HTTP-shaped answer. Measured (`websocket-intercept-gap.test.ts`):
|
|
110
|
+
* Playwright's `WebSocket.on("close")` carries no code or reason —
|
|
111
|
+
* identical for a clean 1000 close and an abrupt TCP termination — so
|
|
112
|
+
* this type doesn't claim normal vs. abnormal either. Emitted only when
|
|
113
|
+
* no `socketerror` was already reported for the same socket, so a
|
|
114
|
+
* failed connection isn't double-reported.
|
|
115
|
+
*
|
|
116
|
+
* Deliberately outside `signal-channel.ts`'s `CHANNEL_BY_EVENT_TYPE` —
|
|
117
|
+
* falls through to no-signal, the documented fail-closed default.
|
|
118
|
+
* Per-message frame traffic and EventSource/SSE are not captured
|
|
119
|
+
* (disclosed gap, `browser-network-collector.ts`).
|
|
249
120
|
*/
|
|
250
121
|
"WEBSOCKET_CLOSED",
|
|
251
122
|
];
|
|
252
123
|
/**
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* Without knowing the prefix it attributed them to the application, and a
|
|
262
|
-
* user's report showed Descry's own instrumentation chatter as lines their
|
|
263
|
-
* service printed. This constant is the one place that says which vocabulary
|
|
264
|
-
* is Descry's, so the collector can leave it alone and every marker module can
|
|
265
|
-
* derive from it instead of spelling the prefix again.
|
|
266
|
-
*
|
|
267
|
-
* Anchored at the start of a line by every consumer: a log line that merely
|
|
268
|
-
* *mentions* a marker is the application's own output.
|
|
124
|
+
* The prefix Descry reserves on an observed process's stdout. A preload
|
|
125
|
+
* instrumenting a process from the inside reports each observation as one
|
|
126
|
+
* line of structured JSON there (`DESCRY_DB_QUERY {...}`, etc). Found the
|
|
127
|
+
* hard way: without this, the backend log collector reading the same
|
|
128
|
+
* stdout attributed Descry's own instrumentation chatter to the
|
|
129
|
+
* application. One place defines the prefix; every marker module derives
|
|
130
|
+
* from it. Anchored at line start by every consumer — a line that merely
|
|
131
|
+
* mentions a marker is the application's own output.
|
|
269
132
|
*/
|
|
270
133
|
export const RESERVED_MARKER_PREFIX = "DESCRY_";
|
|
271
134
|
//# sourceMappingURL=runtime-event.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-event.js","sourceRoot":"","sources":["../src/runtime-event.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runtime-event.js","sourceRoot":"","sources":["../src/runtime-event.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,iBAAiB;IACjB,eAAe;IACf,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,OAAO;IACP,OAAO;IACP,sLAAsL;IACtL,YAAY;IACZ;;;;;OAKG;IACH,OAAO;IACP,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,YAAY;IACZ,aAAa;IACb,WAAW;IACX,aAAa;IACb;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,cAAc;IACd,aAAa;IACb,aAAa;IACb,cAAc;IACd;;;;;;;OAOG;IACH,gBAAgB;IAChB,kBAAkB;IAClB;;;;;;;OAOG;IACH,iBAAiB;IACjB;;;;;OAKG;IACH,6BAA6B;IAC7B;;;OAGG;IACH,8BAA8B;IAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,kBAAkB;CACV,CAAC;AAIX;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC"}
|
package/dist/source-root.d.ts
CHANGED
|
@@ -1,71 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Origin -> service root (RT-023, built on RT-028's `ProcessHandle.serviceName`/
|
|
3
3
|
* `.port` and `ExecutionConfiguration.services`). Answers "which service's
|
|
4
|
-
* declared `cwd` served this browser origin
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* resolution logic can run.
|
|
4
|
+
* declared `cwd` served this browser origin" — the link `BrowserConsoleCollector`
|
|
5
|
+
* needs to turn `http://localhost:4000/app.js` into a candidate on-disk root
|
|
6
|
+
* before `file://`-based source resolution can run.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* only (RT-021's precedent) -- this lives in contracts so that boundary
|
|
12
|
-
* holds for this resolver too.
|
|
8
|
+
* Stops at a configuration-layer fact, not a collector — `packages/browser`
|
|
9
|
+
* depends on `@descryy/runtime-contracts` only (RT-021), so this lives here.
|
|
13
10
|
*
|
|
14
|
-
* Two
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* ephemeral allocation (RT-024's own default) this is true almost all
|
|
21
|
-
* of the time, which is exactly the phrase RT-024 says not to write
|
|
22
|
-
* down as identity. Nothing here re-verifies the process is still the
|
|
23
|
-
* one that was live when the browser made the request.
|
|
24
|
-
* 2. **A resolved root is configured, not verified** -- see
|
|
25
|
-
* `ConfiguredServiceRoot`.
|
|
26
|
-
*
|
|
27
|
-
* Same class of gap, two layers: a port match confirms an address: a
|
|
28
|
-
* `cwd` confirms a declared root. Neither confirms who was actually there.
|
|
11
|
+
* Two disclosed honesty gaps (RT-024-shaped):
|
|
12
|
+
* 1. The port join proves an address, not a correspondent — matching
|
|
13
|
+
* `origin.port` to a recorded `ProcessHandle` proves the origin matches
|
|
14
|
+
* a port this execution assigned, not that the browser talked to that
|
|
15
|
+
* specific process. Nothing re-verifies the process was still live.
|
|
16
|
+
* 2. A resolved root is configured, not verified — see `ConfiguredServiceRoot`.
|
|
29
17
|
*/
|
|
30
18
|
import type { Execution } from "./execution.ts";
|
|
31
19
|
/**
|
|
32
20
|
* A service's declared working directory, recovered by joining a running
|
|
33
21
|
* process's assigned port back to `ExecutionConfiguration.services`.
|
|
34
22
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* the stronger claim without breaking this weaker one. Same shape as
|
|
41
|
-
* RT-024's "readiness proves liveness, not identity": this proves *a*
|
|
42
|
-
* root, not that a given file came from the checkout in it.
|
|
23
|
+
* Configured, not verified: proves the origin maps to a directory the
|
|
24
|
+
* orchestrator was told to run the service from, not that any specific
|
|
25
|
+
* file actually lives under it (a subdirectory-rooted static server,
|
|
26
|
+
* symlink, proxy, or post-spawn `cwd` change would all break the stronger
|
|
27
|
+
* claim without breaking this one).
|
|
43
28
|
*
|
|
44
|
-
* Not a refusal
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* applies to `file://` paths rather than trusting "the path looks right."
|
|
50
|
-
* A failed existence check downstream is the honest refusal; this function
|
|
51
|
-
* returning a root is not, by itself, a claim that the check will pass.
|
|
29
|
+
* Not a refusal — the weaker claim is still useful. The caller should
|
|
30
|
+
* join the frame's path onto `declaredCwd` and confirm the file exists
|
|
31
|
+
* (same `existsSync` discipline `createNodeSourceLocationResolver` uses
|
|
32
|
+
* for `file://` paths) — that check, not this function, is where a
|
|
33
|
+
* failure should surface.
|
|
52
34
|
*/
|
|
53
35
|
export interface ConfiguredServiceRoot {
|
|
54
36
|
readonly serviceName: string;
|
|
55
37
|
readonly declaredCwd: string;
|
|
56
38
|
}
|
|
57
39
|
/**
|
|
58
|
-
* Closed, so a caller can branch on *why* rather than pattern-match prose
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* input itself wasn't a resolvable origin; `noProcessOnPort` means nothing
|
|
64
|
-
* in this execution claims that port at all; `processUnnamed` is a wiring
|
|
65
|
-
* gap (a real process, spawned without a `serviceName`) that's closable by
|
|
66
|
-
* whoever spawned it; `serviceNotConfigured` is a configuration error (a
|
|
67
|
-
* `serviceName` with no matching `services` entry) -- different from a
|
|
68
|
-
* wiring gap because the name exists but the config doesn't back it.
|
|
40
|
+
* Closed, so a caller can branch on *why* rather than pattern-match prose.
|
|
41
|
+
* `originNoPort`/`originUnparseable`: input wasn't a resolvable origin.
|
|
42
|
+
* `noProcessOnPort`: nothing in this execution claims that port.
|
|
43
|
+
* `processUnnamed`: a real process spawned without a `serviceName` (wiring gap).
|
|
44
|
+
* `serviceNotConfigured`: a `serviceName` with no matching `services` entry.
|
|
69
45
|
*/
|
|
70
46
|
export declare const SERVICE_ROOT_REFUSALS: readonly ["originNoPort", "originUnparseable", "noProcessOnPort", "processUnnamed", "serviceNotConfigured"];
|
|
71
47
|
export type ServiceRootRefusal = (typeof SERVICE_ROOT_REFUSALS)[number];
|
|
@@ -79,19 +55,16 @@ export type ServiceRootLookup = {
|
|
|
79
55
|
};
|
|
80
56
|
/**
|
|
81
57
|
* Resolves a browser origin (e.g. `"http://localhost:4000"`) to the
|
|
82
|
-
* service that served it
|
|
83
|
-
*
|
|
58
|
+
* service that served it: `execution.processes[].port` (real OS-assigned
|
|
59
|
+
* port, RT-028) to `.serviceName`, then to
|
|
84
60
|
* `execution.configuration.services[name].cwd`.
|
|
85
61
|
*
|
|
86
|
-
* `origin` is a clean origin, not a full frame location
|
|
87
|
-
* `file:37:12`-shaped V8 frame down to its origin is the caller's job
|
|
88
|
-
* (mirrors `createNodeSourceLocationResolver`'s own division of labor:
|
|
89
|
-
* frame parsing is a separate concern from root resolution).
|
|
62
|
+
* `origin` is a clean origin, not a full frame location — stripping a
|
|
63
|
+
* `file:37:12`-shaped V8 frame down to its origin is the caller's job.
|
|
90
64
|
*
|
|
91
|
-
* Two services sharing the same `declaredCwd`
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* coincidentally-shared path on the output side has nothing to disambiguate.
|
|
65
|
+
* Two services sharing the same `declaredCwd` isn't ambiguous here:
|
|
66
|
+
* resolution is process -> serviceName -> keyed lookup, never a reverse
|
|
67
|
+
* search by directory.
|
|
95
68
|
*/
|
|
96
69
|
export declare function resolveServiceRootForOrigin(origin: string, execution: Pick<Execution, "processes" | "configuration">): ServiceRootLookup;
|
|
97
70
|
//# sourceMappingURL=source-root.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-root.d.ts","sourceRoot":"","sources":["../src/source-root.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"source-root.d.ts","sourceRoot":"","sources":["../src/source-root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,6GAMxB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9F;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe,CAAC,GACxD,iBAAiB,CA2CnB"}
|
package/dist/source-root.js
CHANGED
|
@@ -1,44 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Origin -> service root (RT-023, built on RT-028's `ProcessHandle.serviceName`/
|
|
3
3
|
* `.port` and `ExecutionConfiguration.services`). Answers "which service's
|
|
4
|
-
* declared `cwd` served this browser origin
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* resolution logic can run.
|
|
4
|
+
* declared `cwd` served this browser origin" — the link `BrowserConsoleCollector`
|
|
5
|
+
* needs to turn `http://localhost:4000/app.js` into a candidate on-disk root
|
|
6
|
+
* before `file://`-based source resolution can run.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* only (RT-021's precedent) -- this lives in contracts so that boundary
|
|
12
|
-
* holds for this resolver too.
|
|
8
|
+
* Stops at a configuration-layer fact, not a collector — `packages/browser`
|
|
9
|
+
* depends on `@descryy/runtime-contracts` only (RT-021), so this lives here.
|
|
13
10
|
*
|
|
14
|
-
* Two
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* ephemeral allocation (RT-024's own default) this is true almost all
|
|
21
|
-
* of the time, which is exactly the phrase RT-024 says not to write
|
|
22
|
-
* down as identity. Nothing here re-verifies the process is still the
|
|
23
|
-
* one that was live when the browser made the request.
|
|
24
|
-
* 2. **A resolved root is configured, not verified** -- see
|
|
25
|
-
* `ConfiguredServiceRoot`.
|
|
26
|
-
*
|
|
27
|
-
* Same class of gap, two layers: a port match confirms an address: a
|
|
28
|
-
* `cwd` confirms a declared root. Neither confirms who was actually there.
|
|
11
|
+
* Two disclosed honesty gaps (RT-024-shaped):
|
|
12
|
+
* 1. The port join proves an address, not a correspondent — matching
|
|
13
|
+
* `origin.port` to a recorded `ProcessHandle` proves the origin matches
|
|
14
|
+
* a port this execution assigned, not that the browser talked to that
|
|
15
|
+
* specific process. Nothing re-verifies the process was still live.
|
|
16
|
+
* 2. A resolved root is configured, not verified — see `ConfiguredServiceRoot`.
|
|
29
17
|
*/
|
|
30
18
|
/**
|
|
31
|
-
* Closed, so a caller can branch on *why* rather than pattern-match prose
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* input itself wasn't a resolvable origin; `noProcessOnPort` means nothing
|
|
37
|
-
* in this execution claims that port at all; `processUnnamed` is a wiring
|
|
38
|
-
* gap (a real process, spawned without a `serviceName`) that's closable by
|
|
39
|
-
* whoever spawned it; `serviceNotConfigured` is a configuration error (a
|
|
40
|
-
* `serviceName` with no matching `services` entry) -- different from a
|
|
41
|
-
* wiring gap because the name exists but the config doesn't back it.
|
|
19
|
+
* Closed, so a caller can branch on *why* rather than pattern-match prose.
|
|
20
|
+
* `originNoPort`/`originUnparseable`: input wasn't a resolvable origin.
|
|
21
|
+
* `noProcessOnPort`: nothing in this execution claims that port.
|
|
22
|
+
* `processUnnamed`: a real process spawned without a `serviceName` (wiring gap).
|
|
23
|
+
* `serviceNotConfigured`: a `serviceName` with no matching `services` entry.
|
|
42
24
|
*/
|
|
43
25
|
export const SERVICE_ROOT_REFUSALS = [
|
|
44
26
|
"originNoPort",
|
|
@@ -49,19 +31,16 @@ export const SERVICE_ROOT_REFUSALS = [
|
|
|
49
31
|
];
|
|
50
32
|
/**
|
|
51
33
|
* Resolves a browser origin (e.g. `"http://localhost:4000"`) to the
|
|
52
|
-
* service that served it
|
|
53
|
-
*
|
|
34
|
+
* service that served it: `execution.processes[].port` (real OS-assigned
|
|
35
|
+
* port, RT-028) to `.serviceName`, then to
|
|
54
36
|
* `execution.configuration.services[name].cwd`.
|
|
55
37
|
*
|
|
56
|
-
* `origin` is a clean origin, not a full frame location
|
|
57
|
-
* `file:37:12`-shaped V8 frame down to its origin is the caller's job
|
|
58
|
-
* (mirrors `createNodeSourceLocationResolver`'s own division of labor:
|
|
59
|
-
* frame parsing is a separate concern from root resolution).
|
|
38
|
+
* `origin` is a clean origin, not a full frame location — stripping a
|
|
39
|
+
* `file:37:12`-shaped V8 frame down to its origin is the caller's job.
|
|
60
40
|
*
|
|
61
|
-
* Two services sharing the same `declaredCwd`
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* coincidentally-shared path on the output side has nothing to disambiguate.
|
|
41
|
+
* Two services sharing the same `declaredCwd` isn't ambiguous here:
|
|
42
|
+
* resolution is process -> serviceName -> keyed lookup, never a reverse
|
|
43
|
+
* search by directory.
|
|
65
44
|
*/
|
|
66
45
|
export function resolveServiceRootForOrigin(origin, execution) {
|
|
67
46
|
let port;
|
package/dist/source-root.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-root.js","sourceRoot":"","sources":["../src/source-root.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"source-root.js","sourceRoot":"","sources":["../src/source-root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAyBH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,gBAAgB;IAChB,sBAAsB;CACd,CAAC;AAOX;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAc,EACd,SAAyD;IAEzD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;YACpB,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,cAAc;gBACvB,OAAO,EAAE,WAAW,MAAM,wEAAwE;aACnG,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,IAAI,MAAM,6BAA6B,EAAE,CAAC;IAC1G,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACjF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,iBAAiB;YAC1B,OAAO,EAAE,iDAAiD,IAAI,EAAE;SACjE,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QACjC,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,gBAAgB;YACzB,OAAO,EAAE,6BAA6B,IAAI,oIAAoI;SAC/K,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,sBAAsB;YAC/B,OAAO,EAAE,gBAAgB,OAAO,CAAC,WAAW,qCAAqC,IAAI,mDAAmD;SACzI,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;AAC/F,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descryy/runtime-contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The six runtime contracts: Execution, Evidence, Runtime Event, Collector, Capability, Correlation. Agents 2-4 build against this; it does not depend on them.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/descryhq-wq/descry-runtime.git",
|
|
10
|
+
"directory": "packages/contracts"
|
|
11
|
+
},
|
|
7
12
|
"engines": {
|
|
8
13
|
"node": ">=22.5"
|
|
9
14
|
},
|