@gate-forge/witness 0.0.0-stage → 0.9.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 +4963 -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,193 @@
1
+ import type { BehaviorExecuteRequest, BehaviorExecuteResponse, BehaviorPrincipalRequest, BehaviorPrincipalResponse, BrowserActionRequest, BrowserActionResponse, BrowserSurfaceRequest, BrowserVisibleRequest, BrowserVisibleResponse, IntervalCloseResponse, IntervalOpenResponse, PersistenceRequest, PersistenceResponse, PreObservationRequest, PreObservationResponse, RecordsRequest, RecordsResponse, SessionIdentityRequest, SessionIdentityResponse, SessionResolveRequest, SessionResolveResponse } from '../witness/types.js';
2
+ /** A witness call that failed (status + single-cause diagnostic). */
3
+ export declare class WitnessRequestError extends Error {
4
+ readonly status: number;
5
+ readonly detail: string | null;
6
+ constructor(status: number, message: string, detail?: string | null);
7
+ }
8
+ /**
9
+ * Resolves the witness base URL: env first, then the spawned-witness
10
+ * file in the run-state dir (written by the reporter when it auto-spawns
11
+ * a witness without `--witness-url`).
12
+ *
13
+ * Returns:
14
+ * string: the witness base URL.
15
+ *
16
+ * Throws:
17
+ * Error: with the exact setup step required when no witness is wired.
18
+ */
19
+ export declare function resolveWitnessUrl(): string;
20
+ /**
21
+ * The fixture's witness transport.
22
+ *
23
+ * Args:
24
+ * url: witness base URL (default: resolved from env/state file).
25
+ * token: run token (default: GATEFORGE_RUN_TOKEN).
26
+ * timeoutMs: per-call timeout.
27
+ */
28
+ export declare class WitnessClient {
29
+ readonly url: string;
30
+ readonly token: string;
31
+ readonly timeoutMs: number;
32
+ constructor(url?: string, token?: string | undefined, timeoutMs?: number);
33
+ /** POST /records (pin #7; Phase 1: requires the supervisor-issued session credential). */
34
+ postRecords(request: RecordsRequest): Promise<RecordsResponse>;
35
+ /**
36
+ * POST /sessions/resolve (Phase 1, worker side): asks for the OPEN
37
+ * session bound to the exact (workerIndex, testId) pair.
38
+ *
39
+ * Deliberately the ONLY session-lifecycle call on the suite-side
40
+ * client (enforcement-review fix 3): open and close live on the
41
+ * supervisor channel (`SupervisorClient`, verifier-key authenticated)
42
+ * and are dispatched by the trusted CLI's spool drain — the tested
43
+ * suite has NO reachable path to mint, seal, or re-seal a session,
44
+ * and with it no path to forge the execution record supervision
45
+ * grades. Resolve only ever answers for a session the supervisor
46
+ * already opened; it cannot create or extend one.
47
+ *
48
+ * Returns:
49
+ * SessionResolveResponse when an open session answers; null when the
50
+ * witness answers 404 (not yet opened, or sealed).
51
+ */
52
+ resolveSession(request: SessionResolveRequest): Promise<SessionResolveResponse | null>;
53
+ /**
54
+ * POST /sessions/identity (plan Phase 4b item 3b): registers the login
55
+ * of the tenant this test just created, for THIS session only.
56
+ *
57
+ * It changes who the engine reads as — nothing else: the engine still
58
+ * performs every read, a wrong tenant makes the row unfound (fail
59
+ * closed), and the credential never reaches a record, the run state, a
60
+ * log or a report. The call carries the session credential, so it can
61
+ * only ever register for the session the caller is running under.
62
+ */
63
+ registerSessionIdentity(request: SessionIdentityRequest): Promise<SessionIdentityResponse>;
64
+ /**
65
+ * POST /sessions/intervals/open (Phase 1): marks the start of a
66
+ * UI-action observation interval on the witness's monotonic clock.
67
+ * Proxy exchanges completing inside the interval are the session's
68
+ * browser evidence; everything outside (setup traffic) is never
69
+ * credited.
70
+ */
71
+ beginActionInterval(request: {
72
+ sessionId: string;
73
+ sessionToken: string;
74
+ operation: string;
75
+ }): Promise<IntervalOpenResponse>;
76
+ /**
77
+ * POST /sessions/intervals/close (Phase 1): seals the interval. A
78
+ * closed interval can never be stretched later (409 on re-close).
79
+ */
80
+ endActionInterval(request: {
81
+ sessionId: string;
82
+ sessionToken: string;
83
+ intervalId: string;
84
+ }): Promise<IntervalCloseResponse>;
85
+ /**
86
+ * POST /witness/pre-observation (audit round 4): engine-side id-set
87
+ * snapshot BEFORE a claimed create; pass the returned
88
+ * `observationId` to `verifyPersistence` so the issued record carries
89
+ * `before: {entityAbsent}`. Phase 1: requires the supervisor-issued
90
+ * session credential — the snapshot belongs to the open test session.
91
+ */
92
+ preObserve(request: PreObservationRequest): Promise<PreObservationResponse>;
93
+ /**
94
+ * POST /witness/http-observation (ADR 0004 D7, plan §8 / D1):
95
+ * consumes one witness-observed HTTP exchange matching (method, path)
96
+ * and issues witnessed `http.request` records for the declaring
97
+ * test's claimed obligations. Phase 1: the caller must hold a valid
98
+ * OPEN session and only an exchange observed through THAT session's
99
+ * proxy prefix within one of its recorded action intervals can be
100
+ * consumed — the claim set may be given as `claimIds`, or as the
101
+ * singular legacy `claimId`/`obligationId` pair (folded in by the
102
+ * server; a split assignment with distinct values is refused with 400).
103
+ */
104
+ observeHttp(request: {
105
+ claimIds?: string[];
106
+ claimId?: string;
107
+ obligationId?: string;
108
+ testId: string;
109
+ method: string;
110
+ path: string;
111
+ expectedStatus?: number;
112
+ sessionId: string;
113
+ sessionToken: string;
114
+ }): Promise<{
115
+ recordId: string;
116
+ runId: string;
117
+ trust: string;
118
+ status: number;
119
+ records: Array<{
120
+ recordId: string;
121
+ obligationId: string;
122
+ }>;
123
+ }>;
124
+ /**
125
+ * POST /witness/persistence and record adapter wall time.
126
+ *
127
+ * Args:
128
+ * request: persistence observation bound to a supervised test session.
129
+ *
130
+ * Returns:
131
+ * Promise<PersistenceResponse>: the engine-side adapter result.
132
+ */
133
+ verifyPersistence(request: PersistenceRequest & {
134
+ testId: string;
135
+ claimId: string;
136
+ sessionId: string;
137
+ sessionToken: string;
138
+ }): Promise<PersistenceResponse>;
139
+ /**
140
+ * POST /browser/surface (plan Phase 1 item 4): registers the
141
+ * consumer-declared surface descriptor + the app base the ENGINE must
142
+ * drive for this session. Validated engine-side (structure, loopback,
143
+ * fingerprint); selectors are locators only.
144
+ */
145
+ registerBrowserSurface(request: BrowserSurfaceRequest): Promise<{
146
+ registered: true;
147
+ }>;
148
+ /**
149
+ * POST /browser/action (plan Phase 1 item 4): the ENGINE performs one
150
+ * constrained surface operation on its own page and returns its own
151
+ * observation (observed entity id, entered + rendered fields, app
152
+ * status, pre-observation id, issued record ids). Test code supplies
153
+ * intent only — it never touches the engine page.
154
+ */
155
+ browserAction(request: BrowserActionRequest): Promise<BrowserActionResponse>;
156
+ /**
157
+ * POST /browser/visible (plan Phase 1 item 4): the ENGINE re-reads
158
+ * the rendered result for the engine-observed entity and returns the
159
+ * rendered fields.
160
+ */
161
+ browserVisible(request: BrowserVisibleRequest): Promise<BrowserVisibleResponse>;
162
+ /**
163
+ * POST /behavior/execute (plan 2026-09-19 Phase 6): asks the ENGINE to
164
+ * execute one approved behavior case. The call carries ONLY the
165
+ * allowed case id plus the session credential — actor material,
166
+ * expectations, and subjects resolve engine-side and are never
167
+ * readable or overridable here.
168
+ */
169
+ proveCase(request: BehaviorExecuteRequest): Promise<BehaviorExecuteResponse>;
170
+ /**
171
+ * POST /behavior/principal (plan 2026-09-19 Phase 6): asks the ENGINE
172
+ * to drive the prepared execution's principal operation and seal the
173
+ * case record. Same credential-only boundary as `proveCase`.
174
+ */
175
+ drivePrincipal(request: BehaviorPrincipalRequest): Promise<BehaviorPrincipalResponse>;
176
+ /** GET /records — the issued ledger for this run. */
177
+ listRecords(): Promise<{
178
+ records: IssuedLedgerRecord[];
179
+ }>;
180
+ private request;
181
+ }
182
+ /** One witness-issued ledger record as seen by the ledger endpoint. */
183
+ export interface IssuedLedgerRecord {
184
+ recordId: string;
185
+ runId: string;
186
+ trust: 'witnessed' | 'claimed';
187
+ obligationId: string;
188
+ kind: string;
189
+ testId: string;
190
+ payload: unknown;
191
+ issuedAt?: string;
192
+ }
193
+ //# sourceMappingURL=witness-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"witness-client.d.ts","sourceRoot":"","sources":["../../src/client/witness-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,321 @@
1
+ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { ENV_RUN_ID, ENV_RUN_TOKEN, ENV_STATE_DIR, ENV_WITNESS_URL, RUN_HEADER, WITNESS_URL_FILE, } from '../constants.js';
4
+ /** A witness call that failed (status + single-cause diagnostic). */
5
+ export class WitnessRequestError extends Error {
6
+ status;
7
+ detail;
8
+ constructor(status, message, detail = null) {
9
+ super(detail === null ? message : `${message}: ${detail}`);
10
+ this.name = 'WitnessRequestError';
11
+ this.status = status;
12
+ this.detail = detail;
13
+ }
14
+ }
15
+ /**
16
+ * Appends persistence adapter wall time to the run diagnostics.
17
+ *
18
+ * Args:
19
+ * durationMs: elapsed wall time for the witness persistence request.
20
+ * testId: runner-issued test identity associated with the call.
21
+ * stateDir: Gateforge run-state directory, if a supervised run is active.
22
+ *
23
+ * Returns:
24
+ * void: writes one JSONL row when run diagnostics are available.
25
+ */
26
+ function recordPersistenceTiming(durationMs, testId, stateDir) {
27
+ if (stateDir === undefined || stateDir.length === 0)
28
+ return;
29
+ const diagnosticsDir = join(stateDir, 'diagnostics');
30
+ mkdirSync(diagnosticsDir, { recursive: true });
31
+ appendFileSync(join(diagnosticsDir, 'adapter-timing.jsonl'), `${JSON.stringify({
32
+ timestamp: new Date().toISOString(),
33
+ operation: 'verifyPersistence',
34
+ runId: process.env[ENV_RUN_ID] ?? null,
35
+ testId,
36
+ durationMs,
37
+ })}\n`, 'utf8');
38
+ if (durationMs > 2_000) {
39
+ process.stderr.write(`Gateforge witness adapter verifyPersistence took ${durationMs}ms for ${testId}\n`);
40
+ }
41
+ }
42
+ /**
43
+ * Resolves the witness base URL: env first, then the spawned-witness
44
+ * file in the run-state dir (written by the reporter when it auto-spawns
45
+ * a witness without `--witness-url`).
46
+ *
47
+ * Returns:
48
+ * string: the witness base URL.
49
+ *
50
+ * Throws:
51
+ * Error: with the exact setup step required when no witness is wired.
52
+ */
53
+ export function resolveWitnessUrl() {
54
+ const fromEnv = process.env[ENV_WITNESS_URL];
55
+ if (fromEnv !== undefined && fromEnv !== '')
56
+ return fromEnv;
57
+ const stateDir = process.env[ENV_STATE_DIR];
58
+ if (stateDir !== undefined && stateDir !== '') {
59
+ try {
60
+ const record = JSON.parse(readFileSync(join(stateDir, WITNESS_URL_FILE), 'utf8'));
61
+ if (typeof record.url === 'string' && record.url !== '')
62
+ return record.url;
63
+ }
64
+ catch {
65
+ // fall through to the actionable error
66
+ }
67
+ }
68
+ throw new Error(`no witness service is wired: set ${ENV_WITNESS_URL} (or run under 'gateforge test-gates', ` +
69
+ 'which exports it) so evidence primitives can submit records');
70
+ }
71
+ /**
72
+ * The fixture's witness transport.
73
+ *
74
+ * Args:
75
+ * url: witness base URL (default: resolved from env/state file).
76
+ * token: run token (default: GATEFORGE_RUN_TOKEN).
77
+ * timeoutMs: per-call timeout.
78
+ */
79
+ export class WitnessClient {
80
+ url;
81
+ token;
82
+ timeoutMs;
83
+ constructor(url = resolveWitnessUrl(), token = process.env[ENV_RUN_TOKEN], timeoutMs = 5000) {
84
+ this.url = url;
85
+ if (token === undefined || token === '') {
86
+ throw new Error(`${ENV_RUN_TOKEN} is required to talk to the witness service`);
87
+ }
88
+ this.token = token;
89
+ this.timeoutMs = timeoutMs;
90
+ }
91
+ /** POST /records (pin #7; Phase 1: requires the supervisor-issued session credential). */
92
+ async postRecords(request) {
93
+ const body = await this.request('/records', request);
94
+ return body;
95
+ }
96
+ /**
97
+ * POST /sessions/resolve (Phase 1, worker side): asks for the OPEN
98
+ * session bound to the exact (workerIndex, testId) pair.
99
+ *
100
+ * Deliberately the ONLY session-lifecycle call on the suite-side
101
+ * client (enforcement-review fix 3): open and close live on the
102
+ * supervisor channel (`SupervisorClient`, verifier-key authenticated)
103
+ * and are dispatched by the trusted CLI's spool drain — the tested
104
+ * suite has NO reachable path to mint, seal, or re-seal a session,
105
+ * and with it no path to forge the execution record supervision
106
+ * grades. Resolve only ever answers for a session the supervisor
107
+ * already opened; it cannot create or extend one.
108
+ *
109
+ * Returns:
110
+ * SessionResolveResponse when an open session answers; null when the
111
+ * witness answers 404 (not yet opened, or sealed).
112
+ */
113
+ async resolveSession(request) {
114
+ try {
115
+ return await this.request('/sessions/resolve', request);
116
+ }
117
+ catch (error) {
118
+ if (error instanceof WitnessRequestError && error.status === 404)
119
+ return null;
120
+ throw error;
121
+ }
122
+ }
123
+ /**
124
+ * POST /sessions/identity (plan Phase 4b item 3b): registers the login
125
+ * of the tenant this test just created, for THIS session only.
126
+ *
127
+ * It changes who the engine reads as — nothing else: the engine still
128
+ * performs every read, a wrong tenant makes the row unfound (fail
129
+ * closed), and the credential never reaches a record, the run state, a
130
+ * log or a report. The call carries the session credential, so it can
131
+ * only ever register for the session the caller is running under.
132
+ */
133
+ async registerSessionIdentity(request) {
134
+ return this.request('/sessions/identity', request);
135
+ }
136
+ /**
137
+ * POST /sessions/intervals/open (Phase 1): marks the start of a
138
+ * UI-action observation interval on the witness's monotonic clock.
139
+ * Proxy exchanges completing inside the interval are the session's
140
+ * browser evidence; everything outside (setup traffic) is never
141
+ * credited.
142
+ */
143
+ async beginActionInterval(request) {
144
+ return this.request('/sessions/intervals/open', request);
145
+ }
146
+ /**
147
+ * POST /sessions/intervals/close (Phase 1): seals the interval. A
148
+ * closed interval can never be stretched later (409 on re-close).
149
+ */
150
+ async endActionInterval(request) {
151
+ return this.request('/sessions/intervals/close', request);
152
+ }
153
+ /**
154
+ * POST /witness/pre-observation (audit round 4): engine-side id-set
155
+ * snapshot BEFORE a claimed create; pass the returned
156
+ * `observationId` to `verifyPersistence` so the issued record carries
157
+ * `before: {entityAbsent}`. Phase 1: requires the supervisor-issued
158
+ * session credential — the snapshot belongs to the open test session.
159
+ */
160
+ async preObserve(request) {
161
+ return this.request('/witness/pre-observation', request);
162
+ }
163
+ /**
164
+ * POST /witness/http-observation (ADR 0004 D7, plan §8 / D1):
165
+ * consumes one witness-observed HTTP exchange matching (method, path)
166
+ * and issues witnessed `http.request` records for the declaring
167
+ * test's claimed obligations. Phase 1: the caller must hold a valid
168
+ * OPEN session and only an exchange observed through THAT session's
169
+ * proxy prefix within one of its recorded action intervals can be
170
+ * consumed — the claim set may be given as `claimIds`, or as the
171
+ * singular legacy `claimId`/`obligationId` pair (folded in by the
172
+ * server; a split assignment with distinct values is refused with 400).
173
+ */
174
+ async observeHttp(request) {
175
+ const body = await this.request('/witness/http-observation', request);
176
+ const records = Array.isArray(body['records'])
177
+ ? body['records']
178
+ : // Legacy single-record response shape.
179
+ [{ recordId: String(body['recordId'] ?? ''), obligationId: String(request.claimId ?? request.obligationId ?? '') }];
180
+ return {
181
+ recordId: String(body['recordId'] ?? records[0]?.recordId ?? ''),
182
+ runId: String(body['runId'] ?? ''),
183
+ trust: String(body['trust'] ?? ''),
184
+ status: typeof body['status'] === 'number' ? body['status'] : 0,
185
+ records,
186
+ };
187
+ }
188
+ /**
189
+ * POST /witness/persistence and record adapter wall time.
190
+ *
191
+ * Args:
192
+ * request: persistence observation bound to a supervised test session.
193
+ *
194
+ * Returns:
195
+ * Promise<PersistenceResponse>: the engine-side adapter result.
196
+ */
197
+ async verifyPersistence(request) {
198
+ const startedAt = performance.now();
199
+ try {
200
+ return await this.request('/witness/persistence', request);
201
+ }
202
+ finally {
203
+ recordPersistenceTiming(Math.round(performance.now() - startedAt), request.testId, process.env[ENV_STATE_DIR]);
204
+ }
205
+ }
206
+ /**
207
+ * POST /browser/surface (plan Phase 1 item 4): registers the
208
+ * consumer-declared surface descriptor + the app base the ENGINE must
209
+ * drive for this session. Validated engine-side (structure, loopback,
210
+ * fingerprint); selectors are locators only.
211
+ */
212
+ async registerBrowserSurface(request) {
213
+ return this.request('/browser/surface', request);
214
+ }
215
+ /**
216
+ * POST /browser/action (plan Phase 1 item 4): the ENGINE performs one
217
+ * constrained surface operation on its own page and returns its own
218
+ * observation (observed entity id, entered + rendered fields, app
219
+ * status, pre-observation id, issued record ids). Test code supplies
220
+ * intent only — it never touches the engine page.
221
+ */
222
+ async browserAction(request) {
223
+ return this.request('/browser/action', request);
224
+ }
225
+ /**
226
+ * POST /browser/visible (plan Phase 1 item 4): the ENGINE re-reads
227
+ * the rendered result for the engine-observed entity and returns the
228
+ * rendered fields.
229
+ */
230
+ async browserVisible(request) {
231
+ return this.request('/browser/visible', request);
232
+ }
233
+ /**
234
+ * POST /behavior/execute (plan 2026-09-19 Phase 6): asks the ENGINE to
235
+ * execute one approved behavior case. The call carries ONLY the
236
+ * allowed case id plus the session credential — actor material,
237
+ * expectations, and subjects resolve engine-side and are never
238
+ * readable or overridable here.
239
+ */
240
+ async proveCase(request) {
241
+ return this.request('/behavior/execute', request);
242
+ }
243
+ /**
244
+ * POST /behavior/principal (plan 2026-09-19 Phase 6): asks the ENGINE
245
+ * to drive the prepared execution's principal operation and seal the
246
+ * case record. Same credential-only boundary as `proveCase`.
247
+ */
248
+ async drivePrincipal(request) {
249
+ return this.request('/behavior/principal', request);
250
+ }
251
+ /** GET /records — the issued ledger for this run. */
252
+ async listRecords() {
253
+ const controller = new AbortController();
254
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
255
+ let response;
256
+ try {
257
+ response = await fetch(`${this.url}/records`, {
258
+ method: 'GET',
259
+ headers: { [RUN_HEADER]: this.token, accept: 'application/json' },
260
+ signal: controller.signal,
261
+ });
262
+ }
263
+ catch (error) {
264
+ throw new WitnessRequestError(0, `witness call to /records failed: ${error.message}`);
265
+ }
266
+ finally {
267
+ clearTimeout(timer);
268
+ }
269
+ let body;
270
+ try {
271
+ body = await response.json();
272
+ }
273
+ catch {
274
+ body = null;
275
+ }
276
+ if (!response.ok) {
277
+ const record = isObject(body) ? body : {};
278
+ throw new WitnessRequestError(response.status, typeof record['error'] === 'string' ? record['error'] : `witness answered HTTP ${response.status}`, typeof record['detail'] === 'string' ? record['detail'] : null);
279
+ }
280
+ const records = isObject(body) && Array.isArray(body['records']) ? body['records'] : [];
281
+ return { records: records };
282
+ }
283
+ async request(path, payload) {
284
+ const controller = new AbortController();
285
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
286
+ let response;
287
+ try {
288
+ response = await fetch(`${this.url}${path}`, {
289
+ method: 'POST',
290
+ headers: {
291
+ [RUN_HEADER]: this.token,
292
+ 'content-type': 'application/json',
293
+ accept: 'application/json',
294
+ },
295
+ body: JSON.stringify(payload),
296
+ signal: controller.signal,
297
+ });
298
+ }
299
+ catch (error) {
300
+ clearTimeout(timer);
301
+ throw new WitnessRequestError(0, `witness call to ${path} failed: ${error.message}`);
302
+ }
303
+ clearTimeout(timer);
304
+ let body;
305
+ try {
306
+ body = await response.json();
307
+ }
308
+ catch {
309
+ body = null;
310
+ }
311
+ if (!response.ok) {
312
+ const record = isObject(body) ? body : {};
313
+ throw new WitnessRequestError(response.status, typeof record['error'] === 'string' ? record['error'] : `witness answered HTTP ${response.status}`, typeof record['detail'] === 'string' ? record['detail'] : null);
314
+ }
315
+ return body;
316
+ }
317
+ }
318
+ function isObject(value) {
319
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
320
+ }
321
+ //# sourceMappingURL=witness-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"witness-client.js","sourceRoot":"","sources":["../../src/client/witness-client.ts"],"names":[],"mappings":"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"}