@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
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* The
|
|
6
|
-
* `CollectionEncryption` descriptor verbatim, whose current epoch IS the
|
|
7
|
-
* current
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the
|
|
12
|
-
* epoch stamp marks a cached copy stale.
|
|
5
|
+
* The user key wrap set: the `key-map/user-key.json` roster resource. Its body
|
|
6
|
+
* is a `CollectionEncryption` descriptor verbatim, whose current epoch IS the
|
|
7
|
+
* current user key -- the epoch id is the user key's did:key and the wrapped
|
|
8
|
+
* secret is the user key's raw 32-byte key, wrapped to each enrolled client's
|
|
9
|
+
* key-agreement key. The roster is the delivery channel for user key rotation:
|
|
10
|
+
* each client keeps the user key in its own local state under the unlock layer,
|
|
11
|
+
* and the roster's epoch stamp marks a cached copy stale.
|
|
13
12
|
*
|
|
14
13
|
* Everything mutates through was-client's descriptor-store seam (the
|
|
15
14
|
* plain-resource adapter): read-with-etag, compare-and-swap writes, and a
|
|
@@ -18,38 +17,50 @@
|
|
|
18
17
|
*
|
|
19
18
|
* A resource-hosted descriptor gets NONE of the server-side epoch invariants a
|
|
20
19
|
* Collection Description enforces (append-only epochs, monotone
|
|
21
|
-
* `currentEpoch`), so
|
|
20
|
+
* `currentEpoch`), so four client-side compensations are load-bearing alone
|
|
22
21
|
* against a tampering host:
|
|
23
22
|
*
|
|
24
23
|
* - **`epochsMac`** -- the epoch configuration is authenticated under the
|
|
25
24
|
* current epoch's secret, which the server never holds; a fabricated
|
|
26
|
-
* configuration fails the MAC (`
|
|
25
|
+
* configuration fails the MAC (`UserKeyRosterIntegrityError`).
|
|
27
26
|
* - **The epoch pin** -- the latest-seen roster epoch is pinned locally by the
|
|
28
27
|
* consuming app (beside the account-pointer pin); a served
|
|
29
28
|
* roster that rolls back behind the pin is refused
|
|
30
|
-
* (`
|
|
29
|
+
* (`UserKeyRosterContinuityError`) rather than followed. Stale-roster replay
|
|
31
30
|
* thereby lands in the same accepted continuity class as a substituted
|
|
32
31
|
* account pointer.
|
|
33
32
|
* - **The roster delivers, never sources** -- the recipient-key source of
|
|
34
33
|
* record is the locally verified did:webvh document (one `keyAgreement`
|
|
35
34
|
* verification method per enrolled client). When an epoch rotates, each
|
|
36
35
|
* remaining recipient's key is resolved from that document
|
|
37
|
-
* (`
|
|
36
|
+
* (`userKeyRosterRecipientResolver`); a roster entry with no matching document
|
|
38
37
|
* verification method is dropped and never receives a wrap, so a
|
|
39
38
|
* server-injected entry sits ignored. Wraps are minted only by enrolled
|
|
40
39
|
* clients, against log-verified keys.
|
|
40
|
+
* - **`epochsSig`** -- the epoch configuration is additionally SIGNED by the
|
|
41
|
+
* writing client's enrolled Ed25519 key (`userKeyRosterEpochsSigner`), and a
|
|
42
|
+
* read that adopts an epoch this client has not vouched for itself (a
|
|
43
|
+
* rotated read, or a freshly enrolled client's first read) verifies that
|
|
44
|
+
* signature against the locally verified did:webvh document
|
|
45
|
+
* (`verifyUserKeyRosterEpochsSig`). This is the check the `epochsMac` alone
|
|
46
|
+
* cannot make on those paths: the MAC is keyed by a secret unwrapped from
|
|
47
|
+
* the served descriptor itself, so a host that mints its own epoch, wraps
|
|
48
|
+
* it to this client's world-readable key-agreement key, and MACs the
|
|
49
|
+
* fabricated configuration under the same minted secret passes the MAC --
|
|
50
|
+
* but it cannot produce a signature by a key the document backs.
|
|
41
51
|
*/
|
|
42
52
|
import type { IKeyAgreementKey } from '@interop/data-integrity-core';
|
|
43
53
|
import type { CollectionEncryption } from '@interop/was-client';
|
|
44
|
-
import { type EncryptionDescriptorStore, type RecipientPublicKey } from '@interop/was-client/edv';
|
|
45
|
-
import type
|
|
54
|
+
import { type EncryptionDescriptorStore, type EpochsSigner, type RecipientPublicKey } from '@interop/was-client/edv';
|
|
55
|
+
import { type ICapabilityAgent } from '../webvh/zcap.js';
|
|
56
|
+
import type { UserKey } from './userKey.js';
|
|
46
57
|
/**
|
|
47
58
|
* Thrown when a served roster fails its client-side authentication: a
|
|
48
59
|
* missing/unsupported/invalid `epochsMac`, or a descriptor whose `currentEpoch`
|
|
49
60
|
* names no epoch in its own list. The server (or whoever can write to it) has
|
|
50
61
|
* produced a configuration no enrolled client authenticated.
|
|
51
62
|
*/
|
|
52
|
-
export declare class
|
|
63
|
+
export declare class UserKeyRosterIntegrityError extends Error {
|
|
53
64
|
constructor(message: string);
|
|
54
65
|
}
|
|
55
66
|
/**
|
|
@@ -59,7 +70,7 @@ export declare class PukRosterIntegrityError extends Error {
|
|
|
59
70
|
* an older consistent configuration, which a valid `epochsMac` alone cannot
|
|
60
71
|
* catch; refused rather than followed.
|
|
61
72
|
*/
|
|
62
|
-
export declare class
|
|
73
|
+
export declare class UserKeyRosterContinuityError extends Error {
|
|
63
74
|
pinnedEpochId: string;
|
|
64
75
|
constructor({ pinnedEpochId }: {
|
|
65
76
|
pinnedEpochId: string;
|
|
@@ -68,10 +79,10 @@ export declare class PukRosterContinuityError extends Error {
|
|
|
68
79
|
/**
|
|
69
80
|
* Thrown when this client holds no usable wrap in the roster's current epoch
|
|
70
81
|
* (no recipient entry for its key-agreement key, or the entry fails to
|
|
71
|
-
* unwrap). The client cannot obtain the current
|
|
82
|
+
* unwrap). The client cannot obtain the current user key -- it may have been
|
|
72
83
|
* rotated off the roster.
|
|
73
84
|
*/
|
|
74
|
-
export declare class
|
|
85
|
+
export declare class UserKeyRosterUnwrapError extends Error {
|
|
75
86
|
constructor(message: string);
|
|
76
87
|
}
|
|
77
88
|
/**
|
|
@@ -89,6 +100,41 @@ export interface RosterRecipientDocument {
|
|
|
89
100
|
publicKeyMultibase?: string;
|
|
90
101
|
}>;
|
|
91
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* The roster's epoch-configuration signer: signs each roster write's epoch
|
|
105
|
+
* configuration with this client's own Ed25519 signing key, under a `kid`
|
|
106
|
+
* that is the key's public multibase -- exactly the string enrolled as this
|
|
107
|
+
* client's verification method in the did:webvh document, so a reader
|
|
108
|
+
* resolves the signature against the document rather than anything the
|
|
109
|
+
* roster (or the server) supplies.
|
|
110
|
+
*
|
|
111
|
+
* @param options {object}
|
|
112
|
+
* @param options.keyAgent {ICapabilityAgent} this client's signing key
|
|
113
|
+
* agent (the `keyAgent` of `agentsFromSeed`)
|
|
114
|
+
* @returns {EpochsSigner} the `signEpochs` hook for roster writes
|
|
115
|
+
*/
|
|
116
|
+
export declare function userKeyRosterEpochsSigner({ keyAgent }: {
|
|
117
|
+
keyAgent: ICapabilityAgent;
|
|
118
|
+
}): EpochsSigner;
|
|
119
|
+
/**
|
|
120
|
+
* Verifies a served roster's `epochsSig` against the locally verified
|
|
121
|
+
* did:webvh document -- the root of trust the server cannot mint. The
|
|
122
|
+
* signature must be present and supported, its `kid` must be the public
|
|
123
|
+
* multibase of one of the document's verification methods (an enrolled
|
|
124
|
+
* client's signing key), and it must verify over the canonical
|
|
125
|
+
* epoch-configuration payload. Throws {@link UserKeyRosterIntegrityError}
|
|
126
|
+
* otherwise: a configuration no enrolled client signed.
|
|
127
|
+
*
|
|
128
|
+
* @param options {object}
|
|
129
|
+
* @param options.descriptor {CollectionEncryption} the served roster
|
|
130
|
+
* @param options.document {RosterRecipientDocument} the locally verified
|
|
131
|
+
* did:webvh document (never a server-supplied roster field)
|
|
132
|
+
* @returns {Promise<void>}
|
|
133
|
+
*/
|
|
134
|
+
export declare function verifyUserKeyRosterEpochsSig({ descriptor, document }: {
|
|
135
|
+
descriptor: CollectionEncryption;
|
|
136
|
+
document: RosterRecipientDocument;
|
|
137
|
+
}): Promise<void>;
|
|
92
138
|
/**
|
|
93
139
|
* A wallet client's roster kid: its key-agreement key's id exactly as
|
|
94
140
|
* `agentsFromSeed` derives it at the client's own logins
|
|
@@ -122,32 +168,36 @@ export declare function rosterRecipientKid({ signingKeyMultibase, keyAgreementKe
|
|
|
122
168
|
* did:webvh document (never a server-supplied roster field)
|
|
123
169
|
* @returns {function} a `resolveRecipientKey` for `removeRecipient`
|
|
124
170
|
*/
|
|
125
|
-
export declare function
|
|
171
|
+
export declare function userKeyRosterRecipientResolver({ document }: {
|
|
126
172
|
document: RosterRecipientDocument;
|
|
127
173
|
}): (kid: string) => Promise<RecipientPublicKey | null>;
|
|
128
174
|
/**
|
|
129
|
-
* Ensures the roster exists, create-if-absent: an absent roster is
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
175
|
+
* Ensures the roster exists, create-if-absent: an absent roster is initialized
|
|
176
|
+
* with the account's existing user key installed as the first epoch, wrapped to
|
|
177
|
+
* this client's key-agreement key; an existing roster is returned as-is
|
|
178
|
+
* (authentication is the read path's job, and provisioning must never clobber
|
|
179
|
+
* an established roster). Idempotent -- losing the guarded-create race to a
|
|
180
|
+
* concurrent first init converges on the winner's roster.
|
|
135
181
|
*
|
|
136
182
|
* @param options {object}
|
|
137
183
|
* @param options.store {EncryptionDescriptorStore} the roster's descriptor
|
|
138
184
|
* store
|
|
139
|
-
* @param options.
|
|
185
|
+
* @param options.userKey {UserKey} the account's user key
|
|
140
186
|
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
141
187
|
* (identity) key-agreement key -- the roster recipient
|
|
188
|
+
* @param options.signEpochs {EpochsSigner} this client's epoch-configuration
|
|
189
|
+
* signer ({@link userKeyRosterEpochsSigner}), so the first configuration is
|
|
190
|
+
* vouched for by an enrollable key rather than only its own MAC
|
|
142
191
|
* @returns {Promise<CollectionEncryption>} the roster descriptor
|
|
143
192
|
*/
|
|
144
|
-
export declare function
|
|
193
|
+
export declare function ensureUserKeyRoster({ store, userKey, clientKeyAgreementKey, signEpochs }: {
|
|
145
194
|
store: EncryptionDescriptorStore;
|
|
146
|
-
|
|
195
|
+
userKey: UserKey;
|
|
147
196
|
clientKeyAgreementKey: IKeyAgreementKey;
|
|
197
|
+
signEpochs: EpochsSigner;
|
|
148
198
|
}): Promise<CollectionEncryption>;
|
|
149
199
|
/**
|
|
150
|
-
* Wraps the
|
|
200
|
+
* Wraps the user key to a client being enrolled -- the roster half of the
|
|
151
201
|
* enrollment ceremony, and deliberately its FIRST write (decryption material
|
|
152
202
|
* before authorization, the push order): the wrap lands before the did:webvh
|
|
153
203
|
* log entries, so no enrolled client is ever authorized but blind, and a tear
|
|
@@ -172,22 +222,22 @@ export declare function ensurePukRoster({ store, puk, clientKeyAgreementKey }: {
|
|
|
172
222
|
* re-wrapping
|
|
173
223
|
* @returns {Promise<CollectionEncryption>} the refreshed roster descriptor
|
|
174
224
|
*/
|
|
175
|
-
export declare function
|
|
225
|
+
export declare function addUserKeyRosterRecipient({ store, recipient, ownerKeyAgreementKey }: {
|
|
176
226
|
store: EncryptionDescriptorStore;
|
|
177
227
|
recipient: RecipientPublicKey;
|
|
178
228
|
ownerKeyAgreementKey: IKeyAgreementKey;
|
|
179
229
|
}): Promise<CollectionEncryption>;
|
|
180
230
|
/**
|
|
181
|
-
* Rotates the
|
|
182
|
-
* enrolled wallet client or a recovery code. A thin, deliberate composition
|
|
231
|
+
* Rotates the user key roster off one recipient -- the roster half of revoking
|
|
232
|
+
* an enrolled wallet client or a recovery code. A thin, deliberate composition
|
|
183
233
|
* of was-client's `removeRecipient` with the two roster-specific choices
|
|
184
|
-
* spelled once: the remaining recipients are resolved from the locally
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
234
|
+
* spelled once: the remaining recipients are resolved from the locally verified
|
|
235
|
+
* did:webvh document ("the roster delivers, never sources" -- an entry with no
|
|
236
|
+
* matching `keyAgreement` verification method is dropped and never receives a
|
|
237
|
+
* wrap), and the pull axis is a no-op, because for a roster recipient the pull
|
|
238
|
+
* axis IS the document edit the caller performed first -- under the
|
|
239
|
+
* current-key-set rule the removed party's server-side access died the moment
|
|
240
|
+
* its verification method left the document.
|
|
191
241
|
*
|
|
192
242
|
* @param options {object}
|
|
193
243
|
* @param options.store {EncryptionDescriptorStore} the roster's descriptor
|
|
@@ -196,18 +246,22 @@ export declare function addPukRosterRecipient({ store, recipient, ownerKeyAgreem
|
|
|
196
246
|
* did:webvh document, AFTER the removal edit
|
|
197
247
|
* @param options.retireRecipientId {string} the removed recipient's roster
|
|
198
248
|
* kid
|
|
249
|
+
* @param options.signEpochs {EpochsSigner} the rotating client's
|
|
250
|
+
* epoch-configuration signer ({@link userKeyRosterEpochsSigner}), vouching for
|
|
251
|
+
* the fresh epoch so other clients' rotated reads accept it
|
|
199
252
|
* @returns {Promise<CollectionEncryption>} the rotated roster descriptor
|
|
200
253
|
*/
|
|
201
|
-
export declare function
|
|
254
|
+
export declare function rotateUserKeyRoster({ store, document, retireRecipientId, signEpochs }: {
|
|
202
255
|
store: EncryptionDescriptorStore;
|
|
203
256
|
document: RosterRecipientDocument;
|
|
204
257
|
retireRecipientId: string;
|
|
258
|
+
signEpochs: EpochsSigner;
|
|
205
259
|
}): Promise<CollectionEncryption>;
|
|
206
260
|
/**
|
|
207
261
|
* Converges the roster onto the account document: the standing detector for a
|
|
208
262
|
* revocation cascade torn between its two halves. The cascade edits the
|
|
209
263
|
* document first and rotates the roster second, so a client that crashes in
|
|
210
|
-
* between leaves a roster that keeps wrapping the CURRENT
|
|
264
|
+
* between leaves a roster that keeps wrapping the CURRENT user key to a
|
|
211
265
|
* recipient the document no longer keys -- durable, silent, and permanent,
|
|
212
266
|
* since the revoked client's document edit will never be re-run.
|
|
213
267
|
*
|
|
@@ -215,7 +269,7 @@ export declare function rotatePukRoster({ store, document, retireRecipientId }:
|
|
|
215
269
|
* document-backed resolver cannot answer for is exactly a recipient the
|
|
216
270
|
* document no longer keys, so a healthy account reads the descriptor and
|
|
217
271
|
* writes nothing. When any such recipient is found the roster is rotated away
|
|
218
|
-
* from ALL of them at once -- a single {@link
|
|
272
|
+
* from ALL of them at once -- a single {@link rotateUserKeyRoster} suffices,
|
|
219
273
|
* because the resolver drops every unbacked entry from the fresh epoch, not
|
|
220
274
|
* just the one named as retiring.
|
|
221
275
|
*
|
|
@@ -224,8 +278,8 @@ export declare function rotatePukRoster({ store, document, retireRecipientId }:
|
|
|
224
278
|
* account), not a cascade to finish, and completing it would lock every
|
|
225
279
|
* client out of the account.
|
|
226
280
|
*
|
|
227
|
-
* The fresh
|
|
228
|
-
* ordinary way, by re-reading the roster ({@link
|
|
281
|
+
* The fresh user key itself is not returned: the caller adopts it the
|
|
282
|
+
* ordinary way, by re-reading the roster ({@link readUserKeyRoster}) once
|
|
229
283
|
* `rotated` says there is something to adopt, and then runs the collection
|
|
230
284
|
* fan-out.
|
|
231
285
|
*
|
|
@@ -237,14 +291,18 @@ export declare function rotatePukRoster({ store, document, retireRecipientId }:
|
|
|
237
291
|
* @param [options.descriptor] {CollectionEncryption} a descriptor the caller
|
|
238
292
|
* has just read (a login-time roster read), to save a re-read; omitted, the
|
|
239
293
|
* roster is read fresh
|
|
294
|
+
* @param options.signEpochs {EpochsSigner} the converging client's
|
|
295
|
+
* epoch-configuration signer ({@link userKeyRosterEpochsSigner}), for the
|
|
296
|
+
* rotation this call may perform
|
|
240
297
|
* @returns {Promise<object>} whether the roster rotated on this call, the
|
|
241
298
|
* stale recipient kids found, and the roster descriptor as it now stands
|
|
242
299
|
* (`null` when the account has no roster yet)
|
|
243
300
|
*/
|
|
244
|
-
export declare function
|
|
301
|
+
export declare function convergeUserKeyRosterToDocument({ store, document, descriptor, signEpochs }: {
|
|
245
302
|
store: EncryptionDescriptorStore;
|
|
246
303
|
document: RosterRecipientDocument;
|
|
247
304
|
descriptor?: CollectionEncryption;
|
|
305
|
+
signEpochs: EpochsSigner;
|
|
248
306
|
}): Promise<{
|
|
249
307
|
rotated: boolean;
|
|
250
308
|
staleRecipientIds: string[];
|
|
@@ -252,13 +310,13 @@ export declare function convergePukRosterToDocument({ store, document, descripto
|
|
|
252
310
|
}>;
|
|
253
311
|
/**
|
|
254
312
|
* What a roster read resolves to: the authenticated descriptor, the current
|
|
255
|
-
*
|
|
313
|
+
* user key (the cached one confirmed current, or a fresh one unwrapped from a
|
|
256
314
|
* rotated epoch -- `rotated` says which), and the epoch id the caller must pin
|
|
257
315
|
* as the new latest-seen.
|
|
258
316
|
*/
|
|
259
|
-
export interface
|
|
317
|
+
export interface UserKeyRosterReadResult {
|
|
260
318
|
descriptor: CollectionEncryption;
|
|
261
|
-
|
|
319
|
+
userKey: UserKey;
|
|
262
320
|
rotated: boolean;
|
|
263
321
|
latestEpochId: string;
|
|
264
322
|
}
|
|
@@ -269,37 +327,56 @@ export interface PukRosterReadResult {
|
|
|
269
327
|
*
|
|
270
328
|
* 1. **Continuity**: the served epochs must contain the pinned latest-seen
|
|
271
329
|
* epoch, and `currentEpoch` must not precede it in the append-only list
|
|
272
|
-
* (`
|
|
273
|
-
* 2. **Possession**: `currentEpoch ===
|
|
330
|
+
* (`UserKeyRosterContinuityError` -- the rollback/replay refusal).
|
|
331
|
+
* 2. **Possession**: `currentEpoch === userKey.id` confirms the cached user key
|
|
274
332
|
* current; otherwise the current epoch was rotated by another client and
|
|
275
333
|
* this client's wrap is unwrapped with its own key-agreement key
|
|
276
|
-
* (`
|
|
277
|
-
* 3. **
|
|
278
|
-
*
|
|
334
|
+
* (`UserKeyRosterUnwrapError` when it holds none).
|
|
335
|
+
* 3. **Provenance** (the rotated/first-read path only): the epoch
|
|
336
|
+
* configuration's `epochsSig` is verified against the locally verified
|
|
337
|
+
* did:webvh document ({@link verifyUserKeyRosterEpochsSig}) BEFORE the epoch
|
|
338
|
+
* it delivers is adopted. On this path the `epochsMac` alone proves
|
|
339
|
+
* nothing against the host -- its key is unwrapped from the served
|
|
340
|
+
* descriptor itself -- so an epoch no enrolled client signed is refused
|
|
341
|
+
* (`UserKeyRosterIntegrityError`). The cached-current path needs no signature:
|
|
342
|
+
* there the MAC is keyed by a secret this client already trusts.
|
|
343
|
+
* 4. **Authentication**: the descriptor's `epochsMac` is verified under the
|
|
344
|
+
* current epoch's secret (`UserKeyRosterIntegrityError` on any mismatch -- a
|
|
279
345
|
* fabricated configuration).
|
|
280
346
|
*
|
|
281
|
-
* A rotated read returns the fresh
|
|
347
|
+
* A rotated read returns the fresh user key; its Ed25519 signing seed does not
|
|
282
348
|
* travel through the roster (the roster wraps the key-agreement secret
|
|
283
|
-
* alone), so the returned
|
|
349
|
+
* alone), so the returned user key carries none.
|
|
284
350
|
*
|
|
285
|
-
* A caller with no cached
|
|
286
|
-
* first post-enrollment read -- omits `
|
|
287
|
-
* the result's `rotated` is then true (the
|
|
351
|
+
* A caller with no cached user key at all -- a freshly enrolled client making
|
|
352
|
+
* its first post-enrollment read -- omits `userKey` and always takes the unwrap
|
|
353
|
+
* path; the result's `rotated` is then true (the user key was adopted from the
|
|
354
|
+
* roster). Every unwrap-path caller must therefore supply the account document
|
|
355
|
+
* (or a way to resolve it): `document` when it already holds a verified copy,
|
|
356
|
+
* or `resolveDocument` to fetch-and-verify lazily, only when the read actually
|
|
357
|
+
* rotates.
|
|
288
358
|
*
|
|
289
359
|
* @param options {object}
|
|
290
360
|
* @param options.store {EncryptionDescriptorStore} the roster's descriptor
|
|
291
361
|
* store
|
|
292
|
-
* @param [options.
|
|
362
|
+
* @param [options.userKey] {UserKey} this client's cached user key, when it holds one
|
|
293
363
|
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
294
364
|
* (identity) key-agreement key, unwrapping a rotated epoch
|
|
295
365
|
* @param [options.pinnedEpochId] {string} the locally pinned latest-seen
|
|
296
366
|
* roster epoch, when this client has seen the roster before
|
|
297
|
-
* @
|
|
367
|
+
* @param [options.document] {RosterRecipientDocument} the locally verified
|
|
368
|
+
* did:webvh document, when the caller already holds one
|
|
369
|
+
* @param [options.resolveDocument] {function} resolves the locally verified
|
|
370
|
+
* did:webvh document on demand; called only when the read takes the
|
|
371
|
+
* rotated/first-read path
|
|
372
|
+
* @returns {Promise<UserKeyRosterReadResult | null>}
|
|
298
373
|
*/
|
|
299
|
-
export declare function
|
|
374
|
+
export declare function readUserKeyRoster({ store, userKey, clientKeyAgreementKey, pinnedEpochId, document, resolveDocument }: {
|
|
300
375
|
store: EncryptionDescriptorStore;
|
|
301
|
-
|
|
376
|
+
userKey?: UserKey;
|
|
302
377
|
clientKeyAgreementKey: IKeyAgreementKey;
|
|
303
378
|
pinnedEpochId?: string | null;
|
|
304
|
-
|
|
305
|
-
|
|
379
|
+
document?: RosterRecipientDocument;
|
|
380
|
+
resolveDocument?: () => Promise<RosterRecipientDocument>;
|
|
381
|
+
}): Promise<UserKeyRosterReadResult | null>;
|
|
382
|
+
//# sourceMappingURL=userKeyRoster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userKeyRoster.d.ts","sourceRoot":"","sources":["../../src/keys/userKeyRoster.ts"],"names":[],"mappings":"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"}
|