@interop/wallet-core 0.16.0 → 0.18.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 +13 -13
- package/dist/clients/index.d.ts +4 -3
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +3 -2
- package/dist/clients/index.js.map +1 -1
- package/dist/clients/policy.d.ts +3 -3
- package/dist/clients/policy.d.ts.map +1 -1
- package/dist/clients/policy.js +1 -1
- package/dist/clients/revocation.d.ts +18 -15
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +42 -26
- package/dist/clients/revocation.js.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +46 -24
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.js +106 -48
- package/dist/clients/rosterPolicy.js.map +1 -1
- package/dist/descriptors/refresh.d.ts +3 -1
- package/dist/descriptors/refresh.d.ts.map +1 -1
- package/dist/descriptors/refresh.js +3 -1
- package/dist/descriptors/refresh.js.map +1 -1
- package/dist/display/alignment.d.ts +8 -2
- package/dist/display/alignment.d.ts.map +1 -1
- package/dist/display/alignment.js +11 -8
- package/dist/display/alignment.js.map +1 -1
- package/dist/display/displayFields.d.ts +6 -2
- package/dist/display/displayFields.d.ts.map +1 -1
- package/dist/display/displayFields.js.map +1 -1
- package/dist/display/evidence.d.ts +9 -3
- package/dist/display/evidence.d.ts.map +1 -1
- package/dist/display/evidence.js +3 -1
- package/dist/display/evidence.js.map +1 -1
- package/dist/display/index.d.ts +1 -1
- package/dist/display/index.d.ts.map +1 -1
- package/dist/display/index.js +1 -1
- package/dist/display/index.js.map +1 -1
- package/dist/display/issuer.d.ts +12 -4
- package/dist/display/issuer.d.ts.map +1 -1
- package/dist/display/issuer.js.map +1 -1
- package/dist/display/obv3.d.ts +7 -2
- package/dist/display/obv3.d.ts.map +1 -1
- package/dist/display/obv3.js +14 -24
- package/dist/display/obv3.js.map +1 -1
- package/dist/display/parse.d.ts +6 -2
- package/dist/display/parse.d.ts.map +1 -1
- package/dist/display/parse.js +6 -2
- package/dist/display/parse.js.map +1 -1
- package/dist/display/subject.d.ts +4 -0
- package/dist/display/subject.d.ts.map +1 -1
- package/dist/display/subject.js +12 -10
- package/dist/display/subject.js.map +1 -1
- package/dist/display/text.d.ts +11 -0
- package/dist/display/text.d.ts.map +1 -1
- package/dist/display/text.js +20 -4
- package/dist/display/text.js.map +1 -1
- package/dist/display/types.js +1 -1
- package/dist/display/types.js.map +1 -1
- package/dist/display/validity.js +4 -4
- package/dist/display/validity.js.map +1 -1
- package/dist/display/verificationView.d.ts +21 -7
- package/dist/display/verificationView.d.ts.map +1 -1
- package/dist/display/verificationView.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts +21 -19
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +98 -34
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/enrollment/index.d.ts +1 -1
- package/dist/enrollment/index.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/keys/clientKeyRecord.d.ts +19 -17
- package/dist/keys/clientKeyRecord.d.ts.map +1 -1
- package/dist/keys/clientKeyRecord.js +77 -41
- package/dist/keys/clientKeyRecord.js.map +1 -1
- package/dist/keys/index.d.ts +19 -17
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +16 -14
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterStore.d.ts +3 -3
- package/dist/keys/rosterStore.d.ts.map +1 -1
- package/dist/keys/rosterStore.js +13 -13
- package/dist/keys/rosterStore.js.map +1 -1
- package/dist/keys/userKey.d.ts +43 -0
- package/dist/keys/userKey.d.ts.map +1 -0
- package/dist/keys/{puk.js → userKey.js} +23 -21
- package/dist/keys/userKey.js.map +1 -0
- package/dist/keys/{pukCascade.d.ts → userKeyCascade.d.ts} +69 -69
- package/dist/keys/userKeyCascade.d.ts.map +1 -0
- package/dist/keys/{pukCascade.js → userKeyCascade.js} +77 -75
- package/dist/keys/userKeyCascade.js.map +1 -0
- package/dist/keys/{pukRoster.d.ts → userKeyRoster.d.ts} +141 -64
- package/dist/keys/userKeyRoster.d.ts.map +1 -0
- package/dist/keys/{pukRoster.js → userKeyRoster.js} +200 -72
- package/dist/keys/userKeyRoster.js.map +1 -0
- package/dist/recovery/index.d.ts +1 -1
- package/dist/recovery/index.js +1 -1
- package/dist/recovery/recoveryCode.d.ts +1 -1
- package/dist/recovery/recoveryCode.js +6 -6
- package/dist/recovery/recoveryRecord.d.ts +1 -1
- package/dist/recovery/recoveryWebvh.d.ts +1 -1
- package/dist/recovery/recoveryWebvh.js +1 -1
- package/dist/request/classify.d.ts +15 -1
- package/dist/request/classify.d.ts.map +1 -1
- package/dist/request/classify.js +38 -14
- package/dist/request/classify.js.map +1 -1
- package/dist/request/composeVp.d.ts.map +1 -1
- package/dist/request/composeVp.js +10 -3
- package/dist/request/composeVp.js.map +1 -1
- package/dist/request/matching.d.ts +6 -0
- package/dist/request/matching.d.ts.map +1 -1
- package/dist/request/matching.js +33 -8
- package/dist/request/matching.js.map +1 -1
- package/dist/request/parse.d.ts +5 -2
- package/dist/request/parse.d.ts.map +1 -1
- package/dist/request/parse.js +30 -5
- package/dist/request/parse.js.map +1 -1
- package/dist/request/presentationSuite.d.ts.map +1 -1
- package/dist/request/presentationSuite.js +6 -2
- package/dist/request/presentationSuite.js.map +1 -1
- package/dist/request/processRequest.js +1 -1
- package/dist/request/processRequest.js.map +1 -1
- package/dist/space/activity.d.ts +22 -8
- package/dist/space/activity.d.ts.map +1 -1
- package/dist/space/activity.js +19 -7
- package/dist/space/activity.js.map +1 -1
- package/dist/space/collections.d.ts +33 -21
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +34 -22
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +2 -2
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +2 -2
- package/dist/space/index.js.map +1 -1
- package/dist/space/wasLink.d.ts +6 -2
- package/dist/space/wasLink.d.ts.map +1 -1
- package/dist/space/wasLink.js +5 -2
- package/dist/space/wasLink.js.map +1 -1
- package/dist/sync/contactsConflict.d.ts +1 -1
- package/dist/sync/contactsConflict.js +1 -1
- package/dist/sync/engine.d.ts +33 -11
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +4 -3
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/pull.d.ts +5 -3
- package/dist/sync/pull.d.ts.map +1 -1
- package/dist/sync/pull.js +34 -10
- package/dist/sync/pull.js.map +1 -1
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +24 -8
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/types.d.ts +30 -6
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/webvh/didWebvh.d.ts +29 -1
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +46 -11
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/index.d.ts +1 -1
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +1 -1
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/listClients.d.ts +19 -0
- package/dist/webvh/listClients.d.ts.map +1 -1
- package/dist/webvh/listClients.js +37 -1
- package/dist/webvh/listClients.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +11 -3
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +83 -14
- package/dist/webvh/revokeClient.js.map +1 -1
- package/package.json +3 -3
- package/dist/keys/puk.d.ts +0 -42
- package/dist/keys/puk.d.ts.map +0 -1
- package/dist/keys/puk.js.map +0 -1
- package/dist/keys/pukCascade.d.ts.map +0 -1
- package/dist/keys/pukCascade.js.map +0 -1
- package/dist/keys/pukRoster.d.ts.map +0 -1
- package/dist/keys/pukRoster.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userKeyCascade.d.ts","sourceRoot":"","sources":["../../src/keys/userKeyCascade.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,EAAoB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;CACjB,GAAG,kBAAkB,CAKrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,UAAU,EACV,qBAAqB,EACtB,EAAE;IACD,UAAU,EAAE,oBAAoB,CAAA;IAChC,qBAAqB,EAAE,gBAAgB,CAAA;CACxC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAkBrB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,gCAAgC,GAC1C,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAA;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,KAAK,EACL,OAAO,EACP,WAAW,EACZ,EAAE;IACD,KAAK,EAAE,yBAAyB,CAAA;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,OAAO,EAAE,CAAA;CACvB,GAAG,OAAO,CAAC,gCAAgC,CAAC,CA6H5C;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAA;IAC1D,MAAM,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,2BAA2B,CAAC,EAChD,aAAa,EACb,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,OAAO,EACR,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,OAAO,EAAE,OAAO,CAAA;CACjB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAwBhC"}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
import { addRecipient, epochKeyIdFor, initRecipients, replaceRecipient, unwrapEpochSecret } from '@interop/was-client/edv';
|
|
2
2
|
import { ValidationError } from '@interop/was-client';
|
|
3
|
-
import {
|
|
3
|
+
import { userKeyVaultKeys } from './userKey.js';
|
|
4
4
|
/**
|
|
5
|
-
* A
|
|
5
|
+
* A user key presented as an epoch-roster recipient: the kid is the
|
|
6
6
|
* self-describing `<did:key>#<fingerprint>` form every collection epoch names
|
|
7
7
|
* the user under, and the public key is the did:key's own multibase.
|
|
8
8
|
*
|
|
9
9
|
* @param options {object}
|
|
10
|
-
* @param options.
|
|
10
|
+
* @param options.userKey {UserKey}
|
|
11
11
|
* @returns {RecipientPublicKey}
|
|
12
12
|
*/
|
|
13
|
-
export function
|
|
13
|
+
export function userKeyAsRecipient({ userKey }) {
|
|
14
14
|
return {
|
|
15
|
-
id: epochKeyIdFor(
|
|
16
|
-
publicKeyMultibase:
|
|
15
|
+
id: epochKeyIdFor(userKey.id),
|
|
16
|
+
publicKeyMultibase: userKey.id.split(':')[2]
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Recovers every
|
|
21
|
-
* is one generation (its id the generation's did:key, its wrapped secret
|
|
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
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
20
|
+
* Recovers every user key generation from the roster descriptor: each roster
|
|
21
|
+
* epoch is one generation (its id the generation's did:key, its wrapped secret
|
|
22
|
+
* the generation's raw key), escrow-wrapped to every enrolled client -- so this
|
|
23
|
+
* client's key-agreement key unwraps them all, in roster (chronological) order.
|
|
24
|
+
* A generation whose wrap is missing or fails to unwrap is skipped rather than
|
|
25
|
+
* fatal (the cascade then simply cannot recognize or escrow that generation;
|
|
26
|
+
* the current epoch always unwraps or the roster read itself would have
|
|
27
|
+
* refused).
|
|
28
28
|
*
|
|
29
29
|
* @param options {object}
|
|
30
30
|
* @param options.descriptor {CollectionEncryption} the roster descriptor
|
|
31
31
|
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
32
32
|
* (identity) key-agreement key
|
|
33
|
-
* @returns {Promise<
|
|
33
|
+
* @returns {Promise<UserKey[]>} the generations, oldest first
|
|
34
34
|
*/
|
|
35
|
-
export async function
|
|
35
|
+
export async function unwrapUserKeyGenerations({ descriptor, clientKeyAgreementKey }) {
|
|
36
36
|
const generations = [];
|
|
37
37
|
for (const epoch of descriptor.epochs ?? []) {
|
|
38
38
|
const entry = epoch.recipients.find(recipient => recipient.header.kid === clientKeyAgreementKey.id);
|
|
@@ -50,22 +50,22 @@ export async function unwrapPukGenerations({ descriptor, clientKeyAgreementKey }
|
|
|
50
50
|
return generations;
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
* Brings ONE encrypted collection's epoch roster onto the current
|
|
54
|
-
* per-collection op of the revocation cascade and of the completion sweep:
|
|
53
|
+
* Brings ONE encrypted collection's epoch roster onto the current user key --
|
|
54
|
+
* the per-collection op of the revocation cascade and of the completion sweep:
|
|
55
55
|
*
|
|
56
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
|
|
57
|
+
* (see the module doc), wrapped to that generation and the current user key,
|
|
58
58
|
* then fall through to the rotation. A first-generation account (nothing
|
|
59
|
-
* prior) installs the current
|
|
59
|
+
* prior) installs the current user key alone and is done.
|
|
60
60
|
* - **Stale current epoch** (names a non-current generation): one
|
|
61
|
-
* `replaceRecipient` write -- the current
|
|
61
|
+
* `replaceRecipient` write -- the current user key escrowed into every epoch,
|
|
62
62
|
* a fresh epoch minted without the stale generations. Two requests per
|
|
63
63
|
* collection; app recipients and other readers ride through untouched (the
|
|
64
64
|
* default did:key resolver re-wraps them).
|
|
65
65
|
* - **Current already** and fully escrowed: no write at all, so a naive
|
|
66
66
|
* re-run after a mid-cascade crash converges with zero redundant epochs.
|
|
67
67
|
*
|
|
68
|
-
* The pull axis is deliberately a no-op here: a
|
|
68
|
+
* The pull axis is deliberately a no-op here: a user key rotation follows a
|
|
69
69
|
* document edit (client revocation, code retirement) that already killed the
|
|
70
70
|
* revoked party's server-side access everywhere under the current-key-set
|
|
71
71
|
* rule -- there is no per-collection revoke.
|
|
@@ -73,40 +73,42 @@ export async function unwrapPukGenerations({ descriptor, clientKeyAgreementKey }
|
|
|
73
73
|
* @param options {object}
|
|
74
74
|
* @param options.store {EncryptionDescriptorStore} the collection's
|
|
75
75
|
* descriptor store
|
|
76
|
-
* @param options.
|
|
77
|
-
* @param options.generations {
|
|
78
|
-
* could unwrap ({@link
|
|
79
|
-
* @returns {Promise<
|
|
76
|
+
* @param options.userKey {UserKey} the roster's CURRENT user key
|
|
77
|
+
* @param options.generations {UserKey[]} every roster generation this client
|
|
78
|
+
* could unwrap ({@link unwrapUserKeyGenerations}), oldest first
|
|
79
|
+
* @returns {Promise<CollectionUserKeyRotationOutcome>}
|
|
80
80
|
*/
|
|
81
|
-
export async function
|
|
81
|
+
export async function rotateCollectionEpochsToUserKey({ store, userKey, generations }) {
|
|
82
82
|
const current = await store.read();
|
|
83
83
|
if (current === null) {
|
|
84
84
|
return 'noop';
|
|
85
85
|
}
|
|
86
86
|
let descriptor = current.descriptor;
|
|
87
|
-
const staleGenerations = generations.filter(generation => generation.id !==
|
|
87
|
+
const staleGenerations = generations.filter(generation => generation.id !== userKey.id);
|
|
88
88
|
if (!descriptor.epochs?.length || !descriptor.currentEpoch) {
|
|
89
|
-
// Pre-epoch: the collection's envelopes are sealed to the era's
|
|
90
|
-
// which -- the
|
|
89
|
+
// Pre-epoch: the collection's envelopes are sealed to the era's user key KAK,
|
|
90
|
+
// which -- the user key being the epoch construction -- makes them epoch-of-
|
|
91
91
|
// that-generation envelopes. Install that generation as the first epoch.
|
|
92
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
93
|
try {
|
|
102
|
-
|
|
94
|
+
const installed = await initRecipients({
|
|
103
95
|
store,
|
|
104
|
-
recipients:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
96
|
+
recipients: previous
|
|
97
|
+
? [
|
|
98
|
+
userKeyAsRecipient({ userKey: previous }),
|
|
99
|
+
userKeyAsRecipient({ userKey })
|
|
100
|
+
]
|
|
101
|
+
: [userKeyAsRecipient({ userKey })],
|
|
102
|
+
epoch: previous
|
|
103
|
+
? { epochId: previous.id, secret: previous.secret }
|
|
104
|
+
: { epochId: userKey.id, secret: userKey.secret }
|
|
109
105
|
});
|
|
106
|
+
if (!previous) {
|
|
107
|
+
// A first-generation account: nothing prior to escrow, nothing to
|
|
108
|
+
// retire, so the install IS the whole step.
|
|
109
|
+
return 'installed';
|
|
110
|
+
}
|
|
111
|
+
descriptor = installed;
|
|
110
112
|
}
|
|
111
113
|
catch (err) {
|
|
112
114
|
// A concurrent cascade won the first-epoch race; re-read and continue
|
|
@@ -127,65 +129,65 @@ export async function rotateCollectionEpochsToPuk({ store, puk, generations }) {
|
|
|
127
129
|
const staleKids = staleGenerations
|
|
128
130
|
.map(generation => epochKeyIdFor(generation.id))
|
|
129
131
|
.filter(kid => currentKids.has(kid));
|
|
130
|
-
const
|
|
132
|
+
const userKeyKid = epochKeyIdFor(userKey.id);
|
|
131
133
|
if (staleKids.length === 0) {
|
|
132
|
-
const escrowComplete = (descriptor.epochs ?? []).every(epoch => epoch.recipients.some(entry => entry.header.kid ===
|
|
133
|
-
if (currentKids.has(
|
|
134
|
+
const escrowComplete = (descriptor.epochs ?? []).every(epoch => epoch.recipients.some(entry => entry.header.kid === userKeyKid));
|
|
135
|
+
if (currentKids.has(userKeyKid) && escrowComplete) {
|
|
134
136
|
return 'noop';
|
|
135
137
|
}
|
|
136
138
|
}
|
|
137
139
|
if (staleKids.length > 0) {
|
|
138
140
|
// The escrow owner: the newest stale generation still named by the
|
|
139
141
|
// current epoch, which the cascade invariant escrowed into every prior
|
|
140
|
-
// epoch -- so it unwraps the whole history for the fresh
|
|
142
|
+
// epoch -- so it unwraps the whole history for the fresh user key's escrow.
|
|
141
143
|
const ownerGeneration = [...staleGenerations]
|
|
142
144
|
.reverse()
|
|
143
145
|
.find(generation => currentKids.has(epochKeyIdFor(generation.id)));
|
|
144
|
-
const owner =
|
|
146
|
+
const owner = userKeyVaultKeys({ userKey: ownerGeneration });
|
|
145
147
|
await replaceRecipient({
|
|
146
148
|
store,
|
|
147
149
|
retire: staleKids,
|
|
148
|
-
recipient:
|
|
150
|
+
recipient: userKeyAsRecipient({ userKey }),
|
|
149
151
|
owner: { keyAgreementKey: owner.keyAgreementKey },
|
|
150
152
|
pull: async () => { }
|
|
151
153
|
});
|
|
152
154
|
return 'rotated';
|
|
153
155
|
}
|
|
154
|
-
if (!currentKids.has(
|
|
155
|
-
// No stale generation to retire, but the current
|
|
156
|
-
// at all: this collection's roster is not
|
|
156
|
+
if (!currentKids.has(userKeyKid)) {
|
|
157
|
+
// No stale generation to retire, but the current user key is not a recipient
|
|
158
|
+
// at all: this collection's roster is not user-key-owned in a shape this
|
|
157
159
|
// cascade can heal -- surface it rather than silently minting an epoch
|
|
158
160
|
// whose history the account cannot read.
|
|
159
|
-
throw new Error('The collection current epoch names no
|
|
160
|
-
'can recognize; its roster cannot be rotated to the current
|
|
161
|
+
throw new Error('The collection current epoch names no user key generation this client ' +
|
|
162
|
+
'can recognize; its roster cannot be rotated to the current user key.');
|
|
161
163
|
}
|
|
162
|
-
// Escrow completion only: the current epoch is already on the current
|
|
164
|
+
// Escrow completion only: the current epoch is already on the current user key,
|
|
163
165
|
// but some historical epoch is missing its wrap. The owner must unwrap
|
|
164
166
|
// exactly those epochs -- the newest generation named by every incomplete
|
|
165
167
|
// epoch.
|
|
166
|
-
const incomplete = (descriptor.epochs ?? []).filter(epoch => !epoch.recipients.some(entry => entry.header.kid ===
|
|
168
|
+
const incomplete = (descriptor.epochs ?? []).filter(epoch => !epoch.recipients.some(entry => entry.header.kid === userKeyKid));
|
|
167
169
|
const escrowOwner = [...generations]
|
|
168
170
|
.reverse()
|
|
169
171
|
.find(generation => incomplete.every(epoch => epoch.recipients.some(entry => entry.header.kid === epochKeyIdFor(generation.id))));
|
|
170
172
|
if (!escrowOwner) {
|
|
171
|
-
throw new Error("The current
|
|
172
|
-
'no held
|
|
173
|
+
throw new Error("The current user key cannot be escrowed into this collection's history: " +
|
|
174
|
+
'no held user key generation is a recipient of every incomplete epoch.');
|
|
173
175
|
}
|
|
174
|
-
const owner =
|
|
176
|
+
const owner = userKeyVaultKeys({ userKey: escrowOwner });
|
|
175
177
|
await addRecipient({
|
|
176
178
|
store,
|
|
177
|
-
recipient:
|
|
179
|
+
recipient: userKeyAsRecipient({ userKey }),
|
|
178
180
|
owner: { keyAgreementKey: owner.keyAgreementKey }
|
|
179
181
|
});
|
|
180
182
|
return 'escrowed';
|
|
181
183
|
}
|
|
182
184
|
/**
|
|
183
|
-
* The collection fan-out of the
|
|
184
|
-
* collection onto the roster's current
|
|
185
|
-
* generations from the roster once. The wallet supplies what only
|
|
186
|
-
* which collections exist (`collectionIds`) and how to reach each
|
|
187
|
-
* descriptor (`storeFor`); the per-collection staleness rule and re-epoch
|
|
188
|
-
* in {@link
|
|
185
|
+
* The collection fan-out of the user key rotation cascade: re-epochs every
|
|
186
|
+
* named collection onto the roster's current user key, in parallel, unwrapping
|
|
187
|
+
* the user key generations from the roster once. The wallet supplies what only
|
|
188
|
+
* it knows -- which collections exist (`collectionIds`) and how to reach each
|
|
189
|
+
* one's descriptor (`storeFor`); the per-collection staleness rule and re-epoch
|
|
190
|
+
* live in {@link rotateCollectionEpochsToUserKey}.
|
|
189
191
|
*
|
|
190
192
|
* A collection that fails is reported in `failed` and the rest proceed; the
|
|
191
193
|
* caller decides what a failure means (the login-time completion sweep is the
|
|
@@ -202,14 +204,14 @@ export async function rotateCollectionEpochsToPuk({ store, puk, generations }) {
|
|
|
202
204
|
* own task so a throwing check lands in that collection's `failed` entry
|
|
203
205
|
* (e.g. a standard collection an account never provisioned server-side)
|
|
204
206
|
* @param options.rosterDescriptor {CollectionEncryption} the freshly read
|
|
205
|
-
* `key-map/
|
|
207
|
+
* `key-map/user-key.json` roster (the source of the user key generations)
|
|
206
208
|
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
207
209
|
* (identity) key-agreement key, unwrapping the generations
|
|
208
|
-
* @param options.
|
|
209
|
-
* @returns {Promise<
|
|
210
|
+
* @param options.userKey {UserKey} the roster's current user key
|
|
211
|
+
* @returns {Promise<UserKeyCascadeResult>}
|
|
210
212
|
*/
|
|
211
|
-
export async function
|
|
212
|
-
const generations = await
|
|
213
|
+
export async function cascadeCollectionsToUserKey({ collectionIds, storeFor, isEncrypted, rosterDescriptor, clientKeyAgreementKey, userKey }) {
|
|
214
|
+
const generations = await unwrapUserKeyGenerations({
|
|
213
215
|
descriptor: rosterDescriptor,
|
|
214
216
|
clientKeyAgreementKey
|
|
215
217
|
});
|
|
@@ -220,9 +222,9 @@ export async function cascadeCollectionsToPuk({ collectionIds, storeFor, isEncry
|
|
|
220
222
|
if (isEncrypted && !(await isEncrypted(collectionId))) {
|
|
221
223
|
return;
|
|
222
224
|
}
|
|
223
|
-
outcomes[collectionId] = await
|
|
225
|
+
outcomes[collectionId] = await rotateCollectionEpochsToUserKey({
|
|
224
226
|
store: storeFor(collectionId),
|
|
225
|
-
|
|
227
|
+
userKey,
|
|
226
228
|
generations
|
|
227
229
|
});
|
|
228
230
|
}
|
|
@@ -232,4 +234,4 @@ export async function cascadeCollectionsToPuk({ collectionIds, storeFor, isEncry
|
|
|
232
234
|
}));
|
|
233
235
|
return { outcomes, failed };
|
|
234
236
|
}
|
|
235
|
-
//# sourceMappingURL=
|
|
237
|
+
//# sourceMappingURL=userKeyCascade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userKeyCascade.js","sourceRoot":"","sources":["../../src/keys/userKeyCascade.ts"],"names":[],"mappings":"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"}
|