@attestry/sdk 0.6.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 (99) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +1269 -0
  3. package/dist/client.d.ts +58 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +74 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/constants.d.ts +7 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +43 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/errors.d.ts +16 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +41 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/index.d.ts +17 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +20 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/lines-parser.d.ts +50 -0
  20. package/dist/lines-parser.d.ts.map +1 -0
  21. package/dist/lines-parser.js +211 -0
  22. package/dist/lines-parser.js.map +1 -0
  23. package/dist/ndjson-parser.d.ts +57 -0
  24. package/dist/ndjson-parser.d.ts.map +1 -0
  25. package/dist/ndjson-parser.js +245 -0
  26. package/dist/ndjson-parser.js.map +1 -0
  27. package/dist/resources/abac-policies.d.ts +1034 -0
  28. package/dist/resources/abac-policies.d.ts.map +1 -0
  29. package/dist/resources/abac-policies.js +1519 -0
  30. package/dist/resources/abac-policies.js.map +1 -0
  31. package/dist/resources/audit-log.d.ts +588 -0
  32. package/dist/resources/audit-log.d.ts.map +1 -0
  33. package/dist/resources/audit-log.js +629 -0
  34. package/dist/resources/audit-log.js.map +1 -0
  35. package/dist/resources/batch.d.ts +845 -0
  36. package/dist/resources/batch.d.ts.map +1 -0
  37. package/dist/resources/batch.js +1074 -0
  38. package/dist/resources/batch.js.map +1 -0
  39. package/dist/resources/chat.d.ts +151 -0
  40. package/dist/resources/chat.d.ts.map +1 -0
  41. package/dist/resources/chat.js +124 -0
  42. package/dist/resources/chat.js.map +1 -0
  43. package/dist/resources/check.d.ts +348 -0
  44. package/dist/resources/check.d.ts.map +1 -0
  45. package/dist/resources/check.js +543 -0
  46. package/dist/resources/check.js.map +1 -0
  47. package/dist/resources/compliance-check.d.ts +330 -0
  48. package/dist/resources/compliance-check.d.ts.map +1 -0
  49. package/dist/resources/compliance-check.js +402 -0
  50. package/dist/resources/compliance-check.js.map +1 -0
  51. package/dist/resources/decisions.d.ts +1208 -0
  52. package/dist/resources/decisions.d.ts.map +1 -0
  53. package/dist/resources/decisions.js +1362 -0
  54. package/dist/resources/decisions.js.map +1 -0
  55. package/dist/resources/evidence-pack.d.ts +1080 -0
  56. package/dist/resources/evidence-pack.d.ts.map +1 -0
  57. package/dist/resources/evidence-pack.js +1789 -0
  58. package/dist/resources/evidence-pack.js.map +1 -0
  59. package/dist/resources/gate.d.ts +613 -0
  60. package/dist/resources/gate.d.ts.map +1 -0
  61. package/dist/resources/gate.js +737 -0
  62. package/dist/resources/gate.js.map +1 -0
  63. package/dist/resources/incidents.d.ts +136 -0
  64. package/dist/resources/incidents.d.ts.map +1 -0
  65. package/dist/resources/incidents.js +229 -0
  66. package/dist/resources/incidents.js.map +1 -0
  67. package/dist/resources/regulatory-changes.d.ts +307 -0
  68. package/dist/resources/regulatory-changes.d.ts.map +1 -0
  69. package/dist/resources/regulatory-changes.js +365 -0
  70. package/dist/resources/regulatory-changes.js.map +1 -0
  71. package/dist/resources/safe-input-read.d.ts +21 -0
  72. package/dist/resources/safe-input-read.d.ts.map +1 -0
  73. package/dist/resources/safe-input-read.js +57 -0
  74. package/dist/resources/safe-input-read.js.map +1 -0
  75. package/dist/resources/ship-gate.d.ts +475 -0
  76. package/dist/resources/ship-gate.d.ts.map +1 -0
  77. package/dist/resources/ship-gate.js +727 -0
  78. package/dist/resources/ship-gate.js.map +1 -0
  79. package/dist/resources/vision.d.ts +540 -0
  80. package/dist/resources/vision.d.ts.map +1 -0
  81. package/dist/resources/vision.js +1036 -0
  82. package/dist/resources/vision.js.map +1 -0
  83. package/dist/retry.d.ts +103 -0
  84. package/dist/retry.d.ts.map +1 -0
  85. package/dist/retry.js +224 -0
  86. package/dist/retry.js.map +1 -0
  87. package/dist/sse-parser.d.ts +64 -0
  88. package/dist/sse-parser.d.ts.map +1 -0
  89. package/dist/sse-parser.js +271 -0
  90. package/dist/sse-parser.js.map +1 -0
  91. package/dist/transport.d.ts +142 -0
  92. package/dist/transport.d.ts.map +1 -0
  93. package/dist/transport.js +455 -0
  94. package/dist/transport.js.map +1 -0
  95. package/dist/types.d.ts +61 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +3 -0
  98. package/dist/types.js.map +1 -0
  99. package/package.json +44 -0
@@ -0,0 +1,629 @@
1
+ // ─── AuditLog resource ──────────────────────────────────────────────────────
2
+ //
3
+ // Wraps the audit-log SIEM export surface (Prompt C.4) + the org-wide
4
+ // audit-log hash-chain verifier (session 19):
5
+ //
6
+ // - GET /api/v1/audit-log/export NDJSON / ECS / CEF stream of audit_log rows
7
+ // - GET /api/v1/audit-chain/verify Org-wide hash-chain integrity verdict
8
+ //
9
+ // First non-decisions resource on `@attestry/sdk`. Sibling to
10
+ // `IncidentsResource`, `DecisionsResource`, `ChatResource`. Two
11
+ // public methods today (`export` + `verifyChain`); the resource class
12
+ // is the landing pad for future audit-log methods if/when the kernel
13
+ // adds them.
14
+ //
15
+ // **`verifyChain()` vs `decisions.verifyChain()`** — DISTINCT surfaces:
16
+ // - `decisions.verifyChain(systemId)` — verifies a SINGLE system's
17
+ // decision chain (per-system hash-chain integrity). Takes a UUID
18
+ // path parameter; emits `ChainVerificationResult` with per-record
19
+ // tampered/broken arrays. Used for security/ops signals on a
20
+ // specific system.
21
+ // - `auditLog.verifyChain()` — verifies the entire ORG's audit log
22
+ // chain (org-wide tamper-evidence). Takes NO arguments; emits
23
+ // `AuditChainVerificationResult` with one `brokenAt` UUID (if any).
24
+ // Used by compliance auditors for end-to-end audit-log integrity.
25
+ // Different responsibility, different kernel route, different consumer
26
+ // audience. The two methods complement each other.
27
+ //
28
+ // Dual-auth admin scope: the kernel route gates on
29
+ // `requireSessionOrApiKey(request, { sessionRoles: ["admin"],
30
+ // apiKeyPermissions: [API_KEY_PERMISSIONS.ADMIN] })` (verified at
31
+ // `src/app/api/v1/audit-log/export/route.ts:66-68`) — the identical
32
+ // dual-auth pattern the abacPolicies cluster uses. The SDK's transport
33
+ // always sends `x-api-key`, so the api-key path is the only one
34
+ // reachable from SDK consumers: **HTTP 401** for no / invalid /
35
+ // expired api-key, **HTTP 403** for a VALID api-key whose permissions
36
+ // do NOT include `ADMIN`. The two are DISTINCT.
37
+ //
38
+ // (Corrected — session-22 hostile review #2. The prior comment claimed
39
+ // "HTTP 401 for both no-auth AND insufficient-permission"; that
40
+ // mis-read the kernel TEST at `audit-log/export/__tests__/route.test.ts`,
41
+ // which MOCKS `AuthError(401)` and never exercises the real
42
+ // `requireSessionOrApiKey` middleware. The middleware's
43
+ // `requireApiKeyWithPermission` path returns 403 for the
44
+ // insufficient-permission case — same surface as every abacPolicies
45
+ // method.)
46
+ //
47
+ // Three wire formats:
48
+ // - `jsonl` (default): one JSON object per line, structured
49
+ // `AuditLogRecord` shape. SDK validates wire shape strictly and
50
+ // yields parsed objects.
51
+ // - `ecs`: one Elastic Common Schema 8.x event per line (JSON-encoded).
52
+ // Rides the same `application/x-ndjson` content-type as `jsonl` —
53
+ // consumers parse the ECS shape themselves; SDK yields `unknown`.
54
+ // - `cef`: one ArcSight CEF v0 line per row. Plain text, NOT JSON.
55
+ // Content-Type: `text/plain`. SDK yields raw `string`.
56
+ //
57
+ // Cursor pagination via response HEADER (`x-attestry-next-cursor`) —
58
+ // NOT a body trailer (asymmetric with `decisions.export`). The SDK
59
+ // auto-paginates by default: the iterator transparently fetches the
60
+ // next page whenever the current page exhausts and the kernel emitted
61
+ // a next-cursor header. Single-page behavior is opt-in via
62
+ // `autoPaginate: false`.
63
+ //
64
+ // Compound cursor format: `<ISO-8601-UTC>:<UUID>`. Bare ISO is a legacy
65
+ // fallback (may skip same-microsecond rows; documented kernel behavior).
66
+ import { AttestryError } from "../errors.js";
67
+ import { parseLinesResponse } from "../lines-parser.js";
68
+ import { parseNDJSONResponse } from "../ndjson-parser.js";
69
+ import { readInputField } from "./safe-input-read.js";
70
+ // Module-load snapshot of `Object.hasOwn` — defends against a
71
+ // late-loading hostile/buggy npm dependency that overrides the global
72
+ // (e.g., `Object.hasOwn = () => true`). Without the snapshot, the
73
+ // prototype-pollution defenses in `validateAuditChainVerificationResponse`
74
+ // would use whatever Object.hasOwn the dependency replaced it with at
75
+ // request time. Snapshotting at module load captures the original
76
+ // implementation BEFORE most consumer code has a chance to monkey-
77
+ // patch.
78
+ //
79
+ // Mirror of `batch.ts` / `gate.ts` / `check.ts` / `compliance-check.ts`
80
+ // pattern. Used on the response side of `verifyChain()` (this method
81
+ // has no input; the input-side defense is N/A — no fields to guard).
82
+ // Carry-forward of session-16 second-hostile-review MEDIUM #3 +
83
+ // session-17 build-round baked-in pattern.
84
+ const objectHasOwn = Object.hasOwn;
85
+ /**
86
+ * Public closed-enum of supported wire formats. Mirrors the kernel's
87
+ * `VALID_FORMATS` const at `src/lib/audit-log/export-helpers.ts:15-19`.
88
+ * Drift-pinned in `src/lib/incidents/__tests__/sdk-drift.test.ts`.
89
+ *
90
+ * Forward-compat: when a future format is added (e.g., `csv`), bump the
91
+ * SDK minor version and extend this array. The kernel's parseFormat
92
+ * function returns 400 for any value outside this set; the SDK
93
+ * pre-rejects invalid values synchronously as `TypeError` (build-round
94
+ * D5 — closed-enum input validates at the SDK boundary so the failure
95
+ * is faster + clearer than waiting for the server's 400).
96
+ */
97
+ export const AUDIT_LOG_EXPORT_FORMATS = Object.freeze([
98
+ "jsonl",
99
+ "ecs",
100
+ "cef",
101
+ ]);
102
+ /**
103
+ * AuditLog resource — sibling to `IncidentsResource`, `DecisionsResource`,
104
+ * `ChatResource`. Today wraps two endpoints (`export` + `verifyChain`);
105
+ * the class is the landing pad for future audit-log methods.
106
+ */
107
+ export class AuditLogResource {
108
+ client;
109
+ constructor(client) {
110
+ this.client = client;
111
+ }
112
+ export(input, options) {
113
+ // Top-level shape — when provided, must be a non-null, non-array
114
+ // object. typeof null === "object" and typeof [] === "object", so
115
+ // guard both explicitly. Unlike decisions.export (which requires
116
+ // `input.systemId`), auditLog.export's input is OPTIONAL — `()`
117
+ // and `(undefined)` are both valid.
118
+ if (input !== undefined) {
119
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
120
+ throw new TypeError("auditLog.export: `input` must be an object when provided");
121
+ }
122
+ // Snapshot each input field via `readInputField` — a throwing
123
+ // accessor surfaces as the documented synchronous `TypeError`
124
+ // rather than the getter's raw exception (session-22 hostile
125
+ // review #1 — the SDK-wide MEDIUM-1 getter-throws fix). The
126
+ // export helper below still receives the original `input` (a
127
+ // throwing getter is caught here first, so it is never reached).
128
+ const format = readInputField(input, "format", "auditLog.export");
129
+ const cursor = readInputField(input, "cursor", "auditLog.export");
130
+ const limit = readInputField(input, "limit", "auditLog.export");
131
+ const autoPaginate = readInputField(input, "autoPaginate", "auditLog.export");
132
+ // format: closed enum. Pre-reject invalid values synchronously
133
+ // (faster + clearer than waiting for server's 400). Build-round D5.
134
+ if (format !== undefined) {
135
+ if (typeof format !== "string" ||
136
+ !AUDIT_LOG_EXPORT_FORMATS.includes(format)) {
137
+ throw new TypeError(`auditLog.export: \`format\` must be one of ${AUDIT_LOG_EXPORT_FORMATS.join(", ")} when provided`);
138
+ }
139
+ }
140
+ // cursor: non-empty string + lone-surrogate guard.
141
+ if (cursor !== undefined) {
142
+ if (typeof cursor !== "string" || cursor.length === 0) {
143
+ throw new TypeError("auditLog.export: `cursor` must be a non-empty string when provided");
144
+ }
145
+ assertEncodableQueryString(cursor, "cursor", "auditLog.export");
146
+ }
147
+ // limit: positive finite integer. NaN / Infinity / fractional /
148
+ // <= 0 rejected. Stricter than kernel's silent coerce-to-1000
149
+ // (build-round D4).
150
+ if (limit !== undefined) {
151
+ if (typeof limit !== "number" ||
152
+ !Number.isInteger(limit) ||
153
+ limit <= 0) {
154
+ throw new TypeError("auditLog.export: `limit` must be a positive integer when provided");
155
+ }
156
+ }
157
+ // autoPaginate: strict boolean.
158
+ if (autoPaginate !== undefined && typeof autoPaginate !== "boolean") {
159
+ throw new TypeError("auditLog.export: `autoPaginate` must be a boolean when provided");
160
+ }
161
+ }
162
+ return runAuditLogExport(this.client, input, options);
163
+ }
164
+ /**
165
+ * Verify the integrity of the org's audit-log hash chain. Returns
166
+ * an `AuditChainVerificationResult` describing whether the chain is
167
+ * intact, and (when broken) the UUID of the entry where verification
168
+ * failed.
169
+ *
170
+ * Wraps `GET /api/v1/audit-chain/verify` — no input, no query
171
+ * parameters, no body. The caller's org is implicit from auth; the
172
+ * kernel fetches up to 5000 audit-log entries ordered ascending by
173
+ * timestamp and runs `verifyAuditChain()` on them.
174
+ *
175
+ * **API-key auth scope** (uses `requireApiKey` DIRECT — distinct
176
+ * from BOTH siblings): the kernel route calls `requireApiKey(request)`
177
+ * at `route.ts:31` with NO permission scoping AND NO subsequent
178
+ * role check. Any valid API key for the org can verify the chain.
179
+ * Returns **HTTP 401** for no/invalid API key; the `requireApiKey`
180
+ * branch does NOT distinguish "no key" from "invalid key". **Note**:
181
+ * `auditLog.export` ALSO calls `requireApiKey(request)` directly at
182
+ * its route but then performs a separate role/permission check
183
+ * (ADMIN-only — see audit-log/export route). `verifyChain()` is
184
+ * distinct: NO role check, NO permission filter. The 403 path is
185
+ * unreachable for this route, and ALL valid api-keys in the org
186
+ * succeed (in contrast to `auditLog.export` where only ADMIN keys
187
+ * succeed).
188
+ *
189
+ * **Kernel-side invariant (session-19 review-3 L2 carry-forward)**:
190
+ * the route at `route.ts:32` reads `apiKeyUser.orgId` and passes
191
+ * it directly to the Drizzle `eq(schema.auditLog.orgId, orgId)`
192
+ * filter without a null-guard. The SDK assumes the kernel's
193
+ * `requireApiKey` returns an `ApiKeyUser` with a non-null `orgId`
194
+ * (i.e., the `apiKeys` table's `orgId` column is NOT NULL). If
195
+ * a future schema migration relaxes that constraint, the route
196
+ * could match zero rows on a malformed key and return a vacuous-
197
+ * truth `valid: true` verdict, masking actual chain tampering.
198
+ * This is a kernel-side hardening concern (SDK cannot detect
199
+ * it from the wire); flagged here so a future kernel-hardening
200
+ * audit knows to add a runtime guard in `requireApiKey`.
201
+ *
202
+ * **CRITICAL contract — does NOT throw on `valid: false`** (carry-
203
+ * forward invariant #12). The kernel returns HTTP 200 with
204
+ * `valid: false` on a tampered chain; the SDK MUST resolve the
205
+ * Promise with the verdict body. Top-level structural failures
206
+ * (auth, rate limit, internal) throw `AttestryAPIError`. Mirror of
207
+ * `decisions.verifyChain`'s same contract.
208
+ *
209
+ * **NO `writeAuditLog` side effect** — the verifier is quiet
210
+ * (asymmetric with `gate.evaluate` / `batch.submit` which both write
211
+ * audit-log entries). Writing to the audit log while verifying it
212
+ * would be ironic; the kernel team avoided this. `auditLog.verifyChain`
213
+ * is a pure read.
214
+ *
215
+ * **Silent kernel-side truncation at 5000 entries** (invariant #50).
216
+ * The kernel's audit-log fetch is capped at 5000 entries
217
+ * (`route.ts:51`: `.limit(5000)`). For an org with more than 5000
218
+ * audit-log entries, only the OLDEST 5000 are verified by this call.
219
+ * The kernel does NOT emit a "truncated" flag — `totalEntries`
220
+ * equals the number of rows fetched, NOT the org's full audit-log
221
+ * row count. **Documented kernel surface gap**; the SDK does NOT
222
+ * mask. Consumers with high-volume audit logs should be aware that
223
+ * the kernel's verifier sees a stale window of the chain. A future
224
+ * kernel pagination or higher limit would be additive (the SDK
225
+ * forwards `totalEntries` verbatim).
226
+ *
227
+ * **Kernel-side 30-second timeout** (`maxDuration = 30` at
228
+ * `route.ts:14`). The SDK does NOT enforce a client-side timeout
229
+ * (consumers manage via `options.signal`), but the kernel's
230
+ * function-runtime cap bounds the verification latency on the
231
+ * server side. Cron-job consumers should budget call latency
232
+ * relative to this cap — a near-5000-entry verification can take
233
+ * tens of seconds under high SHA-256 load. A future kernel raise
234
+ * (e.g., 30 → 60s) would relax this cap; downstream cron-job
235
+ * sizing assumptions should be revisited.
236
+ *
237
+ * **Pollution-safe discriminator pattern** — branch on
238
+ * `result.valid` (closed-enum boolean) to detect a broken chain,
239
+ * NOT on `result.brokenAt === undefined`. The kernel emits
240
+ * `brokenAt` as an OWN-PROPERTY of the response only when the
241
+ * chain is broken; on a valid chain it's omitted entirely (kernel
242
+ * uses a conditional spread at `route.ts:72`). Under
243
+ * `Object.prototype.brokenAt = <value>` pollution, the equality
244
+ * check walks the prototype and reads the polluted value —
245
+ * returning false (i.e., "field is present") even when the
246
+ * own-property is genuinely absent. The SDK's response-side
247
+ * validator uses `Object.hasOwn` (snapshotted at module load) to
248
+ * defend against this; consumers should use `result.valid`
249
+ * directly. Carry-forward of session-17 first-hostile-review
250
+ * MEDIUM #3 + session-18 build-round baked-in pattern.
251
+ *
252
+ * **Errors** — ordered by kernel firing precedence (rate-limit →
253
+ * auth-pass-or-401 → DB fetch → verifier → 500-catchall):
254
+ * - `AttestryAPIError` (status 429) — rate limit FIRES FIRST
255
+ * (auto-retried by default — invariant #18; per-IP rate-limit
256
+ * key `audit-chain-verify:${ip}` against the standard
257
+ * `apiLimiter`).
258
+ * - `AttestryAPIError` (status 401) — no API key OR invalid key.
259
+ * Single 401 surface (NO 403 — the route has no permission
260
+ * filter). Surfaces only when `requireApiKey` throws an
261
+ * `AuthError`; the route's catch (route.ts:74-77) propagates
262
+ * `error.statusCode` (401 for `AuthError`).
263
+ * - `AttestryAPIError` (status 500) — internal kernel error
264
+ * (scrubbed message via `internalErrorResponse`). Surfaces
265
+ * when the DB connection drops mid-fetch, the verifier
266
+ * throws, OR `requireApiKey`'s INFRASTRUCTURE fails (e.g., a
267
+ * DB error during the API-key lookup, not an auth-rejection;
268
+ * non-`AuthError` errors fall through to the route's
269
+ * `internalErrorResponse` catchall at route.ts:78).
270
+ * - `AttestryError` ("request aborted by caller") — caller-
271
+ * supplied `options.signal` fired (pre-aborted or mid-flight).
272
+ * - `AttestryError` (P2 hardening) — kernel response failed
273
+ * SDK-side shape validation. See "Response-shape validation"
274
+ * below.
275
+ * - `AttestryAPIError` (P3 hardening) — kernel response had a
276
+ * wrong Content-Type (transport-level guard).
277
+ *
278
+ * **Notably ABSENT from the error surface**:
279
+ * - **No 400** — this method has no input; nothing to reject for
280
+ * malformed input. The route doesn't parse query params or
281
+ * body.
282
+ * - **No 402 plan-limit** — verifyChain is a READ; no quota.
283
+ * - **No 403** — no permission filter on the route (any key with
284
+ * a valid org binding succeeds). Asymmetric with
285
+ * `auditLog.export` (which gates on ADMIN role).
286
+ * - **No 404** — orgId is implicit from auth; no path/query
287
+ * parameters that could mismatch.
288
+ * - **No 413** — the kernel's `.limit(5000)` silently caps the
289
+ * fetch; oversize orgs see a truncated verification (NOT a
290
+ * 413). Documented kernel surface gap.
291
+ * - **No 422** — no Zod schema (no body, no query).
292
+ * - **No TypeError from SDK** — this method has no input to
293
+ * validate.
294
+ *
295
+ * **Response-shape validation** (P2 hardening — symmetric defense
296
+ * on response side via the module-load `objectHasOwn` snapshot;
297
+ * mirror of `batch.ts` / `gate.ts` patterns):
298
+ * - Rejects with `AttestryError` if the response isn't a non-null,
299
+ * non-array object.
300
+ * - Rejects if `valid` isn't a boolean.
301
+ * - Rejects if `entriesVerified` / `totalEntries` aren't numbers.
302
+ * - Rejects if `firstEntry` / `lastEntry` aren't `null` OR a
303
+ * string.
304
+ * - Rejects if `brokenAt` is OWN-PROPERTY present but NOT a
305
+ * string. (When absent, the field is forward-compatibly
306
+ * undefined — kernel omits it on valid chains.)
307
+ * - Each response field read goes through the module-load
308
+ * `objectHasOwn` snapshot — defends against
309
+ * `Object.prototype.<field>` pollution masking a missing field.
310
+ *
311
+ * **Transport-shape validation** (P3 hardening):
312
+ * - Rejects with `AttestryAPIError` if the kernel responds with
313
+ * a non-`application/json` Content-Type. NOTE: `valid: false`
314
+ * is a normal 200 response and resolves the promise (carry-
315
+ * forward invariant #12); only structural failures throw.
316
+ *
317
+ * @example Detect a tampered audit log
318
+ * ```ts
319
+ * const verdict = await client.auditLog.verifyChain();
320
+ * if (!verdict.valid) {
321
+ * // brokenAt is an OWN-PROPERTY only on broken chains.
322
+ * await notifySecurity({
323
+ * entryId: verdict.brokenAt,
324
+ * verifiedUpTo: verdict.entriesVerified,
325
+ * totalEntries: verdict.totalEntries,
326
+ * });
327
+ * }
328
+ * console.log(`Verified ${verdict.entriesVerified}/${verdict.totalEntries} entries`);
329
+ * ```
330
+ *
331
+ * @example Schedule periodic verification (cron job)
332
+ * ```ts
333
+ * // Run hourly from a cron — surfaces tampering within an hour
334
+ * // of occurrence (high-frequency monitoring for compliance-
335
+ * // critical orgs).
336
+ * try {
337
+ * const verdict = await client.auditLog.verifyChain();
338
+ * if (!verdict.valid) {
339
+ * await pageOncall({ brokenAt: verdict.brokenAt });
340
+ * }
341
+ * } catch (err) {
342
+ * if (err instanceof AttestryAPIError && err.status === 429) {
343
+ * // Back off — verifier is rate-limited per IP.
344
+ * return;
345
+ * }
346
+ * throw err;
347
+ * }
348
+ * ```
349
+ */
350
+ verifyChain(options) {
351
+ // No input → no SDK-side input validation. Mirror of decisions'
352
+ // `verifyChain(systemId)` minus the path-segment validation.
353
+ return this.client
354
+ ._request({
355
+ method: "GET",
356
+ path: "/api/v1/audit-chain/verify",
357
+ options,
358
+ })
359
+ .then((result) => validateAuditChainVerificationResponse(result));
360
+ }
361
+ }
362
+ /**
363
+ * Synchronously verify a query-string value is encodable via
364
+ * `encodeURIComponent`. Mirrors the helper at `decisions.ts` (carry-
365
+ * forward invariant #32 — URIError defect-class is uniformly handled).
366
+ *
367
+ * Duplicated rather than shared because cross-resource imports between
368
+ * `audit-log.ts` and `decisions.ts` would create a graph cycle hazard
369
+ * — both files want to remain leaf-resource modules. A future SDK
370
+ * refactor may extract validation helpers to a shared module
371
+ * (e.g., `src/validate.ts`) when a third caller shows up; for now the
372
+ * duplication is intentional and documented.
373
+ */
374
+ function assertEncodableQueryString(value, fieldName, methodName) {
375
+ try {
376
+ encodeURIComponent(value);
377
+ }
378
+ catch (err) {
379
+ throw new TypeError(`${methodName}: \`${fieldName}\` contains invalid UTF-16 sequences (${
380
+ // encodeURIComponent always throws URIError (an Error subclass),
381
+ // so the String(err) branch is unreachable. Defense-in-depth
382
+ // marker for the v8 coverage tool.
383
+ /* v8 ignore next */
384
+ err instanceof Error ? err.message : String(err)})`, { cause: err });
385
+ }
386
+ }
387
+ /**
388
+ * Internal — async generator backing `auditLog.export`. Lazy: the
389
+ * request is NOT issued until the first iteration.
390
+ *
391
+ * Auto-pagination loop: each iteration fetches one page; in
392
+ * `autoPaginate: true` (the default), continues until the kernel stops
393
+ * emitting `x-attestry-next-cursor`. Each page's INITIAL fetch goes
394
+ * through the retry middleware (429 + Retry-After). Mid-stream errors
395
+ * bubble per invariant #20.
396
+ *
397
+ * Format dispatch:
398
+ * - `cef` → `parseLinesResponse` (raw line splitter; yields strings)
399
+ * - `jsonl` → `parseNDJSONResponse` + per-row shape validation; yields
400
+ * `AuditLogRecord`. The SDK is the typed boundary — a malformed row
401
+ * (schema bug, version skew) throws `AttestryError` rather than
402
+ * yielding `undefined as string`.
403
+ * - `ecs` → `parseNDJSONResponse`; yields `unknown` (consumer parses
404
+ * ECS event shape themselves).
405
+ */
406
+ async function* runAuditLogExport(client, input, options) {
407
+ const format = input?.format ?? "jsonl";
408
+ const autoPaginate = input?.autoPaginate ?? true;
409
+ // The transport's `expectedContentType` guard runs per-request;
410
+ // jsonl/ecs ride `application/x-ndjson`, cef rides `text/plain`.
411
+ // Drives both the `Accept:` request header AND the response
412
+ // content-type fail-fast guard (single source of truth).
413
+ const expectedContentType = format === "cef" ? "text/plain" : "application/x-ndjson";
414
+ let cursor = input?.cursor;
415
+ while (true) {
416
+ // Build query — `format` always, `cursor` and `limit` only when
417
+ // provided. `encodeQuery` skips `undefined` values.
418
+ const query = {
419
+ format,
420
+ cursor,
421
+ limit: input?.limit,
422
+ };
423
+ const response = await client._streamRequest({
424
+ path: "/api/v1/audit-log/export",
425
+ query,
426
+ options,
427
+ expectedContentType,
428
+ });
429
+ if (format === "cef") {
430
+ // Raw line splitter — yields strings.
431
+ for await (const line of parseLinesResponse(response)) {
432
+ yield line;
433
+ }
434
+ }
435
+ else if (format === "ecs") {
436
+ // ECS rides NDJSON; SDK doesn't enforce ECS shape — consumers
437
+ // parse via their own ECS schema. Forward-compatible with
438
+ // future ECS-version additions.
439
+ for await (const raw of parseNDJSONResponse(response)) {
440
+ yield raw;
441
+ }
442
+ }
443
+ else {
444
+ // jsonl — validate AuditLogRecord shape per row.
445
+ for await (const raw of parseNDJSONResponse(response)) {
446
+ // Every NDJSON line must be a JSON object — neither primitives
447
+ // nor arrays nor nulls are valid rows. Defensive: kernel always
448
+ // emits objects, but a parser yielding e.g. a bare number would
449
+ // otherwise pass through as `frame` of type `unknown`.
450
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
451
+ throw new AttestryError("auditLog.export: NDJSON line was not a JSON object");
452
+ }
453
+ const obj = raw;
454
+ // Validate per-row shape. The SDK is the typed boundary — a
455
+ // malformed row (schema bug, version skew) throws here rather
456
+ // than yielding `undefined as string` to the caller. Same
457
+ // invariant as decisions.export's per-record validation.
458
+ if (typeof obj.id !== "string" ||
459
+ typeof obj.timestamp !== "string" ||
460
+ typeof obj.orgId !== "string" ||
461
+ (obj.userId !== null && typeof obj.userId !== "string") ||
462
+ typeof obj.action !== "string" ||
463
+ (obj.resourceType !== null && typeof obj.resourceType !== "string") ||
464
+ (obj.resourceId !== null && typeof obj.resourceId !== "string") ||
465
+ // `details` is `unknown` (jsonb) — pass through as-is.
466
+ (obj.ipAddress !== null && typeof obj.ipAddress !== "string") ||
467
+ (obj.userAgent !== null && typeof obj.userAgent !== "string") ||
468
+ (obj.sessionId !== null && typeof obj.sessionId !== "string") ||
469
+ (obj.entryHash !== null && typeof obj.entryHash !== "string") ||
470
+ (obj.previousEntryHash !== null &&
471
+ typeof obj.previousEntryHash !== "string")) {
472
+ throw new AttestryError("auditLog.export: NDJSON record missing required fields or wrong type");
473
+ }
474
+ yield {
475
+ id: obj.id,
476
+ timestamp: obj.timestamp,
477
+ orgId: obj.orgId,
478
+ userId: obj.userId,
479
+ action: obj.action,
480
+ resourceType: obj.resourceType,
481
+ resourceId: obj.resourceId,
482
+ details: obj.details,
483
+ ipAddress: obj.ipAddress,
484
+ userAgent: obj.userAgent,
485
+ sessionId: obj.sessionId,
486
+ entryHash: obj.entryHash,
487
+ previousEntryHash: obj.previousEntryHash,
488
+ };
489
+ }
490
+ }
491
+ // Pagination decision. The cursor lives in the response HEADER
492
+ // (NOT a body trailer — asymmetric with decisions.export, build-
493
+ // round D8). After draining the body, read the header. If absent
494
+ // OR autoPaginate is false, exit. Otherwise feed the cursor back
495
+ // into the next page's query.
496
+ const nextCursor = response.headers.get("x-attestry-next-cursor");
497
+ if (!autoPaginate || nextCursor === null) {
498
+ return;
499
+ }
500
+ cursor = nextCursor;
501
+ }
502
+ }
503
+ /**
504
+ * P2 hardening: validate the `verifyChain()` response's 5 always-
505
+ * present fields plus the optional `brokenAt` field. Symmetric
506
+ * prototype-pollution defense — read EACH field via the module-load
507
+ * `objectHasOwn` snapshot so a hostile npm dep polluting
508
+ * `Object.prototype.<field>` cannot mask a kernel regression that
509
+ * drops the field (per session-16 second-hostile-review MEDIUM #3
510
+ * carry-forward — defense applied on the response boundary even when
511
+ * the input boundary is empty).
512
+ *
513
+ * Returns the validated `result` (typed `AuditChainVerificationResult`)
514
+ * on success; throws `AttestryError` on any shape violation. Extracted
515
+ * as a free function so the resource method body stays focused on
516
+ * request construction.
517
+ *
518
+ * **`brokenAt` is INTENTIONALLY omitted from the wire on valid chains**
519
+ * — the kernel uses a conditional spread
520
+ * `...(result.brokenAtId ? { brokenAt: result.brokenAtId } : {})` at
521
+ * `route.ts:72`. When `valid: true`, the field is NOT an own-property
522
+ * of the response. The validator checks `objectHasOwn` BEFORE
523
+ * type-checking, so absent-and-untyped is forward-compatible —
524
+ * present-but-non-string is the actual regression signal.
525
+ *
526
+ * **Number-field validation is `typeof X === "number"` ONLY**
527
+ * (session-19 review-2 LOW-2 carry-forward — faithful-courier
528
+ * documented asymmetry). The check accepts `NaN`, `Infinity`,
529
+ * `-Infinity`, `-0`, and `MAX_SAFE_INTEGER+1` (which loses
530
+ * precision) — these would all pass `typeof === "number"`. This
531
+ * is INTENTIONAL: JSON.parse on a kernel-emitted JSON string can
532
+ * NEVER produce NaN / Infinity (JSON spec doesn't represent them);
533
+ * `-0` and large numbers round-trip with whatever precision the
534
+ * JSON gave. Tightening to `Number.isFinite` / `Number.isInteger`
535
+ * would be a stricter contract than the kernel emits — the SDK
536
+ * stays faithful-courier on numbers (symmetric with batch /
537
+ * decisions / gate's response validators). **If a future wire
538
+ * format (msgpack, CBOR) is added, this asymmetry must be
539
+ * revisited** — the new wire could carry NaN literally, and the
540
+ * faithful-courier semantic would leak NaN to consumers.
541
+ *
542
+ * **Single-field rejection semantics** (session-19 review-3 M1
543
+ * carry-forward — UX/diagnostic clarification). The validator
544
+ * checks fields SEQUENTIALLY in declaration order (valid →
545
+ * entriesVerified → totalEntries → firstEntry → lastEntry →
546
+ * brokenAt) and throws on the FIRST failing field. If a kernel
547
+ * regression drops MULTIPLE fields at once, the consumer sees
548
+ * ONLY the first failing field's diagnostic — they must fix
549
+ * the fixture and re-run to surface the next failure. This
550
+ * matches batch.ts / gate.ts / check.ts patterns (project
551
+ * convention for response-shape validators); accumulating into
552
+ * a multi-field message would diverge from the rest of the SDK.
553
+ * Trade-off accepted: consistency-with-project-pattern wins
554
+ * over single-cycle full-diagnostic.
555
+ */
556
+ function validateAuditChainVerificationResponse(result) {
557
+ if (result === null ||
558
+ typeof result !== "object" ||
559
+ Array.isArray(result)) {
560
+ throw new AttestryError(`auditLog.verifyChain: expected an object response from the kernel ` +
561
+ `(got ${describeType(result)})`);
562
+ }
563
+ const obj = result;
564
+ const valid = objectHasOwn(obj, "valid") ? obj.valid : undefined;
565
+ if (typeof valid !== "boolean") {
566
+ throw new AttestryError(`auditLog.verifyChain: expected response.valid to be a boolean ` +
567
+ `(got ${describeType(valid)})`);
568
+ }
569
+ const entriesVerified = objectHasOwn(obj, "entriesVerified")
570
+ ? obj.entriesVerified
571
+ : undefined;
572
+ if (typeof entriesVerified !== "number") {
573
+ throw new AttestryError(`auditLog.verifyChain: expected response.entriesVerified to be a number ` +
574
+ `(got ${describeType(entriesVerified)})`);
575
+ }
576
+ const totalEntries = objectHasOwn(obj, "totalEntries")
577
+ ? obj.totalEntries
578
+ : undefined;
579
+ if (typeof totalEntries !== "number") {
580
+ throw new AttestryError(`auditLog.verifyChain: expected response.totalEntries to be a number ` +
581
+ `(got ${describeType(totalEntries)})`);
582
+ }
583
+ const firstEntry = objectHasOwn(obj, "firstEntry")
584
+ ? obj.firstEntry
585
+ : undefined;
586
+ if (firstEntry !== null && typeof firstEntry !== "string") {
587
+ throw new AttestryError(`auditLog.verifyChain: expected response.firstEntry to be a string or null ` +
588
+ `(got ${describeType(firstEntry)})`);
589
+ }
590
+ const lastEntry = objectHasOwn(obj, "lastEntry")
591
+ ? obj.lastEntry
592
+ : undefined;
593
+ if (lastEntry !== null && typeof lastEntry !== "string") {
594
+ throw new AttestryError(`auditLog.verifyChain: expected response.lastEntry to be a string or null ` +
595
+ `(got ${describeType(lastEntry)})`);
596
+ }
597
+ // `brokenAt` is OPTIONAL — kernel omits it entirely on valid chains.
598
+ // Only enforce the type guard when the field is an own-property of
599
+ // the response. Absent-AND-untyped is the valid-chain shape.
600
+ if (objectHasOwn(obj, "brokenAt")) {
601
+ const brokenAt = obj.brokenAt;
602
+ if (typeof brokenAt !== "string") {
603
+ throw new AttestryError(`auditLog.verifyChain: expected response.brokenAt to be a string when present ` +
604
+ `(got ${describeType(brokenAt)})`);
605
+ }
606
+ }
607
+ return result;
608
+ }
609
+ /**
610
+ * Human-readable type description for error messages. Distinguishes
611
+ * `null` and `array` from generic `object`. Duplicated in
612
+ * `decisions.ts`, `incidents.ts`, `regulatory-changes.ts`,
613
+ * `compliance-check.ts`, `check.ts`, `gate.ts`, `batch.ts` per
614
+ * project pattern (small helper, leaf-resource modules, no shared
615
+ * module yet).
616
+ *
617
+ * All four branches are reachable through `validateAuditChainVerificationResponse`'s
618
+ * call sites: top-level shape check (null + array + non-object scalar),
619
+ * per-field type guards (each field's `describeType(<wrong type>)`
620
+ * exercised by tests).
621
+ */
622
+ function describeType(value) {
623
+ if (value === null)
624
+ return "null";
625
+ if (Array.isArray(value))
626
+ return "array";
627
+ return typeof value;
628
+ }
629
+ //# sourceMappingURL=audit-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-log.js","sourceRoot":"","sources":["../../src/resources/audit-log.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,sEAAsE;AACtE,8CAA8C;AAC9C,EAAE;AACF,uFAAuF;AACvF,iFAAiF;AACjF,EAAE;AACF,8DAA8D;AAC9D,gEAAgE;AAChE,sEAAsE;AACtE,qEAAqE;AACrE,aAAa;AACb,EAAE;AACF,wEAAwE;AACxE,qEAAqE;AACrE,qEAAqE;AACrE,sEAAsE;AACtE,iEAAiE;AACjE,uBAAuB;AACvB,qEAAqE;AACrE,kEAAkE;AAClE,wEAAwE;AACxE,sEAAsE;AACtE,uEAAuE;AACvE,mDAAmD;AACnD,EAAE;AACF,mDAAmD;AACnD,8DAA8D;AAC9D,kEAAkE;AAClE,oEAAoE;AACpE,uEAAuE;AACvE,gEAAgE;AAChE,gEAAgE;AAChE,sEAAsE;AACtE,gDAAgD;AAChD,EAAE;AACF,uEAAuE;AACvE,gEAAgE;AAChE,0EAA0E;AAC1E,4DAA4D;AAC5D,wDAAwD;AACxD,yDAAyD;AACzD,oEAAoE;AACpE,WAAW;AACX,EAAE;AACF,sBAAsB;AACtB,8DAA8D;AAC9D,oEAAoE;AACpE,6BAA6B;AAC7B,0EAA0E;AAC1E,sEAAsE;AACtE,sEAAsE;AACtE,qEAAqE;AACrE,2DAA2D;AAC3D,EAAE;AACF,qEAAqE;AACrE,mEAAmE;AACnE,oEAAoE;AACpE,sEAAsE;AACtE,2DAA2D;AAC3D,yBAAyB;AACzB,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AAGzE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,8DAA8D;AAC9D,sEAAsE;AACtE,kEAAkE;AAClE,2EAA2E;AAC3E,sEAAsE;AACtE,kEAAkE;AAClE,mEAAmE;AACnE,SAAS;AACT,EAAE;AACF,wEAAwE;AACxE,qEAAqE;AACrE,qEAAqE;AACrE,gEAAgE;AAChE,2CAA2C;AAC3C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;AAEnC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;IACpD,OAAO;IACP,KAAK;IACL,KAAK;CACG,CAAC,CAAC;AA0OZ;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;IAAG,CAAC;IA2JvD,MAAM,CACJ,KAA2B,EAC3B,OAAwB;QAExB,iEAAiE;QACjE,kEAAkE;QAClE,iEAAiE;QACjE,gEAAgE;QAChE,oCAAoC;QACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxE,MAAM,IAAI,SAAS,CAAC,0DAA0D,CAAC,CAAC;YAClF,CAAC;YACD,8DAA8D;YAC9D,8DAA8D;YAC9D,6DAA6D;YAC7D,4DAA4D;YAC5D,6DAA6D;YAC7D,iEAAiE;YACjE,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;YAChE,MAAM,YAAY,GAAG,cAAc,CACjC,KAAK,EACL,cAAc,EACd,iBAAiB,CAClB,CAAC;YACF,+DAA+D;YAC/D,oEAAoE;YACpE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,IACE,OAAO,MAAM,KAAK,QAAQ;oBAC1B,CAAE,wBAA8C,CAAC,QAAQ,CAAC,MAAM,CAAC,EACjE,CAAC;oBACD,MAAM,IAAI,SAAS,CACjB,8CAA8C,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAClG,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,mDAAmD;YACnD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtD,MAAM,IAAI,SAAS,CACjB,oEAAoE,CACrE,CAAC;gBACJ,CAAC;gBACD,0BAA0B,CAAC,MAAM,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YAClE,CAAC;YACD,gEAAgE;YAChE,8DAA8D;YAC9D,oBAAoB;YACpB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IACE,OAAO,KAAK,KAAK,QAAQ;oBACzB,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;oBACxB,KAAK,IAAI,CAAC,EACV,CAAC;oBACD,MAAM,IAAI,SAAS,CACjB,mEAAmE,CACpE,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,gCAAgC;YAChC,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,YAAY,KAAK,SAAS,EAAE,CAAC;gBACpE,MAAM,IAAI,SAAS,CACjB,iEAAiE,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyLG;IACH,WAAW,CACT,OAAwB;QAExB,gEAAgE;QAChE,6DAA6D;QAC7D,OAAO,IAAI,CAAC,MAAM;aACf,QAAQ,CAA+B;YACtC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,4BAA4B;YAClC,OAAO;SACR,CAAC;aACD,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,sCAAsC,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,SAAS,0BAA0B,CACjC,KAAa,EACb,SAAiB,EACjB,UAAkB;IAElB,IAAI,CAAC;QACH,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CACjB,GAAG,UAAU,OAAO,SAAS,yCAAyC;QACpE,iEAAiE;QACjE,6DAA6D;QAC7D,mCAAmC;QACnC,oBAAoB;QACpB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,GAAG,EACH,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,KAAK,SAAS,CAAC,CAAC,iBAAiB,CAC/B,MAAsB,EACtB,KAAsC,EACtC,OAAmC;IAEnC,MAAM,MAAM,GAAyB,KAAK,EAAE,MAAM,IAAI,OAAO,CAAC;IAC9D,MAAM,YAAY,GAAG,KAAK,EAAE,YAAY,IAAI,IAAI,CAAC;IAEjD,gEAAgE;IAChE,iEAAiE;IACjE,4DAA4D;IAC5D,yDAAyD;IACzD,MAAM,mBAAmB,GACvB,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,sBAAsB,CAAC;IAE3D,IAAI,MAAM,GAAuB,KAAK,EAAE,MAAM,CAAC;IAE/C,OAAO,IAAI,EAAE,CAAC;QACZ,gEAAgE;QAChE,oDAAoD;QACpD,MAAM,KAAK,GAAgD;YACzD,MAAM;YACN,MAAM;YACN,KAAK,EAAE,KAAK,EAAE,KAAK;SACpB,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;YAC3C,IAAI,EAAE,0BAA0B;YAChC,KAAK;YACL,OAAO;YACP,mBAAmB;SACpB,CAAC,CAAC;QAEH,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,sCAAsC;YACtC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,CAAC;YACb,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YAC5B,8DAA8D;YAC9D,0DAA0D;YAC1D,gCAAgC;YAChC,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,iDAAiD;YACjD,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtD,+DAA+D;gBAC/D,gEAAgE;gBAChE,gEAAgE;gBAChE,uDAAuD;gBACvD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;oBAClE,MAAM,IAAI,aAAa,CACrB,oDAAoD,CACrD,CAAC;gBACJ,CAAC;gBACD,MAAM,GAAG,GAAG,GAA8B,CAAC;gBAC3C,4DAA4D;gBAC5D,8DAA8D;gBAC9D,0DAA0D;gBAC1D,yDAAyD;gBACzD,IACE,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;oBAC1B,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ;oBACjC,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;oBAC7B,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC;oBACvD,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ;oBAC9B,CAAC,GAAG,CAAC,YAAY,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,CAAC;oBACnE,CAAC,GAAG,CAAC,UAAU,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC;oBAC/D,uDAAuD;oBACvD,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC;oBAC7D,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC;oBAC7D,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC;oBAC7D,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC;oBAC7D,CAAC,GAAG,CAAC,iBAAiB,KAAK,IAAI;wBAC7B,OAAO,GAAG,CAAC,iBAAiB,KAAK,QAAQ,CAAC,EAC5C,CAAC;oBACD,MAAM,IAAI,aAAa,CACrB,sEAAsE,CACvE,CAAC;gBACJ,CAAC;gBACD,MAAM;oBACJ,EAAE,EAAE,GAAG,CAAC,EAAE;oBACV,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,MAAM,EAAE,GAAG,CAAC,MAAuB;oBACnC,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,YAAY,EAAE,GAAG,CAAC,YAA6B;oBAC/C,UAAU,EAAE,GAAG,CAAC,UAA2B;oBAC3C,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,SAAS,EAAE,GAAG,CAAC,SAA0B;oBACzC,SAAS,EAAE,GAAG,CAAC,SAA0B;oBACzC,SAAS,EAAE,GAAG,CAAC,SAA0B;oBACzC,SAAS,EAAE,GAAG,CAAC,SAA0B;oBACzC,iBAAiB,EAAE,GAAG,CAAC,iBAAkC;iBAC1D,CAAC;YACJ,CAAC;QACH,CAAC;QAED,+DAA+D;QAC/D,iEAAiE;QACjE,iEAAiE;QACjE,iEAAiE;QACjE,8BAA8B;QAC9B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACzC,OAAO;QACT,CAAC;QACD,MAAM,GAAG,UAAU,CAAC;IACtB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,SAAS,sCAAsC,CAC7C,MAAe;IAEf,IACE,MAAM,KAAK,IAAI;QACf,OAAO,MAAM,KAAK,QAAQ;QAC1B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EACrB,CAAC;QACD,MAAM,IAAI,aAAa,CACrB,oEAAoE;YAClE,QAAQ,YAAY,CAAC,MAAM,CAAC,GAAG,CAClC,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,MAAiC,CAAC;IAE9C,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,aAAa,CACrB,gEAAgE;YAC9D,QAAQ,YAAY,CAAC,KAAK,CAAC,GAAG,CACjC,CAAC;IACJ,CAAC;IACD,MAAM,eAAe,GAAG,YAAY,CAAC,GAAG,EAAE,iBAAiB,CAAC;QAC1D,CAAC,CAAC,GAAG,CAAC,eAAe;QACrB,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,OAAO,eAAe,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,IAAI,aAAa,CACrB,yEAAyE;YACvE,QAAQ,YAAY,CAAC,eAAe,CAAC,GAAG,CAC3C,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,EAAE,cAAc,CAAC;QACpD,CAAC,CAAC,GAAG,CAAC,YAAY;QAClB,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,IAAI,aAAa,CACrB,sEAAsE;YACpE,QAAQ,YAAY,CAAC,YAAY,CAAC,GAAG,CACxC,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC;QAChD,CAAC,CAAC,GAAG,CAAC,UAAU;QAChB,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,UAAU,KAAK,IAAI,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,aAAa,CACrB,4EAA4E;YAC1E,QAAQ,YAAY,CAAC,UAAU,CAAC,GAAG,CACtC,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,EAAE,WAAW,CAAC;QAC9C,CAAC,CAAC,GAAG,CAAC,SAAS;QACf,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QACxD,MAAM,IAAI,aAAa,CACrB,2EAA2E;YACzE,QAAQ,YAAY,CAAC,SAAS,CAAC,GAAG,CACrC,CAAC;IACJ,CAAC;IACD,qEAAqE;IACrE,mEAAmE;IACnE,6DAA6D;IAC7D,IAAI,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC9B,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,aAAa,CACrB,+EAA+E;gBAC7E,QAAQ,YAAY,CAAC,QAAQ,CAAC,GAAG,CACpC,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,MAAsC,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACzC,OAAO,OAAO,KAAK,CAAC;AACtB,CAAC"}