@atrib/verify 0.1.2 → 0.2.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/README.md CHANGED
@@ -73,7 +73,7 @@ This method operates on `RecommendationDocument` shapes (settlement-recommendati
73
73
 
74
74
  ### `verifyRecord(record, options): Promise<RecordVerificationResult>`
75
75
 
76
- Per-record verification. Verifies a single signed record's Ed25519 signature and surfaces per-record annotations defined by spec sections [§1.2.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#125-informed_by) ([D041](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d041-informed_by-linking-primitive-and-informed_by-edge-type)), [§1.2.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#126-provenance_token) ([D044](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d044-provenance_token-field-for-cross-session-causal-anchoring)), and [§8.4](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#84-coarsened-timing-posture) ([D045](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d045-privacy-postures-normative-spec-section)).
76
+ Per-record verification. Verifies a single signed record's Ed25519 signature and surfaces per-record annotations defined by spec sections [§1.2.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#125-informed_by) ([D041](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d041-informed_by-linking-primitive-and-informed_by-edge-type)), [§1.2.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#126-provenance_token) ([D044](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d044-provenance_token-field-for-cross-session-causal-anchoring)), [§6.7](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#67-capability-declarations) ([D051](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d051-capability-scoped-records-via-directory-published-envelopes)), and [§8.4](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#84-coarsened-timing-posture) ([D045](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d045-privacy-postures-normative-spec-section)).
77
77
 
78
78
  ```typescript
79
79
  import { verifyRecord } from '@atrib/verify'
@@ -81,6 +81,7 @@ import { verifyRecord } from '@atrib/verify'
81
81
  const result = await verifyRecord(record, {
82
82
  upstreamCandidate, // optional, for provenance_token resolution
83
83
  informedByCandidates: [], // optional, for informed_by[] resolution
84
+ identityClaim, // optional, for capability_check (caller does directory lookup)
84
85
  })
85
86
  // result: {
86
87
  // valid: boolean
@@ -88,6 +89,7 @@ const result = await verifyRecord(record, {
88
89
  // posture: { timestamp_granularity, timestamp_consistent, timestamp_granularity_explicit }
89
90
  // provenance?: { token, upstream_record_hash, upstream_resolved }
90
91
  // informed_by_resolution?: { resolved: string[], dangling: string[] }
92
+ // capability_check?: { envelope, in_envelope, mismatches, unresolvable }
91
93
  // warnings: string[]
92
94
  // }
93
95
  ```
@@ -96,14 +98,14 @@ const result = await verifyRecord(record, {
96
98
 
97
99
  - `provenance`: `{ token, upstream_record_hash, upstream_resolved }` per session-genesis record carrying `provenance_token` ([D044](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d044-provenance_token-field-for-cross-session-causal-anchoring) / [§1.2.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#126-provenance_token)). The 16-byte token truncation is irreversible: `upstream_record_hash` populates only when the caller supplies a candidate whose canonical-form SHA-256[:16] matches the token.
98
100
  - `informed_by_resolution`: `{ resolved: string[], dangling: string[] }` per record carrying `informed_by` ([D041](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d041-informed_by-linking-primitive-and-informed_by-edge-type) / [§1.2.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#125-informed_by)). Dangling references are flagged but do not fail verification: they signal "the verifier has not seen upstream context," not "the record is invalid."
99
- - `posture`: `{ timestamp_granularity, timestamp_consistent, timestamp_granularity_explicit }` ([D045](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d045-privacy-postures-normative-spec-section) / [§8.4](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#84-coarsened-timing-posture)). Always populated. Surfaces the declared timing granularity, whether the timestamp value structurally matches the spec's trailing-zero invariant for that granularity, and whether the field was explicitly set vs defaulted from absence.
101
+ - `posture`: `{ timestamp_granularity, timestamp_consistent, timestamp_granularity_explicit, args_commitment_form, result_commitment_form, tool_name_form }` ([D045](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d045-privacy-postures-normative-spec-section) / [D061](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d061-add-tool_name-args_hash-result_hash-fields-to-§121) / [§8.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#82-opaque-name-posture) / [§8.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#83-salted-commitment-posture) / [§8.4](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#84-coarsened-timing-posture)). Always populated. Surfaces (a) the declared timing granularity, whether the timestamp value structurally matches the spec's trailing-zero invariant, and whether the field was explicitly set vs defaulted; (b) the structurally-detected `args_hash` / `result_hash` commitment scheme: `'salted-sha256'` when `args_salt` / `result_salt` is present, `'plain-sha256'` otherwise (the `'hmac-sha256'` variant from §8.3 is signaled out-of-band and is not structurally detectable); and (c) the §8.2 `tool_name_form`: `'hashed'` when `tool_name` matches `^sha256:[0-9a-f]{64}$`, `'plain'` for any other present value, `null` when the field is absent. Per D061 the §8.2 verbatim-vs-opaque distinction is NOT structurally detectable — both surface as `'plain'`.
102
+ - `capability_check`: `{ envelope, in_envelope, mismatches, unresolvable }` ([D051](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d051-capability-scoped-records-via-directory-published-envelopes) / [§6.7](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#67-capability-declarations)). Populated only when the caller passes a resolved `identityClaim` in options. Checks the record's `event_type` against the envelope's `event_types` allowlist and the record's `timestamp` against `expires_at`. `tool_names` (against tool_call records), `max_amount`, and `counterparties` (against transaction records) flag `unresolvable: true` because the constraints depend on data not yet on the standard record shape (`tool_name`) or out-of-band protocol events (payment amount + counterparty). Per [§6.7.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#673-out-of-envelope-records) out-of-envelope is a signal, not invalidation: mismatches do not flip `valid` to false. The caller is responsible for fetching the active envelope at the record's timestamp via `@atrib/directory`'s `lookup()` (or a cached equivalent); `@atrib/verify` intentionally has no `@atrib/directory` dependency.
103
+ - `cross_attestation`: `{ signers_count, signers_valid, missing }` ([D052](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d052-cross-attestation-requirement-for-transaction-records) / [§1.7.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#176-cross-attestation-requirement-for-transaction-records)). Populated only on transaction records (`event_type = transaction`). Each entry in `signers[]` is verified against the cross-attestation canonical bytes (JCS form with `signers: []` and the top-level `signature` field omitted, per §1.7.6). `missing: true` when fewer than 2 signers verify — atrib's normative minimum. Per §1.7.6 missing is a SIGNAL not invalidation: `valid` stays true if the underlying signature path holds. Legacy single-signer transaction records (no `signers[]` array, only top-level `signature`) surface as `signers_count: 0, missing: true` so consumers can flag them while accepting the cryptographic validity.
100
104
 
101
105
  **Pending per-record annotations** (tracked as a Pending decision in [DECISIONS.md P005](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#p005-reconcile-atribverify-readme-per-record-annotations-with-actual-code-surface)):
102
106
 
103
- - `capability_check` ([D051](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d051-capability-scoped-records-via-directory-published-envelopes) / [§6.7](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#67-capability-declarations)): requires `@atrib/directory` integration to look up the signing key's capability envelope.
104
- - `cross_attestation` ([D052](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d052-cross-attestation-requirement-for-transaction-records) / [§1.7.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#176-cross-attestation-requirement-for-transaction-records)): requires a `signers[]` field on `AtribRecord` plus a transaction-record canonicalization variant in `@atrib/mcp`.
105
107
  - `cross_log_proof_count` / `cross_log_threshold_met` / `cross_log_equivocation_detected` ([D050](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d050-cross-log-replication-for-equivocation-defense) / [§2.11](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#211-cross-log-replication)): requires multi-log proof-bundle parsing and trusted-log-set config.
106
- - `tool_name_form` / `args_commitment_form` ([§8.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#82-opaque-name-posture) / [§8.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#83-salted-commitment-posture)): requires `tool_name`, `args_hash`, and `args_salt` fields on `AtribRecord` (the standard record shape currently exposes only the derived `content_id`).
108
+ (Note: `tool_name_form`, `args_commitment_form`, and `result_commitment_form` per §8.2/§8.3 are all now implemented under `posture` above. D061 added `tool_name`, `args_hash`, and `result_hash` to the §1.2.1 canonical record schema, completing the structural inputs.)
107
109
 
108
110
  Each pending annotation is its own ADR scope when external consumers need it.
109
111
 
@@ -9,13 +9,19 @@
9
9
  * Implemented annotations (this file):
10
10
  * - provenance: { token, upstream_record_hash, upstream_resolved } (D044 / §1.2.6)
11
11
  * - informed_by_resolution: { resolved: string[], dangling: string[] } (D041 / §1.2.5, §3.2.4)
12
- * - posture: { timestamp_granularity, timestamp_consistent } (D045 / §8.4)
12
+ * - posture: { timestamp_granularity, timestamp_consistent, ...} (D045 / §8.2 / §8.3 / §8.4)
13
+ * - capability_check: { envelope, in_envelope, mismatches, unresolvable } (D051 / §6.7)
13
14
  *
14
15
  * Pending annotations (tracked in DECISIONS.md P005):
15
- * - capability_check: D051 / §6.7 (needs @atrib/directory integration)
16
16
  * - cross_attestation: D052 / §1.7.6 (needs `signers[]` type addition + transaction-record signing variant in @atrib/mcp)
17
17
  * - cross_log_*: D050 / §2.11 (needs multi-log proof-bundle infrastructure)
18
- * - tool_name_form / args_commitment_form: §8.2 / §8.3 (needs tool_name + args_hash fields on the record shape — currently only content_id is exposed)
18
+ *
19
+ * Design note on dependencies. The capability_check annotation does NOT
20
+ * fetch the identity claim itself; the caller does the @atrib/directory
21
+ * lookup and passes the resolved claim into VerifyRecordOptions. This
22
+ * keeps @atrib/verify lean (no WASM-bridge dep) and lets the caller
23
+ * decide lookup strategy (cached vs live, batch vs per-record). Same
24
+ * pattern as `upstreamCandidate` and `informedByCandidates`.
19
25
  */
20
26
  import { base64urlDecode, type AtribRecord } from '@atrib/mcp';
21
27
  /**
@@ -48,18 +54,108 @@ export interface InformedByAnnotation {
48
54
  dangling: string[];
49
55
  }
50
56
  /**
51
- * Posture surfacing for a record. Currently exposes only the timing
52
- * posture (§8.4); tool_name_form (§8.2) and args_commitment_form (§8.3)
53
- * require fields that aren't on the current AtribRecord shape.
57
+ * Capability-envelope shape from spec §6.7.1. All sub-fields are optional;
58
+ * a claim with an empty envelope (`{}`) declares no scope. The verifier
59
+ * reads this off the resolved IdentityClaim's `capabilities` field.
60
+ */
61
+ export interface CapabilityEnvelope {
62
+ tool_names?: string[];
63
+ event_types?: string[];
64
+ max_amount?: {
65
+ currency: string;
66
+ value: number;
67
+ };
68
+ counterparties?: string[];
69
+ expires_at?: number;
70
+ }
71
+ /**
72
+ * Capability-check surfacing for a record whose signer published an
73
+ * IdentityClaim with a `capabilities` field (D051 / spec §6.7).
74
+ *
75
+ * Per §6.7.3: out-of-envelope is a SIGNAL, not invalidation. Records
76
+ * outside the envelope remain cryptographically valid; the signature
77
+ * verifies, log inclusion verifies. Consumers decide policy.
78
+ */
79
+ export interface CapabilityCheckAnnotation {
80
+ /** The active envelope at the record's timestamp, or null if none. */
81
+ envelope: CapabilityEnvelope | null;
82
+ /**
83
+ * True iff every present envelope field accommodates the record. False
84
+ * when any present constraint excludes the record's content. True when
85
+ * envelope is null (no constraint = trivially in-envelope).
86
+ */
87
+ in_envelope: boolean;
88
+ /**
89
+ * Specific constraints the record violates, listed for debugging.
90
+ * Each entry is a short string like 'event_type not in allowlist' or
91
+ * 'expires_at exceeded'. Empty when in_envelope is true.
92
+ */
93
+ mismatches: string[];
94
+ /**
95
+ * True iff one or more checks could not be resolved out-of-band
96
+ * (e.g., a transaction record's amount + counterparty are not
97
+ * derivable without the protocol-specific payment event). Per §6.7.2
98
+ * the verifier MUST flag this rather than passing or failing silently.
99
+ */
100
+ unresolvable: boolean;
101
+ }
102
+ /**
103
+ * Cross-attestation surfacing for a transaction record per spec §1.7.6
104
+ * (D052). atrib's normative minimum is two verified signers per
105
+ * transaction record (typically agent + counterparty). Records below
106
+ * the minimum get `missing: true`; verifiers MUST flag this rather
107
+ * than silently passing or failing.
108
+ *
109
+ * The annotation populates ONLY for records with
110
+ * `event_type = https://atrib.dev/v1/types/transaction`. Other event
111
+ * types continue to use the standard single-signer signature path.
112
+ */
113
+ export interface CrossAttestationAnnotation {
114
+ /**
115
+ * Total signers attached to the record (regardless of validity).
116
+ * `0` for legacy single-signer transaction records that carry only the
117
+ * top-level `signature` field instead of the `signers[]` array.
118
+ */
119
+ signers_count: number;
120
+ /**
121
+ * Number of signers whose Ed25519 signature successfully verifies
122
+ * against the cross-attestation canonical bytes (JCS form with
123
+ * `signers: []` and `signature` omitted, per §1.7.6).
124
+ */
125
+ signers_valid: number;
126
+ /**
127
+ * `true` iff `signers_valid < 2` (atrib's normative minimum). Per
128
+ * §1.7.6 verifiers MUST flag this; consumers decide whether to accept
129
+ * the record. Like §6.7's `in_envelope: false`, this is a SIGNAL not
130
+ * an invalidation: the underlying record may still be cryptographically
131
+ * valid via the legacy top-level signature.
132
+ */
133
+ missing: boolean;
134
+ }
135
+ /**
136
+ * Posture surfacing for a record. Exposes three §8 postures: timing
137
+ * (§8.4), args/result commitment (§8.3), and tool-name disclosure (§8.2).
54
138
  *
55
139
  * `timestamp_granularity` is the declared coarsening level (or 'ms' by
56
140
  * default when absent). `timestamp_consistent` is true iff the timestamp
57
141
  * value matches the granularity's trailing-zero invariant per spec §8.4
58
- * (e.g., 'min' requires `timestamp % 60000 == 0`). A consistent posture
59
- * means the record's coarsening claim is structurally honest; an
60
- * inconsistent posture means the implementation declared a granularity
61
- * that the timestamp doesn't satisfy, which validators and verifiers
62
- * MUST reject per §8.4.
142
+ * (e.g., 'min' requires `timestamp % 60000 == 0`).
143
+ *
144
+ * `args_commitment_form` and `result_commitment_form` are detected
145
+ * structurally per spec §8.3. Presence of `args_salt` indicates the
146
+ * salted-sha256 scheme; absence indicates the default plain-sha256
147
+ * scheme. The hmac-sha256 variant is structurally indistinguishable to
148
+ * non-key-holders (the issuer signals it out-of-band per §8.3, not via
149
+ * record fields), so we surface only the two structurally-detectable
150
+ * forms.
151
+ *
152
+ * `tool_name_form` is the §8.2 / D061 form of the optional `tool_name`
153
+ * field. The §8.2 verbatim-vs-opaque distinction is NOT structurally
154
+ * detectable (`book_flight` matches the opaque regex), so per D061 we
155
+ * surface only `'hashed' | 'plain' | null`: hashed when the value
156
+ * matches `^sha256:[0-9a-f]{64}$`, plain for any other present value,
157
+ * null when the field is absent. Consumers wanting verbatim-vs-opaque
158
+ * MUST use out-of-band metadata (e.g., a name registry).
63
159
  */
64
160
  export interface PostureAnnotation {
65
161
  timestamp_granularity: 'ms' | 's' | 'min' | 'h' | 'd';
@@ -74,6 +170,25 @@ export interface PostureAnnotation {
74
170
  * Surfaced separately because absence affects JCS canonical form per §1.3.
75
171
  */
76
172
  timestamp_granularity_explicit: boolean;
173
+ /**
174
+ * Detected commitment scheme for `args_hash`. 'salted-sha256' iff
175
+ * `args_salt` is present on the record; 'plain-sha256' otherwise. The
176
+ * 'hmac-sha256' variant from §8.3 is not structurally detectable.
177
+ */
178
+ args_commitment_form: 'plain-sha256' | 'salted-sha256';
179
+ /**
180
+ * Detected commitment scheme for `result_hash`. Same semantics as
181
+ * `args_commitment_form` but driven by `result_salt`.
182
+ */
183
+ result_commitment_form: 'plain-sha256' | 'salted-sha256';
184
+ /**
185
+ * Detected form of the optional `tool_name` field per §8.2 / D061:
186
+ * - 'hashed' when value matches `^sha256:[0-9a-f]{64}$` (unambiguous)
187
+ * - 'plain' for any other present value (verbatim and opaque-label
188
+ * forms are not structurally distinguishable; both surface as plain)
189
+ * - null when the field is absent (the §8.1 default posture)
190
+ */
191
+ tool_name_form: 'hashed' | 'plain' | null;
77
192
  }
78
193
  export interface RecordVerificationResult {
79
194
  /** True iff signatureOk AND no fatal warnings. */
@@ -103,8 +218,34 @@ export interface RecordVerificationResult {
103
218
  * granularity and whether the timestamp value structurally matches it.
104
219
  */
105
220
  posture: PostureAnnotation;
221
+ /**
222
+ * Capability-check annotation. Populated only when the caller passes
223
+ * an `identityClaim` in options. When the claim has no `capabilities`
224
+ * field (or an empty envelope), in_envelope is true and mismatches is
225
+ * empty (no constraint = trivially in-envelope per §6.7.1).
226
+ */
227
+ capability_check?: CapabilityCheckAnnotation;
228
+ /**
229
+ * Cross-attestation annotation per §1.7.6 (D052). Populated ONLY for
230
+ * transaction records (`event_type = https://atrib.dev/v1/types/transaction`).
231
+ * Surfaces signers_count, signers_valid, and missing (true when fewer
232
+ * than 2 signers verified). Per §1.7.6 verifiers MUST flag missing
233
+ * cross-attestation; consumers decide policy.
234
+ */
235
+ cross_attestation?: CrossAttestationAnnotation;
106
236
  warnings: string[];
107
237
  }
238
+ /**
239
+ * Resolved identity claim for capability-check input. This is the SHAPE
240
+ * @atrib/verify needs from a directory lookup, NOT the @atrib/directory
241
+ * type itself (avoids a hard package dep). Callers pass either:
242
+ * - the @atrib/directory `IdentityClaim` (structurally compatible), or
243
+ * - a hand-constructed object with this shape (e.g., from a cache)
244
+ */
245
+ export interface ResolvedIdentityClaim {
246
+ creator_key: string;
247
+ capabilities?: CapabilityEnvelope;
248
+ }
108
249
  export interface VerifyRecordOptions {
109
250
  /**
110
251
  * Candidate upstream record for provenance_token resolution. If
@@ -123,6 +264,19 @@ export interface VerifyRecordOptions {
123
264
  * not invalidating.
124
265
  */
125
266
  informedByCandidates?: AtribRecord[];
267
+ /**
268
+ * Resolved identity claim for the record's `creator_key`, used for
269
+ * capability_check (D051 / §6.7). When supplied, verifyRecord populates
270
+ * `capability_check` on the result. The claim should be the active
271
+ * envelope at the record's timestamp per §6.7.2 step 1; the caller
272
+ * is responsible for picking the right historical version when the
273
+ * envelope has rotated. When omitted, capability_check is not surfaced.
274
+ *
275
+ * Caller is responsible for fetching this via @atrib/directory's
276
+ * lookup() or a cached equivalent. @atrib/verify intentionally does
277
+ * NOT depend on @atrib/directory.
278
+ */
279
+ identityClaim?: ResolvedIdentityClaim;
126
280
  }
127
281
  /**
128
282
  * Verify one signed record.
@@ -135,6 +289,41 @@ export interface VerifyRecordOptions {
135
289
  export declare function verifyRecord(record: AtribRecord, options?: VerifyRecordOptions): Promise<RecordVerificationResult>;
136
290
  declare function resolveProvenance(token: string, upstreamCandidate: AtribRecord | undefined): ProvenanceAnnotation;
137
291
  declare function resolveInformedBy(entries: string[], candidates: AtribRecord[], warnings: string[]): InformedByAnnotation;
292
+ /**
293
+ * Capability-check derivation per spec §6.7.2.
294
+ *
295
+ * The signer's claim may declare a capability envelope. We check the
296
+ * record against each present sub-field of the envelope and report any
297
+ * mismatches. The caller is responsible for supplying the ACTIVE envelope
298
+ * at the record's timestamp (i.e., picking the right historical version
299
+ * when capabilities have rotated per §6.7.4).
300
+ *
301
+ * Per §6.7.3 mismatches are SIGNALS, not invalidation. We don't push
302
+ * mismatches into `warnings` (which would set `valid: false`); they go
303
+ * into the structured `mismatches[]` field for consumer policy to weigh.
304
+ *
305
+ * For transaction records with `max_amount` or `counterparties`
306
+ * constraints, we set `unresolvable: true`. The protocol-specific
307
+ * transaction event isn't accessible to @atrib/verify; the caller would
308
+ * need to provide the resolved amount + counterparty out-of-band, which
309
+ * is a future-API extension if a real consumer needs it.
310
+ */
311
+ declare function resolveCapabilityCheck(record: AtribRecord, claim: ResolvedIdentityClaim, _warnings: string[]): CapabilityCheckAnnotation;
312
+ /**
313
+ * Cross-attestation derivation per spec §1.7.6 (D052).
314
+ *
315
+ * For each entry in `record.signers`, verify the Ed25519 signature
316
+ * against the cross-attestation canonical bytes (JCS form with
317
+ * `signers: []` and the top-level `signature` field omitted). Count
318
+ * valid signatures; flag `missing: true` when fewer than 2 verify.
319
+ *
320
+ * Per §1.7.6 mismatches are SIGNALS, not invalidation: missing
321
+ * cross-attestation does NOT push to `warnings[]` (which would flip
322
+ * `valid` to false). The legacy top-level `signature` (already
323
+ * verified above by `verifyRecordSignature`) keeps the record
324
+ * cryptographically valid; cross_attestation is a policy signal.
325
+ */
326
+ declare function resolveCrossAttestation(record: AtribRecord): Promise<CrossAttestationAnnotation>;
138
327
  declare function detectPosture(record: AtribRecord, warnings: string[]): PostureAnnotation;
139
328
  export declare const __test_only__: {
140
329
  PROVENANCE_TOKEN_PATTERN: RegExp;
@@ -142,6 +331,8 @@ export declare const __test_only__: {
142
331
  GRANULARITY_MULTIPLIER: Record<"s" | "ms" | "min" | "h" | "d", number>;
143
332
  resolveProvenance: typeof resolveProvenance;
144
333
  resolveInformedBy: typeof resolveInformedBy;
334
+ resolveCapabilityCheck: typeof resolveCapabilityCheck;
335
+ resolveCrossAttestation: typeof resolveCrossAttestation;
145
336
  detectPosture: typeof detectPosture;
146
337
  base64urlDecode: typeof base64urlDecode;
147
338
  };
@@ -1 +1 @@
1
- {"version":3,"file":"verify-record.d.ts","sourceRoot":"","sources":["../src/verify-record.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACL,eAAe,EAMf,KAAK,WAAW,EACjB,MAAM,YAAY,CAAA;AAKnB;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC;;;OAGG;IACH,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,EAAE,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,CAAA;IACrD;;;OAGG;IACH,oBAAoB,EAAE,OAAO,CAAA;IAC7B;;;;OAIG;IACH,8BAA8B,EAAE,OAAO,CAAA;CACxC;AAUD,MAAM,WAAW,wBAAwB;IACvC,kDAAkD;IAClD,KAAK,EAAE,OAAO,CAAA;IACd,iEAAiE;IACjE,WAAW,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,oBAAoB,CAAA;IACjC;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,oBAAoB,CAAA;IAC7C;;;;OAIG;IACH,OAAO,EAAE,iBAAiB,CAAA;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,WAAW,CAAA;IAC/B;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,WAAW,EAAE,CAAA;CACrC;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,wBAAwB,CAAC,CAyCnC;AAED,iBAAS,iBAAiB,CACxB,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,WAAW,GAAG,SAAS,GACzC,oBAAoB,CAetB;AAED,iBAAS,iBAAiB,CACxB,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,WAAW,EAAE,EACzB,QAAQ,EAAE,MAAM,EAAE,GACjB,oBAAoB,CAuBtB;AAED,iBAAS,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAmBjF;AAID,eAAO,MAAM,aAAa;;;;;;;;CAQzB,CAAA"}
1
+ {"version":3,"file":"verify-record.d.ts","sourceRoot":"","sources":["../src/verify-record.ts"],"names":[],"mappings":"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"}
@@ -10,17 +10,29 @@
10
10
  * Implemented annotations (this file):
11
11
  * - provenance: { token, upstream_record_hash, upstream_resolved } (D044 / §1.2.6)
12
12
  * - informed_by_resolution: { resolved: string[], dangling: string[] } (D041 / §1.2.5, §3.2.4)
13
- * - posture: { timestamp_granularity, timestamp_consistent } (D045 / §8.4)
13
+ * - posture: { timestamp_granularity, timestamp_consistent, ...} (D045 / §8.2 / §8.3 / §8.4)
14
+ * - capability_check: { envelope, in_envelope, mismatches, unresolvable } (D051 / §6.7)
14
15
  *
15
16
  * Pending annotations (tracked in DECISIONS.md P005):
16
- * - capability_check: D051 / §6.7 (needs @atrib/directory integration)
17
17
  * - cross_attestation: D052 / §1.7.6 (needs `signers[]` type addition + transaction-record signing variant in @atrib/mcp)
18
18
  * - cross_log_*: D050 / §2.11 (needs multi-log proof-bundle infrastructure)
19
- * - tool_name_form / args_commitment_form: §8.2 / §8.3 (needs tool_name + args_hash fields on the record shape — currently only content_id is exposed)
19
+ *
20
+ * Design note on dependencies. The capability_check annotation does NOT
21
+ * fetch the identity claim itself; the caller does the @atrib/directory
22
+ * lookup and passes the resolved claim into VerifyRecordOptions. This
23
+ * keeps @atrib/verify lean (no WASM-bridge dep) and lets the caller
24
+ * decide lookup strategy (cached vs live, batch vs per-record). Same
25
+ * pattern as `upstreamCandidate` and `informedByCandidates`.
20
26
  */
21
- import { base64urlDecode, base64urlEncode, canonicalRecord, hexEncode, sha256, verifyRecord as verifyRecordSignature, } from '@atrib/mcp';
27
+ import { base64urlDecode, base64urlEncode, canonicalCrossAttestationInput, canonicalRecord, hexEncode, sha256, verifyRecord as verifyRecordSignature, } from '@atrib/mcp';
28
+ import * as ed from '@noble/ed25519';
22
29
  const PROVENANCE_TOKEN_PATTERN = /^[A-Za-z0-9_-]{22}$/;
23
30
  const SHA256_REF_PATTERN = /^sha256:[0-9a-f]{64}$/;
31
+ // §8.2 hashed tool_name form per D061. The verbatim and opaque-label forms
32
+ // are NOT structurally distinguishable (the spec's verbatim example
33
+ // `book_flight` also matches the opaque regex), so this is the only
34
+ // regex-detectable form.
35
+ const TOOL_NAME_HASHED_PATTERN = /^sha256:[0-9a-f]{64}$/;
24
36
  const GRANULARITY_MULTIPLIER = {
25
37
  ms: 1,
26
38
  s: 1000,
@@ -38,14 +50,31 @@ const GRANULARITY_MULTIPLIER = {
38
50
  */
39
51
  export async function verifyRecord(record, options = {}) {
40
52
  const warnings = [];
53
+ // §1.2.1 + §1.7.6: the top-level `signature` field is OPTIONAL on
54
+ // transaction records that carry the `signers[]` array. Skip the
55
+ // legacy single-sig check when (a) the record is a transaction AND
56
+ // (b) signers[] is present and non-empty. The cross_attestation
57
+ // annotation below covers signature verification per signer.
58
+ const isTransaction = record.event_type === 'https://atrib.dev/v1/types/transaction';
59
+ const hasSignersArray = Array.isArray(record.signers) && record.signers.length > 0;
60
+ const skipLegacySignatureCheck = isTransaction && hasSignersArray;
41
61
  let signatureOk = false;
42
- try {
43
- signatureOk = await verifyRecordSignature(record);
44
- if (!signatureOk)
45
- warnings.push('signature verification failed');
62
+ if (skipLegacySignatureCheck) {
63
+ // §1.7.6: signature validity for transaction records lives in
64
+ // cross_attestation, not signatureOk. We treat signatureOk as true
65
+ // here so consumers' valid-bit logic isn't broken; the actual
66
+ // multi-sig validity is exposed via cross_attestation.signers_valid.
67
+ signatureOk = true;
46
68
  }
47
- catch (err) {
48
- warnings.push(`signature verification error: ${err.message}`);
69
+ else {
70
+ try {
71
+ signatureOk = await verifyRecordSignature(record);
72
+ if (!signatureOk)
73
+ warnings.push('signature verification failed');
74
+ }
75
+ catch (err) {
76
+ warnings.push(`signature verification error: ${err.message}`);
77
+ }
49
78
  }
50
79
  const result = {
51
80
  valid: false,
@@ -67,6 +96,17 @@ export async function verifyRecord(record, options = {}) {
67
96
  if (record.informed_by && record.informed_by.length > 0) {
68
97
  result.informed_by_resolution = resolveInformedBy(record.informed_by, options.informedByCandidates ?? [], warnings);
69
98
  }
99
+ // capability_check (D051 / §6.7) — surface only when caller supplied a
100
+ // resolved identity claim. We do not look up the claim ourselves to
101
+ // avoid coupling @atrib/verify to @atrib/directory's WASM bridge.
102
+ if (options.identityClaim) {
103
+ result.capability_check = resolveCapabilityCheck(record, options.identityClaim, warnings);
104
+ }
105
+ // cross_attestation (D052 / §1.7.6) — surface only on transaction records.
106
+ // Other event types continue to use the standard single-signer path.
107
+ if (record.event_type === 'https://atrib.dev/v1/types/transaction') {
108
+ result.cross_attestation = await resolveCrossAttestation(record);
109
+ }
70
110
  result.valid = signatureOk && warnings.length === 0;
71
111
  return result;
72
112
  }
@@ -106,6 +146,128 @@ function resolveInformedBy(entries, candidates, warnings) {
106
146
  }
107
147
  return { resolved, dangling };
108
148
  }
149
+ /**
150
+ * Capability-check derivation per spec §6.7.2.
151
+ *
152
+ * The signer's claim may declare a capability envelope. We check the
153
+ * record against each present sub-field of the envelope and report any
154
+ * mismatches. The caller is responsible for supplying the ACTIVE envelope
155
+ * at the record's timestamp (i.e., picking the right historical version
156
+ * when capabilities have rotated per §6.7.4).
157
+ *
158
+ * Per §6.7.3 mismatches are SIGNALS, not invalidation. We don't push
159
+ * mismatches into `warnings` (which would set `valid: false`); they go
160
+ * into the structured `mismatches[]` field for consumer policy to weigh.
161
+ *
162
+ * For transaction records with `max_amount` or `counterparties`
163
+ * constraints, we set `unresolvable: true`. The protocol-specific
164
+ * transaction event isn't accessible to @atrib/verify; the caller would
165
+ * need to provide the resolved amount + counterparty out-of-band, which
166
+ * is a future-API extension if a real consumer needs it.
167
+ */
168
+ function resolveCapabilityCheck(record, claim, _warnings) {
169
+ const envelope = claim.capabilities ?? null;
170
+ // Empty envelope or absent capabilities field: no constraint declared.
171
+ // Per §6.7.1: "A claim with `capabilities: {}` declares no scope."
172
+ if (!envelope || Object.keys(envelope).length === 0) {
173
+ return { envelope: null, in_envelope: true, mismatches: [], unresolvable: false };
174
+ }
175
+ const mismatches = [];
176
+ let unresolvable = false;
177
+ // expires_at: envelope expired when the record's timestamp is after the cutoff.
178
+ // Per §6.7.2: expired envelope is "treated as having no constraint and flagged
179
+ // separately" — we add the mismatch but don't treat it as out-of-envelope on
180
+ // its own; other sub-fields still apply if present.
181
+ if (typeof envelope.expires_at === 'number' && record.timestamp > envelope.expires_at) {
182
+ mismatches.push(`envelope expired at ${envelope.expires_at}; record timestamp ${record.timestamp}`);
183
+ }
184
+ // event_types: the record's event_type URI must be in the allowlist.
185
+ if (Array.isArray(envelope.event_types) && envelope.event_types.length > 0) {
186
+ if (!envelope.event_types.includes(record.event_type)) {
187
+ mismatches.push(`event_type '${record.event_type}' not in allowlist`);
188
+ }
189
+ }
190
+ // tool_names: per §6.7.2 step 2, only applies to tool_call records and
191
+ // requires the record's tool_name. The current AtribRecord shape does
192
+ // not expose tool_name (per §8.2 default posture: only content_id is
193
+ // present, which is a hash of serverUrl + toolName). Without tool_name
194
+ // we can't check this constraint. Mark unresolvable.
195
+ if (Array.isArray(envelope.tool_names) && envelope.tool_names.length > 0) {
196
+ if (record.event_type === 'https://atrib.dev/v1/types/tool_call') {
197
+ unresolvable = true;
198
+ }
199
+ }
200
+ // max_amount + counterparties: per §6.7.2 the verifier "MUST resolve
201
+ // the transaction amount and counterparty from the protocol-specific
202
+ // transaction event the record commits to". @atrib/verify doesn't
203
+ // have access to the payment-protocol event; flag as unresolvable.
204
+ // Future API extension: accept resolved amount + counterparty as
205
+ // VerifyRecordOptions inputs if a real consumer needs it.
206
+ if (record.event_type === 'https://atrib.dev/v1/types/transaction') {
207
+ if (envelope.max_amount || (Array.isArray(envelope.counterparties) && envelope.counterparties.length > 0)) {
208
+ unresolvable = true;
209
+ }
210
+ }
211
+ return {
212
+ envelope,
213
+ in_envelope: mismatches.length === 0,
214
+ mismatches,
215
+ unresolvable,
216
+ };
217
+ }
218
+ /**
219
+ * Cross-attestation derivation per spec §1.7.6 (D052).
220
+ *
221
+ * For each entry in `record.signers`, verify the Ed25519 signature
222
+ * against the cross-attestation canonical bytes (JCS form with
223
+ * `signers: []` and the top-level `signature` field omitted). Count
224
+ * valid signatures; flag `missing: true` when fewer than 2 verify.
225
+ *
226
+ * Per §1.7.6 mismatches are SIGNALS, not invalidation: missing
227
+ * cross-attestation does NOT push to `warnings[]` (which would flip
228
+ * `valid` to false). The legacy top-level `signature` (already
229
+ * verified above by `verifyRecordSignature`) keeps the record
230
+ * cryptographically valid; cross_attestation is a policy signal.
231
+ */
232
+ async function resolveCrossAttestation(record) {
233
+ const signers = Array.isArray(record.signers) ? record.signers : [];
234
+ const signers_count = signers.length;
235
+ if (signers_count === 0) {
236
+ // Legacy single-signer transaction record. Per §1.7.6 normative
237
+ // minimum is 2; flag as missing.
238
+ return { signers_count: 0, signers_valid: 0, missing: true };
239
+ }
240
+ // All signers cover the same canonical bytes (§1.7.6).
241
+ let canonicalBytes;
242
+ try {
243
+ canonicalBytes = canonicalCrossAttestationInput(record);
244
+ }
245
+ catch {
246
+ // Canonicalization shouldn't fail on a structurally-valid record;
247
+ // if it does, treat all signers as unverifiable.
248
+ return { signers_count, signers_valid: 0, missing: true };
249
+ }
250
+ let signers_valid = 0;
251
+ for (const entry of signers) {
252
+ if (typeof entry?.creator_key !== 'string' || typeof entry?.signature !== 'string')
253
+ continue;
254
+ try {
255
+ const pubKey = base64urlDecode(entry.creator_key);
256
+ const sig = base64urlDecode(entry.signature);
257
+ const ok = await ed.verifyAsync(sig, canonicalBytes, pubKey);
258
+ if (ok)
259
+ signers_valid++;
260
+ }
261
+ catch {
262
+ // Malformed key/sig bytes: skip without counting.
263
+ }
264
+ }
265
+ return {
266
+ signers_count,
267
+ signers_valid,
268
+ missing: signers_valid < 2,
269
+ };
270
+ }
109
271
  function detectPosture(record, warnings) {
110
272
  const declared = record.timestamp_granularity;
111
273
  const explicit = typeof declared === 'string';
@@ -116,10 +278,26 @@ function detectPosture(record, warnings) {
116
278
  if (!consistent) {
117
279
  warnings.push(`timestamp_granularity declares '${granularity}' but timestamp ${record.timestamp} is not a multiple of ${multiplier}`);
118
280
  }
281
+ // Spec §8.3 commitment-posture detection: presence of args_salt /
282
+ // result_salt indicates the salted-sha256 scheme; absence indicates the
283
+ // default plain-sha256 scheme. The hmac-sha256 variant from §8.3 is
284
+ // signaled out-of-band and is not structurally detectable.
285
+ const args_commitment_form = typeof record.args_salt === 'string' ? 'salted-sha256' : 'plain-sha256';
286
+ const result_commitment_form = typeof record.result_salt === 'string' ? 'salted-sha256' : 'plain-sha256';
287
+ // Spec §8.2 / D061 tool_name_form: hashed when the value matches the
288
+ // `sha256:<hex>` form (unambiguous), plain otherwise (verbatim vs opaque
289
+ // not structurally distinguishable), null when the field is absent.
290
+ let tool_name_form = null;
291
+ if (typeof record.tool_name === 'string') {
292
+ tool_name_form = TOOL_NAME_HASHED_PATTERN.test(record.tool_name) ? 'hashed' : 'plain';
293
+ }
119
294
  return {
120
295
  timestamp_granularity: granularity,
121
296
  timestamp_consistent: consistent,
122
297
  timestamp_granularity_explicit: explicit,
298
+ args_commitment_form,
299
+ result_commitment_form,
300
+ tool_name_form,
123
301
  };
124
302
  }
125
303
  // Re-exported defensively so consumers that want stricter validation can
@@ -130,6 +308,8 @@ export const __test_only__ = {
130
308
  GRANULARITY_MULTIPLIER,
131
309
  resolveProvenance,
132
310
  resolveInformedBy,
311
+ resolveCapabilityCheck,
312
+ resolveCrossAttestation,
133
313
  detectPosture,
134
314
  base64urlDecode,
135
315
  };
@@ -1 +1 @@
1
- {"version":3,"file":"verify-record.js","sourceRoot":"","sources":["../src/verify-record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verify-record.js","sourceRoot":"","sources":["../src/verify-record.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,eAAe,EACf,eAAe,EACf,8BAA8B,EAC9B,eAAe,EACf,SAAS,EACT,MAAM,EACN,YAAY,IAAI,qBAAqB,GAGtC,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAEpC,MAAM,wBAAwB,GAAG,qBAAqB,CAAA;AACtD,MAAM,kBAAkB,GAAG,uBAAuB,CAAA;AAClD,2EAA2E;AAC3E,oEAAoE;AACpE,oEAAoE;AACpE,yBAAyB;AACzB,MAAM,wBAAwB,GAAG,uBAAuB,CAAA;AA2KxD,MAAM,sBAAsB,GAA+D;IACzF,EAAE,EAAE,CAAC;IACL,CAAC,EAAE,IAAI;IACP,GAAG,EAAE,MAAM;IACX,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,UAAU;CACd,CAAA;AA6FD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAmB,EACnB,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,kEAAkE;IAClE,iEAAiE;IACjE,mEAAmE;IACnE,gEAAgE;IAChE,6DAA6D;IAC7D,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,KAAK,wCAAwC,CAAA;IACpF,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;IAClF,MAAM,wBAAwB,GAAG,aAAa,IAAI,eAAe,CAAA;IAEjE,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,IAAI,wBAAwB,EAAE,CAAC;QAC7B,8DAA8D;QAC9D,mEAAmE;QACnE,8DAA8D;QAC9D,qEAAqE;QACrE,WAAW,GAAG,IAAI,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;YACjD,IAAI,CAAC,WAAW;gBAAE,QAAQ,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,iCAAkC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAA6B;QACvC,KAAK,EAAE,KAAK;QACZ,WAAW;QACX,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC;QACxC,QAAQ;KACT,CAAA;IAED,4EAA4E;IAC5E,MAAM,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAA;IAC/C,IAAI,OAAO,eAAe,KAAK,QAAQ,EAAE,CAAC;QACxC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YACpD,QAAQ,CAAC,IAAI,CACX,qEAAqE,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CACpG,CAAA;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,UAAU,GAAG,iBAAiB,CAAC,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;QACnF,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,sBAAsB,GAAG,iBAAiB,CAC/C,MAAM,CAAC,WAAW,EAClB,OAAO,CAAC,oBAAoB,IAAI,EAAE,EAClC,QAAQ,CACT,CAAA;IACH,CAAC;IAED,uEAAuE;IACvE,oEAAoE;IACpE,kEAAkE;IAClE,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,CAAC,gBAAgB,GAAG,sBAAsB,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;IAC3F,CAAC;IAED,2EAA2E;IAC3E,qEAAqE;IACrE,IAAI,MAAM,CAAC,UAAU,KAAK,wCAAwC,EAAE,CAAC;QACnE,MAAM,CAAC,iBAAiB,GAAG,MAAM,uBAAuB,CAAC,MAAM,CAAC,CAAA;IAClE,CAAC;IAED,MAAM,CAAC,KAAK,GAAG,WAAW,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA;IACnD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAa,EACb,iBAA0C;IAE1C,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAA;IACxE,CAAC;IAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACrE,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC3D,MAAM,cAAc,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAAA;IAE3D,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAA;IACxE,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,SAAS,CAAC,kBAAkB,CAAC,EAAE,CAAA;IAC1D,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAA;AAC3E,CAAC;AAED,SAAS,iBAAiB,CACxB,OAAiB,EACjB,UAAyB,EACzB,QAAkB;IAElB,qEAAqE;IACrE,sEAAsE;IACtE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAA;IACzC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,eAAe,CAAC,GAAG,CAAC,UAAU,SAAS,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACxE,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,yCAAyC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;YAC5E,SAAQ;QACV,CAAC;QACD,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;AAC/B,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,sBAAsB,CAC7B,MAAmB,EACnB,KAA4B,EAC5B,SAAmB;IAEnB,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,IAAI,IAAI,CAAA;IAC3C,uEAAuE;IACvE,mEAAmE;IACnE,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAA;IACnF,CAAC;IAED,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,IAAI,YAAY,GAAG,KAAK,CAAA;IAExB,gFAAgF;IAChF,+EAA+E;IAC/E,6EAA6E;IAC7E,oDAAoD;IACpD,IAAI,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtF,UAAU,CAAC,IAAI,CAAC,uBAAuB,QAAQ,CAAC,UAAU,sBAAsB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;IACrG,CAAC;IAED,qEAAqE;IACrE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3E,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACtD,UAAU,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,UAAU,oBAAoB,CAAC,CAAA;QACvE,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,sEAAsE;IACtE,qEAAqE;IACrE,uEAAuE;IACvE,qDAAqD;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzE,IAAI,MAAM,CAAC,UAAU,KAAK,sCAAsC,EAAE,CAAC;YACjE,YAAY,GAAG,IAAI,CAAA;QACrB,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,qEAAqE;IACrE,kEAAkE;IAClE,mEAAmE;IACnE,iEAAiE;IACjE,0DAA0D;IAC1D,IAAI,MAAM,CAAC,UAAU,KAAK,wCAAwC,EAAE,CAAC;QACnE,IAAI,QAAQ,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;YAC1G,YAAY,GAAG,IAAI,CAAA;QACrB,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ;QACR,WAAW,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC;QACpC,UAAU;QACV,YAAY;KACb,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,KAAK,UAAU,uBAAuB,CAAC,MAAmB;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IACnE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAA;IAEpC,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;QACxB,gEAAgE;QAChE,iCAAiC;QACjC,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC9D,CAAC;IAED,uDAAuD;IACvD,IAAI,cAA0B,CAAA;IAC9B,IAAI,CAAC;QACH,cAAc,GAAG,8BAA8B,CAAC,MAAM,CAAC,CAAA;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;QAClE,iDAAiD;QACjD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC3D,CAAC;IAED,IAAI,aAAa,GAAG,CAAC,CAAA;IACrB,KAAK,MAAM,KAAK,IAAI,OAAwB,EAAE,CAAC;QAC7C,IAAI,OAAO,KAAK,EAAE,WAAW,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ;YAAE,SAAQ;QAC5F,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;YACjD,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;YAC5C,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,CAAA;YAC5D,IAAI,EAAE;gBAAE,aAAa,EAAE,CAAA;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa;QACb,aAAa;QACb,OAAO,EAAE,aAAa,GAAG,CAAC;KAC3B,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,MAAmB,EAAE,QAAkB;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,qBAAqB,CAAA;IAC7C,MAAM,QAAQ,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAA;IAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAS,CAAC,CAAC,CAAE,IAAc,CAAA;IAE1D,qFAAqF;IACrF,MAAM,UAAU,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAA;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,GAAG,UAAU,KAAK,CAAC,CAAA;IACtD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CACX,mCAAmC,WAAW,mBAAmB,MAAM,CAAC,SAAS,yBAAyB,UAAU,EAAE,CACvH,CAAA;IACH,CAAC;IAED,kEAAkE;IAClE,wEAAwE;IACxE,oEAAoE;IACpE,2DAA2D;IAC3D,MAAM,oBAAoB,GAAG,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,cAAc,CAAA;IACpG,MAAM,sBAAsB,GAAG,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,cAAc,CAAA;IAExG,qEAAqE;IACrE,yEAAyE;IACzE,oEAAoE;IACpE,IAAI,cAAc,GAA8B,IAAI,CAAA;IACpD,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QACzC,cAAc,GAAG,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;IACvF,CAAC;IAED,OAAO;QACL,qBAAqB,EAAE,WAAW;QAClC,oBAAoB,EAAE,UAAU;QAChC,8BAA8B,EAAE,QAAQ;QACxC,oBAAoB;QACpB,sBAAsB;QACtB,cAAc;KACf,CAAA;AACH,CAAC;AAED,yEAAyE;AACzE,gEAAgE;AAChE,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,wBAAwB;IACxB,kBAAkB;IAClB,sBAAsB;IACtB,iBAAiB;IACjB,iBAAiB;IACjB,sBAAsB;IACtB,uBAAuB;IACvB,aAAa;IACb,eAAe;CAChB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atrib/verify",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "@noble/ed25519": "^2.3.0",
31
31
  "@noble/hashes": "^2.2.0",
32
32
  "canonicalize": "^2.1.0",
33
- "@atrib/mcp": "0.1.2"
33
+ "@atrib/mcp": "0.3.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^25.6.0",