@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.
- package/LICENSE +190 -0
- package/README.md +1269 -0
- package/dist/client.d.ts +58 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +74 -0
- package/dist/client.js.map +1 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +43 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/lines-parser.d.ts +50 -0
- package/dist/lines-parser.d.ts.map +1 -0
- package/dist/lines-parser.js +211 -0
- package/dist/lines-parser.js.map +1 -0
- package/dist/ndjson-parser.d.ts +57 -0
- package/dist/ndjson-parser.d.ts.map +1 -0
- package/dist/ndjson-parser.js +245 -0
- package/dist/ndjson-parser.js.map +1 -0
- package/dist/resources/abac-policies.d.ts +1034 -0
- package/dist/resources/abac-policies.d.ts.map +1 -0
- package/dist/resources/abac-policies.js +1519 -0
- package/dist/resources/abac-policies.js.map +1 -0
- package/dist/resources/audit-log.d.ts +588 -0
- package/dist/resources/audit-log.d.ts.map +1 -0
- package/dist/resources/audit-log.js +629 -0
- package/dist/resources/audit-log.js.map +1 -0
- package/dist/resources/batch.d.ts +845 -0
- package/dist/resources/batch.d.ts.map +1 -0
- package/dist/resources/batch.js +1074 -0
- package/dist/resources/batch.js.map +1 -0
- package/dist/resources/chat.d.ts +151 -0
- package/dist/resources/chat.d.ts.map +1 -0
- package/dist/resources/chat.js +124 -0
- package/dist/resources/chat.js.map +1 -0
- package/dist/resources/check.d.ts +348 -0
- package/dist/resources/check.d.ts.map +1 -0
- package/dist/resources/check.js +543 -0
- package/dist/resources/check.js.map +1 -0
- package/dist/resources/compliance-check.d.ts +330 -0
- package/dist/resources/compliance-check.d.ts.map +1 -0
- package/dist/resources/compliance-check.js +402 -0
- package/dist/resources/compliance-check.js.map +1 -0
- package/dist/resources/decisions.d.ts +1208 -0
- package/dist/resources/decisions.d.ts.map +1 -0
- package/dist/resources/decisions.js +1362 -0
- package/dist/resources/decisions.js.map +1 -0
- package/dist/resources/evidence-pack.d.ts +1080 -0
- package/dist/resources/evidence-pack.d.ts.map +1 -0
- package/dist/resources/evidence-pack.js +1789 -0
- package/dist/resources/evidence-pack.js.map +1 -0
- package/dist/resources/gate.d.ts +613 -0
- package/dist/resources/gate.d.ts.map +1 -0
- package/dist/resources/gate.js +737 -0
- package/dist/resources/gate.js.map +1 -0
- package/dist/resources/incidents.d.ts +136 -0
- package/dist/resources/incidents.d.ts.map +1 -0
- package/dist/resources/incidents.js +229 -0
- package/dist/resources/incidents.js.map +1 -0
- package/dist/resources/regulatory-changes.d.ts +307 -0
- package/dist/resources/regulatory-changes.d.ts.map +1 -0
- package/dist/resources/regulatory-changes.js +365 -0
- package/dist/resources/regulatory-changes.js.map +1 -0
- package/dist/resources/safe-input-read.d.ts +21 -0
- package/dist/resources/safe-input-read.d.ts.map +1 -0
- package/dist/resources/safe-input-read.js +57 -0
- package/dist/resources/safe-input-read.js.map +1 -0
- package/dist/resources/ship-gate.d.ts +475 -0
- package/dist/resources/ship-gate.d.ts.map +1 -0
- package/dist/resources/ship-gate.js +727 -0
- package/dist/resources/ship-gate.js.map +1 -0
- package/dist/resources/vision.d.ts +540 -0
- package/dist/resources/vision.d.ts.map +1 -0
- package/dist/resources/vision.js +1036 -0
- package/dist/resources/vision.js.map +1 -0
- package/dist/retry.d.ts +103 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +224 -0
- package/dist/retry.js.map +1 -0
- package/dist/sse-parser.d.ts +64 -0
- package/dist/sse-parser.d.ts.map +1 -0
- package/dist/sse-parser.js +271 -0
- package/dist/sse-parser.js.map +1 -0
- package/dist/transport.d.ts +142 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +455 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/resources/check.ts"],"names":[],"mappings":"AAwFA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA2ClD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;OAeG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;;;;;;;OAYG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;OASG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwLG;IACH,GAAG,CACD,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,aAAa,CAAC;CA8N1B"}
|
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
// ─── Check resource ─────────────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Wraps the CI/CD compliance-check surface (session 16):
|
|
4
|
+
//
|
|
5
|
+
// - POST /api/v1/check Body: {systemId: <UUID>, frameworks?: string[]}
|
|
6
|
+
//
|
|
7
|
+
// Fourth non-decisions resource on `@attestry/sdk`. Sibling to
|
|
8
|
+
// `IncidentsResource`, `DecisionsResource`, `ChatResource`,
|
|
9
|
+
// `AuditLogResource`, `RegulatoryChangesResource`,
|
|
10
|
+
// `ComplianceCheckResource`. Single public method today (`run`); the
|
|
11
|
+
// resource class exists as the landing pad for future check methods
|
|
12
|
+
// if/when the kernel adds them (resource-class-per-kernel-resource
|
|
13
|
+
// convention, carry-forward invariant #43).
|
|
14
|
+
//
|
|
15
|
+
// Method name `run` rather than `check` — `client.check.check(...)`
|
|
16
|
+
// would be awkward; `run` mirrors the verb pattern of `chat.send`,
|
|
17
|
+
// `decisions.ingest`, `auditLog.export`. User-confirmed at session
|
|
18
|
+
// start.
|
|
19
|
+
//
|
|
20
|
+
// **Multi-permission UNION auth scope**: the kernel route gates on
|
|
21
|
+
// `requireApiKeyWithPermission(request, READ_ASSESSMENTS, READ_SYSTEMS)`
|
|
22
|
+
// which is OR semantics — `permissions.ts:53-55` uses `Array.some()`,
|
|
23
|
+
// NOT `.every()`. A key with EITHER permission (or `ADMIN`, or empty
|
|
24
|
+
// permissions for backwards-compat) succeeds. **HTTP 401** for
|
|
25
|
+
// no/invalid API key; **HTTP 403** for an authenticated key that has
|
|
26
|
+
// NEITHER required permission. Pin BOTH branches separately.
|
|
27
|
+
// Carry-forward invariant #45 (no re-discovery this round — same shape
|
|
28
|
+
// as `complianceCheck.check`).
|
|
29
|
+
//
|
|
30
|
+
// **First SDK route to PRE-VALIDATE every Zod closed-spec rule
|
|
31
|
+
// synchronously**. Other Zod-bodied SDK routes (e.g.,
|
|
32
|
+
// `incidents.create`) pass input through without SDK-side validation,
|
|
33
|
+
// so a 422 from Zod has been a consumer-visible surface there since
|
|
34
|
+
// v0.1. In `check.run` the kernel uses `parseBody(request,
|
|
35
|
+
// checkSchema)` where `checkSchema` is `z.object({systemId:
|
|
36
|
+
// z.string().uuid(), frameworks: z.array(z.string().min(1).max(100))
|
|
37
|
+
// .max(20).optional()})`. The SDK pre-validates EVERY closed-spec
|
|
38
|
+
// rule synchronously (UUID format, string length 1-100, array length
|
|
39
|
+
// cap 20). The SDK's runtime checks always run regardless of
|
|
40
|
+
// TypeScript types — `as any` casts do NOT bypass them. So 422 from
|
|
41
|
+
// this route reaches consumers ONLY via kernel-side rule changes the
|
|
42
|
+
// SDK hasn't synced to. Codifies new invariant candidate #49
|
|
43
|
+
// (pre-validate Zod closed-spec rules SDK-side) and #51 (POST + Zod
|
|
44
|
+
// body — pre-rejected TypeError is the primary path, kernel 422 is
|
|
45
|
+
// the fallback for rules the SDK hasn't synced to).
|
|
46
|
+
//
|
|
47
|
+
// **Asymmetric cross-org error code**: cross-org `systemId` returns
|
|
48
|
+
// **404** (kernel's `and(eq id, eq orgId)` at route.ts:42-51 followed
|
|
49
|
+
// by "System not found" — mirror of `decisions.retrieve` +
|
|
50
|
+
// `complianceCheck.check`'s systemId branch). Partial carry-forward
|
|
51
|
+
// of #47 (no orgName twin here, so only the 404 half applies).
|
|
52
|
+
//
|
|
53
|
+
// **Three silent kernel-side truncations** (faithful courier — SDK
|
|
54
|
+
// does NOT mask):
|
|
55
|
+
// 1. `issues` capped at 20 (`gaps.slice(0, 20)` at route.ts:90).
|
|
56
|
+
// 2. `assessments` capped at 100 (`.limit(100)` at route.ts:62).
|
|
57
|
+
// 3. `attestations` capped at 50 (`.limit(50)` at route.ts:100).
|
|
58
|
+
// Each documented in JSDoc + README + drift-pinned. New invariant
|
|
59
|
+
// candidate #50 (multi-silent-truncation enumeration).
|
|
60
|
+
//
|
|
61
|
+
// **`score` defaults to 0 (NOT null) when no completed assessment
|
|
62
|
+
// exists** (route.ts:84 — `typeof scores?.overallScore === "number"
|
|
63
|
+
// ? scores.overallScore : 0`). Asymmetric with
|
|
64
|
+
// `complianceCheck.check` which used `null` for "no data".
|
|
65
|
+
// Consumers cannot distinguish "scored zero" from "no completed
|
|
66
|
+
// assessment" via `score` alone — must check `lastAssessedAt ===
|
|
67
|
+
// null` to differentiate. Kernel surface gap, documented prominently.
|
|
68
|
+
//
|
|
69
|
+
// **`compliant` threshold stricter than `complianceCheck.check`**:
|
|
70
|
+
// here `compliant === activeAttestations > 0 && overallScore >= 70 &&
|
|
71
|
+
// issues.length === 0` (three conjuncts). Because `score` defaults
|
|
72
|
+
// to 0 (not null), a system with no completed assessment automatically
|
|
73
|
+
// has `compliant: false` here, even when active attestations exist.
|
|
74
|
+
//
|
|
75
|
+
// **NO URIError defense on body fields** — POST body uses
|
|
76
|
+
// `JSON.stringify`, which handles lone UTF-16 surrogates by emitting
|
|
77
|
+
// them as literal `\uDxxx` escapes. The URIError defect class
|
|
78
|
+
// (carry-forward invariant #32) applies only to query-string paths
|
|
79
|
+
// (`encodeURIComponent`); this route has no query string and a fixed
|
|
80
|
+
// path. `assertEncodableQueryString` is NOT invoked here — explicit
|
|
81
|
+
// asymmetry vs `complianceCheck.check` / decisions / incidents /
|
|
82
|
+
// audit-log / regulatory-changes. Documented as D4.
|
|
83
|
+
//
|
|
84
|
+
// Sync JSON request/response: reuses `client._request` and the
|
|
85
|
+
// existing `{success:true, data}` envelope-unwrap (carry-forward
|
|
86
|
+
// invariant #9). NO new SDK primitive needed. Returns
|
|
87
|
+
// `Promise<CheckResponse>`.
|
|
88
|
+
import { AttestryError } from "../errors.js";
|
|
89
|
+
import { readInputField } from "./safe-input-read.js";
|
|
90
|
+
// Module-load snapshot of `Object.hasOwn` — defends against a
|
|
91
|
+
// late-loading hostile/buggy npm dependency that overrides the global
|
|
92
|
+
// (e.g., `Object.hasOwn = () => true`). Without the snapshot, the
|
|
93
|
+
// prototype-pollution defense below uses whatever Object.hasOwn the
|
|
94
|
+
// dependency replaced it with at request time. Snapshotting at module
|
|
95
|
+
// load captures the original implementation BEFORE most consumer
|
|
96
|
+
// code has a chance to monkey-patch.
|
|
97
|
+
//
|
|
98
|
+
// Caveat: this is partial. If the hostile dependency is imported
|
|
99
|
+
// BEFORE @attestry/sdk in the consumer's load graph, the snapshot
|
|
100
|
+
// captures the bad version. Consumers ordering imports
|
|
101
|
+
// SDK-then-untrusted-deps benefit; the reverse ordering does not.
|
|
102
|
+
// Combined with `Object.hasOwn` itself being immune to
|
|
103
|
+
// `obj.hasOwnProperty = ...` overrides (per MDN), this gives a
|
|
104
|
+
// layered defense.
|
|
105
|
+
//
|
|
106
|
+
// Mirror of `complianceCheck.check`'s pattern (hostile review session
|
|
107
|
+
// 15 LOW #2). Generalizes #48 beyond XOR branching: prototype
|
|
108
|
+
// pollution can lie about presence of ANY field where presence affects
|
|
109
|
+
// SDK control flow (here: `systemId` required-vs-missing, `frameworks`
|
|
110
|
+
// provided-vs-not). See build-round audit doc D5.
|
|
111
|
+
const objectHasOwn = Object.hasOwn;
|
|
112
|
+
// UUID format regex — RFC 4122 hyphenated form (8-4-4-4-12 hex,
|
|
113
|
+
// case-insensitive). Matches Zod's `z.string().uuid()` regex
|
|
114
|
+
// effectively (the `\b` word-boundaries in Zod's version are
|
|
115
|
+
// redundant between hex chars and hyphens). Drift-pinned in
|
|
116
|
+
// `sdk-drift.test.ts` spec-diff-round Pin so a kernel-side switch to
|
|
117
|
+
// a different UUID flavor (ULID, KSUID, etc.) fires before consumer
|
|
118
|
+
// regressions.
|
|
119
|
+
//
|
|
120
|
+
// Pre-validation here gives consumers a synchronous `TypeError` for
|
|
121
|
+
// malformed UUID input — faster + clearer than waiting for the
|
|
122
|
+
// kernel's 422 with `fieldErrors`. D2 deviation from
|
|
123
|
+
// `complianceCheck.check` (which deferred to kernel's `isValidUuid`
|
|
124
|
+
// returning 400). Codifies new invariant #49 (Zod-schema-validated
|
|
125
|
+
// input — pre-validate closed-spec rules SDK-side).
|
|
126
|
+
const UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
127
|
+
/**
|
|
128
|
+
* `check` resource — sibling to `IncidentsResource`,
|
|
129
|
+
* `DecisionsResource`, `ChatResource`, `AuditLogResource`,
|
|
130
|
+
* `RegulatoryChangesResource`, `ComplianceCheckResource`. Today
|
|
131
|
+
* wraps a single endpoint (`run`); the class is the landing pad for
|
|
132
|
+
* future check methods if the kernel adds them
|
|
133
|
+
* (resource-class-per-kernel-resource convention, invariant #43).
|
|
134
|
+
*/
|
|
135
|
+
export class CheckResource {
|
|
136
|
+
client;
|
|
137
|
+
constructor(client) {
|
|
138
|
+
this.client = client;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Run a CI/CD compliance check for a single system. Returns a flat
|
|
142
|
+
* 6-field summary: `{compliant, score, issues, activeAttestations,
|
|
143
|
+
* lastAssessedAt, checkedAt}`. Sync JSON request/response — no
|
|
144
|
+
* pagination, no streaming.
|
|
145
|
+
*
|
|
146
|
+
* **Multi-permission UNION auth scope**: kernel uses
|
|
147
|
+
* `requireApiKeyWithPermission(req, READ_ASSESSMENTS, READ_SYSTEMS)`
|
|
148
|
+
* which is OR semantics (`Array.some()` at
|
|
149
|
+
* `permissions.ts:53-55`). A key with EITHER permission (or
|
|
150
|
+
* `ADMIN`, or null/empty permissions for backwards-compat)
|
|
151
|
+
* succeeds. **HTTP 401** for no/invalid API key, **HTTP 403** for
|
|
152
|
+
* an authenticated key that has NEITHER required permission. Pin
|
|
153
|
+
* BOTH branches separately. Carry-forward invariant #45 (same
|
|
154
|
+
* shape as `complianceCheck.check`).
|
|
155
|
+
*
|
|
156
|
+
* **Asymmetric cross-org error code** (carry-forward #47, partial):
|
|
157
|
+
* cross-org `systemId` returns **404** — the kernel's
|
|
158
|
+
* `and(eq id, eq orgId)` at route.ts:42-51 collapses
|
|
159
|
+
* cross-org to "System not found" (mirror of
|
|
160
|
+
* `decisions.retrieve`). Consumers writing defensive error-handling
|
|
161
|
+
* logic must recognize: a 404 may be "not your org" OR "genuine
|
|
162
|
+
* missing UUID". No 403-via-orgName twin here (no orgName input
|
|
163
|
+
* mode).
|
|
164
|
+
*
|
|
165
|
+
* **THREE silent kernel-side truncations** (faithful courier;
|
|
166
|
+
* documented as kernel surface gaps — JSDoc + README + drift
|
|
167
|
+
* pinned). New invariant candidate #50:
|
|
168
|
+
* 1. `issues` — `.slice(0, 20)` at route.ts:90. If the latest
|
|
169
|
+
* completed assessment has >20 gaps, the 21st+ are invisible.
|
|
170
|
+
* 2. `assessments` row-population — `.limit(100)` at route.ts:62.
|
|
171
|
+
* If the system has >100 assessments, the kernel's JS-side
|
|
172
|
+
* `.sort()` operates on the first 100 only; the "latest
|
|
173
|
+
* completed" may be missed.
|
|
174
|
+
* 3. `attestations` row-population — `.limit(50)` at
|
|
175
|
+
* route.ts:100. If the system has >50 attestation rows,
|
|
176
|
+
* `activeAttestations` may be undercounted.
|
|
177
|
+
*
|
|
178
|
+
* **`score` defaults to 0 (NOT null) — kernel surface gap**:
|
|
179
|
+
* route.ts:84 — `typeof scores?.overallScore === "number" ?
|
|
180
|
+
* scores.overallScore : 0`. Consumers MUST check `lastAssessedAt
|
|
181
|
+
* === null` to distinguish "no completed assessment yet" from
|
|
182
|
+
* "scored zero / fails compliance". Asymmetric with
|
|
183
|
+
* `complianceCheck.check`'s null-on-no-data.
|
|
184
|
+
*
|
|
185
|
+
* **`frameworks` filter is OR-overlap, NOT AND-all-required** —
|
|
186
|
+
* route.ts:67-71 uses `aFrameworks.some((fw) =>
|
|
187
|
+
* body.frameworks!.some(...))`. An assessment matches if its
|
|
188
|
+
* `frameworks` array intersects the filter (at least one in
|
|
189
|
+
* common), not if it covers ALL of them. Consumers wanting AND
|
|
190
|
+
* semantics must filter post-hoc.
|
|
191
|
+
*
|
|
192
|
+
* Errors — ordered by kernel firing precedence (rate-limit → auth
|
|
193
|
+
* → Zod body validation → DB lookup → internal). A request with
|
|
194
|
+
* multiple problems surfaces ONLY the highest-precedence one. For
|
|
195
|
+
* example: a request with bad auth AND a malformed body surfaces
|
|
196
|
+
* 401, not 422; a request with valid auth + bad body AND a cross-
|
|
197
|
+
* org systemId surfaces 422, not 404.
|
|
198
|
+
* - `AttestryAPIError` (status 429) — rate limit FIRES FIRST
|
|
199
|
+
* (auto-retried by default — invariant #18; per-IP rate-limit
|
|
200
|
+
* key `v1-check:${ip}`).
|
|
201
|
+
* - `AttestryAPIError` (status 401) — no API key OR invalid key.
|
|
202
|
+
* Fires AFTER rate-limit but BEFORE input validation.
|
|
203
|
+
* - `AttestryAPIError` (status 403) — authenticated key has
|
|
204
|
+
* NEITHER `READ_ASSESSMENTS` nor `READ_SYSTEMS` (the
|
|
205
|
+
* permission-check branch). Single test case — the union-auth
|
|
206
|
+
* pattern collapses three intuition-suggesting cases to one.
|
|
207
|
+
* - `AttestryAPIError` (status 422) — Zod schema rejection
|
|
208
|
+
* (kernel's `BodyParseError` surface — `parseBody(request,
|
|
209
|
+
* checkSchema)` failed). **Fires BEFORE the systemId/cross-
|
|
210
|
+
* org 404 lookup**, so a request with bad UUID format AND
|
|
211
|
+
* cross-org-correct UUID surfaces 422 (the kernel's Zod
|
|
212
|
+
* `.uuid()` reject), not 404. `apiErr.details` carries the
|
|
213
|
+
* full kernel error body verbatim (the transport does NOT
|
|
214
|
+
* strip the `{success:false, ...}` envelope on error responses
|
|
215
|
+
* — only the `{success:true, data}` envelope on success). The
|
|
216
|
+
* wire shape is: `{success: false, error: "Validation failed.",
|
|
217
|
+
* details: Array<{path: string; message: string}>}` — `error`
|
|
218
|
+
* is the literal string
|
|
219
|
+
* "Validation failed." (with trailing period), `details` is
|
|
220
|
+
* an array (NOT a keyed map) of `{path, message}` pairs
|
|
221
|
+
* derived from Zod's `result.error.errors`. Consumers
|
|
222
|
+
* reading field-by-field errors should iterate
|
|
223
|
+
* `apiErr.details.details` (the kernel's `details` array
|
|
224
|
+
* nested under the SDK's parsed-body wrapper). **The SDK
|
|
225
|
+
* pre-validates all closed-spec rules** (UUID format,
|
|
226
|
+
* framework element length 1-100, array length ≤20) AND the
|
|
227
|
+
* runtime checks always run regardless of TypeScript types —
|
|
228
|
+
* `as any` casts do NOT bypass them. So 422 reaches consumers
|
|
229
|
+
* ONLY via kernel rule changes the SDK hasn't synced to (e.g.,
|
|
230
|
+
* a future kernel tightening that adds a new Zod rule the SDK
|
|
231
|
+
* hasn't yet learned to pre-validate). New invariant candidate
|
|
232
|
+
* #51.
|
|
233
|
+
* - `AttestryAPIError` (status 404) — system not found OR
|
|
234
|
+
* cross-org systemId (kernel collapses to "System not found",
|
|
235
|
+
* route.ts:53-54). Fires AFTER Zod validation (422).
|
|
236
|
+
* - `AttestryAPIError` (status 500) — internal kernel error
|
|
237
|
+
* (scrubbed message via `internalErrorResponse`).
|
|
238
|
+
* - `AttestryError` ("request aborted by caller") — caller-
|
|
239
|
+
* supplied `options.signal` fired (pre-aborted or mid-flight).
|
|
240
|
+
* - `AttestryError` (P2 hardening) — kernel response failed
|
|
241
|
+
* SDK-side shape validation (not an object, wrong type on any
|
|
242
|
+
* of the 6 documented fields).
|
|
243
|
+
* - `AttestryAPIError` (P3 hardening) — kernel response had a
|
|
244
|
+
* wrong Content-Type (transport-level guard before body
|
|
245
|
+
* parsing).
|
|
246
|
+
* - `TypeError` (synchronous, no fetch issued) — input failed
|
|
247
|
+
* SDK-side validation (null / array / non-object input,
|
|
248
|
+
* missing systemId, invalid UUID format, frameworks array too
|
|
249
|
+
* long, frameworks element wrong type or length).
|
|
250
|
+
*
|
|
251
|
+
* **Notably ABSENT**:
|
|
252
|
+
* - **No 400** — all input validation is Zod (422). The "missing
|
|
253
|
+
* required field" 400 from compliance-check is irrelevant
|
|
254
|
+
* (single required field; SDK pre-rejects as TypeError).
|
|
255
|
+
* - **No 413** — body size limit not explicit; the kernel's
|
|
256
|
+
* `parseBody` may have one but it isn't documented and the
|
|
257
|
+
* SDK doesn't pin it.
|
|
258
|
+
* - **No 402** — read-only, doesn't count against
|
|
259
|
+
* decisionsPerMonth quota.
|
|
260
|
+
*
|
|
261
|
+
* **SDK-side validation** (synchronous `TypeError`, no fetch
|
|
262
|
+
* issued):
|
|
263
|
+
* - `input` itself: required; must be a non-null, non-array
|
|
264
|
+
* object.
|
|
265
|
+
* - `input.systemId`: required own-property (Object.hasOwn
|
|
266
|
+
* defends against prototype pollution lying about presence —
|
|
267
|
+
* generalization of invariant #48); must be a non-empty
|
|
268
|
+
* string; must match the RFC 4122 hyphenated UUID format
|
|
269
|
+
* (D2 — SDK pre-validates closed-spec rule). No
|
|
270
|
+
* lone-surrogate URIError defense (D4 — POST body uses
|
|
271
|
+
* JSON.stringify, not encodeURIComponent).
|
|
272
|
+
* - `input.frameworks` (when provided): must be an array of
|
|
273
|
+
* ≤20 strings, each of length 1-100. SDK pre-validates each
|
|
274
|
+
* rule (D3 — closed-spec rules mirror Zod). Array is
|
|
275
|
+
* snapshotted via `Array.from` for TOCTOU defense (Proxy /
|
|
276
|
+
* getter inputs can't yield different values across
|
|
277
|
+
* validate-vs-send).
|
|
278
|
+
*
|
|
279
|
+
* **Response-shape validation** (P2 hardening — D6, stricter than
|
|
280
|
+
* `complianceCheck.check`'s 3-field top-level):
|
|
281
|
+
* - Rejects with `AttestryError` if the kernel response isn't a
|
|
282
|
+
* non-null, non-array object.
|
|
283
|
+
* - Rejects if `compliant` isn't a boolean.
|
|
284
|
+
* - Rejects if `score` isn't a number.
|
|
285
|
+
* - Rejects if `issues` isn't an array.
|
|
286
|
+
* - Rejects if `activeAttestations` isn't a number.
|
|
287
|
+
* - Rejects if `lastAssessedAt` isn't a string OR null.
|
|
288
|
+
* - Rejects if `checkedAt` isn't a string.
|
|
289
|
+
* - Each response field read goes through the module-load
|
|
290
|
+
* `objectHasOwn` snapshot (symmetric to the input-side
|
|
291
|
+
* prototype-pollution defense — D5 generalized to the response
|
|
292
|
+
* boundary). A hostile npm dep that pollutes
|
|
293
|
+
* `Object.prototype.<field>` cannot mask a kernel regression
|
|
294
|
+
* where the field is missing — the SDK requires the field to
|
|
295
|
+
* be a kernel-emitted own property.
|
|
296
|
+
* - Per-issue-string shape (open string) is faithful-courier —
|
|
297
|
+
* NOT validated.
|
|
298
|
+
*
|
|
299
|
+
* **Transport-shape validation** (P3 hardening):
|
|
300
|
+
* - Rejects with `AttestryAPIError` if the kernel responds with
|
|
301
|
+
* a non-`application/json` Content-Type.
|
|
302
|
+
*
|
|
303
|
+
* @example Basic check
|
|
304
|
+
* ```ts
|
|
305
|
+
* const result = await client.check.run({
|
|
306
|
+
* systemId: "11111111-1111-1111-1111-111111111111",
|
|
307
|
+
* });
|
|
308
|
+
* if (result.compliant) {
|
|
309
|
+
* console.log("OK to deploy — score:", result.score);
|
|
310
|
+
* } else if (result.lastAssessedAt === null) {
|
|
311
|
+
* console.warn("No completed assessment yet — score=0 is the default, not a failing grade");
|
|
312
|
+
* } else {
|
|
313
|
+
* console.warn("Compliance gaps:", result.issues);
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*
|
|
317
|
+
* @example Filtered by frameworks (OR-overlap)
|
|
318
|
+
* ```ts
|
|
319
|
+
* const euOnly = await client.check.run({
|
|
320
|
+
* systemId: "11111111-1111-1111-1111-111111111111",
|
|
321
|
+
* frameworks: ["EU_AI_ACT", "ISO_42001"],
|
|
322
|
+
* });
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
run(input, options) {
|
|
326
|
+
// Top-level shape — input is REQUIRED. typeof null === "object"
|
|
327
|
+
// and typeof [] === "object", so guard both explicitly.
|
|
328
|
+
if (input === null ||
|
|
329
|
+
typeof input !== "object" ||
|
|
330
|
+
Array.isArray(input)) {
|
|
331
|
+
throw new TypeError("check.run: `input` must be a non-null object with `systemId`");
|
|
332
|
+
}
|
|
333
|
+
// Snapshot each field's value EXACTLY ONCE up front via the
|
|
334
|
+
// own-property indexer, then operate only on the locals
|
|
335
|
+
// downstream. Three motivations:
|
|
336
|
+
// 1. **Prototype-pollution defense (generalization of #48)**:
|
|
337
|
+
// `Object.prototype.systemId = "<some-uuid>"` (set somewhere
|
|
338
|
+
// else in the consumer's process) DOES NOT trick the SDK
|
|
339
|
+
// into silently sending the polluted value when the user
|
|
340
|
+
// passes `{}`. `Object.hasOwn` only checks own properties
|
|
341
|
+
// (ES2022, Node 16.9+ — below the SDK's Node 18 floor). Use
|
|
342
|
+
// the module-load snapshot (`objectHasOwn`) so a
|
|
343
|
+
// late-loading dep that overrides the global doesn't defeat
|
|
344
|
+
// the defense (mirror of `complianceCheck.check`'s hostile-
|
|
345
|
+
// review LOW #2 fix).
|
|
346
|
+
// 2. **TOCTOU defense**: a Proxy or getter-defining input could
|
|
347
|
+
// yield DIFFERENT values across multiple reads of the same
|
|
348
|
+
// field. Snapshotting once collapses validate-then-send to a
|
|
349
|
+
// single read per field; the validated value is provably the
|
|
350
|
+
// value sent.
|
|
351
|
+
// 3. An explicit `{systemId: "..."}` (no `frameworks`) is
|
|
352
|
+
// treated as frameworks-omitted — `objectHasOwn` correctly
|
|
353
|
+
// returns false on the missing key.
|
|
354
|
+
const hasSystemId = objectHasOwn(input, "systemId");
|
|
355
|
+
const systemIdRaw = hasSystemId
|
|
356
|
+
? readInputField(input, "systemId", "check.run")
|
|
357
|
+
: undefined;
|
|
358
|
+
const hasFrameworks = objectHasOwn(input, "frameworks");
|
|
359
|
+
const frameworksRaw = hasFrameworks
|
|
360
|
+
? readInputField(input, "frameworks", "check.run")
|
|
361
|
+
: undefined;
|
|
362
|
+
// systemId is REQUIRED. Reject missing-or-undefined first with a
|
|
363
|
+
// clear "required" message; subsequent checks assume present.
|
|
364
|
+
if (!hasSystemId || systemIdRaw === undefined) {
|
|
365
|
+
throw new TypeError("check.run: `systemId` is required");
|
|
366
|
+
}
|
|
367
|
+
if (typeof systemIdRaw !== "string" || systemIdRaw.length === 0) {
|
|
368
|
+
throw new TypeError("check.run: `systemId` must be a non-empty string");
|
|
369
|
+
}
|
|
370
|
+
// UUID format pre-validation (D2 — SDK matches kernel's Zod
|
|
371
|
+
// `z.string().uuid()` closed-spec rule). Faster + clearer than
|
|
372
|
+
// waiting for kernel 422 + fieldErrors decoding. Drift-pinned so
|
|
373
|
+
// a future Zod regex change (e.g., adding v7 ULID support) trips
|
|
374
|
+
// the suite.
|
|
375
|
+
if (!UUID_REGEX.test(systemIdRaw)) {
|
|
376
|
+
throw new TypeError("check.run: `systemId` must be an RFC 4122 hyphenated UUID " +
|
|
377
|
+
"(matched regex: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-" +
|
|
378
|
+
"[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/)");
|
|
379
|
+
}
|
|
380
|
+
// frameworks — optional. When provided, MUST mirror Zod:
|
|
381
|
+
// - Array (not other iterable).
|
|
382
|
+
// - Length ≤20.
|
|
383
|
+
// - Each element a string of length 1-100.
|
|
384
|
+
// Snapshot via Array.from up front so a Proxy whose `.length` or
|
|
385
|
+
// `[i]` changes between reads can't slip past validation. The
|
|
386
|
+
// snapshot is then sent verbatim as the body field — no
|
|
387
|
+
// re-read.
|
|
388
|
+
let validatedFrameworks;
|
|
389
|
+
if (hasFrameworks && frameworksRaw !== undefined) {
|
|
390
|
+
if (!Array.isArray(frameworksRaw)) {
|
|
391
|
+
throw new TypeError(`check.run: \`frameworks\` must be an array when provided ` +
|
|
392
|
+
`(got ${describeType(frameworksRaw)})`);
|
|
393
|
+
}
|
|
394
|
+
const snapshot = Array.from(frameworksRaw);
|
|
395
|
+
if (snapshot.length > 20) {
|
|
396
|
+
throw new TypeError(`check.run: \`frameworks\` array exceeds the kernel's max ` +
|
|
397
|
+
`length of 20 (got ${snapshot.length})`);
|
|
398
|
+
}
|
|
399
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
400
|
+
const elem = snapshot[i];
|
|
401
|
+
if (typeof elem !== "string") {
|
|
402
|
+
throw new TypeError(`check.run: \`frameworks[${i}]\` must be a string ` +
|
|
403
|
+
`(got ${describeType(elem)})`);
|
|
404
|
+
}
|
|
405
|
+
if (elem.length === 0) {
|
|
406
|
+
throw new TypeError(`check.run: \`frameworks[${i}]\` must be a non-empty string`);
|
|
407
|
+
}
|
|
408
|
+
if (elem.length > 100) {
|
|
409
|
+
throw new TypeError(`check.run: \`frameworks[${i}]\` exceeds the kernel's max ` +
|
|
410
|
+
`length of 100 chars (got ${elem.length})`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Cast: we've validated every element is a string.
|
|
414
|
+
validatedFrameworks = snapshot;
|
|
415
|
+
}
|
|
416
|
+
// Construct the body. Omit `frameworks` entirely when not
|
|
417
|
+
// provided — the kernel's Zod schema marks it `.optional()` and a
|
|
418
|
+
// missing key is the cleanest representation. (JSON.stringify
|
|
419
|
+
// would also drop `undefined`-valued keys, but explicit
|
|
420
|
+
// construction is clearer.)
|
|
421
|
+
const body = {
|
|
422
|
+
systemId: systemIdRaw,
|
|
423
|
+
};
|
|
424
|
+
if (validatedFrameworks !== undefined) {
|
|
425
|
+
body.frameworks = validatedFrameworks;
|
|
426
|
+
}
|
|
427
|
+
return this.client
|
|
428
|
+
._request({
|
|
429
|
+
method: "POST",
|
|
430
|
+
path: "/api/v1/check",
|
|
431
|
+
body,
|
|
432
|
+
options,
|
|
433
|
+
})
|
|
434
|
+
.then((result) => {
|
|
435
|
+
// P2 hardening: validate every documented field type. The
|
|
436
|
+
// check response is FLAT — all 6 fields are top-level (no
|
|
437
|
+
// nested wrapper like `complianceCheck.check`'s `systems[]`).
|
|
438
|
+
// A kernel-side regression that emits the wrong type on any
|
|
439
|
+
// field would let a malformed shape reach consumers, who
|
|
440
|
+
// crash downstream with a confusing TypeError. Catch at the
|
|
441
|
+
// SDK boundary with a clear AttestryError naming the
|
|
442
|
+
// specific field.
|
|
443
|
+
if (result === null ||
|
|
444
|
+
typeof result !== "object" ||
|
|
445
|
+
Array.isArray(result)) {
|
|
446
|
+
throw new AttestryError(`check.run: expected an object response from the kernel ` +
|
|
447
|
+
`(got ${describeType(result)})`);
|
|
448
|
+
}
|
|
449
|
+
const obj = result;
|
|
450
|
+
// **Prototype-pollution defense on the RESPONSE side**
|
|
451
|
+
// (symmetric to the input-side D5 generalization of #48).
|
|
452
|
+
// Snapshot each response field via `objectHasOwn` so a hostile
|
|
453
|
+
// npm dep that pollutes `Object.prototype.<field> = <value>`
|
|
454
|
+
// (e.g., `Object.prototype.compliant = true`) cannot mask a
|
|
455
|
+
// kernel regression where the field is missing from the
|
|
456
|
+
// response. Without this defense: kernel-regression-drops-field
|
|
457
|
+
// + prototype-pollution-supplies-default → SDK accepts the
|
|
458
|
+
// polluted value via prototype walk; consumer silently gets a
|
|
459
|
+
// wrong response. With this defense: missing own-property →
|
|
460
|
+
// describeType(undefined) → AttestryError thrown.
|
|
461
|
+
//
|
|
462
|
+
// Found by session-16 SECOND independent hostile review as
|
|
463
|
+
// MEDIUM #3 — symmetric attack to the input-side defense,
|
|
464
|
+
// previously unguarded on the response path.
|
|
465
|
+
const compliant = objectHasOwn(obj, "compliant")
|
|
466
|
+
? obj.compliant
|
|
467
|
+
: undefined;
|
|
468
|
+
if (typeof compliant !== "boolean") {
|
|
469
|
+
throw new AttestryError(`check.run: expected response.compliant to be a boolean ` +
|
|
470
|
+
`(got ${describeType(compliant)})`);
|
|
471
|
+
}
|
|
472
|
+
const score = objectHasOwn(obj, "score") ? obj.score : undefined;
|
|
473
|
+
if (typeof score !== "number") {
|
|
474
|
+
throw new AttestryError(`check.run: expected response.score to be a number ` +
|
|
475
|
+
`(got ${describeType(score)})`);
|
|
476
|
+
}
|
|
477
|
+
const issues = objectHasOwn(obj, "issues") ? obj.issues : undefined;
|
|
478
|
+
if (!Array.isArray(issues)) {
|
|
479
|
+
throw new AttestryError(`check.run: expected response.issues to be an array ` +
|
|
480
|
+
`(got ${describeType(issues)})`);
|
|
481
|
+
}
|
|
482
|
+
const activeAttestations = objectHasOwn(obj, "activeAttestations")
|
|
483
|
+
? obj.activeAttestations
|
|
484
|
+
: undefined;
|
|
485
|
+
if (typeof activeAttestations !== "number") {
|
|
486
|
+
throw new AttestryError(`check.run: expected response.activeAttestations to be a number ` +
|
|
487
|
+
`(got ${describeType(activeAttestations)})`);
|
|
488
|
+
}
|
|
489
|
+
const lastAssessedAt = objectHasOwn(obj, "lastAssessedAt")
|
|
490
|
+
? obj.lastAssessedAt
|
|
491
|
+
: undefined;
|
|
492
|
+
if (lastAssessedAt !== null && typeof lastAssessedAt !== "string") {
|
|
493
|
+
throw new AttestryError(`check.run: expected response.lastAssessedAt to be a string or null ` +
|
|
494
|
+
`(got ${describeType(lastAssessedAt)})`);
|
|
495
|
+
}
|
|
496
|
+
const checkedAt = objectHasOwn(obj, "checkedAt")
|
|
497
|
+
? obj.checkedAt
|
|
498
|
+
: undefined;
|
|
499
|
+
if (typeof checkedAt !== "string") {
|
|
500
|
+
throw new AttestryError(`check.run: expected response.checkedAt to be a string ` +
|
|
501
|
+
`(got ${describeType(checkedAt)})`);
|
|
502
|
+
}
|
|
503
|
+
return result;
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Human-readable type description for error messages. Distinguishes
|
|
509
|
+
* `null` and `array` from generic `object`. Duplicated in
|
|
510
|
+
* `decisions.ts`, `incidents.ts`, `regulatory-changes.ts`,
|
|
511
|
+
* `compliance-check.ts` per project pattern (small helper, leaf-
|
|
512
|
+
* resource modules, no shared module yet).
|
|
513
|
+
*
|
|
514
|
+
* Every branch is reachable in this file:
|
|
515
|
+
* 1. The top-level "expected object" path can see null OR scalar
|
|
516
|
+
* OR array (the negation of "non-null non-array object").
|
|
517
|
+
* 2. The `compliant` / `score` / `activeAttestations` / `checkedAt`
|
|
518
|
+
* type guards can see any non-matching type (including null and
|
|
519
|
+
* array).
|
|
520
|
+
* 3. The `lastAssessedAt` guard can see any type except string OR
|
|
521
|
+
* null (so the null branch is structurally unreachable from
|
|
522
|
+
* THAT call site — null would be filtered by the `!== null`
|
|
523
|
+
* check upstream).
|
|
524
|
+
* 4. The `issues` guard can see any type except array (so the
|
|
525
|
+
* array branch is structurally unreachable from THAT call
|
|
526
|
+
* site).
|
|
527
|
+
* 5. The `frameworks` non-array case can see any non-array type
|
|
528
|
+
* (so the array branch is structurally unreachable from THAT
|
|
529
|
+
* call site).
|
|
530
|
+
* 6. The `frameworks[i]` non-string guard can see any
|
|
531
|
+
* non-string type.
|
|
532
|
+
*
|
|
533
|
+
* Multiple call sites means every branch IS reachable across the
|
|
534
|
+
* module's invocations — no v8-ignore markers needed.
|
|
535
|
+
*/
|
|
536
|
+
function describeType(value) {
|
|
537
|
+
if (value === null)
|
|
538
|
+
return "null";
|
|
539
|
+
if (Array.isArray(value))
|
|
540
|
+
return "array";
|
|
541
|
+
return typeof value;
|
|
542
|
+
}
|
|
543
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/resources/check.ts"],"names":[],"mappings":"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"}
|