@gate-forge/witness 0.0.0-stage → 0.8.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.
Files changed (123) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +114 -2
  3. package/dist/adapter/contract-suite.d.ts +167 -0
  4. package/dist/adapter/contract-suite.d.ts.map +1 -0
  5. package/dist/adapter/contract-suite.js +348 -0
  6. package/dist/adapter/contract-suite.js.map +1 -0
  7. package/dist/adapter/contract.d.ts +266 -0
  8. package/dist/adapter/contract.d.ts.map +1 -0
  9. package/dist/adapter/contract.js +2 -0
  10. package/dist/adapter/contract.js.map +1 -0
  11. package/dist/adapter/index.d.ts +8 -0
  12. package/dist/adapter/index.d.ts.map +1 -0
  13. package/dist/adapter/index.js +2 -0
  14. package/dist/adapter/index.js.map +1 -0
  15. package/dist/adapter-kit/config.d.ts +163 -0
  16. package/dist/adapter-kit/config.d.ts.map +1 -0
  17. package/dist/adapter-kit/config.js +21 -0
  18. package/dist/adapter-kit/config.js.map +1 -0
  19. package/dist/adapter-kit/define.d.ts +47 -0
  20. package/dist/adapter-kit/define.d.ts.map +1 -0
  21. package/dist/adapter-kit/define.js +336 -0
  22. package/dist/adapter-kit/define.js.map +1 -0
  23. package/dist/adapter-kit/index.d.ts +34 -0
  24. package/dist/adapter-kit/index.d.ts.map +1 -0
  25. package/dist/adapter-kit/index.js +32 -0
  26. package/dist/adapter-kit/index.js.map +1 -0
  27. package/dist/adapter-kit/projection.d.ts +69 -0
  28. package/dist/adapter-kit/projection.d.ts.map +1 -0
  29. package/dist/adapter-kit/projection.js +85 -0
  30. package/dist/adapter-kit/projection.js.map +1 -0
  31. package/dist/adapter-kit/session.d.ts +105 -0
  32. package/dist/adapter-kit/session.d.ts.map +1 -0
  33. package/dist/adapter-kit/session.js +230 -0
  34. package/dist/adapter-kit/session.js.map +1 -0
  35. package/dist/client/witness-client.d.ts +193 -0
  36. package/dist/client/witness-client.d.ts.map +1 -0
  37. package/dist/client/witness-client.js +321 -0
  38. package/dist/client/witness-client.js.map +1 -0
  39. package/dist/constants.d.ts +189 -0
  40. package/dist/constants.d.ts.map +1 -0
  41. package/dist/constants.js +197 -0
  42. package/dist/constants.js.map +1 -0
  43. package/dist/index.d.ts +15 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +20 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/json.d.ts +16 -0
  48. package/dist/json.d.ts.map +1 -0
  49. package/dist/json.js +21 -0
  50. package/dist/json.js.map +1 -0
  51. package/dist/queue/bullmq.d.ts +28 -0
  52. package/dist/queue/bullmq.d.ts.map +1 -0
  53. package/dist/queue/bullmq.js +210 -0
  54. package/dist/queue/bullmq.js.map +1 -0
  55. package/dist/queue/observer.d.ts +130 -0
  56. package/dist/queue/observer.d.ts.map +1 -0
  57. package/dist/queue/observer.js +179 -0
  58. package/dist/queue/observer.js.map +1 -0
  59. package/dist/surface.d.ts +211 -0
  60. package/dist/surface.d.ts.map +1 -0
  61. package/dist/surface.js +268 -0
  62. package/dist/surface.js.map +1 -0
  63. package/dist/witness/adapter-registry.d.ts +92 -0
  64. package/dist/witness/adapter-registry.d.ts.map +1 -0
  65. package/dist/witness/adapter-registry.js +370 -0
  66. package/dist/witness/adapter-registry.js.map +1 -0
  67. package/dist/witness/behavior-request.d.ts +80 -0
  68. package/dist/witness/behavior-request.d.ts.map +1 -0
  69. package/dist/witness/behavior-request.js +335 -0
  70. package/dist/witness/behavior-request.js.map +1 -0
  71. package/dist/witness/behavior.d.ts +52 -0
  72. package/dist/witness/behavior.d.ts.map +1 -0
  73. package/dist/witness/behavior.js +118 -0
  74. package/dist/witness/behavior.js.map +1 -0
  75. package/dist/witness/bin.d.ts +21 -0
  76. package/dist/witness/bin.d.ts.map +1 -0
  77. package/dist/witness/bin.js +254 -0
  78. package/dist/witness/bin.js.map +1 -0
  79. package/dist/witness/browser.d.ts +221 -0
  80. package/dist/witness/browser.d.ts.map +1 -0
  81. package/dist/witness/browser.js +644 -0
  82. package/dist/witness/browser.js.map +1 -0
  83. package/dist/witness/chaos.d.ts +179 -0
  84. package/dist/witness/chaos.d.ts.map +1 -0
  85. package/dist/witness/chaos.js +270 -0
  86. package/dist/witness/chaos.js.map +1 -0
  87. package/dist/witness/classifications.d.ts +42 -0
  88. package/dist/witness/classifications.d.ts.map +1 -0
  89. package/dist/witness/classifications.js +87 -0
  90. package/dist/witness/classifications.js.map +1 -0
  91. package/dist/witness/env-attestation.d.ts +98 -0
  92. package/dist/witness/env-attestation.d.ts.map +1 -0
  93. package/dist/witness/env-attestation.js +202 -0
  94. package/dist/witness/env-attestation.js.map +1 -0
  95. package/dist/witness/fixture-provider.d.ts +89 -0
  96. package/dist/witness/fixture-provider.d.ts.map +1 -0
  97. package/dist/witness/fixture-provider.js +116 -0
  98. package/dist/witness/fixture-provider.js.map +1 -0
  99. package/dist/witness/loopback-pins.d.ts +79 -0
  100. package/dist/witness/loopback-pins.d.ts.map +1 -0
  101. package/dist/witness/loopback-pins.js +244 -0
  102. package/dist/witness/loopback-pins.js.map +1 -0
  103. package/dist/witness/run-options.d.ts +47 -0
  104. package/dist/witness/run-options.d.ts.map +1 -0
  105. package/dist/witness/run-options.js +179 -0
  106. package/dist/witness/run-options.js.map +1 -0
  107. package/dist/witness/server.d.ts +34 -0
  108. package/dist/witness/server.d.ts.map +1 -0
  109. package/dist/witness/server.js +4899 -0
  110. package/dist/witness/server.js.map +1 -0
  111. package/dist/witness/task.d.ts +77 -0
  112. package/dist/witness/task.d.ts.map +1 -0
  113. package/dist/witness/task.js +201 -0
  114. package/dist/witness/task.js.map +1 -0
  115. package/dist/witness/twin-shapes.d.ts +51 -0
  116. package/dist/witness/twin-shapes.d.ts.map +1 -0
  117. package/dist/witness/twin-shapes.js +127 -0
  118. package/dist/witness/twin-shapes.js.map +1 -0
  119. package/dist/witness/types.d.ts +1094 -0
  120. package/dist/witness/types.d.ts.map +1 -0
  121. package/dist/witness/types.js +2 -0
  122. package/dist/witness/types.js.map +1 -0
  123. package/package.json +98 -4
@@ -0,0 +1,335 @@
1
+ /**
2
+ * Witness-owned engine-http request driver (plan 2026-09-19 §4.6, Phase 5):
3
+ * executes one approved `request` action against the approved subject
4
+ * origin with approved actor material. The worker never touches the
5
+ * request — method, path, query, body, and credentials all resolve
6
+ * engine-side from the supervisor-bound case and the trusted lease.
7
+ *
8
+ * Bounds (fail closed, never a hashed prefix):
9
+ * - request/response bodies are capped (over-limit blocks);
10
+ * - the origin must be loopback (plan invariant 5, GF-10);
11
+ * - the `multipart` encoding still needs the Phase 6 file driver and
12
+ * blocks here; `raw` bodies are supported ONLY with an engine-side
13
+ * signature profile (plan 2026-09-25 Phase 1), because raw bytes are
14
+ * exactly what a signature covers;
15
+ * - resolved path values cannot smuggle segments (`/` rejected).
16
+ */
17
+ import { createHmac, randomUUID } from 'node:crypto';
18
+ import { BEHAVIOR_SIGNING_SECRET_HEADER, parseBehaviorSignatureProfile, sha256Canonical, } from '@gate-forge/core';
19
+ import { assertLoopback } from './env-attestation.js';
20
+ /** Proof-input bound (request and response bodies alike). */
21
+ export const BEHAVIOR_BODY_LIMIT_BYTES = 256 * 1024;
22
+ /** Typed driver failure (always a blocking diagnostic, never proof). */
23
+ export class BehaviorDriverError extends Error {
24
+ constructor(message) {
25
+ super(message);
26
+ this.name = 'BehaviorDriverError';
27
+ }
28
+ }
29
+ /** Unsafe fixture-key segments (no prototype-chain traversal). */
30
+ const FORBIDDEN_SEGMENTS = new Set(['__proto__', 'prototype', 'constructor']);
31
+ /** Resolves one InputValue against sealed lease subjects. */
32
+ function resolveValue(raw, subjects, what) {
33
+ if (raw.from === 'literal')
34
+ return raw.value ?? null;
35
+ if (raw.from === 'fixture') {
36
+ if (typeof raw.key !== 'string')
37
+ throw new BehaviorDriverError(`${what} fixture reference has no key`);
38
+ const segments = raw.key.split('.');
39
+ if (segments.some((segment) => segment.length === 0 || FORBIDDEN_SEGMENTS.has(segment))) {
40
+ throw new BehaviorDriverError(`${what} fixture key is forbidden`);
41
+ }
42
+ let current = subjects;
43
+ for (const segment of segments) {
44
+ if (typeof current !== 'object' || current === null || Array.isArray(current)) {
45
+ throw new BehaviorDriverError(`${what} fixture key '${raw.key}' does not resolve`);
46
+ }
47
+ if (!Object.prototype.hasOwnProperty.call(current, segment)) {
48
+ throw new BehaviorDriverError(`${what} fixture key '${raw.key}' does not resolve`);
49
+ }
50
+ current = current[segment];
51
+ }
52
+ return current ?? null;
53
+ }
54
+ throw new BehaviorDriverError(`${what} uses an unsupported value source '${raw.from}'`);
55
+ }
56
+ /** Reads a bounded body from a fetch response (over-limit aborts). */
57
+ async function readBoundedBody(response, limit) {
58
+ const reader = response.body?.getReader();
59
+ if (reader === undefined || reader === null) {
60
+ const text = await response.text();
61
+ if (text.length > limit)
62
+ throw new BehaviorDriverError('response body exceeds the proof bound');
63
+ return text;
64
+ }
65
+ const chunks = [];
66
+ let total = 0;
67
+ for (;;) {
68
+ const { done, value } = await reader.read();
69
+ if (done)
70
+ break;
71
+ total += value.byteLength;
72
+ if (total > limit) {
73
+ try {
74
+ await response.body?.cancel();
75
+ }
76
+ catch {
77
+ // Best-effort cancel; the bound violation below is the verdict.
78
+ }
79
+ throw new BehaviorDriverError('response body exceeds the proof bound');
80
+ }
81
+ chunks.push(value);
82
+ }
83
+ return Buffer.concat(chunks).toString('utf8');
84
+ }
85
+ /** Parses a body as JSON, falling back to raw text. */
86
+ function parseBody(text) {
87
+ const trimmed = text.trim();
88
+ if (trimmed.length === 0)
89
+ return '';
90
+ try {
91
+ return JSON.parse(trimmed);
92
+ }
93
+ catch {
94
+ return text;
95
+ }
96
+ }
97
+ /**
98
+ * Stamps one engine-side signature (plan 2026-09-25 Phase 1).
99
+ *
100
+ * The secret is read from the trusted lease and never leaves this
101
+ * function: the request carries the digest, not the key. The digest
102
+ * covers the EXACT bytes that go on the wire.
103
+ *
104
+ * Args:
105
+ * profile: the validated signature profile.
106
+ * secret: engine-side signing secret from the actor material.
107
+ * bodyText: the exact request body the driver sends.
108
+ * headers: request headers to stamp into (mutated in place).
109
+ * declaredTimestampMs: a lease-declared stamp (a stale-delivery case),
110
+ * or null to stamp the engine clock.
111
+ *
112
+ * Returns:
113
+ * string: the body text to send (always the declared body).
114
+ *
115
+ * Throws:
116
+ * BehaviorDriverError: the engine's own stamp is outside the declared
117
+ * tolerance — always a blocking diagnostic, never proof.
118
+ */
119
+ function stampSignature(profile, secret, bodyText, headers, declaredTimestampMs) {
120
+ const now = Date.now();
121
+ // The signature covers the EXACT bytes the driver sends. A declared
122
+ // forgery flips one nibble of the DIGEST, never the body: the engine
123
+ // binds submitted bytes to the declared fixture, so an altered body
124
+ // would be refused as evidence rather than graded.
125
+ let digest = createHmac('sha256', secret).update(bodyText, 'utf8').digest('hex');
126
+ if (profile.forgery === 'signature') {
127
+ // The digest is not the secret: flipping one nibble makes it a
128
+ // signature that cannot verify, deterministically.
129
+ const last = digest.length - 1;
130
+ digest = `${digest.slice(0, last)}${digest[last] === '0' ? '1' : '0'}`;
131
+ }
132
+ headers[profile.header] = digest;
133
+ if (profile.timestampHeader !== null) {
134
+ const stamp = declaredTimestampMs ?? now;
135
+ if (profile.toleranceMs !== null && Math.abs(now - stamp) > profile.toleranceMs) {
136
+ throw new BehaviorDriverError(`declared signature timestamp is ${String(Math.abs(now - stamp))}ms from the engine clock, ` +
137
+ `outside the declared tolerance of ${String(profile.toleranceMs)}ms`);
138
+ }
139
+ headers[profile.timestampHeader] = String(stamp);
140
+ }
141
+ if (profile.attemptHeader !== null) {
142
+ headers[profile.attemptHeader] = String(profile.attempt);
143
+ }
144
+ return bodyText;
145
+ }
146
+ /**
147
+ * Drives one approved request and captures the bounded observation.
148
+ *
149
+ * Args:
150
+ * input: action, lease, actor profile, origin, credential resolver,
151
+ * and timeout.
152
+ *
153
+ * Returns:
154
+ * DrivenRequest: method/path/query/body/status/response plus
155
+ * identity digests (headers never leave the driver).
156
+ *
157
+ * Throws:
158
+ * BehaviorDriverError: unsupported encoding, unresolvable value,
159
+ * non-loopback origin, timeout, over-limit body, or transport
160
+ * failure — always a blocking diagnostic, never proof.
161
+ */
162
+ export async function driveBehaviorRequest(input) {
163
+ const { action, lease } = input;
164
+ // The declared profile names what the ENGINE does with a secret it
165
+ // holds; an unknown algorithm or parameter fails closed here, exactly
166
+ // as the config schema refuses it at parse time.
167
+ let signature = null;
168
+ if (action.signatureProfile !== undefined) {
169
+ const parsed = parseBehaviorSignatureProfile(action.signatureProfile);
170
+ if (parsed.ok === false)
171
+ throw new BehaviorDriverError(parsed.error);
172
+ signature = parsed.profile;
173
+ }
174
+ if (action.body.encoding === 'multipart') {
175
+ throw new BehaviorDriverError(`'multipart' bodies need the Phase 6 file driver`);
176
+ }
177
+ if (action.body.encoding === 'raw' && action.signatureProfile === undefined) {
178
+ throw new BehaviorDriverError(`'raw' bodies require an engine-side signature profile`);
179
+ }
180
+ await assertLoopback(input.origin, 'behavior principal').catch((error) => {
181
+ throw new BehaviorDriverError(error instanceof Error ? error.message : String(error));
182
+ });
183
+ const base = input.origin.replace(/\/+$/, '');
184
+ // Concrete path: every template variable resolves to a segment-safe value.
185
+ const templateSegments = action.pathTemplate.split('/');
186
+ const concreteSegments = [];
187
+ for (const segment of templateSegments) {
188
+ const match = /^\{([A-Za-z0-9_]+)\}$/.exec(segment);
189
+ if (match === null) {
190
+ concreteSegments.push(segment);
191
+ continue;
192
+ }
193
+ const name = match[1];
194
+ const raw = action.path[name];
195
+ if (raw === undefined)
196
+ throw new BehaviorDriverError(`path parameter '${name}' is not declared`);
197
+ const resolved = resolveValue(raw, lease.subjects, `path parameter '${name}'`);
198
+ if (typeof resolved !== 'string' && typeof resolved !== 'number') {
199
+ throw new BehaviorDriverError(`path parameter '${name}' is not a scalar`);
200
+ }
201
+ const text = String(resolved);
202
+ if (text.length === 0 || text.includes('/')) {
203
+ throw new BehaviorDriverError(`path parameter '${name}' would smuggle path segments`);
204
+ }
205
+ concreteSegments.push(encodeURIComponent(text));
206
+ }
207
+ const path = concreteSegments.join('/').replace(/\/+/g, '/');
208
+ // Declared query, resolved exactly (the driver sends the contract).
209
+ const query = {};
210
+ for (const [name, raw] of Object.entries(action.query)) {
211
+ const resolved = resolveValue(raw, lease.subjects, `query parameter '${name}'`);
212
+ if (typeof resolved !== 'string' && typeof resolved !== 'number' && typeof resolved !== 'boolean') {
213
+ throw new BehaviorDriverError(`query parameter '${name}' is not a scalar`);
214
+ }
215
+ query[name] = resolved;
216
+ }
217
+ const queryText = Object.entries(query)
218
+ .map(([name, value]) => `${encodeURIComponent(name)}=${encodeURIComponent(String(value))}`)
219
+ .join('&');
220
+ // Declared body, resolved exactly. `raw` resolves the fixture-named
221
+ // EXACT bytes from the trusted lease subjects — the signature (when a
222
+ // profile is declared) is computed engine-side over those exact bytes,
223
+ // never over a re-serialization.
224
+ let bodyFields = {};
225
+ let bodyText;
226
+ let contentType;
227
+ if (action.body.encoding === 'raw') {
228
+ const fixtureName = action.body.fixture;
229
+ if (typeof fixtureName !== 'string')
230
+ throw new BehaviorDriverError('raw body has no fixture reference');
231
+ const resolved = resolveValue({ from: 'fixture', key: fixtureName }, lease.subjects, 'raw body fixture');
232
+ if (typeof resolved !== 'string')
233
+ throw new BehaviorDriverError('raw body fixture is not exact bytes (string)');
234
+ bodyText = resolved;
235
+ contentType = 'application/json';
236
+ }
237
+ else {
238
+ for (const [name, raw] of Object.entries(action.body.fields ?? {})) {
239
+ bodyFields[name] = resolveValue(raw, lease.subjects, `body field '${name}'`);
240
+ }
241
+ if (action.body.encoding === 'json') {
242
+ bodyText = JSON.stringify(bodyFields);
243
+ contentType = 'application/json';
244
+ }
245
+ else {
246
+ bodyText = new URLSearchParams(Object.entries(bodyFields).map(([name, value]) => [name, typeof value === 'string' ? value : JSON.stringify(value)])).toString();
247
+ contentType = 'application/x-www-form-urlencoded';
248
+ }
249
+ }
250
+ if (bodyText.length > BEHAVIOR_BODY_LIMIT_BYTES) {
251
+ throw new BehaviorDriverError('request body exceeds the proof bound');
252
+ }
253
+ // Actor material resolves privately, engine-side only.
254
+ const headers = { 'content-type': contentType };
255
+ const actor = lease.actors[input.actorProfile];
256
+ if (actor === undefined) {
257
+ throw new BehaviorDriverError(`actor profile '${input.actorProfile}' has no lease`);
258
+ }
259
+ if (input.action.credentialVariant === 'valid' || input.action.credentialVariant === 'corrupted') {
260
+ const material = await input.resolveCredential(actor.credentialRef);
261
+ if (material === null)
262
+ throw new BehaviorDriverError('actor credential reference does not resolve');
263
+ if (input.action.credentialVariant === 'valid') {
264
+ for (const [name, value] of Object.entries(material.headers)) {
265
+ // The signing secret is consumed by the driver (never sent as a
266
+ // header); the signature is computed over the exact raw bytes.
267
+ if (name === BEHAVIOR_SIGNING_SECRET_HEADER)
268
+ continue;
269
+ headers[name] = value;
270
+ }
271
+ if (signature !== null) {
272
+ const secret = material.headers[BEHAVIOR_SIGNING_SECRET_HEADER];
273
+ if (secret === undefined || secret.length === 0) {
274
+ throw new BehaviorDriverError('signing profile declared but no engine-side secret is bound');
275
+ }
276
+ const declared = lease.subjects['signatureTimestampMs'];
277
+ bodyText = stampSignature(signature, secret, bodyText, headers, typeof declared === 'number' && Number.isFinite(declared) ? declared : null);
278
+ }
279
+ }
280
+ else {
281
+ for (const [name, value] of Object.entries(material.headers)) {
282
+ if (name === BEHAVIOR_SIGNING_SECRET_HEADER)
283
+ continue;
284
+ headers[name] = value.length > 0 ? `${value.slice(0, -1)}X` : 'X';
285
+ }
286
+ }
287
+ }
288
+ const engineRequestId = randomUUID();
289
+ const controller = new AbortController();
290
+ const timer = setTimeout(() => controller.abort(), input.timeoutMs);
291
+ let response;
292
+ try {
293
+ response = await fetch(`${base}${path}${queryText.length > 0 ? `?${queryText}` : ''}`, {
294
+ method: action.method.toUpperCase(),
295
+ headers,
296
+ body: action.method.toUpperCase() === 'GET' || action.method.toUpperCase() === 'HEAD' ? undefined : bodyText,
297
+ signal: controller.signal,
298
+ // Never follow redirects: the observed status is the principal's
299
+ // own response (a form POST legitimately answers 303).
300
+ redirect: 'manual',
301
+ });
302
+ }
303
+ catch (error) {
304
+ throw new BehaviorDriverError(`principal request failed: ${error instanceof Error ? error.message : String(error)}`);
305
+ }
306
+ finally {
307
+ clearTimeout(timer);
308
+ }
309
+ const responseText = await readBoundedBody(response, BEHAVIOR_BODY_LIMIT_BYTES);
310
+ const responseBody = parseBody(responseText);
311
+ const bodyValue = action.body.encoding === 'raw'
312
+ ? bodyText
313
+ : action.body.encoding === 'json'
314
+ ? parseBody(bodyText)
315
+ : Object.fromEntries(new URLSearchParams(bodyText).entries());
316
+ const requestDigest = sha256Canonical({
317
+ method: action.method.toUpperCase(),
318
+ path,
319
+ query,
320
+ body: bodyValue,
321
+ });
322
+ const responseDigest = sha256Canonical({ status: response.status, body: responseBody });
323
+ return {
324
+ engineRequestId,
325
+ method: action.method.toUpperCase(),
326
+ path,
327
+ query,
328
+ body: bodyValue,
329
+ status: response.status,
330
+ responseBody,
331
+ requestDigest,
332
+ responseDigest,
333
+ };
334
+ }
335
+ //# sourceMappingURL=behavior-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior-request.js","sourceRoot":"","sources":["../../src/witness/behavior-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /** What a snapshot was validated against. */
2
+ export interface SnapshotScopeSpec {
3
+ /** Approved snapshot scope key. */
4
+ scope: string;
5
+ /** Fixture namespace the case lease owns. */
6
+ fixtureNamespace: string;
7
+ /** Exact ordered identity columns (tenant included where needed). */
8
+ identityFields: string[];
9
+ /** Nonempty relevant field projection. */
10
+ fields: string[];
11
+ /** Hard entity cap (bounded memory). */
12
+ maxEntities?: number;
13
+ }
14
+ /** Default entity cap when the caller names none. */
15
+ export declare const DEFAULT_MAX_SNAPSHOT_ENTITIES = 10000;
16
+ /** Validated snapshot: entities indexed by canonical identity key. */
17
+ export interface ValidatedSnapshot {
18
+ /** The validated checkpoint. */
19
+ checkpoint: string;
20
+ /** Identity key → entity index (canonical order preserved). */
21
+ index: Map<string, {
22
+ entityId: unknown;
23
+ fields: Record<string, unknown>;
24
+ }>;
25
+ /** Identity keys in snapshot order. */
26
+ order: string[];
27
+ }
28
+ export type SnapshotValidation = {
29
+ ok: true;
30
+ snapshot: ValidatedSnapshot;
31
+ } | {
32
+ ok: false;
33
+ detail: string;
34
+ };
35
+ /**
36
+ * Canonical identity key: scalars stringify directly; composite keys
37
+ * serialize the COMPLETE column-keyed object with sorted column names.
38
+ * Missing identity columns are an unknown identity (null return).
39
+ */
40
+ export declare function identityKeyOf(entityId: unknown, identityFields: string[]): string | null;
41
+ /**
42
+ * Validates one trusted scope snapshot against its declared spec.
43
+ *
44
+ * Args:
45
+ * snapshot: the adapter-produced snapshot (untrusted input).
46
+ * spec: the declared scope, namespace, identity, and projection.
47
+ *
48
+ * Returns:
49
+ * SnapshotValidation: the indexed snapshot, or a blocking detail.
50
+ */
51
+ export declare function validateScopeSnapshot(snapshot: unknown, spec: SnapshotScopeSpec): SnapshotValidation;
52
+ //# sourceMappingURL=behavior.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior.d.ts","sourceRoot":"","sources":["../../src/witness/behavior.ts"],"names":[],"mappings":"AAiBA,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qDAAqD;AACrD,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAEpD,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC3E,uCAAuC;IACvC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,iBAAiB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAS3G;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAexF;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAqEpG"}
@@ -0,0 +1,118 @@
1
+ /** Default entity cap when the caller names none. */
2
+ export const DEFAULT_MAX_SNAPSHOT_ENTITIES = 10_000;
3
+ /** True for plain data objects (never arrays, null, or class instances). */
4
+ function isRecord(value) {
5
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
6
+ return false;
7
+ const proto = Object.getPrototypeOf(value);
8
+ return proto === Object.prototype || proto === null;
9
+ }
10
+ /**
11
+ * Canonical identity key: scalars stringify directly; composite keys
12
+ * serialize the COMPLETE column-keyed object with sorted column names.
13
+ * Missing identity columns are an unknown identity (null return).
14
+ */
15
+ export function identityKeyOf(entityId, identityFields) {
16
+ if (entityId === null || entityId === undefined)
17
+ return null;
18
+ if (typeof entityId === 'string' || typeof entityId === 'number' || typeof entityId === 'boolean') {
19
+ return `${typeof entityId}:${String(entityId)}`;
20
+ }
21
+ if (!isRecord(entityId))
22
+ return null;
23
+ const parts = [];
24
+ for (const column of [...identityFields].sort()) {
25
+ const value = entityId[column];
26
+ if (value === undefined || value === null)
27
+ return null;
28
+ if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean')
29
+ return null;
30
+ parts.push(`${column}=${typeof value}:${String(value)}`);
31
+ }
32
+ if (parts.length === 0)
33
+ return null;
34
+ return `composite:${parts.join('|')}`;
35
+ }
36
+ /**
37
+ * Validates one trusted scope snapshot against its declared spec.
38
+ *
39
+ * Args:
40
+ * snapshot: the adapter-produced snapshot (untrusted input).
41
+ * spec: the declared scope, namespace, identity, and projection.
42
+ *
43
+ * Returns:
44
+ * SnapshotValidation: the indexed snapshot, or a blocking detail.
45
+ */
46
+ export function validateScopeSnapshot(snapshot, spec) {
47
+ const fail = (detail) => ({ ok: false, detail });
48
+ if (!isRecord(snapshot))
49
+ return fail('scope snapshot must be an object');
50
+ if (snapshot['scope'] !== spec.scope) {
51
+ return fail(`scope snapshot scope '${String(snapshot['scope'])}' does not match declared scope '${spec.scope}'`);
52
+ }
53
+ if (snapshot['fixtureNamespace'] !== spec.fixtureNamespace) {
54
+ return fail(`scope snapshot namespace '${String(snapshot['fixtureNamespace'])}' does not match the case lease namespace`);
55
+ }
56
+ if (snapshot['complete'] !== true) {
57
+ return fail(`scope '${spec.scope}' collection is incomplete (complete:false) — no partial credit`);
58
+ }
59
+ const checkpoint = snapshot['checkpoint'];
60
+ if (typeof checkpoint !== 'string' || checkpoint.length === 0) {
61
+ return fail(`scope '${spec.scope}' has no authoritative checkpoint`);
62
+ }
63
+ if (snapshot['exhausted'] !== true) {
64
+ return fail(`scope '${spec.scope}' pagination not exhausted — a one-page snapshot cannot prove the set`);
65
+ }
66
+ const entities = snapshot['entities'];
67
+ if (!Array.isArray(entities))
68
+ return fail(`scope '${spec.scope}' entities must be an array`);
69
+ const max = spec.maxEntities ?? DEFAULT_MAX_SNAPSHOT_ENTITIES;
70
+ if (entities.length > max) {
71
+ return fail(`scope '${spec.scope}' exceeds the entity bound (${String(entities.length)} > ${String(max)})`);
72
+ }
73
+ const totalSize = snapshot['totalSize'];
74
+ if (totalSize !== undefined) {
75
+ if (typeof totalSize !== 'number' || !Number.isInteger(totalSize) || totalSize < 0) {
76
+ return fail(`scope '${spec.scope}' totalSize must be a non-negative integer when present`);
77
+ }
78
+ if (entities.length !== totalSize) {
79
+ return fail(`scope '${spec.scope}' truncated (${String(entities.length)} of ${String(totalSize)}) — never silently sampled`);
80
+ }
81
+ }
82
+ if (spec.fields.length === 0)
83
+ return fail(`scope '${spec.scope}' declares an empty field projection`);
84
+ const index = new Map();
85
+ const order = [];
86
+ let previous = null;
87
+ for (let position = 0; position < entities.length; position += 1) {
88
+ const entity = entities[position];
89
+ if (!isRecord(entity))
90
+ return fail(`scope '${spec.scope}' entity ${String(position)} must be an object`);
91
+ const key = identityKeyOf(entity['entityId'], spec.identityFields);
92
+ if (key === null) {
93
+ return fail(`scope '${spec.scope}' entity ${String(position)} has unknown identity (fail closed)`);
94
+ }
95
+ if (index.has(key)) {
96
+ return fail(`scope '${spec.scope}' has a duplicate identity '${key}' — ambiguous, not proof`);
97
+ }
98
+ if (previous !== null && key <= previous) {
99
+ return fail(`scope '${spec.scope}' is not in canonical identity order ('${key}' after '${previous}')`);
100
+ }
101
+ previous = key;
102
+ const fields = entity['fields'];
103
+ if (!isRecord(fields))
104
+ return fail(`scope '${spec.scope}' entity ${String(position)} fields must be an object`);
105
+ for (const name of spec.fields) {
106
+ if (!(name in fields)) {
107
+ return fail(`scope '${spec.scope}' entity ${String(position)} omits declared field '${name}'`);
108
+ }
109
+ }
110
+ const projected = {};
111
+ for (const [name, value] of Object.entries(fields))
112
+ projected[name] = value;
113
+ index.set(key, { entityId: entity['entityId'], fields: projected });
114
+ order.push(key);
115
+ }
116
+ return { ok: true, snapshot: { checkpoint, index, order } };
117
+ }
118
+ //# sourceMappingURL=behavior.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior.js","sourceRoot":"","sources":["../../src/witness/behavior.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { WitnessHandle } from './types.js';
2
+ /** One-line usage (the header comment above is the long form). */
3
+ export declare const WITNESS_BIN_USAGE: string;
4
+ /**
5
+ * Reads env + argv and starts the witness.
6
+ *
7
+ * Args:
8
+ * argv: CLI flags (see the module header; `--help` prints usage and
9
+ * returns a never-started handle).
10
+ * env: process environment.
11
+ *
12
+ * Returns:
13
+ * WitnessHandle once listening (or a handle with an empty `url` for
14
+ * `--help`; the wrapper skips its URL banner in that case).
15
+ *
16
+ * Throws:
17
+ * WitnessStartupError / AttestationError / AdapterRegistryError:
18
+ * fail-closed startup problems (exit 2 via the wrapper).
19
+ */
20
+ export declare function main(argv: readonly string[], env: NodeJS.ProcessEnv): Promise<WitnessHandle>;
21
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../../src/witness/bin.ts"],"names":[],"mappings":"AAsEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,QAKK,CAAC;AAqGpC;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,IAAI,CACxB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,aAAa,CAAC,CAiExB"}