@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.
- package/README.md +5 -5
- package/dist/chain/index.d.ts +154 -8
- package/dist/chain/index.js +18 -2
- package/dist/{chunk-4EJCATUC.js → chunk-3USIENKC.js} +207 -4
- package/dist/{chunk-FMHROCFH.js → chunk-PGFHCBGH.js} +1 -1
- package/dist/credentials/index.d.ts +3 -163
- package/dist/credentials/index.js +1 -1
- package/dist/dfos-credential-CAYCqUCP.d.ts +493 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +18 -2
- package/package.json +1 -1
- package/schemas/credit-claim.v1.json +75 -0
- package/schemas/post.v1.json +24 -10
- package/dist/schemas-BXye25k7.d.ts +0 -220
|
@@ -1,47 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
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
|
-
|
|
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 };
|
|
@@ -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 };
|