@ziffer-io/types 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1696 @@
1
+ /**
2
+ * AS0 software key · AS1 multi-factor-protected key · AS2 hardware-bound
3
+ * key. Ordered: AS0 < AS1 < AS2, and AT-10 compares an entry's level against
4
+ * the registry floor with >=, so the ordering is load-bearing — a chain like
5
+ * §4's custody tiers and floors' resource tiers, NOT like suites, whose
6
+ * floor is containment (CR-4) precisely because suites do not rank.
7
+ * Correspondence, stated so the M-A annex can cite it and a buyer can map
8
+ * it: AS1 is the arrangement NIST SP 800-63B calls AAL2 (multi-factor,
9
+ * software permitted), AS2 is AAL3's (hardware authenticator). The names are
10
+ * this specification's own because an external framework's labels move on
11
+ * that framework's schedule.
12
+ * Generated from attesters.schema.json#/$defs/assurance.
13
+ */
14
+ export type Assurance = 'AS0' | 'AS1' | 'AS2';
15
+ /**
16
+ * Assurance low to high, from the schema's declared order.
17
+ *
18
+ * TypeScript has no derived ordering, so the ladder is a value and the
19
+ * comparison is a function. §8.4 composes with max, so `max` is what
20
+ * callers need and index arithmetic is what they must not write.
21
+ */
22
+ export declare const ASSURANCE_ORDER: readonly Assurance[];
23
+ export declare function maxAssurance(a: Assurance, b: Assurance): Assurance;
24
+ /**
25
+ * Which of the two acknowledgement duties an enrolled identity may
26
+ * discharge.
27
+ *
28
+ * Hoisted into `$defs` for the same reason `reversibility` was: an inline
29
+ * enum has no name, and a generator inventing one invents a name that
30
+ * drifts.
31
+ *
32
+ * DELIBERATELY NOT ORDERED. A confirmer does not outrank an approver; they
33
+ * are different duties, and DR-9's separation is enforced per action against
34
+ * the proposer rather than by comparing roles.
35
+ * Generated from attesters.schema.json#/$defs/attester_role.
36
+ */
37
+ export type AttesterRole = 'approver' | 'confirmer';
38
+ /**
39
+ * The credential's public key as a COSE_Key (RFC 9052) map, canonical CBOR,
40
+ * base64, holding EXACTLY the labels kty, crv, x and (for EC2) y and nothing
41
+ * else. Every real authenticator also returns label 3 (alg); the enrolling
42
+ * service strips it before the entry is written, because a key that admits
43
+ * two encodings is two `public_key` strings for one credential, and PB-7's
44
+ * distinctness over `public_key` would then see one holder as two. The
45
+ * verifier refuses label 3 at load as Malformed rather than tolerating it,
46
+ * so the one encoding is the one the registry can hold. Not re-encoded to a
47
+ * raw point either, for AB-1's reason: a re-encoding is a second definition
48
+ * of the key. The verifier decodes it (kty EC2 / P-256 for `webauthn-es256`;
49
+ * kty OKP / Ed25519 for `webauthn-ed25519`) and refuses at load a key whose
50
+ * kty/crv/alg do not match the entry's `alg`, a P-256 point not on the
51
+ * curve, or an Ed25519 point of small order (HM-5, PB-9).
52
+ * Generated from attesters.schema.json#/$defs/cose_key.
53
+ *
54
+ * The schema constrains this to `^[A-Za-z0-9+/]{40,}={0,2}$`, which is NOT enforced here.
55
+ */
56
+ export type CoseKey = string;
57
+ /**
58
+ * The authenticator's credential id from registration, base64 (the
59
+ * registry's encoding, as `ed25519_pub` and `mldsa65_pub` are). Not a secret
60
+ * and not a key: it names the credential, and the Consumption Ledger keys
61
+ * the signature counter on it (HM-4 (f)).
62
+ * Generated from attesters.schema.json#/$defs/credential_id.
63
+ *
64
+ * The schema constrains this to `^[A-Za-z0-9+/]{20,}={0,2}$`, which is NOT enforced here.
65
+ */
66
+ export type CredentialId = string;
67
+ /**
68
+ * Ed25519 verification key (RFC 8032), base64. 32 bytes raw; the decoded
69
+ * length is asserted in code, because a base64 string of the wrong length is
70
+ * well-formed JSON and a schema pattern alone would let a truncated key
71
+ * through.
72
+ * Generated from attesters.schema.json#/$defs/ed25519_pub.
73
+ *
74
+ * The schema constrains this to `^[A-Za-z0-9+/]{43}=$`, which is NOT enforced here.
75
+ */
76
+ export type Ed25519PublicKey = string;
77
+ /**
78
+ * F-HIGH: no free text reaches the Proposal; every field is a bounded
79
+ * scalar, constrained string, enum or fixed-shape nested model, so
80
+ * instruction injection into the Proposal is grammatically impossible.
81
+ * F-LOW: a translator model produced the Proposal from free text, injection
82
+ * into the TRANSLATION STEP is possible by construction, and containment
83
+ * rests on capability limits, confirmation and receipts -- never on ingress
84
+ * hygiene (FC-1, FC-3). Exactly one class per adapter.
85
+ *
86
+ * DELIBERATELY UNORDERED. There is no `x-acp-ordered` here and there must
87
+ * not be. The two classes are not ranked: FC-2 conditions on the class and
88
+ * requires confirmation for F-LOW at effective tier >= T2, which is a case
89
+ * distinction, not a comparison. An ordering invented for convenience would
90
+ * invite `>=` against a value that has no scale, which is the
91
+ * tier-versus-risk conflation this repository has already published a
92
+ * correction for -- and the names point the wrong way for a ladder, since
93
+ * here HIGH is the safer class.
94
+ *
95
+ * THIS IS ALSO THE WIRE ROOT'S `FidelityClass` (ACP-73). It was declared in
96
+ * `spec/schemas/wire/proposal.schema.json` until this table existed, and
97
+ * `proposal`, `decision_receipt` and `audit_record` now `$ref` this
98
+ * declaration across roots rather than restating it, for the reason
99
+ * `SuiteId` is homed in `signature.schema.json`: TR-8 compares the receipt's
100
+ * transmitted `fidelity` against the class registered HERE, and two enums
101
+ * that merely look alike is that comparison passing on a vocabulary nobody
102
+ * checked. The signed side owns the vocabulary; the wire carries it.
103
+ * Generated from adapters.schema.json#/$defs/fidelity_class.
104
+ */
105
+ export type FidelityClass = 'F-HIGH' | 'F-LOW';
106
+ /**
107
+ * ML-DSA-65 verification key (FIPS 204), base64. 1952 bytes raw. Its size is
108
+ * why hybrid receipts run 13.2 kB against 256 B classical-only — a 53x wire
109
+ * increase that is algorithm-bound and does not improve with a faster
110
+ * library.
111
+ * Generated from attesters.schema.json#/$defs/mldsa65_pub.
112
+ *
113
+ * The schema constrains this to `^[A-Za-z0-9+/]{2603}=$`, which is NOT enforced here.
114
+ */
115
+ export type MlDsa65PublicKey = string;
116
+ /**
117
+ * A primitive NAME as it appears on the wire.
118
+ *
119
+ * `pq-slh` is declared and NOT implemented. It keeps its own name and fails
120
+ * closed — aliasing it to `pq` would let a verifier report success for a
121
+ * primitive it cannot compute, which is the one thing an unimplemented
122
+ * primitive must never do.
123
+ * Generated from signature.schema.json#/$defs/primitive.
124
+ */
125
+ export type PrimitiveName = 'classical' | 'pq' | 'pq-slh';
126
+ /**
127
+ * Whether an action class can be undone.
128
+ *
129
+ * Hoisted out of `additionalProperties` into `$defs` so that it has a NAME.
130
+ * An inline enum is a type the generator has to invent a name for, and an
131
+ * invented name is a name that drifts — `floors.schema.json` already
132
+ * declared its values under `$defs.tier` and this file did not, which is a
133
+ * difference with no reason behind it.
134
+ *
135
+ * DELIBERATELY NOT ORDERED. REVERSIBLE and IRREVERSIBLE are two cases, not a
136
+ * scale; a generated `Ord` would invite `max` composition that means nothing
137
+ * here.
138
+ * Generated from reversibility.schema.json#/$defs/reversibility.
139
+ */
140
+ export type Reversibility = 'REVERSIBLE' | 'IRREVERSIBLE';
141
+ /**
142
+ * Ordered LOW < MEDIUM < HIGH. §8.4 composes with max.
143
+ *
144
+ * A RISK LEVEL IS NOT A RESOURCE TIER. This is a different ladder from
145
+ * `floors.schema.json`'s T0..T3, over a different subject, and §8.4 composes
146
+ * both with max — which is exactly why one type served for both until
147
+ * someone looked. The Rust and TypeScript definitions carried a single
148
+ * `RiskTier` enum whose doc comment cited RK-1's absent-⇒-T3 rule and whose
149
+ * values were LOW/MEDIUM/HIGH, so the fail-safe default was stated in the
150
+ * wrong domain in both. Generated separately, and named separately, for that
151
+ * reason.
152
+ * Generated from risk_functions.schema.json#/$defs/risk.
153
+ */
154
+ export type Risk = 'LOW' | 'MEDIUM' | 'HIGH';
155
+ /**
156
+ * Risk low to high, from the schema's declared order.
157
+ *
158
+ * TypeScript has no derived ordering, so the ladder is a value and the
159
+ * comparison is a function. §8.4 composes with max, so `max` is what
160
+ * callers need and index arithmetic is what they must not write.
161
+ */
162
+ export declare const RISK_ORDER: readonly Risk[];
163
+ export declare function maxRisk(a: Risk, b: Risk): Risk;
164
+ /**
165
+ * The WebAuthn relying-party identifier the credential was created for: the
166
+ * approval page's host, lower-case, no scheme, no port, no path (e.g.
167
+ * `approve.example.com`). Stored PER ENTRY because that is what the
168
+ * credential itself is bound to; HM-4 (c) requires the assertion's origin to
169
+ * be exactly `https://` + this, and (d) requires `rpIdHash` = SHA-256 of it.
170
+ * Signed policy: an assertion for any other origin is an assertion made on
171
+ * another site, which is the phishing case this field refuses.
172
+ * Generated from attesters.schema.json#/$defs/rp_id.
173
+ *
174
+ * The schema constrains this to `^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?)+$`, which is NOT enforced here.
175
+ */
176
+ export type RpId = string;
177
+ /**
178
+ * A suite NAME as it appears on the wire.
179
+ *
180
+ * DELIBERATELY NOT ORDERED. There is no `x-acp-ordered` here and there must
181
+ * not be one: CR-4's floor is satisfied by CONTAINMENT of primitives, not by
182
+ * rank. A generated `Ord` would make `declared >= floor` compile, and that
183
+ * comparison is the downgrade — `ed25519` and `slhdsa128s` are incomparable,
184
+ * not adjacent. The behavioural type is `acp_crypto::Suite`, which carries
185
+ * `satisfies_floor` and `primitives()`; this is the wire name and nothing
186
+ * more.
187
+ *
188
+ * NOT `const`. Listing only the hybrid suite would make a bundle signed
189
+ * under `ed25519` fail SHAPE validation, when the required outcome is a CR-4
190
+ * refusal naming the floor. Unknown names outside this list are refused
191
+ * under CR-1 by the loader, never defaulted to a known suite. THIS IS ALSO
192
+ * THE WIRE ROOT'S `SuiteId` (ACP-78 M1): the Decision Receipt's `alg`
193
+ * `$ref`s this declaration across roots. CR-4 compares a receipt's suite
194
+ * against the floor registered here, so the two artifacts must draw from ONE
195
+ * set -- two enums that merely look alike is the comparison passing on a
196
+ * vocabulary nobody checked.
197
+ * Generated from signature.schema.json#/$defs/suite_id.
198
+ */
199
+ export type SuiteId = 'ed25519' | 'hybrid-ed25519-mldsa65' | 'slhdsa128s';
200
+ /**
201
+ * One tenant, named once, in signed policy. Declared here and CARRIED by
202
+ * every wire message that names a tenant -- the receipt, the ledger claim,
203
+ * the pending-release record, the audit record and the anchor all `$ref`
204
+ * this definition -- because the bundle is what says which tenant a decision
205
+ * belongs to (RAD-5) and a message can only repeat it. Same direction as
206
+ * `SuiteId` and `Tier`: policy defines, messages carry. Through ACP-78 M1
207
+ * this was the wire root's one `TenantId`, homed on the ledger claim; it
208
+ * moved here with RAD-5 (v1.3.23) when the bundle gained the field, so that
209
+ * the manifest's copy and the messages' copies cannot be two types.
210
+ *
211
+ * IN A MESSAGE IT NAMES A NAMESPACE AND DOES NOT AUTHORISE ONE (RES-8). CL-5
212
+ * permits both topologies -- one ledger per tenant, or one ledger keyed by
213
+ * tenant -- and under the first this value is redundant with the instance
214
+ * the Executor is connected to. It is carried under both so that one claim
215
+ * has one encoding rather than two, which is the Z4 rule applied to a
216
+ * deployment choice. A ledger that RESOLVES which tenant's namespace to use
217
+ * from this field, rather than from the authenticated connection, has let
218
+ * the claimant pick its own scope; EX-1 scopes the Executor's credentials
219
+ * per tenant precisely so the connection is the thing that answers.
220
+ *
221
+ * THE MAXIMUM IS L-04's AND ITS SCOPE IS CONTESTED. This declaration is the
222
+ * wire root's one `TenantId`, and it was five declarations with three bounds
223
+ * before ACP-78 M1: unbounded here, 2,048 in the audit record and the
224
+ * anchor, 128 in the receipt and the pending-release record. Two lengths for
225
+ * one value means a tenant nameable in one artifact and unnameable in the
226
+ * artifact that produced it, so one bound was kept -- the only one any
227
+ * clause states. L-04 reads `max string field length 2,048 chars. No
228
+ * exceptions` with `Schema` as its enforcement point. It is applied here and
229
+ * the reading is disclosed rather than assumed: L-04's neighbours L-03,
230
+ * L-05, L-06 and L-07 are all about TENANT-REGISTERED schemas, so `Schema`
231
+ * may well scope it there, and read literally across every wire string it
232
+ * makes CR-6's hybrid floor unsatisfiable -- an ML-DSA-65 signature is 4,412
233
+ * base64 characters. AB-6's rationale separately treats `tenant_id` length
234
+ * as deployment-variable in as many words. Whichever way the document
235
+ * settles that, this file states one length rather than three.
236
+ * Generated from manifest.schema.json#/$defs/tenant_id.
237
+ */
238
+ export type TenantId = string;
239
+ /**
240
+ * T0 public/sandbox · T1 internal · T2 production · T3 privileged. Ordered:
241
+ * T0 < T1 < T2 < T3, and §8.4 composes tiers with max, so the ordering is
242
+ * load-bearing rather than cosmetic. THIS IS ALSO THE WIRE ROOT'S `Tier`
243
+ * (ACP-78 M1): `spec/schemas/wire/context_read.schema.json` `$ref`s this
244
+ * declaration across roots rather than restating it, because TR-3 composes
245
+ * the FLOOR from this table with the RAISE from the Context read using
246
+ * `max`, and a value nameable in one and not the other leaves that `max`
247
+ * undefined. It was declared in both roots until M1, character for
248
+ * character, each copy carrying a note saying the two must move together.
249
+ * Generated from floors.schema.json#/$defs/tier.
250
+ */
251
+ export type Tier = 'T0' | 'T1' | 'T2' | 'T3';
252
+ /**
253
+ * Tier low to high, from the schema's declared order.
254
+ *
255
+ * TypeScript has no derived ordering, so the ladder is a value and the
256
+ * comparison is a function. §8.4 composes with max, so `max` is what
257
+ * callers need and index arithmetic is what they must not write.
258
+ */
259
+ export declare const TIER_ORDER: readonly Tier[];
260
+ export declare function maxTier(a: Tier, b: Tier): Tier;
261
+ /**
262
+ * Which key type HM-4 (e) verifies under: ES256 (ECDSA P-256 with SHA-256,
263
+ * DER-encoded, COSE alg -7 -- what every authenticator supports) or Ed25519
264
+ * (COSE alg -8, RFC 8032 under ACP-106's strict rule). An attestation-entry
265
+ * suite only: CR-8 forbids either as a bundle, receipt or door suite, and
266
+ * neither is compared against `min_suite` -- a human leg is outside the
267
+ * floor by construction, and HM-6 states the cost.
268
+ * Generated from attesters.schema.json#/$defs/webauthn_alg.
269
+ */
270
+ export type WebauthnAlg = 'webauthn-es256' | 'webauthn-ed25519';
271
+ /**
272
+ * Maps each registered `schema_id` to the fidelity class of the ingress
273
+ * adapter that produces Proposals under it. This is the "bundle-registered
274
+ * adapter binding" §9.3 step 7 tells the Executor to verify `fidelity`
275
+ * against, and it is the last bundle table on the decision path to get a
276
+ * schema (ACP-73).
277
+ *
278
+ * A CONTROL INPUT, NOT METADATA. The value looked up here is bound into the
279
+ * EL-1 environment as `fidelity` (`acp_executor.py`, `recompute_risk`), so
280
+ * any `raise_to` clause can read it and it can raise or fail to raise a
281
+ * grade; FC-2 keys the confirmation requirement on it; and §9.3 step 7a
282
+ * makes disagreement between this table and the receipt's transmitted
283
+ * `fidelity` a CRITICAL ALERT (T-18), which the reference raises at
284
+ * `acp_executor.py`'s `execute` under TR-8. It is inside the bundle hash
285
+ * (`Bundle.hash`), so it is signed policy, and PB-4 makes it read-only to
286
+ * the runtime by cryptography.
287
+ *
288
+ * ABSENCE IS REFUSED, NEVER DEFAULTED, AND JSON SCHEMA CANNOT SAY SO. The
289
+ * reference is `Bundle.recompute_fidelity`: a `schema_id` with no entry here
290
+ * raises `FailClosed("TR-8", "schema_id not bound to a registered
291
+ * adapter")`, and the simulation's Policy Engine turns the same refusal into
292
+ * a DENY at §8.4 step 2 (`sim/policy.py`). The rule is carried by the
293
+ * `x-acp-absent` annotation below and GENERATED into the accessor in both
294
+ * languages, the `RiskFunctions` / `NoticeTargets` shape rather than the
295
+ * `Floors` / `Reversibility` default-value shape, because there is no
296
+ * fail-safe class to fall back to: defaulting to F-HIGH suppresses FC-2's
297
+ * confirmation exactly as a forged stamp would (X1), and defaulting to F-LOW
298
+ * looks conservative but is a policy value the implementation invented for
299
+ * an adapter nobody registered. P-4: unknown is refused. The WHOLE table is
300
+ * likewise required, not optional -- the reference `Bundle` dataclass gives
301
+ * `adapters` no default, so a bundle without it fails to construct rather
302
+ * than acquiring an empty registry that refuses every Proposal for a reason
303
+ * nobody wrote down.
304
+ *
305
+ * WHY A MAP AND NOT A ROW ARRAY. FC-1 says every adapter declares EXACTLY
306
+ * ONE fidelity class. A map keyed by `schema_id` cannot carry two classes
307
+ * for one id, so the schema enforces FC-1 by shape; an array of `{schema_id,
308
+ * fidelity}` rows would need the loader's duplicate-key refusal that
309
+ * `risk_functions.json` needs for `applies_to`.
310
+ *
311
+ * WHAT THIS SCHEMA FOUND. Until it existed the TR-8 refusal was a
312
+ * hand-written `if` in the Python reference and a hand-written `let ...
313
+ * else` in `crates/acp-decision` (ACP-45 slice 3, disclosed there rather
314
+ * than typed), and `tools/codegen.sh` emitted no type and no accessor for
315
+ * the one table whose miss suppresses a confirmation. It also found that
316
+ * §8.2's bundle tree names NO FILE for this binding: `floors.json`,
317
+ * `reversibility.json`, `notice_targets.json` and `risk_functions.json` are
318
+ * listed and `adapters.json` is not, although §9.3 step 7 and FC-1 both
319
+ * require the binding to be bundle-registered. The file name here follows
320
+ * its four siblings; the §8.2 listing is reported as a normative gap, not
321
+ * silently closed by this file. And the fidelity vocabulary had been
322
+ * declared in the WIRE root (`proposal.schema.json`) with no signed table to
323
+ * draw from -- the value the Executor compares a receipt against lived only
324
+ * on the side being verified. It is declared once, below, and the wire root
325
+ * now `$ref`s it, exactly as `Tier` and `SuiteId` are homed in
326
+ * `floors.schema.json` and `signature.schema.json` (ACP-78 M1).
327
+ *
328
+ * A-7 applies here as it does to floors and reversibility: that an adapter's
329
+ * declared class is HONEST is conceded unprovable. An F-LOW adapter
330
+ * registered as F-HIGH defeats FC-2 with zero attack, and no verifier can
331
+ * tell from this file. Registration is the governance task; this file is
332
+ * where that risk concentrates.
333
+ * Generated from adapters.schema.json.
334
+ */
335
+ export interface Adapters {
336
+ readonly schemaVersion: '1';
337
+ /**
338
+ * schema_id -> fidelity class. Open map (schemas are deployment-specific),
339
+ * closed values. The key space is the Proposal's `schema_id` (SR-1's
340
+ * identifier half) and is `$ref`d rather than restated so the two spellings
341
+ * cannot drift; note that `tools/codegen.sh` resolves the `$ref` under
342
+ * `propertyNames` (it halts on one it cannot resolve, ACP-128) and carries
343
+ * its description into both languages' doc comments, but still emits map
344
+ * keys as plain strings, so the key constraint is documentary until a
345
+ * validator reads it (ACP-52).
346
+ *
347
+ * Map keys: A registered `schema_id`, the same identifier a Proposal carries
348
+ * and the Executor looks this table up by (§9.3 step 7).
349
+ */
350
+ readonly adapters: Readonly<Record<string, FidelityClass>>;
351
+ }
352
+ /**
353
+ * Look up one entry in Adapters.adapters.
354
+ *
355
+ * TR-8: a schema_id bound to no registered adapter is REFUSED, never
356
+ * defaulted. `fidelity` is readable by any raise_to clause and FC-2 keys
357
+ * confirmation on it, so there is no fail-safe class to fall back to: F-HIGH
358
+ * suppresses the confirmation requirement exactly as a forged stamp would
359
+ * (X1, T-18), and F-LOW is a policy value the implementation invented for an
360
+ * adapter nobody registered. A lookup returning `Option` here would let a
361
+ * caller write `unwrap_or_default()` and grade a Proposal from an
362
+ * unregistered ingress on a class nobody signed.
363
+ *
364
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
365
+ */
366
+ export type AdaptersLookup = {
367
+ readonly present: true;
368
+ readonly value: FidelityClass;
369
+ } | {
370
+ readonly present: false;
371
+ readonly clause: string;
372
+ readonly why: string;
373
+ };
374
+ export declare function adaptersLookup(table: Adapters, key: string): AdaptersLookup;
375
+ /**
376
+ * The lenient projection of Adapters: every field optional, every enum
377
+ * degraded to `string`. What a verifier parses. Never make a decision on
378
+ * one — the fail-safe lookups live on the strict type only.
379
+ */
380
+ export interface RawAdapters {
381
+ readonly schemaVersion?: string;
382
+ readonly adapters?: Readonly<Record<string, string>>;
383
+ }
384
+ /**
385
+ * Maps each class of critical alert to the parties woken when one is raised.
386
+ * PB-10 (v1.3.23).
387
+ *
388
+ * WHY THIS FILE EXISTS. Twenty-odd sentences in ZIFFER-SPEC-001 end in 'with
389
+ * a critical alert' and, through v1.3.22, none said to whom. Every
390
+ * implementation therefore chose its own audience -- the notifier's
391
+ * configuration, the KMS's, the deployment's -- and a service that selects
392
+ * its own alert audience is certifying its own coverage: RES-8, and the
393
+ * exact shape of the still-open finding T-32 one component over. It surfaced
394
+ * while the KMS was built as a service, where every 'critical alert'
395
+ * sentence landed on a seam whose only implementation was a no-op (ACP-134).
396
+ *
397
+ * WHY THE MECHANISM IS notice_targets' AND NOT A NEW ONE. DR-13(2) already
398
+ * solved this problem for the fast-path notice: the recipient set is read
399
+ * from the signed bundle, keyed by class, inside policy_bundle_hash, and a
400
+ * class naming nobody fails closed because a notice with no addressee is not
401
+ * a detection channel. It is mutation-proven. Alerts take the identical
402
+ * mechanism -- two mechanisms for one problem is the two-definitions defect
403
+ * this repository has published corrections for three times -- and this file
404
+ * is notice_targets.schema.json with the key set changed.
405
+ *
406
+ * COMPLETENESS FAILS CLOSED AT LOAD, AND JSON SCHEMA CANNOT SAY SO. PB-10
407
+ * enumerates the alert classes and requires every one of them to name at
408
+ * least one recipient; a bundle missing any is invalid and MUST be refused
409
+ * at load by every consumer, on PB-1's footing. The list of classes is owned
410
+ * by the clause, not by this file -- a `required` list here would be a
411
+ * second definition of it -- so the enforcement point is the loader, as with
412
+ * PB-7 in attesters.schema.json. A normative rule with no enforcement point
413
+ * is a comment. Why load-time and not raise-time: a notice's 'fail closed'
414
+ * has an action to withhold, but an alert is raised on a path that has
415
+ * already failed, so refusing at raise time would withhold nothing. What can
416
+ * be withheld is the bundle: a deployment either names who is woken for each
417
+ * class, or it does not run.
418
+ *
419
+ * WHAT IS NOT DECIDED HERE: the transport of an alert (pager, queue,
420
+ * webhook) and what acknowledgement closes it. Those are deployment
421
+ * obligations in DR-12's shape -- silence as measurable debt -- and belong
422
+ * in ZIFFER-DEPLOY-001. Identities, not addresses, for notice_targets'
423
+ * reason: an address is a routing detail that changes without a policy
424
+ * review, and putting one under an offline signing key makes routine
425
+ * operations require RK-5.
426
+ * Generated from alert_targets.schema.json.
427
+ */
428
+ export interface AlertTargets {
429
+ readonly schemaVersion: '1';
430
+ /**
431
+ * alert class -> recipient identities. Keys are the classes PB-10 enumerates
432
+ * (BUNDLE_INVALID, SIGNING_SUBSTRATE, RECEIPT_INVALID,
433
+ * RECOMPUTATION_MISMATCH, ATTESTATION_INVALID, LEDGER_REPLAY,
434
+ * SUITE_BELOW_FLOOR, DEFERRED_RELEASE, AUDIT_INTEGRITY,
435
+ * ATTESTATION_QUEUE_DEPTH, CONTEXT_STORE); the map is open here so that the
436
+ * clause, not this file, owns the list, and the loader refuses a bundle in
437
+ * which any of them is missing. Every value is a non-empty set: an empty
438
+ * array is REFUSED rather than read as 'wake nobody', because the two are
439
+ * indistinguishable at run time from an entry never written, and the
440
+ * fail-safe reading of both is refusal.
441
+ *
442
+ * Schema constraints, carried as documentation and NOT enforced by this
443
+ * type: values minItems 1, uniqueItems; values items minLength 1, maxLength
444
+ * 128.
445
+ */
446
+ readonly alertTargets: Readonly<Record<string, readonly string[]>>;
447
+ }
448
+ /**
449
+ * Look up one entry in AlertTargets.alert_targets.
450
+ *
451
+ * PB-10: an alert with no addressee is not a detection channel. PB-10
452
+ * requires every class to be present at load, so a miss here means a loader
453
+ * skipped PB-10 -- and the generated accessor refuses rather than returning
454
+ * an Option a caller could unwrap_or_default() into silence. Same rule as
455
+ * notice_targets, and deliberately not a value default: there is no
456
+ * fail-safe recipient.
457
+ *
458
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
459
+ */
460
+ export type AlertTargetsLookup = {
461
+ readonly present: true;
462
+ readonly value: readonly string[];
463
+ } | {
464
+ readonly present: false;
465
+ readonly clause: string;
466
+ readonly why: string;
467
+ };
468
+ export declare function alertTargetsLookup(table: AlertTargets, key: string): AlertTargetsLookup;
469
+ /**
470
+ * The lenient projection of AlertTargets: every field optional, every enum
471
+ * degraded to `string`. What a verifier parses. Never make a decision on
472
+ * one — the fail-safe lookups live on the strict type only.
473
+ */
474
+ export interface RawAlertTargets {
475
+ readonly schemaVersion?: string;
476
+ readonly alertTargets?: Readonly<Record<string, readonly string[]>>;
477
+ }
478
+ /**
479
+ * The approver and confirmer verification keys, and the quorum k.
480
+ *
481
+ * PUBLIC KEYS ONLY. This is not a stylistic constraint — it is the v1.3.14
482
+ * custody fix, and it closed a real hole. Through v1.3.13 the primitives
483
+ * were HMAC-SHA256, so verifying a signature required holding the key that
484
+ * made it: the Executor held every attester key and could therefore MINT ITS
485
+ * OWN QUORUM. INV-1-HIGH did not hold against the very adversary it names,
486
+ * and no protocol test could have found it, because the defect was key
487
+ * CUSTODY rather than control flow. Never reintroduce a symmetric primitive
488
+ * here, not even for tests.
489
+ *
490
+ * PB-KEY: this registry is INSIDE the bundle hash. A `policy_bundle_hash`
491
+ * that does not cover it lets two Executors trusting DIFFERENT attesters
492
+ * agree that they hold the same bundle — which is the encoding-split defect
493
+ * wearing a key registry as a hat.
494
+ *
495
+ * ACK-4 (reference-level, see reference/src/acp_ack.py — not a spec clause):
496
+ * an attester's identity is the one the SIGNATURE covers, never a
497
+ * transmitted `attester_id` field. This registry maps identity to key so
498
+ * that the signature can establish which of these entries signed. It does
499
+ * not authorise anyone to name themselves.
500
+ * Generated from attesters.schema.json.
501
+ */
502
+ export interface AttesterRegistry {
503
+ readonly schemaVersion: '1';
504
+ /**
505
+ * How many DISTINCT attesters must sign the same canonical hash for a
506
+ * floor-HIGH action. INV-1-HIGH. k=1 is permitted by the schema and is a
507
+ * deployment choice, not a conformance failure — but it collapses the
508
+ * invariant to single-compromise, so a deployment choosing it should say so
509
+ * in its residual risk statement rather than discover it later.
510
+ *
511
+ * DR-9 is enforced separately and is not expressible here: whoever proposed
512
+ * the action can never be among the k.
513
+ *
514
+ * Schema constraints, carried as documentation and NOT enforced by this
515
+ * type: minimum 1.
516
+ */
517
+ readonly quorumK: number;
518
+ /**
519
+ * attester identity -> a machine's hybrid public key or a human's WebAuthn
520
+ * credential (`kind` tells which, HM-1, v1.3.30). Open map (people are
521
+ * deployment-specific), closed entries.
522
+ *
523
+ * PB-DISTINCT (NORMATIVE, and NOT EXPRESSIBLE HERE): no two identities may
524
+ * carry the same public key. `quorum_k` counts DISTINCT KEY HOLDERS; a
525
+ * registry mapping two names onto one key lets the holder of that one
526
+ * private key sign two objects with different nonces, label them with the
527
+ * two names, and satisfy a k=2 quorum alone. INV-1-HIGH broken by a single
528
+ * compromise, reached through the registry rather than through the
529
+ * threshold.
530
+ *
531
+ * JSON Schema cannot state this: `uniqueItems` applies to arrays, and there
532
+ * is no keyword for uniqueness across the VALUES of a map. The rule is
533
+ * therefore enforced by the LOADER, and a loader that does not enforce it is
534
+ * non-conformant however cleanly it validates. Reference implementation:
535
+ * `Bundle.__post_init__` in reference/src/acp_executor.py, which refuses at
536
+ * construction — a bundle whose registry cannot support its own quorum is
537
+ * malformed everywhere it is used, not only on the quorum path. Compare over
538
+ * the full hybrid identity, not the classical half alone; two identities
539
+ * sharing only an ML-DSA key is CR-3 undone at the registry.
540
+ */
541
+ readonly attesters: Readonly<Record<string, Attester>>;
542
+ /**
543
+ * AT-10: the minimum authenticator assurance every attestation counted
544
+ * toward a quorum must clear. OPTIONAL, and absent means AS0 — the
545
+ * permissive reading, taken deliberately and disclosed in the same breath,
546
+ * exactly as `quorum_k: 1` is permitted and must be disclosed (PB-6): a
547
+ * floor nobody chose must not silently invalidate every registry written
548
+ * before the field existed, and AS0 is what those registries were already
549
+ * getting. A deployment claiming any Door A property stronger than key
550
+ * possession raises this floor; the EU AI Act Art. 14(5) reading of 'two
551
+ * natural persons' is not supported at AS0 and a deployment at AS0 should
552
+ * say so in its residual risk statement.
553
+ */
554
+ readonly minAttesterAssurance?: Assurance;
555
+ /**
556
+ * AT-10: attester identity -> the assurance level that identity's key was
557
+ * ENROLLED at, over $defs/assurance. A SEPARATE map beside `attesters`
558
+ * rather than a field inside each entry, deliberately: every implementation
559
+ * carries it this way on the wire (the reference Bundle's dict, the
560
+ * differential bridge, the Rust QuorumPolicy), and the map shape is what
561
+ * gives the generated fail-safe accessor an absent rule to answer with -- an
562
+ * identity missing from this map reads AS0, a claim's safe default, inverted
563
+ * from RK-1's floors: an entry claiming less than it has can only cause a
564
+ * refusal, one defaulting to more than it has is the attack. What no field
565
+ * here can carry is honesty: whether a key is REALLY hardware-bound is
566
+ * established at enrolment by humans, and a wrong label is A-7's conceded
567
+ * shape, stated at AT-10.
568
+ */
569
+ readonly assurance?: Readonly<Record<string, Assurance>>;
570
+ }
571
+ /**
572
+ * Look up one entry in AttesterRegistry.attesters.
573
+ *
574
+ * AT-9, PB-6: an identity absent from the signed registry is not an
575
+ * attester. Its signature verifies against no key here and counts toward no
576
+ * quorum, and resolving it to a default would let a name nobody enrolled
577
+ * satisfy INV-1-HIGH. ACK-4: identity is what the SIGNATURE covers, never a
578
+ * transmitted `attester_id` — this map is how a signature is resolved to an
579
+ * enrolled key, not how a name authorises itself.
580
+ *
581
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
582
+ */
583
+ export type AttesterRegistryLookup = {
584
+ readonly present: true;
585
+ readonly value: Attester;
586
+ } | {
587
+ readonly present: false;
588
+ readonly clause: string;
589
+ readonly why: string;
590
+ };
591
+ export declare function attesterRegistryAttestersLookup(table: AttesterRegistry, key: string): AttesterRegistryLookup;
592
+ /**
593
+ * Look up one entry in AttesterRegistry.assurance.
594
+ *
595
+ * AT-10: an identity with no recorded level is read as AS0 -- for a CLAIM
596
+ * the low default is the fail-safe one. Resolving it upward would let an
597
+ * unlabelled key satisfy a floor nobody vouched it for.
598
+ *
599
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
600
+ */
601
+ export declare function attesterRegistryAssuranceLookup(table: AttesterRegistry, key: string): Assurance;
602
+ /**
603
+ * `AttesterRegistry.min_attester_assurance`, with the schema's absent rule
604
+ * applied.
605
+ *
606
+ * AT-10: the floor is POLICY, and its permissive default is taken openly and
607
+ * disclosed on PB-6's terms (quorum_k = 1): a floor nobody chose must not
608
+ * silently invalidate every registry written before the field existed. A
609
+ * deployment claiming any Door A property stronger than key possession
610
+ * raises it.
611
+ *
612
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
613
+ */
614
+ export declare function attesterRegistryMinAttesterAssurance(doc: AttesterRegistry): Assurance;
615
+ /**
616
+ * The lenient projection of AttesterRegistry: every field optional, every enum
617
+ * degraded to `string`. What a verifier parses. Never make a decision on
618
+ * one — the fail-safe lookups live on the strict type only.
619
+ */
620
+ export interface RawAttesterRegistry {
621
+ readonly schemaVersion?: string;
622
+ readonly quorumK?: number;
623
+ readonly attesters?: Readonly<Record<string, string>>;
624
+ readonly minAttesterAssurance?: string;
625
+ readonly assurance?: Readonly<Record<string, string>>;
626
+ }
627
+ /**
628
+ * How the bundle signing key is held.
629
+ *
630
+ * CLASSIFIED **T** (trusted as transmitted) AND NOT A CONTROL INPUT. A
631
+ * verifier MUST NOT weight any decision on this object. A bundle asserting
632
+ * its own custody strength is the recurring defect RES-8/RES-9/RES-10 names:
633
+ * a verifier must never accept a derived security value from the party it is
634
+ * verifying. A compromised signer writes this object freely.
635
+ *
636
+ * It is recorded for humans — auditors, operators, and the reviewer named
637
+ * above — and for no other purpose. The real binding is that the verifier is
638
+ * configured out of band with the expected public key.
639
+ * Generated from manifest.schema.json#/$defs/custody.
640
+ */
641
+ export interface Custody {
642
+ /**
643
+ * T0 development only; T1 encrypted key on an air-gapped host; T2
644
+ * non-exportable cloud KMS; T3 PKCS#11 HSM. Split custody reports the WEAKER
645
+ * of its two legs, because a claim should never round in the flattering
646
+ * direction.
647
+ *
648
+ * The SAME four values as a resource floor, drawn from `floors.schema.json`
649
+ * so there is one definition of the tier ladder. Note that the two uses are
650
+ * unrelated in meaning: a resource floor says how sensitive a thing is, a
651
+ * custody tier says how a key is held. They share a scale, not a subject.
652
+ */
653
+ readonly tier: Tier;
654
+ readonly classical: CustodyLeg;
655
+ readonly pq: CustodyLeg;
656
+ }
657
+ /**
658
+ * The lenient projection of Custody: every field optional, every enum
659
+ * degraded to `string`. What a verifier parses. Never make a decision on
660
+ * one — the fail-safe lookups live on the strict type only.
661
+ */
662
+ export interface RawCustody {
663
+ readonly tier?: string;
664
+ readonly classical?: RawCustodyLeg;
665
+ readonly pq?: RawCustodyLeg;
666
+ }
667
+ /**
668
+ * Custody of one primitive. The two legs may differ, and differing is not a
669
+ * weakness: verification is conjunctive (CR-3), so forging requires BOTH
670
+ * signatures and therefore BOTH keys. An attacker must defeat both
671
+ * mechanisms.
672
+ * Generated from manifest.schema.json#/$defs/custody_leg.
673
+ */
674
+ export interface CustodyLeg {
675
+ readonly tier: Tier;
676
+ /**
677
+ * Free text naming the concrete mechanism, e.g. "YubiHSM2 slot 3" or
678
+ * "age-encrypted file, offline laptop". Human-readable only.
679
+ *
680
+ * Schema constraints, carried as documentation and NOT enforced by this
681
+ * type: minLength 1, maxLength 256.
682
+ */
683
+ readonly mechanism: string;
684
+ }
685
+ /**
686
+ * The lenient projection of CustodyLeg: every field optional, every enum
687
+ * degraded to `string`. What a verifier parses. Never make a decision on
688
+ * one — the fail-safe lookups live on the strict type only.
689
+ */
690
+ export interface RawCustodyLeg {
691
+ readonly tier?: string;
692
+ readonly mechanism?: string;
693
+ }
694
+ /**
695
+ * Names the two services whose summaries the Executor consumes during a
696
+ * deferred-release hold, each with the verification keys its Rendered
697
+ * Summary objects (DR-14; notification.schema.json `$defs/rendered_summary`)
698
+ * are signed under. PB-11 (v1.3.25).
699
+ *
700
+ * WHY THIS FILE EXISTS. From v1.3.6 to v1.3.24 the Executor established
701
+ * DR-2's independence -- the notification path shares no rendering code with
702
+ * the approval path -- by comparing two labels the notification service
703
+ * chose (`source_path`) and reading a boolean it set (`from_canonical`).
704
+ * Both were classified T in ACP-CLASS-001 (rows 24-25, finding T-32):
705
+ * evidence about a service, produced by that service. A compromised notifier
706
+ * that rendered through the approval path, labelled itself otherwise and
707
+ * reported full delivery passed every check, and
708
+ * `reference/suites/class_findings.py` demonstrated it for thirteen
709
+ * revisions. The structural reason was recorded in notification.schema.json:
710
+ * the notification was not a signed structure, so there were no bytes to
711
+ * verify. This file supplies the keys those bytes are now verified under.
712
+ *
713
+ * WHY THE MECHANISM IS THE ATTESTER REGISTRY'S AND NOT A NEW ONE. Who may
714
+ * speak for a door is the same kind of value as who may attest (PB-6, PB-7),
715
+ * who is told (DR-13) and who is woken (PB-10): a service that names its own
716
+ * identity is certifying its own independence, RES-8. So the identities sit
717
+ * in signed policy under RK-5 two-person control, in the attester registry's
718
+ * key shape -- one Ed25519 and one ML-DSA-65 verification key, the same
719
+ * named scalars -- and the loader applies PB-7's distinctness rule across
720
+ * the two: compared over the COMPLETE suite, because two identities sharing
721
+ * a post-quantum key are not distinct, and treating them as such is CR-3's
722
+ * conjunctive guarantee undone at the registry instead of at the verifier.
723
+ *
724
+ * DISTINCTNESS FAILS CLOSED AT LOAD, AND JSON SCHEMA CANNOT SAY SO.
725
+ * `presentation` and `notification` are both required here, so an absent one
726
+ * is a schema violation as well as a PB-11 refusal; but 'the two share no
727
+ * key' is a relation across two values, and there is no keyword for it. As
728
+ * with PB-7 in attesters.schema.json the enforcement point is the loader: a
729
+ * bundle in which either key of one door equals the corresponding key of the
730
+ * other is refused at load by every consumer, on PB-1's footing. A normative
731
+ * rule with no enforcement point is a comment.
732
+ *
733
+ * WHAT A KEY HERE DOES NOT PROVE. A Rendered Summary that verifies under the
734
+ * `notification` key was produced by the holder of that key, for the
735
+ * proposal hash it names. That the prose is faithful to those bytes is
736
+ * DR-2's STRUCTURAL requirement -- no shared rendering path, demonstrated at
737
+ * build time under conformance suite 3 -- and no signature supplies it. A
738
+ * signature over a lie is a signed lie; what it can no longer be is a lie
739
+ * told by the other door.
740
+ *
741
+ * WHAT IS DELIBERATELY NOT HERE. Addresses, endpoints, channels: identities
742
+ * rather than routing, for notice_targets' and alert_targets' reason -- a
743
+ * routing detail changes without a policy review, and putting one under an
744
+ * offline signing key makes routine operations require RK-5. And no third
745
+ * role: the fast-path notice (DR-13) is committed by the Executor to its own
746
+ * state and involves no service, so it needs no identity.
747
+ * Generated from door_identities.schema.json.
748
+ */
749
+ export interface DoorIdentities {
750
+ readonly schemaVersion: '1';
751
+ /**
752
+ * The Attestation Presentation Service: the approval path, the door the
753
+ * attesters were shown the action through. Its key signs the approval
754
+ * summary the Executor compares against the notification at DR-14.
755
+ */
756
+ readonly presentation: DoorIdentity;
757
+ /**
758
+ * The notification service: DR-2's independent path, the door the
759
+ * out-of-band summary reaches the attesters and the operator through. Its
760
+ * key signs the Notification (DR-3 leg). A summary that verifies under this
761
+ * key was not produced by the presentation service -- which is the whole of
762
+ * what deferred release needs the second door for.
763
+ */
764
+ readonly notification: DoorIdentity;
765
+ }
766
+ /**
767
+ * The lenient projection of DoorIdentities: every field optional, every enum
768
+ * degraded to `string`. What a verifier parses. Never make a decision on
769
+ * one — the fail-safe lookups live on the strict type only.
770
+ */
771
+ export interface RawDoorIdentities {
772
+ readonly schemaVersion?: string;
773
+ readonly presentation?: RawDoorIdentity;
774
+ readonly notification?: RawDoorIdentity;
775
+ }
776
+ /**
777
+ * `DoorIdentity`.
778
+ * Generated from door_identities.schema.json#/$defs/door.
779
+ */
780
+ export interface DoorIdentity {
781
+ /**
782
+ * The identity's name, for the audit record and the alert. NOT what the
783
+ * Executor resolves a signature by -- ACK-4's rule applies here too:
784
+ * identity is what the signature verifies under, and this name is a label
785
+ * for the key beside it, never a way for a name to authorise itself.
786
+ *
787
+ * Schema constraints, carried as documentation and NOT enforced by this
788
+ * type: minLength 1, maxLength 128.
789
+ */
790
+ readonly name: string;
791
+ /**
792
+ * The door's Ed25519 verification key. The attester registry's named scalar,
793
+ * referenced rather than re-declared: one definition of a key encoding.
794
+ */
795
+ readonly classical: Ed25519PublicKey;
796
+ /**
797
+ * The door's ML-DSA-65 verification key. Both legs are required because CR-3
798
+ * is conjunctive and the bundle's suite names both; a door registered with
799
+ * one leg would be a door whose summaries can never verify.
800
+ */
801
+ readonly pq: MlDsa65PublicKey;
802
+ }
803
+ /**
804
+ * The lenient projection of DoorIdentity: every field optional, every enum
805
+ * degraded to `string`. What a verifier parses. Never make a decision on
806
+ * one — the fail-safe lookups live on the strict type only.
807
+ */
808
+ export interface RawDoorIdentity {
809
+ readonly name?: string;
810
+ readonly classical?: string;
811
+ readonly pq?: string;
812
+ }
813
+ /**
814
+ * Maps each governable resource to its floor tier.
815
+ *
816
+ * RK-1: a resource ABSENT from this file MUST be treated as T3. That rule
817
+ * cannot be expressed in JSON Schema — a schema constrains what is present,
818
+ * never what is missing — so it is carried instead by the `x-acp-absent`
819
+ * annotation on `floors` below, which `tools/codegen.sh` reads to GENERATE
820
+ * the fail-safe direction into `Tier::for_unclassified()` (crates/acp-core)
821
+ * and its TypeScript equivalent. The Python reference spells the same
822
+ * default at `acp_executor.py`. A conformance case asserts it, because a
823
+ * fail-safe default that only exists in a comment is not a control — and
824
+ * stating it only in this prose is what let the Rust and TypeScript versions
825
+ * return HIGH, a RISK LEVEL, where a TIER was required.
826
+ *
827
+ * RES-1 (A-7): the architecture guarantees no runtime component evaluates a
828
+ * resource BELOW its signed floor. It cannot know whether the floor was set
829
+ * correctly. A production database labelled T0 defeats the design with zero
830
+ * attack. Floor maintenance is the highest-leverage governance task in the
831
+ * system and is structurally unprovable — this file is where that risk
832
+ * concentrates.
833
+ * Generated from floors.schema.json.
834
+ */
835
+ export interface Floors {
836
+ readonly schemaVersion: '1';
837
+ /**
838
+ * resource identifier -> floor tier. Deliberately an open map: resources are
839
+ * deployment-specific. The VALUES are closed.
840
+ */
841
+ readonly floors: Readonly<Record<string, Tier>>;
842
+ }
843
+ /**
844
+ * Look up one entry in Floors.floors.
845
+ *
846
+ * RK-1: absent means unknown, and unknown is the HIGHEST tier, not the
847
+ * lowest (P-4). Returning T0 or T1 here is the whole class of defect this
848
+ * specification exists to prevent, and it is the direction a lookup
849
+ * returning `Option` invites.
850
+ *
851
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
852
+ */
853
+ export declare function floorsLookup(table: Floors, key: string): Tier;
854
+ /**
855
+ * The lenient projection of Floors: every field optional, every enum
856
+ * degraded to `string`. What a verifier parses. Never make a decision on
857
+ * one — the fail-safe lookups live on the strict type only.
858
+ */
859
+ export interface RawFloors {
860
+ readonly schemaVersion?: string;
861
+ readonly floors?: Readonly<Record<string, string>>;
862
+ }
863
+ /**
864
+ * A human attester (HM-1, v1.3.30): a person who enrolled a WebAuthn
865
+ * credential -- a passkey on their phone or laptop, or a hardware security
866
+ * key -- through a registration ceremony with user verification required and
867
+ * attestation requested. Their signature is a WebAuthn assertion over the
868
+ * same bytes a machine signs (HM-2), verified under HM-4; it is classical,
869
+ * and HM-6 says what that costs. The level recorded for this identity in
870
+ * `assurance` is DERIVED from the authenticator (platform + UV = AS1,
871
+ * roaming hardware = AS2) and an entry at AS0 or with no level is an invalid
872
+ * bundle.
873
+ * Generated from attesters.schema.json#/$defs/human_attester.
874
+ */
875
+ export interface HumanAttester {
876
+ /**
877
+ * The discriminator. `webauthn`: this identity is a person holding an
878
+ * authenticator; the entry's signature is an assertion, never a hybrid pair.
879
+ */
880
+ readonly kind: 'webauthn';
881
+ /**
882
+ * approver signs for authorisation; confirmer provides the non-operator
883
+ * positive acknowledgement DR-9 requires for irreversible actions. One
884
+ * person MAY hold both roles in the registry — DR-9 is enforced per action
885
+ * against the proposer, not by role exclusion here.
886
+ */
887
+ readonly role: AttesterRole;
888
+ readonly rpId: RpId;
889
+ readonly credentialId: CredentialId;
890
+ readonly publicKey: CoseKey;
891
+ readonly alg: WebauthnAlg;
892
+ }
893
+ /**
894
+ * The lenient projection of HumanAttester: every field optional, every enum
895
+ * degraded to `string`. What a verifier parses. Never make a decision on
896
+ * one — the fail-safe lookups live on the strict type only.
897
+ */
898
+ export interface RawHumanAttester {
899
+ readonly kind?: string;
900
+ readonly role?: string;
901
+ readonly rpId?: string;
902
+ readonly credentialId?: string;
903
+ readonly publicKey?: string;
904
+ readonly alg?: string;
905
+ }
906
+ /**
907
+ * `Identity`.
908
+ * Generated from manifest.schema.json#/$defs/identity.
909
+ */
910
+ export interface Identity {
911
+ /**
912
+ * Stable identifier. Compared byte-for-byte for PB-2; display_name is never
913
+ * used for the comparison because two people can share a display name.
914
+ *
915
+ * Schema constraints, carried as documentation and NOT enforced by this
916
+ * type: minLength 1, maxLength 128.
917
+ */
918
+ readonly id: string;
919
+ /**
920
+ * Schema constraints, carried as documentation and NOT enforced by this
921
+ * type: minLength 1, maxLength 256.
922
+ */
923
+ readonly displayName: string;
924
+ }
925
+ /**
926
+ * The lenient projection of Identity: every field optional, every enum
927
+ * degraded to `string`. What a verifier parses. Never make a decision on
928
+ * one — the fail-safe lookups live on the strict type only.
929
+ */
930
+ export interface RawIdentity {
931
+ readonly id?: string;
932
+ readonly displayName?: string;
933
+ }
934
+ /**
935
+ * The three numbers this document calls policy and no member carried: how
936
+ * long a human has to approve (L-15), how long a floor-HIGH action is held
937
+ * before release (DR-1, L-28), and what fraction of reversible releases
938
+ * draws a mandatory confirmation (DR-10, L-29). Signed, inside the tree
939
+ * hash, read by the issuer of each: the Policy Engine sets an Attestation
940
+ * Object's `expires_at` from `attestation_window_seconds`; the Executor
941
+ * builds its deferred door from the other two.
942
+ *
943
+ * WHY THIS MEMBER EXISTS (ACP-287, v1.3.30). DR-1 and DR-10 said
944
+ * `bundle-configured` since v1.3.7 and no schema had a field for either, so
945
+ * every implementation read the hold window and the sampling rate from its
946
+ * own environment -- a number this document calls signed policy, set per
947
+ * process by whoever runs it. L-15 gave the attestation window a ceiling and
948
+ * no home at all, so the one engine that issues attestations used the
949
+ * ceiling as the window and said so in its module note: shortening it would
950
+ * be that binary choosing how long a human has to approve. It was right. The
951
+ * place the number lives is here.
952
+ *
953
+ * EVERY FIELD IS OPTIONAL, AND ABSENT MEANS THE DOCUMENT'S OWN DEFAULT --
954
+ * the AT-10 precedent (`min_attester_assurance`, absent ⇒ AS0): a permissive
955
+ * reading taken openly, so that no bundle written before this member existed
956
+ * is invalidated by it, and a bundle that omits the file altogether reads as
957
+ * every field at its default. The defaults are this document's numbers and
958
+ * not an implementation's: 3600 s is L-15's ceiling and what every
959
+ * deployment had; 60 s and 10 % are the values DR-1 and DR-10 state. A
960
+ * deployment that wants the document's defaults may say nothing; one that
961
+ * wants anything else must sign it here.
962
+ *
963
+ * BOUNDS ARE REFUSALS, NOT CLAMPS. A value outside its declared range is an
964
+ * invalid bundle under PB-1 (`LimitOutOfBounds`), refused at load by every
965
+ * consumer and never rounded to the nearest legal value -- a clamped limit
966
+ * is a limit nobody chose. The bounds are the document's: L-15's ceiling,
967
+ * L-28's floor and DR-6's ceiling (a hold at or above L-14's 120 s receipt
968
+ * validity is an unsatisfiable configuration), and a percentage. A present
969
+ * file that is not an object, or a field of the wrong type, is `Malformed`.
970
+ *
971
+ * INTEGERS ONLY. A float in a signed policy file is a canonicalisation
972
+ * question -- AT-8a forbids one in a canonical structure for the reason
973
+ * `canon()` cannot encode it deterministically -- and DR-10's own unit is a
974
+ * percentage, so the fraction is carried as an integer percent. One-percent
975
+ * resolution is deliberate and disclosed: DR-10 exists to keep the detection
976
+ * channel live, not to meter it.
977
+ *
978
+ * WHAT IS NOT HERE, AND WHY. L-25 (DS-6e, the re-drive maximum,
979
+ * `bundle-configured, default 3`) and L-23 (AQ-3, queue depth per attester)
980
+ * are also called bundle-configured and have no reader in any
981
+ * implementation; a field nothing reads is documentation shaped like a
982
+ * control (the RV-1 lesson, v1.3.15), so each joins this member with its
983
+ * first reader and not before. The Executor cannot VERIFY the attestation
984
+ * window either: AT-1's object carries `expires_at` and no issue instant, so
985
+ * only the issuer knows the length. The declared value governs the issuer,
986
+ * and the bundle is signed.
987
+ * Generated from limits.schema.json.
988
+ */
989
+ export interface Limits {
990
+ readonly schemaVersion: '1';
991
+ /**
992
+ * AT-1 / L-15: the Attestation Object's `expires_at` is its issue instant
993
+ * plus this many seconds. At most 3600, L-15's ceiling. Absent ⇒ 3600, which
994
+ * is what every deployment had before this field existed and the only number
995
+ * the document stated.
996
+ *
997
+ * Schema constraints, carried as documentation and NOT enforced by this
998
+ * type: minimum 1, maximum 3600.
999
+ */
1000
+ readonly attestationWindowSeconds?: number;
1001
+ /**
1002
+ * DR-1 / L-28: how long a floor-HIGH action is held in `pending_release`
1003
+ * before it may release. At least 30 (L-28's floor: a hold too short for a
1004
+ * human to read the summary is not a detection channel), and below 120
1005
+ * (DR-6: L-14 caps receipt validity at 120 s, and a hold that can outlive
1006
+ * its receipt is an unsatisfiable configuration, refused rather than
1007
+ * silently never releasing). Absent ⇒ 60, DR-1's default.
1008
+ *
1009
+ * Schema constraints, carried as documentation and NOT enforced by this
1010
+ * type: minimum 30, maximum 119.
1011
+ */
1012
+ readonly holdWindowSeconds?: number;
1013
+ /**
1014
+ * DR-10 / L-29: the percentage of REVERSIBLE floor-HIGH actions selected for
1015
+ * mandatory acknowledgement under the DR-9 rule, drawn by the Executor from
1016
+ * a CSPRNG (DR-11). 0 is permitted by the schema and is a deployment choice
1017
+ * that switches the sampled channel off; a deployment choosing it should say
1018
+ * so in its residual risk statement. Absent ⇒ 10, DR-10's default.
1019
+ *
1020
+ * Schema constraints, carried as documentation and NOT enforced by this
1021
+ * type: minimum 0, maximum 100.
1022
+ */
1023
+ readonly samplePercent?: number;
1024
+ }
1025
+ /**
1026
+ * `Limits.attestation_window_seconds`, with the schema's absent rule
1027
+ * applied.
1028
+ *
1029
+ * L-15: the ceiling is the document's own number and the behaviour every
1030
+ * deployment had; a shorter window is a deployment's choice and must be
1031
+ * signed here to take effect.
1032
+ *
1033
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1034
+ */
1035
+ export declare function limitsAttestationWindowSeconds(doc: Limits): number;
1036
+ /**
1037
+ * `Limits.hold_window_seconds`, with the schema's absent rule applied.
1038
+ *
1039
+ * DR-1: DR-1 states the default; a bundle that says nothing gets the
1040
+ * document's number and not a process's environment.
1041
+ *
1042
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1043
+ */
1044
+ export declare function limitsHoldWindowSeconds(doc: Limits): number;
1045
+ /**
1046
+ * `Limits.sample_percent`, with the schema's absent rule applied.
1047
+ *
1048
+ * DR-10: DR-10 states the default; a bundle that says nothing gets the
1049
+ * document's number.
1050
+ *
1051
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1052
+ */
1053
+ export declare function limitsSamplePercent(doc: Limits): number;
1054
+ /**
1055
+ * The lenient projection of Limits: every field optional, every enum
1056
+ * degraded to `string`. What a verifier parses. Never make a decision on
1057
+ * one — the fail-safe lookups live on the strict type only.
1058
+ */
1059
+ export interface RawLimits {
1060
+ readonly schemaVersion?: string;
1061
+ readonly attestationWindowSeconds?: number;
1062
+ readonly holdWindowSeconds?: number;
1063
+ readonly samplePercent?: number;
1064
+ }
1065
+ /**
1066
+ * A machine attester: a service that signs with a hybrid key pair -- the
1067
+ * sandbox robot, a confirmer that is a system. The shape every registry
1068
+ * entry had before v1.3.30, plus `kind`, which every entry now carries so
1069
+ * that a human and a machine are told apart by a signed tag and never by
1070
+ * which fields happen to be present (HM-1).
1071
+ * Generated from attesters.schema.json#/$defs/machine_attester.
1072
+ */
1073
+ export interface MachineAttester {
1074
+ /**
1075
+ * The discriminator. `hybrid`: this identity signs with the two-primitive
1076
+ * pair below and is held to CR-3/CR-4.
1077
+ */
1078
+ readonly kind: 'hybrid';
1079
+ /**
1080
+ * approver signs for authorisation; confirmer provides the non-operator
1081
+ * positive acknowledgement DR-9 requires for irreversible actions. One
1082
+ * person MAY hold both roles in the registry — DR-9 is enforced per action
1083
+ * against the proposer, not by role exclusion here.
1084
+ */
1085
+ readonly role: AttesterRole;
1086
+ readonly classical: Ed25519PublicKey;
1087
+ readonly pq: MlDsa65PublicKey;
1088
+ }
1089
+ /**
1090
+ * The lenient projection of MachineAttester: every field optional, every enum
1091
+ * degraded to `string`. What a verifier parses. Never make a decision on
1092
+ * one — the fail-safe lookups live on the strict type only.
1093
+ */
1094
+ export interface RawMachineAttester {
1095
+ readonly kind?: string;
1096
+ readonly role?: string;
1097
+ readonly classical?: string;
1098
+ readonly pq?: string;
1099
+ }
1100
+ /**
1101
+ * Identity and provenance of one signed policy bundle. PB-5: bundle_epoch is
1102
+ * strictly increasing and never reused or decreased. PB-2: author and
1103
+ * reviewer identities MUST differ — asserted by the signer, because a schema
1104
+ * cannot express a comparison between two of its own fields.
1105
+ * Generated from manifest.schema.json.
1106
+ */
1107
+ export interface Manifest {
1108
+ /**
1109
+ * Version of this manifest schema. Present so a decoder can refuse a bundle
1110
+ * it does not fully understand rather than ignoring fields it does not
1111
+ * recognise.
1112
+ */
1113
+ readonly schemaVersion: '1';
1114
+ /**
1115
+ * RAD-5 (v1.3.23). The tenant this bundle governs, inside the tree hash
1116
+ * because every member is. This is the value the KMS binds a signing request
1117
+ * to (§9.1.1 step 5a) and the Executor binds a receipt to (§9.3 step 8): a
1118
+ * request or a receipt naming any other tenant is refused. Through v1.3.22
1119
+ * no bundle named its tenant, so the KMS chose which tenant's receipt key
1120
+ * signs from `tenant_id` in the request body -- a value the Policy Engine
1121
+ * wrote, i.e. the party under verification, classified T -- and the only
1122
+ * thing between tenant A's bundle and tenant B's key was a repository
1123
+ * partition a verifier cannot inspect (ACP-139). This is PB-6's move:
1124
+ * `quorum_k` went into signed policy as the only authoritative source, and
1125
+ * the tenant goes in for the same reason.
1126
+ *
1127
+ * REQUIRED, AND ABSENCE IS REFUSAL. A manifest naming no tenant is an
1128
+ * invalid bundle under PB-1 and is refused at load by every consumer -- the
1129
+ * KMS under RAD-4, the Policy Engine under PB-1, the Executor at §9.3 step
1130
+ * 4. There is no default tenant to fall back to, for the reason there is no
1131
+ * default notice recipient (DR-13): the fail-safe reading of 'no tenant' is
1132
+ * 'no bundle', never 'any tenant'. Not derived from the transport either:
1133
+ * the control plane is multi-tenant, so the Policy Engine's mTLS identity is
1134
+ * not the tenant's.
1135
+ */
1136
+ readonly tenantId: TenantId;
1137
+ /**
1138
+ * PB-5. Strictly increasing integer. Never reused, never decreased. The
1139
+ * Executor keeps a high-water mark indefinitely (CL-4) — an expiring epoch
1140
+ * mark would reopen rollback.
1141
+ *
1142
+ * Schema constraints, carried as documentation and NOT enforced by this
1143
+ * type: minimum 0.
1144
+ */
1145
+ readonly bundleEpoch: number;
1146
+ /**
1147
+ * RFC 3339 UTC. Informational: freshness is enforced by expires_at and by
1148
+ * the epoch, never by comparing this to a local clock.
1149
+ *
1150
+ * Schema constraints, carried as documentation and NOT enforced by this
1151
+ * type: format `date-time`.
1152
+ */
1153
+ readonly createdAt: string;
1154
+ /**
1155
+ * Who wrote this bundle. PB-2: MUST differ from reviewer.
1156
+ */
1157
+ readonly author: Identity;
1158
+ /**
1159
+ * Who reviewed it. PB-2: MUST differ from author. Two-person integrity on
1160
+ * the highest-leverage governance artifact in the system — RES-1 names floor
1161
+ * maintenance as exactly that.
1162
+ */
1163
+ readonly reviewer: Identity;
1164
+ /**
1165
+ * RFC 3339 UTC. PB-1: the engine MUST refuse to serve an expired bundle. A
1166
+ * deployment MAY configure a grace window during which all Decisions are
1167
+ * capped at ATTEST — it may not configure one that serves the bundle
1168
+ * normally.
1169
+ *
1170
+ * Schema constraints, carried as documentation and NOT enforced by this
1171
+ * type: format `date-time`.
1172
+ */
1173
+ readonly expiresAt: string;
1174
+ /**
1175
+ * CR-4. The signed floor on signature suites. A receipt or attestation
1176
+ * declaring a weaker suite is refused. This is in the signed bundle
1177
+ * precisely so a downgrade cannot be negotiated at runtime.
1178
+ *
1179
+ * It is NOT this bundle's own floor. It floors the suites of downstream
1180
+ * receipts and attestations; the floor THIS bundle must clear is configured
1181
+ * out of band in the verifier, because a floor a bundle can lower is not a
1182
+ * floor (RES-8). Wiring this field in as the bundle's own floor looks like
1183
+ * an improvement and is the recurring defect.
1184
+ *
1185
+ * Drawn from `signature.schema.json` rather than restated, so that one edit
1186
+ * to the suite list cannot leave the two spellings disagreeing.
1187
+ */
1188
+ readonly minSuite: SuiteId;
1189
+ readonly custody: Custody;
1190
+ }
1191
+ /**
1192
+ * The lenient projection of Manifest: every field optional, every enum
1193
+ * degraded to `string`. What a verifier parses. Never make a decision on
1194
+ * one — the fail-safe lookups live on the strict type only.
1195
+ */
1196
+ export interface RawManifest {
1197
+ readonly schemaVersion?: string;
1198
+ readonly tenantId?: string;
1199
+ readonly bundleEpoch?: number;
1200
+ readonly createdAt?: string;
1201
+ readonly author?: RawIdentity;
1202
+ readonly reviewer?: RawIdentity;
1203
+ readonly expiresAt?: string;
1204
+ readonly minSuite?: string;
1205
+ readonly custody?: RawCustody;
1206
+ }
1207
+ /**
1208
+ * Maps each action class to the parties told when an IRREVERSIBLE action of
1209
+ * that class executes BELOW floor-HIGH.
1210
+ *
1211
+ * WHY THIS FILE EXISTS. Risk is recomputed from the target resource's tier
1212
+ * floor; reversibility is a property of the action class. They are
1213
+ * orthogonal, so an action can be IRREVERSIBLE and LOW at the same time —
1214
+ * and every clause governing irreversible actions lived behind DR-1, which
1215
+ * scopes the deferred-release gate to floor-HIGH. Below HIGH the Executor
1216
+ * computed the reversibility class and discarded it: the action executed
1217
+ * with no notification, no acknowledgement, and no record that a human
1218
+ * existed. RV-1's fail-safe default set a value nothing on that path read.
1219
+ * Mail exfiltration is exactly this shape — floor an inbox at T1, which is
1220
+ * the natural choice because reading mail is routine, and an injected
1221
+ * send_email goes out unseen.
1222
+ *
1223
+ * WHY THE RECIPIENTS ARE HERE AND NOT IN THE NOTIFIER'S CONFIGURATION. A
1224
+ * notification service that selects its own audience is certifying its own
1225
+ * coverage. That is RES-8 — a verifier must never accept a derived security
1226
+ * value from the party it is verifying — and it is the exact shape of the
1227
+ * still-open finding T-32, where note.source_path, note.from_canonical and
1228
+ * delivered are all classified T. Naming recipients in the signed bundle
1229
+ * puts the audience under RK-5 two-person offline control alongside the
1230
+ * floors it complements, and makes "who would have found out" a property an
1231
+ * auditor reads off signed policy rather than asks the notifier about.
1232
+ *
1233
+ * ABSENCE FAILS CLOSED, AND JSON SCHEMA CANNOT SAY SO. An action class that
1234
+ * is IRREVERSIBLE, graded below HIGH, and absent from this file MUST cause
1235
+ * the Executor to refuse the action: a notice with no addressee is not a
1236
+ * detection channel, and DR-8's rule — executing while the detection channel
1237
+ * is absent is executing unwatched — does not become false because the risk
1238
+ * grade is lower. The condition spans three files (this one,
1239
+ * reversibility.json, and the risk grading over floors.json), so no schema
1240
+ * keyword can express it. The rule is normative in §9.6 DR-13 and its
1241
+ * enforcement point is the Executor, as with PB-7 in attesters.schema.json.
1242
+ * A normative rule with no enforcement point is a comment.
1243
+ *
1244
+ * WHAT IS NOT REQUIRED: acknowledgement. DR-9's friction is affordable at
1245
+ * floor-HIGH because a human quorum has already been paid for. Below HIGH
1246
+ * there is no quorum and the traffic is the bulk of a deployment, so
1247
+ * demanding acknowledgement would page a human for routine work at volume —
1248
+ * T-26 habituation and AT-7 rubber-stamping, and W2 already recorded that
1249
+ * saturating approvers produces assent rather than refusal. DR-13 buys
1250
+ * detection, not prevention, and is stated as the weaker guarantee it is.
1251
+ *
1252
+ * DELIVERY IS NOT A PRECONDITION OF EXECUTION. EO-2 budgets 25 ms p99
1253
+ * end-to-end for LOW and MEDIUM decisions and a synchronous confirmed
1254
+ * delivery does not fit inside it — two normative requirements that cannot
1255
+ * both hold, which is the DR-6 defect class. What DR-13 requires before
1256
+ * execution is the durable local commit of the notice. A notice committed
1257
+ * and never delivered leaves an audit record and no human; that residual is
1258
+ * disclosed as RES-P6, and reconciling committed notices against delivery
1259
+ * outcomes is a deployment obligation.
1260
+ *
1261
+ * A-7 applies here as it does to floors and to reversibility: that a
1262
+ * deployment named the RIGHT recipients is conceded unprovable. Deployments
1263
+ * SHOULD floor action classes that are both irreversible and externally
1264
+ * visible at T2 or above, which moves them onto the deferred path under
1265
+ * DR-9; this file is what holds when they have not.
1266
+ * Generated from notice_targets.schema.json.
1267
+ */
1268
+ export interface NoticeTargets {
1269
+ readonly schemaVersion: '1';
1270
+ /**
1271
+ * action class -> recipient identities. Open map (actions are
1272
+ * deployment-specific), and every value is a non-empty set. An empty array
1273
+ * is REFUSED rather than treated as 'notify nobody': the two are
1274
+ * indistinguishable at run time from an entry that was never written, and
1275
+ * the fail-safe reading of both is refusal. Making the empty case invalid
1276
+ * here means a deployment that wants no notice channel for a class must say
1277
+ * so by floor policy — raise the class to T2+ and let DR-9 govern it —
1278
+ * rather than by writing a control that looks configured and does nothing.
1279
+ *
1280
+ * Schema constraints, carried as documentation and NOT enforced by this
1281
+ * type: values minItems 1, uniqueItems; values items minLength 1, maxLength
1282
+ * 128.
1283
+ */
1284
+ readonly noticeTargets: Readonly<Record<string, readonly string[]>>;
1285
+ }
1286
+ /**
1287
+ * Look up one entry in NoticeTargets.notice_targets.
1288
+ *
1289
+ * DR-13: a notice with no addressee is not a detection channel, and DR-8's
1290
+ * rule — executing while the detection channel is absent is executing
1291
+ * unwatched — does not become false because the risk grade is lower. This is
1292
+ * the one absent-rule of the three that is NOT a default value: there is no
1293
+ * fail-safe recipient to fall back to, so the fail-safe outcome is that the
1294
+ * action does not run. A lookup returning `Option` here would let a caller
1295
+ * write `unwrap_or_default()` and execute unwatched with an empty audience.
1296
+ *
1297
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1298
+ */
1299
+ export type NoticeTargetsLookup = {
1300
+ readonly present: true;
1301
+ readonly value: readonly string[];
1302
+ } | {
1303
+ readonly present: false;
1304
+ readonly clause: string;
1305
+ readonly why: string;
1306
+ };
1307
+ export declare function noticeTargetsLookup(table: NoticeTargets, key: string): NoticeTargetsLookup;
1308
+ /**
1309
+ * The lenient projection of NoticeTargets: every field optional, every enum
1310
+ * degraded to `string`. What a verifier parses. Never make a decision on
1311
+ * one — the fail-safe lookups live on the strict type only.
1312
+ */
1313
+ export interface RawNoticeTargets {
1314
+ readonly schemaVersion?: string;
1315
+ readonly noticeTargets?: Readonly<Record<string, readonly string[]>>;
1316
+ }
1317
+ /**
1318
+ * `RaiseClause`.
1319
+ * Generated from risk_functions.schema.json#/$defs/raise_clause.
1320
+ */
1321
+ export interface RaiseClause {
1322
+ /**
1323
+ * An EL-1 expression. EL-1 is deliberately minimal, TOTAL (no expression can
1324
+ * fail to evaluate, so there is no error path to fall open through) and
1325
+ * monotone.
1326
+ *
1327
+ * PRECEDENCE IS NORMATIVE: `&&` binds tighter than `||`. That sentence
1328
+ * exists because its absence WAS a defect — Z1, found by building two
1329
+ * evaluators from the prose alone and running 10,000 differential cases
1330
+ * until they disagreed. An implementation that leaves precedence to its host
1331
+ * language reproduces the ambiguity.
1332
+ *
1333
+ * Schema constraints, carried as documentation and NOT enforced by this
1334
+ * type: minLength 1, maxLength 1024.
1335
+ */
1336
+ readonly if: string;
1337
+ readonly then: Risk;
1338
+ }
1339
+ /**
1340
+ * The lenient projection of RaiseClause: every field optional, every enum
1341
+ * degraded to `string`. What a verifier parses. Never make a decision on
1342
+ * one — the fail-safe lookups live on the strict type only.
1343
+ */
1344
+ export interface RawRaiseClause {
1345
+ readonly if?: string;
1346
+ readonly then?: string;
1347
+ }
1348
+ /**
1349
+ * The tenant's receipt verification keys -- the public half of the
1350
+ * `receipt_signing_key` the KMS holds (§4, EX-4) -- one per primitive of the
1351
+ * bundle's suite, named by the signed bundle. PB-12 (v1.3.27).
1352
+ *
1353
+ * WHY THIS FILE EXISTS. §9.3 step 1 has read, since v1.3.0, `Signature valid
1354
+ * under the current receipt_signing_key (public key from the signed
1355
+ * bundle)`, and §8.2's tree named no member that could carry it. Every
1356
+ * implementation therefore took the key from somewhere else: the Python
1357
+ * reference held it as a field of its modelled bundle (and hashed it there,
1358
+ * so `policy_bundle_hash` covered a value the on-disk tree did not), the
1359
+ * Rust differential passed it in beside the bundle, and the first Executor
1360
+ * process (M7) would have read it from its own configuration -- a verifier
1361
+ * trusting its deployment's description of the party it verifies, which is
1362
+ * the T-32 shape one level below the bundle. This file is the member step
1363
+ * 1's words had always assumed, and the on-disk tree now covers what the
1364
+ * reference's hash already did.
1365
+ *
1366
+ * WHY THE MECHANISM IS THE DOORS' AND THE REGISTRY'S. Who signs receipts is
1367
+ * the same kind of value as who may attest (PB-6, PB-7) and who speaks for a
1368
+ * door (PB-11): an identity a runtime component supplied about itself would
1369
+ * be RES-8. So it sits in signed policy under RK-5 two-person control, in
1370
+ * the attester registry's key shape -- one Ed25519 and one ML-DSA-65
1371
+ * verification key, the same named scalars -- and both legs are REQUIRED
1372
+ * because CR-3 is conjunctive: a receipt key registered with one leg is a
1373
+ * key under which no receipt can ever verify.
1374
+ *
1375
+ * WHAT THE LOADER CHECKS, AND WHAT IT DELIBERATELY DOES NOT. Present, both
1376
+ * legs at their declared lengths, and the classical leg not a small-order
1377
+ * point (PB-9's rule, the same predicate the registry and the doors are held
1378
+ * to) -- else the bundle is refused at load by every consumer, on PB-1's
1379
+ * footing, under one name (`ReceiptIdentityAbsent` for a member that is
1380
+ * missing, one leg short or not a key). NO distinctness bar against the
1381
+ * attester registry or the two doors, and that is a decision rather than an
1382
+ * omission: at any k >= 2 a KMS that also held one attester key still needs
1383
+ * a second approver, so INV-1-HIGH is not broken by that component alone and
1384
+ * the bar would remove no compromise while dressing an arbitrary rule as a
1385
+ * control -- the reference has recorded that reasoning beside its door check
1386
+ * since PB-11 landed, and it applies unchanged here. EX-4's rule that no
1387
+ * component HOLDS private keys from more than one class is custody, enforced
1388
+ * at the KMS and not by comparing public keys in a file.
1389
+ *
1390
+ * WHAT THE KMS DOES WITH IT. §9.1.1 step 4: the KMS compares the identity it
1391
+ * holds for the tenant against this member of the bundle it independently
1392
+ * verified, and answers `SIGNING_DENIED` on a mismatch -- RAD-5's shape (the
1393
+ * bundle and the signer agree, and the bundle is the byte the ceremony
1394
+ * covered) applied to the key rather than to the tenant. A bundle that names
1395
+ * a key the KMS does not hold is a bundle under which nothing will ever be
1396
+ * signed, and refusing at the signer says so where an operator can read it
1397
+ * instead of at the Executor's step 1 at 03:00.
1398
+ *
1399
+ * WHAT IS DELIBERATELY NOT HERE. Custody metadata: the tier the key is held
1400
+ * at is the manifest's `custody` (§4) and belongs beside the epoch, not
1401
+ * beside the key. Rotation: a new receipt identity is a new bundle epoch
1402
+ * (PB-5), which is what makes the old key's receipts refuse at step 4 before
1403
+ * they can fail at step 1.
1404
+ * Generated from receipt_identity.schema.json.
1405
+ */
1406
+ export interface ReceiptIdentity {
1407
+ readonly schemaVersion: '1';
1408
+ /**
1409
+ * The identity's name, for the audit record and the alert -- a label for the
1410
+ * keys beside it, never what the Executor resolves a signature by (ACK-4's
1411
+ * rule, as for the doors).
1412
+ *
1413
+ * Schema constraints, carried as documentation and NOT enforced by this
1414
+ * type: minLength 1, maxLength 128.
1415
+ */
1416
+ readonly name: string;
1417
+ /**
1418
+ * The Ed25519 verification key. The attester registry's named scalar,
1419
+ * referenced rather than re-declared: one definition of a key encoding. Held
1420
+ * to PB-9 at load: a small-order point here is a key under which one
1421
+ * signature verifies every message.
1422
+ */
1423
+ readonly classical: Ed25519PublicKey;
1424
+ /**
1425
+ * The ML-DSA-65 verification key. Required because CR-3 is conjunctive and
1426
+ * the bundle's suite names both primitives; a receipt verifies only when
1427
+ * every leg does.
1428
+ */
1429
+ readonly pq: MlDsa65PublicKey;
1430
+ }
1431
+ /**
1432
+ * The lenient projection of ReceiptIdentity: every field optional, every enum
1433
+ * degraded to `string`. What a verifier parses. Never make a decision on
1434
+ * one — the fail-safe lookups live on the strict type only.
1435
+ */
1436
+ export interface RawReceiptIdentity {
1437
+ readonly schemaVersion?: string;
1438
+ readonly name?: string;
1439
+ readonly classical?: string;
1440
+ readonly pq?: string;
1441
+ }
1442
+ /**
1443
+ * Maps each action class to whether it can be undone.
1444
+ *
1445
+ * RV-1: an action ABSENT from this file MUST be treated as IRREVERSIBLE. As
1446
+ * with floors, JSON Schema cannot express absence, so the rule is carried by
1447
+ * the `x-acp-absent` annotation below and GENERATED into the type: `impl
1448
+ * Default for Reversibility` returns `Irreversible` in crates/acp-core, and
1449
+ * the lookup on the table returns it directly, so a struct update, a
1450
+ * deserialisation gap, or an `Option` a caller unwraps cannot silently
1451
+ * produce the permissive value.
1452
+ *
1453
+ * Why this matters more than it looks: reversibility selects the
1454
+ * acknowledgement regime. IRREVERSIBLE at floor-HIGH demands positive
1455
+ * acknowledgement from a non-operator (DR-9) — silence is not consent.
1456
+ * Getting this entry wrong in the permissive direction converts a held
1457
+ * action into a released one.
1458
+ *
1459
+ * RV-3 is the reason the value is recomputed here and never read from a
1460
+ * receipt: a compromised issuer claiming REVERSIBLE otherwise obtains Silent
1461
+ * mode. Proven in reference/proofs/binding.dfy as
1462
+ * `RV3_TrustedModeAcceptsDowngrade`.
1463
+ *
1464
+ * A-7 applies here exactly as it does to floors: that a classification is
1465
+ * HONEST is conceded unprovable.
1466
+ * Generated from reversibility.schema.json.
1467
+ */
1468
+ export interface ReversibilityTable {
1469
+ readonly schemaVersion: '1';
1470
+ /**
1471
+ * action class -> reversibility. Open map (actions are deployment-specific),
1472
+ * closed values.
1473
+ */
1474
+ readonly reversibility: Readonly<Record<string, Reversibility>>;
1475
+ }
1476
+ /**
1477
+ * Look up one entry in ReversibilityTable.reversibility.
1478
+ *
1479
+ * RV-1: reversibility selects the acknowledgement regime, so the permissive
1480
+ * default converts a held action into a released one. An action nobody
1481
+ * classified is one nobody thought about, and the fail-safe reading of that
1482
+ * is that it cannot be undone.
1483
+ *
1484
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1485
+ */
1486
+ export declare function reversibilityTableLookup(table: ReversibilityTable, key: string): Reversibility;
1487
+ /**
1488
+ * The lenient projection of ReversibilityTable: every field optional, every enum
1489
+ * degraded to `string`. What a verifier parses. Never make a decision on
1490
+ * one — the fail-safe lookups live on the strict type only.
1491
+ */
1492
+ export interface RawReversibilityTable {
1493
+ readonly schemaVersion?: string;
1494
+ readonly reversibility?: Readonly<Record<string, string>>;
1495
+ }
1496
+ /**
1497
+ * `RiskFunction`.
1498
+ * Generated from risk_functions.schema.json#/$defs/risk_function.
1499
+ */
1500
+ export interface RiskFunction {
1501
+ /**
1502
+ * Action class this function grades. At most one function per action class —
1503
+ * two functions for one class is an ambiguity, not a merge, and the loader
1504
+ * refuses it.
1505
+ *
1506
+ * Schema constraints, carried as documentation and NOT enforced by this
1507
+ * type: minLength 1, maxLength 128.
1508
+ */
1509
+ readonly appliesTo: string;
1510
+ readonly base: Risk;
1511
+ /**
1512
+ * Clauses evaluated in order. MONOTONE BY CONSTRUCTION: a clause can only
1513
+ * raise the level, never lower it, which is why the field is `raise_to` and
1514
+ * there is no `lower_to`. Monotonicity is what makes the Dafny proof that
1515
+ * floors dominate raises tractable — a lowering clause would let a crafted
1516
+ * parameter walk a HIGH action down to LOW.
1517
+ */
1518
+ readonly raiseTo: readonly RaiseClause[];
1519
+ }
1520
+ /**
1521
+ * The lenient projection of RiskFunction: every field optional, every enum
1522
+ * degraded to `string`. What a verifier parses. Never make a decision on
1523
+ * one — the fail-safe lookups live on the strict type only.
1524
+ */
1525
+ export interface RawRiskFunction {
1526
+ readonly appliesTo?: string;
1527
+ readonly base?: string;
1528
+ readonly raiseTo?: readonly RawRaiseClause[];
1529
+ }
1530
+ /**
1531
+ * Deterministic functions from a Proposal's parameters and its targets'
1532
+ * effective tiers to a risk level.
1533
+ *
1534
+ * RK-2 exists because static per-action risk is insufficient:
1535
+ * `modify_firewall_rule = HIGH` says nothing useful, since risk is a
1536
+ * function of PARAMETERS and TARGETS, not action names.
1537
+ *
1538
+ * THE ABSENT CASE DIFFERS FROM floors AND reversibility. An action with no
1539
+ * risk function is REFUSED at §8.4 step 3 — it is NOT graded HIGH. Refusing
1540
+ * and grading-HIGH are different behaviours: grading HIGH would route an
1541
+ * unknown action into the human quorum, which looks conservative but
1542
+ * silently teaches approvers to rubber-stamp things the policy author never
1543
+ * considered. P-4: unknown is never LOW, and here it is not HIGH either — it
1544
+ * is a refusal.
1545
+ *
1546
+ * TR-8: these functions are evaluated by the Executor over the INDEPENDENTLY
1547
+ * RECEIVED canonical Proposal and the trusted bundle, ignoring every
1548
+ * Context-Store raise and ignoring any risk value asserted in the receipt.
1549
+ * The recomputed value is what all subsequent attestation requirements key
1550
+ * on.
1551
+ * Generated from risk_functions.schema.json.
1552
+ */
1553
+ export interface RiskFunctions {
1554
+ readonly schemaVersion: '1';
1555
+ readonly riskFunctions: readonly RiskFunction[];
1556
+ }
1557
+ /**
1558
+ * Look up one entry in RiskFunctions.risk_functions.
1559
+ *
1560
+ * 8.4-3: THE ABSENT CASE HERE IS NOT THE ABSENT CASE IN floors OR
1561
+ * reversibility. An action with no risk function is REFUSED, not graded
1562
+ * HIGH. Grading HIGH would route an unknown action into the human quorum,
1563
+ * which looks conservative and is worse: it teaches approvers to
1564
+ * rubber-stamp things the policy author never considered (T-26 habituation,
1565
+ * AT-7). P-4 says unknown is never LOW; here it is not HIGH either. A lookup
1566
+ * returning `Option` would let a caller reach for HIGH as the obvious safe
1567
+ * default and get this exactly wrong.
1568
+ *
1569
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1570
+ */
1571
+ export type RiskFunctionsLookup = {
1572
+ readonly present: true;
1573
+ readonly value: RiskFunction;
1574
+ } | {
1575
+ readonly present: false;
1576
+ readonly clause: string;
1577
+ readonly why: string;
1578
+ };
1579
+ export declare function riskFunctionsLookup(table: RiskFunctions, key: string): RiskFunctionsLookup;
1580
+ /**
1581
+ * The lenient projection of RiskFunctions: every field optional, every enum
1582
+ * degraded to `string`. What a verifier parses. Never make a decision on
1583
+ * one — the fail-safe lookups live on the strict type only.
1584
+ */
1585
+ export interface RawRiskFunctions {
1586
+ readonly schemaVersion?: string;
1587
+ readonly riskFunctions?: readonly RawRiskFunction[];
1588
+ }
1589
+ /**
1590
+ * The `SIGNATURE` file at the bundle root: the declared suite, and one
1591
+ * signature value per primitive that suite requires, over SHA-256 of the
1592
+ * canonical bundle tree.
1593
+ *
1594
+ * A CORRECTION IS RECORDED HERE. Until this revision this file was named
1595
+ * `bundle.schema.json` and described a *tree index* — `schema_version`, a
1596
+ * `members` array of path+digest pairs, and a `signature` object carrying
1597
+ * two fixed base64 fields named `classical` and `pq`. None of that artifact
1598
+ * exists. §8.2's file listing contains no index file; the covered set is
1599
+ * established by the CANONICAL WALK (`walk_bundle`, in both
1600
+ * implementations), which is what makes "the tree" a fact rather than a
1601
+ * convention. And PB-8, added in v1.3.15 when the offline signer turned the
1602
+ * format from a diagram into bytes, specifies the file as a suite plus ONE
1603
+ * VALUE PER PRIMITIVE — a map keyed by primitive name, hex-encoded — which
1604
+ * is not the fixed pair the old schema declared.
1605
+ *
1606
+ * So the normative source held two descriptions of one object, and they
1607
+ * disagreed: the encoding-split defect arriving inside the document that
1608
+ * exists to prevent it. It survived because NOTHING READ THE SCHEMAS. They
1609
+ * were normative and unexecuted, and the first consumer — `tools/codegen.sh`
1610
+ * — found this on its first run. That is the same shape as `sim/bundle.py`
1611
+ * silently dropping three fields from a hash for several releases: a
1612
+ * load-bearing artifact with no gate line.
1613
+ *
1614
+ * WHY THE MEMBERS INDEX IS NOT COMING BACK. The old rationale was real —
1615
+ * without an explicit list, a verifier that skipped a file and a signer that
1616
+ * included it compute different hashes and neither can tell which is wrong.
1617
+ * The adopted answer is to make the WALK normative rather than to ship a
1618
+ * list: it refuses symlinks, refuses unrecognised file types, and orders
1619
+ * byte-wise, so two conformant implementations enumerate the same set. A
1620
+ * committed index would be a second statement of the same fact, and this
1621
+ * file exists because of what happens to the second statement.
1622
+ * Generated from signature.schema.json.
1623
+ */
1624
+ export interface SignatureEnvelope {
1625
+ /**
1626
+ * The suite this signature was produced under. PB-8: it MUST be inside the
1627
+ * tree hash. Outside it, an attacker relabels a hybrid bundle as classical,
1628
+ * the verifier obligingly requires one primitive, and the CR-3 downgrade
1629
+ * costs nothing.
1630
+ */
1631
+ readonly suite: SuiteId;
1632
+ /**
1633
+ * primitive name -> signature value, lowercase hex.
1634
+ *
1635
+ * CR-3, CONJUNCTIVE: the values present MUST be exactly those the declared
1636
+ * suite requires, and every one of them MUST verify. Not "at least": a value
1637
+ * for a primitive the suite does not declare is as much a refusal as a
1638
+ * missing one, because an `any`-shaped check lets an attacker strip the
1639
+ * post-quantum leg, present a genuine classical signature, and be accepted.
1640
+ *
1641
+ * Hex rather than base64, matching what both implementations write.
1642
+ * Per-primitive lengths (Ed25519 64 bytes, ML-DSA-65 3309) are asserted in
1643
+ * code and not here: `parts` is keyed by primitive, so no single value
1644
+ * pattern can express a length that depends on its own key.
1645
+ *
1646
+ * Schema constraints, carried as documentation and NOT enforced by this
1647
+ * type: values pattern `^[0-9a-f]+$`.
1648
+ */
1649
+ readonly parts: Readonly<Record<string, string>>;
1650
+ }
1651
+ /**
1652
+ * Look up one entry in SignatureEnvelope.parts.
1653
+ *
1654
+ * CR-3, PB-8: a primitive the declared suite requires and this file does not
1655
+ * carry is a stripped leg, and a stripped leg is the downgrade the hybrid
1656
+ * suite exists to prevent. Absent is refused, never treated as 'not
1657
+ * applicable'.
1658
+ *
1659
+ * Generated from the schema's `x-acp-absent` rule. It is not restated here.
1660
+ */
1661
+ export type SignatureEnvelopeLookup = {
1662
+ readonly present: true;
1663
+ readonly value: string;
1664
+ } | {
1665
+ readonly present: false;
1666
+ readonly clause: string;
1667
+ readonly why: string;
1668
+ };
1669
+ export declare function signatureEnvelopeLookup(table: SignatureEnvelope, key: string): SignatureEnvelopeLookup;
1670
+ /**
1671
+ * The lenient projection of SignatureEnvelope: every field optional, every enum
1672
+ * degraded to `string`. What a verifier parses. Never make a decision on
1673
+ * one — the fail-safe lookups live on the strict type only.
1674
+ */
1675
+ export interface RawSignatureEnvelope {
1676
+ readonly suite?: string;
1677
+ readonly parts?: Readonly<Record<string, string>>;
1678
+ }
1679
+ /**
1680
+ * One registry entry: a machine (`kind: hybrid`) or a human (`kind:
1681
+ * webauthn`). A TAGGED union, deliberately: the generator refuses an
1682
+ * untagged `oneOf` because 'first branch that parses' is how a document
1683
+ * meant as one thing is read as another, and a key kind guessed from which
1684
+ * fields are present is exactly that guess. Every entry carries `kind`; one
1685
+ * without it is `Malformed` at load (HM-1).
1686
+ * Generated from attesters.schema.json#/$defs/attester.
1687
+ *
1688
+ * A DISCRIMINATED union over `kind`, which every branch pins to a literal.
1689
+ * Narrow it by switching on that field; a `default` arm that accepts an
1690
+ * unrecognised value is a branch this union does not have, and the fail-safe
1691
+ * answer there is to refuse. There is no `Raw` union: with every field
1692
+ * optional each branch would accept every other document and the tag would
1693
+ * decide nothing.
1694
+ */
1695
+ export type Attester = MachineAttester | HumanAttester;
1696
+ //# sourceMappingURL=generated.d.ts.map