@lovrozagar/oat 0.7.3 → 0.7.5

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 (59) hide show
  1. package/README.md +181 -136
  2. package/dist/cli.js +19 -1
  3. package/dist/config/define-config.d.ts +29 -4
  4. package/dist/config/define-config.d.ts.map +1 -1
  5. package/dist/config/define-config.js.map +1 -1
  6. package/dist/report/console.d.ts.map +1 -1
  7. package/dist/report/console.js +1 -0
  8. package/dist/report/console.js.map +1 -1
  9. package/dist/report/matrix.d.ts.map +1 -1
  10. package/dist/report/matrix.js +4 -1
  11. package/dist/report/matrix.js.map +1 -1
  12. package/dist/report/render.d.ts +4 -0
  13. package/dist/report/render.d.ts.map +1 -1
  14. package/dist/report/render.js +12 -2
  15. package/dist/report/render.js.map +1 -1
  16. package/dist/runtime/body.d.ts.map +1 -1
  17. package/dist/runtime/body.js +18 -2
  18. package/dist/runtime/body.js.map +1 -1
  19. package/dist/runtime/checks.d.ts.map +1 -1
  20. package/dist/runtime/checks.js +199 -123
  21. package/dist/runtime/checks.js.map +1 -1
  22. package/dist/runtime/client.d.ts +7 -1
  23. package/dist/runtime/client.d.ts.map +1 -1
  24. package/dist/runtime/client.js +3 -1
  25. package/dist/runtime/client.js.map +1 -1
  26. package/dist/runtime/effects.d.ts +43 -0
  27. package/dist/runtime/effects.d.ts.map +1 -0
  28. package/dist/runtime/effects.js +141 -0
  29. package/dist/runtime/effects.js.map +1 -0
  30. package/dist/runtime/exchanges.d.ts +37 -0
  31. package/dist/runtime/exchanges.d.ts.map +1 -0
  32. package/dist/runtime/exchanges.js +298 -0
  33. package/dist/runtime/exchanges.js.map +1 -0
  34. package/dist/runtime/finding.d.ts +6 -4
  35. package/dist/runtime/finding.d.ts.map +1 -1
  36. package/dist/runtime/finding.js +13 -8
  37. package/dist/runtime/finding.js.map +1 -1
  38. package/dist/runtime/run.d.ts +9 -0
  39. package/dist/runtime/run.d.ts.map +1 -1
  40. package/dist/runtime/run.js +17 -1
  41. package/dist/runtime/run.js.map +1 -1
  42. package/dist/runtime/upload-each.d.ts +14 -0
  43. package/dist/runtime/upload-each.d.ts.map +1 -0
  44. package/dist/runtime/upload-each.js +69 -0
  45. package/dist/runtime/upload-each.js.map +1 -0
  46. package/dist/runtime/upload.d.ts +8 -0
  47. package/dist/runtime/upload.d.ts.map +1 -1
  48. package/dist/runtime/upload.js +26 -4
  49. package/dist/runtime/upload.js.map +1 -1
  50. package/dist/runtime/world.d.ts.map +1 -1
  51. package/dist/runtime/world.js +57 -27
  52. package/dist/runtime/world.js.map +1 -1
  53. package/dist/spec/extensions.d.ts +4 -1
  54. package/dist/spec/extensions.d.ts.map +1 -1
  55. package/dist/spec/extensions.js +8 -2
  56. package/dist/spec/extensions.js.map +1 -1
  57. package/dist/spec/graph.js +1 -1
  58. package/dist/spec/graph.js.map +1 -1
  59. package/package.json +1 -1
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Persist every HTTP exchange under the run dir so a green run is still inspectable.
3
+ *
4
+ * Layout (next to `progress.tsv`):
5
+ * exchanges.jsonl one line per Exchange.seq, join key = requestId = TSV req_id
6
+ * exchanges/<requestId>.json full exchange (headers + described / spilled bodies)
7
+ * blobs/<sha256> content-addressed bytes (multipart, binary, oversized text)
8
+ *
9
+ * Redaction is on by default. This is oat's journal, not a HAR file.
10
+ */
11
+ import { createHash } from "node:crypto";
12
+ import { existsSync } from "node:fs";
13
+ import { appendFile, mkdir, writeFile } from "node:fs/promises";
14
+ import { join } from "node:path";
15
+ import { describeRequestBody } from "./client.js";
16
+ import { sseEvents } from "./sse.js";
17
+ export const INLINE_BODY_LIMIT = 256 * 1024;
18
+ const REDACTED = "<redacted>";
19
+ const REDACT_HEADER_NAMES = new Set(["authorization", "cookie", "set-cookie", "proxy-authorization", "x-ia-tester-key"]);
20
+ const REDACT_JSON_KEYS = new Set([
21
+ "access_token",
22
+ "refresh_token",
23
+ "id_token",
24
+ "password",
25
+ "token",
26
+ "secret",
27
+ "api_key",
28
+ ]);
29
+ export function resolveSaveExchanges(options) {
30
+ if (options.flag !== undefined)
31
+ return options.flag;
32
+ if (options.config !== undefined)
33
+ return options.config;
34
+ return options.profile !== "cheap";
35
+ }
36
+ export function isSecretHeaderName(name) {
37
+ const lower = name.toLowerCase();
38
+ if (REDACT_HEADER_NAMES.has(lower))
39
+ return true;
40
+ return /^x-.+-(key|secret)$/i.test(lower);
41
+ }
42
+ export function redactHeaders(headers) {
43
+ const out = {};
44
+ for (const [key, value] of Object.entries(headers)) {
45
+ out[key] = isSecretHeaderName(key) ? REDACTED : value;
46
+ }
47
+ return out;
48
+ }
49
+ export function redactJson(value) {
50
+ if (Array.isArray(value))
51
+ return value.map((item) => redactJson(item));
52
+ if (value === null || typeof value !== "object")
53
+ return value;
54
+ const out = {};
55
+ for (const [key, child] of Object.entries(value)) {
56
+ out[key] = REDACT_JSON_KEYS.has(key.toLowerCase()) ? REDACTED : redactJson(child);
57
+ }
58
+ return out;
59
+ }
60
+ export function sanitizeExchangeId(requestId) {
61
+ const cleaned = requestId
62
+ .trim()
63
+ .replace(/[^A-Za-z0-9._-]+/g, "_")
64
+ .replace(/^_+|_+$/g, "");
65
+ return cleaned === "" ? "id" : cleaned.slice(0, 180);
66
+ }
67
+ export function exchangeFileStem(requestId, seq, taken) {
68
+ const trimmed = requestId.trim();
69
+ const base = trimmed === "" ? `seq-${seq}` : sanitizeExchangeId(trimmed);
70
+ if (!taken.has(base))
71
+ return base;
72
+ const dup = `${base}-${seq}`;
73
+ if (!taken.has(dup))
74
+ return dup;
75
+ let n = 2;
76
+ while (taken.has(`${dup}-${n}`))
77
+ n += 1;
78
+ return `${dup}-${n}`;
79
+ }
80
+ export function primaryMediaType(mediaType, fallback) {
81
+ const named = mediaType
82
+ .split(";")
83
+ .map((part) => part.trim())
84
+ .find((part) => part.includes("/"));
85
+ return named === undefined || named === "" ? fallback : named;
86
+ }
87
+ export function isBinaryMediaType(mediaType) {
88
+ const type = primaryMediaType(mediaType, "").toLowerCase();
89
+ if (type.startsWith("image/") || type.startsWith("audio/") || type.startsWith("video/"))
90
+ return true;
91
+ if (type === "application/octet-stream" || type === "application/pdf" || type === "application/zip")
92
+ return true;
93
+ if (type === "application/vnd.ms-excel")
94
+ return true;
95
+ if (type.includes("spreadsheet") || type.includes("officedocument") || type.includes("opendocument"))
96
+ return true;
97
+ return false;
98
+ }
99
+ function sha256Hex(bytes) {
100
+ return createHash("sha256").update(bytes).digest("hex");
101
+ }
102
+ function utf8Bytes(text) {
103
+ return new TextEncoder().encode(text);
104
+ }
105
+ function headerOf(headers, name) {
106
+ const want = name.toLowerCase();
107
+ for (const [key, value] of Object.entries(headers)) {
108
+ if (key.toLowerCase() === want && value.trim() !== "")
109
+ return value;
110
+ }
111
+ return undefined;
112
+ }
113
+ async function bytesOf(value) {
114
+ if (value instanceof Uint8Array)
115
+ return value;
116
+ if (typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer)
117
+ return new Uint8Array(value);
118
+ if (ArrayBuffer.isView(value))
119
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
120
+ if (typeof Blob !== "undefined" && value instanceof Blob)
121
+ return new Uint8Array(await value.arrayBuffer());
122
+ return undefined;
123
+ }
124
+ function isFormData(body) {
125
+ return typeof FormData !== "undefined" && body instanceof FormData;
126
+ }
127
+ function isURLSearchParams(body) {
128
+ return typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams;
129
+ }
130
+ export function createExchangeJournal(dir) {
131
+ const taken = new Set();
132
+ const writtenBlobs = new Set();
133
+ let count = 0;
134
+ let ready;
135
+ const ensure = async () => {
136
+ if (ready === undefined) {
137
+ ready = Promise.all([
138
+ mkdir(join(dir, "exchanges"), { recursive: true }),
139
+ mkdir(join(dir, "blobs"), { recursive: true }),
140
+ ]).then(() => undefined);
141
+ }
142
+ await ready;
143
+ };
144
+ const putBlob = async (bytes) => {
145
+ const sha256 = sha256Hex(bytes);
146
+ if (!writtenBlobs.has(sha256)) {
147
+ const path = join(dir, "blobs", sha256);
148
+ if (!existsSync(path))
149
+ await writeFile(path, bytes);
150
+ writtenBlobs.add(sha256);
151
+ }
152
+ return { bytes: bytes.byteLength, sha256 };
153
+ };
154
+ const spillText = async (text, mediaType) => {
155
+ const bytes = utf8Bytes(text);
156
+ if (bytes.byteLength <= INLINE_BODY_LIMIT)
157
+ return text;
158
+ const blob = await putBlob(bytes);
159
+ return { ...blob, mediaType };
160
+ };
161
+ const persistJson = async (value, mediaType) => {
162
+ const redacted = redactJson(value);
163
+ const text = JSON.stringify(redacted);
164
+ if (utf8Bytes(text).byteLength <= INLINE_BODY_LIMIT)
165
+ return redacted;
166
+ const blob = await putBlob(utf8Bytes(text));
167
+ return { ...blob, mediaType };
168
+ };
169
+ const persistRequestBody = async (body) => {
170
+ if (body === undefined)
171
+ return undefined;
172
+ if (isFormData(body)) {
173
+ const parts = [];
174
+ for (const [field, value] of body.entries()) {
175
+ if (typeof value === "string") {
176
+ parts.push({
177
+ field,
178
+ value: REDACT_JSON_KEYS.has(field.toLowerCase()) ? REDACTED : value,
179
+ });
180
+ continue;
181
+ }
182
+ const bytes = new Uint8Array(await value.arrayBuffer());
183
+ const blob = await putBlob(bytes);
184
+ parts.push({
185
+ bytes: blob.bytes,
186
+ field,
187
+ filename: value.name,
188
+ mediaType: value.type || "application/octet-stream",
189
+ sha256: blob.sha256,
190
+ });
191
+ }
192
+ return { parts };
193
+ }
194
+ if (isURLSearchParams(body))
195
+ return redactJson(Object.fromEntries(body.entries()));
196
+ const raw = await bytesOf(body);
197
+ if (raw !== undefined) {
198
+ const blob = await putBlob(raw);
199
+ return { ...blob, mediaType: "application/octet-stream" };
200
+ }
201
+ if (typeof body === "string")
202
+ return spillText(body, "text/plain");
203
+ if (body !== null && typeof body === "object")
204
+ return persistJson(body, "application/json");
205
+ return describeRequestBody(body);
206
+ };
207
+ const persistResponseBody = async (exchange) => {
208
+ const mediaType = headerOf(exchange.responseHeaders, "content-type") ?? "";
209
+ const body = exchange.responseBody;
210
+ if (mediaType.toLowerCase().includes("text/event-stream") && typeof body === "string") {
211
+ const frames = sseEvents(body);
212
+ if (frames !== null) {
213
+ return frames.map((frame) => ({ data: redactJson(frame.data), event: frame.event }));
214
+ }
215
+ return spillText(body, primaryMediaType(mediaType, "text/event-stream"));
216
+ }
217
+ if (isBinaryMediaType(mediaType)) {
218
+ const bytes = typeof body === "string" ? utf8Bytes(body) : ((await bytesOf(body)) ?? utf8Bytes(JSON.stringify(body)));
219
+ const blob = await putBlob(bytes);
220
+ return { ...blob, mediaType: primaryMediaType(mediaType, "application/octet-stream") };
221
+ }
222
+ if (body === undefined)
223
+ return undefined;
224
+ if (typeof body === "string") {
225
+ const asFrames = sseEvents(body);
226
+ if (asFrames !== null) {
227
+ return asFrames.map((frame) => ({ data: redactJson(frame.data), event: frame.event }));
228
+ }
229
+ return spillText(body, primaryMediaType(mediaType, "text/plain"));
230
+ }
231
+ if (body !== null && typeof body === "object") {
232
+ return persistJson(body, primaryMediaType(mediaType, "application/json"));
233
+ }
234
+ return body;
235
+ };
236
+ return {
237
+ get count() {
238
+ return count;
239
+ },
240
+ get dir() {
241
+ return dir;
242
+ },
243
+ async record(exchange, meta = {}) {
244
+ await ensure();
245
+ const requestBody = await persistRequestBody(exchange.requestBody);
246
+ const responseBody = await persistResponseBody(exchange);
247
+ let stem = exchangeFileStem(exchange.requestId, exchange.seq, taken);
248
+ const exchangesDir = join(dir, "exchanges");
249
+ while (existsSync(join(exchangesDir, `${stem}.json`))) {
250
+ taken.add(stem);
251
+ stem = exchangeFileStem(exchange.requestId, exchange.seq, taken);
252
+ }
253
+ taken.add(stem);
254
+ const rel = `exchanges/${stem}.json`;
255
+ const file = {
256
+ at: exchange.at,
257
+ durationMs: exchange.durationMs,
258
+ ...(exchange.fixture === undefined ? {} : { fixture: exchange.fixture }),
259
+ method: exchange.method,
260
+ ...(exchange.operationId === undefined ? {} : { operationId: exchange.operationId }),
261
+ requestBody,
262
+ requestHeaders: redactHeaders(exchange.requestHeaders),
263
+ requestId: exchange.requestId,
264
+ responseBody,
265
+ responseHeaders: redactHeaders(exchange.responseHeaders),
266
+ seq: exchange.seq,
267
+ status: exchange.status,
268
+ url: exchange.url,
269
+ };
270
+ await writeFile(join(dir, rel), `${JSON.stringify(file, null, 2)}\n`);
271
+ const line = {
272
+ at: exchange.at,
273
+ durationMs: exchange.durationMs,
274
+ file: rel,
275
+ method: exchange.method,
276
+ requestBytes: exchange.requestBytes,
277
+ requestId: exchange.requestId,
278
+ responseBytes: exchange.responseBytes,
279
+ seq: exchange.seq,
280
+ status: exchange.status,
281
+ url: exchange.url,
282
+ };
283
+ if (exchange.operationId !== undefined)
284
+ line.operationId = exchange.operationId;
285
+ if (exchange.fixture !== undefined)
286
+ line.fixture = exchange.fixture;
287
+ if (meta.check !== undefined)
288
+ line.check = meta.check;
289
+ if (meta.entity !== undefined)
290
+ line.entity = meta.entity;
291
+ if (meta.phase !== undefined)
292
+ line.phase = meta.phase;
293
+ await appendFile(join(dir, "exchanges.jsonl"), `${JSON.stringify(line)}\n`);
294
+ count += 1;
295
+ },
296
+ };
297
+ }
298
+ //# sourceMappingURL=exchanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchanges.js","sourceRoot":"","sources":["../../src/runtime/exchanges.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,mBAAmB,EAAiB,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,GAAG,IAAI,CAAA;AAE3C,MAAM,QAAQ,GAAG,YAAY,CAAA;AAE7B,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAC,CAAA;AAExH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAChC,cAAc;IACd,eAAe;IACf,UAAU;IACV,UAAU;IACV,OAAO;IACP,QAAQ;IACR,SAAS;CACT,CAAC,CAAA;AAcF,MAAM,UAAU,oBAAoB,CAAC,OAKpC;IACA,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,IAAI,CAAA;IACnD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,MAAM,CAAA;IACvD,OAAO,OAAO,CAAC,OAAO,KAAK,OAAO,CAAA;AACnC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAChC,IAAI,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAC/C,OAAO,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAA+B;IAC5D,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAA;IACtD,CAAC;IACD,OAAO,GAAG,CAAA;AACX,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACxC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;IACtE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7D,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,GAAG,CAAA;AACX,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IACnD,MAAM,OAAO,GAAG,SAAS;SACvB,IAAI,EAAE;SACN,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC;SACjC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IACzB,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,GAAW,EAAE,KAA0B;IAC1F,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAA;IAChC,MAAM,IAAI,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAA;IACxE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IACjC,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE,CAAA;IAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAA;IAC/B,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;QAAE,CAAC,IAAI,CAAC,CAAA;IACvC,OAAO,GAAG,GAAG,IAAI,CAAC,EAAE,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,QAAgB;IACnE,MAAM,KAAK,GAAG,SAAS;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;IACpC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IAClD,MAAM,IAAI,GAAG,gBAAgB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IAC1D,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAA;IACpG,IAAI,IAAI,KAAK,0BAA0B,IAAI,IAAI,KAAK,iBAAiB,IAAI,IAAI,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAA;IAChH,IAAI,IAAI,KAAK,0BAA0B;QAAE,OAAO,IAAI,CAAA;IACpD,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,IAAI,CAAA;IACjH,OAAO,KAAK,CAAA;AACb,CAAC;AAED,SAAS,SAAS,CAAC,KAAiB;IACnC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC9B,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AACtC,CAAC;AAED,SAAS,QAAQ,CAAC,OAA+B,EAAE,IAAY;IAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,KAAK,CAAA;IACpE,CAAC;IACD,OAAO,SAAS,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,KAAc;IACpC,IAAI,KAAK,YAAY,UAAU;QAAE,OAAO,KAAK,CAAA;IAC7C,IAAI,OAAO,WAAW,KAAK,WAAW,IAAI,KAAK,YAAY,WAAW;QAAE,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAA;IACpG,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACtG,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;IAC1G,OAAO,SAAS,CAAA;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,IAAa;IAChC,OAAO,OAAO,QAAQ,KAAK,WAAW,IAAI,IAAI,YAAY,QAAQ,CAAA;AACnE,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAa;IACvC,OAAO,OAAO,eAAe,KAAK,WAAW,IAAI,IAAI,YAAY,eAAe,CAAA;AACjF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAChD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;IAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IACtC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,KAAgC,CAAA;IAEpC,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;QACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC;gBACnB,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;gBAClD,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;aAC9C,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QACzB,CAAC;QACD,MAAM,KAAK,CAAA;IACZ,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,KAAK,EAAE,KAAiB,EAA8C,EAAE;QACvF,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;YACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,MAAM,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YACnD,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;IAC3C,CAAC,CAAA;IAED,MAAM,SAAS,GAAG,KAAK,EACtB,IAAY,EACZ,SAAiB,EACwD,EAAE;QAC3E,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC7B,IAAI,KAAK,CAAC,UAAU,IAAI,iBAAiB;YAAE,OAAO,IAAI,CAAA;QACtD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAA;QACjC,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAA;IAC9B,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,KAAK,EAAE,KAAc,EAAE,SAAiB,EAAoB,EAAE;QACjF,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACrC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,iBAAiB;YAAE,OAAO,QAAQ,CAAA;QACpE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QAC3C,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAA;IAC9B,CAAC,CAAA;IAED,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAa,EAAoB,EAAE;QACpE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QACxC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,KAAK,GAAmC,EAAE,CAAA;YAChD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC/B,KAAK,CAAC,IAAI,CAAC;wBACV,KAAK;wBACL,KAAK,EAAE,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK;qBACnE,CAAC,CAAA;oBACF,SAAQ;gBACT,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;gBACvD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAA;gBACjC,KAAK,CAAC,IAAI,CAAC;oBACV,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,KAAK;oBACL,QAAQ,EAAE,KAAK,CAAC,IAAI;oBACpB,SAAS,EAAE,KAAK,CAAC,IAAI,IAAI,0BAA0B;oBACnD,MAAM,EAAE,IAAI,CAAC,MAAM;iBACnB,CAAC,CAAA;YACH,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,CAAA;QACjB,CAAC;QACD,IAAI,iBAAiB,CAAC,IAAI,CAAC;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAClF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;QAC/B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;YAC/B,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,0BAA0B,EAAE,CAAA;QAC1D,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;QAClE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;QAC3F,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC,CAAA;IAED,MAAM,mBAAmB,GAAG,KAAK,EAAE,QAAkB,EAAoB,EAAE;QAC1E,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,IAAI,EAAE,CAAA;QAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAA;QAClC,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvF,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;YAC9B,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACrF,CAAC;YACD,OAAO,SAAS,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC,CAAA;QACzE,CAAC;QACD,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,GACV,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACxG,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAA;YACjC,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,SAAS,EAAE,0BAA0B,CAAC,EAAE,CAAA;QACvF,CAAC;QACD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QACxC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACvB,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACvF,CAAC;YACD,OAAO,SAAS,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAA;QAClE,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/C,OAAO,WAAW,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAA;QAC1E,CAAC;QACD,OAAO,IAAI,CAAA;IACZ,CAAC,CAAA;IAED,OAAO;QACN,IAAI,KAAK;YACR,OAAO,KAAK,CAAA;QACb,CAAC;QACD,IAAI,GAAG;YACN,OAAO,GAAG,CAAA;QACX,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE;YAC/B,MAAM,MAAM,EAAE,CAAA;YACd,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;YAClE,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAA;YACxD,IAAI,IAAI,GAAG,gBAAgB,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACpE,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;YAC3C,OAAO,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;gBACvD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACf,IAAI,GAAG,gBAAgB,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACjE,CAAC;YACD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACf,MAAM,GAAG,GAAG,aAAa,IAAI,OAAO,CAAA;YACpC,MAAM,IAAI,GAAG;gBACZ,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACxE,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,GAAG,CAAC,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACpF,WAAW;gBACX,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC;gBACtD,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,YAAY;gBACZ,eAAe,EAAE,aAAa,CAAC,QAAQ,CAAC,eAAe,CAAC;gBACxD,GAAG,EAAE,QAAQ,CAAC,GAAG;gBACjB,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,GAAG,EAAE,QAAQ,CAAC,GAAG;aACjB,CAAA;YACD,MAAM,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;YACrE,MAAM,IAAI,GAA4B;gBACrC,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,IAAI,EAAE,GAAG;gBACT,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,GAAG,EAAE,QAAQ,CAAC,GAAG;gBACjB,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,GAAG,EAAE,QAAQ,CAAC,GAAG;aACjB,CAAA;YACD,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS;gBAAE,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;YAC/E,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAA;YACnE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;YACrD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;YACxD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;YACrD,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC3E,KAAK,IAAI,CAAC,CAAA;QACX,CAAC;KACD,CAAA;AACF,CAAC"}
@@ -15,6 +15,8 @@ export interface Finding {
15
15
  evidence: Exchange[];
16
16
  /** Set when the finding came from a non-primary `origins[]` host. */
17
17
  origin?: string;
18
+ /** Fixture filename when `uploads.each` drove the invocation. */
19
+ fixture?: string;
18
20
  }
19
21
  /**
20
22
  * A check that ran, could not reach a verdict, and stopped.
@@ -41,10 +43,10 @@ export declare class FindingCollector {
41
43
  */
42
44
  unresolved(check: string, entity: string, reason: string): undefined;
43
45
  report(finding: Finding): void;
44
- backend(check: string, entity: string, summary: string, detail: string, evidence: Exchange[]): void;
45
- security(check: string, entity: string, summary: string, detail: string, evidence: Exchange[]): void;
46
- spec(check: string, entity: string, summary: string, detail: string, evidence: Exchange[]): void;
47
- gap(check: string, entity: string, summary: string, detail: string): void;
46
+ backend(check: string, entity: string, summary: string, detail: string, evidence: Exchange[], fixture?: string): void;
47
+ security(check: string, entity: string, summary: string, detail: string, evidence: Exchange[], fixture?: string): void;
48
+ spec(check: string, entity: string, summary: string, detail: string, evidence: Exchange[], fixture?: string): void;
49
+ gap(check: string, entity: string, summary: string, detail: string, fixture?: string): void;
48
50
  blocked(check: string, entity: string, summary: string, cause: string): void;
49
51
  checks(): string[];
50
52
  byVerdict(verdict: Verdict): Finding[];
@@ -1 +1 @@
1
- {"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../../src/runtime/finding.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,SAAS,CAAA;AAExG,MAAM,WAAW,OAAO;IACvB,gGAAgG;IAChG,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;CACd;AAED,qBAAa,gBAAgB;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAK;IACjC,QAAQ,CAAC,YAAY,EAAE,YAAY,EAAE,CAAK;IAE1C;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS;IAKpE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI9B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI;IAInG,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI;IAIpG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI;IAIhG,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIzE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAW5E,MAAM,IAAI,MAAM,EAAE;IAIlB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE;CAGtC"}
1
+ {"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../../src/runtime/finding.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,SAAS,CAAA;AAExG,MAAM,WAAW,OAAO;IACvB,gGAAgG;IAChG,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;CACd;AAOD,qBAAa,gBAAgB;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAK;IACjC,QAAQ,CAAC,YAAY,EAAE,YAAY,EAAE,CAAK;IAE1C;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS;IAKpE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI9B,OAAO,CACN,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAAE,EACpB,OAAO,CAAC,EAAE,MAAM,GACd,IAAI;IAIP,QAAQ,CACP,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAAE,EACpB,OAAO,CAAC,EAAE,MAAM,GACd,IAAI;IAIP,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAIlH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAI3F,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAW5E,MAAM,IAAI,MAAM,EAAE;IAIlB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE;CAGtC"}
@@ -3,6 +3,11 @@
3
3
  * from what the evidence shows, which is what lets the report collapse cascades and lets the
4
4
  * conformance suite assert "exactly this defect was detected".
5
5
  */
6
+ function withFixture(finding, fixture) {
7
+ if (fixture === undefined || fixture === "")
8
+ return finding;
9
+ return { ...finding, fixture };
10
+ }
6
11
  export class FindingCollector {
7
12
  findings = [];
8
13
  inconclusive = [];
@@ -18,17 +23,17 @@ export class FindingCollector {
18
23
  report(finding) {
19
24
  this.findings.push(finding);
20
25
  }
21
- backend(check, entity, summary, detail, evidence) {
22
- this.report({ check, detail, entity, evidence, summary, verdict: "BACKEND_BUG" });
26
+ backend(check, entity, summary, detail, evidence, fixture) {
27
+ this.report(withFixture({ check, detail, entity, evidence, summary, verdict: "BACKEND_BUG" }, fixture));
23
28
  }
24
- security(check, entity, summary, detail, evidence) {
25
- this.report({ check, detail, entity, evidence, summary, verdict: "SECURITY" });
29
+ security(check, entity, summary, detail, evidence, fixture) {
30
+ this.report(withFixture({ check, detail, entity, evidence, summary, verdict: "SECURITY" }, fixture));
26
31
  }
27
- spec(check, entity, summary, detail, evidence) {
28
- this.report({ check, detail, entity, evidence, summary, verdict: "SPEC_BUG" });
32
+ spec(check, entity, summary, detail, evidence, fixture) {
33
+ this.report(withFixture({ check, detail, entity, evidence, summary, verdict: "SPEC_BUG" }, fixture));
29
34
  }
30
- gap(check, entity, summary, detail) {
31
- this.report({ check, detail, entity, evidence: [], summary, verdict: "COVERAGE_GAP" });
35
+ gap(check, entity, summary, detail, fixture) {
36
+ this.report(withFixture({ check, detail, entity, evidence: [], summary, verdict: "COVERAGE_GAP" }, fixture));
32
37
  }
33
38
  blocked(check, entity, summary, cause) {
34
39
  this.report({
@@ -1 +1 @@
1
- {"version":3,"file":"finding.js","sourceRoot":"","sources":["../../src/runtime/finding.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkCH,MAAM,OAAO,gBAAgB;IACnB,QAAQ,GAAc,EAAE,CAAA;IACxB,YAAY,GAAmB,EAAE,CAAA;IAE1C;;;;OAIG;IACH,UAAU,CAAC,KAAa,EAAE,MAAc,EAAE,MAAc;QACvD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QACjD,OAAO,SAAS,CAAA;IACjB,CAAC;IAED,MAAM,CAAC,OAAgB;QACtB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,MAAc,EAAE,QAAoB;QAC3F,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAA;IAClF,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,MAAc,EAAE,QAAoB;QAC5F,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAA;IAC/E,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,MAAc,EAAE,QAAoB;QACxF,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAA;IAC/E,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,MAAc;QACjE,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAA;IACvF,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,KAAa;QACpE,IAAI,CAAC,MAAM,CAAC;YACX,KAAK;YACL,MAAM,EAAE,cAAc,KAAK,EAAE;YAC7B,MAAM;YACN,QAAQ,EAAE,EAAE;YACZ,OAAO;YACP,OAAO,EAAE,SAAS;SAClB,CAAC,CAAA;IACH,CAAC;IAED,MAAM;QACL,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9D,CAAC;IAED,SAAS,CAAC,OAAgB;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAA;IAC1D,CAAC;CACD"}
1
+ {"version":3,"file":"finding.js","sourceRoot":"","sources":["../../src/runtime/finding.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoCH,SAAS,WAAW,CAAC,OAAgB,EAAE,OAAgB;IACtD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,OAAO,CAAA;IAC3D,OAAO,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAA;AAC/B,CAAC;AAED,MAAM,OAAO,gBAAgB;IACnB,QAAQ,GAAc,EAAE,CAAA;IACxB,YAAY,GAAmB,EAAE,CAAA;IAE1C;;;;OAIG;IACH,UAAU,CAAC,KAAa,EAAE,MAAc,EAAE,MAAc;QACvD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QACjD,OAAO,SAAS,CAAA;IACjB,CAAC;IAED,MAAM,CAAC,OAAgB;QACtB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,OAAO,CACN,KAAa,EACb,MAAc,EACd,OAAe,EACf,MAAc,EACd,QAAoB,EACpB,OAAgB;QAEhB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;IACxG,CAAC;IAED,QAAQ,CACP,KAAa,EACb,MAAc,EACd,OAAe,EACf,MAAc,EACd,QAAoB,EACpB,OAAgB;QAEhB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;IACrG,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,MAAc,EAAE,QAAoB,EAAE,OAAgB;QAC1G,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;IACrG,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,MAAc,EAAE,OAAgB;QACnF,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;IAC7G,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,MAAc,EAAE,OAAe,EAAE,KAAa;QACpE,IAAI,CAAC,MAAM,CAAC;YACX,KAAK;YACL,MAAM,EAAE,cAAc,KAAK,EAAE;YAC7B,MAAM;YACN,QAAQ,EAAE,EAAE;YACZ,OAAO;YACP,OAAO,EAAE,SAAS;SAClB,CAAC,CAAA;IACH,CAAC;IAED,MAAM;QACL,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9D,CAAC;IAED,SAAS,CAAC,OAAgB;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAA;IAC1D,CAAC;CACD"}
@@ -48,6 +48,11 @@ export interface RunOptions {
48
48
  query?: QueryCapabilities;
49
49
  /** Per-entity overlays. */
50
50
  entities?: Record<string, EntityConfig>;
51
+ /**
52
+ * Persist every exchange under this run dir (`exchanges.jsonl`, `exchanges/`, `blobs/`).
53
+ * Omit to leave the journal off. The CLI decides the default from the profile.
54
+ */
55
+ exchangeDir?: string;
51
56
  }
52
57
  export interface RunResult {
53
58
  findings: Finding[];
@@ -88,6 +93,10 @@ export interface RunResult {
88
93
  teardown: TeardownReport | null;
89
94
  /** Credentials as they stood after acquire — written to `<outDir>/<datetime>/principals.json` by the CLI. */
90
95
  principals: PersistedPrincipal[];
96
+ /** Journal size when `exchangeDir` was set. */
97
+ exchanges?: {
98
+ count: number;
99
+ };
91
100
  }
92
101
  export declare function run(options: RunOptions): Promise<RunResult>;
93
102
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/runtime/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/runtime/run.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ import { buildModel } from "../spec/graph.js";
9
9
  import { dereference, loadSpec } from "../spec/load.js";
10
10
  import { isAuthFlow } from "../config/define-config.js";
11
11
  import { createPrincipal } from "./auth.js";
12
+ import { createExchangeJournal } from "./exchanges.js";
12
13
  import { resolveBackoff } from "./poll.js";
13
14
  import { persistedToPrincipal, snapshotPrincipal } from "./principals.js";
14
15
  import { CHECKS } from "./checks.js";
@@ -298,8 +299,21 @@ export async function run(options) {
298
299
  url: exchange.url,
299
300
  };
300
301
  };
301
- const onExchange = (exchange) => {
302
+ const journal = options.exchangeDir === undefined ? null : createExchangeJournal(options.exchangeDir);
303
+ const onExchange = async (exchange) => {
302
304
  remember(exchange);
305
+ if (journal !== null) {
306
+ try {
307
+ await journal.record(exchange, {
308
+ ...(currentCheck === undefined ? {} : { check: currentCheck }),
309
+ ...(currentEntity === undefined ? {} : { entity: currentEntity }),
310
+ phase: currentPhase,
311
+ });
312
+ }
313
+ catch {
314
+ /* journal is observability — a write error must not fail the request */
315
+ }
316
+ }
303
317
  publish(snapshot({ omitInflight: true }));
304
318
  const remaining = oldestInflight();
305
319
  if (remaining !== undefined)
@@ -865,6 +879,7 @@ export async function run(options) {
865
879
  profile: profile.name,
866
880
  profileExclusions,
867
881
  teardown,
882
+ ...(journal === null ? {} : { exchanges: { count: journal.count } }),
868
883
  };
869
884
  }
870
885
  async function loadOriginClients(origins, hooks, maxInFlight, globalHeaders, onExchange, httpHooks) {
@@ -910,6 +925,7 @@ async function runSecondaryOrigins(options, persisted, findings, checksRun, chec
910
925
  ...(options.onProgress === undefined ? {} : { onProgress: options.onProgress }),
911
926
  ...(options.query === undefined ? {} : { query: options.query }),
912
927
  ...(options.entities === undefined ? {} : { entities: options.entities }),
928
+ ...(options.exchangeDir === undefined ? {} : { exchangeDir: options.exchangeDir }),
913
929
  });
914
930
  for (const finding of result.findings) {
915
931
  findings.report({ ...finding, origin: origin.id });