@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.
@@ -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
- authKeys: [],
252
- assertKeys: [],
253
- controllerKeys: [],
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
- if (op.controllerKeys.length === 0) {
283
- throw new Error(`log[${idx}]: create must have at least one controller key`);
453
+ try {
454
+ assertSingleKeyGenesis(op);
455
+ } catch (e) {
456
+ throw new Error(`log[${idx}]: ${e.message}`);
284
457
  }
285
- state.authKeys = op.authKeys;
286
- state.assertKeys = op.assertKeys;
287
- state.controllerKeys = op.controllerKeys;
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 = [...state.authKeys, ...state.assertKeys, ...state.controllerKeys];
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
- state.authKeys = op.authKeys;
380
- state.assertKeys = op.assertKeys;
381
- state.controllerKeys = op.controllerKeys;
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
- authKeys: state.authKeys,
397
- assertKeys: state.assertKeys,
398
- controllerKeys: state.controllerKeys,
399
- services: state.services
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 = currentState.controllerKeys.find((k) => k.id === signingKeyId);
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: op.authKeys,
473
- assertKeys: op.assertKeys,
474
- controllerKeys: op.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, h as MAX_CREDENTIAL_SIZE, R as RevocationChecker, V as VerifiedDFOSCredential, t as VerifiedDelegationChain, v as createDFOSCredential, w as decodeDFOSCredentialUnsafe, x as isAttenuated, y as matchesResource, B as verifyDFOSCredential, E as verifyDelegationChain } from '../dfos-credential-X6uvPIth.js';
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, verifyDFOSCredential as B, CONTENT_ID_ANCHOR_RE as C, DFOSCredentialPayload as D, verifyDelegationChain as E, 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, Iso8601 as g, MAX_CREDENTIAL_SIZE as h, MAX_CREDIT_CLAIM_SIZE as i, MAX_OPERATION_SIZE as j, MAX_SERVICES_ENTRIES as k, MAX_SERVICES_PAYLOAD_SIZE as l, MAX_SIGN_REQUEST_PAYLOAD_SIZE as m, MAX_SIGN_REQUEST_SIZE as n, MultikeyPublicKey as o, RevocationPayload as p, ServicesArray as q, SignRequestPayload as r, type Signer as s, type VerifiedDelegationChain as t, VerifiedIdentity as u, createDFOSCredential as v, decodeDFOSCredentialUnsafe as w, isAttenuated as x, matchesResource as y, parseProtocolTimestampUnix as z };
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, g as Iso8601, M as MAX_ARTIFACT_PAYLOAD_SIZE, h as MAX_CREDENTIAL_SIZE, i as MAX_CREDIT_CLAIM_SIZE, j as MAX_OPERATION_SIZE, k as MAX_SERVICES_ENTRIES, l as MAX_SERVICES_PAYLOAD_SIZE, m as MAX_SIGN_REQUEST_PAYLOAD_SIZE, n as MAX_SIGN_REQUEST_SIZE, o as MultikeyPublicKey, R as RevocationChecker, p as RevocationPayload, S as ServiceEntry, q as ServicesArray, r as SignRequestPayload, s as Signer, V as VerifiedDFOSCredential, t as VerifiedDelegationChain, u as VerifiedIdentity, v as createDFOSCredential, w as decodeDFOSCredentialUnsafe, x as isAttenuated, y as matchesResource, z as parseProtocolTimestampUnix, B as verifyDFOSCredential, E as verifyDelegationChain } from './dfos-credential-X6uvPIth.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, 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';