@metalabel/dfos-protocol 0.10.0 → 0.12.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 +7 -7
- package/dist/chain/index.d.ts +28 -31
- package/dist/chain/index.js +29 -9
- package/dist/{chunk-GQOZJKKO.js → chunk-4QQ5HK5M.js} +7 -3
- package/dist/{chunk-LQFOBE6X.js → chunk-J3XXF6F5.js} +18 -15
- package/dist/{chunk-GZ7ZAIRD.js → chunk-J5C4OXL4.js} +154 -103
- package/dist/credentials/index.d.ts +17 -6
- package/dist/credentials/index.js +4 -2
- package/dist/crypto/index.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +31 -9
- package/dist/schemas-Bb_9P8_s.d.ts +213 -0
- package/examples/identity-services.json +38 -0
- package/package.json +2 -2
- package/dist/schemas-BhikXSf_.d.ts +0 -146
- package/examples/beacon.json +0 -14
- package/schemas/manifest.v1.json +0 -29
|
@@ -1,51 +1,88 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MAX_CREDENTIAL_SIZE,
|
|
2
3
|
decodeDFOSCredentialUnsafe,
|
|
3
4
|
decodeMultikey,
|
|
4
5
|
matchesResource,
|
|
5
6
|
verifyDFOSCredential,
|
|
6
7
|
verifyDelegationChain
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-J3XXF6F5.js";
|
|
8
9
|
import {
|
|
9
10
|
createJws,
|
|
10
11
|
dagCborCanonicalEncode,
|
|
11
12
|
decodeJwsUnsafe,
|
|
12
13
|
generateIdNoPrefix,
|
|
13
14
|
verifyJws
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-4QQ5HK5M.js";
|
|
15
16
|
|
|
16
17
|
// src/chain/schemas.ts
|
|
17
18
|
import { z } from "zod";
|
|
18
|
-
var
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
var
|
|
23
|
-
var
|
|
24
|
-
|
|
25
|
-
id: z.string().max(MAX_KEY_ID),
|
|
19
|
+
var MAX_KEYS_PER_ROLE = 256;
|
|
20
|
+
var MAX_RELATION = 64;
|
|
21
|
+
var MAX_SERVICES_ENTRIES = 256;
|
|
22
|
+
var MAX_SERVICES_PAYLOAD_SIZE = 32768;
|
|
23
|
+
var MAX_OPERATION_SIZE = 65536;
|
|
24
|
+
var MultikeyPublicKey = z.looseObject({
|
|
25
|
+
id: z.string(),
|
|
26
26
|
type: z.literal("Multikey"),
|
|
27
|
-
publicKeyMultibase: z.string()
|
|
27
|
+
publicKeyMultibase: z.string()
|
|
28
28
|
});
|
|
29
|
+
var CONTENT_ID_ANCHOR_RE = /^[2346789acdefhknrtvz]{31}$/;
|
|
30
|
+
var ARTIFACT_CID_ANCHOR_RE = /^baf[a-z2-7]{20,}$/;
|
|
31
|
+
var ServiceEntry = z.object({
|
|
32
|
+
id: z.string().min(1),
|
|
33
|
+
type: z.string().min(1)
|
|
34
|
+
}).catchall(z.unknown()).superRefine((entry, ctx) => {
|
|
35
|
+
if (entry.type === "DfosRelay") {
|
|
36
|
+
const endpoint = entry["endpoint"];
|
|
37
|
+
if (typeof endpoint !== "string" || endpoint.length < 1) {
|
|
38
|
+
ctx.addIssue({ code: "custom", message: "DfosRelay requires a non-empty endpoint string" });
|
|
39
|
+
}
|
|
40
|
+
} else if (entry.type === "ContentAnchor") {
|
|
41
|
+
const label = entry["label"];
|
|
42
|
+
const anchor = entry["anchor"];
|
|
43
|
+
if (typeof label !== "string" || label.length < 1) {
|
|
44
|
+
ctx.addIssue({
|
|
45
|
+
code: "custom",
|
|
46
|
+
message: "ContentAnchor requires a non-empty label string"
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (typeof anchor !== "string" || !(CONTENT_ID_ANCHOR_RE.test(anchor) || ARTIFACT_CID_ANCHOR_RE.test(anchor))) {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: "custom",
|
|
52
|
+
message: "ContentAnchor anchor must be a 31-char contentId or a CIDv1 artifact CID"
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
var ServicesArray = z.array(ServiceEntry).max(MAX_SERVICES_ENTRIES).refine(
|
|
58
|
+
(arr) => new Set(arr.map((e) => e.id)).size === arr.length,
|
|
59
|
+
"service entry ids must be unique"
|
|
60
|
+
);
|
|
29
61
|
var Iso8601 = z.iso.datetime({ offset: false, precision: 3 });
|
|
30
|
-
var CIDString = z.string()
|
|
31
|
-
var IdentityCreate = z.
|
|
62
|
+
var CIDString = z.string();
|
|
63
|
+
var IdentityCreate = z.looseObject({
|
|
32
64
|
version: z.literal(1),
|
|
33
65
|
type: z.literal("create"),
|
|
34
66
|
authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
35
67
|
assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
36
68
|
controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
69
|
+
// Full-state discovery vocabulary. Optional so ops without services encode
|
|
70
|
+
// identically (undefined strips under canonical CBOR — CID-neutral).
|
|
71
|
+
services: ServicesArray.optional(),
|
|
37
72
|
createdAt: Iso8601
|
|
38
73
|
});
|
|
39
|
-
var IdentityUpdate = z.
|
|
74
|
+
var IdentityUpdate = z.looseObject({
|
|
40
75
|
version: z.literal(1),
|
|
41
76
|
type: z.literal("update"),
|
|
42
77
|
previousOperationCID: CIDString,
|
|
43
78
|
authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
44
79
|
assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
45
80
|
controllerKeys: z.array(MultikeyPublicKey).min(1, "update must have at least one controller key").max(MAX_KEYS_PER_ROLE),
|
|
81
|
+
// Full-state: an update REPLACES the entire services set (omit to clear).
|
|
82
|
+
services: ServicesArray.optional(),
|
|
46
83
|
createdAt: Iso8601
|
|
47
84
|
});
|
|
48
|
-
var IdentityDelete = z.
|
|
85
|
+
var IdentityDelete = z.looseObject({
|
|
49
86
|
version: z.literal(1),
|
|
50
87
|
type: z.literal("delete"),
|
|
51
88
|
previousOperationCID: CIDString,
|
|
@@ -57,40 +94,42 @@ var IdentityOperation = z.discriminatedUnion("type", [
|
|
|
57
94
|
IdentityDelete
|
|
58
95
|
]);
|
|
59
96
|
var VerifiedIdentity = z.strictObject({
|
|
60
|
-
did: z.string()
|
|
97
|
+
did: z.string(),
|
|
61
98
|
isDeleted: z.boolean(),
|
|
62
99
|
authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
63
100
|
assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
64
|
-
controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE)
|
|
101
|
+
controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
102
|
+
/** Resolved discovery vocabulary — projection of the winning head's services */
|
|
103
|
+
services: ServicesArray
|
|
65
104
|
});
|
|
66
|
-
var ContentCreate = z.
|
|
105
|
+
var ContentCreate = z.looseObject({
|
|
67
106
|
version: z.literal(1),
|
|
68
107
|
type: z.literal("create"),
|
|
69
|
-
did: z.string()
|
|
108
|
+
did: z.string(),
|
|
70
109
|
documentCID: CIDString,
|
|
71
110
|
baseDocumentCID: CIDString.nullable(),
|
|
72
111
|
createdAt: Iso8601,
|
|
73
|
-
note: z.string().
|
|
112
|
+
note: z.string().nullable()
|
|
74
113
|
});
|
|
75
|
-
var ContentUpdate = z.
|
|
114
|
+
var ContentUpdate = z.looseObject({
|
|
76
115
|
version: z.literal(1),
|
|
77
116
|
type: z.literal("update"),
|
|
78
|
-
did: z.string()
|
|
117
|
+
did: z.string(),
|
|
79
118
|
previousOperationCID: CIDString,
|
|
80
119
|
documentCID: CIDString.nullable(),
|
|
81
120
|
baseDocumentCID: CIDString.nullable(),
|
|
82
121
|
createdAt: Iso8601,
|
|
83
|
-
note: z.string().
|
|
122
|
+
note: z.string().nullable(),
|
|
84
123
|
/** DFOS credential authorizing this operation when signer is not the chain creator */
|
|
85
124
|
authorization: z.string().optional()
|
|
86
125
|
});
|
|
87
|
-
var ContentDelete = z.
|
|
126
|
+
var ContentDelete = z.looseObject({
|
|
88
127
|
version: z.literal(1),
|
|
89
128
|
type: z.literal("delete"),
|
|
90
|
-
did: z.string()
|
|
129
|
+
did: z.string(),
|
|
91
130
|
previousOperationCID: CIDString,
|
|
92
131
|
createdAt: Iso8601,
|
|
93
|
-
note: z.string().
|
|
132
|
+
note: z.string().nullable(),
|
|
94
133
|
/** DFOS credential authorizing this operation when signer is not the chain creator */
|
|
95
134
|
authorization: z.string().optional()
|
|
96
135
|
});
|
|
@@ -99,34 +138,27 @@ var ContentOperation = z.discriminatedUnion("type", [
|
|
|
99
138
|
ContentUpdate,
|
|
100
139
|
ContentDelete
|
|
101
140
|
]);
|
|
102
|
-
var BeaconPayload = z.strictObject({
|
|
103
|
-
version: z.literal(1),
|
|
104
|
-
type: z.literal("beacon"),
|
|
105
|
-
did: z.string().max(MAX_DID),
|
|
106
|
-
manifestContentId: z.string().max(MAX_CID),
|
|
107
|
-
createdAt: Iso8601
|
|
108
|
-
});
|
|
109
|
-
var MAX_SCHEMA = 256;
|
|
110
141
|
var MAX_ARTIFACT_PAYLOAD_SIZE = 16384;
|
|
111
|
-
var ArtifactContent = z.object({ $schema: z.string()
|
|
112
|
-
var ArtifactPayload = z.
|
|
142
|
+
var ArtifactContent = z.object({ $schema: z.string() }).catchall(z.unknown());
|
|
143
|
+
var ArtifactPayload = z.looseObject({
|
|
113
144
|
version: z.literal(1),
|
|
114
145
|
type: z.literal("artifact"),
|
|
115
|
-
did: z.string()
|
|
146
|
+
did: z.string(),
|
|
116
147
|
content: ArtifactContent,
|
|
117
148
|
createdAt: Iso8601
|
|
118
149
|
});
|
|
119
|
-
var CountersignPayload = z.
|
|
150
|
+
var CountersignPayload = z.looseObject({
|
|
120
151
|
version: z.literal(1),
|
|
121
152
|
type: z.literal("countersign"),
|
|
122
|
-
did: z.string()
|
|
153
|
+
did: z.string(),
|
|
123
154
|
targetCID: CIDString,
|
|
155
|
+
relation: z.string().min(1).max(MAX_RELATION).optional(),
|
|
124
156
|
createdAt: Iso8601
|
|
125
157
|
});
|
|
126
|
-
var RevocationPayload = z.
|
|
158
|
+
var RevocationPayload = z.looseObject({
|
|
127
159
|
version: z.literal(1),
|
|
128
160
|
type: z.literal("revocation"),
|
|
129
|
-
did: z.string()
|
|
161
|
+
did: z.string(),
|
|
130
162
|
credentialCID: CIDString,
|
|
131
163
|
createdAt: Iso8601
|
|
132
164
|
});
|
|
@@ -140,6 +172,27 @@ var deriveContentId = (cidBytes) => {
|
|
|
140
172
|
return generateIdNoPrefix({ seed: cidBytes });
|
|
141
173
|
};
|
|
142
174
|
|
|
175
|
+
// src/chain/services.ts
|
|
176
|
+
var assertServicesWithinCap = async (services) => {
|
|
177
|
+
const encoded = await dagCborCanonicalEncode(services);
|
|
178
|
+
if (encoded.bytes.length > MAX_SERVICES_PAYLOAD_SIZE) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
`services payload exceeds max size: ${encoded.bytes.length} > ${MAX_SERVICES_PAYLOAD_SIZE}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
var classifyAnchor = (anchor) => {
|
|
185
|
+
if (CONTENT_ID_ANCHOR_RE.test(anchor)) return "chain";
|
|
186
|
+
if (ARTIFACT_CID_ANCHOR_RE.test(anchor)) return "artifact";
|
|
187
|
+
return "invalid";
|
|
188
|
+
};
|
|
189
|
+
var RECOGNIZED_SERVICE_TYPES = ["DfosRelay", "ContentAnchor"];
|
|
190
|
+
var isRecognizedServiceType = (type) => RECOGNIZED_SERVICE_TYPES.includes(type);
|
|
191
|
+
var relayEndpoints = (services) => services.filter((e) => e.type === "DfosRelay").map((e) => e["endpoint"]).filter((v) => typeof v === "string");
|
|
192
|
+
var anchorsByLabel = (services, label) => services.filter(
|
|
193
|
+
(e) => e.type === "ContentAnchor" && e["label"] === label
|
|
194
|
+
);
|
|
195
|
+
|
|
143
196
|
// src/chain/identity-chain.ts
|
|
144
197
|
var signIdentityOperation = async (input) => {
|
|
145
198
|
const kid = input.identityDID ? `${input.identityDID}#${input.keyId}` : input.keyId;
|
|
@@ -162,6 +215,7 @@ var verifyIdentityChain = async (input) => {
|
|
|
162
215
|
authKeys: [],
|
|
163
216
|
assertKeys: [],
|
|
164
217
|
controllerKeys: [],
|
|
218
|
+
services: [],
|
|
165
219
|
seenKeys: /* @__PURE__ */ new Map()
|
|
166
220
|
};
|
|
167
221
|
for (const [idx, jwsToken] of input.log.entries()) {
|
|
@@ -190,6 +244,7 @@ var verifyIdentityChain = async (input) => {
|
|
|
190
244
|
state.authKeys = op.authKeys;
|
|
191
245
|
state.assertKeys = op.assertKeys;
|
|
192
246
|
state.controllerKeys = op.controllerKeys;
|
|
247
|
+
state.services = op.services ?? [];
|
|
193
248
|
}
|
|
194
249
|
if (op.type === "update" || op.type === "delete") {
|
|
195
250
|
if (op.previousOperationCID !== state.previousOperationCID) {
|
|
@@ -217,8 +272,20 @@ var verifyIdentityChain = async (input) => {
|
|
|
217
272
|
throw new Error(`log[${idx}]: cannot repeat key ids in same usage`);
|
|
218
273
|
}
|
|
219
274
|
});
|
|
275
|
+
if (op.services) {
|
|
276
|
+
try {
|
|
277
|
+
await assertServicesWithinCap(op.services);
|
|
278
|
+
} catch (e) {
|
|
279
|
+
throw new Error(`log[${idx}]: ${e.message}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
220
282
|
}
|
|
221
283
|
const encoded = await dagCborCanonicalEncode(op);
|
|
284
|
+
if (encoded.bytes.length > MAX_OPERATION_SIZE) {
|
|
285
|
+
throw new Error(
|
|
286
|
+
`log[${idx}]: operation exceeds max size: ${encoded.bytes.length} > ${MAX_OPERATION_SIZE}`
|
|
287
|
+
);
|
|
288
|
+
}
|
|
222
289
|
const operationCID = encoded.cid.toString();
|
|
223
290
|
if (!decoded.header.cid) {
|
|
224
291
|
throw new Error(`log[${idx}]: missing cid in protected header`);
|
|
@@ -271,6 +338,7 @@ var verifyIdentityChain = async (input) => {
|
|
|
271
338
|
state.authKeys = op.authKeys;
|
|
272
339
|
state.assertKeys = op.assertKeys;
|
|
273
340
|
state.controllerKeys = op.controllerKeys;
|
|
341
|
+
state.services = op.services ?? [];
|
|
274
342
|
break;
|
|
275
343
|
case "delete":
|
|
276
344
|
state.isDeleted = true;
|
|
@@ -283,7 +351,8 @@ var verifyIdentityChain = async (input) => {
|
|
|
283
351
|
isDeleted: state.isDeleted,
|
|
284
352
|
authKeys: state.authKeys,
|
|
285
353
|
assertKeys: state.assertKeys,
|
|
286
|
-
controllerKeys: state.controllerKeys
|
|
354
|
+
controllerKeys: state.controllerKeys,
|
|
355
|
+
services: state.services
|
|
287
356
|
};
|
|
288
357
|
};
|
|
289
358
|
var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
@@ -312,6 +381,9 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
312
381
|
throw new Error("createdAt must be after last op");
|
|
313
382
|
}
|
|
314
383
|
const encoded = await dagCborCanonicalEncode(op);
|
|
384
|
+
if (encoded.bytes.length > MAX_OPERATION_SIZE) {
|
|
385
|
+
throw new Error(`operation exceeds max size: ${encoded.bytes.length} > ${MAX_OPERATION_SIZE}`);
|
|
386
|
+
}
|
|
315
387
|
const operationCID = encoded.cid.toString();
|
|
316
388
|
if (!decoded.header.cid) throw new Error("missing cid in protected header");
|
|
317
389
|
if (decoded.header.cid !== operationCID) throw new Error("cid mismatch in protected header");
|
|
@@ -342,24 +414,39 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
342
414
|
throw new Error("cannot repeat key ids in same usage");
|
|
343
415
|
}
|
|
344
416
|
});
|
|
417
|
+
if (op.services) await assertServicesWithinCap(op.services);
|
|
345
418
|
}
|
|
346
419
|
const newState = op.type === "update" ? {
|
|
347
420
|
did: currentState.did,
|
|
348
421
|
isDeleted: false,
|
|
349
422
|
authKeys: op.authKeys,
|
|
350
423
|
assertKeys: op.assertKeys,
|
|
351
|
-
controllerKeys: op.controllerKeys
|
|
424
|
+
controllerKeys: op.controllerKeys,
|
|
425
|
+
services: op.services ?? []
|
|
352
426
|
} : {
|
|
353
427
|
did: currentState.did,
|
|
354
428
|
isDeleted: true,
|
|
355
429
|
authKeys: currentState.authKeys,
|
|
356
430
|
assertKeys: currentState.assertKeys,
|
|
357
|
-
controllerKeys: currentState.controllerKeys
|
|
431
|
+
controllerKeys: currentState.controllerKeys,
|
|
432
|
+
services: currentState.services
|
|
358
433
|
};
|
|
359
434
|
return { state: newState, operationCID, createdAt: op.createdAt };
|
|
360
435
|
};
|
|
361
436
|
|
|
362
437
|
// src/chain/content-chain.ts
|
|
438
|
+
var operationSizeForCap = async (op, fullByteLength) => {
|
|
439
|
+
const auth = op.authorization;
|
|
440
|
+
if (typeof auth !== "string") return fullByteLength;
|
|
441
|
+
if (auth.length > MAX_CREDENTIAL_SIZE) {
|
|
442
|
+
throw new Error(
|
|
443
|
+
`authorization credential exceeds max size: ${auth.length} > ${MAX_CREDENTIAL_SIZE}`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
const { authorization: _omit, ...rest } = op;
|
|
447
|
+
const encoded = await dagCborCanonicalEncode(rest);
|
|
448
|
+
return encoded.bytes.length;
|
|
449
|
+
};
|
|
363
450
|
var signContentOperation = async (input) => {
|
|
364
451
|
const encoded = await dagCborCanonicalEncode(input.operation);
|
|
365
452
|
const operationCID = encoded.cid.toString();
|
|
@@ -483,6 +570,10 @@ var verifyContentChain = async (input) => {
|
|
|
483
570
|
}
|
|
484
571
|
}
|
|
485
572
|
const encoded = await dagCborCanonicalEncode(op);
|
|
573
|
+
const opSize = await operationSizeForCap(op, encoded.bytes.length);
|
|
574
|
+
if (opSize > MAX_OPERATION_SIZE) {
|
|
575
|
+
throw new Error(`operation exceeds max size: ${opSize} > ${MAX_OPERATION_SIZE}`);
|
|
576
|
+
}
|
|
486
577
|
const operationCID = encoded.cid.toString();
|
|
487
578
|
if (!decoded.header.cid) {
|
|
488
579
|
throw new Error(`log[${idx}]: missing cid in protected header`);
|
|
@@ -584,6 +675,10 @@ var verifyContentExtensionFromTrustedState = async (input) => {
|
|
|
584
675
|
}
|
|
585
676
|
}
|
|
586
677
|
const encoded = await dagCborCanonicalEncode(op);
|
|
678
|
+
const opSize = await operationSizeForCap(op, encoded.bytes.length);
|
|
679
|
+
if (opSize > MAX_OPERATION_SIZE) {
|
|
680
|
+
throw new Error(`operation exceeds max size: ${opSize} > ${MAX_OPERATION_SIZE}`);
|
|
681
|
+
}
|
|
587
682
|
const operationCID = encoded.cid.toString();
|
|
588
683
|
if (!decoded.header.cid) throw new Error("missing cid in protected header");
|
|
589
684
|
if (decoded.header.cid !== operationCID) throw new Error("cid mismatch in protected header");
|
|
@@ -599,61 +694,6 @@ var verifyContentExtensionFromTrustedState = async (input) => {
|
|
|
599
694
|
return { state: newState, operationCID, createdAt: op.createdAt };
|
|
600
695
|
};
|
|
601
696
|
|
|
602
|
-
// src/chain/beacon.ts
|
|
603
|
-
var signBeacon = async (input) => {
|
|
604
|
-
const encoded = await dagCborCanonicalEncode(input.payload);
|
|
605
|
-
const beaconCID = encoded.cid.toString();
|
|
606
|
-
const jwsToken = await createJws({
|
|
607
|
-
header: { alg: "EdDSA", typ: "did:dfos:beacon", kid: input.kid, cid: beaconCID },
|
|
608
|
-
payload: input.payload,
|
|
609
|
-
sign: input.signer
|
|
610
|
-
});
|
|
611
|
-
return { jwsToken, beaconCID };
|
|
612
|
-
};
|
|
613
|
-
var MAX_FUTURE_MS = 5 * 60 * 1e3;
|
|
614
|
-
var verifyBeacon = async (input) => {
|
|
615
|
-
const decoded = decodeJwsUnsafe(input.jwsToken);
|
|
616
|
-
if (!decoded) throw new Error("failed to decode beacon JWS");
|
|
617
|
-
const result = BeaconPayload.safeParse(decoded.payload);
|
|
618
|
-
if (!result.success) {
|
|
619
|
-
const messages = result.error.issues.map((e) => e.message).join(", ");
|
|
620
|
-
throw new Error(`invalid beacon payload: ${messages}`);
|
|
621
|
-
}
|
|
622
|
-
const payload = result.data;
|
|
623
|
-
if (decoded.header.typ !== "did:dfos:beacon") {
|
|
624
|
-
throw new Error(`invalid beacon typ: ${decoded.header.typ}`);
|
|
625
|
-
}
|
|
626
|
-
const kid = decoded.header.kid;
|
|
627
|
-
const hashIdx = kid.indexOf("#");
|
|
628
|
-
if (hashIdx < 0) throw new Error("beacon kid must be a DID URL");
|
|
629
|
-
const kidDid = kid.substring(0, hashIdx);
|
|
630
|
-
if (kidDid !== payload.did) {
|
|
631
|
-
throw new Error("beacon kid DID does not match payload did");
|
|
632
|
-
}
|
|
633
|
-
const publicKey = await input.resolveKey(kid);
|
|
634
|
-
try {
|
|
635
|
-
verifyJws({ token: input.jwsToken, publicKey });
|
|
636
|
-
} catch {
|
|
637
|
-
throw new Error("invalid beacon signature");
|
|
638
|
-
}
|
|
639
|
-
const encoded = await dagCborCanonicalEncode(payload);
|
|
640
|
-
const beaconCID = encoded.cid.toString();
|
|
641
|
-
if (!decoded.header.cid) throw new Error("missing cid in beacon header");
|
|
642
|
-
if (decoded.header.cid !== beaconCID) throw new Error("beacon cid mismatch");
|
|
643
|
-
const now = input.now ?? Date.now();
|
|
644
|
-
const beaconTime = new Date(payload.createdAt).getTime();
|
|
645
|
-
if (beaconTime > now + MAX_FUTURE_MS) {
|
|
646
|
-
throw new Error("beacon createdAt is too far in the future");
|
|
647
|
-
}
|
|
648
|
-
return {
|
|
649
|
-
did: payload.did,
|
|
650
|
-
manifestContentId: payload.manifestContentId,
|
|
651
|
-
createdAt: payload.createdAt,
|
|
652
|
-
signerKeyId: kid,
|
|
653
|
-
beaconCID
|
|
654
|
-
};
|
|
655
|
-
};
|
|
656
|
-
|
|
657
697
|
// src/chain/countersign.ts
|
|
658
698
|
var signCountersignature = async (input) => {
|
|
659
699
|
const encoded = await dagCborCanonicalEncode(input.payload);
|
|
@@ -697,7 +737,8 @@ var verifyCountersignature = async (input) => {
|
|
|
697
737
|
return {
|
|
698
738
|
countersignCID,
|
|
699
739
|
witnessDID: payload.did,
|
|
700
|
-
targetCID: payload.targetCID
|
|
740
|
+
targetCID: payload.targetCID,
|
|
741
|
+
...payload.relation !== void 0 ? { relation: payload.relation } : {}
|
|
701
742
|
};
|
|
702
743
|
};
|
|
703
744
|
|
|
@@ -813,25 +854,35 @@ var verifyRevocation = async (input) => {
|
|
|
813
854
|
};
|
|
814
855
|
|
|
815
856
|
export {
|
|
857
|
+
MAX_SERVICES_ENTRIES,
|
|
858
|
+
MAX_SERVICES_PAYLOAD_SIZE,
|
|
859
|
+
MAX_OPERATION_SIZE,
|
|
816
860
|
MultikeyPublicKey,
|
|
861
|
+
CONTENT_ID_ANCHOR_RE,
|
|
862
|
+
ARTIFACT_CID_ANCHOR_RE,
|
|
863
|
+
ServiceEntry,
|
|
864
|
+
ServicesArray,
|
|
817
865
|
IdentityOperation,
|
|
818
866
|
VerifiedIdentity,
|
|
819
867
|
ContentOperation,
|
|
820
|
-
BeaconPayload,
|
|
821
868
|
MAX_ARTIFACT_PAYLOAD_SIZE,
|
|
822
869
|
ArtifactPayload,
|
|
823
870
|
CountersignPayload,
|
|
824
871
|
RevocationPayload,
|
|
825
872
|
deriveChainIdentifier,
|
|
826
873
|
deriveContentId,
|
|
874
|
+
assertServicesWithinCap,
|
|
875
|
+
classifyAnchor,
|
|
876
|
+
RECOGNIZED_SERVICE_TYPES,
|
|
877
|
+
isRecognizedServiceType,
|
|
878
|
+
relayEndpoints,
|
|
879
|
+
anchorsByLabel,
|
|
827
880
|
signIdentityOperation,
|
|
828
881
|
verifyIdentityChain,
|
|
829
882
|
verifyIdentityExtensionFromTrustedState,
|
|
830
883
|
signContentOperation,
|
|
831
884
|
verifyContentChain,
|
|
832
885
|
verifyContentExtensionFromTrustedState,
|
|
833
|
-
signBeacon,
|
|
834
|
-
verifyBeacon,
|
|
835
886
|
signCountersignature,
|
|
836
887
|
verifyCountersignature,
|
|
837
888
|
signArtifact,
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { V as VerifiedIdentity } from '../schemas-
|
|
2
|
+
import { V as VerifiedIdentity } from '../schemas-Bb_9P8_s.js';
|
|
3
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-hop 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;
|
|
4
15
|
/** Single attenuation entry — resource + action pair */
|
|
5
16
|
declare const Attenuation: z.ZodObject<{
|
|
6
17
|
resource: z.ZodString;
|
|
7
18
|
action: z.ZodString;
|
|
8
|
-
}, z.core.$
|
|
19
|
+
}, z.core.$loose>;
|
|
9
20
|
type Attenuation = z.infer<typeof Attenuation>;
|
|
10
21
|
/** DFOS credential payload — UCAN-style authorization token */
|
|
11
22
|
declare const DFOSCredentialPayload: z.ZodObject<{
|
|
@@ -16,11 +27,11 @@ declare const DFOSCredentialPayload: z.ZodObject<{
|
|
|
16
27
|
att: z.ZodArray<z.ZodObject<{
|
|
17
28
|
resource: z.ZodString;
|
|
18
29
|
action: z.ZodString;
|
|
19
|
-
}, z.core.$
|
|
30
|
+
}, z.core.$loose>>;
|
|
20
31
|
prf: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
21
32
|
exp: z.ZodNumber;
|
|
22
33
|
iat: z.ZodNumber;
|
|
23
|
-
}, z.core.$
|
|
34
|
+
}, z.core.$loose>;
|
|
24
35
|
type DFOSCredentialPayload = z.infer<typeof DFOSCredentialPayload>;
|
|
25
36
|
/** Claims for a DID-signed auth token (relay AuthN) */
|
|
26
37
|
declare const AuthTokenClaims: z.ZodObject<{
|
|
@@ -29,7 +40,7 @@ declare const AuthTokenClaims: z.ZodObject<{
|
|
|
29
40
|
aud: z.ZodString;
|
|
30
41
|
exp: z.ZodNumber;
|
|
31
42
|
iat: z.ZodNumber;
|
|
32
|
-
}, z.core.$
|
|
43
|
+
}, z.core.$loose>;
|
|
33
44
|
type AuthTokenClaims = z.infer<typeof AuthTokenClaims>;
|
|
34
45
|
|
|
35
46
|
interface AuthTokenCreateOptions {
|
|
@@ -200,4 +211,4 @@ declare class CredentialVerificationError extends Error {
|
|
|
200
211
|
constructor(message: string);
|
|
201
212
|
}
|
|
202
213
|
|
|
203
|
-
export { Attenuation, AuthTokenClaims, type AuthTokenCreateOptions, AuthTokenVerificationError, type AuthTokenVerifyOptions, CredentialVerificationError, DFOSCredentialPayload, type VerifiedAuthToken, type VerifiedDFOSCredential, type VerifiedDelegationChain, createAuthToken, createDFOSCredential, decodeDFOSCredentialUnsafe, isAttenuated, matchesResource, verifyAuthToken, verifyDFOSCredential, verifyDelegationChain };
|
|
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 };
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
AuthTokenVerificationError,
|
|
5
5
|
CredentialVerificationError,
|
|
6
6
|
DFOSCredentialPayload,
|
|
7
|
+
MAX_CREDENTIAL_SIZE,
|
|
7
8
|
createAuthToken,
|
|
8
9
|
createDFOSCredential,
|
|
9
10
|
decodeDFOSCredentialUnsafe,
|
|
@@ -12,14 +13,15 @@ import {
|
|
|
12
13
|
verifyAuthToken,
|
|
13
14
|
verifyDFOSCredential,
|
|
14
15
|
verifyDelegationChain
|
|
15
|
-
} from "../chunk-
|
|
16
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-J3XXF6F5.js";
|
|
17
|
+
import "../chunk-4QQ5HK5M.js";
|
|
17
18
|
export {
|
|
18
19
|
Attenuation,
|
|
19
20
|
AuthTokenClaims,
|
|
20
21
|
AuthTokenVerificationError,
|
|
21
22
|
CredentialVerificationError,
|
|
22
23
|
DFOSCredentialPayload,
|
|
24
|
+
MAX_CREDENTIAL_SIZE,
|
|
23
25
|
createAuthToken,
|
|
24
26
|
createDFOSCredential,
|
|
25
27
|
decodeDFOSCredentialUnsafe,
|
package/dist/crypto/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { JwsHeader, JwsVerificationError, JwtClaims, JwtCreateOptions, JwtHeader, JwtVerificationError, JwtVerifyOptions, PrefixedID, assertJwsProfile, base64urlDecode, base64urlEncode, createJws, createJwt, createNewEd25519Keypair, dagCborCanonicalEncode, decodeJwsUnsafe, decodeJwtUnsafe, generateId, generateIdNoPrefix, importEd25519Keypair, isCanonicallyEqual, isValidEd25519Signature, isValidId, normalizedId, parseDagCborCID, signPayloadEd25519, verifyJws, verifyJwt } from './crypto/index.js';
|
|
2
|
-
export { A as
|
|
3
|
-
export { ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC,
|
|
4
|
-
export { Attenuation, AuthTokenClaims, AuthTokenCreateOptions, AuthTokenVerificationError, AuthTokenVerifyOptions, CredentialVerificationError, DFOSCredentialPayload, VerifiedAuthToken, VerifiedDFOSCredential, VerifiedDelegationChain, createAuthToken, createDFOSCredential, decodeDFOSCredentialUnsafe, isAttenuated, matchesResource, verifyAuthToken, verifyDFOSCredential, verifyDelegationChain } from './credentials/index.js';
|
|
2
|
+
export { A as ARTIFACT_CID_ANCHOR_RE, a as ArtifactPayload, C as CONTENT_ID_ANCHOR_RE, b as ContentOperation, c as CountersignPayload, I as IdentityOperation, M as MAX_ARTIFACT_PAYLOAD_SIZE, d as MAX_OPERATION_SIZE, e as MAX_SERVICES_ENTRIES, f as MAX_SERVICES_PAYLOAD_SIZE, g as MultikeyPublicKey, R as RevocationPayload, S as ServiceEntry, h as ServicesArray, i as Signer, V as VerifiedIdentity } from './schemas-Bb_9P8_s.js';
|
|
3
|
+
export { AnchorKind, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, RECOGNIZED_SERVICE_TYPES, VerifiedArtifact, VerifiedContentChain, VerifiedCountersignature, VerifiedRevocation, anchorsByLabel, assertServicesWithinCap, classifyAnchor, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation } from './chain/index.js';
|
|
4
|
+
export { Attenuation, AuthTokenClaims, AuthTokenCreateOptions, AuthTokenVerificationError, AuthTokenVerifyOptions, CredentialVerificationError, DFOSCredentialPayload, MAX_CREDENTIAL_SIZE, VerifiedAuthToken, VerifiedDFOSCredential, VerifiedDelegationChain, createAuthToken, createDFOSCredential, decodeDFOSCredentialUnsafe, isAttenuated, matchesResource, verifyAuthToken, verifyDFOSCredential, verifyDelegationChain } from './credentials/index.js';
|
|
5
5
|
import 'multiformats';
|
|
6
6
|
import 'multiformats/cid';
|
|
7
7
|
import 'zod';
|