@interop/wallet-core 0.38.1 → 0.40.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.
Files changed (99) hide show
  1. package/README.md +8 -6
  2. package/dist/clients/revocation.d.ts.map +1 -1
  3. package/dist/clients/revocation.js +5 -10
  4. package/dist/clients/revocation.js.map +1 -1
  5. package/dist/keyring/fetch.d.ts +2 -1
  6. package/dist/keyring/fetch.d.ts.map +1 -1
  7. package/dist/keyring/fetch.js +7 -2
  8. package/dist/keyring/fetch.js.map +1 -1
  9. package/dist/keyring/index.d.ts +15 -9
  10. package/dist/keyring/index.d.ts.map +1 -1
  11. package/dist/keyring/index.js +14 -8
  12. package/dist/keyring/index.js.map +1 -1
  13. package/dist/keyring/kdf.d.ts +3 -1
  14. package/dist/keyring/kdf.d.ts.map +1 -1
  15. package/dist/keyring/kdf.js +16 -2
  16. package/dist/keyring/kdf.js.map +1 -1
  17. package/dist/keyring/record.d.ts +207 -41
  18. package/dist/keyring/record.d.ts.map +1 -1
  19. package/dist/keyring/record.js +318 -32
  20. package/dist/keyring/record.js.map +1 -1
  21. package/dist/keyring/unlockSpace.d.ts +25 -0
  22. package/dist/keyring/unlockSpace.d.ts.map +1 -1
  23. package/dist/keyring/unlockSpace.js +31 -2
  24. package/dist/keyring/unlockSpace.js.map +1 -1
  25. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  26. package/dist/keys/rosterLogStore.js +6 -1
  27. package/dist/keys/rosterLogStore.js.map +1 -1
  28. package/dist/keys/userKeyRoster.d.ts +22 -3
  29. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  30. package/dist/keys/userKeyRoster.js +11 -59
  31. package/dist/keys/userKeyRoster.js.map +1 -1
  32. package/dist/recovery/index.d.ts +8 -3
  33. package/dist/recovery/index.d.ts.map +1 -1
  34. package/dist/recovery/index.js +7 -2
  35. package/dist/recovery/index.js.map +1 -1
  36. package/dist/recovery/recoveryCode.d.ts +7 -0
  37. package/dist/recovery/recoveryCode.d.ts.map +1 -1
  38. package/dist/recovery/recoveryCode.js +10 -0
  39. package/dist/recovery/recoveryCode.js.map +1 -1
  40. package/dist/recovery/recoveryRecord.d.ts +134 -43
  41. package/dist/recovery/recoveryRecord.d.ts.map +1 -1
  42. package/dist/recovery/recoveryRecord.js +226 -23
  43. package/dist/recovery/recoveryRecord.js.map +1 -1
  44. package/dist/request/index.d.ts +1 -1
  45. package/dist/request/index.js +1 -1
  46. package/dist/request/matching.d.ts +24 -5
  47. package/dist/request/matching.d.ts.map +1 -1
  48. package/dist/request/matching.js +36 -39
  49. package/dist/request/matching.js.map +1 -1
  50. package/dist/request/walletInput.d.ts.map +1 -1
  51. package/dist/request/walletInput.js +3 -6
  52. package/dist/request/walletInput.js.map +1 -1
  53. package/dist/resourceLog/controller.d.ts +7 -4
  54. package/dist/resourceLog/controller.d.ts.map +1 -1
  55. package/dist/resourceLog/controller.js +17 -35
  56. package/dist/resourceLog/controller.js.map +1 -1
  57. package/dist/resourceLog/index.d.ts +1 -0
  58. package/dist/resourceLog/index.d.ts.map +1 -1
  59. package/dist/resourceLog/index.js +1 -0
  60. package/dist/resourceLog/index.js.map +1 -1
  61. package/dist/resourceLog/seal.d.ts +9 -1
  62. package/dist/resourceLog/seal.d.ts.map +1 -1
  63. package/dist/resourceLog/seal.js +21 -11
  64. package/dist/resourceLog/seal.js.map +1 -1
  65. package/dist/resourceLog/verify.d.ts.map +1 -1
  66. package/dist/resourceLog/verify.js +26 -9
  67. package/dist/resourceLog/verify.js.map +1 -1
  68. package/dist/resourceLog/vmFragment.d.ts +33 -0
  69. package/dist/resourceLog/vmFragment.d.ts.map +1 -0
  70. package/dist/resourceLog/vmFragment.js +39 -0
  71. package/dist/resourceLog/vmFragment.js.map +1 -0
  72. package/dist/space/collections.d.ts +22 -1
  73. package/dist/space/collections.d.ts.map +1 -1
  74. package/dist/space/collections.js +40 -10
  75. package/dist/space/collections.js.map +1 -1
  76. package/dist/space/index.d.ts +3 -2
  77. package/dist/space/index.d.ts.map +1 -1
  78. package/dist/space/index.js +3 -2
  79. package/dist/space/index.js.map +1 -1
  80. package/dist/space/publicLink.d.ts +2 -0
  81. package/dist/space/publicLink.d.ts.map +1 -1
  82. package/dist/space/publicLink.js +13 -1
  83. package/dist/space/publicLink.js.map +1 -1
  84. package/dist/space/wasLink.d.ts +5 -0
  85. package/dist/space/wasLink.d.ts.map +1 -1
  86. package/dist/space/wasLink.js +7 -2
  87. package/dist/space/wasLink.js.map +1 -1
  88. package/dist/webvh/didWeb.d.ts +3 -11
  89. package/dist/webvh/didWeb.d.ts.map +1 -1
  90. package/dist/webvh/didWeb.js +5 -1
  91. package/dist/webvh/didWeb.js.map +1 -1
  92. package/dist/webvh/listClients.d.ts +3 -1
  93. package/dist/webvh/listClients.d.ts.map +1 -1
  94. package/dist/webvh/listClients.js +46 -29
  95. package/dist/webvh/listClients.js.map +1 -1
  96. package/dist/webvh/verifyLog.d.ts.map +1 -1
  97. package/dist/webvh/verifyLog.js +5 -1
  98. package/dist/webvh/verifyLog.js.map +1 -1
  99. package/package.json +3 -3
package/README.md CHANGED
@@ -35,10 +35,11 @@ The subpaths:
35
35
 
36
36
  - **`@interop/wallet-core/space`** -- the wallet Space layout contract: the
37
37
  shared collection ids and descriptive specs (`private-credentials`,
38
- `public-credentials`, `wallet-activity`), the `wallet-activity` wire shape
39
- with its pure `addHistory*` payload builders, the `publicCredentialUrl`
40
- derivation, and the `was-link` QR hand-off contract. Contacts collection specs
41
- live in [`@interop/social-core`](https://npm.im/@interop/social-core).
38
+ `public-credentials`, `wallet-activity`, `app-connections`), the
39
+ `wallet-activity` wire shape with its pure `addHistory*` payload builders, the
40
+ `publicCredentialUrl` derivation, and the `was-link` QR hand-off contract.
41
+ Contacts collection specs live in
42
+ [`@interop/social-core`](https://npm.im/@interop/social-core).
42
43
 
43
44
  - **`@interop/wallet-core/identity`** -- the WAS identity derivation both wallet
44
45
  apps must perform byte-for-byte identically: `agentsFromSecret` /
@@ -120,8 +121,9 @@ The subpaths:
120
121
  unknown-epoch refresh policy, including a self-refreshing EDV document cipher.
121
122
 
122
123
  - **`@interop/wallet-core/keyring`** -- the unlock layer: the unlock derivation,
123
- the `{ version, wrapped }` account-pointer record codec, and the unlock Space
124
- lifecycle.
124
+ the signed `{ version, encryption, wrapped, proof }` account-pointer record
125
+ codec (the proof is verified before the record is decrypted), and the unlock
126
+ Space lifecycle.
125
127
 
126
128
  - **`@interop/wallet-core/enrollment`** -- the client enrollment ceremony
127
129
  (connect code, approval, completion) plus the onboarding-response envelope
@@ -1 +1 @@
1
- {"version":3,"file":"revocation.d.ts","sourceRoot":"","sources":["../../src/clients/revocation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"revocation.d.ts","sourceRoot":"","sources":["../../src/clients/revocation.ts"],"names":[],"mappings":"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"}
@@ -100,26 +100,21 @@ export async function revokeAccountClient({ idStore, updateKeys, revokedClient,
100
100
  document: doc
101
101
  };
102
102
  }
103
- await rotateUserKeyRoster({
103
+ const rotatedDescriptor = await rotateUserKeyRoster({
104
104
  store: rosterStore,
105
105
  document: doc,
106
106
  retireRecipientId: rosterRecipientKid(revokedClient)
107
107
  });
108
+ // The rotation's own verified result is threaded into the adopting read, so
109
+ // one cascade run acquires the roster once for both halves of stage 2 (the
110
+ // continuity and possession checks still run on the threaded descriptor).
108
111
  const read = await readUserKeyRoster({
109
112
  store: rosterStore,
113
+ descriptor: rotatedDescriptor,
110
114
  ...(userKey ? { userKey } : {}),
111
115
  clientKeyAgreementKey,
112
116
  pinnedEpochId
113
117
  });
114
- if (!read) {
115
- // The roster stood a moment ago and the rotation just wrote it, so its
116
- // disappearance is a real fault, not the no-roster case above: the fresh
117
- // key is only readable from the roster, and reporting success here would
118
- // fan out under the retired one.
119
- throw new Error('The wrap-set roster vanished between its rotation and the read that ' +
120
- 'adopts the fresh user key; the client is disconnected, but the ' +
121
- 'rotation must be completed by re-running the revocation.');
122
- }
123
118
  if (read.rotated) {
124
119
  await onUserKeyAdopted?.({
125
120
  userKey: read.userKey,
@@ -1 +1 @@
1
- {"version":3,"file":"revocation.js","sourceRoot":"","sources":["../../src/clients/revocation.ts"],"names":[],"mappings":"AAqDA,OAAO,EACL,iBAAiB,EAIlB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EAGpB,MAAM,kBAAkB,CAAA;AA6CzB;;;;;;;GAOG;AACH,KAAK,UAAU,eAAe,CAAC,EAC7B,WAAW,EAGZ;IACC,MAAM,EAAE,aAAa,EAAE,GAAG,WAAW,CAAA;IACrC,OAAO,OAAO,aAAa,KAAK,UAAU;QACxC,CAAC,CAAC,MAAM,aAAa,EAAE;QACvB,CAAC,CAAC,aAAa,CAAA;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EACxC,OAAO,EACP,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,WAAW,EACX,OAAO,EACP,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,yBAAyB,EACzB,iBAAiB,EAsBlB;IACC,IACE,sBAAsB;QACtB,sBAAsB,KAAK,aAAa,CAAC,mBAAmB,EAC5D,CAAC;QACD,MAAM,IAAI,KAAK,CACb,oEAAoE;YAClE,sCAAsC,CACzC,CAAA;IACH,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,oEAAoE;YAClE,8CAA8C,CACjD,CAAA;IACH,CAAC;IAED,2EAA2E;IAC3E,0EAA0E;IAC1E,mBAAmB;IACnB,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,iBAAiB,CAAC;QACtC,OAAO;QACP,UAAU;QACV,aAAa;QACb,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC,CAAA;IAEF,uEAAuE;IACvE,4EAA4E;IAC5E,kFAAkF;IAClF,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAA;IACvC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YACzC,QAAQ,EAAE,GAAG;SACd,CAAA;IACH,CAAC;IACD,MAAM,mBAAmB,CAAC;QACxB,KAAK,EAAE,WAAW;QAClB,QAAQ,EAAE,GAAG;QACb,iBAAiB,EAAE,kBAAkB,CAAC,aAAa,CAAC;KACrD,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC;QACnC,KAAK,EAAE,WAAW;QAClB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,qBAAqB;QACrB,aAAa;KACd,CAAC,CAAA;IACF,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,uEAAuE;QACvE,yEAAyE;QACzE,yEAAyE;QACzE,iCAAiC;QACjC,MAAM,IAAI,KAAK,CACb,sEAAsE;YACpE,iEAAiE;YACjE,0DAA0D,CAC7D,CAAA;IACH,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,gBAAgB,EAAE,CAAC;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAA;IACJ,CAAC;IAED,uEAAuE;IACvE,wEAAwE;IACxE,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,yEAAyE;IACzE,2BAA2B;IAC3B,IAAI,UAAwC,CAAA;IAC5C,IAAI,yBAAyB,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,UAAU,GAAG,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,EAAE,CAAA;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAU,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAA;QAChD,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,6EAA6E;IAC7E,+CAA+C;IAC/C,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC;QAChD,aAAa,EAAE,MAAM,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,GAAG,CAAC,WAAW,CAAC,WAAW;YACzB,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE;YAC1C,CAAC,CAAC,EAAE,CAAC;QACP,gBAAgB,EAAE,IAAI,CAAC,UAAU;QACjC,qBAAqB;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAA;IAEF,2EAA2E;IAC3E,qCAAqC;IACrC,MAAM,QAAQ,GAAG,MAAM,yBAAyB,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAA;IAErE,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;IACtD,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,WAAW,EAAE,OAAO;QACpB,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,gBAAgB,EAAE,IAAI,CAAC,UAAU;QACjC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"revocation.js","sourceRoot":"","sources":["../../src/clients/revocation.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import type { UnlockKdf } from './kdf.js';
2
2
  import type { KeyringRecordContents } from './record.js';
3
3
  /**
4
- * Fetches and unwraps the keyring record an unlock secret addresses, or
4
+ * Fetches, verifies, and unwraps the keyring record an unlock secret
5
+ * addresses, or
5
6
  * resolves `null` when no record exists there (an unknown secret). The derived
6
7
  * unlock Space id is returned alongside the contents -- it is already computed,
7
8
  * and callers key their local state on it.
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/keyring/fetch.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAIzC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAExD;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,MAAM,EACN,GAAiB,EACjB,gBAAgB,EACjB,EAAE;IACD,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;IAC3B,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;CACzB,GAAG,OAAO,CAAC,CAAC,qBAAqB,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAAC,CAkBtE"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/keyring/fetch.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAIzC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,MAAM,EACN,GAAiB,EACjB,gBAAgB,EACjB,EAAE;IACD,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;IAC3B,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;CACzB,GAAG,OAAO,CAAC,CAAC,qBAAqB,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAAC,CAsBtE"}
@@ -2,7 +2,8 @@ import { deriveUnlockIdentity, KEYRING_KDF } from './kdf.js';
2
2
  import { getUnlockKeyring } from './unlockSpace.js';
3
3
  import { unwrapKeyringRecord } from './record.js';
4
4
  /**
5
- * Fetches and unwraps the keyring record an unlock secret addresses, or
5
+ * Fetches, verifies, and unwraps the keyring record an unlock secret
6
+ * addresses, or
6
7
  * resolves `null` when no record exists there (an unknown secret). The derived
7
8
  * unlock Space id is returned alongside the contents -- it is already computed,
8
9
  * and callers key their local state on it.
@@ -28,7 +29,11 @@ export async function fetchKeyringRecord({ secret, kdf = KEYRING_KDF, storageSer
28
29
  // `id` is always set on the unlock KAK (a controller was supplied at
29
30
  // derivation), so it satisfies IKeyAgreementKey's required `id`.
30
31
  keyAgreementKey: unlock.keyAgreementKey,
31
- keyResolver: unlock.keyResolver
32
+ keyResolver: unlock.keyResolver,
33
+ // The unlock identity's own signing key: derived from the secret the
34
+ // caller typed, so the record's proof is verified against a prior this
35
+ // client holds rather than anything the server served beside it.
36
+ expectedKeyMultibase: unlock.recordSigner.keyMultibase
32
37
  });
33
38
  return { ...contents, unlockSpaceId: unlock.spaceId };
34
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/keyring/fetch.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,MAAM,EACN,GAAG,GAAG,WAAW,EACjB,gBAAgB,EAKjB;IACC,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAC1D,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;QACpC,gBAAgB;QAChB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAA;IACF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC;QACzC,MAAM;QACN,qEAAqE;QACrE,iEAAiE;QACjE,eAAe,EAAE,MAAM,CAAC,eAAmC;QAC3D,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAA;IACF,OAAO,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;AACvD,CAAC"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/keyring/fetch.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,MAAM,EACN,GAAG,GAAG,WAAW,EACjB,gBAAgB,EAKjB;IACC,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAC1D,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;QACpC,gBAAgB;QAChB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAA;IACF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC;QACzC,MAAM;QACN,qEAAqE;QACrE,iEAAiE;QACjE,eAAe,EAAE,MAAM,CAAC,eAAmC;QAC3D,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,qEAAqE;QACrE,uEAAuE;QACvE,iEAAiE;QACjE,oBAAoB,EAAE,MAAM,CAAC,YAAY,CAAC,YAAY;KACvD,CAAC,CAAA;IACF,OAAO,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;AACvD,CAAC"}
@@ -11,12 +11,18 @@
11
11
  * unchanged where WebCrypto's `deriveBits` is unavailable) and the unlock
12
12
  * Space addressing convention.
13
13
  * - `wrapKeyringRecord` / `unwrapKeyringRecord` -- the
14
- * `{ version, encryption, wrapped }` account-pointer record codec.
15
- * - `mintRecordEncryption` / `recordCipher` / `parseRecordFrame` -- the
16
- * record-own-epoch envelope construction the codec seals with plus the frame
17
- * validation it opens with, exported so an app's own locally stored records
18
- * seal and unseal the same way (under their own cipher context) rather than
19
- * re-deriving the construction.
14
+ * `{ version, encryption, wrapped, proof }` account-pointer record codec.
15
+ * - `recordSignerFromAgent` / `signRecordFrame` / `verifyRecordProof` /
16
+ * `RecordProofError` -- the record's authenticity layer: the proof over the
17
+ * frame members by the unlock identity's signing key, verified before any
18
+ * decryption, so a storage host cannot substitute a record it sealed itself.
19
+ * - `mintRecordEncryption` / `recordCipher` / `parseRecordFrame` /
20
+ * `parseRecordCreatedAt` / `recordCreatedAtStamp` -- the record-own-epoch
21
+ * envelope construction the
22
+ * codec seals with plus the frame and plaintext validation it opens with,
23
+ * exported so an app's own locally stored records seal and unseal the same
24
+ * way (under their own cipher context) rather than re-deriving the
25
+ * construction.
20
26
  * - `ensureUnlockSpace` / `getUnlockKeyring` / `putUnlockKeyring` /
21
27
  * `deleteUnlockSpace` / `deleteUnlockSpaceWithCapability` -- the unlock
22
28
  * Space's lifecycle and its one resource.
@@ -28,8 +34,8 @@
28
34
  */
29
35
  export { deriveUnlockIdentity, KEYRING_KDF, UNLOCK_HANDLE, UNLOCK_KEY_NAME, unlockSpaceIdFor } from './kdf.js';
30
36
  export type { UnlockIdentity, UnlockKdf } from './kdf.js';
31
- export { KEYRING_RECORD_VERSION, mintRecordEncryption, parseRecordFrame, parseRecordPointer, recordCipher, unwrapKeyringRecord, wrapKeyringRecord } from './record.js';
32
- export type { AccountPointer, KeyringRecordContents } from './record.js';
33
- export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, putUnlockKeyring, putUnlockKeyringWithCapability, UNLOCK_SPACE_NAME } from './unlockSpace.js';
37
+ export { KEYRING_RECORD_VERSION, mintRecordEncryption, parseRecordCreatedAt, parseRecordFrame, parseRecordPointer, recordCipher, recordCreatedAtStamp, RecordProofError, recordProofKeyMultibase, recordSignerFromAgent, signRecordFrame, unwrapKeyringRecord, verifyRecordProof, wrapKeyringRecord } from './record.js';
38
+ export type { AccountPointer, KeyringRecordContents, RecordProof, RecordSigner, SignedRecord } from './record.js';
39
+ export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, getUnlockKeyringWithCapability, putUnlockKeyring, putUnlockKeyringWithCapability, UNLOCK_SPACE_NAME } from './unlockSpace.js';
34
40
  export { fetchKeyringRecord } from './fetch.js';
35
41
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keyring/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAExE,OAAO,EACL,iBAAiB,EACjB,+BAA+B,EAC/B,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,8BAA8B,EAC9B,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keyring/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,YAAY,EACb,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,iBAAiB,EACjB,+BAA+B,EAC/B,iBAAiB,EACjB,gBAAgB,EAChB,8BAA8B,EAC9B,gBAAgB,EAChB,8BAA8B,EAC9B,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
@@ -11,12 +11,18 @@
11
11
  * unchanged where WebCrypto's `deriveBits` is unavailable) and the unlock
12
12
  * Space addressing convention.
13
13
  * - `wrapKeyringRecord` / `unwrapKeyringRecord` -- the
14
- * `{ version, encryption, wrapped }` account-pointer record codec.
15
- * - `mintRecordEncryption` / `recordCipher` / `parseRecordFrame` -- the
16
- * record-own-epoch envelope construction the codec seals with plus the frame
17
- * validation it opens with, exported so an app's own locally stored records
18
- * seal and unseal the same way (under their own cipher context) rather than
19
- * re-deriving the construction.
14
+ * `{ version, encryption, wrapped, proof }` account-pointer record codec.
15
+ * - `recordSignerFromAgent` / `signRecordFrame` / `verifyRecordProof` /
16
+ * `RecordProofError` -- the record's authenticity layer: the proof over the
17
+ * frame members by the unlock identity's signing key, verified before any
18
+ * decryption, so a storage host cannot substitute a record it sealed itself.
19
+ * - `mintRecordEncryption` / `recordCipher` / `parseRecordFrame` /
20
+ * `parseRecordCreatedAt` / `recordCreatedAtStamp` -- the record-own-epoch
21
+ * envelope construction the
22
+ * codec seals with plus the frame and plaintext validation it opens with,
23
+ * exported so an app's own locally stored records seal and unseal the same
24
+ * way (under their own cipher context) rather than re-deriving the
25
+ * construction.
20
26
  * - `ensureUnlockSpace` / `getUnlockKeyring` / `putUnlockKeyring` /
21
27
  * `deleteUnlockSpace` / `deleteUnlockSpaceWithCapability` -- the unlock
22
28
  * Space's lifecycle and its one resource.
@@ -27,7 +33,7 @@
27
33
  * was-client dependency graph (the same isolation pattern as `./identity`).
28
34
  */
29
35
  export { deriveUnlockIdentity, KEYRING_KDF, UNLOCK_HANDLE, UNLOCK_KEY_NAME, unlockSpaceIdFor } from './kdf.js';
30
- export { KEYRING_RECORD_VERSION, mintRecordEncryption, parseRecordFrame, parseRecordPointer, recordCipher, unwrapKeyringRecord, wrapKeyringRecord } from './record.js';
31
- export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, putUnlockKeyring, putUnlockKeyringWithCapability, UNLOCK_SPACE_NAME } from './unlockSpace.js';
36
+ export { KEYRING_RECORD_VERSION, mintRecordEncryption, parseRecordCreatedAt, parseRecordFrame, parseRecordPointer, recordCipher, recordCreatedAtStamp, RecordProofError, recordProofKeyMultibase, recordSignerFromAgent, signRecordFrame, unwrapKeyringRecord, verifyRecordProof, wrapKeyringRecord } from './record.js';
37
+ export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, getUnlockKeyringWithCapability, putUnlockKeyring, putUnlockKeyringWithCapability, UNLOCK_SPACE_NAME } from './unlockSpace.js';
32
38
  export { fetchKeyringRecord } from './fetch.js';
33
39
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keyring/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAA;AAGjB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,iBAAiB,EACjB,+BAA+B,EAC/B,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,8BAA8B,EAC9B,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keyring/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAA;AAGjB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,aAAa,CAAA;AASpB,OAAO,EACL,iBAAiB,EACjB,+BAA+B,EAC/B,iBAAiB,EACjB,gBAAgB,EAChB,8BAA8B,EAC9B,gBAAgB,EAChB,8BAA8B,EAC9B,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
@@ -64,7 +64,8 @@ export declare const KEYRING_KDF: UnlockKdf;
64
64
  * Derives the full unlock identity from an unlock secret: the unlock
65
65
  * CapabilityAgent, a ZcapClient that can both invoke and delegate (the
66
66
  * unlock agent delegates a management zcap on its own Space to the account
67
- * controller at bind time), the unlock KAK + resolver for wrap/unwrap, and the
67
+ * controller at bind time), the unlock KAK + resolver for wrap/unwrap, the
68
+ * record signer that signs and verifies the keyring record's proof, and the
68
69
  * unlock Space id. Performs no I/O -- the derivation seam for tests and future
69
70
  * unlock methods.
70
71
  *
@@ -81,6 +82,7 @@ export declare function deriveUnlockIdentity({ secret, kdf }: {
81
82
  zcapClient: ZcapClient;
82
83
  keyAgreementKey: X25519KeyAgreementKey2020;
83
84
  keyResolver: IKeyResolver;
85
+ recordSigner: import("./record.js").RecordSigner;
84
86
  spaceId: string;
85
87
  }>;
86
88
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["../../src/keyring/kdf.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAOhE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,eAAO,MAAM,eAAe,eAAe,CAAA;AAQ3C;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GACjB;IACE,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAEL;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,SAMzB,CAAA;AA2DD;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,GAAG,EACJ,EAAE;IACD,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;IAC3B,GAAG,EAAE,SAAS,CAAA;CACf;;;;;;GAyBA;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEjE;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["../../src/keyring/kdf.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAQhE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,eAAO,MAAM,eAAe,eAAe,CAAA;AAQ3C;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GACjB;IACE,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAEL;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,SAMzB,CAAA;AA2DD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,GAAG,EACJ,EAAE;IACD,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;IAC3B,GAAG,EAAE,SAAS,CAAA;CACf;;;;;;;GAsCA;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEjE;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAA"}
@@ -24,6 +24,7 @@ import { hkdf } from '@noble/hashes/hkdf.js';
24
24
  import { pbkdf2Async } from '@noble/hashes/pbkdf2.js';
25
25
  import { sha256, sha512 } from '@noble/hashes/sha2.js';
26
26
  import { singleKeyResolver } from '../identity/keyResolver.js';
27
+ import { recordSignerFromAgent } from './record.js';
27
28
  /**
28
29
  * The load-bearing `CapabilityAgent` derivation names for an unlock identity
29
30
  * (the counterpart of the data identity's bootstrap names): every unlock
@@ -101,7 +102,8 @@ async function deriveUnlockSeed({ secret, kdf }) {
101
102
  * Derives the full unlock identity from an unlock secret: the unlock
102
103
  * CapabilityAgent, a ZcapClient that can both invoke and delegate (the
103
104
  * unlock agent delegates a management zcap on its own Space to the account
104
- * controller at bind time), the unlock KAK + resolver for wrap/unwrap, and the
105
+ * controller at bind time), the unlock KAK + resolver for wrap/unwrap, the
106
+ * record signer that signs and verifies the keyring record's proof, and the
105
107
  * unlock Space id. Performs no I/O -- the derivation seam for tests and future
106
108
  * unlock methods.
107
109
  *
@@ -130,8 +132,20 @@ export async function deriveUnlockIdentity({ secret, kdf }) {
130
132
  keyPair: agent.getVerificationKeyPair()
131
133
  });
132
134
  const keyResolver = singleKeyResolver({ keyAgreementKey });
135
+ // The record signer is the unlock signing key itself, named by its public
136
+ // multibase: the keyring record's proof is made and checked against a key
137
+ // that derives from the secret, so the storage host never holds it and a
138
+ // fresh client holds the verification prior by construction.
139
+ const recordSigner = recordSignerFromAgent({ keyAgent: agent });
133
140
  const spaceId = unlockSpaceIdFor({ did: agent.id });
134
- return { agent, zcapClient, keyAgreementKey, keyResolver, spaceId };
141
+ return {
142
+ agent,
143
+ zcapClient,
144
+ keyAgreementKey,
145
+ keyResolver,
146
+ recordSigner,
147
+ spaceId
148
+ };
135
149
  }
136
150
  /**
137
151
  * The unlock Space id an unlock identity addresses:
@@ -1 +1 @@
1
- {"version":3,"file":"kdf.js","sourceRoot":"","sources":["../../src/keyring/kdf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kdf.js","sourceRoot":"","sources":["../../src/keyring/kdf.ts"],"names":[],"mappings":"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"}
@@ -1,31 +1,120 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
1
+ import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
2
+ import type { CollectionEncryption } from '@interop/was-client';
3
+ import { type DocCipher } from '@interop/was-client/edv';
4
+ /**
5
+ * The version stamped on the stored `{ version, encryption, wrapped, proof }`
6
+ * keyring envelope: the signed record, whose envelope seals under the record's
7
+ * own key epoch (the `encryption` member) and whose sibling members carry a
8
+ * Data Integrity proof by the unlock identity's signing key. Any other version
9
+ * is refused as unusable -- such accounts are re-provisioned, not migrated.
10
+ */
11
+ export declare const KEYRING_RECORD_VERSION = 2;
12
+ /**
13
+ * The record signer's seam: the signing key's public multibase (which names
14
+ * the key in the proof's `verificationMethod`) and a raw detached-signature
15
+ * hook over it. Structurally the resource log's `ResourceLogSigner`, so one
16
+ * adapter feeds both, deliberately restated here rather than imported -- a
17
+ * record is not a log, and the keyring module keeps its own vocabulary.
18
+ */
19
+ export interface RecordSigner {
20
+ keyMultibase: string;
21
+ sign(input: {
22
+ data: Uint8Array;
23
+ }): Promise<Uint8Array>;
24
+ }
25
+ /**
26
+ * The fixed proof shape a signed record carries: an eddsa-jcs-2022 Data
27
+ * Integrity proof over the record's sibling members, `assertionMethod`
28
+ * purpose, with the signing key named by a `did:key:<multibase>#<multibase>`
29
+ * verification method.
3
30
  */
31
+ export interface RecordProof {
32
+ type: 'DataIntegrityProof';
33
+ cryptosuite: 'eddsa-jcs-2022';
34
+ verificationMethod: string;
35
+ proofPurpose: 'assertionMethod';
36
+ created?: string;
37
+ proofValue: string;
38
+ }
4
39
  /**
5
- * The keyring record codec: the `{ version, encryption, wrapped }` envelope
6
- * stored as the one resource of an account's unlock Space. Its plaintext
7
- * carries the account controller, the email captured at bind time, and the
8
- * account pointer -- and deliberately no key material of any kind, so the
9
- * record locates an account without authorizing anything against it.
40
+ * A stored signed record: the frame members the proof secures, plus the proof
41
+ * itself.
42
+ */
43
+ export interface SignedRecord {
44
+ version: number;
45
+ encryption: CollectionEncryption;
46
+ wrapped: unknown;
47
+ proof: RecordProof;
48
+ }
49
+ /**
50
+ * A record's proof is absent, malformed, signed by a key this client does not
51
+ * accept, or does not verify over the record's own members. Its own class,
52
+ * distinct from a decrypt failure or an unusable-version refusal: this is the
53
+ * refusal that says the storage host forged or tampered with the record, which
54
+ * an app maps to its own login copy.
55
+ */
56
+ export declare class RecordProofError extends Error {
57
+ constructor(message: string, options?: {
58
+ cause?: unknown;
59
+ });
60
+ }
61
+ /**
62
+ * Adapts a signing key agent (the unlock identity's `CapabilityAgent`, or an
63
+ * enrolled client's own key agent) to the record signer seam: the agent's
64
+ * did:key id supplies the public multibase, its signer the raw signature.
10
65
  *
11
- * The wrap is an EDV document envelope sealed under the record's own key
12
- * epoch: every EDV envelope seals to an epoch key, so the record carries its
13
- * one-epoch descriptor in its `encryption` member, epoch[0] wrapped to the
14
- * unlock key-agreement key. The record stays self-contained -- unlock KAK in,
15
- * contents out. The cipher's `keyring` collection context labels errors only
16
- * (the codec is agnostic to it); what keeps a swapped-in foreign record from
17
- * being accepted is the contents validation on unwrap, not the cipher.
66
+ * @param options {object}
67
+ * @param options.keyAgent {object} a did:key `CapabilityAgent`-shaped agent
68
+ * @returns {RecordSigner}
18
69
  */
19
- import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
20
- import type { CollectionEncryption } from '@interop/was-client';
21
- import { type DocCipher } from '@interop/was-client/edv';
70
+ export declare function recordSignerFromAgent({ keyAgent }: {
71
+ keyAgent: {
72
+ id: string;
73
+ getSigner: () => {
74
+ sign: (input: {
75
+ data: Uint8Array;
76
+ }) => Promise<Uint8Array>;
77
+ };
78
+ };
79
+ }): RecordSigner;
80
+ /**
81
+ * Signs a record's frame members and returns the stored signed record. Shared
82
+ * by the keyring and recovery wrap paths (and available to an app's own record
83
+ * kinds), so one construction produces every signed record: the proof covers
84
+ * `{ version, encryption, wrapped }` plus any record-kind members under JCS
85
+ * canonicalization.
86
+ *
87
+ * @param options {object}
88
+ * @param options.version {number} the frame version to stamp
89
+ * @param options.encryption {CollectionEncryption} the record's descriptor
90
+ * @param options.wrapped {unknown} the sealed envelope
91
+ * @param options.signer {RecordSigner} the signing key
92
+ * @param [options.members] {object} additional record-kind frame members the
93
+ * proof must cover (e.g. the recovery record's `binding`)
94
+ * @returns {Promise<SignedRecord>}
95
+ */
96
+ export declare function signRecordFrame({ version, encryption, wrapped, signer, members }: {
97
+ version: number;
98
+ encryption: CollectionEncryption;
99
+ wrapped: unknown;
100
+ signer: RecordSigner;
101
+ members?: Record<string, unknown>;
102
+ }): Promise<SignedRecord>;
22
103
  /**
23
- * The version stamped on the stored `{ version, encryption, wrapped }` keyring
24
- * envelope: the record whose envelope seals under the record's own key epoch
25
- * (the `encryption` member). Any other version is refused as unusable -- such
26
- * accounts are re-provisioned, not migrated.
104
+ * The signing key's public multibase named by a proof's `verificationMethod`:
105
+ * its fragment. The signer emits `did:key:<multibase>#<multibase>`; the DID
106
+ * half is not what authorizes anything -- the multibase IS the key, and the
107
+ * caller's allowlist decides whether it may sign this record.
108
+ *
109
+ * @param options {object}
110
+ * @param options.verificationMethod {string}
111
+ * @param options.label {string} names the record kind in the refusal
112
+ * @returns {string}
27
113
  */
28
- export declare const KEYRING_RECORD_VERSION = 1;
114
+ export declare function recordProofKeyMultibase({ verificationMethod, label }: {
115
+ verificationMethod: string;
116
+ label: string;
117
+ }): string;
29
118
  /**
30
119
  * Mints the one-epoch descriptor a fresh record is sealed under: epoch[0]
31
120
  * wrapped to the given KAK alone, built through `initRecipients` against a
@@ -69,9 +158,15 @@ export declare function recordCipher({ keyAgreementKey, keyResolver, encryption,
69
158
  /**
70
159
  * Validates the common `{ version, encryption, wrapped }` frame of a stored
71
160
  * record (keyring or recovery -- `label` names the refusals) and returns its
72
- * members. Exported so an app's own record kinds open their records through
73
- * the same frame validation the codec here seals with, rather than re-deriving
74
- * the version and shape checks.
161
+ * members, the `proof` among them for the signed frame. Exported so an app's
162
+ * own record kinds open their records through the same frame validation the
163
+ * codec here seals with, rather than re-deriving the version and shape checks.
164
+ *
165
+ * A frame at the keyring record version is the signed frame, so it must carry
166
+ * a fixed-shape proof; a record kind stamping its own version is unaffected
167
+ * (its authenticity story is its own). Validating the shape here does not
168
+ * verify it -- {@link verifyRecordProof} does, and every unwrap path in this
169
+ * module runs it before decrypting.
75
170
  *
76
171
  * @param options {object}
77
172
  * @param options.record {unknown}
@@ -79,7 +174,8 @@ export declare function recordCipher({ keyAgreementKey, keyResolver, encryption,
79
174
  * kind's own label
80
175
  * @param [options.version] {number} the version the frame must carry;
81
176
  * defaults to the keyring record version
82
- * @returns {{ encryption: CollectionEncryption, wrapped: unknown }}
177
+ * @returns {{ encryption: CollectionEncryption, wrapped: unknown,
178
+ * proof?: RecordProof }}
83
179
  */
84
180
  export declare function parseRecordFrame({ record, label, version }: {
85
181
  record: unknown;
@@ -88,7 +184,34 @@ export declare function parseRecordFrame({ record, label, version }: {
88
184
  }): {
89
185
  encryption: CollectionEncryption;
90
186
  wrapped: unknown;
187
+ proof?: RecordProof;
91
188
  };
189
+ /**
190
+ * Verifies a stored record's proof: the fixed proof shape, the signing key
191
+ * against the caller's allowlist, and the signature over the record's sibling
192
+ * members (everything except `proof`, JCS-canonicalized). Refuses with
193
+ * {@link RecordProofError} in every failing case -- a class of its own, so an
194
+ * app tells "the host forged or tampered with this record" apart from a wrong
195
+ * unlock secret or an unusable version.
196
+ *
197
+ * Standalone as well as internal, because the recovery record's re-minted
198
+ * signer is only knowable after the record is decrypted (see
199
+ * `unwrapRecoveryRecord`).
200
+ *
201
+ * @param options {object}
202
+ * @param options.record {unknown} the stored record, proof included
203
+ * @param options.allowedKeyMultibases {string | string[]} the signing keys
204
+ * this caller accepts, as public multibases or as verification-method ids
205
+ * whose fragment is one
206
+ * @param [options.label] {string} names the record kind in refusals;
207
+ * defaults to the keyring record
208
+ * @returns {Promise<string>} the verified signing key's public multibase
209
+ */
210
+ export declare function verifyRecordProof({ record, allowedKeyMultibases, label }: {
211
+ record: unknown;
212
+ allowedKeyMultibases: string | string[];
213
+ label?: string;
214
+ }): Promise<string>;
92
215
  /**
93
216
  * The account pointer a keyring record carries in place of the retired data
94
217
  * seed: where the account lives (`spaceId` + `host`, the WAS server origin)
@@ -111,12 +234,17 @@ export interface KeyringRecordContents {
111
234
  controller: string;
112
235
  email?: string;
113
236
  pointer?: AccountPointer;
237
+ createdAt: string;
114
238
  }
115
239
  /**
116
240
  * Wraps the account-pointer contents into a keyring record: the controller,
117
241
  * email, and pointer (+ timestamp) sealed under a freshly minted record epoch
118
- * whose key is wrapped to the unlock KAK. Deliberately carries no key material
119
- * of any kind.
242
+ * whose key is wrapped to the unlock KAK, then signed by the unlock identity's
243
+ * signing key. Deliberately carries no key material of any kind.
244
+ *
245
+ * The timestamp stays inside the plaintext (the signature covers the
246
+ * ciphertext, so it is covered transitively), so bind times do not leak to a
247
+ * reader of the unlock Space.
120
248
  *
121
249
  * @param options {object}
122
250
  * @param options.controller {string} the account did:key
@@ -125,37 +253,75 @@ export interface KeyringRecordContents {
125
253
  * no-WAS deployments)
126
254
  * @param options.keyAgreementKey {IKeyAgreementKey} the unlock KAK
127
255
  * @param options.keyResolver {IKeyResolver}
128
- * @returns {Promise<{ version: number, encryption: CollectionEncryption,
129
- * wrapped: unknown }>}
256
+ * @param options.signer {RecordSigner} the unlock identity's signing key
257
+ * (`recordSignerFromAgent` over the unlock agent)
258
+ * @param [options.createdAt] {string} the bind timestamp to stamp, as an ISO
259
+ * string; defaults to now. Supplied by a caller that pins record freshness,
260
+ * so it knows the stamp without unwrapping the record it just wrote.
261
+ * @returns {Promise<SignedRecord>}
130
262
  */
131
- export declare function wrapKeyringRecord({ controller, email, pointer, keyAgreementKey, keyResolver }: {
263
+ export declare function wrapKeyringRecord({ controller, email, pointer, keyAgreementKey, keyResolver, signer, createdAt }: {
132
264
  controller: string;
133
265
  email?: string;
134
266
  pointer?: AccountPointer;
135
267
  keyAgreementKey: IKeyAgreementKey;
136
268
  keyResolver: IKeyResolver;
137
- }): Promise<{
138
- version: number;
139
- encryption: CollectionEncryption;
140
- wrapped: unknown;
141
- }>;
269
+ signer: RecordSigner;
270
+ createdAt?: string;
271
+ }): Promise<SignedRecord>;
142
272
  /**
143
- * Unwraps and validates a keyring record. Rejects a record whose `version` is
144
- * not the current one (accounts are re-provisioned, not migrated), and
145
- * sanity-checks the decrypted plaintext (non-empty controller, well-formed
146
- * pointer when present).
273
+ * Unwraps and validates a keyring record. Verifies the record's proof against
274
+ * the unlock identity's own signing key BEFORE decrypting -- there is no
275
+ * unwrap path that skips it, so a record the storage host substituted is
276
+ * refused ({@link RecordProofError}) rather than decrypted and inspected.
277
+ * Rejects a record whose `version` is not the current one (accounts are
278
+ * re-provisioned, not migrated), and sanity-checks the decrypted plaintext
279
+ * (non-empty controller, well-formed pointer when present, a parseable
280
+ * `createdAt`).
147
281
  *
148
282
  * @param options {object}
149
283
  * @param options.record {unknown}
150
284
  * @param options.keyAgreementKey {IKeyAgreementKey} the unlock KAK
151
285
  * @param options.keyResolver {IKeyResolver}
286
+ * @param options.expectedKeyMultibase {string} the unlock identity's signing
287
+ * key multibase, derived from the typed secret -- the only key that may have
288
+ * signed this record
152
289
  * @returns {Promise<KeyringRecordContents>}
153
290
  */
154
- export declare function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver }: {
291
+ export declare function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver, expectedKeyMultibase }: {
155
292
  record: unknown;
156
293
  keyAgreementKey: IKeyAgreementKey;
157
294
  keyResolver: IKeyResolver;
295
+ expectedKeyMultibase: string;
158
296
  }): Promise<KeyringRecordContents>;
297
+ /**
298
+ * The bind timestamp a wrap path stamps into a record's plaintext: the
299
+ * caller's, validated as a parseable ISO timestamp, or now. A caller supplies
300
+ * one when it pins record freshness, so it knows the stamp of the record it is
301
+ * writing without reading it back.
302
+ *
303
+ * @param options {object}
304
+ * @param [options.createdAt] {string} the caller's timestamp
305
+ * @returns {string}
306
+ */
307
+ export declare function recordCreatedAtStamp({ createdAt }: {
308
+ createdAt?: string;
309
+ }): string;
310
+ /**
311
+ * Parses and validates the required `createdAt` member of a record plaintext:
312
+ * the moment the record was bound, as an ISO timestamp that must parse. Apps
313
+ * pin freshness on it, so a record that cannot state its own bind time is
314
+ * refused rather than defaulted.
315
+ *
316
+ * @param options {object}
317
+ * @param options.value {unknown} the plaintext's `createdAt` member
318
+ * @param options.label {string} names the record kind in the refusal
319
+ * @returns {string}
320
+ */
321
+ export declare function parseRecordCreatedAt({ value, label }: {
322
+ value: unknown;
323
+ label: string;
324
+ }): string;
159
325
  /**
160
326
  * Parses and validates the optional `pointer` member of a keyring record
161
327
  * plaintext. An absent member is a no-WAS record (returns undefined); a