@metalabel/dfos-protocol 0.23.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,47 +1,5 @@
1
- import { z } from 'zod';
2
- import { V as VerifiedIdentity } from '../schemas-BXye25k7.js';
3
-
4
- /**
5
- * Max byte length of a credential JWS token — the credential's analog of
6
- * MAX_OPERATION_SIZE. Credentials are EXEMPT from the 64 KiB operation cap (a
7
- * maximum-depth 16-credential delegation chain embeds each parent token in `prf` and
8
- * legitimately exceeds it), so they carry their own larger ceiling. Measured
9
- * over the serialized leaf token, which contains the entire nested chain, so one
10
- * bound caps the whole delegation. A DoS guard on the nested `prf` structure;
11
- * generous (a max-depth chain serializes to well under this). VALIDITY-
12
- * determining: MUST match the Go reference (maxCredentialSize in jwt.go).
13
- */
14
- declare const MAX_CREDENTIAL_SIZE = 262144;
15
- /** Single attenuation entry — resource + action pair */
16
- declare const Attenuation: z.ZodObject<{
17
- resource: z.ZodString;
18
- action: z.ZodString;
19
- }, z.core.$loose>;
20
- type Attenuation = z.infer<typeof Attenuation>;
21
- /** DFOS credential payload — UCAN-style authorization token */
22
- declare const DFOSCredentialPayload: z.ZodObject<{
23
- version: z.ZodLiteral<1>;
24
- type: z.ZodLiteral<"DFOSCredential">;
25
- iss: z.ZodString;
26
- aud: z.ZodString;
27
- att: z.ZodArray<z.ZodObject<{
28
- resource: z.ZodString;
29
- action: z.ZodString;
30
- }, z.core.$loose>>;
31
- prf: z.ZodDefault<z.ZodArray<z.ZodString>>;
32
- exp: z.ZodNumber;
33
- iat: z.ZodNumber;
34
- }, z.core.$loose>;
35
- type DFOSCredentialPayload = z.infer<typeof DFOSCredentialPayload>;
36
- /** Claims for a DID-signed auth token (relay AuthN) */
37
- declare const AuthTokenClaims: z.ZodObject<{
38
- iss: z.ZodString;
39
- sub: z.ZodString;
40
- aud: z.ZodString;
41
- exp: z.ZodNumber;
42
- iat: z.ZodNumber;
43
- }, z.core.$loose>;
44
- type AuthTokenClaims = z.infer<typeof AuthTokenClaims>;
1
+ export { b as Attenuation, c as AuthTokenClaims, f as CredentialVerificationError, D as DFOSCredentialPayload, i as MAX_CREDENTIAL_SIZE, R as RevocationChecker, V as VerifiedDFOSCredential, r as VerifiedDelegationChain, t as createDFOSCredential, u as decodeDFOSCredentialUnsafe, v as isAttenuated, w as matchesResource, y as verifyDFOSCredential, z as verifyDelegationChain } from '../dfos-credential-CAYCqUCP.js';
2
+ import 'zod';
45
3
 
46
4
  interface AuthTokenCreateOptions {
47
5
  /** The DID proving identity */
@@ -93,122 +51,4 @@ declare class AuthTokenVerificationError extends Error {
93
51
  constructor(message: string);
94
52
  }
95
53
 
96
- interface VerifiedDFOSCredential {
97
- /** Issuer DID */
98
- iss: string;
99
- /** Audience DID or "*" for public */
100
- aud: string;
101
- /** Attenuations — resource + action pairs */
102
- att: Attenuation[];
103
- /** Parent credential JWS tokens */
104
- prf: string[];
105
- /** Expiry (unix seconds) */
106
- exp: number;
107
- /** Issued at (unix seconds) */
108
- iat: number;
109
- /** CID of the credential payload (for revocation references) */
110
- credentialCID: string;
111
- /** kid from the JWS header */
112
- signerKeyId: string;
113
- }
114
- interface VerifiedDelegationChain {
115
- /** The leaf credential */
116
- credential: VerifiedDFOSCredential;
117
- /** All credentials in the chain, from leaf to root */
118
- chain: VerifiedDFOSCredential[];
119
- /** The root DID that ultimately authorized the chain */
120
- rootDID: string;
121
- }
122
- /**
123
- * Create a signed DFOS credential
124
- *
125
- * The credential is a JWS with `typ: "did:dfos:credential"` and a CID in the
126
- * protected header for revocation addressability.
127
- */
128
- declare const createDFOSCredential: (options: {
129
- issuerDID: string;
130
- /** Audience DID, or "*" for public credentials */
131
- audienceDID: string;
132
- att: Attenuation[];
133
- /** Parent credential JWS tokens (for delegation chains) */
134
- prf?: string[];
135
- /** Expiry — unix seconds */
136
- exp: number;
137
- /** Signer function */
138
- signer: (message: Uint8Array) => Promise<Uint8Array>;
139
- /** Key ID (without DID prefix — just the key_xxx part) */
140
- keyId: string;
141
- /** Issued-at override — unix seconds (defaults to Date.now()) */
142
- iat?: number;
143
- }) => Promise<string>;
144
- /**
145
- * Verify a DFOS credential — signature, schema, expiry, CID integrity
146
- *
147
- * Does NOT verify the delegation chain. Use `verifyDelegationChain` for full
148
- * chain verification including attenuation enforcement.
149
- */
150
- declare const verifyDFOSCredential: (jwsToken: string, options: {
151
- resolveIdentity: (did: string) => Promise<VerifiedIdentity | undefined>;
152
- /** Current time in seconds (defaults to Date.now() / 1000) */
153
- now?: number;
154
- }) => Promise<VerifiedDFOSCredential>;
155
- /**
156
- * Verify a full delegation chain — walk `prf`, confirm monotonic attenuation,
157
- * verify each credential's signature, and confirm the chain roots at `rootDID`.
158
- *
159
- * The chain is walked from the leaf credential upward through each parent in
160
- * `prf`. At each hop: the child's `iss` must match a parent's `aud` (or the
161
- * parent's `aud` must be `"*"`), the child's `att` must be attenuated from the
162
- * parent's `att`, and the child's `exp` must not exceed the parent's `exp`.
163
- *
164
- * The chain terminates when a credential has `prf: []` (root credential). The
165
- * root credential's `iss` must equal `rootDID`.
166
- */
167
- declare const verifyDelegationChain: (credential: VerifiedDFOSCredential, options: {
168
- resolveIdentity: (did: string) => Promise<VerifiedIdentity | undefined>;
169
- /** The expected root authority DID (e.g., content chain creator) */
170
- rootDID: string;
171
- /** Current time in seconds (defaults to Date.now() / 1000) */
172
- now?: number;
173
- /** Check if a credential has been revoked (checked at every level of the chain) */
174
- isRevoked?: (issuerDID: string, credentialCID: string) => Promise<boolean>;
175
- }) => Promise<VerifiedDelegationChain>;
176
- /**
177
- * Check if `childAtt` is a valid attenuation of `parentAtt`
178
- *
179
- * Every entry in `childAtt` must be covered by at least one entry in
180
- * `parentAtt`. Coverage rules:
181
- *
182
- * - `chain:X` covered by `chain:X` (exact match)
183
- * - `chain:X` covered by `chain:*` (narrowing from wildcard — valid)
184
- * - `chain:*` covered by `chain:*` (exact match)
185
- * - `chain:*` NOT covered by `chain:X` (widening — invalid)
186
- * - Actions: child action set must be a subset of parent action set
187
- */
188
- declare const isAttenuated: (parentAtt: Attenuation[], childAtt: Attenuation[]) => boolean;
189
- /**
190
- * Check if an `att` array covers a requested resource
191
- *
192
- * Used at the relay to determine if a credential authorizes access to a
193
- * specific content chain.
194
- */
195
- declare const matchesResource: (att: Attenuation[], resource: string, action: string) => Promise<boolean>;
196
- /**
197
- * Decode a DFOS credential JWS without verifying the signature
198
- *
199
- * Returns null if the token is malformed or payload is invalid.
200
- */
201
- declare const decodeDFOSCredentialUnsafe: (jwsToken: string) => {
202
- header: {
203
- alg: string;
204
- typ: string;
205
- kid: string;
206
- cid: string;
207
- };
208
- payload: DFOSCredentialPayload;
209
- } | null;
210
- declare class CredentialVerificationError extends Error {
211
- constructor(message: string);
212
- }
213
-
214
- export { Attenuation, AuthTokenClaims, type AuthTokenCreateOptions, AuthTokenVerificationError, type AuthTokenVerifyOptions, CredentialVerificationError, DFOSCredentialPayload, MAX_CREDENTIAL_SIZE, type VerifiedAuthToken, type VerifiedDFOSCredential, type VerifiedDelegationChain, createAuthToken, createDFOSCredential, decodeDFOSCredentialUnsafe, isAttenuated, matchesResource, verifyAuthToken, verifyDFOSCredential, verifyDelegationChain };
54
+ export { type AuthTokenCreateOptions, AuthTokenVerificationError, type AuthTokenVerifyOptions, type VerifiedAuthToken, createAuthToken, verifyAuthToken };
@@ -13,7 +13,7 @@ import {
13
13
  verifyAuthToken,
14
14
  verifyDFOSCredential,
15
15
  verifyDelegationChain
16
- } from "../chunk-FMHROCFH.js";
16
+ } from "../chunk-PGFHCBGH.js";
17
17
  import "../chunk-4QQ5HK5M.js";
18
18
  export {
19
19
  Attenuation,
@@ -0,0 +1,493 @@
1
+ import { z } from 'zod';
2
+
3
+ /** Function that signs a byte array and returns a signature */
4
+ type Signer = (message: Uint8Array) => Promise<Uint8Array>;
5
+ /**
6
+ * Max number of service entries in an identity's services state — a generous
7
+ * cardinality ceiling on resolution fan-out. Individual entry fields are NOT
8
+ * separately length-capped (no per-field length zoo): the aggregate byte cap
9
+ * below, plus the operation-size cap, bound entry size. The op-size cap is the
10
+ * real arbiter when services and keys are both large.
11
+ */
12
+ declare const MAX_SERVICES_ENTRIES = 256;
13
+ /**
14
+ * Max CBOR-encoded size of the services array (bytes) — the SINGLE aggregate that
15
+ * bounds the services manifest, replacing the former per-field length caps (the
16
+ * same collapse the op-size cap applied at the operation level). Sized so the
17
+ * 256-entry ceiling is genuinely reachable with realistic entries.
18
+ */
19
+ declare const MAX_SERVICES_PAYLOAD_SIZE = 32768;
20
+ /**
21
+ * Max dag-cbor-encoded size of a single protocol operation payload (bytes) — the
22
+ * one aggregate validity bound on operation size, measured over the exact bytes
23
+ * the CID commits to. Generously set (64 KiB) so it never binds a legitimate
24
+ * proof-layer operation while bounding decode/verify cost (a DoS + determinism
25
+ * invariant). This is a VALIDITY-determining cap: it MUST be identical across
26
+ * implementations. Large binary media does NOT travel in operation payloads —
27
+ * it is referenced, not inlined — so this bound is about proof-layer ops only.
28
+ */
29
+ declare const MAX_OPERATION_SIZE = 65536;
30
+ declare const MultikeyPublicKey: z.ZodObject<{
31
+ id: z.ZodString;
32
+ type: z.ZodLiteral<"Multikey">;
33
+ publicKeyMultibase: z.ZodString;
34
+ }, z.core.$loose>;
35
+ type MultikeyPublicKey = z.infer<typeof MultikeyPublicKey>;
36
+ /**
37
+ * Anchor target shapes — a ContentAnchor references a STABLE content
38
+ * identifier, dispatched by structural form:
39
+ * - 31-char contentId (content chain) → mutable, gateable
40
+ * - CIDv1 dag-cbor+sha256 (artifact) → immutable, public
41
+ * Both are stable; a chain HEAD CID (also a `bafyrei…` CID but resolves to a
42
+ * non-artifact op) is rejected by the shape-dispatch + resolution type check,
43
+ * never anchored.
44
+ *
45
+ * The artifact form is the EXACT 59-char CIDv1(dag-cbor 0x71 + sha256 0x12 0x20)
46
+ * base32 string — 36 raw bytes → 58 base32 chars + the `b` multibase prefix,
47
+ * fixed `bafyrei` head + 52 base32 chars. Artifact payloads are ALWAYS dag-cbor +
48
+ * sha256 (ArtifactPayload below), so every real artifact CID is `bafyrei…`. The
49
+ * regex is pinned to that exact length (not a loose `baf…{20,}`) so an anchor of
50
+ * any other shape — wrong codec, wrong length — is rejected uniformly across
51
+ * implementations. New anchor KINDS arrive via a new service `type`, never a new
52
+ * anchor shape.
53
+ */
54
+ declare const CONTENT_ID_ANCHOR_RE: RegExp;
55
+ declare const ARTIFACT_CID_ANCHOR_RE: RegExp;
56
+ /**
57
+ * Service entry — discovery vocabulary in identity-chain state.
58
+ *
59
+ * Open namespace: `type` is an arbitrary bounded string. Recognized types
60
+ * (`DfosRelay`, `ContentAnchor`) are structurally validated; UNRECOGNIZED types
61
+ * are preserved verbatim and ignored (MUST-ignore-unknown) — only the common
62
+ * envelope (id + type) and the byte cap apply. New service types therefore
63
+ * never require a protocol/cross-language change.
64
+ */
65
+ declare const ServiceEntry: z.ZodObject<{
66
+ id: z.ZodString;
67
+ type: z.ZodString;
68
+ }, z.core.$catchall<z.ZodUnknown>>;
69
+ type ServiceEntry = z.infer<typeof ServiceEntry>;
70
+ /** Identity services state — full-state, bounded, unique entry ids */
71
+ declare const ServicesArray: z.ZodArray<z.ZodObject<{
72
+ id: z.ZodString;
73
+ type: z.ZodString;
74
+ }, z.core.$catchall<z.ZodUnknown>>>;
75
+ type ServicesArray = z.infer<typeof ServicesArray>;
76
+ /**
77
+ * The canonical DFOS operation timestamp grammar: fixed 3-digit fraction, literal
78
+ * `Z`, full calendar validation. Deliberately stricter than RFC 3339 (no numeric
79
+ * offsets, no variable fraction) so two implementations cannot disagree about
80
+ * whether a signed timestamp is well-formed. The Go twin is
81
+ * `time.Parse(protocolTimeFormat, …)`; the 22-case vector set asserting they agree
82
+ * verdict-for-verdict lives in tests/timestamp-grammar.spec.ts and
83
+ * dfos-protocol-go/timestamp_grammar_test.go.
84
+ */
85
+ declare const Iso8601: z.ZodISODateTime;
86
+ /**
87
+ * Parse a canonical DFOS timestamp to integer unix **seconds**, or null when it
88
+ * does not match the grammar above.
89
+ *
90
+ * This is the ONE parse every consumer of a signed timestamp should use when it
91
+ * needs a comparable instant. A lenient `new Date(value)` accepts inputs the
92
+ * protocol rejects (numeric offsets, missing `Z` — which some runtimes then read
93
+ * as LOCAL time), so two verifiers in different timezones could order the same two
94
+ * signed timestamps differently. Truncates (floors) the millisecond remainder to
95
+ * match the credential temporal basis — see CREDENTIALS.md "Time Basis Conversion
96
+ * and Boundaries". Go twin: `ParseProtocolTimestamp`.
97
+ */
98
+ declare const parseProtocolTimestampUnix: (value: string) => number | null;
99
+ declare const IdentityOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
100
+ version: z.ZodLiteral<1>;
101
+ type: z.ZodLiteral<"create">;
102
+ authKeys: z.ZodArray<z.ZodObject<{
103
+ id: z.ZodString;
104
+ type: z.ZodLiteral<"Multikey">;
105
+ publicKeyMultibase: z.ZodString;
106
+ }, z.core.$loose>>;
107
+ assertKeys: z.ZodArray<z.ZodObject<{
108
+ id: z.ZodString;
109
+ type: z.ZodLiteral<"Multikey">;
110
+ publicKeyMultibase: z.ZodString;
111
+ }, z.core.$loose>>;
112
+ controllerKeys: z.ZodArray<z.ZodObject<{
113
+ id: z.ZodString;
114
+ type: z.ZodLiteral<"Multikey">;
115
+ publicKeyMultibase: z.ZodString;
116
+ }, z.core.$loose>>;
117
+ services: z.ZodOptional<z.ZodArray<z.ZodObject<{
118
+ id: z.ZodString;
119
+ type: z.ZodString;
120
+ }, z.core.$catchall<z.ZodUnknown>>>>;
121
+ createdAt: z.ZodISODateTime;
122
+ }, z.core.$loose>, z.ZodObject<{
123
+ version: z.ZodLiteral<1>;
124
+ type: z.ZodLiteral<"update">;
125
+ previousOperationCID: z.ZodString;
126
+ authKeys: z.ZodArray<z.ZodObject<{
127
+ id: z.ZodString;
128
+ type: z.ZodLiteral<"Multikey">;
129
+ publicKeyMultibase: z.ZodString;
130
+ }, z.core.$loose>>;
131
+ assertKeys: z.ZodArray<z.ZodObject<{
132
+ id: z.ZodString;
133
+ type: z.ZodLiteral<"Multikey">;
134
+ publicKeyMultibase: z.ZodString;
135
+ }, z.core.$loose>>;
136
+ controllerKeys: z.ZodArray<z.ZodObject<{
137
+ id: z.ZodString;
138
+ type: z.ZodLiteral<"Multikey">;
139
+ publicKeyMultibase: z.ZodString;
140
+ }, z.core.$loose>>;
141
+ services: z.ZodOptional<z.ZodArray<z.ZodObject<{
142
+ id: z.ZodString;
143
+ type: z.ZodString;
144
+ }, z.core.$catchall<z.ZodUnknown>>>>;
145
+ createdAt: z.ZodISODateTime;
146
+ }, z.core.$loose>, z.ZodObject<{
147
+ version: z.ZodLiteral<1>;
148
+ type: z.ZodLiteral<"delete">;
149
+ previousOperationCID: z.ZodString;
150
+ createdAt: z.ZodISODateTime;
151
+ }, z.core.$loose>], "type">;
152
+ type IdentityOperation = z.infer<typeof IdentityOperation>;
153
+ declare const VerifiedIdentity: z.ZodObject<{
154
+ did: z.ZodString;
155
+ isDeleted: z.ZodBoolean;
156
+ authKeys: z.ZodArray<z.ZodObject<{
157
+ id: z.ZodString;
158
+ type: z.ZodLiteral<"Multikey">;
159
+ publicKeyMultibase: z.ZodString;
160
+ }, z.core.$loose>>;
161
+ assertKeys: z.ZodArray<z.ZodObject<{
162
+ id: z.ZodString;
163
+ type: z.ZodLiteral<"Multikey">;
164
+ publicKeyMultibase: z.ZodString;
165
+ }, z.core.$loose>>;
166
+ controllerKeys: z.ZodArray<z.ZodObject<{
167
+ id: z.ZodString;
168
+ type: z.ZodLiteral<"Multikey">;
169
+ publicKeyMultibase: z.ZodString;
170
+ }, z.core.$loose>>;
171
+ services: z.ZodArray<z.ZodObject<{
172
+ id: z.ZodString;
173
+ type: z.ZodString;
174
+ }, z.core.$catchall<z.ZodUnknown>>>;
175
+ }, z.core.$strict>;
176
+ type VerifiedIdentity = z.infer<typeof VerifiedIdentity>;
177
+ declare const ContentOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
178
+ version: z.ZodLiteral<1>;
179
+ type: z.ZodLiteral<"create">;
180
+ did: z.ZodString;
181
+ documentCID: z.ZodString;
182
+ baseDocumentCID: z.ZodNullable<z.ZodString>;
183
+ createdAt: z.ZodISODateTime;
184
+ }, z.core.$loose>, z.ZodObject<{
185
+ version: z.ZodLiteral<1>;
186
+ type: z.ZodLiteral<"update">;
187
+ did: z.ZodString;
188
+ previousOperationCID: z.ZodString;
189
+ documentCID: z.ZodNullable<z.ZodString>;
190
+ baseDocumentCID: z.ZodNullable<z.ZodString>;
191
+ createdAt: z.ZodISODateTime;
192
+ authorization: z.ZodOptional<z.ZodString>;
193
+ }, z.core.$loose>, z.ZodObject<{
194
+ version: z.ZodLiteral<1>;
195
+ type: z.ZodLiteral<"delete">;
196
+ did: z.ZodString;
197
+ previousOperationCID: z.ZodString;
198
+ createdAt: z.ZodISODateTime;
199
+ authorization: z.ZodOptional<z.ZodString>;
200
+ }, z.core.$loose>], "type">;
201
+ type ContentOperation = z.infer<typeof ContentOperation>;
202
+ /** Max CBOR-encoded payload size for artifacts (bytes) — protocol constant */
203
+ declare const MAX_ARTIFACT_PAYLOAD_SIZE = 16384;
204
+ /** Artifact: standalone signed inline document, immutable, CID-addressable */
205
+ declare const ArtifactPayload: z.ZodObject<{
206
+ version: z.ZodLiteral<1>;
207
+ type: z.ZodLiteral<"artifact">;
208
+ did: z.ZodString;
209
+ content: z.ZodObject<{
210
+ $schema: z.ZodString;
211
+ }, z.core.$catchall<z.ZodUnknown>>;
212
+ createdAt: z.ZodISODateTime;
213
+ }, z.core.$loose>;
214
+ type ArtifactPayload = z.infer<typeof ArtifactPayload>;
215
+ /**
216
+ * Countersign: standalone witness attestation referencing a target operation by CID.
217
+ *
218
+ * `relation` is an OPEN-namespace tag naming the nature of the attestation
219
+ * (e.g. `coauthors`, `endorses`, `witnessed`, `holds`, `received`). It is an
220
+ * arbitrary bounded string — recognized values carry social meaning to clients,
221
+ * unrecognized values MUST be preserved and ignored. Optional, so a bare witness
222
+ * attestation (no relation) encodes identically (CID-neutral).
223
+ */
224
+ declare const CountersignPayload: z.ZodObject<{
225
+ version: z.ZodLiteral<1>;
226
+ type: z.ZodLiteral<"countersign">;
227
+ did: z.ZodString;
228
+ targetCID: z.ZodString;
229
+ relation: z.ZodOptional<z.ZodString>;
230
+ createdAt: z.ZodISODateTime;
231
+ }, z.core.$loose>;
232
+ type CountersignPayload = z.infer<typeof CountersignPayload>;
233
+ /** Revocation: signed credential revocation artifact, gossiped on the proof plane */
234
+ declare const RevocationPayload: z.ZodObject<{
235
+ version: z.ZodLiteral<1>;
236
+ type: z.ZodLiteral<"revocation">;
237
+ did: z.ZodString;
238
+ credentialCID: z.ZodString;
239
+ createdAt: z.ZodISODateTime;
240
+ }, z.core.$loose>;
241
+ type RevocationPayload = z.infer<typeof RevocationPayload>;
242
+ /**
243
+ * Max byte length of a credit-claim JWS token — the claim's aggregate size bound,
244
+ * the same register as MAX_CREDENTIAL_SIZE (measured over the serialized token,
245
+ * checked before any decode as a DoS guard). Claims are small by construction:
246
+ * two identifiers, a role string, and a timestamp. Deliberately tight because
247
+ * claims travel INSIDE document bytes — a document embedding many credits carries
248
+ * one token per claimed entry, so a generous per-claim cap would multiply into the
249
+ * document blob. `role` therefore carries no separate length cap; this aggregate
250
+ * is the single byte arbiter. VALIDITY-determining: MUST match the Go reference
251
+ * (maxCreditClaimSize in credit_claim.go).
252
+ */
253
+ declare const MAX_CREDIT_CLAIM_SIZE = 4096;
254
+ /**
255
+ * Credit claim: a claimant's signed assertion that it holds a named role on a
256
+ * content chain. A document-plane artifact — it is NOT gossiped and relays are not
257
+ * credit-claim aware; a claim travels inside the document bytes that embed it (see
258
+ * `specs/CREDITS.md`).
259
+ *
260
+ * `contentId` is the binder — the STABLE 31-char content chain id, never a
261
+ * documentCID or a chain head CID. Binding to the chain (not a document) is what
262
+ * makes a claim survive edits verbatim and avoids the circularity of a claim
263
+ * embedded in the very document it would otherwise commit to. It is shape-validated
264
+ * against the same 31-char contentId form used for anchor dispatch, so an artifact
265
+ * CID (immutable, chainless, and therefore unable to host a credits slot) is
266
+ * rejected uniformly across implementations.
267
+ *
268
+ * `role` is an OPEN-namespace tag compared by exact, case-sensitive byte equality —
269
+ * it is the third component of the entry↔claim bind, so no normalization of any kind
270
+ * is applied to it.
271
+ *
272
+ * `asOfDocumentCID` is an OPTIONAL content-strength flavor: the claimant pins the
273
+ * document state it is crediting itself on. Omitted by default, and omission is
274
+ * CID-neutral (undefined strips under canonical CBOR). Consumers that ignore it are
275
+ * conformant — the bind never depends on it. When the key IS present it MUST be a
276
+ * non-empty string: an empty string is a distinct, CID-changing encoding from an
277
+ * absent field, so accepting it would mean two different claim CIDs for the same
278
+ * (absent-flavor) statement.
279
+ *
280
+ * `did` is constrained to the `did:` prefix and non-empty, which is STRICTER than
281
+ * the sibling wire payloads above (`RevocationPayload.did`, `ContentOperation.did`
282
+ * are bare strings). That is deliberate, not drift: the published
283
+ * `credit-claim/v1` JSON Schema already mandates `^did:`, so leaving the zod schema
284
+ * permissive forked validity between the schema, this verifier, and the Go twin.
285
+ * The check is a PREFIX check, not full did:dfos validation — a claimant DID is not
286
+ * required to be a did:dfos identifier.
287
+ */
288
+ declare const CreditClaimPayload: z.ZodObject<{
289
+ version: z.ZodLiteral<1>;
290
+ type: z.ZodLiteral<"credit-claim">;
291
+ contentId: z.ZodString;
292
+ did: z.ZodString;
293
+ role: z.ZodString;
294
+ createdAt: z.ZodISODateTime;
295
+ asOfDocumentCID: z.ZodOptional<z.ZodString>;
296
+ }, z.core.$loose>;
297
+ type CreditClaimPayload = z.infer<typeof CreditClaimPayload>;
298
+
299
+ /**
300
+ * Max byte length of a credential JWS token — the credential's analog of
301
+ * MAX_OPERATION_SIZE. Credentials are EXEMPT from the 64 KiB operation cap (a
302
+ * maximum-depth 16-credential delegation chain embeds each parent token in `prf` and
303
+ * legitimately exceeds it), so they carry their own larger ceiling. Measured
304
+ * over the serialized leaf token, which contains the entire nested chain, so one
305
+ * bound caps the whole delegation. A DoS guard on the nested `prf` structure;
306
+ * generous (a max-depth chain serializes to well under this). VALIDITY-
307
+ * determining: MUST match the Go reference (maxCredentialSize in jwt.go).
308
+ */
309
+ declare const MAX_CREDENTIAL_SIZE = 262144;
310
+ /** Single attenuation entry — resource + action pair */
311
+ declare const Attenuation: z.ZodObject<{
312
+ resource: z.ZodString;
313
+ action: z.ZodString;
314
+ }, z.core.$loose>;
315
+ type Attenuation = z.infer<typeof Attenuation>;
316
+ /** DFOS credential payload — UCAN-style authorization token */
317
+ declare const DFOSCredentialPayload: z.ZodObject<{
318
+ version: z.ZodLiteral<1>;
319
+ type: z.ZodLiteral<"DFOSCredential">;
320
+ iss: z.ZodString;
321
+ aud: z.ZodString;
322
+ att: z.ZodArray<z.ZodObject<{
323
+ resource: z.ZodString;
324
+ action: z.ZodString;
325
+ }, z.core.$loose>>;
326
+ prf: z.ZodDefault<z.ZodArray<z.ZodString>>;
327
+ exp: z.ZodNumber;
328
+ iat: z.ZodNumber;
329
+ }, z.core.$loose>;
330
+ type DFOSCredentialPayload = z.infer<typeof DFOSCredentialPayload>;
331
+ /** Claims for a DID-signed auth token (relay AuthN) */
332
+ declare const AuthTokenClaims: z.ZodObject<{
333
+ iss: z.ZodString;
334
+ sub: z.ZodString;
335
+ aud: z.ZodString;
336
+ exp: z.ZodNumber;
337
+ iat: z.ZodNumber;
338
+ }, z.core.$loose>;
339
+ type AuthTokenClaims = z.infer<typeof AuthTokenClaims>;
340
+
341
+ interface VerifiedDFOSCredential {
342
+ /** Issuer DID */
343
+ iss: string;
344
+ /** Audience DID or "*" for public */
345
+ aud: string;
346
+ /** Attenuations — resource + action pairs */
347
+ att: Attenuation[];
348
+ /** Parent credential JWS tokens */
349
+ prf: string[];
350
+ /** Expiry (unix seconds) */
351
+ exp: number;
352
+ /** Issued at (unix seconds) */
353
+ iat: number;
354
+ /** CID of the credential payload (for revocation references) */
355
+ credentialCID: string;
356
+ /** kid from the JWS header */
357
+ signerKeyId: string;
358
+ }
359
+ interface VerifiedDelegationChain {
360
+ /** The leaf credential */
361
+ credential: VerifiedDFOSCredential;
362
+ /** All credentials in the chain, from leaf to root */
363
+ chain: VerifiedDFOSCredential[];
364
+ /** The root DID that ultimately authorized the chain */
365
+ rootDID: string;
366
+ }
367
+ /**
368
+ * Check whether a credential (leaf or any parent) has been revoked.
369
+ *
370
+ * `asOfUnix` selects WHICH question is being asked, and the two are different
371
+ * decisions: **acceptance is a freshness decision; verification of committed
372
+ * history is a validity decision.**
373
+ *
374
+ * - **Omitted, or `<= 0` (timeless)** — "is this credential revoked as far as you
375
+ * know right now?". The freshness question. Used by acceptance gates: relay
376
+ * ingest (do not admit a NEW operation authorized by a credential we already
377
+ * know to be revoked) and live read-path authorization. Non-positive instants
378
+ * are timeless because the Go twin uses `0` as its in-band sentinel and cannot
379
+ * express "as of epoch 0"; the degenerate case (an operation dated at or before
380
+ * 1970) therefore gets the stricter answer in both languages.
381
+ * - **Positive (as-of)** — "was this credential already revoked at `asOfUnix`?".
382
+ * The validity question. Return true only if a revocation exists AND its
383
+ * signed `createdAt` is ≤ `asOfUnix`. Used when verifying operations already
384
+ * committed to a chain, where `asOfUnix` is the operation's own `createdAt`.
385
+ * A revocation signed AFTER an operation does not invalidate it — see
386
+ * CREDENTIALS.md "Revocation Scope".
387
+ *
388
+ * An implementation that ignores `asOfUnix` degrades to the timeless answer,
389
+ * which is always the stricter (safe) direction — it can only reject history
390
+ * that as-of semantics would accept.
391
+ */
392
+ type RevocationChecker = (issuerDID: string, credentialCID: string, asOfUnix?: number) => Promise<boolean>;
393
+ /**
394
+ * Create a signed DFOS credential
395
+ *
396
+ * The credential is a JWS with `typ: "did:dfos:credential"` and a CID in the
397
+ * protected header for revocation addressability.
398
+ */
399
+ declare const createDFOSCredential: (options: {
400
+ issuerDID: string;
401
+ /** Audience DID, or "*" for public credentials */
402
+ audienceDID: string;
403
+ att: Attenuation[];
404
+ /** Parent credential JWS tokens (for delegation chains) */
405
+ prf?: string[];
406
+ /** Expiry — unix seconds */
407
+ exp: number;
408
+ /** Signer function */
409
+ signer: (message: Uint8Array) => Promise<Uint8Array>;
410
+ /** Key ID (without DID prefix — just the key_xxx part) */
411
+ keyId: string;
412
+ /** Issued-at override — unix seconds (defaults to Date.now()) */
413
+ iat?: number;
414
+ }) => Promise<string>;
415
+ /**
416
+ * Verify a DFOS credential — signature, schema, expiry, CID integrity
417
+ *
418
+ * Does NOT verify the delegation chain. Use `verifyDelegationChain` for full
419
+ * chain verification including attenuation enforcement.
420
+ */
421
+ declare const verifyDFOSCredential: (jwsToken: string, options: {
422
+ resolveIdentity: (did: string) => Promise<VerifiedIdentity | undefined>;
423
+ /** Current time in seconds (defaults to Date.now() / 1000) */
424
+ now?: number;
425
+ }) => Promise<VerifiedDFOSCredential>;
426
+ /**
427
+ * Verify a full delegation chain — walk `prf`, confirm monotonic attenuation,
428
+ * verify each credential's signature, and confirm the chain roots at `rootDID`.
429
+ *
430
+ * The chain is walked from the leaf credential upward through each parent in
431
+ * `prf`. At each hop: the child's `iss` must match a parent's `aud` (or the
432
+ * parent's `aud` must be `"*"`), the child's `att` must be attenuated from the
433
+ * parent's `att`, and the child's `exp` must not exceed the parent's `exp`.
434
+ *
435
+ * The chain terminates when a credential has `prf: []` (root credential). The
436
+ * root credential's `iss` must equal `rootDID`.
437
+ */
438
+ declare const verifyDelegationChain: (credential: VerifiedDFOSCredential, options: {
439
+ resolveIdentity: (did: string) => Promise<VerifiedIdentity | undefined>;
440
+ /** The expected root authority DID (e.g., content chain creator) */
441
+ rootDID: string;
442
+ /** Current time in seconds (defaults to Date.now() / 1000) */
443
+ now?: number;
444
+ /** Check if a credential has been revoked (checked at every level of the chain) */
445
+ isRevoked?: RevocationChecker;
446
+ /**
447
+ * As-of basis for the revocation check, unix seconds. Kept SEPARATE from
448
+ * `now` (the expiry basis) on purpose: expiry and revocation are two
449
+ * different decisions, and a caller evaluating expiry against a deterministic
450
+ * basis does not automatically want history-relative revocation. Omitted =
451
+ * timeless revocation (current knowledge). See `RevocationChecker`.
452
+ */
453
+ asOfUnix?: number;
454
+ }) => Promise<VerifiedDelegationChain>;
455
+ /**
456
+ * Check if `childAtt` is a valid attenuation of `parentAtt`
457
+ *
458
+ * Every entry in `childAtt` must be covered by at least one entry in
459
+ * `parentAtt`. Coverage rules:
460
+ *
461
+ * - `chain:X` covered by `chain:X` (exact match)
462
+ * - `chain:X` covered by `chain:*` (narrowing from wildcard — valid)
463
+ * - `chain:*` covered by `chain:*` (exact match)
464
+ * - `chain:*` NOT covered by `chain:X` (widening — invalid)
465
+ * - Actions: child action set must be a subset of parent action set
466
+ */
467
+ declare const isAttenuated: (parentAtt: Attenuation[], childAtt: Attenuation[]) => boolean;
468
+ /**
469
+ * Check if an `att` array covers a requested resource
470
+ *
471
+ * Used at the relay to determine if a credential authorizes access to a
472
+ * specific content chain.
473
+ */
474
+ declare const matchesResource: (att: Attenuation[], resource: string, action: string) => Promise<boolean>;
475
+ /**
476
+ * Decode a DFOS credential JWS without verifying the signature
477
+ *
478
+ * Returns null if the token is malformed or payload is invalid.
479
+ */
480
+ declare const decodeDFOSCredentialUnsafe: (jwsToken: string) => {
481
+ header: {
482
+ alg: string;
483
+ typ: string;
484
+ kid: string;
485
+ cid: string;
486
+ };
487
+ payload: DFOSCredentialPayload;
488
+ } | null;
489
+ declare class CredentialVerificationError extends Error {
490
+ constructor(message: string);
491
+ }
492
+
493
+ export { ARTIFACT_CID_ANCHOR_RE as A, CONTENT_ID_ANCHOR_RE as C, DFOSCredentialPayload as D, IdentityOperation as I, MAX_ARTIFACT_PAYLOAD_SIZE as M, type RevocationChecker as R, ServiceEntry as S, type VerifiedDFOSCredential as V, ArtifactPayload as a, Attenuation as b, AuthTokenClaims as c, ContentOperation as d, CountersignPayload as e, CredentialVerificationError as f, CreditClaimPayload as g, Iso8601 as h, MAX_CREDENTIAL_SIZE as i, MAX_CREDIT_CLAIM_SIZE as j, MAX_OPERATION_SIZE as k, MAX_SERVICES_ENTRIES as l, MAX_SERVICES_PAYLOAD_SIZE as m, MultikeyPublicKey as n, RevocationPayload as o, ServicesArray as p, type Signer as q, type VerifiedDelegationChain as r, VerifiedIdentity as s, createDFOSCredential as t, decodeDFOSCredentialUnsafe as u, isAttenuated as v, matchesResource as w, parseProtocolTimestampUnix as x, verifyDFOSCredential as y, verifyDelegationChain as z };