@gate-forge/pack-playwright 0.1.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 (140) hide show
  1. package/LICENSE +202 -0
  2. package/bin/gateforge-witness.js +40 -0
  3. package/dist/attestation/proxy.d.ts +40 -0
  4. package/dist/attestation/proxy.d.ts.map +1 -0
  5. package/dist/attestation/proxy.js +78 -0
  6. package/dist/attestation/proxy.js.map +1 -0
  7. package/dist/constants.d.ts +130 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +138 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/discovery/adapters.d.ts +167 -0
  12. package/dist/discovery/adapters.d.ts.map +1 -0
  13. package/dist/discovery/adapters.js +276 -0
  14. package/dist/discovery/adapters.js.map +1 -0
  15. package/dist/discovery/discover.d.ts +57 -0
  16. package/dist/discovery/discover.d.ts.map +1 -0
  17. package/dist/discovery/discover.js +544 -0
  18. package/dist/discovery/discover.js.map +1 -0
  19. package/dist/discovery/index.d.ts +15 -0
  20. package/dist/discovery/index.d.ts.map +1 -0
  21. package/dist/discovery/index.js +15 -0
  22. package/dist/discovery/index.js.map +1 -0
  23. package/dist/discovery/inference.d.ts +63 -0
  24. package/dist/discovery/inference.d.ts.map +1 -0
  25. package/dist/discovery/inference.js +173 -0
  26. package/dist/discovery/inference.js.map +1 -0
  27. package/dist/discovery/pytest-adapter.d.ts +205 -0
  28. package/dist/discovery/pytest-adapter.d.ts.map +1 -0
  29. package/dist/discovery/pytest-adapter.js +548 -0
  30. package/dist/discovery/pytest-adapter.js.map +1 -0
  31. package/dist/discovery/reconcile.d.ts +106 -0
  32. package/dist/discovery/reconcile.d.ts.map +1 -0
  33. package/dist/discovery/reconcile.js +268 -0
  34. package/dist/discovery/reconcile.js.map +1 -0
  35. package/dist/discovery/runner-env.d.ts +80 -0
  36. package/dist/discovery/runner-env.d.ts.map +1 -0
  37. package/dist/discovery/runner-env.js +139 -0
  38. package/dist/discovery/runner-env.js.map +1 -0
  39. package/dist/discovery/static-discovery.d.ts +121 -0
  40. package/dist/discovery/static-discovery.d.ts.map +1 -0
  41. package/dist/discovery/static-discovery.js +1028 -0
  42. package/dist/discovery/static-discovery.js.map +1 -0
  43. package/dist/discovery/supervised-run.d.ts +110 -0
  44. package/dist/discovery/supervised-run.d.ts.map +1 -0
  45. package/dist/discovery/supervised-run.js +328 -0
  46. package/dist/discovery/supervised-run.js.map +1 -0
  47. package/dist/discovery/trusted-config.d.ts +103 -0
  48. package/dist/discovery/trusted-config.d.ts.map +1 -0
  49. package/dist/discovery/trusted-config.js +117 -0
  50. package/dist/discovery/trusted-config.js.map +1 -0
  51. package/dist/fixture/evidence.d.ts +191 -0
  52. package/dist/fixture/evidence.d.ts.map +1 -0
  53. package/dist/fixture/evidence.js +366 -0
  54. package/dist/fixture/evidence.js.map +1 -0
  55. package/dist/fixture/fixture.d.ts +37 -0
  56. package/dist/fixture/fixture.d.ts.map +1 -0
  57. package/dist/fixture/fixture.js +38 -0
  58. package/dist/fixture/fixture.js.map +1 -0
  59. package/dist/fixture/witness-client.d.ts +164 -0
  60. package/dist/fixture/witness-client.d.ts.map +1 -0
  61. package/dist/fixture/witness-client.js +253 -0
  62. package/dist/fixture/witness-client.js.map +1 -0
  63. package/dist/index.d.ts +64 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +55 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/json.d.ts +16 -0
  68. package/dist/json.d.ts.map +1 -0
  69. package/dist/json.js +21 -0
  70. package/dist/json.js.map +1 -0
  71. package/dist/reporter/ledger.d.ts +105 -0
  72. package/dist/reporter/ledger.d.ts.map +1 -0
  73. package/dist/reporter/ledger.js +197 -0
  74. package/dist/reporter/ledger.js.map +1 -0
  75. package/dist/reporter/reporter.cjs +105 -0
  76. package/dist/reporter/reporter.cjs.map +1 -0
  77. package/dist/reporter/reporter.d.cts +35 -0
  78. package/dist/reporter/reporter.d.cts.map +1 -0
  79. package/dist/reporter/reporter.d.ts +167 -0
  80. package/dist/reporter/reporter.d.ts.map +1 -0
  81. package/dist/reporter/reporter.js +673 -0
  82. package/dist/reporter/reporter.js.map +1 -0
  83. package/dist/setup.d.ts +49 -0
  84. package/dist/setup.d.ts.map +1 -0
  85. package/dist/setup.js +167 -0
  86. package/dist/setup.js.map +1 -0
  87. package/dist/supervisor/client.d.ts +73 -0
  88. package/dist/supervisor/client.d.ts.map +1 -0
  89. package/dist/supervisor/client.js +164 -0
  90. package/dist/supervisor/client.js.map +1 -0
  91. package/dist/supervisor/drain.d.ts +45 -0
  92. package/dist/supervisor/drain.d.ts.map +1 -0
  93. package/dist/supervisor/drain.js +235 -0
  94. package/dist/supervisor/drain.js.map +1 -0
  95. package/dist/supervisor/index.d.ts +16 -0
  96. package/dist/supervisor/index.d.ts.map +1 -0
  97. package/dist/supervisor/index.js +13 -0
  98. package/dist/supervisor/index.js.map +1 -0
  99. package/dist/supervisor/spool.d.ts +137 -0
  100. package/dist/supervisor/spool.d.ts.map +1 -0
  101. package/dist/supervisor/spool.js +263 -0
  102. package/dist/supervisor/spool.js.map +1 -0
  103. package/dist/surface.d.ts +134 -0
  104. package/dist/surface.d.ts.map +1 -0
  105. package/dist/surface.js +139 -0
  106. package/dist/surface.js.map +1 -0
  107. package/dist/witness/adapter-registry.d.ts +38 -0
  108. package/dist/witness/adapter-registry.d.ts.map +1 -0
  109. package/dist/witness/adapter-registry.js +158 -0
  110. package/dist/witness/adapter-registry.js.map +1 -0
  111. package/dist/witness/bin.d.ts +21 -0
  112. package/dist/witness/bin.d.ts.map +1 -0
  113. package/dist/witness/bin.js +172 -0
  114. package/dist/witness/bin.js.map +1 -0
  115. package/dist/witness/browser.d.ts +173 -0
  116. package/dist/witness/browser.d.ts.map +1 -0
  117. package/dist/witness/browser.js +580 -0
  118. package/dist/witness/browser.js.map +1 -0
  119. package/dist/witness/classifications.d.ts +42 -0
  120. package/dist/witness/classifications.d.ts.map +1 -0
  121. package/dist/witness/classifications.js +87 -0
  122. package/dist/witness/classifications.js.map +1 -0
  123. package/dist/witness/env-attestation.d.ts +98 -0
  124. package/dist/witness/env-attestation.d.ts.map +1 -0
  125. package/dist/witness/env-attestation.js +202 -0
  126. package/dist/witness/env-attestation.js.map +1 -0
  127. package/dist/witness/loopback-pins.d.ts +79 -0
  128. package/dist/witness/loopback-pins.d.ts.map +1 -0
  129. package/dist/witness/loopback-pins.js +244 -0
  130. package/dist/witness/loopback-pins.js.map +1 -0
  131. package/dist/witness/server.d.ts +34 -0
  132. package/dist/witness/server.d.ts.map +1 -0
  133. package/dist/witness/server.js +2539 -0
  134. package/dist/witness/server.js.map +1 -0
  135. package/dist/witness/types.d.ts +643 -0
  136. package/dist/witness/types.d.ts.map +1 -0
  137. package/dist/witness/types.js +2 -0
  138. package/dist/witness/types.js.map +1 -0
  139. package/package.json +64 -0
  140. package/python/gateforge_persistence_intents.py +100 -0
@@ -0,0 +1,366 @@
1
+ import { CLAIM_ANNOTATION_TYPE } from '../constants.js';
2
+ import { SURFACE_DESCRIPTOR_VERSION, declaredSurfaceFields, validateSurface, } from '../surface.js';
3
+ import { WitnessClient } from './witness-client.js';
4
+ export { SURFACE_DESCRIPTOR_VERSION };
5
+ /** Receipt branding: per-instance symbol, own-property checked (GF-22). */
6
+ function makeReceiptBrand() {
7
+ const token = Symbol('gateforge.receipt');
8
+ return {
9
+ stamp(receipt) {
10
+ return Object.freeze({ ...receipt, kind: 'ui', [token]: true });
11
+ },
12
+ isGenuine(receipt) {
13
+ return (receipt !== null &&
14
+ typeof receipt === 'object' &&
15
+ Object.prototype.hasOwnProperty.call(receipt, token) &&
16
+ receipt[token] === true);
17
+ },
18
+ };
19
+ }
20
+ /** Claims from the test annotations (`{type: 'gateforge', description}`). */
21
+ export function claimsFromAnnotations(annotations) {
22
+ return annotations
23
+ .filter((annotation) => annotation.type === CLAIM_ANNOTATION_TYPE)
24
+ .map((annotation) => annotation.description ?? '')
25
+ .filter((description) => description.length > 0);
26
+ }
27
+ /** Splits `<resourceId>:<contract>` at the first colon. */
28
+ export function resourceIdOfClaim(claim) {
29
+ const colon = claim.indexOf(':');
30
+ return colon === -1 ? claim : claim.slice(0, colon);
31
+ }
32
+ /** Bounded wait while the supervisor's session open lands (see below). */
33
+ const DEFAULT_SESSION_RESOLVE_TIMEOUT_MS = 5000;
34
+ /** Poll cadence for the session resolve (supervisor→witness RPC latency). */
35
+ const SESSION_RESOLVE_POLL_MS = 50;
36
+ /**
37
+ * Resolves the supervisor-issued session credential for this test: the
38
+ * fixture proves it runs on (workerIndex, testId) and the witness
39
+ * answers only while THAT session is open. `onTestBegin` (supervisor)
40
+ * and the test body (worker) race, so a bounded poll absorbs the
41
+ * dispatch latency; a missing session at the deadline fails closed —
42
+ * there is no fixture path that mints a credential itself.
43
+ */
44
+ async function resolveSessionCredential(witness, testInfo, timeoutMs) {
45
+ const deadline = Date.now() + timeoutMs;
46
+ for (;;) {
47
+ const resolved = await witness.resolveSession({
48
+ testId: testInfo.testId,
49
+ workerIndex: testInfo.workerIndex,
50
+ });
51
+ if (resolved !== null) {
52
+ if (resolved.testId !== testInfo.testId) {
53
+ throw new Error(`session resolve returned testId '${resolved.testId}' for test '${testInfo.title}' ` +
54
+ `(expected '${testInfo.testId}') — refusing a mismatched session binding`);
55
+ }
56
+ return resolved;
57
+ }
58
+ if (Date.now() > deadline) {
59
+ throw new Error(`no open witness session for test '${testInfo.title}' (workerIndex ` +
60
+ `${String(testInfo.workerIndex)}, testId '${testInfo.testId}'): the trusted supervisor ` +
61
+ '(the gateforge Playwright reporter) opens one session per started test and evidence ' +
62
+ 'primitives submit only under it — records without a valid open session are rejected ' +
63
+ 'by the witness (fail closed)');
64
+ }
65
+ await new Promise((resolveSleep) => setTimeout(resolveSleep, SESSION_RESOLVE_POLL_MS));
66
+ }
67
+ }
68
+ /**
69
+ * Creates the evidence API for one test.
70
+ *
71
+ * Args:
72
+ * page: IGNORED for evidence (kept for call-shape compatibility) —
73
+ * the engine drives its own page; the worker page is never an
74
+ * evidence channel.
75
+ * testInfo: the running test's info (annotations, testId, workerIndex).
76
+ * surface: REQUIRED consumer-declared {@link SurfaceDescriptor} — the
77
+ * pack carries no application-specific selectors (plan Phase 1
78
+ * item 7). Registered with the witness; the ENGINE drives it
79
+ * against the provisioned attested subject (fake-frontend fix:
80
+ * the driven origin comes from trusted witness configuration,
81
+ * never from suite input — there is no app-base parameter here
82
+ * by design).
83
+ * client: witness transport override (tests inject their own).
84
+ * session: pre-resolved session credential (harnesses that opened the
85
+ * session themselves); default resolves it from the supervisor
86
+ * channel. A credential whose testId differs from this test's is
87
+ * refused.
88
+ * sessionResolveTimeoutMs: bounded wait for the supervisor's session
89
+ * open (harness tuning; default 5s).
90
+ *
91
+ * Returns:
92
+ * Promise<EvidenceApi>: the frozen primitive surface.
93
+ *
94
+ * Throws:
95
+ * Error: on a missing/outdated surface descriptor (migration error
96
+ * naming the new required `surface` parameter), when the test
97
+ * declares no gateforge claim and its session carries no
98
+ * supervisor-registered (mapped) claims, when no app base or witness
99
+ * or OPEN session is wired, or when an action/verification fails
100
+ * fail-closed.
101
+ */
102
+ export async function createEvidence({ page, testInfo, surface, client, session, sessionResolveTimeoutMs = DEFAULT_SESSION_RESOLVE_TIMEOUT_MS, }) {
103
+ void page; // the engine drives its own page; the worker page is never evidence
104
+ // Versioned compatibility (plan Phase 1 item 7): the old no-surface
105
+ // shape carried Accounts selectors INSIDE the pack — that behavior was
106
+ // moved to the consumer. Never silently keep it.
107
+ if (surface === undefined || surface === null) {
108
+ throw new Error("createEvidence now requires a consumer-declared 'surface' descriptor " +
109
+ `(SurfaceDescriptor, schemaVersion ${String(SURFACE_DESCRIPTOR_VERSION)}): pass the ` +
110
+ 'declarative surface (list page, row/field selectors, form templates, archive control, ' +
111
+ 'status values) with the evidence call or via `test.extend({ surface })`. The previous ' +
112
+ 'Accounts-specific fixture was removed from the pack (plan Phase 1 item 7) — see ' +
113
+ 'example/e2e/accounts-surface.js for a complete consumer declaration');
114
+ }
115
+ // Worker-side structural validation (fail fast with the exact missing
116
+ // piece); the ENGINE re-validates authoritatively at registration —
117
+ // worker approval never substitutes for it.
118
+ const descriptor = validateSurface(surface);
119
+ const testId = testInfo.testId;
120
+ // The witness transport is built LAZILY: supplying a pre-resolved
121
+ // session credential (harnesses) must not require witness env wiring
122
+ // until a primitive actually talks to the witness.
123
+ let witnessInstance = null;
124
+ function witness() {
125
+ witnessInstance ??= client ?? new WitnessClient();
126
+ return witnessInstance;
127
+ }
128
+ // The supervisor-issued session credential (Phase 1). Every engine
129
+ // call carries it; the witness forces the record's testId onto the
130
+ // session's supervisor-registered value.
131
+ const credential = session ??
132
+ (await resolveSessionCredential(witness(), {
133
+ testId,
134
+ workerIndex: testInfo.workerIndex,
135
+ title: testInfo.title,
136
+ }, sessionResolveTimeoutMs));
137
+ if (credential.testId !== testId) {
138
+ throw new Error(`the supplied session binds testId '${credential.testId}' but this test is '${testId}' — ` +
139
+ 'records can only be minted for the supervisor-registered test of the open session');
140
+ }
141
+ // Effective claims: native annotations first, plus the
142
+ // supervisor-registered claims this session was opened with (Phase 4
143
+ // claim injection). The injection covers helper-based journeys with NO
144
+ // annotation whose obligation claims come from the tracked
145
+ // `.gateforge/test-map.yml` sidecar (plan E02): the orchestrating CLI
146
+ // resolves the sidecar against the catalog and the supervisor carries
147
+ // the mapped claims on the session-open path. Claims remain
148
+ // DECLARATIONS — they route evidence onto obligation identities; the
149
+ // witness still forces every record onto the supervisor-registered
150
+ // session/test identity and the gate grades witnessed evidence only.
151
+ const claims = [
152
+ ...new Set([...claimsFromAnnotations(testInfo.annotations), ...(credential.claims ?? [])]),
153
+ ].sort();
154
+ if (claims.length === 0) {
155
+ throw new Error(`test '${testInfo.title}' uses gateforge evidence primitives but declares no ` +
156
+ `'${CLAIM_ANNOTATION_TYPE}' annotation and its session carries no supervisor-registered ` +
157
+ '(mapped) claims — annotate the test or map it in .gateforge/test-map.yml');
158
+ }
159
+ const sessionChannel = {
160
+ sessionId: credential.sessionId,
161
+ sessionToken: credential.sessionToken,
162
+ };
163
+ // Register the consumer surface with the witness lazily on the first
164
+ // UI call (construction performs no I/O): the engine validates it and
165
+ // drives every later action against the provisioned attested subject.
166
+ // No origin crosses here — the driven target comes from trusted
167
+ // witness configuration only. Registration proves nothing by itself.
168
+ const receiptBrand = makeReceiptBrand();
169
+ let surfaceRegistered = false;
170
+ async function ensureSurfaceRegistered() {
171
+ if (surfaceRegistered)
172
+ return;
173
+ await witness().registerBrowserSurface({
174
+ ...sessionChannel,
175
+ testId,
176
+ surface: descriptor,
177
+ });
178
+ surfaceRegistered = true;
179
+ }
180
+ /**
181
+ * Asks the ENGINE to perform one constrained surface operation and
182
+ * wraps its observation in a branded receipt. The engine verified the
183
+ * rendered control, the application request, and the visible outcome
184
+ * itself — the receipt carries the engine-observed entity id and the
185
+ * ENTERED input (exact-value echo source), never suite assertions.
186
+ */
187
+ async function engineAction(operation, resourceId, input) {
188
+ await ensureSurfaceRegistered();
189
+ const response = await witness().browserAction({
190
+ ...sessionChannel,
191
+ testId,
192
+ claimIds: [...claims],
193
+ operation,
194
+ ...(input.fields !== undefined ? { fields: input.fields } : {}),
195
+ ...(input.entityId !== undefined ? { entityId: input.entityId } : {}),
196
+ });
197
+ const receipt = {
198
+ operation,
199
+ resourceId,
200
+ entityId: response.entityId,
201
+ fields: response.enteredFields,
202
+ mode: operation === 'read' ? 'form' : 'row',
203
+ ...(response.preObservationId !== null ? { preObservationId: response.preObservationId } : {}),
204
+ };
205
+ return { receipt, preObservationId: response.preObservationId };
206
+ }
207
+ // ---------- UI primitives (engine-driven) ----------
208
+ const ui = {
209
+ async create(input) {
210
+ const fields = declaredSurfaceFields('ui.create', input.fields, descriptor.create.fields);
211
+ const resourceId = resourceIdOfClaim(claims[0]);
212
+ const { receipt } = await engineAction('create', resourceId, { fields });
213
+ return receiptBrand.stamp(receipt);
214
+ },
215
+ async read(input) {
216
+ const { entityId } = input;
217
+ if (!entityId)
218
+ throw new Error('ui.read requires { entityId }');
219
+ const resourceId = resourceIdOfClaim(claims[0]);
220
+ const { receipt } = await engineAction('read', resourceId, { entityId });
221
+ return receiptBrand.stamp(receipt);
222
+ },
223
+ async update(input) {
224
+ const { entityId } = input;
225
+ const fields = declaredSurfaceFields('ui.update', input.fields, descriptor.edit.fields);
226
+ const resourceId = resourceIdOfClaim(claims[0]);
227
+ const { receipt } = await engineAction('update', resourceId, { fields, entityId });
228
+ return receiptBrand.stamp(receipt);
229
+ },
230
+ async archive(input) {
231
+ const { entityId } = input;
232
+ if (!entityId)
233
+ throw new Error('ui.archive requires { entityId }');
234
+ const resourceId = resourceIdOfClaim(claims[0]);
235
+ const { receipt } = await engineAction('delete', resourceId, { entityId });
236
+ return receiptBrand.stamp({ ...receipt, operation: 'delete' });
237
+ },
238
+ };
239
+ // ---------- visible-result primitive (engine re-read) ----------
240
+ const visible = {
241
+ async confirm(receipt) {
242
+ if (!receiptBrand.isGenuine(receipt)) {
243
+ throw new Error('visible.confirm requires a receipt issued by an evidence.ui primitive ' +
244
+ '(hand-rolled objects are rejected — GF-22)');
245
+ }
246
+ const response = await witness().browserVisible({
247
+ ...sessionChannel,
248
+ testId,
249
+ claimIds: [...claims],
250
+ entityId: receipt.entityId,
251
+ operation: receipt.operation,
252
+ });
253
+ return { entityId: response.entityId, fields: response.fields };
254
+ },
255
+ };
256
+ // ---------- persistence primitive (plan §5.3 steps 3-4) ----------
257
+ const persistence = {
258
+ async verify(receipt) {
259
+ if (!receiptBrand.isGenuine(receipt)) {
260
+ throw new Error('persistence.verify requires a receipt issued by an evidence.ui primitive ' +
261
+ '(hand-rolled objects are rejected — GF-22)');
262
+ }
263
+ const response = await witness().verifyPersistence({
264
+ resourceId: receipt.resourceId,
265
+ entityId: receipt.entityId,
266
+ testId,
267
+ claimId: claims[0],
268
+ ...sessionChannel,
269
+ ...(receipt.preObservationId !== undefined
270
+ ? { preObservationId: receipt.preObservationId }
271
+ : {}),
272
+ });
273
+ return {
274
+ recordId: response.recordId,
275
+ runId: response.runId,
276
+ verdictRelevant: response.verdictRelevant,
277
+ };
278
+ },
279
+ };
280
+ // ---------- http observation (ADR 0004 D7, plan §8 / D1) ----------
281
+ // Consumes one ENGINE-CAPTURED exchange the engine's own action caused
282
+ // and binds the witnessed `http.request` record to the declared http:*
283
+ // obligation claims. Only an exchange the engine captured inside its
284
+ // own action interval can be consumed — without a real engine action
285
+ // the witness answers 409 — the suite cannot mint network evidence,
286
+ // borrow another test's request, or credit setup traffic.
287
+ async function observeHttp(request) {
288
+ // Explicit claim selection (plan §8 step 7): an explicit target
289
+ // outside the test's declared claims is caller error, never a
290
+ // silent binding to the wrong obligation.
291
+ if (request.obligationId !== undefined) {
292
+ if (!claims.includes(request.obligationId)) {
293
+ throw new Error(`http.observe targets '${request.obligationId}' which this test did not declare ` +
294
+ `(declared: ${claims.join(', ') || '<none>'})`);
295
+ }
296
+ const targets = [request.obligationId];
297
+ const result = await witness().observeHttp({
298
+ claimIds: [...targets],
299
+ testId,
300
+ method: request.method.toUpperCase(),
301
+ path: request.path,
302
+ ...sessionChannel,
303
+ ...(request.expectedStatus !== undefined ? { expectedStatus: request.expectedStatus } : {}),
304
+ });
305
+ return {
306
+ status: result.status,
307
+ recordId: result.records[0]?.recordId ?? '',
308
+ recordIds: result.records.map((record) => record.recordId),
309
+ };
310
+ }
311
+ const httpClaims = claims.filter((claim) => claim.includes(':http:'));
312
+ const candidates = httpClaims.length > 0 ? httpClaims : claims;
313
+ // Ambiguous omitted selection must fail with a useful error — never
314
+ // silently assign evidence to the first claim.
315
+ if (candidates.length > 1) {
316
+ throw new Error(`http.observe is ambiguous: the test declares ${candidates.length} claims ` +
317
+ `(${candidates.join(', ')}); pass an explicit obligationId`);
318
+ }
319
+ const targets = candidates;
320
+ const result = await witness().observeHttp({
321
+ claimIds: [...targets],
322
+ testId,
323
+ method: request.method.toUpperCase(),
324
+ path: request.path,
325
+ ...sessionChannel,
326
+ ...(request.expectedStatus !== undefined ? { expectedStatus: request.expectedStatus } : {}),
327
+ });
328
+ return {
329
+ status: result.status,
330
+ recordId: result.records[0]?.recordId ?? '',
331
+ recordIds: result.records.map((record) => record.recordId),
332
+ };
333
+ }
334
+ // ---------- finalize (fail-fast + ledger cross-check) ----------
335
+ async function finalize() {
336
+ const ledger = await witness().listRecords();
337
+ const mine = ledger.records.filter((record) => record['testId'] === testId);
338
+ for (const claim of claims) {
339
+ const count = mine.filter((record) => record['obligationId'] === claim).length;
340
+ if (count === 0) {
341
+ throw new Error(`claim '${claim}' produced no witness records (finalize fail-fast; the gate would grade it missing)`);
342
+ }
343
+ }
344
+ const records = mine.map((record) => {
345
+ const entry = record;
346
+ return {
347
+ recordId: String(entry['recordId'] ?? ''),
348
+ runId: String(entry['runId'] ?? ''),
349
+ obligationId: String(entry['obligationId'] ?? ''),
350
+ kind: String(entry['kind'] ?? ''),
351
+ payload: entry['payload'],
352
+ };
353
+ });
354
+ return { claims: [...claims], records };
355
+ }
356
+ // Freeze the surface: no method can be added/replaced from the test;
357
+ // the transcript stays closure-private (no escape hatch, invariant 6).
358
+ return Object.freeze({
359
+ ui: Object.freeze(ui),
360
+ visible: Object.freeze(visible),
361
+ persistence: Object.freeze(persistence),
362
+ http: Object.freeze({ observe: observeHttp }),
363
+ finalize,
364
+ });
365
+ }
366
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/fixture/evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The gateforge Playwright fixture (plan §5.3, GF-24, invariant 6;
3
+ * Phase 1: consumer-declared surface + supervisor-issued sessions).
4
+ *
5
+ * `test` is `test.extend` exposing the `evidence` fixture built from
6
+ * {@link createEvidence} — the ONLY way tests interact with gateforge:
7
+ * the trusted primitives (`ui`, `visible`, `persistence`, `http`,
8
+ * `finalize`) submit witness-stamped records under the supervisor-issued
9
+ * test session; there is no boolean escape hatch and no direct record
10
+ * API. Consumers MUST extend this runner with their declarative
11
+ * `surface` descriptor (`test.extend({ surface })`) — the pack carries
12
+ * no application-specific selectors (plan Phase 1 item 7). Tests must
13
+ * import `{ test, expect }` FROM A RUNNER EXTENDED LIKE THIS — importing
14
+ * raw `playwright/test` bypasses the fixture and produces claims with no
15
+ * records (the engine grades the obligation `missing`; GF-24).
16
+ */
17
+ import { expect } from 'playwright/test';
18
+ import { type EvidenceApi, type SurfaceDescriptor } from './evidence.js';
19
+ /** Fixture map this pack adds to every test. */
20
+ export type EvidenceFixtures = {
21
+ /**
22
+ * The consumer-declared surface descriptor (list page, selectors,
23
+ * form templates, status values). Declare it once per consumer:
24
+ * `const test = gateforgeTest.extend({ surface: mySurface })`.
25
+ */
26
+ surface: SurfaceDescriptor;
27
+ /** The trusted evidence primitive surface for the running test. */
28
+ evidence: EvidenceApi;
29
+ };
30
+ /**
31
+ * The extended test runner. The `surface` fixture has NO default: a test
32
+ * that needs `evidence` without a wired surface fails fast with the
33
+ * actionable error below (fail closed — never generic selectors).
34
+ */
35
+ export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & EvidenceFixtures, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions>;
36
+ export { expect };
37
+ //# sourceMappingURL=fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/fixture/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAgB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAC;AAEvB,gDAAgD;AAChD,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,OAAO,EAAE,iBAAiB,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,IAAI,2PAcf,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The gateforge Playwright fixture (plan §5.3, GF-24, invariant 6;
3
+ * Phase 1: consumer-declared surface + supervisor-issued sessions).
4
+ *
5
+ * `test` is `test.extend` exposing the `evidence` fixture built from
6
+ * {@link createEvidence} — the ONLY way tests interact with gateforge:
7
+ * the trusted primitives (`ui`, `visible`, `persistence`, `http`,
8
+ * `finalize`) submit witness-stamped records under the supervisor-issued
9
+ * test session; there is no boolean escape hatch and no direct record
10
+ * API. Consumers MUST extend this runner with their declarative
11
+ * `surface` descriptor (`test.extend({ surface })`) — the pack carries
12
+ * no application-specific selectors (plan Phase 1 item 7). Tests must
13
+ * import `{ test, expect }` FROM A RUNNER EXTENDED LIKE THIS — importing
14
+ * raw `playwright/test` bypasses the fixture and produces claims with no
15
+ * records (the engine grades the obligation `missing`; GF-24).
16
+ */
17
+ import { test as base, expect } from 'playwright/test';
18
+ import { createEvidence, SURFACE_DESCRIPTOR_VERSION, } from './evidence.js';
19
+ /**
20
+ * The extended test runner. The `surface` fixture has NO default: a test
21
+ * that needs `evidence` without a wired surface fails fast with the
22
+ * actionable error below (fail closed — never generic selectors).
23
+ */
24
+ export const test = base.extend({
25
+ surface: async ({}, use) => {
26
+ void use; // no usable default exists — fail closed with the setup action
27
+ throw new Error('no surface descriptor is wired for the evidence fixture: extend the gateforge runner ' +
28
+ 'with `test.extend({ surface })` and pass your consumer-declared SurfaceDescriptor ' +
29
+ `(schemaVersion ${String(SURFACE_DESCRIPTOR_VERSION)}). The pack ships no application ` +
30
+ 'selectors (plan Phase 1 item 7) — see example/e2e/accounts-surface.js');
31
+ },
32
+ evidence: async ({ page, surface }, use, testInfo) => {
33
+ const evidence = await createEvidence({ page, testInfo, surface });
34
+ await use(evidence);
35
+ },
36
+ });
37
+ export { expect }; // re-exported so tests never need `playwright/test`
38
+ //# sourceMappingURL=fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.js","sourceRoot":"","sources":["../../src/fixture/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EACL,cAAc,EACd,0BAA0B,GAG3B,MAAM,eAAe,CAAC;AAcvB;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAmB;IAChD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAiB,EAAE;QACxC,KAAK,GAAG,CAAC,CAAC,+DAA+D;QACzE,MAAM,IAAI,KAAK,CACb,uFAAuF;YACrF,oFAAoF;YACpF,kBAAkB,MAAM,CAAC,0BAA0B,CAAC,mCAAmC;YACvF,uEAAuE,CAC1E,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE;QACnD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACnE,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,oDAAoD"}
@@ -0,0 +1,164 @@
1
+ import type { BrowserActionRequest, BrowserActionResponse, BrowserSurfaceRequest, BrowserVisibleRequest, BrowserVisibleResponse, IntervalCloseResponse, IntervalOpenResponse, PersistenceRequest, PersistenceResponse, PreObservationRequest, PreObservationResponse, RecordsRequest, RecordsResponse, 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/intervals/open (Phase 1): marks the start of a
55
+ * UI-action observation interval on the witness's monotonic clock.
56
+ * Proxy exchanges completing inside the interval are the session's
57
+ * browser evidence; everything outside (setup traffic) is never
58
+ * credited.
59
+ */
60
+ beginActionInterval(request: {
61
+ sessionId: string;
62
+ sessionToken: string;
63
+ operation: string;
64
+ }): Promise<IntervalOpenResponse>;
65
+ /**
66
+ * POST /sessions/intervals/close (Phase 1): seals the interval. A
67
+ * closed interval can never be stretched later (409 on re-close).
68
+ */
69
+ endActionInterval(request: {
70
+ sessionId: string;
71
+ sessionToken: string;
72
+ intervalId: string;
73
+ }): Promise<IntervalCloseResponse>;
74
+ /**
75
+ * POST /witness/pre-observation (audit round 4): engine-side id-set
76
+ * snapshot BEFORE a claimed create; pass the returned
77
+ * `observationId` to `verifyPersistence` so the issued record carries
78
+ * `before: {entityAbsent}`. Phase 1: requires the supervisor-issued
79
+ * session credential — the snapshot belongs to the open test session.
80
+ */
81
+ preObserve(request: PreObservationRequest): Promise<PreObservationResponse>;
82
+ /**
83
+ * POST /witness/http-observation (ADR 0004 D7, plan §8 / D1):
84
+ * consumes one witness-observed HTTP exchange matching (method, path)
85
+ * and issues witnessed `http.request` records for the declaring
86
+ * test's claimed obligations. Phase 1: the caller must hold a valid
87
+ * OPEN session and only an exchange observed through THAT session's
88
+ * proxy prefix within one of its recorded action intervals can be
89
+ * consumed — the claim set may be given as `claimIds`, or as the
90
+ * singular legacy `claimId`/`obligationId` pair (folded in by the
91
+ * server; a split assignment with distinct values is refused with 400).
92
+ */
93
+ observeHttp(request: {
94
+ claimIds?: string[];
95
+ claimId?: string;
96
+ obligationId?: string;
97
+ testId: string;
98
+ method: string;
99
+ path: string;
100
+ expectedStatus?: number;
101
+ sessionId: string;
102
+ sessionToken: string;
103
+ }): Promise<{
104
+ recordId: string;
105
+ runId: string;
106
+ trust: string;
107
+ status: number;
108
+ records: Array<{
109
+ recordId: string;
110
+ obligationId: string;
111
+ }>;
112
+ }>;
113
+ /**
114
+ * POST /witness/persistence (Phase 1): runs the engine-side adapter
115
+ * read under the supervisor-opened session, so the persistence record
116
+ * binds to the same channel the UI action used.
117
+ */
118
+ verifyPersistence(request: PersistenceRequest & {
119
+ testId: string;
120
+ claimId: string;
121
+ sessionId: string;
122
+ sessionToken: string;
123
+ }): Promise<PersistenceResponse>;
124
+ /**
125
+ * POST /browser/surface (plan Phase 1 item 4): registers the
126
+ * consumer-declared surface descriptor + the app base the ENGINE must
127
+ * drive for this session. Validated engine-side (structure, loopback,
128
+ * fingerprint); selectors are locators only.
129
+ */
130
+ registerBrowserSurface(request: BrowserSurfaceRequest): Promise<{
131
+ registered: true;
132
+ }>;
133
+ /**
134
+ * POST /browser/action (plan Phase 1 item 4): the ENGINE performs one
135
+ * constrained surface operation on its own page and returns its own
136
+ * observation (observed entity id, entered + rendered fields, app
137
+ * status, pre-observation id, issued record ids). Test code supplies
138
+ * intent only — it never touches the engine page.
139
+ */
140
+ browserAction(request: BrowserActionRequest): Promise<BrowserActionResponse>;
141
+ /**
142
+ * POST /browser/visible (plan Phase 1 item 4): the ENGINE re-reads
143
+ * the rendered result for the engine-observed entity and returns the
144
+ * rendered fields.
145
+ */
146
+ browserVisible(request: BrowserVisibleRequest): Promise<BrowserVisibleResponse>;
147
+ /** GET /records — the issued ledger for this run. */
148
+ listRecords(): Promise<{
149
+ records: IssuedLedgerRecord[];
150
+ }>;
151
+ private request;
152
+ }
153
+ /** One witness-issued ledger record as seen by the ledger endpoint. */
154
+ export interface IssuedLedgerRecord {
155
+ recordId: string;
156
+ runId: string;
157
+ trust: 'witnessed' | 'claimed';
158
+ obligationId: string;
159
+ kind: string;
160
+ testId: string;
161
+ payload: unknown;
162
+ issuedAt?: string;
163
+ }
164
+ //# sourceMappingURL=witness-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"witness-client.d.ts","sourceRoot":"","sources":["../../src/fixture/witness-client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,cAAc,EACd,eAAe,EAEf,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,qEAAqE;AACrE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;gBACnB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW;CAM1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAkB1C;AACD;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAGzB,GAAG,GAAE,MAA4B,EACjC,KAAK,GAAE,MAAM,GAAG,SAAsC,EACtD,SAAS,SAAO;IAUlB,0FAA0F;IACpF,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAKpE;;;;;;;;;;;;;;;;OAgBG;IACG,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAS5F;;;;;;OAMG;IACG,mBAAmB,CAAC,OAAO,EAAE;QACjC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAIjC;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE;QAC/B,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAIlC;;;;;;OAMG;IACG,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAIjF;;;;;;;;;;OAUG;IACG,WAAW,CACf,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;KACtB,GACA,OAAO,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC5D,CAAC;IAeF;;;;OAIG;IACG,iBAAiB,CACrB,OAAO,EAAE,kBAAkB,GAAG;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;KACtB,GACA,OAAO,CAAC,mBAAmB,CAAC;IAI/B;;;;;OAKG;IACG,sBAAsB,CAC1B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC;QAAE,UAAU,EAAE,IAAI,CAAA;KAAE,CAAC;IAIhC;;;;;;OAMG;IACG,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAIlF;;;;OAIG;IACG,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAIpF,qDAAqD;IACjD,WAAW,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAAC;YAiChD,OAAO;CAoCtB;AAMD,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB"}