@humanagencyp/hap-core 0.11.2 → 0.12.1

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/dist/index.d.ts CHANGED
@@ -1,123 +1,97 @@
1
1
  /**
2
- * HAP Core Types — Agent Demo
2
+ * Canonical v0.7 error codes — protocol.md → *Error Codes*.
3
+ *
4
+ * "Error codes are canonical across the protocol. Implementations MUST emit
5
+ * exactly these codes and MUST NOT alias them under different names." This
6
+ * module is the single list both the Gatekeeper (local checks) and any AS
7
+ * client built on this library read from, so the two cannot drift.
8
+ *
9
+ * v0.7 renamed every code that carried a retired word (attestation → mandate,
10
+ * context → scope, receipt → ticket) — see protocol.md → *Migration from
11
+ * v0.6* → "Error-code renames" for the old→new map. There is no alias: a v0.6
12
+ * code name is simply gone from this list, by design (no backward
13
+ * compatibility — CLAUDE.md "Decided by the owner").
14
+ */
15
+ /** Codes an Authority Server (or a local Gatekeeper check) emits refusing a mandate request. */
16
+ declare const MANDATE_ERROR_CODES: readonly ["BOUNDS_HASH_MISMATCH", "SCOPE_HASH_MISMATCH", "INVALID_SIGNATURE", "OWNER_NOT_COVERED", "TTL_EXPIRED", "PROFILE_NOT_FOUND", "PROFILE_INVALID", "PROFILE_HASH_MISMATCH", "COVERAGE_INSUFFICIENT", "MALFORMED_MANDATE", "VERSION_UNSUPPORTED", "OWNER_NOT_APPROVER", "BOUNDS_INVALID_VALUE", "SCOPE_INVALID_VALUE", "ABOVE_CAP_CONFIG_INVALID", "OWNER_SIGNATURE_REQUIRED", "OWNER_SIGNATURE_INVALID"];
17
+ /** Codes an Authority Server emits refusing a ticket request. */
18
+ declare const TICKET_ERROR_CODES: readonly ["MANDATE_NOT_FOUND", "MANDATE_EXPIRED", "MANDATE_REVOKED", "BOUND_EXCEEDED", "CUMULATIVE_LIMIT_EXCEEDED", "COVERAGE_INSUFFICIENT", "PROFILE_NOT_FOUND", "INVALID_ACTION_TYPE", "APPROVAL_REQUIRED", "PROPOSAL_REQUIRED", "PROPOSAL_NOT_FOUND", "PROPOSAL_NOT_APPROVED", "PROPOSAL_EXPIRED", "PROPOSAL_REJECTED", "PROPOSAL_MISMATCH", "PROPOSAL_MANDATE_MISMATCH", "PROPOSAL_ALREADY_EXECUTED", "MALFORMED_TICKET_REQUEST", "IDEMPOTENCY_KEY_REQUIRED", "IDEMPOTENCY_MISMATCH", "APPROVAL_SIGNATURE_REQUIRED", "APPROVAL_SIGNATURE_INVALID"];
19
+ /** The full canonical surface — every code a conformant implementation may emit. */
20
+ type HapErrorCode = (typeof MANDATE_ERROR_CODES)[number] | (typeof TICKET_ERROR_CODES)[number];
21
+ /**
22
+ * A refusal carrying one of the canonical codes above. Thrown by local
23
+ * (Gatekeeper-side, no-wire-round-trip) checks in this library; an AS client
24
+ * built on hap-core maps a wire `{ code, message }` error onto the same type.
25
+ */
26
+ declare class HapError extends Error {
27
+ readonly code: HapErrorCode;
28
+ constructor(code: HapErrorCode, message: string);
29
+ }
30
+
31
+ /**
32
+ * HAP Core Types — v0.7 ("mandate" / "ticket" / "scope" / "Mandate Owner")
3
33
  *
4
- * Types for agent-oriented profiles with bounded execution.
34
+ * v0.7 is a vocabulary release (protocol.md → *Migration from v0.6*): the
35
+ * wire renames *attestation* → *mandate*, *context* → *scope*, *execution
36
+ * receipt* → *mandate ticket*, and *Decision Owner* → *Mandate Owner*. There
37
+ * is no backward-compat alias here — v0.6 and earlier artifacts are
38
+ * verification-only history outside this package (CLAUDE.md "Decided by the
39
+ * owner": no verify path for 0.5/0.6, no old→new code map).
5
40
  */
6
- interface AttestationHeader {
7
- typ: 'HAP-attestation';
41
+ interface MandateHeader {
42
+ typ: 'HAP-mandate';
8
43
  alg: 'EdDSA';
9
- kid?: string;
10
- }
11
- interface ResolvedDomain {
12
- domain: string;
13
- did: string;
14
- }
15
- interface AttestationPayload {
16
- attestation_id: string;
17
- version: '0.3' | '0.4' | '0.5' | '0.6';
18
- profile_id: string;
19
- /** v0.3 (deprecated) — hash of the authorization frame */
20
- frame_hash?: string;
21
- /** v0.4 — hash of the bounds parameters */
22
- bounds_hash?: string;
23
- /** v0.4 — hash of the context parameters */
24
- context_hash?: string;
25
- execution_context_hash: string;
26
- /**
27
- * v0.4 (deprecated in v0.5) — domain-scoped owners. Optional so v0.5
28
- * attestations that carry only `resolved_owners` remain valid. During the
29
- * transition the AS emits BOTH `resolved_domains` (internal coverage) and
30
- * `resolved_owners` (the v0.5 signed wire field).
31
- */
32
- resolved_domains?: ResolvedDomain[];
33
- /**
34
- * v0.5 — the Decision Owner DIDs this attestation covers (person-centric
35
- * model; replaces the abstract domain in `resolved_domains`). Carried in the
36
- * signed payload so verifiers bind the action to the human(s) who authorized it.
37
- */
38
- resolved_owners?: string[];
39
- gate_content_hashes: Record<string, string>;
40
- /**
41
- * v0.5 (companion spec `intent-disclosure@0.1`) — present iff the attestation
42
- * carries an encrypted-intent disclosure object. `sha256:`-prefixed hash that
43
- * binds the disclosure's `intent_ciphertext` + `approvers_frozen` into the
44
- * signed payload (see {@link computeIntentDisclosureHash}), so a compromised
45
- * AS cannot swap the ciphertext/wrapped keys or alter the approver set
46
- * without invalidating the attestation signature (companion invariant C2).
47
- */
48
- intent_disclosure_hash?: string;
49
44
  /**
50
- * v0.6 (Identity Assurance) — optional signed overlay carrying the verified
51
- * real-world identity of the Decision Owner(s), one entry per owner. Present
52
- * only when identity is disclosed; an attestation with no `subjects` renders
53
- * as `low` (pseudonymous, no name). See {@link Subject} and
54
- * {@link deriveIdentityLine}.
55
- */
56
- subjects?: Subject[];
57
- /**
58
- * v0.4 — commitment mode chosen by the decision owner at attestation time.
59
- * - 'automatic': agent may invoke bounded tools without per-action review.
60
- * - 'review': every tool call requires an approved proposal before the
61
- * receipt route will sign a receipt.
62
- *
63
- * Cryptographically bound in the signed payload so a compromised SP cannot
64
- * silently flip 'review' → 'automatic'. Absent on v0.3 attestations.
65
- * `review_above_cap` (v0.5): automatic below the signed caps, proposal above.
45
+ * When present MUST identify the same key as `issuer` (for a `did:key`
46
+ * issuer, the multibase key fingerprint) — Mandate rule 8. The field a
47
+ * party writes (`kid`) loses to the field a party cannot forge (`issuer`).
66
48
  */
67
- commitment_mode?: 'automatic' | 'review' | 'review_above_cap';
68
- /**
69
- * v0.6 (Owner Mandate Signatures) — the Decision Owner's own signature(s)
70
- * over the mandate projection ({@link MandateProjection}), one entry per
71
- * co-signing owner. Carried INSIDE the AS-signed payload, so the AS attests
72
- * to having received it and cannot strip it without invalidating its own
73
- * signature. Optional and additive: an attestation without it behaves as
74
- * before (the v0.5 posture — the AS asserts, nobody co-signs).
75
- */
76
- owner_mandates?: OwnerMandate[];
77
- issued_at: number;
78
- expires_at: number;
49
+ kid?: string;
79
50
  }
80
- /** Mandate-assurance axis — what custody signed the mandate. Independent of
81
- * identity assurance ({@link Subject.method}). */
82
- type MandateBinding = 'raw' | 'webauthn' | 'eudi';
51
+ /** Signature-assurance axis — what custody signed the mandate projection or
52
+ * approval. Independent of identity assurance ({@link Subject.method}). */
53
+ type OwnerSignatureBinding = 'raw' | 'webauthn' | 'eudi';
83
54
  /** Which surface showed the owner what they signed. A DECLARATION, not a proof
84
- * — no verifier can check it; see protocol.md → Owner Mandate Signatures. */
55
+ * — no verifier can check it; see protocol.md → *Owner Signatures*. */
85
56
  type SigningSurface = 'gatekeeper_local' | 'as_web' | 'wallet_display';
86
57
  /**
87
- * v0.6 — one owner's signature over the mandate projection.
58
+ * v0.7 `mandate_owners` entry (protocol.md → *Mandate field: mandate_owners*).
59
+ * `did` is required; the remaining fields are present together when the
60
+ * owner co-signed and absent together when they did not (Mandate rule 7).
88
61
  *
89
62
  * There is deliberately NO `public_key` field, and it MUST NOT be added: the
90
63
  * verification key is carried in the DID itself (key-bearing `did:key`), so a
91
64
  * non-key-bearing DID fails STRUCTURALLY instead of validating against a key
92
- * the AS could have substituted. `alg` is kept only as curve-confusion
93
- * hygiene; if it disagrees with the DID's key type, the DID is authoritative.
65
+ * the AS could have substituted.
94
66
  */
95
- interface OwnerMandate {
96
- /** The signing owner's key-bearing DID. MUST be a member of `resolved_owners`. */
67
+ interface MandateOwnerEntry {
68
+ /** The Mandate Owner's DID. For a co-signing entry, MUST be key-bearing. */
97
69
  did: string;
98
70
  /** Signature algorithm hint. The DID's multicodec wins on any disagreement. */
99
- alg: 'EdDSA' | 'ES256';
71
+ alg?: 'EdDSA' | 'ES256';
100
72
  /** base64url (no padding) signature over the JCS bytes of the mandate projection. */
101
- signature: string;
73
+ signature?: string;
102
74
  /** When the owner signed (unix seconds). */
103
- signed_at: number;
75
+ signed_at?: number;
104
76
  /** Defence-in-depth against duplicate issuance by an HONEST AS only —
105
77
  * AS-side nonce enforcement is no defence against the AS itself. */
106
- nonce: string;
107
- binding: MandateBinding;
78
+ nonce?: string;
79
+ /** Required-present, value-open when a signature is carried: an AS MUST
80
+ * NOT reject an entry for a `binding` value it does not recognize. */
81
+ binding?: OwnerSignatureBinding;
108
82
  signing_surface?: SigningSurface;
109
83
  }
110
84
  /**
111
- * v0.6 Identity Assurance — a signed overlay binding a Decision Owner's verified
112
- * real-world identity to the attestation, gated by HOW the identity was verified.
85
+ * v0.6 Identity Assurance — a signed overlay binding a Mandate Owner's verified
86
+ * real-world identity to the mandate, gated by HOW the identity was verified.
113
87
  *
114
88
  * Two display levels (`assurance`): `low` discloses no name; `high` MAY disclose a
115
89
  * name. At `high`, two trust roots: `as` (the AS operator vouches — valid only
116
90
  * within its own domain) and `external` (an external eID such as EUDI — carries the
117
- * owner's own signature, AS-independent). See review.md → "Identity Assurance".
91
+ * owner's own signature, AS-independent).
118
92
  */
119
93
  interface Subject {
120
- /** The Decision Owner DID this subject describes (matches an entry in resolved_owners). */
94
+ /** The Mandate Owner DID this subject describes (matches the `mandate_owners` entry). */
121
95
  did: string;
122
96
  /** `low` → no name shown; `high` → the name MAY be shown. */
123
97
  assurance: 'low' | 'high';
@@ -133,18 +107,53 @@ interface Subject {
133
107
  };
134
108
  /** When the underlying verification was performed (unix seconds). */
135
109
  verified_at?: number;
110
+ }
111
+ /** protocol.md → *Mandate Payload (v0.7)*. */
112
+ interface MandatePayload {
113
+ mandate_id: string;
114
+ version: '0.7';
115
+ profile_id: string;
116
+ /** Hash of the canonical bounds string. */
117
+ bounds_hash: string;
118
+ /** Hash of the canonical scope string (sha256 of "" when scope is empty). */
119
+ scope_hash: string;
120
+ execution_context_hash: string;
121
+ /** `sha256` over the JCS serialization of the profile the Gatekeeper
122
+ * provisioned for `profile_id` — the content address of the rulebook this
123
+ * mandate was issued under (new in v0.7). */
124
+ profile_hash: string;
125
+ /** The Authority Server's DID — SHOULD be the `did:key` of the signing key
126
+ * itself (new in v0.7). */
127
+ issuer: string;
128
+ /** Exactly one entry in v0.7 (Mandate rule 7). */
129
+ mandate_owners: MandateOwnerEntry[];
130
+ gate_content_hashes: Record<string, string>;
131
+ commitment_mode: 'automatic' | 'review' | 'review_above_cap';
132
+ /** Required, together with `above_cap_approvers`, iff `commitment_mode === "review_above_cap"`. */
133
+ above_cap_caps?: Record<string, number>;
134
+ above_cap_approvers?: string[];
136
135
  /**
137
- * @deprecated v0.6 — replaced by {@link AttestationPayload.owner_mandates}.
138
- * This field signed the wrong object (the identity claim, not what was
139
- * committed to) and was welded to one method. Implementations MUST NOT emit
140
- * it; verifiers MAY ignore it on artifacts that carry it. Kept readable for
141
- * audit of pre-0.6 artifacts only.
136
+ * Present iff the mandate carries an encrypted-intent disclosure object
137
+ * (companion spec `intent-disclosure@0.1`) — `sha256:`-prefixed hash
138
+ * binding `intent_ciphertext` + `approvers_frozen` into the signed payload.
142
139
  */
143
- owner_signature?: string | null;
140
+ intent_disclosure_hash?: string;
141
+ /** Signed identity-assurance block, one entry per owner — present iff the
142
+ * Mandate Owner disclosed identity. */
143
+ subjects?: Subject[];
144
+ /**
145
+ * The owner's narrowing of the profile's `disclose_fields` list (new in
146
+ * v0.7) — a subset of the profile's own list. See *Ticket Disclosure Is
147
+ * Declared*.
148
+ */
149
+ disclose_fields?: string[];
150
+ issued_at: number;
151
+ expires_at: number;
144
152
  }
145
- interface Attestation {
146
- header: AttestationHeader;
147
- payload: AttestationPayload;
153
+ interface Mandate {
154
+ header: MandateHeader;
155
+ payload: MandatePayload;
156
+ /** base64url (no padding) Ed25519 signature over the JCS-canonical payload. */
148
157
  signature: string;
149
158
  }
150
159
  /**
@@ -179,24 +188,13 @@ interface FieldConstraint {
179
188
  requiredFor?: string[];
180
189
  }
181
190
  /**
182
- * Frame field definition within a profile.
183
- */
184
- interface ProfileFrameField {
185
- type: 'string' | 'number';
186
- required: boolean;
187
- description?: string;
188
- constraint?: FieldConstraint;
189
- enum?: string[];
190
- }
191
- /**
192
- * Bound enforcement semantics — how a v0.4 bound is checked.
191
+ * Bound enforcement semantics — how a bound is checked.
193
192
  *
194
- * Every bounds field in a v0.4 profile declares a `boundType` so the SP
195
- * receipt route and hap-core gatekeeper can dispatch on it directly,
196
- * without parsing field names or guessing conventions. This is the
197
- * single source of truth for "what does this bound mean at enforcement
198
- * time" — if a new kind is needed, add a variant here and update the
199
- * dispatch sites.
193
+ * Every bounds field in a profile declares a `boundType` so the AS and
194
+ * hap-core gatekeeper can dispatch on it directly, without parsing field
195
+ * names or guessing conventions. This is the single source of truth for
196
+ * "what does this bound mean at enforcement time" — if a new kind is needed,
197
+ * add a variant here and update the dispatch sites.
200
198
  *
201
199
  * See `ProfileBoundsField.boundType`.
202
200
  */
@@ -206,23 +204,15 @@ type BoundType =
206
204
  * satisfy `execution[of] <= bound` for the current call. No cumulative
207
205
  * tracking. Used by: amount_max, recipient_max, booking_duration_max, etc.
208
206
  *
209
- * `requiredFor` (v0.8+) closes the converse: without it, a call that does
210
- * not carry `of` at all is simply skipped — a 5,000 cap refuses 6,000 but
207
+ * `requiredFor` closes the converse: without it, a call that does not
208
+ * carry `of` at all is simply skipped — a 5,000 cap refuses 6,000 but
211
209
  * permits a call that declares no value whatsoever, which is indistinguishable
212
- * from an unenforced bound. The same hole, and the same fix, as
213
- * `FieldConstraint.requiredFor` on a scope constraint (below): values drawn
214
- * from the profile's `boundsSchema.actionTypes` registry. For a listed
215
- * `action_type`, an execution whose context lacks `of` — or whose value is
216
- * not a finite number — MUST be refused rather than skipped. For an
217
- * unlisted (or when `requiredFor` is absent) action type, today's
218
- * skip-on-absence behaviour is unchanged. Meaningful only on
219
- * `per_transaction`; the other `BoundType` kinds have no per-call "value
220
- * exposed or not" question — `cumulative_sum`/`cumulative_count` always read
221
- * from the execution log regardless of what this call declares, and `enum`
222
- * is a capability flag, not a runtime value — so the field does not exist
223
- * on those variants and a profile that puts it there has it silently
224
- * ignored by every enforcement point (TypeScript also refuses it when the
225
- * profile is authored against this type rather than raw JSON).
210
+ * from an unenforced bound. Values are drawn from the profile's
211
+ * `boundsSchema.actionTypes` registry. For a listed `action_type`, an
212
+ * execution whose context lacks `of` — or whose value is not a finite
213
+ * number — MUST be refused rather than skipped. `appliesTo` MUST NOT be
214
+ * declared on a `per_transaction` bound (protocol.md → Bounds Schema rule 7)
215
+ * — it applies wherever `of` is present in the execution context.
226
216
  */
227
217
  {
228
218
  kind: 'per_transaction';
@@ -230,10 +220,12 @@ type BoundType =
230
220
  requiredFor?: string[];
231
221
  }
232
222
  /**
233
- * Cumulative sum within a time window. The SP maintains a running sum
234
- * of `execution[of]` across all prior executions in the window; the
223
+ * Cumulative sum within a time window. The AS maintains a running sum
224
+ * of `execution[of]` across all prior tickets in the window; the
235
225
  * current call is approved iff `running_sum + execution[of] <= bound`.
236
- * Used by: amount_daily_max, spend_monthly_max, etc.
226
+ * AS-only enforcement (protocol.md → *Enforcement Authority*); the
227
+ * Gatekeeper MUST NOT enforce this locally. Used by: amount_daily_max,
228
+ * spend_monthly_max, etc.
237
229
  */
238
230
  | {
239
231
  kind: 'cumulative_sum';
@@ -241,10 +233,14 @@ type BoundType =
241
233
  window: CumulativeWindow;
242
234
  }
243
235
  /**
244
- * Cumulative count within a time window. Every qualifying execution
236
+ * Cumulative count within a time window. Every qualifying ticket
245
237
  * counts as +1; the current call is approved iff
246
238
  * `running_count + 1 <= bound`. No execution context field is read.
247
- * Used by: write_daily_max, post_monthly_max, booking_daily_max, etc.
239
+ * AS-only enforcement. `appliesTo` is REQUIRED on a profile published
240
+ * under v0.7 or later (Bounds Schema rule 7) — absence would mean
241
+ * "governs every action type", so a forgotten declaration silently
242
+ * throttles every action. Used by: write_daily_max, post_monthly_max,
243
+ * booking_daily_max, etc.
248
244
  */
249
245
  | {
250
246
  kind: 'cumulative_count';
@@ -252,11 +248,12 @@ type BoundType =
252
248
  }
253
249
  /**
254
250
  * String bound restricted to a fixed set of allowed values. The bound's
255
- * value must be one of `values` at attestation time. The gateway
251
+ * value must be one of `values` at mandate time. The gateway
256
252
  * tool-proxy gates tool calls based on the stored bound (via the
257
253
  * integration manifest's `boundField` + `requiredValue`). Not cumulated,
258
- * not checked by the SP receipt route — it's a capability flag.
259
- * Used by: read_access, delete_access, archive_access.
254
+ * not checked by the AS ticket route — it's a capability flag.
255
+ * `appliesTo` MUST NOT be declared here (it is a capability flag, not an
256
+ * action-scoped limit). Used by: read_access, delete_access, archive_access.
260
257
  */
261
258
  | {
262
259
  kind: 'enum';
@@ -274,11 +271,11 @@ type BoundType =
274
271
  */
275
272
  type FieldUnit = 'count' | 'minutes' | 'hours' | 'days' | `currency:${string}` | 'percent';
276
273
  /**
277
- * Bounds field definition within a v0.4 profile.
274
+ * Bounds field definition within a profile.
278
275
  *
279
- * v0.4 adds the required `boundType` — an explicit declaration of how
280
- * the bound is enforced. The older `constraint.enforceable` pattern is
281
- * deprecated and superseded by `boundType`.
276
+ * Every non-metadata bounds field MUST declare `boundType` — an explicit
277
+ * declaration of how the bound is enforced. Implementations MUST fail
278
+ * closed on any bounds field that omits it (Bounds Schema rule 2).
282
279
  */
283
280
  interface ProfileBoundsField {
284
281
  type: 'string' | 'number';
@@ -286,26 +283,18 @@ interface ProfileBoundsField {
286
283
  description?: string;
287
284
  displayName?: string;
288
285
  format?: 'email' | 'domain' | 'url' | 'currency';
289
- /**
290
- * v0.4 enforcement semantics. Required for all new profiles.
291
- * Optional here only so the type stays backward compatible with v0.3
292
- * profiles that predate the boundType convention — consumers must
293
- * treat a missing boundType as an error when running in v0.4 mode.
294
- */
286
+ /** Enforcement semantics. REQUIRED on every bounds field except `profile`. */
295
287
  boundType?: BoundType;
296
288
  /**
297
289
  * Which execution action types this bound governs, e.g. `["write"]`.
298
290
  *
299
- * When present, this is authoritative. When absent, enforcement falls back to
300
- * inferring the action type from the FIELD NAME (`send_daily_max` → `send`),
301
- * which is a convention rather than a contract: a profile that names a bound
302
- * after the domain concept instead of the action — calendar's
303
- * `booking_daily_max` against an action type of `write` — matches nothing and
304
- * is skipped, so a limit the user set is never applied and nothing says so.
305
- *
306
- * Declaring it removes the guess. Deliberately additive: profiles migrate one
307
- * at a time, and every remaining fallback is logged, so the cases still
308
- * relying on the naming convention become visible instead of staying silent.
291
+ * When present, this is authoritative. When absent, a `cumulative_sum` bound
292
+ * (or any bound on a profile published before v0.7) governs every action
293
+ * type in the profile's `actionTypes` registry; a `cumulative_count` bound
294
+ * on a v0.7+ profile MUST declare it (Bounds Schema rule 7). MUST NOT be
295
+ * declared on a `per_transaction` bound (it applies wherever its `of`
296
+ * field is present in the execution context) or on an `enum` bound (a
297
+ * capability flag, not an action-scoped limit).
309
298
  */
310
299
  appliesTo?: string[];
311
300
  /**
@@ -328,18 +317,14 @@ interface ProfileBoundsField {
328
317
  * min(value, maximum). Absent → no ceiling.
329
318
  */
330
319
  maximum?: number;
331
- /** @deprecated v0.4: use boundType instead. */
332
- constraint?: FieldConstraint;
333
- /** @deprecated v0.4: use boundType: { kind: 'enum', values: [...] }. */
334
- enum?: string[];
335
320
  }
336
321
  /**
337
322
  * v0.5 Content Provenance — how a profile's action content is hashed into a
338
- * signed receipt (`contentHash`). The ephemeral-content analog of Output
323
+ * signed ticket (`contentHash`). The ephemeral-content analog of Output
339
324
  * Provenance: it binds the *bytes* of the action rather than a location.
340
325
  *
341
326
  * Profile-bound and OPTIONAL. Absent → no content hash is produced (full
342
- * backward compatibility). The gateway computes the hash; the SP only ever
327
+ * backward compatibility). The gateway computes the hash; the AS only ever
343
328
  * receives the hash, never the content, so HAP's privacy-minimal design holds.
344
329
  *
345
330
  * At `version:"1"` the profile declares only the *policy* — whether to bind and
@@ -399,18 +384,35 @@ interface ContentBinding {
399
384
  * Absent → the binding applies to every gated action under the profile.
400
385
  */
401
386
  appliesTo?: string[];
387
+ /**
388
+ * v2 only — what kind of value each bound field holds, so a verifier (or any
389
+ * view) can collect and show it without guessing from the field's name:
390
+ * - `text` — one string (an email body);
391
+ * - `list` — an array of strings (recipients);
392
+ * - `files` — the sealed fingerprints of documents sent by reference:
393
+ * `[{ filename, sha256 }]` — never the bytes. A verifier asks for the
394
+ * files themselves and computes each SHA-256 locally.
395
+ *
396
+ * A hint only: it never changes what is hashed. Keys MUST be a subset of
397
+ * {@link fields}; a field without an entry is unspecified (a verifier may
398
+ * offer a choice, as before).
399
+ */
400
+ field_kinds?: Record<string, ContentFieldKind>;
402
401
  }
402
+ /** See {@link ContentBinding.field_kinds}. */
403
+ type ContentFieldKind = 'text' | 'list' | 'files';
403
404
  /**
404
- * Context field definition within a v0.4 profile.
405
+ * Scope field definition within a profile (renamed from `ProfileContextField`
406
+ * in v0.7 — protocol.md → *Migration from v0.6*, `contextSchema` → `scopeSchema`).
405
407
  */
406
- interface ProfileContextField {
408
+ interface ProfileScopeField {
407
409
  type: 'string' | 'number';
408
410
  required: boolean;
409
411
  description?: string;
410
412
  displayName?: string;
411
413
  format?: 'email' | 'domain' | 'url' | 'currency';
412
414
  /**
413
- * v0.6 — what this field NAMES on the read path. `counterparty` = the other
415
+ * What this field NAMES on the read path. `counterparty` = the other
414
416
  * party to a communication (matched against an item's participants);
415
417
  * `resource` = the container an item belongs to (a direct attribute match —
416
418
  * and a resource scope enforced on writes MUST also bind reads). Absent →
@@ -419,7 +421,6 @@ interface ProfileContextField {
419
421
  */
420
422
  scopeKind?: 'counterparty' | 'resource';
421
423
  constraint?: FieldConstraint;
422
- enum?: string[];
423
424
  }
424
425
  /**
425
426
  * Execution context field definition — declared source (value comes from the agent's tool call).
@@ -435,13 +436,11 @@ interface DeclaredFieldDef {
435
436
  */
436
437
  type CumulativeWindow = 'daily' | 'weekly' | 'monthly';
437
438
  /**
438
- * Execution context field definition — cumulative source (resolved from execution log).
439
+ * Execution context field definition — cumulative source (resolved from the
440
+ * AS's ticket history; see protocol.md → *Cumulative State*).
439
441
  *
440
- * The gatekeeper resolves these by querying the execution log:
441
442
  * - `cumulativeField`: which declared field to sum (use "_count" for plain counting)
442
443
  * - `window`: time window for aggregation (daily, weekly, monthly)
443
- *
444
- * The resolved value = running total within window + current call value.
445
444
  */
446
445
  interface CumulativeFieldDef {
447
446
  source: 'cumulative';
@@ -456,35 +455,21 @@ interface CumulativeFieldDef {
456
455
  */
457
456
  type ExecutionContextFieldDef = DeclaredFieldDef | CumulativeFieldDef;
458
457
  /**
459
- * Gate question definition.
460
- * @deprecated v0.4 uses a single intent gate with no profile-specific questions.
461
- */
462
- interface GateQuestion {
463
- question: string;
464
- required: boolean;
465
- }
466
- /**
467
- * @deprecated Execution paths removed in v0.4. Kept for backward compatibility.
468
- */
469
- interface ExecutionPath {
470
- description: string;
471
- requiredDomains?: string[];
472
- ttl?: {
473
- default: number;
474
- max: number;
475
- };
476
- }
477
- /**
478
- * Agent Profile — defines constraint types, execution paths, gate questions,
479
- * and the frame/bounds/context schemas for bounded execution.
480
- *
481
- * Supports both v0.3 (frameSchema) and v0.4 (boundsSchema + contextSchema).
458
+ * Agent Profile — defines the bounds/scope/execution-context schemas, gates,
459
+ * TTL policy, and retention for a bounded authority (protocol.md → *Profiles*).
482
460
  */
483
461
  /**
484
462
  * A commitment mode a person can choose when signing a mandate. (`review_above_cap`
485
463
  * is not chosen by the signer — it follows from team caps.)
486
464
  */
487
465
  type SignableCommitmentMode = 'automatic' | 'review';
466
+ /** protocol.md → *Owner Signatures* → "Where the requirement lives" — the
467
+ * profile-floor tier: `minBinding` names the weakest `OwnerSignatureBinding`
468
+ * this profile accepts for a co-signing owner. */
469
+ interface ProfileOwnerSignatureFloor {
470
+ required: boolean;
471
+ minBinding?: OwnerSignatureBinding;
472
+ }
488
473
  interface AgentProfile {
489
474
  id: string;
490
475
  name?: string;
@@ -505,9 +490,10 @@ interface AgentProfile {
505
490
  */
506
491
  whatsNew?: string;
507
492
  /**
508
- * Whether receipts under this profile may be looked up BY THEIR CONTENT — a
509
- * verifier holding the content supplies its hash and learns which receipts
510
- * bind it, without needing a receipt id.
493
+ * Whether tickets under this profile may be looked up BY THEIR CONTENT — a
494
+ * verifier holding the content supplies its hash and learns which tickets
495
+ * bind it, without needing a ticket id. (Renamed from `receipt_lookup` in
496
+ * v0.7.)
511
497
  *
512
498
  * OFF unless declared, and that default is the point. The lookup is a
513
499
  * confirmation oracle: given a guess at the content it says whether that
@@ -519,13 +505,8 @@ interface AgentProfile {
519
505
  * Enable only when the bound content is unguessable enough that producing it
520
506
  * is equivalent to already having it: prose, an artifact URL, a whole record
521
507
  * payload. Never for a binding over a short value drawn from a small set.
522
- *
523
- * Why it must exist at all: most consequential actions cannot carry their
524
- * receipt id. A released build was built before the receipt existed, a
525
- * content-addressed artifact would change identity if the id were added, and
526
- * a forwarded message has usually lost the footer that carried it.
527
508
  */
528
- receipt_lookup?: boolean;
509
+ ticket_lookup?: boolean;
529
510
  /**
530
511
  * The commitment modes a mandate under this profile may be signed with.
531
512
  * Absent → every mode (`automatic`, `review`), as before this field existed.
@@ -539,21 +520,14 @@ interface AgentProfile {
539
520
  */
540
521
  commitment_modes?: readonly SignableCommitmentMode[];
541
522
  /**
542
- * v0.3 frame schema (deprecated, kept for backward compat).
543
- * Used when boundsSchema is not present.
544
- */
545
- frameSchema?: {
546
- keyOrder: string[];
547
- fields: Record<string, ProfileFrameField>;
548
- };
549
- /**
550
- * v0.4 bounds schema — defines the authorization bounds parameters.
523
+ * The bounds schema — the enforceable parameters (protocol.md → *Bounds
524
+ * Schema*).
551
525
  */
552
526
  boundsSchema?: {
553
527
  keyOrder: string[];
554
528
  fields: Record<string, ProfileBoundsField>;
555
529
  /**
556
- * v0.5+ registry of the action types this profile recognizes (e.g.
530
+ * Registry of the action types this profile recognizes (e.g.
557
531
  * `["send", "delete", "setup"]`). Every `execution.action_type` the
558
532
  * Authority Server and gateway accept for this profile MUST be a member
559
533
  * when the registry is declared (protocol.md → Bounds Schema, rule 2);
@@ -564,92 +538,45 @@ interface AgentProfile {
564
538
  actionTypes?: readonly string[];
565
539
  };
566
540
  /**
567
- * v0.4 context schema — defines the execution context parameters (e.g., currency, action_type).
568
- * May be absent or empty for profiles with no static context.
541
+ * The scope schema — operational scoping fields that stay local (renamed
542
+ * from `contextSchema` in v0.7). May be absent or empty for profiles with
543
+ * no static scope.
569
544
  */
570
- contextSchema?: {
545
+ scopeSchema?: {
571
546
  keyOrder: string[];
572
- fields: Record<string, ProfileContextField>;
547
+ fields: Record<string, ProfileScopeField>;
573
548
  };
574
549
  executionContextSchema: {
575
550
  fields: Record<string, ExecutionContextFieldDef>;
576
551
  };
577
- /** @deprecated Execution paths removed in v0.4. Kept for backward compatibility. */
578
- executionPaths?: Record<string, ExecutionPath>;
579
552
  requiredGates: string[];
580
- /**
581
- * v0.4: no gateQuestions — intent prompt is universal, defined in the gateway UI.
582
- * v0.3: profile-specific gate questions (deprecated).
583
- */
584
- gateQuestions?: {
585
- problem?: GateQuestion;
586
- objective?: GateQuestion;
587
- tradeoffs?: GateQuestion;
588
- };
589
553
  ttl: {
590
554
  default: number;
591
555
  max: number;
592
556
  };
593
557
  retention_minimum: number;
594
558
  /**
595
- * v0.5 Content Provenance (OPTIONAL, profile-bound). When present, the
559
+ * Content Provenance (OPTIONAL, profile-bound). When present, the
596
560
  * gateway computes a `contentHash` for gated writes under this profile and
597
- * passes it (hash only) to the SP, which signs it into the receipt. Absent
561
+ * passes it (hash only) to the AS, which signs it into the ticket. Absent
598
562
  * → no content hash. See {@link ContentBinding}.
599
563
  */
600
564
  content_binding?: ContentBinding;
601
565
  /**
602
- * Tool gating configuration — how MCP tools map to execution context.
603
- * @deprecated Tool gating now lives in integration manifests (content/integrations/*.json).
604
- * Kept for backward compatibility with profiles that still include it.
566
+ * The execution-context fields a ticket under this profile MAY disclose
567
+ * (new in v0.7 — protocol.md → *Ticket Disclosure Is Declared*). Absent →
568
+ * nothing is disclosed by default. A mandate's own `disclose_fields` (when
569
+ * present) MUST be a subset of this list — a mandate may narrow disclosure,
570
+ * never widen it.
605
571
  */
606
- toolGating?: ProfileToolGating;
607
- }
608
- /**
609
- * Available transforms for array-aware execution mappings.
610
- * - length: array length → number
611
- * - join: array items joined by comma → string
612
- * - join_domains: extract email domains, deduplicate, sort, join → string
613
- */
614
- type ExecutionMappingTransform = 'join' | 'join_domains' | 'length';
615
- /**
616
- * Execution mapping value — how a tool argument maps to execution context field(s).
617
- * - string: direct copy (argName → fieldName)
618
- * - { field, divisor }: numeric division (e.g., cents ÷ 100 → EUR)
619
- * - { field, transform }: array transform (e.g., join_domains)
620
- * - Array form: one argument maps to multiple execution fields
621
- */
622
- type ExecutionMappingValue = string | {
623
- field: string;
624
- divisor: number;
625
- } | {
626
- field: string;
627
- transform: ExecutionMappingTransform;
628
- } | Array<{
629
- field: string;
630
- divisor?: number;
631
- transform?: ExecutionMappingTransform;
632
- }>;
633
- /**
634
- * Tool gating entry — how a tool's calls map to execution context fields.
635
- * Read-only tools use { category: "read" } — they require authorization
636
- * but skip execution context verification.
637
- */
638
- interface ProfileToolGatingEntry {
639
- executionMapping: Record<string, ExecutionMappingValue>;
640
- staticExecution?: Record<string, string | number>;
641
- /** Read-only tools: require authorization but no execution context checks */
642
- category?: 'read';
643
- }
644
- /**
645
- * Profile-level tool gating configuration.
646
- * - default: applied to all tools not listed in overrides
647
- * - overrides: per-tool configs keyed by original MCP tool name
648
- * Use { category: "read" } for read-only tools (null is deprecated)
649
- */
650
- interface ProfileToolGating {
651
- default: ProfileToolGatingEntry;
652
- overrides?: Record<string, ProfileToolGatingEntry | null>;
572
+ disclose_fields?: string[];
573
+ /**
574
+ * Profile-floor requirement for an owner signature on a mandate under this
575
+ * profile (protocol.md → *Owner Signatures* → "Where the requirement
576
+ * lives"). Reserved for domains that cannot mean anything without a
577
+ * signature — used more freely it forks `charge` from `charge-with-cosign`.
578
+ */
579
+ ownerSignature?: ProfileOwnerSignatureFloor;
653
580
  }
654
581
  /**
655
582
  * A recorded execution — stored after gatekeeper approval for cumulative tracking.
@@ -685,51 +612,47 @@ interface ExecutionLogQuery {
685
612
  */
686
613
  actionTypes?: readonly string[]): number;
687
614
  }
688
- /**
689
- * Agent frame parameters — mixed types (strings and numbers).
690
- * Keys and values come from the profile's frameSchema.
691
- */
692
- type AgentFrameParams = Record<string, string | number>;
693
615
  /**
694
616
  * Agent bounds parameters — mixed types (strings and numbers).
695
- * Keys and values come from the profile's boundsSchema (v0.4).
617
+ * Keys and values come from the profile's boundsSchema.
696
618
  */
697
619
  type AgentBoundsParams = Record<string, string | number>;
698
620
  /**
699
- * Agent context parameters — mixed types (strings and numbers).
700
- * Keys and values come from the profile's contextSchema (v0.4).
621
+ * Agent scope parameters — mixed types (strings and numbers). Keys and
622
+ * values come from the profile's scopeSchema (renamed from
623
+ * `AgentContextParams` in v0.7).
701
624
  */
702
- type AgentContextParams = Record<string, string | number>;
625
+ type AgentScopeParams = Record<string, string | number>;
703
626
  /**
704
627
  * Request to the Gatekeeper for bounded execution verification.
705
628
  */
706
629
  interface GatekeeperRequest {
707
- /** The authorization frame (what was attested to) — v0.3 */
708
- frame: AgentFrameParams;
709
- /** Attestation blobs (base64url) for each domain */
710
- attestations: string[];
711
- /** The agent's execution values for this specific action */
630
+ /** The bounds the mandate(s) committed to. */
631
+ bounds: AgentBoundsParams;
632
+ /** Mandate blobs (base64url) to verify against. */
633
+ mandates: string[];
634
+ /** The agent's execution values for this specific action. */
712
635
  execution: Record<string, string | number>;
713
- /** v0.4: context parameters (currency, action_type, etc.) */
714
- context?: AgentContextParams;
636
+ /** Scope parameters (currency, action_type, allowed recipients, etc.) —
637
+ * enforced locally only; never sent to the Authority Server. */
638
+ scope?: AgentScopeParams;
715
639
  /**
716
- * Authorization path used to scope cumulative lookups in the execution log.
717
- *
718
- * Deliberately OUTSIDE `frame`: the frame is hashed and validated against the
719
- * profile's boundsSchema, so an extra key there is rejected as an unknown
720
- * field and breaks attestation verification outright. Cumulative checks
721
- * previously read the path from the frame, where callers cannot legally put
722
- * it — so it resolved to "" while the log stored real paths, no entry ever
723
- * matched, and every running total read zero. The local gate existed but
724
- * could never fire.
640
+ * Authorization path used to scope cumulative lookups in the execution log
641
+ * (display only — see {@link ExecutionLogQuery}; the Gatekeeper MUST NOT
642
+ * enforce cumulative bounds locally, protocol.md → *Enforcement Authority*).
725
643
  */
726
644
  path?: string;
727
645
  }
728
646
  /**
729
- * Structured error from Gatekeeper verification.
647
+ * Structured error from Gatekeeper verification. Codes are the canonical
648
+ * v0.7 surface ({@link HapErrorCode}, `src/errors.ts`) plus the two
649
+ * Gatekeeper-local-only codes that never reach the wire (`FRAME_MISMATCH`
650
+ * is retired with v0.3; a Gatekeeper reports `BOUNDS_HASH_MISMATCH` /
651
+ * `SCOPE_HASH_MISMATCH` for both its own local mismatch and the AS's wire
652
+ * refusal, per protocol.md → *Error Codes*, "Gatekeeper · local").
730
653
  */
731
654
  interface GatekeeperError {
732
- code: 'BOUND_EXCEEDED' | 'CUMULATIVE_LIMIT_EXCEEDED' | 'INVALID_SIGNATURE' | 'TTL_EXPIRED' | 'FRAME_MISMATCH' | 'BOUNDS_MISMATCH' | 'CONTEXT_MISMATCH' | 'DOMAIN_NOT_COVERED' | 'INVALID_PROFILE' | 'MALFORMED_ATTESTATION' | 'INVALID_ACTION_TYPE' | 'ATTESTATION_REVOKED' | 'APPROVAL_REQUIRED' | 'IDEMPOTENCY_MISMATCH' | 'MANDATE_SIGNATURE_REQUIRED' | 'MANDATE_SIGNATURE_INVALID' | 'APPROVAL_SIGNATURE_REQUIRED' | 'APPROVAL_SIGNATURE_INVALID' | 'BOUNDS_INVALID_VALUE' | 'CONTEXT_INVALID_VALUE';
655
+ code: HapErrorCode;
733
656
  field?: string;
734
657
  message: string;
735
658
  bound?: string | number;
@@ -780,6 +703,46 @@ type GatekeeperResult = {
780
703
  */
781
704
  declare function canonicalize(value: unknown): string;
782
705
 
706
+ /**
707
+ * base64url (RFC 4648 §5), strict — no padding, no standard-base64 characters.
708
+ *
709
+ * protocol.md → *Mandate Payload* rule 3: "Signatures MUST be encoded as
710
+ * base64url without padding ... Implementations MUST NOT use standard base64
711
+ * (which differs in `+`/`/` vs `-`/`_` and in padding) — third-party verifiers
712
+ * reading the spec literally will reject standard-base64 signatures."
713
+ *
714
+ * Earlier hap-core verifiers were lenient: they translated `+`/`/` back from
715
+ * `-`/`_` and re-added padding before decoding, so a standard-base64 signature
716
+ * verified exactly as well as a base64url one — silently accepting the wire
717
+ * format the spec forbids. v0.7 closes that: decoding a string that is not
718
+ * strict base64url throws, never silently repairs it.
719
+ */
720
+ /** Encode bytes as base64url with no padding. */
721
+ declare function toBase64Url(bytes: Uint8Array): string;
722
+ /**
723
+ * Decode a STRICT base64url string (no padding, no `+`/`/`/`=`).
724
+ *
725
+ * @throws Error (no protocol code — the caller knows which artifact it was
726
+ * decoding and assigns the code) when the input carries a `+`, `/`, `=`, or
727
+ * any other byte outside the base64url alphabet.
728
+ */
729
+ declare function fromBase64Url(s: string): Uint8Array;
730
+
731
+ /** The protocol version this package issues and verifies. */
732
+ declare const PROTOCOL_VERSION = "0.7";
733
+ /** The protocol versions this package can verify and enforce. */
734
+ declare const SUPPORTED_VERSIONS: readonly string[];
735
+ /**
736
+ * The highest version both the requester and this implementation support.
737
+ *
738
+ * @param requested `supported_versions` from the mandate request. Absent →
739
+ * read as `["0.6"]` (protocol.md rule 1) — which, against this package's
740
+ * `SUPPORTED_VERSIONS`, has no overlap and refuses honestly rather than
741
+ * silently assuming `0.7`.
742
+ * @throws HapError `VERSION_UNSUPPORTED` when no version is common to both.
743
+ */
744
+ declare function negotiateVersion(requested: readonly string[] | undefined, supported?: readonly string[]): string;
745
+
783
746
  /**
784
747
  * Content binding — Level 2 content proof (HAP v0.5 Content Provenance).
785
748
  *
@@ -884,6 +847,14 @@ declare function selectBoundFields(binding: ContentBinding, args: Record<string,
884
847
  * {@link selectBoundFields} + {@link computeContentHash} for the common path.
885
848
  */
886
849
  declare function computeFieldsContentHash(binding: ContentBinding, args: Record<string, unknown>): string;
850
+ /**
851
+ * Why a binding's `field_kinds` is malformed, or null when it is fine (or
852
+ * absent). For profile validation — a malformed hint is a profile error, not
853
+ * a call-time refusal, because it never changes what is hashed.
854
+ */
855
+ declare function invalidFieldKindsReason(binding: ContentBinding): string | null;
856
+ /** The bound fields declared as `files` — sealed document fingerprints. */
857
+ declare function filesFields(binding: ContentBinding): string[];
887
858
 
888
859
  /**
889
860
  * Intent hashing + intent-disclosure binding (HAP v0.5).
@@ -950,20 +921,17 @@ interface SubjectValidation {
950
921
  * - `self_declared` ⇒ `low` / `self`, no disclosed name.
951
922
  * - `as_vouched` ⇒ `high` / `as`, `verifier` required.
952
923
  * - `eudi` ⇒ `high` / `external`, `verifier` required — and, when the
953
- * carrying attestation's `owner_mandates` are supplied, a corresponding
924
+ * carrying mandate's `mandate_owners` are supplied, a corresponding
954
925
  * entry with `binding:"eudi"` for this subject's DID.
955
926
  * - `disclose.name` only at `assurance:"high"`.
956
927
  *
957
- * v0.6: `Subject.owner_signature` is deprecated and IGNORED here — it signed
958
- * the identity claim, not the mandate (see the field's deprecation note). The
959
- * signature-bearing object is the attestation's `owner_mandates` entry, which
928
+ * The signature-bearing object is the mandate's `mandate_owners` entry, which
960
929
  * is payload-level context this per-subject check cannot see on its own; pass
961
- * `opts.ownerMandates` to enforce the eudi ⇒ mandate-entry rule, omit it to
962
- * validate subject shape alone (pre-0.6 callers keep their behaviour minus
963
- * the retired owner_signature requirement).
930
+ * `opts.mandateOwners` to enforce the eudi ⇒ mandate-owner-entry rule, omit it
931
+ * to validate subject shape alone.
964
932
  */
965
933
  declare function validateSubject(subject: Subject, opts?: {
966
- ownerMandates?: OwnerMandate[];
934
+ mandateOwners?: MandateOwnerEntry[];
967
935
  }): SubjectValidation;
968
936
  /**
969
937
  * The footer line for a subject — the ONE place this wording lives.
@@ -991,76 +959,38 @@ declare function deriveIdentityLine(subject: Subject | undefined | null, { opera
991
959
  }): string;
992
960
 
993
961
  /**
994
- * Frame Canonicalization for Agent Profiles
962
+ * Bounds & Scope Canonicalization (protocol.md → *Bounds & Scope
963
+ * Canonicalization*).
995
964
  *
996
- * Agent profiles support mixed-type fields (strings and numbers).
997
965
  * Canonical form: `key=value` records joined with LF, keys in the profile's
998
966
  * keyOrder. Values are stringified with String(value) — the shortest
999
967
  * round-trippable form for numbers — then percent-encoded per protocol.md
1000
968
  * (`=`, `%`, and every byte outside printable ASCII); a value carrying a raw
1001
969
  * LF/CR is refused, never normalized. See `canonicalRecords` below.
1002
970
  *
1003
- * v0.3: frameSchema
1004
- * v0.4: boundsSchema + contextSchema (separate hashes)
971
+ * v0.3's `frameSchema` / `canonicalFrame` / `computeFrameHash` are retired
972
+ * with the rest of v0.3 (CLAUDE.md "Decided by the owner": no backward
973
+ * compatibility). v0.7 renames `contextSchema` → `scopeSchema` and
974
+ * `AgentContextParams` → `AgentScopeParams` (protocol.md → *Migration from
975
+ * v0.6*); the functions below follow suit (`canonicalContext` →
976
+ * `canonicalScope`, `computeContextHash` → `computeScopeHash`,
977
+ * `validateContextParams` → `validateScopeParams`).
1005
978
  */
1006
979
 
1007
980
  /**
1008
- * Validates frame parameters against the profile's frame schema.
1009
- */
1010
- declare function validateFrameParams(params: AgentFrameParams, profile: AgentProfile): {
1011
- valid: boolean;
1012
- errors: string[];
1013
- };
1014
- /**
1015
- * Builds the canonical frame string from parameters.
1016
- * All values are converted to strings. Keys are ordered per profile's keyOrder.
1017
- *
1018
- * @throws Error if any field fails validation
1019
- */
1020
- declare function canonicalFrame(params: AgentFrameParams, profile: AgentProfile): string;
1021
- /**
1022
- * Computes the frame hash from a canonical frame string.
1023
- *
1024
- * @returns Hash in format "sha256:<64 hex chars>"
1025
- */
1026
- declare function frameHash(canonicalFrameString: string): string;
1027
- /**
1028
- * Convenience: builds canonical frame and computes hash in one step.
1029
- */
1030
- declare function computeFrameHash(params: AgentFrameParams, profile: AgentProfile): string;
1031
- /**
1032
- * Validates bounds parameters against the profile's boundsSchema (v0.4).
981
+ * Validates bounds parameters against the profile's boundsSchema.
1033
982
  */
1034
983
  declare function validateBoundsParams(params: AgentBoundsParams, profile: AgentProfile): {
1035
984
  valid: boolean;
1036
985
  errors: string[];
1037
986
  };
1038
987
  /**
1039
- * Validates context parameters against the profile's contextSchema (v0.4).
988
+ * Validates scope parameters against the profile's scopeSchema.
1040
989
  */
1041
- declare function validateContextParams(params: AgentContextParams, profile: AgentProfile): {
990
+ declare function validateScopeParams(params: AgentScopeParams, profile: AgentProfile): {
1042
991
  valid: boolean;
1043
992
  errors: string[];
1044
993
  };
1045
- /**
1046
- * Authoring-time check for `per_transaction` bound `requiredFor` (v0.8+):
1047
- * entries must name a real `action_type` from the profile's declared
1048
- * `boundsSchema.actionTypes` registry, and the field is only meaningful on
1049
- * `per_transaction` bounds (see `BoundType`'s doc comment for why the other
1050
- * kinds don't carry it).
1051
- *
1052
- * This is NOT wired into `registerProfile` or any enforcement path — nothing
1053
- * in hap-core validates profile JSON at load time today (the pre-existing
1054
- * `requiredFor` on a context/scope constraint has the same gap), so adding
1055
- * an automatic refusal here would be new behaviour beyond this change's
1056
- * scope. Call it explicitly from an authoring tool, a hap-profiles CI check,
1057
- * or a test, to catch a `requiredFor` entry that can never match (misspelled
1058
- * action type) or is attached to a bound kind that silently ignores it.
1059
- *
1060
- * Returns an empty array when the profile has no boundsSchema or nothing to
1061
- * check — never throws.
1062
- */
1063
- declare function validateBoundsRequiredFor(profile: AgentProfile): string[];
1064
994
  /**
1065
995
  * Thrown when a value cannot be canonicalized at all — currently only for raw
1066
996
  * LF/CR inside a value. Carries the protocol error code so callers can map it
@@ -1073,9 +1003,9 @@ declare function validateBoundsRequiredFor(profile: AgentProfile): string[];
1073
1003
  * does not faithfully represent the input."
1074
1004
  */
1075
1005
  declare class CanonicalValueError extends Error {
1076
- readonly code: 'BOUNDS_INVALID_VALUE' | 'CONTEXT_INVALID_VALUE';
1006
+ readonly code: 'BOUNDS_INVALID_VALUE' | 'SCOPE_INVALID_VALUE';
1077
1007
  readonly field: string;
1078
- constructor(code: 'BOUNDS_INVALID_VALUE' | 'CONTEXT_INVALID_VALUE', field: string, message: string);
1008
+ constructor(code: 'BOUNDS_INVALID_VALUE' | 'SCOPE_INVALID_VALUE', field: string, message: string);
1079
1009
  }
1080
1010
  /**
1081
1011
  * Builds the canonical bounds string from parameters.
@@ -1087,29 +1017,29 @@ declare class CanonicalValueError extends Error {
1087
1017
  */
1088
1018
  declare function canonicalBounds(params: AgentBoundsParams, profile: AgentProfile): string;
1089
1019
  /**
1090
- * Builds the canonical context string from parameters.
1091
- * Keys are ordered per profile's contextSchema.keyOrder; values are encoded per
1020
+ * Builds the canonical scope string from parameters.
1021
+ * Keys are ordered per profile's scopeSchema.keyOrder; values are encoded per
1092
1022
  * protocol.md → *Value encoding* (see `canonicalRecords`).
1093
- * For empty context (no contextSchema or no fields), returns "".
1023
+ * For empty scope (no scopeSchema or no fields), returns "".
1094
1024
  *
1095
1025
  * @throws Error if any field fails validation
1096
- * @throws CanonicalValueError (code CONTEXT_INVALID_VALUE) if a value carries a raw LF/CR
1026
+ * @throws CanonicalValueError (code SCOPE_INVALID_VALUE) if a value carries a raw LF/CR
1097
1027
  */
1098
- declare function canonicalContext(params: AgentContextParams, profile: AgentProfile): string;
1028
+ declare function canonicalScope(params: AgentScopeParams, profile: AgentProfile): string;
1099
1029
  /**
1100
- * Computes the bounds hash from bounds parameters (v0.4).
1030
+ * Computes the bounds hash from bounds parameters.
1101
1031
  *
1102
1032
  * @returns Hash in format "sha256:<64 hex chars>"
1103
1033
  */
1104
1034
  declare function computeBoundsHash(params: AgentBoundsParams, profile: AgentProfile): string;
1105
1035
  /**
1106
- * Computes the context hash from context parameters (v0.4).
1107
- * For empty context {}, returns the sha256 of "":
1036
+ * Computes the scope hash from scope parameters.
1037
+ * For empty scope {}, returns the sha256 of "":
1108
1038
  * "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
1109
1039
  *
1110
1040
  * @returns Hash in format "sha256:<64 hex chars>"
1111
1041
  */
1112
- declare function computeContextHash(params: AgentContextParams, profile: AgentProfile): string;
1042
+ declare function computeScopeHash(params: AgentScopeParams, profile: AgentProfile): string;
1113
1043
 
1114
1044
  /**
1115
1045
  * Which commitment modes a profile allows its mandates to be signed with
@@ -1128,248 +1058,208 @@ declare const SIGNABLE_COMMITMENT_MODES: readonly SignableCommitmentMode[];
1128
1058
  declare function allowedCommitmentModes(profile: AgentProfile): readonly SignableCommitmentMode[];
1129
1059
  /** Whether a mandate under this profile may be signed with `mode`. */
1130
1060
  declare function isCommitmentModeAllowed(profile: AgentProfile, mode: string): boolean;
1131
- /**
1132
- * Authoring check for a profile's `commitment_modes` declaration — for
1133
- * hap-profiles CI, an authoring tool or a test. Like `validateBoundsRequiredFor`
1134
- * it is not wired into profile loading; enforcement reads the declaration
1135
- * fail-closed through `allowedCommitmentModes`. Empty array = nothing to fix.
1136
- */
1137
- declare function validateCommitmentModes(profile: AgentProfile): string[];
1138
-
1139
- /**
1140
- * Attestation Encoding, Decoding, and Verification
1141
- *
1142
- * Supports both v0.3 (frame_hash) and v0.4 (bounds_hash + context_hash).
1143
- */
1144
1061
 
1062
+ /** One authoring-time finding. `code` is always a canonical v0.7 code — in
1063
+ * practice always `PROFILE_INVALID`, since that is the only mandate-request
1064
+ * refusal the protocol attributes to "the profile fails validation"
1065
+ * (protocol.md → Error Codes). */
1066
+ interface ProfileValidationError {
1067
+ code: HapErrorCode;
1068
+ field?: string;
1069
+ message: string;
1070
+ }
1145
1071
  /**
1146
- * Decodes a base64url-encoded attestation blob.
1147
- */
1148
- declare function decodeAttestationBlob(blob: string): Attestation;
1149
- /**
1150
- * Encodes an attestation as a base64url blob (no padding).
1151
- */
1152
- declare function encodeAttestationBlob(attestation: Attestation): string;
1153
- /**
1154
- * Computes the attestation ID (hash of the blob).
1072
+ * `profile_hash` — `"sha256:" + sha256(JCS(parsed))`, over the PARSED
1073
+ * profile document. Formatting, key order, and a trailing newline on disk
1074
+ * never change it (protocol.md → *Profile hash*; conformance vector set
1075
+ * `profile-hash.json`).
1155
1076
  */
1156
- declare function attestationId(blob: string): string;
1077
+ declare function computeProfileHash(parsed: unknown): string;
1157
1078
  /**
1158
- * Verifies an attestation signature using the SP public key.
1159
- *
1160
- * @returns true if valid
1161
- * @throws Error with code prefix if invalid
1079
+ * Authoring-time structural validation (protocol.md → *Bounds Schema*,
1080
+ * *Owner Signatures* → "Where the requirement lives", *Migration from
1081
+ * v0.6*). Returns `[]` for a clean profile; never throws.
1162
1082
  */
1163
- declare function verifyAttestationSignature(attestation: Attestation, publicKeyHex: string): Promise<void>;
1083
+ declare function validateProfile(profile: AgentProfile): ProfileValidationError[];
1164
1084
  /**
1165
- * Checks if an attestation has expired.
1085
+ * A mandate's `disclose_fields` MUST be a subset of the profile's own list
1086
+ * (protocol.md → *Mandate Payload*, conditional field `disclose_fields`: "a
1087
+ * subset of the profile's `disclose_fields` list"). A mandate may narrow
1088
+ * disclosure, never widen it.
1166
1089
  *
1167
- * @throws Error if expired
1090
+ * @throws Error prefixed `MALFORMED_MANDATE:` when it is not a subset.
1168
1091
  */
1169
- declare function checkAttestationExpiry(payload: AttestationPayload, now?: number): void;
1092
+ declare function checkDiscloseSubset(mandateDiscloseFields: readonly string[] | undefined, profileDiscloseFields: readonly string[] | undefined): void;
1093
+
1170
1094
  /**
1171
- * Verifies that the frame hash in the attestation matches the expected hash (v0.3).
1095
+ * Mandate encoding, decoding, signing, and verification (v0.7).
1172
1096
  *
1173
- * @throws Error if frame hash doesn't match
1097
+ * Renamed from `attestation.ts` (protocol.md → *Migration from v0.6*:
1098
+ * `header.typ: "HAP-attestation"` → `"HAP-mandate"`, `attestation_id` →
1099
+ * `mandate_id`). v0.3's frame-hash path and v0.4's dual frame/bounds
1100
+ * verification are retired with the rest of pre-v0.5 — this module issues
1101
+ * and verifies `version: "0.7"` mandates only (CLAUDE.md "Decided by the
1102
+ * owner": no backward-compat verify path for 0.5/0.6).
1174
1103
  */
1175
- declare function verifyFrameHash(attestation: Attestation, expectedFrameHash: string): void;
1104
+
1176
1105
  /**
1177
- * Detects whether an attestation is v0.4 (has bounds_hash + context_hash)
1178
- * or v0.3 (has frame_hash).
1179
- *
1180
- * Migration rule: if attestation has frame_hash but not bounds_hash, it is v0.3.
1106
+ * Decodes a base64url-encoded mandate blob.
1107
+ * @throws HapError `MALFORMED_MANDATE` on anything that is not a strict
1108
+ * base64url-encoded JSON mandate.
1181
1109
  */
1182
- declare function isV4Attestation(attestation: Attestation): boolean;
1110
+ declare function decodeMandateBlob(blob: string): Mandate;
1183
1111
  /**
1184
- * Verifies that the bounds hash in the attestation matches the expected hash (v0.4).
1185
- *
1186
- * @throws Error if bounds hash doesn't match
1112
+ * Encodes a mandate as a base64url blob (no padding).
1187
1113
  */
1188
- declare function verifyBoundsHash(attestation: Attestation, expectedBoundsHash: string): void;
1114
+ declare function encodeMandateBlob(mandate: Mandate): string;
1189
1115
  /**
1190
- * Verifies that the context hash in the attestation matches the expected hash (v0.4).
1191
- *
1192
- * @throws Error if context hash doesn't match
1116
+ * Computes the mandate blob id (hash of the blob) — renamed from
1117
+ * `attestationId`.
1193
1118
  */
1194
- declare function verifyContextHash(attestation: Attestation, expectedContextHash: string): void;
1119
+ declare function mandateBlobId(blob: string): string;
1195
1120
  /**
1196
- * Full attestation verification (signature + expiry + frame hash) — v0.3.
1121
+ * Sign a mandate payload with the Authority Server's Ed25519 private key.
1197
1122
  *
1198
- * @returns The decoded attestation payload
1199
- * @throws Error on any validation failure
1123
+ * @param opts.kid Optional key id for the envelope header. When present it
1124
+ * MUST identify the same key as `payload.issuer` (Mandate rule 8) — this
1125
+ * function does not enforce that on the signer's side; `verifyMandateSignature`
1126
+ * enforces it on the verifier's side, where a mismatch is actually dangerous.
1200
1127
  */
1201
- declare function verifyAttestation(blob: string, publicKeyHex: string, expectedFrameHash: string): Promise<AttestationPayload>;
1128
+ declare function signMandate(payload: MandatePayload, privateKey: Uint8Array, opts?: {
1129
+ kid?: string;
1130
+ }): Promise<Mandate>;
1202
1131
  /**
1203
- * Full attestation verification for v0.4 (signature + expiry + bounds_hash + context_hash).
1132
+ * Verifies a mandate's Ed25519 signature. The verification key is resolved
1133
+ * from `payload.issuer` itself — never from a key offered alongside the
1134
+ * artifact (protocol.md → *Ticket Verification* step 1, which states the
1135
+ * same rule for tickets; mandates follow it identically).
1204
1136
  *
1205
- * @returns The decoded attestation payload
1206
- * @throws Error on any validation failure
1137
+ * @param opts.trustedIssuers When supplied, an `issuer` not in this list is
1138
+ * rejected before any cryptography runs — "a verifier MUST reject a [...]
1139
+ * whose `issuer` it does not trust" (protocol.md → *Ticket Verification*).
1140
+ * @throws Error prefixed `INVALID_SIGNATURE:` on any verification failure.
1207
1141
  */
1208
- declare function verifyAttestationV4(blob: string, publicKeyHex: string, expectedBoundsHash: string, expectedContextHash: string): Promise<AttestationPayload>;
1209
-
1142
+ declare function verifyMandateSignature(mandate: Mandate, opts?: {
1143
+ trustedIssuers?: readonly string[];
1144
+ }): Promise<void>;
1210
1145
  /**
1211
- * Gatekeeper — Stateless Verification for Bounded Execution
1212
- *
1213
- * Supports both v0.3 (frameSchema / frame_hash) and v0.4 (boundsSchema + contextSchema /
1214
- * bounds_hash + context_hash).
1146
+ * Checks a mandate payload's time rules (Mandate rule 9): `expires_at` is
1147
+ * authoritative, with a {@link CLOCK_SKEW_SECONDS} tolerance that never
1148
+ * extends life past `expires_at + 300s`.
1215
1149
  *
1216
- * v0.3 flow (§8.6):
1217
- * 1. Resolve profile from frame
1218
- * 2. Recompute frame_hash
1219
- * 3. For each required domain: find attestation, verify signature, verify frame_hash, verify TTL
1220
- * 4. Check bounds: max → actual <= bound, enum → actual in allowed
1221
- * 5. Return { approved } or { approved: false, errors: [...] }
1222
- *
1223
- * v0.4 flow:
1224
- * 1. Resolve profile from bounds.profile
1225
- * 2. Recompute bounds_hash and context_hash
1226
- * 3. For each required domain: find attestation, verify signature, verify bounds_hash + context_hash, verify TTL
1227
- * 4. Check bounds (from boundsSchema), check context constraints (from contextSchema)
1228
- * 5. Resolve cumulative fields, check cumulative limits
1229
- * 6. Return { approved } or { approved: false, errors: [...] }
1150
+ * @throws Error prefixed `TTL_EXPIRED:` when expired.
1230
1151
  */
1231
-
1152
+ declare function checkMandateExpiry(payload: MandatePayload, now?: number): void;
1232
1153
  /**
1233
- * Verify an execution request against attested authorization.
1234
- *
1235
- * For v0.4 profiles (have boundsSchema), the `frame` param is interpreted as `bounds`,
1236
- * and the optional `context` param is used for the context hash check.
1154
+ * Validates the structural shape of `mandate_owners` (Mandate rule 7):
1155
+ * exactly one entry, `did` required, and the signature fields present
1156
+ * together or absent together. A co-signing entry's `did` MUST be key-bearing.
1237
1157
  *
1238
- * For v0.3 profiles (have frameSchema only), existing logic is used unchanged.
1239
- *
1240
- * @param request - The frame/bounds, attestations, execution values, and optional context
1241
- * @param publicKeyHex - The SP's public key in hex (cached locally by MCP server)
1242
- * @param now - Current timestamp in seconds (for testing)
1243
- * @param executionLog - Optional execution log for resolving cumulative fields
1158
+ * @throws HapError `MALFORMED_MANDATE` on a cardinality or completeness
1159
+ * violation; `OWNER_SIGNATURE_INVALID` when a co-signing DID is not key-bearing.
1244
1160
  */
1245
- declare function verify(request: GatekeeperRequest, publicKeyHex: string, now?: number, executionLog?: ExecutionLogQuery): Promise<GatekeeperResult>;
1161
+ declare function validateMandateOwners(payload: MandatePayload): void;
1246
1162
  /**
1247
- * Which action types' executions count toward this cumulative bound's running
1248
- * total. `undefined` means all of them.
1163
+ * Full mandate verification: decode, check `version`, verify the AS
1164
+ * signature, check expiry, validate `mandate_owners` shape.
1249
1165
  *
1250
- * `boundGovernsAction` decides whether a bound applies to the current call; this
1251
- * decides what the bound's total is made of. Both are needed: selecting the right
1252
- * bound and then feeding it the profile's combined total is still wrong — sales'
1253
- * "orders per day" was checked only on orders, but counted every quote and send.
1254
- * Consumption is partitioned by action type (*Cumulative Tracking* rule 4), as
1255
- * the Authority Server already does.
1166
+ * Deliberately does NOT verify any `mandate_owners` co-signature — that is
1167
+ * `verifyOwnerSignature` in `owner-signature.ts`, a separate trust axis the
1168
+ * caller opts into.
1256
1169
  *
1257
- * Same answer, same order of preference as `boundGovernsAction`: the declared
1258
- * `appliesTo`; else, for a count bound named for an action (`delete_daily_max`),
1259
- * that action; else every action type. Exported so display surfaces report the
1260
- * same totals the gate enforces.
1170
+ * @throws HapError `VERSION_UNSUPPORTED` for anything other than `"0.7"`.
1171
+ * @throws Error (`INVALID_SIGNATURE:` / `TTL_EXPIRED:` / `MALFORMED_MANDATE:`
1172
+ * prefixed, or `OWNER_SIGNATURE_INVALID` as a HapError) on any other failure.
1261
1173
  */
1262
- declare function boundActionTypes(fieldName: string, fieldDef: ProfileBoundsField): readonly string[] | undefined;
1174
+ declare function verifyMandate(blob: string, opts?: {
1175
+ trustedIssuers?: readonly string[];
1176
+ now?: number;
1177
+ }): Promise<MandatePayload>;
1263
1178
 
1264
1179
  /**
1265
- * Profile Registry — dynamically populated from git-hosted profile sources.
1266
- */
1267
-
1268
- declare function registerProfile(profileId: string, profile: AgentProfile): void;
1269
- declare function getProfile(profileId: string): AgentProfile | undefined;
1270
- declare function listProfiles(): string[];
1271
- declare function getAllProfiles(): AgentProfile[];
1272
- declare function clearProfiles(): void;
1273
-
1274
- /**
1275
- * did:key — encode/decode for KEY-BEARING DIDs (HAP v0.6).
1276
- *
1277
- * A real `did:key` is self-certifying: the public key IS the identifier, so
1278
- * substituting the key produces a DIFFERENT DID and no key directory is ever
1279
- * consulted. That property is what the Owner Mandate design stands on
1280
- * (protocol.md → "Identity DIDs vs signing DIDs"): a signing DID MUST be
1281
- * key-bearing, and verification uses the key carried in the identifier —
1282
- * deliberately, there is no `public_key` field anywhere on the wire.
1283
- *
1284
- * Format (W3C did:key method, Ed25519):
1285
- * did:key:z<base58btc( 0xed 0x01 ‖ 32-byte-public-key )>
1286
- * `z` is the multibase prefix for base58btc; `0xed 0x01` is the multicodec
1287
- * varint for ed25519-pub. The result always starts `did:key:z6Mk`.
1288
- *
1289
- * Scope: Ed25519 only — the one signing curve this protocol version uses.
1290
- * Anything else (including the reference implementation's legacy decorative
1291
- * `did:key:<uuid-fragment>` identifiers) decodes as NOT key-bearing.
1292
- */
1293
- /** Encode a 32-byte Ed25519 public key as a key-bearing `did:key:z6Mk…`. */
1294
- declare function encodeDidKey(publicKey: Uint8Array): string;
1295
- /**
1296
- * Decode a key-bearing `did:key` to its Ed25519 public key bytes.
1297
- *
1298
- * @throws Error prefixed `NOT_KEY_BEARING:` for anything that is not a valid
1299
- * base58btc-multibase Ed25519 did:key — including the legacy decorative
1300
- * `did:key:<uuid-fragment>` identifiers, other multibase prefixes, and other
1301
- * key types. The error name is the point: under the mandate design, a
1302
- * non-key-bearing signing DID must fail STRUCTURALLY, never fall back.
1303
- */
1304
- declare function decodeDidKey(did: string): Uint8Array;
1305
- /** True iff the DID decodes as a key-bearing Ed25519 did:key. Never throws. */
1306
- declare function isKeyBearingDid(did: string): boolean;
1307
-
1308
- /**
1309
- * Owner Mandate Signatures (HAP v0.6) — the `HAP-mandate` projection, the
1180
+ * Owner Signatures (v0.7) — the `HAP-mandate-projection` object, the
1310
1181
  * `HAP-approval` object, and their verification.
1311
1182
  *
1183
+ * Renamed from `mandate.ts` (protocol.md → *Migration from v0.6*: the
1184
+ * owner-signed projection's `typ` moves from `"HAP-mandate"` to
1185
+ * `"HAP-mandate-projection"`, disambiguating it from the AS-signed mandate
1186
+ * itself, which now legitimately owns the name `"HAP-mandate"`).
1187
+ *
1312
1188
  * The human signs BEFORE the AS does, so they cannot sign the finished
1313
- * attestation (`attestation_id`/`issued_at` do not exist yet). They sign a
1314
- * mandate PROJECTION: a canonical object every field of which is known at
1315
- * approval time and reconstructible from the finished attestation — so a
1316
- * verifier rebuilds it from the attestation it already holds and checks the
1317
- * signature with the key carried in the owner's DID. No side channel, no
1318
- * second fetch, no key directory. See protocol.md → "Owner Mandate Signatures".
1319
- *
1320
- * Verification here requires NO trust in the AS. What it cannot do is tell the
1321
- * verifier WHOSE key signed — confirming the DID belongs to the expected
1322
- * person is the out-of-band step (protocol.md → "Identity DIDs vs signing
1323
- * DIDs"), and it is the honest cost of cold verification.
1189
+ * mandate (`mandate_id`/`issued_at` do not exist yet). They sign a mandate
1190
+ * PROJECTION: a canonical object every field of which is known at approval
1191
+ * time and reconstructible from the finished mandate — so a verifier
1192
+ * rebuilds it from the mandate it already holds and checks the signature
1193
+ * with the key carried in the owner's DID. No side channel, no second
1194
+ * fetch, no key directory. See protocol.md → "Owner Signatures".
1195
+ *
1196
+ * Verification here requires NO trust in the AS. What it cannot do is tell
1197
+ * the verifier WHOSE key signed — confirming the DID belongs to the
1198
+ * expected person is the out-of-band step (protocol.md → "Verification
1199
+ * procedure" step 5), and it is the honest cost of cold verification.
1324
1200
  */
1325
1201
 
1326
- /** The object the owner signs — a canonical projection of the mandate. */
1202
+ /** The object the owner signs — a canonical projection of the mandate.
1203
+ * Field absence is defined, not incidental (protocol.md → *The signed
1204
+ * object: HAP-mandate-projection*): each conditional field is included
1205
+ * exactly when the mandate carries it and omitted otherwise. */
1327
1206
  interface MandateProjection {
1328
- typ: 'HAP-mandate';
1207
+ typ: 'HAP-mandate-projection';
1329
1208
  /** Projection/canonicalization version. A verifier MUST pin it. */
1330
- version: '0.6';
1209
+ version: '0.7';
1331
1210
  profile_id: string;
1332
- /** The signing owner's own DID. MUST be a member of `resolved_owners`. */
1211
+ /** Covered deliberately: the owner signs the profile's BYTES, not only its id. */
1212
+ profile_hash: string;
1213
+ /** The signing owner's own DID. MUST equal the carrying mandate's `mandate_owners[0].did`. */
1333
1214
  owner_did: string;
1334
1215
  bounds_hash: string;
1335
- context_hash: string;
1216
+ scope_hash: string;
1336
1217
  execution_context_hash: string;
1337
1218
  gate_content_hashes: Record<string, string>;
1338
- /** Included iff the attestation carries one — binds ciphertext AND the
1219
+ /** Included iff the mandate carries one — binds ciphertext AND the
1339
1220
  * frozen approver set, the swap this mechanism exists to stop. */
1340
1221
  intent_disclosure_hash?: string;
1341
1222
  commitment_mode: string;
1223
+ /** Included together, iff `commitment_mode === "review_above_cap"`. */
1224
+ above_cap_caps?: Record<string, number>;
1225
+ above_cap_approvers?: string[];
1226
+ /** Included iff the mandate narrows the profile's disclose_fields. */
1227
+ disclose_fields?: string[];
1342
1228
  /** The replay defence: the human signs how long the authority lives. */
1343
1229
  expires_at: number;
1344
1230
  nonce: string;
1345
1231
  }
1346
1232
  /** Per-action approval, signed by the owner in `review` mode. Signing a
1347
- * `reject` matters as much as a `commit`: a rejection the AS can discard is a
1348
- * rejection that never happened. */
1233
+ * `reject` matters as much as a `commit`: a rejection the AS can discard is
1234
+ * a rejection that never happened. */
1349
1235
  interface ApprovalObject {
1350
1236
  typ: 'HAP-approval';
1351
- version: '0.6';
1237
+ version: '0.7';
1352
1238
  proposal_id: string;
1353
- attestation_id: string;
1239
+ /** Renamed from `attestation_id` in v0.7. */
1240
+ mandate_id: string;
1354
1241
  decision: 'commit' | 'reject';
1355
- /** What was approved: the receipt's contentHash where the profile binds
1242
+ /** What was approved: the ticket's contentHash where the profile binds
1356
1243
  * content; otherwise sha256 over the JCS of the proposal's argument set. */
1357
1244
  content_hash: string;
1358
1245
  decided_at: number;
1359
1246
  nonce: string;
1360
1247
  }
1361
- declare class MandateError extends Error {
1362
- code: 'MANDATE_SIGNATURE_INVALID' | 'APPROVAL_SIGNATURE_INVALID' | 'NOT_KEY_BEARING' | 'OWNER_NOT_RESOLVED' | 'MALFORMED_ATTESTATION';
1363
- constructor(code: 'MANDATE_SIGNATURE_INVALID' | 'APPROVAL_SIGNATURE_INVALID' | 'NOT_KEY_BEARING' | 'OWNER_NOT_RESOLVED' | 'MALFORMED_ATTESTATION', message: string);
1248
+ /** Renamed from `MandateError` in v0.7 — carries a canonical {@link HapErrorCode}. */
1249
+ declare class OwnerSignatureError extends Error {
1250
+ code: HapErrorCode;
1251
+ constructor(code: HapErrorCode, message: string);
1364
1252
  }
1365
1253
  /**
1366
- * Rebuild the projection a given `owner_mandates` entry signed, from the
1367
- * attestation's own signed fields. Field absence is defined, not incidental:
1368
- * `intent_disclosure_hash` is included iff the attestation carries one.
1254
+ * Rebuild the projection a given `mandate_owners` entry signed, from the
1255
+ * mandate's own signed fields. Field absence is defined, not incidental:
1256
+ * `intent_disclosure_hash`, `above_cap_caps`/`above_cap_approvers`, and
1257
+ * `disclose_fields` are included iff the mandate carries them.
1369
1258
  */
1370
- declare function buildMandateProjection(payload: AttestationPayload, entry: Pick<OwnerMandate, 'did' | 'nonce'>): MandateProjection;
1371
- /** The exact bytes an owner signs: RFC 8785 (JCS) canonical UTF-8. */
1372
- declare function mandateSigningBytes(projection: MandateProjection): Uint8Array;
1259
+ declare function buildMandateProjection(payload: MandatePayload, entry: Pick<MandateOwnerEntry, 'did' | 'nonce'>): MandateProjection;
1260
+ /** The exact bytes an owner signs: RFC 8785 (JCS) canonical UTF-8. Renamed
1261
+ * from `mandateSigningBytes` in v0.7. */
1262
+ declare function projectionSigningBytes(projection: MandateProjection): Uint8Array;
1373
1263
  /** The exact bytes an owner signs for a per-action approval. */
1374
1264
  declare function approvalSigningBytes(approval: ApprovalObject): Uint8Array;
1375
1265
  /**
@@ -1382,40 +1272,61 @@ declare function signMandateProjection(projection: MandateProjection, privateKey
1382
1272
  /** Sign an approval object with a raw Ed25519 private key (`raw` binding). */
1383
1273
  declare function signApproval(approval: ApprovalObject, privateKey: Uint8Array): Promise<string>;
1384
1274
  /**
1385
- * Verify ONE `owner_mandates` entry against the attestation that carries it.
1275
+ * Verify ONE `mandate_owners` entry against the mandate that carries it.
1386
1276
  *
1387
- * Steps (protocol.md → "Verification procedure", steps 4 of 6): membership in
1388
- * `resolved_owners`, key-bearing DID, projection reconstruction, Ed25519 over
1389
- * JCS bytes. The DID is authoritative over `alg` — a disagreement is
1390
- * MANDATE_SIGNATURE_INVALID, never a fallback to the claimed algorithm.
1277
+ * Steps (protocol.md → "Verification procedure", step 4 of 6): the entry
1278
+ * names this mandate's sole owner, its signing DID is key-bearing,
1279
+ * projection reconstruction, Ed25519 over JCS bytes. The DID is
1280
+ * authoritative over `alg` — a disagreement is `OWNER_SIGNATURE_INVALID`,
1281
+ * never a fallback to the claimed algorithm.
1391
1282
  *
1392
- * What this deliberately does NOT verify: that the DID belongs to the person
1393
- * the verifier expects (out-of-band, step 5) and the AS's own signature over
1394
- * the attestation (verifyAttestationSignature, step 1).
1283
+ * What this deliberately does NOT verify: that the DID belongs to the
1284
+ * person the verifier expects (out-of-band, step 5) and the AS's own
1285
+ * signature over the mandate (`verifyMandateSignature`, step 1).
1395
1286
  */
1396
- declare function verifyOwnerMandate(attestation: Attestation, entry: OwnerMandate): Promise<void>;
1397
- /** Verify every `owner_mandates` entry an attestation carries. Resolves to the
1398
- * verified entries; an attestation with none resolves to `[]` (the v0.5
1399
- * posture — nothing to check, and nothing claimed). */
1400
- declare function verifyOwnerMandates(attestation: Attestation): Promise<OwnerMandate[]>;
1287
+ declare function verifyOwnerSignature(mandate: Mandate, entry: MandateOwnerEntry): Promise<void>;
1288
+ /** Verify every co-signing `mandate_owners` entry a mandate carries (i.e.
1289
+ * every entry that carries a signature). Resolves to the verified entries;
1290
+ * a mandate with none resolves to `[]` — nothing to check, nothing claimed. */
1291
+ declare function verifyOwnerSignatures(mandate: Mandate): Promise<MandateOwnerEntry[]>;
1401
1292
  /** Verify an approval signature against a signer's key-bearing DID. */
1402
1293
  declare function verifyApproval(approval: ApprovalObject, signature: string, signerDid: string): Promise<void>;
1294
+ /**
1295
+ * Enforce a profile's `ownerSignature` floor (protocol.md → *Owner
1296
+ * Signatures* → "Where the requirement lives" — the profile-floor tier,
1297
+ * checkable without trusting the AS: `profile_id`/`profile_hash` are in the
1298
+ * signed payload AND in the owner-signed projection).
1299
+ *
1300
+ * An unknown `binding` value is treated as rank 0 (weakest) rather than
1301
+ * rejected outright — "an AS MUST NOT reject a mandate_owners entry solely
1302
+ * because it does not recognize its binding value" extends naturally to a
1303
+ * verifier ranking it, since crediting an unrecognized binding with
1304
+ * unearned strength would be the more dangerous failure mode.
1305
+ *
1306
+ * @throws OwnerSignatureError `OWNER_SIGNATURE_REQUIRED` when the floor is
1307
+ * unmet — "MUST fail, not warn" (protocol.md, same section).
1308
+ */
1309
+ declare function checkOwnerSignatureRequirement(payload: MandatePayload, floor: ProfileOwnerSignatureFloor | undefined): void;
1403
1310
 
1404
1311
  /**
1405
- * Execution receipts (HAP v0.5/v0.6) — the wire type and holder-side
1406
- * verification. Until v0.6 this library had no receipt surface at all; every
1407
- * verifier hand-assembled the strip→canonicalize→verify dance. This module is
1408
- * that dance, once.
1312
+ * Mandate tickets (v0.7) — the wire type, signing, and holder-side
1313
+ * verification. Renamed from `receipt.ts` (protocol.md → *Mandate Tickets*:
1314
+ * "v0.4 introduced the object under the name execution receipt; v0.7 renames
1315
+ * it because the tense was wrong — a receipt follows payment, and the ticket
1316
+ * must come first").
1409
1317
  *
1410
- * Receipt payloads are camelCase on the wire (unlike the snake_case
1411
- * attestation payload) — a shipped inconsistency v0.6 chose to document
1412
- * rather than break (changelog.md → "Renames and terminology").
1318
+ * Ticket payloads are camelCase on the wire (unlike the snake_case mandate
1319
+ * payload) — a shipped inconsistency the spec documents rather than breaks
1320
+ * (protocol.md → *Migration from v0.6*, "Unchanged on purpose").
1413
1321
  */
1414
1322
 
1415
- /** Signed execution receipt — protocol.md → "Receipt Payload Schema". */
1416
- interface ReceiptPayload {
1323
+ /** Signed mandate ticket — protocol.md → *Ticket Payload Schema*. */
1324
+ interface TicketPayload {
1417
1325
  id: string;
1418
- groupId?: string | null;
1326
+ /** The mandate this ticket was issued under (new in v0.7). Audit and
1327
+ * chain-of-custody only — `boundsHash` remains the AS's lookup key. */
1328
+ mandateId: string;
1329
+ groupId: string | null;
1419
1330
  userId?: string;
1420
1331
  boundsHash: string;
1421
1332
  profileId: string;
@@ -1425,35 +1336,169 @@ interface ReceiptPayload {
1425
1336
  actionType: string;
1426
1337
  executionContext: Record<string, unknown>;
1427
1338
  cumulativeState?: Record<string, unknown>;
1428
- limits?: Record<string, unknown>;
1339
+ /** The mandate's plaintext bounds object, exactly as the AS enforced them
1340
+ * for this ticket (new in v0.7 — required). */
1341
+ limits: Record<string, unknown>;
1342
+ /** Protocol version of the ticket — the version of the mandate it was
1343
+ * issued under (new in v0.7). */
1344
+ version: string;
1345
+ /** The AS DID, as in the mandate (new in v0.7). */
1346
+ issuer: string;
1429
1347
  timestamp: number;
1430
- /** v0.6 — hash of the bound content, computed by the Gatekeeper, copied
1348
+ /** Hash of the bound content, computed by the Gatekeeper, copied
1431
1349
  * verbatim by the AS. The AS never sees the content. */
1432
1350
  contentHash?: string;
1433
- /** v0.6 — the binding declaration echoed into the signed receipt, so a
1351
+ /** The binding declaration echoed into the signed ticket, so a
1434
1352
  * verifier knows exactly what `contentHash` covers. */
1435
1353
  contentBinding?: Pick<ContentBinding, 'version' | 'kind' | 'fields' | 'required_fields' | 'appliesTo'>;
1436
- /** v0.6 — disclosed subset of the attestation's identity overlay. */
1354
+ /** Disclosed subset of the mandate's identity overlay. */
1437
1355
  subjects?: Subject[];
1438
- /** v0.6 — review path: the proposal this receipt executed. */
1356
+ /** Review path: the proposal this ticket executed. */
1439
1357
  proposalId?: string;
1440
- /** v0.6 — review path: the owner's HAP-approval signature (or its sha256)
1441
- * for the executed proposal. */
1442
- approvalSignature?: string;
1358
+ /** Review path: the owner's HAP-approval signature for the executed
1359
+ * proposal, as the object itself — never a hash of it, which a holder
1360
+ * could check only by asking the AS. */
1361
+ approvalSignature?: {
1362
+ alg: 'EdDSA' | 'ES256';
1363
+ signature: string;
1364
+ nonce: string;
1365
+ decided_at: number;
1366
+ };
1443
1367
  /** Ed25519 over the JCS-canonical payload (this field excluded), base64url. */
1444
1368
  signature: string;
1445
1369
  }
1446
1370
  /**
1447
- * Verify a receipt's AS signature: strip `signature`, JCS-canonicalize the
1448
- * rest, Ed25519-verify against the AS public key (hex). This is holder-side
1449
- * verification — it needs the COMPLETE receipt; a redacted public view cannot
1450
- * be re-verified this way (protocol.md → "Receipt Verification").
1371
+ * Sign a ticket payload with the Authority Server's Ed25519 private key —
1372
+ * the same key used for mandates.
1373
+ */
1374
+ declare function signTicket(payload: Omit<TicketPayload, 'signature'>, privateKey: Uint8Array): Promise<TicketPayload>;
1375
+ /**
1376
+ * Verify a ticket's AS signature: strip `signature`, JCS-canonicalize the
1377
+ * rest, Ed25519-verify against the key resolved from `issuer` — never
1378
+ * against a key offered alongside the ticket (protocol.md → *Ticket
1379
+ * Verification* step 1). This is holder-side verification — it needs the
1380
+ * COMPLETE ticket; a redacted public view cannot be re-verified this way
1381
+ * (see {@link publicTicketView}).
1451
1382
  *
1452
- * Content is checked separately: where `contentHash` is present, recompute it
1453
- * from the held artifact via the content-binding module and compare.
1383
+ * Content is checked separately: where `contentHash` is present, recompute
1384
+ * it from the held artifact via the content-binding module and compare.
1454
1385
  *
1386
+ * @param opts.trustedIssuers When supplied, an `issuer` not in this list is
1387
+ * rejected before any cryptography runs.
1455
1388
  * @throws Error prefixed `INVALID_SIGNATURE:` when verification fails.
1456
1389
  */
1457
- declare function verifyReceiptSignature(receipt: ReceiptPayload, publicKeyHex: string): Promise<void>;
1390
+ declare function verifyTicketSignature(ticket: TicketPayload, opts?: {
1391
+ trustedIssuers?: readonly string[];
1392
+ }): Promise<void>;
1393
+ /**
1394
+ * A redacted public view of a ticket (new in v0.7 — protocol.md → *Ticket
1395
+ * Disclosure Is Declared*, *Ticket Verification*). Hides `userId`,
1396
+ * `cumulativeState`, and `limits` unconditionally, and narrows
1397
+ * `executionContext` to exactly the keys named by `governingDiscloseFields`
1398
+ * (the mandate's `disclose_fields` where present, otherwise the profile's).
1399
+ *
1400
+ * Disclose NOTHING by default: an empty or absent `governingDiscloseFields`
1401
+ * strips `executionContext` entirely. "The holder is the verifier" — this
1402
+ * view is NOT independently re-verifiable against `signature` (it is missing
1403
+ * signed fields); a "signature valid" indicator on a page showing only this
1404
+ * view is the AS re-verifying its own signature, and implementations MUST
1405
+ * NOT present it as independently verified.
1406
+ */
1407
+ declare function publicTicketView(ticket: TicketPayload, governingDiscloseFields?: readonly string[]): Omit<TicketPayload, 'userId' | 'cumulativeState' | 'limits'>;
1408
+
1409
+ /**
1410
+ * Gatekeeper — local (Phase 1) verification for bounded execution (v0.7).
1411
+ *
1412
+ * protocol.md → *Validation Steps* (Phase 1, never reaches the wire):
1413
+ * 1. Resolve profile from bounds.profile
1414
+ * 2. Recompute bounds_hash and scope_hash
1415
+ * 3. For each mandate: decode, verify AS signature, verify version,
1416
+ * verify bounds_hash / scope_hash / profile_hash, verify expiry
1417
+ * 4. Check actionType registry membership
1418
+ * 5. Check per_transaction bounds and enum capability flags locally
1419
+ * (Enforcement Authority: this is what makes per_transaction
1420
+ * compromise-resistant — *Enforcement classes*)
1421
+ * 6. Check scope constraints (enum, subset, requiredFor) locally — the AS
1422
+ * never sees scope plaintext, so the Gatekeeper is the sole enforcer
1423
+ * 7. Return { approved } or { approved: false, errors: [...] }
1424
+ *
1425
+ * What this module deliberately does NOT do (protocol.md → *Enforcement
1426
+ * Authority*, *Migration from v0.6* semantic change 9): enforce
1427
+ * `cumulative_sum` / `cumulative_count` bounds. "Local cumulative
1428
+ * enforcement is removed, not merely deprecated: a Gatekeeper MUST NOT
1429
+ * refuse an execution on a cumulative bound from its own records" — only
1430
+ * the Authority Server's ticket history is authoritative for a running
1431
+ * total across every Gatekeeper exercising the bucket. v0.3/v0.4's
1432
+ * frame-based path is retired entirely (CLAUDE.md "Decided by the owner").
1433
+ */
1434
+
1435
+ /** Options for {@link verify}. */
1436
+ interface VerifyOptions {
1437
+ /** Restricts mandate-signature verification to these Authority Server
1438
+ * DIDs — protocol.md → *Ticket Verification* step 1 applies identically
1439
+ * to mandates: "a verifier MUST reject a [...] whose issuer it does not
1440
+ * trust." Omitted → any issuer that resolves a valid did:key is accepted
1441
+ * (appropriate for a Gatekeeper that has not yet pinned an AS). */
1442
+ trustedIssuers?: readonly string[];
1443
+ now?: number;
1444
+ }
1445
+ /**
1446
+ * Verify an execution request against the mandates supplied.
1447
+ *
1448
+ * @param request bounds, mandate blobs, execution values, and optional scope
1449
+ */
1450
+ declare function verify(request: GatekeeperRequest, opts?: VerifyOptions): Promise<GatekeeperResult>;
1451
+ /**
1452
+ * Which action types' executions count toward this cumulative bound's
1453
+ * running total — `undefined` means all of them. Display-only now that
1454
+ * local cumulative enforcement is removed (protocol.md → *Enforcement
1455
+ * Authority*: cumulative bounds are AS-only). Exported so a gateway's own
1456
+ * usage display partitions totals the same way the Authority Server does.
1457
+ */
1458
+ declare function boundActionTypes(fieldName: string, fieldDef: ProfileBoundsField): readonly string[] | undefined;
1459
+
1460
+ /**
1461
+ * Profile Registry — dynamically populated from git-hosted profile sources.
1462
+ */
1463
+
1464
+ declare function registerProfile(profileId: string, profile: AgentProfile): void;
1465
+ declare function getProfile(profileId: string): AgentProfile | undefined;
1466
+ declare function listProfiles(): string[];
1467
+ declare function getAllProfiles(): AgentProfile[];
1468
+ declare function clearProfiles(): void;
1469
+
1470
+ /**
1471
+ * did:key — encode/decode for KEY-BEARING DIDs (HAP v0.6).
1472
+ *
1473
+ * A real `did:key` is self-certifying: the public key IS the identifier, so
1474
+ * substituting the key produces a DIFFERENT DID and no key directory is ever
1475
+ * consulted. That property is what the Owner Mandate design stands on
1476
+ * (protocol.md → "Identity DIDs vs signing DIDs"): a signing DID MUST be
1477
+ * key-bearing, and verification uses the key carried in the identifier —
1478
+ * deliberately, there is no `public_key` field anywhere on the wire.
1479
+ *
1480
+ * Format (W3C did:key method, Ed25519):
1481
+ * did:key:z<base58btc( 0xed 0x01 ‖ 32-byte-public-key )>
1482
+ * `z` is the multibase prefix for base58btc; `0xed 0x01` is the multicodec
1483
+ * varint for ed25519-pub. The result always starts `did:key:z6Mk`.
1484
+ *
1485
+ * Scope: Ed25519 only — the one signing curve this protocol version uses.
1486
+ * Anything else (including the reference implementation's legacy decorative
1487
+ * `did:key:<uuid-fragment>` identifiers) decodes as NOT key-bearing.
1488
+ */
1489
+ /** Encode a 32-byte Ed25519 public key as a key-bearing `did:key:z6Mk…`. */
1490
+ declare function encodeDidKey(publicKey: Uint8Array): string;
1491
+ /**
1492
+ * Decode a key-bearing `did:key` to its Ed25519 public key bytes.
1493
+ *
1494
+ * @throws Error prefixed `NOT_KEY_BEARING:` for anything that is not a valid
1495
+ * base58btc-multibase Ed25519 did:key — including the legacy decorative
1496
+ * `did:key:<uuid-fragment>` identifiers, other multibase prefixes, and other
1497
+ * key types. The error name is the point: under the mandate design, a
1498
+ * non-key-bearing signing DID must fail STRUCTURALLY, never fall back.
1499
+ */
1500
+ declare function decodeDidKey(did: string): Uint8Array;
1501
+ /** True iff the DID decodes as a key-bearing Ed25519 did:key. Never throws. */
1502
+ declare function isKeyBearingDid(did: string): boolean;
1458
1503
 
1459
- export { type AgentBoundsParams, type AgentContextParams, type AgentFrameParams, type AgentProfile, type ApprovalObject, type Attestation, type AttestationHeader, type AttestationPayload, type BoundType, CanonicalValueError, type ContentBinding, ContentBindingError, type ContentBindingErrorCode, type CumulativeFieldDef, type CumulativeWindow, type DeclaredFieldDef, type ExecutionContextFieldDef, type ExecutionLogEntry, type ExecutionLogQuery, type ExecutionMappingTransform, type ExecutionMappingValue, type ExecutionPath, type FieldConstraint, type FieldUnit, type GateQuestion, type GatekeeperError, type GatekeeperRequest, type GatekeeperResult, type MandateBinding, MandateError, type MandateProjection, type OwnerMandate, type ProfileBoundsField, type ProfileContextField, type ProfileFrameField, type ProfileToolGating, type ProfileToolGatingEntry, type ReceiptPayload, type ResolvedDomain, SIGNABLE_COMMITMENT_MODES, type SignableCommitmentMode, type SigningSurface, type Subject, type SubjectValidation, allowedCommitmentModes, approvalSigningBytes, attestationId, bindingAppliesTo, boundActionTypes, buildMandateProjection, canonicalBounds, canonicalContext, canonicalFrame, canonicalize, canonicalizeText, checkAttestationExpiry, clearProfiles, computeBoundsHash, computeContentHash, computeContextHash, computeFieldsContentHash, computeFrameHash, computeIntentDisclosureHash, computeIntentHash, contentCanonicalBytes, decodeAttestationBlob, decodeDidKey, deriveIdentityLine, encodeAttestationBlob, encodeDidKey, frameHash, getAllProfiles, getProfile, intentDisclosureCanonicalBytes, isCommitmentModeAllowed, isFieldBinding, isKeyBearingDid, isV4Attestation, listProfiles, mandateSigningBytes, registerProfile, selectBoundFields, signApproval, signMandateProjection, validateBoundsParams, validateBoundsRequiredFor, validateCommitmentModes, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
1504
+ export { type AgentBoundsParams, type AgentProfile, type AgentScopeParams, type ApprovalObject, type BoundType, CanonicalValueError, type ContentBinding, ContentBindingError, type ContentBindingErrorCode, type ContentFieldKind, type CumulativeFieldDef, type CumulativeWindow, type DeclaredFieldDef, type ExecutionContextFieldDef, type ExecutionLogEntry, type ExecutionLogQuery, type FieldConstraint, type FieldUnit, type GatekeeperError, type GatekeeperRequest, type GatekeeperResult, HapError, type HapErrorCode, MANDATE_ERROR_CODES, type Mandate, type MandateHeader, type MandateOwnerEntry, type MandatePayload, type MandateProjection, type OwnerSignatureBinding, OwnerSignatureError, PROTOCOL_VERSION, type ProfileBoundsField, type ProfileOwnerSignatureFloor, type ProfileScopeField, type ProfileValidationError, SIGNABLE_COMMITMENT_MODES, SUPPORTED_VERSIONS, type SignableCommitmentMode, type SigningSurface, type Subject, type SubjectValidation, TICKET_ERROR_CODES, type TicketPayload, type VerifyOptions, allowedCommitmentModes, approvalSigningBytes, bindingAppliesTo, boundActionTypes, buildMandateProjection, canonicalBounds, canonicalScope, canonicalize, canonicalizeText, checkDiscloseSubset, checkMandateExpiry, checkOwnerSignatureRequirement, clearProfiles, computeBoundsHash, computeContentHash, computeFieldsContentHash, computeIntentDisclosureHash, computeIntentHash, computeProfileHash, computeScopeHash, contentCanonicalBytes, decodeDidKey, decodeMandateBlob, deriveIdentityLine, encodeDidKey, encodeMandateBlob, filesFields, fromBase64Url, getAllProfiles, getProfile, intentDisclosureCanonicalBytes, invalidFieldKindsReason, isCommitmentModeAllowed, isFieldBinding, isKeyBearingDid, listProfiles, mandateBlobId, negotiateVersion, projectionSigningBytes, publicTicketView, registerProfile, selectBoundFields, signApproval, signMandate, signMandateProjection, signTicket, toBase64Url, validateBoundsParams, validateMandateOwners, validateProfile, validateScopeParams, validateSubject, verify, verifyApproval, verifyMandate, verifyMandateSignature, verifyOwnerSignature, verifyOwnerSignatures, verifyTicketSignature };