@interop/wallet-core 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/dist/keyring/index.d.ts +1 -1
- package/dist/keyring/index.d.ts.map +1 -1
- package/dist/keyring/index.js +1 -1
- package/dist/keyring/index.js.map +1 -1
- package/dist/keyring/unlockSpace.d.ts +27 -0
- package/dist/keyring/unlockSpace.d.ts.map +1 -1
- package/dist/keyring/unlockSpace.js +31 -0
- package/dist/keyring/unlockSpace.js.map +1 -1
- package/dist/keys/index.d.ts +9 -1
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +8 -1
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/pukCascade.d.ts +157 -0
- package/dist/keys/pukCascade.d.ts.map +1 -0
- package/dist/keys/pukCascade.js +235 -0
- package/dist/keys/pukCascade.js.map +1 -0
- package/dist/keys/pukRoster.d.ts +26 -0
- package/dist/keys/pukRoster.d.ts.map +1 -1
- package/dist/keys/pukRoster.js +30 -1
- package/dist/keys/pukRoster.js.map +1 -1
- package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
- package/dist/recovery/recoveryWebvh.js +1 -20
- package/dist/recovery/recoveryWebvh.js.map +1 -1
- package/dist/space/activity.d.ts +30 -0
- package/dist/space/activity.d.ts.map +1 -1
- package/dist/space/activity.js +33 -0
- package/dist/space/activity.js.map +1 -1
- package/dist/space/index.d.ts +1 -1
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +1 -1
- package/dist/space/index.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +14 -0
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +20 -0
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/index.d.ts +7 -4
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +6 -4
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +64 -0
- package/dist/webvh/revokeClient.d.ts.map +1 -0
- package/dist/webvh/revokeClient.js +241 -0
- package/dist/webvh/revokeClient.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -63,13 +63,18 @@ The subpaths:
|
|
|
63
63
|
|
|
64
64
|
- **`@interop/wallet-core/webvh`** -- the account's did:webvh identity: the
|
|
65
65
|
hosted DID log, its per-client update-key rotation, the client enrollment
|
|
66
|
-
entries,
|
|
66
|
+
entries, the one-entry client-revocation edit (verification methods, update
|
|
67
|
+
key, and standing commitments out in a single entry, the staged commitment
|
|
68
|
+
recovered by log attribution), and ZCap signing under the did:webvh
|
|
69
|
+
verification-method id.
|
|
67
70
|
|
|
68
71
|
- **`@interop/wallet-core/keys`** -- the per-user key (PUK) and its
|
|
69
72
|
`key-map/puk.json` wrap-set roster: minting, the roster's init/read/rotate
|
|
70
73
|
primitives with their client-side guards (`epochsMac`, the latest-seen epoch
|
|
71
|
-
pin, the document-backed recipient resolver),
|
|
72
|
-
|
|
74
|
+
pin, the document-backed recipient resolver), the roster's compare-and-swap
|
|
75
|
+
descriptor store, and the PUK rotation cascade's per-collection op (re-epoch a
|
|
76
|
+
collection onto the roster's current PUK, staleness detected from durable
|
|
77
|
+
state alone, history escrowed -- also the completion sweep's building block).
|
|
73
78
|
|
|
74
79
|
- **`@interop/wallet-core/descriptors`** -- collection encryption-descriptor
|
|
75
80
|
acquisition (fetch / cache / offline fallback) and the unknown-epoch refresh
|
package/dist/keyring/index.d.ts
CHANGED
|
@@ -25,6 +25,6 @@ export { deriveUnlockIdentity, KEYRING_KDF, UNLOCK_HANDLE, UNLOCK_KEY_NAME, unlo
|
|
|
25
25
|
export type { UnlockIdentity, UnlockKdf } from './kdf.js';
|
|
26
26
|
export { KEYRING_RECORD_VERSION, parseRecordPointer, unwrapKeyringRecord, wrapKeyringRecord } from './record.js';
|
|
27
27
|
export type { AccountPointer, KeyringRecordContents } from './record.js';
|
|
28
|
-
export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, putUnlockKeyring, UNLOCK_SPACE_NAME } from './unlockSpace.js';
|
|
28
|
+
export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, putUnlockKeyring, putUnlockKeyringWithCapability, UNLOCK_SPACE_NAME } from './unlockSpace.js';
|
|
29
29
|
export { fetchKeyringRecord } from './fetch.js';
|
|
30
30
|
//# 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;;;;;;;;;;;;;;;;;;;GAmBG;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,kBAAkB,EAClB,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,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;;;;;;;;;;;;;;;;;;;GAmBG;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,kBAAkB,EAClB,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"}
|
package/dist/keyring/index.js
CHANGED
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
*/
|
|
24
24
|
export { deriveUnlockIdentity, KEYRING_KDF, UNLOCK_HANDLE, UNLOCK_KEY_NAME, unlockSpaceIdFor } from './kdf.js';
|
|
25
25
|
export { KEYRING_RECORD_VERSION, parseRecordPointer, unwrapKeyringRecord, wrapKeyringRecord } from './record.js';
|
|
26
|
-
export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, putUnlockKeyring, UNLOCK_SPACE_NAME } from './unlockSpace.js';
|
|
26
|
+
export { deleteUnlockSpace, deleteUnlockSpaceWithCapability, ensureUnlockSpace, getUnlockKeyring, putUnlockKeyring, putUnlockKeyringWithCapability, UNLOCK_SPACE_NAME } from './unlockSpace.js';
|
|
27
27
|
export { fetchKeyringRecord } from './fetch.js';
|
|
28
28
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keyring/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAA;AAGjB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,iBAAiB,EACjB,+BAA+B,EAC/B,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,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;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAA;AAGjB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,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"}
|
|
@@ -59,6 +59,33 @@ export declare function putUnlockKeyring({ storageServerUrl, zcapClient, spaceId
|
|
|
59
59
|
spaceId: string;
|
|
60
60
|
record: object;
|
|
61
61
|
}): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Writes (upserts) the keyring record with an explicitly attached management
|
|
64
|
+
* capability, rather than by root invocation. The `zcapClient` here is an
|
|
65
|
+
* enrolled client's (not the unlock identity's); the attached `capability` --
|
|
66
|
+
* the management zcap the unlock identity delegated at bind time, provided it
|
|
67
|
+
* allows PUT -- authorizes the write against the unlock Space. This is what
|
|
68
|
+
* lets the revocation cascade re-PUT a recovery code's unlock record (a fresh
|
|
69
|
+
* `did.jsonl` delegation inside a re-wrapped record) without holding the
|
|
70
|
+
* code: the record's JWE recipient is the code's unlock KAK, whose PUBLIC
|
|
71
|
+
* half the issuing client recorded, so re-encryption needs no secret.
|
|
72
|
+
*
|
|
73
|
+
* @param options {object}
|
|
74
|
+
* @param options.storageServerUrl {string}
|
|
75
|
+
* @param options.zcapClient {ZcapClient} an enrolled client's zcap client
|
|
76
|
+
* @param options.spaceId {string} the unlock Space id
|
|
77
|
+
* @param options.record {object} the keyring record
|
|
78
|
+
* @param options.capability {IZcap} the delegated management zcap (must
|
|
79
|
+
* allow PUT)
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
*/
|
|
82
|
+
export declare function putUnlockKeyringWithCapability({ storageServerUrl, zcapClient, spaceId, record, capability }: {
|
|
83
|
+
storageServerUrl: string;
|
|
84
|
+
zcapClient: ZcapClient;
|
|
85
|
+
spaceId: string;
|
|
86
|
+
record: object;
|
|
87
|
+
capability: IZcap;
|
|
88
|
+
}): Promise<void>;
|
|
62
89
|
/**
|
|
63
90
|
* Deletes the whole unlock Space (what retires an old passphrase on a
|
|
64
91
|
* passphrase change). `space.delete()` is idempotent, so an already-absent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unlockSpace.d.ts","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AAoIrD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACV,IAAwB,EACzB,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACP,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
|
|
1
|
+
{"version":3,"file":"unlockSpace.d.ts","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AAoIrD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACV,IAAwB,EACzB,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACP,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,MAAM,EACN,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,gBAAgB,EAChB,UAAU,EACV,OAAO,EACR,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,UAAU,EACX,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,KAAK,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
|
|
@@ -175,6 +175,37 @@ export async function putUnlockKeyring({ storageServerUrl, zcapClient, spaceId,
|
|
|
175
175
|
record
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Writes (upserts) the keyring record with an explicitly attached management
|
|
180
|
+
* capability, rather than by root invocation. The `zcapClient` here is an
|
|
181
|
+
* enrolled client's (not the unlock identity's); the attached `capability` --
|
|
182
|
+
* the management zcap the unlock identity delegated at bind time, provided it
|
|
183
|
+
* allows PUT -- authorizes the write against the unlock Space. This is what
|
|
184
|
+
* lets the revocation cascade re-PUT a recovery code's unlock record (a fresh
|
|
185
|
+
* `did.jsonl` delegation inside a re-wrapped record) without holding the
|
|
186
|
+
* code: the record's JWE recipient is the code's unlock KAK, whose PUBLIC
|
|
187
|
+
* half the issuing client recorded, so re-encryption needs no secret.
|
|
188
|
+
*
|
|
189
|
+
* @param options {object}
|
|
190
|
+
* @param options.storageServerUrl {string}
|
|
191
|
+
* @param options.zcapClient {ZcapClient} an enrolled client's zcap client
|
|
192
|
+
* @param options.spaceId {string} the unlock Space id
|
|
193
|
+
* @param options.record {object} the keyring record
|
|
194
|
+
* @param options.capability {IZcap} the delegated management zcap (must
|
|
195
|
+
* allow PUT)
|
|
196
|
+
* @returns {Promise<void>}
|
|
197
|
+
*/
|
|
198
|
+
export async function putUnlockKeyringWithCapability({ storageServerUrl, zcapClient, spaceId, record, capability }) {
|
|
199
|
+
const was = unlockSpaceClient({ storageServerUrl, zcapClient });
|
|
200
|
+
const body = new TextEncoder().encode(JSON.stringify(record));
|
|
201
|
+
await was.request({
|
|
202
|
+
capability,
|
|
203
|
+
path: `/space/${spaceId}/${KEYRING_COLLECTION.id}/${KEYRING_RESOURCE}`,
|
|
204
|
+
method: 'PUT',
|
|
205
|
+
headers: { 'content-type': 'application/json' },
|
|
206
|
+
body
|
|
207
|
+
});
|
|
208
|
+
}
|
|
178
209
|
/**
|
|
179
210
|
* Deletes the whole unlock Space (what retires an old passphrase on a
|
|
180
211
|
* passphrase change). `space.delete()` is idempotent, so an already-absent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unlockSpace.js","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"unlockSpace.js","sourceRoot":"","sources":["../../src/keyring/unlockSpace.ts"],"names":[],"mappings":"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"}
|
package/dist/keys/index.d.ts
CHANGED
|
@@ -16,10 +16,18 @@
|
|
|
16
16
|
* document).
|
|
17
17
|
* - `pukRosterDescriptorStore` -- that descriptor store, built from a bare
|
|
18
18
|
* signing client for the login-time direct read.
|
|
19
|
+
* - `rotatePukRoster` / `unwrapPukGenerations` / `rotateCollectionEpochsToPuk`
|
|
20
|
+
* / `cascadeCollectionsToPuk` / `pukAsRecipient` -- the PUK rotation
|
|
21
|
+
* cascade: the roster rotation off a revoked recipient, the per-collection
|
|
22
|
+
* re-epoch that brings an encrypted collection onto the roster's current
|
|
23
|
+
* PUK, and the parallel best-effort fan-out over the collections the wallet
|
|
24
|
+
* names (also the completion sweep's driver).
|
|
19
25
|
*/
|
|
20
26
|
export { mintPuk, pukVaultKeys } from './puk.js';
|
|
21
27
|
export type { Puk } from './puk.js';
|
|
22
|
-
export { addPukRosterRecipient, ensurePukRoster, PukRosterContinuityError, PukRosterIntegrityError, PukRosterUnwrapError, pukRosterRecipientResolver, readPukRoster } from './pukRoster.js';
|
|
28
|
+
export { addPukRosterRecipient, ensurePukRoster, PukRosterContinuityError, PukRosterIntegrityError, PukRosterUnwrapError, pukRosterRecipientResolver, readPukRoster, rotatePukRoster } from './pukRoster.js';
|
|
29
|
+
export { cascadeCollectionsToPuk, pukAsRecipient, rotateCollectionEpochsToPuk, unwrapPukGenerations } from './pukCascade.js';
|
|
30
|
+
export type { CollectionPukRotationOutcome, PukCascadeResult } from './pukCascade.js';
|
|
23
31
|
export type { PukRosterReadResult, RosterRecipientDocument } from './pukRoster.js';
|
|
24
32
|
export { pukRosterDescriptorStore } from './rosterStore.js';
|
|
25
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/keys/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keys/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keys/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAChD,YAAY,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAEnC,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EAChB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,4BAA4B,EAC5B,gBAAgB,EACjB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/keys/index.js
CHANGED
|
@@ -16,8 +16,15 @@
|
|
|
16
16
|
* document).
|
|
17
17
|
* - `pukRosterDescriptorStore` -- that descriptor store, built from a bare
|
|
18
18
|
* signing client for the login-time direct read.
|
|
19
|
+
* - `rotatePukRoster` / `unwrapPukGenerations` / `rotateCollectionEpochsToPuk`
|
|
20
|
+
* / `cascadeCollectionsToPuk` / `pukAsRecipient` -- the PUK rotation
|
|
21
|
+
* cascade: the roster rotation off a revoked recipient, the per-collection
|
|
22
|
+
* re-epoch that brings an encrypted collection onto the roster's current
|
|
23
|
+
* PUK, and the parallel best-effort fan-out over the collections the wallet
|
|
24
|
+
* names (also the completion sweep's driver).
|
|
19
25
|
*/
|
|
20
26
|
export { mintPuk, pukVaultKeys } from './puk.js';
|
|
21
|
-
export { addPukRosterRecipient, ensurePukRoster, PukRosterContinuityError, PukRosterIntegrityError, PukRosterUnwrapError, pukRosterRecipientResolver, readPukRoster } from './pukRoster.js';
|
|
27
|
+
export { addPukRosterRecipient, ensurePukRoster, PukRosterContinuityError, PukRosterIntegrityError, PukRosterUnwrapError, pukRosterRecipientResolver, readPukRoster, rotatePukRoster } from './pukRoster.js';
|
|
28
|
+
export { cascadeCollectionsToPuk, pukAsRecipient, rotateCollectionEpochsToPuk, unwrapPukGenerations } from './pukCascade.js';
|
|
22
29
|
export { pukRosterDescriptorStore } from './rosterStore.js';
|
|
23
30
|
//# sourceMappingURL=index.js.map
|
package/dist/keys/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keys/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keys/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGhD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EAChB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,iBAAiB,CAAA;AAUxB,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The per-collection half of the PUK rotation cascade: once the roster's
|
|
6
|
+
* current epoch has moved to a fresh PUK (a client revoked, a recovery code
|
|
7
|
+
* spent or revoked), every encrypted collection must take a new epoch naming
|
|
8
|
+
* the fresh PUK and retire the old one -- otherwise writes keep landing under
|
|
9
|
+
* an epoch key the revoked party still holds.
|
|
10
|
+
*
|
|
11
|
+
* The staleness rule is the one the revocation spike verified: **a collection
|
|
12
|
+
* is stale exactly when its current epoch names a PUK KAK other than the
|
|
13
|
+
* roster's current** -- detectable from durable data alone, no checkpoint
|
|
14
|
+
* resource anywhere, which is what makes a crashed cascade resumable by a
|
|
15
|
+
* naive full re-run (and what the login-time completion sweep re-checks).
|
|
16
|
+
* Which KAKs are "PUK generations" is read from the roster itself: its epochs
|
|
17
|
+
* ARE the PUK generations, each escrow-wrapped to every enrolled client, so
|
|
18
|
+
* any enrolled client can recover any generation's key
|
|
19
|
+
* ({@link unwrapPukGenerations}) -- needed both to recognize a stale epoch
|
|
20
|
+
* and to escrow the fresh PUK into a stranded collection's history.
|
|
21
|
+
*
|
|
22
|
+
* One residue, accepted: a collection with NO epochs gets the newest prior
|
|
23
|
+
* generation installed as its first epoch (pre-epoch envelopes are sealed to
|
|
24
|
+
* the era's PUK KAK, and the PUK IS the epoch construction, so they ARE
|
|
25
|
+
* epoch-of-that-generation envelopes) -- envelopes older than that
|
|
26
|
+
* generation, on a collection every prior cascade missed, stay readable only
|
|
27
|
+
* to sessions that held the older key.
|
|
28
|
+
*/
|
|
29
|
+
import type { IKeyAgreementKey } from '@interop/data-integrity-core';
|
|
30
|
+
import type { CollectionEncryption } from '@interop/was-client';
|
|
31
|
+
import { type EncryptionDescriptorStore, type RecipientPublicKey } from '@interop/was-client/edv';
|
|
32
|
+
import { type Puk } from './puk.js';
|
|
33
|
+
/**
|
|
34
|
+
* A PUK presented as an epoch-roster recipient: the kid is the
|
|
35
|
+
* self-describing `<did:key>#<fingerprint>` form every collection epoch names
|
|
36
|
+
* the user under, and the public key is the did:key's own multibase.
|
|
37
|
+
*
|
|
38
|
+
* @param options {object}
|
|
39
|
+
* @param options.puk {Puk}
|
|
40
|
+
* @returns {RecipientPublicKey}
|
|
41
|
+
*/
|
|
42
|
+
export declare function pukAsRecipient({ puk }: {
|
|
43
|
+
puk: Puk;
|
|
44
|
+
}): RecipientPublicKey;
|
|
45
|
+
/**
|
|
46
|
+
* Recovers every PUK generation from the roster descriptor: each roster epoch
|
|
47
|
+
* is one generation (its id the generation's did:key, its wrapped secret the
|
|
48
|
+
* generation's raw key), escrow-wrapped to every enrolled client -- so this
|
|
49
|
+
* client's key-agreement key unwraps them all, in roster (chronological)
|
|
50
|
+
* order. A generation whose wrap is missing or fails to unwrap is skipped
|
|
51
|
+
* rather than fatal (the cascade then simply cannot recognize or escrow that
|
|
52
|
+
* generation; the current epoch always unwraps or the roster read itself
|
|
53
|
+
* would have refused).
|
|
54
|
+
*
|
|
55
|
+
* @param options {object}
|
|
56
|
+
* @param options.descriptor {CollectionEncryption} the roster descriptor
|
|
57
|
+
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
58
|
+
* (identity) key-agreement key
|
|
59
|
+
* @returns {Promise<Puk[]>} the generations, oldest first
|
|
60
|
+
*/
|
|
61
|
+
export declare function unwrapPukGenerations({ descriptor, clientKeyAgreementKey }: {
|
|
62
|
+
descriptor: CollectionEncryption;
|
|
63
|
+
clientKeyAgreementKey: IKeyAgreementKey;
|
|
64
|
+
}): Promise<Puk[]>;
|
|
65
|
+
/**
|
|
66
|
+
* What one collection's cascade step did: `noop` (already on the current
|
|
67
|
+
* PUK), `installed` (a pre-epoch collection on a first-generation account
|
|
68
|
+
* gained its first epoch; nothing to retire), `escrowed` (the current PUK's
|
|
69
|
+
* wrap was completed into history with no stale epoch to rotate), or
|
|
70
|
+
* `rotated` (a fresh epoch sealed to the current PUK, the stale generations
|
|
71
|
+
* retired -- the pre-epoch install falls through to this).
|
|
72
|
+
*/
|
|
73
|
+
export type CollectionPukRotationOutcome = 'noop' | 'installed' | 'escrowed' | 'rotated';
|
|
74
|
+
/**
|
|
75
|
+
* Brings ONE encrypted collection's epoch roster onto the current PUK -- the
|
|
76
|
+
* per-collection op of the revocation cascade and of the completion sweep:
|
|
77
|
+
*
|
|
78
|
+
* - **No epochs yet**: install the newest PRIOR generation as the first epoch
|
|
79
|
+
* (see the module doc), wrapped to that generation and the current PUK,
|
|
80
|
+
* then fall through to the rotation. A first-generation account (nothing
|
|
81
|
+
* prior) installs the current PUK alone and is done.
|
|
82
|
+
* - **Stale current epoch** (names a non-current generation): one
|
|
83
|
+
* `replaceRecipient` write -- the current PUK escrowed into every epoch,
|
|
84
|
+
* a fresh epoch minted without the stale generations. Two requests per
|
|
85
|
+
* collection; app recipients and other readers ride through untouched (the
|
|
86
|
+
* default did:key resolver re-wraps them).
|
|
87
|
+
* - **Current already** and fully escrowed: no write at all, so a naive
|
|
88
|
+
* re-run after a mid-cascade crash converges with zero redundant epochs.
|
|
89
|
+
*
|
|
90
|
+
* The pull axis is deliberately a no-op here: a PUK rotation follows a
|
|
91
|
+
* document edit (client revocation, code retirement) that already killed the
|
|
92
|
+
* revoked party's server-side access everywhere under the current-key-set
|
|
93
|
+
* rule -- there is no per-collection revoke.
|
|
94
|
+
*
|
|
95
|
+
* @param options {object}
|
|
96
|
+
* @param options.store {EncryptionDescriptorStore} the collection's
|
|
97
|
+
* descriptor store
|
|
98
|
+
* @param options.puk {Puk} the roster's CURRENT PUK
|
|
99
|
+
* @param options.generations {Puk[]} every roster generation this client
|
|
100
|
+
* could unwrap ({@link unwrapPukGenerations}), oldest first
|
|
101
|
+
* @returns {Promise<CollectionPukRotationOutcome>}
|
|
102
|
+
*/
|
|
103
|
+
export declare function rotateCollectionEpochsToPuk({ store, puk, generations }: {
|
|
104
|
+
store: EncryptionDescriptorStore;
|
|
105
|
+
puk: Puk;
|
|
106
|
+
generations: Puk[];
|
|
107
|
+
}): Promise<CollectionPukRotationOutcome>;
|
|
108
|
+
/**
|
|
109
|
+
* What the collection fan-out did, per collection id: the outcomes for every
|
|
110
|
+
* collection that needed (or took) work, and the per-collection failures the
|
|
111
|
+
* caller surfaces -- the cascade never aborts on one stuck collection.
|
|
112
|
+
*/
|
|
113
|
+
export interface PukCascadeResult {
|
|
114
|
+
outcomes: Record<string, CollectionPukRotationOutcome>;
|
|
115
|
+
failed: Array<{
|
|
116
|
+
collectionId: string;
|
|
117
|
+
error: unknown;
|
|
118
|
+
}>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The collection fan-out of the PUK rotation cascade: re-epochs every named
|
|
122
|
+
* collection onto the roster's current PUK, in parallel, unwrapping the PUK
|
|
123
|
+
* generations from the roster once. The wallet supplies what only it knows --
|
|
124
|
+
* which collections exist (`collectionIds`) and how to reach each one's
|
|
125
|
+
* descriptor (`storeFor`); the per-collection staleness rule and re-epoch live
|
|
126
|
+
* in {@link rotateCollectionEpochsToPuk}.
|
|
127
|
+
*
|
|
128
|
+
* A collection that fails is reported in `failed` and the rest proceed; the
|
|
129
|
+
* caller decides what a failure means (the login-time completion sweep is the
|
|
130
|
+
* standing backstop, and the staleness rule makes a naive full re-run
|
|
131
|
+
* converge with zero redundant epochs).
|
|
132
|
+
*
|
|
133
|
+
* @param options {object}
|
|
134
|
+
* @param options.collectionIds {string[]} the encrypted collections to
|
|
135
|
+
* cover, deduplicated by the caller
|
|
136
|
+
* @param options.storeFor {Function} `(collectionId) =>
|
|
137
|
+
* EncryptionDescriptorStore` -- the collection's descriptor store
|
|
138
|
+
* @param [options.isEncrypted] {Function} `(collectionId) =>
|
|
139
|
+
* Promise<boolean>` -- optional pre-filter, checked inside each collection's
|
|
140
|
+
* own task so a throwing check lands in that collection's `failed` entry
|
|
141
|
+
* (e.g. a standard collection an account never provisioned server-side)
|
|
142
|
+
* @param options.rosterDescriptor {CollectionEncryption} the freshly read
|
|
143
|
+
* `key-map/puk.json` roster (the source of the PUK generations)
|
|
144
|
+
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
145
|
+
* (identity) key-agreement key, unwrapping the generations
|
|
146
|
+
* @param options.puk {Puk} the roster's current PUK
|
|
147
|
+
* @returns {Promise<PukCascadeResult>}
|
|
148
|
+
*/
|
|
149
|
+
export declare function cascadeCollectionsToPuk({ collectionIds, storeFor, isEncrypted, rosterDescriptor, clientKeyAgreementKey, puk }: {
|
|
150
|
+
collectionIds: string[];
|
|
151
|
+
storeFor: (collectionId: string) => EncryptionDescriptorStore;
|
|
152
|
+
isEncrypted?: (collectionId: string) => Promise<boolean>;
|
|
153
|
+
rosterDescriptor: CollectionEncryption;
|
|
154
|
+
clientKeyAgreementKey: IKeyAgreementKey;
|
|
155
|
+
puk: Puk;
|
|
156
|
+
}): Promise<PukCascadeResult>;
|
|
157
|
+
//# sourceMappingURL=pukCascade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pukCascade.d.ts","sourceRoot":"","sources":["../../src/keys/pukCascade.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAML,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAgB,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAEjD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,GAAG,CAAA;CAAE,GAAG,kBAAkB,CAKxE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,UAAU,EACV,qBAAqB,EACtB,EAAE;IACD,UAAU,EAAE,oBAAoB,CAAA;IAChC,qBAAqB,EAAE,gBAAgB,CAAA;CACxC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAkBjB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GACtC,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAA;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,2BAA2B,CAAC,EAChD,KAAK,EACL,GAAG,EACH,WAAW,EACZ,EAAE;IACD,KAAK,EAAE,yBAAyB,CAAA;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,WAAW,EAAE,GAAG,EAAE,CAAA;CACnB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA2HxC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAA;IACtD,MAAM,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,uBAAuB,CAAC,EAC5C,aAAa,EACb,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,GAAG,EACJ,EAAE;IACD,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,yBAAyB,CAAA;IAC7D,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACxD,gBAAgB,EAAE,oBAAoB,CAAA;IACtC,qBAAqB,EAAE,gBAAgB,CAAA;IACvC,GAAG,EAAE,GAAG,CAAA;CACT,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAwB5B"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { addRecipient, epochKeyIdFor, initRecipients, replaceRecipient, unwrapEpochSecret } from '@interop/was-client/edv';
|
|
2
|
+
import { ValidationError } from '@interop/was-client';
|
|
3
|
+
import { pukVaultKeys } from './puk.js';
|
|
4
|
+
/**
|
|
5
|
+
* A PUK presented as an epoch-roster recipient: the kid is the
|
|
6
|
+
* self-describing `<did:key>#<fingerprint>` form every collection epoch names
|
|
7
|
+
* the user under, and the public key is the did:key's own multibase.
|
|
8
|
+
*
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.puk {Puk}
|
|
11
|
+
* @returns {RecipientPublicKey}
|
|
12
|
+
*/
|
|
13
|
+
export function pukAsRecipient({ puk }) {
|
|
14
|
+
return {
|
|
15
|
+
id: epochKeyIdFor(puk.id),
|
|
16
|
+
publicKeyMultibase: puk.id.split(':')[2]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Recovers every PUK generation from the roster descriptor: each roster epoch
|
|
21
|
+
* is one generation (its id the generation's did:key, its wrapped secret the
|
|
22
|
+
* generation's raw key), escrow-wrapped to every enrolled client -- so this
|
|
23
|
+
* client's key-agreement key unwraps them all, in roster (chronological)
|
|
24
|
+
* order. A generation whose wrap is missing or fails to unwrap is skipped
|
|
25
|
+
* rather than fatal (the cascade then simply cannot recognize or escrow that
|
|
26
|
+
* generation; the current epoch always unwraps or the roster read itself
|
|
27
|
+
* would have refused).
|
|
28
|
+
*
|
|
29
|
+
* @param options {object}
|
|
30
|
+
* @param options.descriptor {CollectionEncryption} the roster descriptor
|
|
31
|
+
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
32
|
+
* (identity) key-agreement key
|
|
33
|
+
* @returns {Promise<Puk[]>} the generations, oldest first
|
|
34
|
+
*/
|
|
35
|
+
export async function unwrapPukGenerations({ descriptor, clientKeyAgreementKey }) {
|
|
36
|
+
const generations = [];
|
|
37
|
+
for (const epoch of descriptor.epochs ?? []) {
|
|
38
|
+
const entry = epoch.recipients.find(recipient => recipient.header.kid === clientKeyAgreementKey.id);
|
|
39
|
+
if (!entry) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const secret = await unwrapEpochSecret({
|
|
43
|
+
entry,
|
|
44
|
+
keyAgreementKey: clientKeyAgreementKey
|
|
45
|
+
});
|
|
46
|
+
if (secret) {
|
|
47
|
+
generations.push({ id: epoch.id, secret });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return generations;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Brings ONE encrypted collection's epoch roster onto the current PUK -- the
|
|
54
|
+
* per-collection op of the revocation cascade and of the completion sweep:
|
|
55
|
+
*
|
|
56
|
+
* - **No epochs yet**: install the newest PRIOR generation as the first epoch
|
|
57
|
+
* (see the module doc), wrapped to that generation and the current PUK,
|
|
58
|
+
* then fall through to the rotation. A first-generation account (nothing
|
|
59
|
+
* prior) installs the current PUK alone and is done.
|
|
60
|
+
* - **Stale current epoch** (names a non-current generation): one
|
|
61
|
+
* `replaceRecipient` write -- the current PUK escrowed into every epoch,
|
|
62
|
+
* a fresh epoch minted without the stale generations. Two requests per
|
|
63
|
+
* collection; app recipients and other readers ride through untouched (the
|
|
64
|
+
* default did:key resolver re-wraps them).
|
|
65
|
+
* - **Current already** and fully escrowed: no write at all, so a naive
|
|
66
|
+
* re-run after a mid-cascade crash converges with zero redundant epochs.
|
|
67
|
+
*
|
|
68
|
+
* The pull axis is deliberately a no-op here: a PUK rotation follows a
|
|
69
|
+
* document edit (client revocation, code retirement) that already killed the
|
|
70
|
+
* revoked party's server-side access everywhere under the current-key-set
|
|
71
|
+
* rule -- there is no per-collection revoke.
|
|
72
|
+
*
|
|
73
|
+
* @param options {object}
|
|
74
|
+
* @param options.store {EncryptionDescriptorStore} the collection's
|
|
75
|
+
* descriptor store
|
|
76
|
+
* @param options.puk {Puk} the roster's CURRENT PUK
|
|
77
|
+
* @param options.generations {Puk[]} every roster generation this client
|
|
78
|
+
* could unwrap ({@link unwrapPukGenerations}), oldest first
|
|
79
|
+
* @returns {Promise<CollectionPukRotationOutcome>}
|
|
80
|
+
*/
|
|
81
|
+
export async function rotateCollectionEpochsToPuk({ store, puk, generations }) {
|
|
82
|
+
const current = await store.read();
|
|
83
|
+
if (current === null) {
|
|
84
|
+
return 'noop';
|
|
85
|
+
}
|
|
86
|
+
let descriptor = current.descriptor;
|
|
87
|
+
const staleGenerations = generations.filter(generation => generation.id !== puk.id);
|
|
88
|
+
if (!descriptor.epochs?.length || !descriptor.currentEpoch) {
|
|
89
|
+
// Pre-epoch: the collection's envelopes are sealed to the era's PUK KAK,
|
|
90
|
+
// which -- the PUK being the epoch construction -- makes them epoch-of-
|
|
91
|
+
// that-generation envelopes. Install that generation as the first epoch.
|
|
92
|
+
const previous = staleGenerations[staleGenerations.length - 1];
|
|
93
|
+
if (!previous) {
|
|
94
|
+
await initRecipients({
|
|
95
|
+
store,
|
|
96
|
+
recipients: [pukAsRecipient({ puk })],
|
|
97
|
+
epoch: { epochId: puk.id, secret: puk.secret }
|
|
98
|
+
});
|
|
99
|
+
return 'installed';
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
descriptor = await initRecipients({
|
|
103
|
+
store,
|
|
104
|
+
recipients: [
|
|
105
|
+
pukAsRecipient({ puk: previous }),
|
|
106
|
+
pukAsRecipient({ puk })
|
|
107
|
+
],
|
|
108
|
+
epoch: { epochId: previous.id, secret: previous.secret }
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
// A concurrent cascade won the first-epoch race; re-read and continue
|
|
113
|
+
// into the rotation below against whatever it installed.
|
|
114
|
+
if (!(err instanceof ValidationError)) {
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
const reread = await store.read();
|
|
118
|
+
if (reread === null) {
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
descriptor = reread.descriptor;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const currentEpoch = descriptor.epochs.find(epoch => epoch.id === descriptor.currentEpoch) ??
|
|
125
|
+
descriptor.epochs[descriptor.epochs.length - 1];
|
|
126
|
+
const currentKids = new Set(currentEpoch.recipients.map(entry => entry.header.kid));
|
|
127
|
+
const staleKids = staleGenerations
|
|
128
|
+
.map(generation => epochKeyIdFor(generation.id))
|
|
129
|
+
.filter(kid => currentKids.has(kid));
|
|
130
|
+
const pukKid = epochKeyIdFor(puk.id);
|
|
131
|
+
if (staleKids.length === 0) {
|
|
132
|
+
const escrowComplete = (descriptor.epochs ?? []).every(epoch => epoch.recipients.some(entry => entry.header.kid === pukKid));
|
|
133
|
+
if (currentKids.has(pukKid) && escrowComplete) {
|
|
134
|
+
return 'noop';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (staleKids.length > 0) {
|
|
138
|
+
// The escrow owner: the newest stale generation still named by the
|
|
139
|
+
// current epoch, which the cascade invariant escrowed into every prior
|
|
140
|
+
// epoch -- so it unwraps the whole history for the fresh PUK's escrow.
|
|
141
|
+
const ownerGeneration = [...staleGenerations]
|
|
142
|
+
.reverse()
|
|
143
|
+
.find(generation => currentKids.has(epochKeyIdFor(generation.id)));
|
|
144
|
+
const owner = pukVaultKeys({ puk: ownerGeneration });
|
|
145
|
+
await replaceRecipient({
|
|
146
|
+
store,
|
|
147
|
+
retire: staleKids,
|
|
148
|
+
recipient: pukAsRecipient({ puk }),
|
|
149
|
+
owner: { keyAgreementKey: owner.keyAgreementKey },
|
|
150
|
+
pull: async () => { }
|
|
151
|
+
});
|
|
152
|
+
return 'rotated';
|
|
153
|
+
}
|
|
154
|
+
if (!currentKids.has(pukKid)) {
|
|
155
|
+
// No stale generation to retire, but the current PUK is not a recipient
|
|
156
|
+
// at all: this collection's roster is not PUK-owned in a shape this
|
|
157
|
+
// cascade can heal -- surface it rather than silently minting an epoch
|
|
158
|
+
// whose history the account cannot read.
|
|
159
|
+
throw new Error('The collection current epoch names no PUK generation this client ' +
|
|
160
|
+
'can recognize; its roster cannot be rotated to the current PUK.');
|
|
161
|
+
}
|
|
162
|
+
// Escrow completion only: the current epoch is already on the current PUK,
|
|
163
|
+
// but some historical epoch is missing its wrap. The owner must unwrap
|
|
164
|
+
// exactly those epochs -- the newest generation named by every incomplete
|
|
165
|
+
// epoch.
|
|
166
|
+
const incomplete = (descriptor.epochs ?? []).filter(epoch => !epoch.recipients.some(entry => entry.header.kid === pukKid));
|
|
167
|
+
const escrowOwner = [...generations]
|
|
168
|
+
.reverse()
|
|
169
|
+
.find(generation => incomplete.every(epoch => epoch.recipients.some(entry => entry.header.kid === epochKeyIdFor(generation.id))));
|
|
170
|
+
if (!escrowOwner) {
|
|
171
|
+
throw new Error("The current PUK cannot be escrowed into this collection's history: " +
|
|
172
|
+
'no held PUK generation is a recipient of every incomplete epoch.');
|
|
173
|
+
}
|
|
174
|
+
const owner = pukVaultKeys({ puk: escrowOwner });
|
|
175
|
+
await addRecipient({
|
|
176
|
+
store,
|
|
177
|
+
recipient: pukAsRecipient({ puk }),
|
|
178
|
+
owner: { keyAgreementKey: owner.keyAgreementKey }
|
|
179
|
+
});
|
|
180
|
+
return 'escrowed';
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The collection fan-out of the PUK rotation cascade: re-epochs every named
|
|
184
|
+
* collection onto the roster's current PUK, in parallel, unwrapping the PUK
|
|
185
|
+
* generations from the roster once. The wallet supplies what only it knows --
|
|
186
|
+
* which collections exist (`collectionIds`) and how to reach each one's
|
|
187
|
+
* descriptor (`storeFor`); the per-collection staleness rule and re-epoch live
|
|
188
|
+
* in {@link rotateCollectionEpochsToPuk}.
|
|
189
|
+
*
|
|
190
|
+
* A collection that fails is reported in `failed` and the rest proceed; the
|
|
191
|
+
* caller decides what a failure means (the login-time completion sweep is the
|
|
192
|
+
* standing backstop, and the staleness rule makes a naive full re-run
|
|
193
|
+
* converge with zero redundant epochs).
|
|
194
|
+
*
|
|
195
|
+
* @param options {object}
|
|
196
|
+
* @param options.collectionIds {string[]} the encrypted collections to
|
|
197
|
+
* cover, deduplicated by the caller
|
|
198
|
+
* @param options.storeFor {Function} `(collectionId) =>
|
|
199
|
+
* EncryptionDescriptorStore` -- the collection's descriptor store
|
|
200
|
+
* @param [options.isEncrypted] {Function} `(collectionId) =>
|
|
201
|
+
* Promise<boolean>` -- optional pre-filter, checked inside each collection's
|
|
202
|
+
* own task so a throwing check lands in that collection's `failed` entry
|
|
203
|
+
* (e.g. a standard collection an account never provisioned server-side)
|
|
204
|
+
* @param options.rosterDescriptor {CollectionEncryption} the freshly read
|
|
205
|
+
* `key-map/puk.json` roster (the source of the PUK generations)
|
|
206
|
+
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
207
|
+
* (identity) key-agreement key, unwrapping the generations
|
|
208
|
+
* @param options.puk {Puk} the roster's current PUK
|
|
209
|
+
* @returns {Promise<PukCascadeResult>}
|
|
210
|
+
*/
|
|
211
|
+
export async function cascadeCollectionsToPuk({ collectionIds, storeFor, isEncrypted, rosterDescriptor, clientKeyAgreementKey, puk }) {
|
|
212
|
+
const generations = await unwrapPukGenerations({
|
|
213
|
+
descriptor: rosterDescriptor,
|
|
214
|
+
clientKeyAgreementKey
|
|
215
|
+
});
|
|
216
|
+
const outcomes = {};
|
|
217
|
+
const failed = [];
|
|
218
|
+
await Promise.all(collectionIds.map(async (collectionId) => {
|
|
219
|
+
try {
|
|
220
|
+
if (isEncrypted && !(await isEncrypted(collectionId))) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
outcomes[collectionId] = await rotateCollectionEpochsToPuk({
|
|
224
|
+
store: storeFor(collectionId),
|
|
225
|
+
puk,
|
|
226
|
+
generations
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
failed.push({ collectionId, error: err });
|
|
231
|
+
}
|
|
232
|
+
}));
|
|
233
|
+
return { outcomes, failed };
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=pukCascade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pukCascade.js","sourceRoot":"","sources":["../../src/keys/pukCascade.ts"],"names":[],"mappings":"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"}
|