@metalabel/dfos-protocol 0.43.0 → 0.45.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/dist/chain/index.d.ts +14 -4
- package/dist/chain/index.js +8 -1
- package/dist/chunk-JVSC67DC.js +981 -0
- package/dist/{chunk-4YBXPYEU.js → chunk-ZRA7FRBE.js} +248 -28
- package/dist/credentials/index.d.ts +1 -1
- package/dist/{dfos-credential-X6uvPIth.d.ts → dfos-credential-BtiYPqBT.d.ts} +118 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +24 -2
- package/dist/key-proof/index.d.ts +202 -18
- package/dist/key-proof/index.js +17 -1
- package/examples/identity-restore.json +3 -3
- package/examples/identity-rotation.json +1 -1
- package/package.json +3 -2
- package/dist/chunk-WCYN7BV7.js +0 -195
|
@@ -5,6 +5,12 @@ import {
|
|
|
5
5
|
verifyDFOSCredential,
|
|
6
6
|
verifyDelegationChain
|
|
7
7
|
} from "./chunk-D4IZXFPM.js";
|
|
8
|
+
import {
|
|
9
|
+
KEY_ADD_JWS_TYP,
|
|
10
|
+
KEY_ROLES,
|
|
11
|
+
unsafeKeyProofSubject,
|
|
12
|
+
verifyChainKeyProof
|
|
13
|
+
} from "./chunk-JVSC67DC.js";
|
|
8
14
|
import {
|
|
9
15
|
decodeMultikey
|
|
10
16
|
} from "./chunk-IDVYITX7.js";
|
|
@@ -22,6 +28,7 @@ import {
|
|
|
22
28
|
// src/chain/schemas.ts
|
|
23
29
|
import { z } from "zod";
|
|
24
30
|
var MAX_KEYS_PER_ROLE = 256;
|
|
31
|
+
var MAX_KEY_PROOFS = 256;
|
|
25
32
|
var MAX_RELATION = 64;
|
|
26
33
|
var MAX_SERVICES_ENTRIES = 256;
|
|
27
34
|
var MAX_SERVICES_PAYLOAD_SIZE = 32768;
|
|
@@ -90,7 +97,28 @@ var IdentityUpdate = z.looseObject({
|
|
|
90
97
|
controllerKeys: z.array(MultikeyPublicKey).min(1, "update must have at least one controller key").max(MAX_KEYS_PER_ROLE),
|
|
91
98
|
// Full-state: an update REPLACES the entire services set (omit to clear).
|
|
92
99
|
services: ServicesArray.optional(),
|
|
93
|
-
createdAt: Iso8601
|
|
100
|
+
createdAt: Iso8601,
|
|
101
|
+
/**
|
|
102
|
+
* POSSESSION PROOFS FOR THE KEYS THIS OPERATION INTRODUCES — compact key-proof
|
|
103
|
+
* JWS strings (specs/KEY-PROOF.md), each signed by the key it speaks for.
|
|
104
|
+
*
|
|
105
|
+
* Optional, and optional in the CID-neutral sense: omitting it encodes
|
|
106
|
+
* identically to an operation that never had it (undefined strips under
|
|
107
|
+
* canonical CBOR), so the overwhelming majority of updates — the ones that
|
|
108
|
+
* merely replay keys already in effective state — carry nothing. Proofs are
|
|
109
|
+
* never replayed forward with the keys; full-state carriage applies to key
|
|
110
|
+
* ARRAYS, not to the evidence that admitted them.
|
|
111
|
+
*
|
|
112
|
+
* PRESENT ON `update` ONLY. A `create` needs none (its single genesis key is
|
|
113
|
+
* proved by signing genesis) and `delete`/`restore` introduce nothing, so an
|
|
114
|
+
* envelope on any of the three is a rejected operation, not an ignored member
|
|
115
|
+
* — see the carriage gate in identity-chain.ts.
|
|
116
|
+
*
|
|
117
|
+
* A MISSING OR BAD PROOF DOES NOT INVALIDATE THE OPERATION. It voids the
|
|
118
|
+
* key-role membership it would have admitted: the operation stands, the chain
|
|
119
|
+
* stands, and the key is simply absent from EFFECTIVE state for that role.
|
|
120
|
+
*/
|
|
121
|
+
keyProofs: z.array(z.string()).max(MAX_KEY_PROOFS).optional()
|
|
94
122
|
});
|
|
95
123
|
var IdentityDelete = z.looseObject({
|
|
96
124
|
version: z.literal(1),
|
|
@@ -110,6 +138,19 @@ var IdentityOperation = z.discriminatedUnion("type", [
|
|
|
110
138
|
IdentityDelete,
|
|
111
139
|
IdentityRestore
|
|
112
140
|
]);
|
|
141
|
+
var DeclaredKeyState = z.strictObject({
|
|
142
|
+
authKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
143
|
+
assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
144
|
+
controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE)
|
|
145
|
+
});
|
|
146
|
+
var VoidKeyMembership = z.strictObject({
|
|
147
|
+
/** The key as declared. */
|
|
148
|
+
key: MultikeyPublicKey,
|
|
149
|
+
/** The role it was declared into but is not effective for. */
|
|
150
|
+
role: z.enum(KEY_ROLES),
|
|
151
|
+
/** The CID of the operation whose declaration is currently unproved. */
|
|
152
|
+
operationCID: z.string()
|
|
153
|
+
});
|
|
113
154
|
var VerifiedIdentity = z.strictObject({
|
|
114
155
|
did: z.string(),
|
|
115
156
|
isDeleted: z.boolean(),
|
|
@@ -117,7 +158,35 @@ var VerifiedIdentity = z.strictObject({
|
|
|
117
158
|
assertKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
118
159
|
controllerKeys: z.array(MultikeyPublicKey).max(MAX_KEYS_PER_ROLE),
|
|
119
160
|
/** Resolved discovery vocabulary — projection of the winning head's services */
|
|
120
|
-
services: ServicesArray
|
|
161
|
+
services: ServicesArray,
|
|
162
|
+
/** What the chain declares, void memberships included. */
|
|
163
|
+
declared: DeclaredKeyState.optional(),
|
|
164
|
+
/** Declared memberships no proof admitted. Empty on a fully-proved chain. */
|
|
165
|
+
voidKeys: z.array(VoidKeyMembership).optional(),
|
|
166
|
+
/**
|
|
167
|
+
* HAS-EVER-PROVED: the union of every effective key state this chain has held,
|
|
168
|
+
* across its whole history. Monotonic — a key that was proved into a role and
|
|
169
|
+
* later removed stays here forever, because the fact it names is that the
|
|
170
|
+
* holder once demonstrated possession, and that does not become untrue.
|
|
171
|
+
*
|
|
172
|
+
* TWO SURFACES NEED EXACTLY THIS, and both are wrong without it:
|
|
173
|
+
*
|
|
174
|
+
* - THE `key=` REVERSE INDEX, which is the one-key-one-DID oracle. A holder
|
|
175
|
+
* asks it before signing a key proof, and refuses when some chain already
|
|
176
|
+
* proved the key — because proving one key into two chains publishes an
|
|
177
|
+
* irreversible public link between them. A DECLARATION publishes no such
|
|
178
|
+
* link: anyone can write anyone's public key into their own chain, so
|
|
179
|
+
* indexing declarations would let a stranger burn a key they do not hold,
|
|
180
|
+
* by writing it into a chain and making every future ceremony refuse it.
|
|
181
|
+
* - HISTORICAL KEY RESOLUTION, which verifies long-lived artifacts across
|
|
182
|
+
* rotations. A credential signed by a key that was proved and later rotated
|
|
183
|
+
* out must still verify; one signed by a key no chain ever proved must not.
|
|
184
|
+
*
|
|
185
|
+
* Computed during the walk, where the fold already runs, so consumers stop
|
|
186
|
+
* re-deriving it from the raw log under a declared-state rule that quietly
|
|
187
|
+
* disagrees with this one.
|
|
188
|
+
*/
|
|
189
|
+
provedKeys: DeclaredKeyState.optional()
|
|
121
190
|
});
|
|
122
191
|
var ContentCreate = z.looseObject({
|
|
123
192
|
version: z.literal(1),
|
|
@@ -230,6 +299,99 @@ var anchorsByLabel = (services, label) => services.filter(
|
|
|
230
299
|
);
|
|
231
300
|
|
|
232
301
|
// src/chain/identity-chain.ts
|
|
302
|
+
var ROLE_ARRAY = {
|
|
303
|
+
auth: "authKeys",
|
|
304
|
+
assert: "assertKeys",
|
|
305
|
+
controller: "controllerKeys"
|
|
306
|
+
};
|
|
307
|
+
var emptyKeyState = () => ({
|
|
308
|
+
authKeys: [],
|
|
309
|
+
assertKeys: [],
|
|
310
|
+
controllerKeys: []
|
|
311
|
+
});
|
|
312
|
+
var keyStateOf = (op) => ({
|
|
313
|
+
authKeys: op.authKeys,
|
|
314
|
+
assertKeys: op.assertKeys,
|
|
315
|
+
controllerKeys: op.controllerKeys
|
|
316
|
+
});
|
|
317
|
+
var fullyProved = (state) => ({
|
|
318
|
+
authKeys: [...state.authKeys],
|
|
319
|
+
assertKeys: [...state.assertKeys],
|
|
320
|
+
controllerKeys: [...state.controllerKeys]
|
|
321
|
+
});
|
|
322
|
+
var unionProved = (into, next) => {
|
|
323
|
+
const merged = emptyKeyState();
|
|
324
|
+
for (const role of KEY_ROLES) {
|
|
325
|
+
const seen = /* @__PURE__ */ new Map();
|
|
326
|
+
for (const key of [...into[ROLE_ARRAY[role]], ...next[ROLE_ARRAY[role]]]) {
|
|
327
|
+
if (!seen.has(key.id)) seen.set(key.id, key);
|
|
328
|
+
}
|
|
329
|
+
merged[ROLE_ARRAY[role]] = [...seen.values()];
|
|
330
|
+
}
|
|
331
|
+
return merged;
|
|
332
|
+
};
|
|
333
|
+
var foldEffectiveKeyState = (input) => {
|
|
334
|
+
const carried = (role, key) => input.priorEffective[ROLE_ARRAY[role]].some((prior) => prior.id === key.id);
|
|
335
|
+
const introduced = /* @__PURE__ */ new Map();
|
|
336
|
+
for (const role of KEY_ROLES) {
|
|
337
|
+
for (const key of input.declared[ROLE_ARRAY[role]]) {
|
|
338
|
+
if (carried(role, key)) continue;
|
|
339
|
+
const entry = introduced.get(key.publicKeyMultibase) ?? { key, roles: /* @__PURE__ */ new Set() };
|
|
340
|
+
entry.roles.add(role);
|
|
341
|
+
introduced.set(key.publicKeyMultibase, entry);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const proved = /* @__PURE__ */ new Map();
|
|
345
|
+
for (const jws of input.keyProofs) {
|
|
346
|
+
const subject = unsafeKeyProofSubject(jws);
|
|
347
|
+
if (subject === null) continue;
|
|
348
|
+
const candidate = introduced.get(subject);
|
|
349
|
+
if (candidate === void 0) continue;
|
|
350
|
+
for (const role of candidate.roles) {
|
|
351
|
+
try {
|
|
352
|
+
verifyChainKeyProof(jws, {
|
|
353
|
+
expectedTyp: KEY_ADD_JWS_TYP,
|
|
354
|
+
did: input.did,
|
|
355
|
+
prevCID: input.previousOperationCID,
|
|
356
|
+
publicKeyMultibase: candidate.key.publicKeyMultibase,
|
|
357
|
+
role
|
|
358
|
+
});
|
|
359
|
+
} catch {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const covered = proved.get(subject) ?? /* @__PURE__ */ new Set();
|
|
363
|
+
covered.add(role);
|
|
364
|
+
proved.set(subject, covered);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const effective = emptyKeyState();
|
|
368
|
+
const voidKeys = [];
|
|
369
|
+
for (const role of KEY_ROLES) {
|
|
370
|
+
for (const key of input.declared[ROLE_ARRAY[role]]) {
|
|
371
|
+
if (carried(role, key) || proved.get(key.publicKeyMultibase)?.has(role) === true) {
|
|
372
|
+
effective[ROLE_ARRAY[role]].push(key);
|
|
373
|
+
} else {
|
|
374
|
+
voidKeys.push({ key, role, operationCID: input.operationCID });
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return { effective, voidKeys };
|
|
379
|
+
};
|
|
380
|
+
var assertSingleKeyGenesis = (op) => {
|
|
381
|
+
if (op.authKeys.length !== 1 || op.assertKeys.length !== 1 || op.controllerKeys.length !== 1) {
|
|
382
|
+
throw new Error("create must declare exactly one key in each of auth, assert and controller");
|
|
383
|
+
}
|
|
384
|
+
const [auth, assert, controller] = [op.authKeys[0], op.assertKeys[0], op.controllerKeys[0]];
|
|
385
|
+
const same = (a, b) => a.id === b.id && a.type === b.type && a.publicKeyMultibase === b.publicKeyMultibase;
|
|
386
|
+
if (!same(auth, assert) || !same(auth, controller)) {
|
|
387
|
+
throw new Error("create must declare the SAME key in auth, assert and controller");
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
var assertKeyProofCarriage = (op) => {
|
|
391
|
+
if (op.type !== "update" && "keyProofs" in op) {
|
|
392
|
+
throw new Error(`keyProofs is valid on update only, not on ${op.type}`);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
233
395
|
var signIdentityOperation = async (input) => {
|
|
234
396
|
const kid = input.identityDID ? `${input.identityDID}#${input.keyId}` : input.keyId;
|
|
235
397
|
const encoded = await dagCborCanonicalEncode(input.operation);
|
|
@@ -248,9 +410,13 @@ var verifyIdentityChain = async (input) => {
|
|
|
248
410
|
isDeleted: false,
|
|
249
411
|
previousOperationCID: null,
|
|
250
412
|
lastCreatedAt: null,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
413
|
+
/** What the chain SAYS — the arbiter of signer validity. */
|
|
414
|
+
declared: emptyKeyState(),
|
|
415
|
+
/** What possession PROVED — what consumers get. */
|
|
416
|
+
effective: emptyKeyState(),
|
|
417
|
+
/** Every membership possession has EVER proved. Monotonic. */
|
|
418
|
+
provedKeys: emptyKeyState(),
|
|
419
|
+
voidKeys: [],
|
|
254
420
|
services: [],
|
|
255
421
|
seenKeys: /* @__PURE__ */ new Map()
|
|
256
422
|
};
|
|
@@ -278,13 +444,20 @@ var verifyIdentityChain = async (input) => {
|
|
|
278
444
|
if (idx > 0 && op.type === "create") {
|
|
279
445
|
throw new Error(`log[${idx}]: create can only be the first operation`);
|
|
280
446
|
}
|
|
447
|
+
try {
|
|
448
|
+
assertKeyProofCarriage(op);
|
|
449
|
+
} catch (e) {
|
|
450
|
+
throw new Error(`log[${idx}]: ${e.message}`);
|
|
451
|
+
}
|
|
281
452
|
if (op.type === "create") {
|
|
282
|
-
|
|
283
|
-
|
|
453
|
+
try {
|
|
454
|
+
assertSingleKeyGenesis(op);
|
|
455
|
+
} catch (e) {
|
|
456
|
+
throw new Error(`log[${idx}]: ${e.message}`);
|
|
284
457
|
}
|
|
285
|
-
state.
|
|
286
|
-
state.
|
|
287
|
-
state.
|
|
458
|
+
state.declared = keyStateOf(op);
|
|
459
|
+
state.effective = fullyProved(state.declared);
|
|
460
|
+
state.provedKeys = fullyProved(state.declared);
|
|
288
461
|
state.services = op.services ?? [];
|
|
289
462
|
}
|
|
290
463
|
if (op.type !== "create") {
|
|
@@ -298,7 +471,11 @@ var verifyIdentityChain = async (input) => {
|
|
|
298
471
|
}
|
|
299
472
|
if (op.type === "create" || op.type === "update") {
|
|
300
473
|
const incomingKeys = [...op.authKeys, ...op.assertKeys, ...op.controllerKeys];
|
|
301
|
-
const currentKeys = [
|
|
474
|
+
const currentKeys = [
|
|
475
|
+
...state.declared.authKeys,
|
|
476
|
+
...state.declared.assertKeys,
|
|
477
|
+
...state.declared.controllerKeys
|
|
478
|
+
];
|
|
302
479
|
for (const k of [...currentKeys, ...incomingKeys]) {
|
|
303
480
|
const existing = state.seenKeys.get(k.id);
|
|
304
481
|
if (!existing) {
|
|
@@ -348,7 +525,7 @@ var verifyIdentityChain = async (input) => {
|
|
|
348
525
|
throw new Error(`log[${idx}]: non-genesis op kid must be DID URL, got bare key ID`);
|
|
349
526
|
}
|
|
350
527
|
}
|
|
351
|
-
const signingKey = state.controllerKeys.find((k) => k.id === signingKeyId);
|
|
528
|
+
const signingKey = state.declared.controllerKeys.find((k) => k.id === signingKeyId);
|
|
352
529
|
if (!signingKey) {
|
|
353
530
|
throw new Error(`log[${idx}]: kid references unknown key: ${signingKeyId}`);
|
|
354
531
|
}
|
|
@@ -361,6 +538,7 @@ var verifyIdentityChain = async (input) => {
|
|
|
361
538
|
if (state.did === void 0) {
|
|
362
539
|
state.did = deriveChainIdentifier(encoded.cid.bytes, input.didPrefix);
|
|
363
540
|
}
|
|
541
|
+
const did = state.did;
|
|
364
542
|
if (idx > 0 && kid.includes("#")) {
|
|
365
543
|
const didFromKid = kid.substring(0, kid.indexOf("#"));
|
|
366
544
|
if (didFromKid !== state.did) {
|
|
@@ -372,15 +550,25 @@ var verifyIdentityChain = async (input) => {
|
|
|
372
550
|
switch (op.type) {
|
|
373
551
|
case "create":
|
|
374
552
|
break;
|
|
375
|
-
case "update":
|
|
553
|
+
case "update": {
|
|
376
554
|
if (op.controllerKeys.length === 0) {
|
|
377
555
|
throw new Error(`log[${idx}]: update must have at least one controller key`);
|
|
378
556
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
557
|
+
const folded = foldEffectiveKeyState({
|
|
558
|
+
did,
|
|
559
|
+
declared: keyStateOf(op),
|
|
560
|
+
priorEffective: state.effective,
|
|
561
|
+
previousOperationCID: op.previousOperationCID,
|
|
562
|
+
operationCID,
|
|
563
|
+
keyProofs: op.keyProofs ?? []
|
|
564
|
+
});
|
|
565
|
+
state.declared = keyStateOf(op);
|
|
566
|
+
state.effective = folded.effective;
|
|
567
|
+
state.provedKeys = unionProved(state.provedKeys, folded.effective);
|
|
568
|
+
state.voidKeys = folded.voidKeys;
|
|
382
569
|
state.services = op.services ?? [];
|
|
383
570
|
break;
|
|
571
|
+
}
|
|
384
572
|
case "delete":
|
|
385
573
|
state.isDeleted = true;
|
|
386
574
|
break;
|
|
@@ -393,14 +581,21 @@ var verifyIdentityChain = async (input) => {
|
|
|
393
581
|
return {
|
|
394
582
|
did: state.did,
|
|
395
583
|
isDeleted: state.isDeleted,
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
584
|
+
// EFFECTIVE state is what a consumer gets. A void key never resolves.
|
|
585
|
+
authKeys: state.effective.authKeys,
|
|
586
|
+
assertKeys: state.effective.assertKeys,
|
|
587
|
+
controllerKeys: state.effective.controllerKeys,
|
|
588
|
+
services: state.services,
|
|
589
|
+
declared: state.declared,
|
|
590
|
+
voidKeys: state.voidKeys,
|
|
591
|
+
provedKeys: state.provedKeys
|
|
400
592
|
};
|
|
401
593
|
};
|
|
402
594
|
var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
403
595
|
const { currentState, headCID, lastCreatedAt, newOp } = input;
|
|
596
|
+
const priorEffective = keyStateOf(currentState);
|
|
597
|
+
const priorDeclared = currentState.declared ?? priorEffective;
|
|
598
|
+
const priorProved = currentState.provedKeys ?? priorEffective;
|
|
404
599
|
const decoded = decodeJwsUnsafe(newOp);
|
|
405
600
|
if (!decoded) throw new Error("failed to decode JWS");
|
|
406
601
|
const result = IdentityOperation.safeParse(decoded.payload);
|
|
@@ -409,6 +604,7 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
409
604
|
throw new Error(messages);
|
|
410
605
|
}
|
|
411
606
|
const op = result.data;
|
|
607
|
+
assertKeyProofCarriage(op);
|
|
412
608
|
if (currentState.isDeleted && op.type !== "restore") {
|
|
413
609
|
throw new Error("cannot extend a deleted identity");
|
|
414
610
|
}
|
|
@@ -444,7 +640,7 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
444
640
|
if (kidDid !== currentState.did) {
|
|
445
641
|
throw new Error("kid DID does not match identity DID");
|
|
446
642
|
}
|
|
447
|
-
const signingKey =
|
|
643
|
+
const signingKey = priorDeclared.controllerKeys.find((k) => k.id === signingKeyId);
|
|
448
644
|
if (!signingKey) {
|
|
449
645
|
throw new Error(`kid references unknown key: ${signingKeyId}`);
|
|
450
646
|
}
|
|
@@ -465,15 +661,30 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
465
661
|
}
|
|
466
662
|
const newState = (() => {
|
|
467
663
|
switch (op.type) {
|
|
468
|
-
case "update":
|
|
664
|
+
case "update": {
|
|
665
|
+
const declared = keyStateOf(op);
|
|
666
|
+
const folded = foldEffectiveKeyState({
|
|
667
|
+
did: currentState.did,
|
|
668
|
+
declared,
|
|
669
|
+
priorEffective,
|
|
670
|
+
previousOperationCID: op.previousOperationCID,
|
|
671
|
+
operationCID,
|
|
672
|
+
keyProofs: op.keyProofs ?? []
|
|
673
|
+
});
|
|
469
674
|
return {
|
|
470
675
|
did: currentState.did,
|
|
471
676
|
isDeleted: false,
|
|
472
|
-
authKeys:
|
|
473
|
-
assertKeys:
|
|
474
|
-
controllerKeys:
|
|
475
|
-
services: op.services ?? []
|
|
677
|
+
authKeys: folded.effective.authKeys,
|
|
678
|
+
assertKeys: folded.effective.assertKeys,
|
|
679
|
+
controllerKeys: folded.effective.controllerKeys,
|
|
680
|
+
services: op.services ?? [],
|
|
681
|
+
declared,
|
|
682
|
+
voidKeys: folded.voidKeys,
|
|
683
|
+
provedKeys: unionProved(priorProved, folded.effective)
|
|
476
684
|
};
|
|
685
|
+
}
|
|
686
|
+
// delete and restore introduce nothing, so both key states — and the void
|
|
687
|
+
// list — travel forward untouched.
|
|
477
688
|
case "delete":
|
|
478
689
|
return {
|
|
479
690
|
did: currentState.did,
|
|
@@ -481,7 +692,10 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
481
692
|
authKeys: currentState.authKeys,
|
|
482
693
|
assertKeys: currentState.assertKeys,
|
|
483
694
|
controllerKeys: currentState.controllerKeys,
|
|
484
|
-
services: currentState.services
|
|
695
|
+
services: currentState.services,
|
|
696
|
+
declared: priorDeclared,
|
|
697
|
+
voidKeys: currentState.voidKeys ?? [],
|
|
698
|
+
provedKeys: priorProved
|
|
485
699
|
};
|
|
486
700
|
case "restore":
|
|
487
701
|
return {
|
|
@@ -490,7 +704,10 @@ var verifyIdentityExtensionFromTrustedState = async (input) => {
|
|
|
490
704
|
authKeys: currentState.authKeys,
|
|
491
705
|
assertKeys: currentState.assertKeys,
|
|
492
706
|
controllerKeys: currentState.controllerKeys,
|
|
493
|
-
services: currentState.services
|
|
707
|
+
services: currentState.services,
|
|
708
|
+
declared: priorDeclared,
|
|
709
|
+
voidKeys: currentState.voidKeys ?? [],
|
|
710
|
+
provedKeys: priorProved
|
|
494
711
|
};
|
|
495
712
|
}
|
|
496
713
|
})();
|
|
@@ -1339,6 +1556,7 @@ var assertCanonicalSignRequestPayload = (payloadTyp, payloadBytes, context) => {
|
|
|
1339
1556
|
};
|
|
1340
1557
|
|
|
1341
1558
|
export {
|
|
1559
|
+
MAX_KEY_PROOFS,
|
|
1342
1560
|
MAX_SERVICES_ENTRIES,
|
|
1343
1561
|
MAX_SERVICES_PAYLOAD_SIZE,
|
|
1344
1562
|
MAX_OPERATION_SIZE,
|
|
@@ -1350,6 +1568,8 @@ export {
|
|
|
1350
1568
|
Iso8601,
|
|
1351
1569
|
parseProtocolTimestampUnix,
|
|
1352
1570
|
IdentityOperation,
|
|
1571
|
+
DeclaredKeyState,
|
|
1572
|
+
VoidKeyMembership,
|
|
1353
1573
|
VerifiedIdentity,
|
|
1354
1574
|
ContentOperation,
|
|
1355
1575
|
MAX_ARTIFACT_PAYLOAD_SIZE,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { b as Attenuation, e as CredentialVerificationError, D as DFOSCredentialPayload,
|
|
1
|
+
export { b as Attenuation, e as CredentialVerificationError, D as DFOSCredentialPayload, i as MAX_CREDENTIAL_SIZE, R as RevocationChecker, V as VerifiedDFOSCredential, v as VerifiedDelegationChain, y as createDFOSCredential, z as decodeDFOSCredentialUnsafe, B as isAttenuated, E as matchesResource, G as verifyDFOSCredential, H as verifyDelegationChain } from '../dfos-credential-BtiYPqBT.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -2,6 +2,15 @@ import { z } from 'zod';
|
|
|
2
2
|
|
|
3
3
|
/** Function that signs a byte array and returns a signature */
|
|
4
4
|
type Signer = (message: Uint8Array) => Promise<Uint8Array>;
|
|
5
|
+
/**
|
|
6
|
+
* Max number of key-proof envelopes an update may carry — a cardinality ceiling
|
|
7
|
+
* matching MAX_KEYS_PER_ROLE, since an operation never needs more envelopes than
|
|
8
|
+
* it introduces keys. The operation-size cap is still the real byte arbiter; this
|
|
9
|
+
* bounds the walk's per-operation verification work so a single 64 KiB operation
|
|
10
|
+
* cannot ask a verifier for an unbounded number of signature checks.
|
|
11
|
+
* VALIDITY-determining: MUST match maxKeyProofs in the Go reference.
|
|
12
|
+
*/
|
|
13
|
+
declare const MAX_KEY_PROOFS = 256;
|
|
5
14
|
/**
|
|
6
15
|
* Max number of service entries in an identity's services state — a generous
|
|
7
16
|
* cardinality ceiling on resolution fan-out. Individual entry fields are NOT
|
|
@@ -143,6 +152,7 @@ declare const IdentityOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
143
152
|
type: z.ZodString;
|
|
144
153
|
}, z.core.$catchall<z.ZodUnknown>>>>;
|
|
145
154
|
createdAt: z.ZodISODateTime;
|
|
155
|
+
keyProofs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
146
156
|
}, z.core.$loose>, z.ZodObject<{
|
|
147
157
|
version: z.ZodLiteral<1>;
|
|
148
158
|
type: z.ZodLiteral<"delete">;
|
|
@@ -155,6 +165,66 @@ declare const IdentityOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
155
165
|
createdAt: z.ZodISODateTime;
|
|
156
166
|
}, z.core.$loose>], "type">;
|
|
157
167
|
type IdentityOperation = z.infer<typeof IdentityOperation>;
|
|
168
|
+
/**
|
|
169
|
+
* The key arrays exactly as the chain's operations DECLARE them, before any
|
|
170
|
+
* question of possession. Structural state: what the controller wrote.
|
|
171
|
+
*/
|
|
172
|
+
declare const DeclaredKeyState: z.ZodObject<{
|
|
173
|
+
authKeys: z.ZodArray<z.ZodObject<{
|
|
174
|
+
id: z.ZodString;
|
|
175
|
+
type: z.ZodLiteral<"Multikey">;
|
|
176
|
+
publicKeyMultibase: z.ZodString;
|
|
177
|
+
}, z.core.$loose>>;
|
|
178
|
+
assertKeys: z.ZodArray<z.ZodObject<{
|
|
179
|
+
id: z.ZodString;
|
|
180
|
+
type: z.ZodLiteral<"Multikey">;
|
|
181
|
+
publicKeyMultibase: z.ZodString;
|
|
182
|
+
}, z.core.$loose>>;
|
|
183
|
+
controllerKeys: z.ZodArray<z.ZodObject<{
|
|
184
|
+
id: z.ZodString;
|
|
185
|
+
type: z.ZodLiteral<"Multikey">;
|
|
186
|
+
publicKeyMultibase: z.ZodString;
|
|
187
|
+
}, z.core.$loose>>;
|
|
188
|
+
}, z.core.$strict>;
|
|
189
|
+
type DeclaredKeyState = z.infer<typeof DeclaredKeyState>;
|
|
190
|
+
/**
|
|
191
|
+
* ONE DECLARED-BUT-UNPROVED KEY-ROLE MEMBERSHIP. The chain says this key holds
|
|
192
|
+
* this role; no possession proof ever admitted it, so consumers do not see it.
|
|
193
|
+
*
|
|
194
|
+
* VOID IS NOT INVALID. The operation that declared it is valid, the chain is
|
|
195
|
+
* valid, and the membership is simply absent from effective state. Enumerating
|
|
196
|
+
* these loudly is the point: a controller who introduced a key without a proof
|
|
197
|
+
* has a chain that verifies and a key that does not resolve, and the only way
|
|
198
|
+
* they learn that is if tooling can see the list.
|
|
199
|
+
*/
|
|
200
|
+
declare const VoidKeyMembership: z.ZodObject<{
|
|
201
|
+
key: z.ZodObject<{
|
|
202
|
+
id: z.ZodString;
|
|
203
|
+
type: z.ZodLiteral<"Multikey">;
|
|
204
|
+
publicKeyMultibase: z.ZodString;
|
|
205
|
+
}, z.core.$loose>;
|
|
206
|
+
role: z.ZodEnum<{
|
|
207
|
+
auth: "auth";
|
|
208
|
+
assert: "assert";
|
|
209
|
+
controller: "controller";
|
|
210
|
+
}>;
|
|
211
|
+
operationCID: z.ZodString;
|
|
212
|
+
}, z.core.$strict>;
|
|
213
|
+
type VoidKeyMembership = z.infer<typeof VoidKeyMembership>;
|
|
214
|
+
/**
|
|
215
|
+
* THE VERIFIED IDENTITY. `authKeys`/`assertKeys`/`controllerKeys` are EFFECTIVE
|
|
216
|
+
* state — the memberships a possession proof actually admitted — because
|
|
217
|
+
* effective state is what every consumer wants: a void key must never resolve,
|
|
218
|
+
* never index, and never enter a has-ever surface.
|
|
219
|
+
*
|
|
220
|
+
* `declared` and `voidKeys` carry the structural half alongside it, so the
|
|
221
|
+
* surfaces that genuinely need "what does the chain SAY" can ask. There is
|
|
222
|
+
* exactly one such surface in the protocol: SIGNER VALIDITY, which stays
|
|
223
|
+
* declared-state-based on purpose (see identity-chain.ts). Both are optional
|
|
224
|
+
* because a caller may hand a hand-built state to the extension verifier;
|
|
225
|
+
* absent `declared` is read as "the arrays are also the declared arrays", which
|
|
226
|
+
* is exactly true for any chain with no void memberships.
|
|
227
|
+
*/
|
|
158
228
|
declare const VerifiedIdentity: z.ZodObject<{
|
|
159
229
|
did: z.ZodString;
|
|
160
230
|
isDeleted: z.ZodBoolean;
|
|
@@ -177,6 +247,53 @@ declare const VerifiedIdentity: z.ZodObject<{
|
|
|
177
247
|
id: z.ZodString;
|
|
178
248
|
type: z.ZodString;
|
|
179
249
|
}, z.core.$catchall<z.ZodUnknown>>>;
|
|
250
|
+
declared: z.ZodOptional<z.ZodObject<{
|
|
251
|
+
authKeys: z.ZodArray<z.ZodObject<{
|
|
252
|
+
id: z.ZodString;
|
|
253
|
+
type: z.ZodLiteral<"Multikey">;
|
|
254
|
+
publicKeyMultibase: z.ZodString;
|
|
255
|
+
}, z.core.$loose>>;
|
|
256
|
+
assertKeys: z.ZodArray<z.ZodObject<{
|
|
257
|
+
id: z.ZodString;
|
|
258
|
+
type: z.ZodLiteral<"Multikey">;
|
|
259
|
+
publicKeyMultibase: z.ZodString;
|
|
260
|
+
}, z.core.$loose>>;
|
|
261
|
+
controllerKeys: z.ZodArray<z.ZodObject<{
|
|
262
|
+
id: z.ZodString;
|
|
263
|
+
type: z.ZodLiteral<"Multikey">;
|
|
264
|
+
publicKeyMultibase: z.ZodString;
|
|
265
|
+
}, z.core.$loose>>;
|
|
266
|
+
}, z.core.$strict>>;
|
|
267
|
+
voidKeys: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
268
|
+
key: z.ZodObject<{
|
|
269
|
+
id: z.ZodString;
|
|
270
|
+
type: z.ZodLiteral<"Multikey">;
|
|
271
|
+
publicKeyMultibase: z.ZodString;
|
|
272
|
+
}, z.core.$loose>;
|
|
273
|
+
role: z.ZodEnum<{
|
|
274
|
+
auth: "auth";
|
|
275
|
+
assert: "assert";
|
|
276
|
+
controller: "controller";
|
|
277
|
+
}>;
|
|
278
|
+
operationCID: z.ZodString;
|
|
279
|
+
}, z.core.$strict>>>;
|
|
280
|
+
provedKeys: z.ZodOptional<z.ZodObject<{
|
|
281
|
+
authKeys: z.ZodArray<z.ZodObject<{
|
|
282
|
+
id: z.ZodString;
|
|
283
|
+
type: z.ZodLiteral<"Multikey">;
|
|
284
|
+
publicKeyMultibase: z.ZodString;
|
|
285
|
+
}, z.core.$loose>>;
|
|
286
|
+
assertKeys: z.ZodArray<z.ZodObject<{
|
|
287
|
+
id: z.ZodString;
|
|
288
|
+
type: z.ZodLiteral<"Multikey">;
|
|
289
|
+
publicKeyMultibase: z.ZodString;
|
|
290
|
+
}, z.core.$loose>>;
|
|
291
|
+
controllerKeys: z.ZodArray<z.ZodObject<{
|
|
292
|
+
id: z.ZodString;
|
|
293
|
+
type: z.ZodLiteral<"Multikey">;
|
|
294
|
+
publicKeyMultibase: z.ZodString;
|
|
295
|
+
}, z.core.$loose>>;
|
|
296
|
+
}, z.core.$strict>>;
|
|
180
297
|
}, z.core.$strict>;
|
|
181
298
|
type VerifiedIdentity = z.infer<typeof VerifiedIdentity>;
|
|
182
299
|
declare const ContentOperation: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -522,4 +639,4 @@ declare class CredentialVerificationError extends Error {
|
|
|
522
639
|
constructor(message: string);
|
|
523
640
|
}
|
|
524
641
|
|
|
525
|
-
export { ARTIFACT_CID_ANCHOR_RE as A,
|
|
642
|
+
export { ARTIFACT_CID_ANCHOR_RE as A, isAttenuated as B, CONTENT_ID_ANCHOR_RE as C, DFOSCredentialPayload as D, matchesResource as E, parseProtocolTimestampUnix as F, verifyDFOSCredential as G, verifyDelegationChain as H, 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, ContentOperation as c, CountersignPayload as d, CredentialVerificationError as e, CreditClaimPayload as f, DeclaredKeyState as g, Iso8601 as h, MAX_CREDENTIAL_SIZE as i, MAX_CREDIT_CLAIM_SIZE as j, MAX_KEY_PROOFS as k, MAX_OPERATION_SIZE as l, MAX_SERVICES_ENTRIES as m, MAX_SERVICES_PAYLOAD_SIZE as n, MAX_SIGN_REQUEST_PAYLOAD_SIZE as o, MAX_SIGN_REQUEST_SIZE as p, MultikeyPublicKey as q, RevocationPayload as r, ServicesArray as s, SignRequestPayload as t, type Signer as u, type VerifiedDelegationChain as v, VerifiedIdentity as w, VoidKeyMembership as x, createDFOSCredential as y, decodeDFOSCredentialUnsafe as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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, sha256, signPayloadEd25519, verifyJws, verifyJwt } from './crypto/index.js';
|
|
2
|
-
export { A as ARTIFACT_CID_ANCHOR_RE, a as ArtifactPayload, b as Attenuation, C as CONTENT_ID_ANCHOR_RE, c as ContentOperation, d as CountersignPayload, e as CredentialVerificationError, f as CreditClaimPayload, D as DFOSCredentialPayload, I as IdentityOperation,
|
|
2
|
+
export { A as ARTIFACT_CID_ANCHOR_RE, a as ArtifactPayload, b as Attenuation, C as CONTENT_ID_ANCHOR_RE, c as ContentOperation, d as CountersignPayload, e as CredentialVerificationError, f as CreditClaimPayload, D as DFOSCredentialPayload, g as DeclaredKeyState, I as IdentityOperation, h as Iso8601, M as MAX_ARTIFACT_PAYLOAD_SIZE, i as MAX_CREDENTIAL_SIZE, j as MAX_CREDIT_CLAIM_SIZE, k as MAX_KEY_PROOFS, l as MAX_OPERATION_SIZE, m as MAX_SERVICES_ENTRIES, n as MAX_SERVICES_PAYLOAD_SIZE, o as MAX_SIGN_REQUEST_PAYLOAD_SIZE, p as MAX_SIGN_REQUEST_SIZE, q as MultikeyPublicKey, R as RevocationChecker, r as RevocationPayload, S as ServiceEntry, s as ServicesArray, t as SignRequestPayload, u as Signer, V as VerifiedDFOSCredential, v as VerifiedDelegationChain, w as VerifiedIdentity, x as VoidKeyMembership, y as createDFOSCredential, z as decodeDFOSCredentialUnsafe, B as isAttenuated, E as matchesResource, F as parseProtocolTimestampUnix, G as verifyDFOSCredential, H as verifyDelegationChain } from './dfos-credential-BtiYPqBT.js';
|
|
3
3
|
export { AnchorKind, CreditClaimFailureReason, CreditClaimVerifyError, CreditEntry, CreditEntryState, ED25519_PRIV_MULTICODEC, ED25519_PUB_MULTICODEC, RECOGNIZED_SERVICE_TYPES, SignRequestFailureReason, SignRequestVerifyError, VerifiedArtifact, VerifiedContentChain, VerifiedCountersignature, VerifiedCreditClaim, VerifiedCreditEntry, VerifiedRevocation, VerifiedSignRequest, anchorsByLabel, assertCanonicalSignRequestPayload, assertServicesWithinCap, buildSignRequest, classifyAnchor, decodeMultikey, deriveChainIdentifier, deriveContentId, encodeEd25519Multikey, isRecognizedServiceType, relayEndpoints, signArtifact, signContentOperation, signCountersignature, signCreditClaim, signIdentityOperation, signRevocation, verifyArtifact, verifyContentChain, verifyContentExtensionFromTrustedState, verifyCountersignature, verifyCreditClaim, verifyCreditEntry, verifyIdentityChain, verifyIdentityExtensionFromTrustedState, verifyRevocation, verifySignRequest } from './chain/index.js';
|
|
4
4
|
export { ApiRequestVerifyError, DEFAULT_PROOF_SKEW_SECONDS, DEFAULT_PROOF_WINDOW_SECONDS, DFOS_AUTH_SCHEME, EMPTY_BODY_SHA256, IDENTITY_PROOF_JWS_TYP, IdentityProofPayload, MAX_BODY_BYTES, MAX_PROOF_FRESHNESS_SPAN_SECONDS, MAX_REQUEST_PROOF_SIZE, ParsedProofPayload, ProofEnvelopeInput, ProofExtraMembers, ProofPresenterState, REQUEST_PROOF_JWS_TYP, RequestProofFailurePhase, RequestProofFailureReason, RequestProofPayload, ResolveProofPresenter, SignApiIdentityRequestInput, SignApiRequestInput, VerifiedProofEnvelope, apiIdentitySigningInput, apiRequestSigningInput, assertProofVerifierConfig, buildApiAuthHeaders, buildApiIdentityHeaders, canonicalExtraMembers, invalidProof, misconfiguredProof, parseDfosAuthorization, sha256BodyHash, signApiIdentityRequest, signApiRequest, unverifiableProof, verifyIdentityProofEnvelope, verifyRequestProofEnvelope } from './credentials/index.js';
|
|
5
|
-
export { DEFAULT_KEY_PROOF_SKEW_SECONDS, KEY_ADD_JWS_TYP, KeyProofFailureReason, KeyProofPayload, KeyProofVerifyError, MAX_KEY_PROOF_SIZE, SignKeyProofInput, VerifiedKeyProof, VerifyKeyProofOptions, keyProofSigningInput, signKeyProof, verifyKeyProof } from './key-proof/index.js';
|
|
5
|
+
export { DEFAULT_KEY_PROOF_SKEW_SECONDS, KEY_ADD_JWS_TYP, KEY_ROLES, KeyProofFailureReason, KeyProofPayload, KeyProofVerifyError, KeyRole, MAX_KEY_PROOF_SIZE, SignKeyProofInput, VerifiedKeyProof, VerifyChainKeyProofOptions, VerifyKeyProofOptions, isCanonicalRoleSet, keyProofSigningInput, keyWordFingerprint, parseRoleSet, roleSetCovers, serializeRoleSet, signKeyProof, unsafeKeyProofSubject, verifyChainKeyProof, verifyKeyProof } from './key-proof/index.js';
|
|
6
6
|
export { FoldOperation, INDEX_V1_SCHEMA, IndexDelta, IndexDocument, IndexEntry, LwwDelta, OrderKey, byteCompare, compareHeadPreference, compareLinear, foldIndexV1, foldLwwMap, linearize } from './fold/index.js';
|
|
7
7
|
import 'multiformats';
|
|
8
8
|
import 'multiformats/cid';
|