@interop/wallet-core 0.106.0 → 0.107.1
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 +1 -1
- package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
- package/dist/clientAnnex/forgetLast.js +0 -1
- package/dist/clientAnnex/forgetLast.js.map +1 -1
- package/dist/clientAnnex/gc.d.ts +55 -24
- package/dist/clientAnnex/gc.d.ts.map +1 -1
- package/dist/clientAnnex/gc.js +111 -31
- package/dist/clientAnnex/gc.js.map +1 -1
- package/dist/clientAnnex/generationRung.d.ts +5 -21
- package/dist/clientAnnex/generationRung.d.ts.map +1 -1
- package/dist/clientAnnex/generationRung.js +30 -41
- package/dist/clientAnnex/generationRung.js.map +1 -1
- package/dist/clientAnnex/grantRevocation.d.ts +11 -7
- package/dist/clientAnnex/grantRevocation.d.ts.map +1 -1
- package/dist/clientAnnex/grantRevocation.js +1 -1
- package/dist/clientAnnex/grantRevocation.js.map +1 -1
- package/dist/clientAnnex/heal.d.ts +14 -4
- package/dist/clientAnnex/heal.d.ts.map +1 -1
- package/dist/clientAnnex/heal.js +32 -12
- package/dist/clientAnnex/heal.js.map +1 -1
- package/dist/clientAnnex/index.d.ts +6 -5
- package/dist/clientAnnex/index.d.ts.map +1 -1
- package/dist/clientAnnex/index.js +6 -5
- package/dist/clientAnnex/index.js.map +1 -1
- package/dist/clientAnnex/log.d.ts +106 -59
- package/dist/clientAnnex/log.d.ts.map +1 -1
- package/dist/clientAnnex/log.js +156 -111
- package/dist/clientAnnex/log.js.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts +5 -0
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.js +5 -0
- package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
- package/dist/clients/grantState.d.ts +11 -9
- package/dist/clients/grantState.d.ts.map +1 -1
- package/dist/clients/grantState.js +19 -16
- package/dist/clients/grantState.js.map +1 -1
- package/dist/clients/index.d.ts +9 -9
- package/dist/clients/index.js +9 -9
- package/dist/clients/listing.d.ts +12 -14
- package/dist/clients/listing.d.ts.map +1 -1
- package/dist/clients/listing.js +17 -23
- package/dist/clients/listing.js.map +1 -1
- package/dist/connections/grantProof.d.ts +47 -14
- package/dist/connections/grantProof.d.ts.map +1 -1
- package/dist/connections/grantProof.js +88 -57
- package/dist/connections/grantProof.js.map +1 -1
- package/dist/connections/grants.d.ts +13 -1
- package/dist/connections/grants.d.ts.map +1 -1
- package/dist/connections/grants.js +15 -26
- package/dist/connections/grants.js.map +1 -1
- package/dist/connections/index.d.ts +4 -3
- package/dist/connections/index.d.ts.map +1 -1
- package/dist/connections/index.js +3 -2
- package/dist/connections/index.js.map +1 -1
- package/dist/testing/accountBuilder.d.ts.map +1 -1
- package/dist/testing/accountBuilder.js +0 -1
- package/dist/testing/accountBuilder.js.map +1 -1
- package/dist/testing/signerFixture.d.ts +3 -3
- package/dist/testing/signerFixture.d.ts.map +1 -1
- package/dist/testing/signerFixture.js +7 -5
- package/dist/testing/signerFixture.js.map +1 -1
- package/dist/unlock/retire.d.ts +5 -2
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/retire.js.map +1 -1
- package/dist/webvh/clientAnnexDid.d.ts +4 -5
- package/dist/webvh/clientAnnexDid.d.ts.map +1 -1
- package/dist/webvh/clientAnnexDid.js +4 -5
- package/dist/webvh/clientAnnexDid.js.map +1 -1
- package/dist/webvh/index.d.ts +13 -6
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +12 -5
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/ladderDerivation.d.ts +1 -2
- package/dist/webvh/ladderDerivation.d.ts.map +1 -1
- package/dist/webvh/ladderDerivation.js +5 -5
- package/dist/webvh/ladderDerivation.js.map +1 -1
- package/dist/webvh/listClients.d.ts +124 -15
- package/dist/webvh/listClients.d.ts.map +1 -1
- package/dist/webvh/listClients.js +148 -43
- package/dist/webvh/listClients.js.map +1 -1
- package/dist/webvh/standingZcap.d.ts +4 -1
- package/dist/webvh/standingZcap.d.ts.map +1 -1
- package/dist/webvh/standingZcap.js +13 -14
- package/dist/webvh/standingZcap.js.map +1 -1
- package/package.json +12 -12
package/dist/clientAnnex/log.js
CHANGED
|
@@ -14,12 +14,14 @@
|
|
|
14
14
|
*
|
|
15
15
|
* The annex's conventions differ from the account log's on purpose:
|
|
16
16
|
*
|
|
17
|
-
* - Update authority is each standing credential's static annex rung
|
|
18
|
-
* (
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
17
|
+
* - Update authority is each standing credential's static annex rung
|
|
18
|
+
* (`clientAnnexRung`): one key per credential, the same on every
|
|
19
|
+
* generation, with no rung advancement and no attribution scan. Genesis
|
|
20
|
+
* states the minting credential's rung key in `updateKeys` and commits its
|
|
21
|
+
* own carry-over hash in `nextKeyHashes`, or no later entry could re-state
|
|
22
|
+
* it. A genesis that supersedes a readable generation also restates that
|
|
23
|
+
* generation's standing set there ({@link standingRungHashesOf}).
|
|
24
|
+
* - Prerotation stays on (the rung hashes are the commitment chain),
|
|
23
25
|
* witnesses stay off, and portability is off: an annex is
|
|
24
26
|
* generation-scoped and host-bound, and replacement is a GC swap, never a
|
|
25
27
|
* portability move.
|
|
@@ -40,13 +42,9 @@
|
|
|
40
42
|
* `gen-` prefix match over the auxiliary Space's collection listing, with no
|
|
41
43
|
* registry of generations anywhere.
|
|
42
44
|
*
|
|
43
|
-
* Generation identity is random
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* the generation-identifying half of the annex rung HKDF labels
|
|
47
|
-
* (`<generationId>/rung/<k>` under the unlock ladder's one salt), so there is
|
|
48
|
-
* exactly one spelling of a generation's identity -- the one the annex
|
|
49
|
-
* DID string already embeds.
|
|
45
|
+
* Generation identity is random rather than a counter: no counter carrier
|
|
46
|
+
* survives GC deleting the old collection. The generation id is the
|
|
47
|
+
* generation collection's name, and the annex DID string embeds it.
|
|
50
48
|
*/
|
|
51
49
|
import { createDID, deriveNextKeyHash, updateDID } from '@interop/did-method-webvh';
|
|
52
50
|
import { rootCapabilityId, spacePath, toUrl } from '@interop/was-client/paths';
|
|
@@ -403,17 +401,14 @@ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generatio
|
|
|
403
401
|
};
|
|
404
402
|
}
|
|
405
403
|
/**
|
|
406
|
-
* Mints a fresh annex generation signed by a standing CREDENTIAL's
|
|
407
|
-
* annex rung
|
|
408
|
-
* login, or a test harness standing in for one).
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
* shape cannot express that ordering. Everything else matches it: the typed
|
|
415
|
-
* Space ensure, the collection create, the create-if-absent genesis publish,
|
|
416
|
-
* and the pointer deliberately left to the caller.
|
|
404
|
+
* Mints a fresh annex generation signed by a standing CREDENTIAL's static
|
|
405
|
+
* annex rung -- the mint a ladder-seed holder runs (a credential-in-hand
|
|
406
|
+
* login, or a test harness standing in for one). It derives the rung from the
|
|
407
|
+
* ladder seed, states the rung key in `updateKeys`, and commits its own
|
|
408
|
+
* carry-over hash in `nextKeyHashes` beside any restated standing hashes.
|
|
409
|
+
* Everything else matches {@link mintClientAnnexGeneration}: the typed Space
|
|
410
|
+
* ensure, the collection create, the create-if-absent genesis publish, and
|
|
411
|
+
* the pointer deliberately left to the caller.
|
|
417
412
|
*
|
|
418
413
|
* @param options {object}
|
|
419
414
|
* @param options.was {WasClient} the storage client, signing as an enrolled
|
|
@@ -426,12 +421,14 @@ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generatio
|
|
|
426
421
|
* seed, from its unlock record
|
|
427
422
|
* @param options.pinStore {ResourceLogPinStore} this client's chain-head
|
|
428
423
|
* pins; the store derives each log's slot
|
|
429
|
-
* @param [options.
|
|
430
|
-
* credentials'
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
424
|
+
* @param [options.standingRungHashes] {string[]} the standing
|
|
425
|
+
* credentials' annex rung hashes, restated from the superseded generation's
|
|
426
|
+
* log ({@link standingRungHashesOf}) by a swap or a heal that supersedes a
|
|
427
|
+
* readable generation. Each is committed in the genesis `nextKeyHashes`
|
|
428
|
+
* beside the minting credential's own carry-over hash, deduplicated, so
|
|
429
|
+
* every credential that could write the old generation can write this
|
|
430
|
+
* one. A first generation (genesis, establishment, the transient-recovery
|
|
431
|
+
* continuation) passes none
|
|
435
432
|
* @param [options.capability] {IZcap} an invocation capability the mint
|
|
436
433
|
* rides -- the transient-recovery continuation minting its fresh generation
|
|
437
434
|
* through the credential's sibling delegation (the auxiliary Space). The
|
|
@@ -450,21 +447,20 @@ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generatio
|
|
|
450
447
|
* controller afterwards need not re-read it. Present exactly when the
|
|
451
448
|
* ensure ran, so absent under a supplied `capability`.
|
|
452
449
|
*/
|
|
453
|
-
export async function mintCredentialClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, pinStore,
|
|
450
|
+
export async function mintCredentialClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, pinStore, standingRungHashes = [], capability }) {
|
|
454
451
|
const spaceDescription = capability === undefined
|
|
455
452
|
? await ensureClientAnnexSpace({ was, spaceId, controller })
|
|
456
453
|
: undefined;
|
|
457
454
|
const generationId = mintGenerationId();
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
const nextKeyHashes = await Promise.all(rungs.map(each => deriveNextKeyHash(each.keyMultibase)));
|
|
455
|
+
const rung = await clientAnnexRung({ ladderSeed });
|
|
456
|
+
const ownHash = await deriveNextKeyHash(rung.keyMultibase);
|
|
461
457
|
const published = await publishClientAnnexGenesis({
|
|
462
458
|
was,
|
|
463
459
|
wasServerUrl,
|
|
464
460
|
spaceId,
|
|
465
461
|
generationId,
|
|
466
462
|
updateKeyPublicKeyMultibase: rung.keyMultibase,
|
|
467
|
-
nextKeyHashes: [...new Set(
|
|
463
|
+
nextKeyHashes: [...new Set([ownHash, ...standingRungHashes])],
|
|
468
464
|
signer: await updateKeySigner({ seed: rung.seed }),
|
|
469
465
|
pinStore,
|
|
470
466
|
...(capability !== undefined ? { capability } : {})
|
|
@@ -1152,15 +1148,15 @@ function withGenerationDelegationEntry({ doc, clientAnnexDid, delegation }) {
|
|
|
1152
1148
|
}
|
|
1153
1149
|
/**
|
|
1154
1150
|
* Thrown when the published annex log commits neither the writing
|
|
1155
|
-
* credential's rung
|
|
1156
|
-
*
|
|
1157
|
-
*
|
|
1158
|
-
*
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
* callers can map it to the fresh-generation path where one is licensed
|
|
1163
|
-
*
|
|
1151
|
+
* credential's annex rung key nor its hash. A generation swap restates the
|
|
1152
|
+
* superseded generation's standing set, so a swap locks no committed
|
|
1153
|
+
* credential out. What is left is the mid-generation bind: a credential
|
|
1154
|
+
* bound after the generation's genesis cannot write the annex until an
|
|
1155
|
+
* existing writer commits its hash ({@link commitClientAnnexRung}), or until
|
|
1156
|
+
* it mints a fresh generation itself (the transient visit's heal, which
|
|
1157
|
+
* restates the superseded generation's set beside its own hash). Typed so
|
|
1158
|
+
* callers can map it to the fresh-generation path where one is licensed or
|
|
1159
|
+
* to honest copy where none is.
|
|
1164
1160
|
*/
|
|
1165
1161
|
export class ClientAnnexRungUncommittedError extends Error {
|
|
1166
1162
|
constructor(message) {
|
|
@@ -1169,20 +1165,86 @@ export class ClientAnnexRungUncommittedError extends Error {
|
|
|
1169
1165
|
}
|
|
1170
1166
|
}
|
|
1171
1167
|
/**
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1174
|
-
* `
|
|
1168
|
+
* The annex's writer-admission rule as a predicate: whether a credential's
|
|
1169
|
+
* static annex rung stands revealed in `updateKeys`, or its hash stands
|
|
1170
|
+
* committed in `nextKeyHashes`. Annex entries verify against the log's own
|
|
1171
|
+
* hash-commitment chain, so a rung this answers false for can never be made
|
|
1172
|
+
* to verify mid-log. A caller that must decide before any write (the
|
|
1173
|
+
* transient visit's heal, choosing between renewal and a fresh mint) asks
|
|
1174
|
+
* this over a head it already read.
|
|
1175
|
+
*
|
|
1176
|
+
* @param options {object}
|
|
1177
|
+
* @param options.ladderSeed {Uint8Array} the credential's ladder seed
|
|
1178
|
+
* @param options.updateKeys {string[]} the log's current update keys
|
|
1179
|
+
* @param options.nextKeyHashes {string[]} the log's current commitments
|
|
1180
|
+
* @returns {Promise<boolean>}
|
|
1181
|
+
*/
|
|
1182
|
+
export async function logCommitsRung({ ladderSeed, updateKeys, nextKeyHashes }) {
|
|
1183
|
+
return rungAdmitted({
|
|
1184
|
+
rung: await clientAnnexRung({ ladderSeed }),
|
|
1185
|
+
updateKeys,
|
|
1186
|
+
nextKeyHashes
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* A credential's annex rung hash, in the multihash form `nextKeyHashes`
|
|
1191
|
+
* carries: what a genesis commits for it and what a swap leaves out when it
|
|
1192
|
+
* retires it.
|
|
1193
|
+
*
|
|
1194
|
+
* @param options {object}
|
|
1195
|
+
* @param options.ladderSeed {Uint8Array} the credential's ladder seed
|
|
1196
|
+
* @returns {Promise<string>}
|
|
1197
|
+
*/
|
|
1198
|
+
export async function clientAnnexRungHash({ ladderSeed }) {
|
|
1199
|
+
const rung = await clientAnnexRung({ ladderSeed });
|
|
1200
|
+
return deriveNextKeyHash(rung.keyMultibase);
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* {@link logCommitsRung} over a rung already derived, so a caller that goes
|
|
1204
|
+
* on to sign with the rung derives it once.
|
|
1205
|
+
*
|
|
1206
|
+
* @param options {object}
|
|
1207
|
+
* @param options.rung {{ keyMultibase: string }} the derived annex rung
|
|
1208
|
+
* @param options.updateKeys {string[]}
|
|
1209
|
+
* @param options.nextKeyHashes {string[]}
|
|
1210
|
+
* @returns {Promise<boolean>}
|
|
1211
|
+
*/
|
|
1212
|
+
async function rungAdmitted({ rung, updateKeys, nextKeyHashes }) {
|
|
1213
|
+
return (updateKeys.includes(rung.keyMultibase) ||
|
|
1214
|
+
nextKeyHashes.includes(await deriveNextKeyHash(rung.keyMultibase)));
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* The standing credentials' annex commitment set, read off a generation
|
|
1218
|
+
* log's current parameters: every `nextKeyHashes` entry, plus the hash of
|
|
1219
|
+
* every revealed `updateKeys` entry, deduplicated. Since each credential's
|
|
1220
|
+
* annex rung is the same on every generation, this is exactly what a fresh
|
|
1221
|
+
* genesis restates to keep every credential that could write the
|
|
1222
|
+
* superseded generation able to write the new one. A strike entry already
|
|
1223
|
+
* dropped a retired credential's key and hash from these parameters, so
|
|
1224
|
+
* nothing it struck is restated.
|
|
1225
|
+
*
|
|
1226
|
+
* @param options {object}
|
|
1227
|
+
* @param options.updateKeys {string[]} the superseded log's current update
|
|
1228
|
+
* keys
|
|
1229
|
+
* @param options.nextKeyHashes {string[]} the superseded log's current
|
|
1230
|
+
* commitments
|
|
1231
|
+
* @returns {Promise<string[]>}
|
|
1232
|
+
*/
|
|
1233
|
+
export async function standingRungHashesOf({ updateKeys, nextKeyHashes }) {
|
|
1234
|
+
const revealed = await Promise.all(updateKeys.map(key => deriveNextKeyHash(key)));
|
|
1235
|
+
return [...new Set([...nextKeyHashes, ...revealed])];
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Derives a credential's annex rung and admits it as the writer of the entry
|
|
1239
|
+
* about to be built, the throwing form of {@link logCommitsRung}.
|
|
1175
1240
|
*
|
|
1176
1241
|
* The one implementation of the annex's writer-admission rule, which every
|
|
1177
|
-
* entry builder in this module applies before it mints anything.
|
|
1178
|
-
*
|
|
1179
|
-
*
|
|
1180
|
-
* the caller supplies only the refusal message, since what a locked-out
|
|
1181
|
-
* credential should do next differs per ceremony.
|
|
1242
|
+
* entry builder in this module applies before it mints anything. The caller
|
|
1243
|
+
* supplies only the refusal message, since what a locked-out credential
|
|
1244
|
+
* should do next differs per ceremony.
|
|
1182
1245
|
*
|
|
1183
1246
|
* @param options {object}
|
|
1184
1247
|
* @param options.ladderSeed {Uint8Array} the acting credential's ladder seed
|
|
1185
|
-
* @param options.generationId {string}
|
|
1186
1248
|
* @param options.updateKeys {string[]} the keys the entry will be verified
|
|
1187
1249
|
* against (the retired members already excluded, where a ceremony excludes
|
|
1188
1250
|
* them)
|
|
@@ -1190,23 +1252,22 @@ export class ClientAnnexRungUncommittedError extends Error {
|
|
|
1190
1252
|
* @param options.message {string} the refusal's message
|
|
1191
1253
|
* @returns {Promise<{ seed: Uint8Array; keyMultibase: string }>}
|
|
1192
1254
|
*/
|
|
1193
|
-
async function admitActingRung({ ladderSeed,
|
|
1194
|
-
const rung = await clientAnnexRung({ ladderSeed
|
|
1195
|
-
|
|
1196
|
-
if (!updateKeys.includes(rung.keyMultibase) &&
|
|
1197
|
-
!nextKeyHashes.includes(rungHash)) {
|
|
1255
|
+
async function admitActingRung({ ladderSeed, updateKeys, nextKeyHashes, message }) {
|
|
1256
|
+
const rung = await clientAnnexRung({ ladderSeed });
|
|
1257
|
+
if (!(await rungAdmitted({ rung, updateKeys, nextKeyHashes }))) {
|
|
1198
1258
|
throw new ClientAnnexRungUncommittedError(message);
|
|
1199
1259
|
}
|
|
1200
1260
|
return rung;
|
|
1201
1261
|
}
|
|
1202
1262
|
/**
|
|
1203
|
-
* The read-only form of the writer-admission rule: whether a
|
|
1204
|
-
*
|
|
1205
|
-
* or committed in its `nextKeyHashes`, read under the store's
|
|
1206
|
-
* pin. A ceremony that must commit ANOTHER credential's rung
|
|
1207
|
-
* (the backup export's required commit) asks this before its
|
|
1208
|
-
* write, so an acting rung the generation does not admit
|
|
1209
|
-
* nothing rather than after a roster wrap and a record are
|
|
1263
|
+
* The read-only form of the writer-admission rule over a store: whether a
|
|
1264
|
+
* credential's annex rung stands revealed in the published log's
|
|
1265
|
+
* `updateKeys` or committed in its `nextKeyHashes`, read under the store's
|
|
1266
|
+
* own chain-head pin. A ceremony that must commit ANOTHER credential's rung
|
|
1267
|
+
* with this one (the backup export's required commit) asks this before its
|
|
1268
|
+
* first durable write, so an acting rung the generation does not admit
|
|
1269
|
+
* refuses over nothing rather than after a roster wrap and a record are
|
|
1270
|
+
* written. An
|
|
1210
1271
|
* absent generation log admits no writer.
|
|
1211
1272
|
*
|
|
1212
1273
|
* @param options {object}
|
|
@@ -1214,13 +1275,11 @@ async function admitActingRung({ ladderSeed, generationId, updateKeys, nextKeyHa
|
|
|
1214
1275
|
* log store
|
|
1215
1276
|
* @param options.ladderSeed {Uint8Array} the acting credential's ladder
|
|
1216
1277
|
* seed
|
|
1217
|
-
* @param options.generationId {string}
|
|
1218
1278
|
* @param [options.expectedDid] {string} the annex DID the log must
|
|
1219
1279
|
* resolve to, from the account document's pointer
|
|
1220
1280
|
* @returns {Promise<boolean>}
|
|
1221
1281
|
*/
|
|
1222
|
-
export async function clientAnnexRungAdmitted({ store, ladderSeed,
|
|
1223
|
-
assertGenerationId(generationId);
|
|
1282
|
+
export async function clientAnnexRungAdmitted({ store, ladderSeed, expectedDid }) {
|
|
1224
1283
|
const published = await readClientAnnexLogOrAbsent({
|
|
1225
1284
|
store,
|
|
1226
1285
|
...(expectedDid !== undefined ? { expectedDid } : {})
|
|
@@ -1228,9 +1287,11 @@ export async function clientAnnexRungAdmitted({ store, ladderSeed, generationId,
|
|
|
1228
1287
|
if (!published) {
|
|
1229
1288
|
return false;
|
|
1230
1289
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
published.
|
|
1290
|
+
return logCommitsRung({
|
|
1291
|
+
ladderSeed,
|
|
1292
|
+
updateKeys: published.updateKeys,
|
|
1293
|
+
nextKeyHashes: published.nextKeyHashes
|
|
1294
|
+
});
|
|
1234
1295
|
}
|
|
1235
1296
|
/**
|
|
1236
1297
|
* Reads and resolves the published annex log through the narrow seam, or
|
|
@@ -1283,9 +1344,8 @@ export async function readClientAnnexLogOrAbsent({ store, expectedDid }) {
|
|
|
1283
1344
|
/**
|
|
1284
1345
|
* TRANSIENT ENROLLMENT: publishes one per-visit verification method into a
|
|
1285
1346
|
* annex generation's log -- one atomic entry, signed by the writing
|
|
1286
|
-
* credential's static rung
|
|
1287
|
-
*
|
|
1288
|
-
* see `clientAnnexRung`). The entry:
|
|
1347
|
+
* credential's static annex rung (derived from the ladder seed alone; see
|
|
1348
|
+
* `clientAnnexRung`). The entry:
|
|
1289
1349
|
*
|
|
1290
1350
|
* - reveals the writer's rung-0 key into `updateKeys` at its first annex
|
|
1291
1351
|
* write (later writes re-state it unchanged);
|
|
@@ -1320,7 +1380,6 @@ export async function readClientAnnexLogOrAbsent({ store, expectedDid }) {
|
|
|
1320
1380
|
* controller-tier)
|
|
1321
1381
|
* @param options.ladderSeed {Uint8Array} the credential's ladder seed, from
|
|
1322
1382
|
* its unlock record
|
|
1323
|
-
* @param options.generationId {string} the generation collection's name
|
|
1324
1383
|
* @param options.transientKeyMultibase {string} the visit's in-memory
|
|
1325
1384
|
* Ed25519 signing key, public multibase
|
|
1326
1385
|
* @param [options.services] {ServiceEndpoint[]} the annex document's
|
|
@@ -1363,8 +1422,7 @@ export async function enrollClientAnnexTransientClient({ published: threadedHead
|
|
|
1363
1422
|
* @param options {object} see {@link enrollClientAnnexTransientClient}
|
|
1364
1423
|
* @returns {Promise<{ did: string, doc: DIDDoc, log: DIDLog }>}
|
|
1365
1424
|
*/
|
|
1366
|
-
async function enrollClientAnnexTransientClientOnce({ store, ladderSeed,
|
|
1367
|
-
assertGenerationId(generationId);
|
|
1425
|
+
async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, transientKeyMultibase, services, mintGenerationDelegation: mintDelegation, expectedDid, published: alreadyRead }) {
|
|
1368
1426
|
const published = alreadyRead !== undefined
|
|
1369
1427
|
? assertPublishedLogDid({
|
|
1370
1428
|
published: alreadyRead,
|
|
@@ -1385,7 +1443,6 @@ async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generat
|
|
|
1385
1443
|
}
|
|
1386
1444
|
const rung = await admitActingRung({
|
|
1387
1445
|
ladderSeed,
|
|
1388
|
-
generationId,
|
|
1389
1446
|
updateKeys: published.updateKeys,
|
|
1390
1447
|
nextKeyHashes: published.nextKeyHashes,
|
|
1391
1448
|
message: "client annex: the log commits neither this credential's rung-0 key nor " +
|
|
@@ -1683,7 +1740,6 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
|
|
|
1683
1740
|
const enrolled = await enrollClientAnnexTransientClient({
|
|
1684
1741
|
store: storeForGenerationId(generationId),
|
|
1685
1742
|
ladderSeed,
|
|
1686
|
-
generationId,
|
|
1687
1743
|
transientKeyMultibase,
|
|
1688
1744
|
expectedDid: clientAnnexDid,
|
|
1689
1745
|
...(head !== undefined ? { published: head } : {}),
|
|
@@ -1739,6 +1795,10 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
|
|
|
1739
1795
|
* pins; the store derives each log's slot
|
|
1740
1796
|
* @param [options.capability] {IZcap} the sibling delegation the annex
|
|
1741
1797
|
* writes ride, for a caller holding a standing invocation authority
|
|
1798
|
+
* @param [options.standingRungHashes] {string[]} the superseded
|
|
1799
|
+
* generation's standing set, restated in the fresh genesis (see
|
|
1800
|
+
* {@link mintCredentialClientAnnexGeneration}); absent on a first
|
|
1801
|
+
* generation and wherever no superseded log was readable
|
|
1742
1802
|
* @param [options.beforePointerEntry] {Function}
|
|
1743
1803
|
* `({ minted }) => Promise<void>` -- runs after the install and before the
|
|
1744
1804
|
* pointer entry, with the mint's published head (its `spaceDescription`
|
|
@@ -1747,7 +1807,7 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
|
|
|
1747
1807
|
* @returns {Promise<{ clientAnnexDid: string, generationDelegation: IZcap,
|
|
1748
1808
|
* pointed: T }>}
|
|
1749
1809
|
*/
|
|
1750
|
-
export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, mintGenerationDelegation, point, pinStore, capability, beforePointerEntry, now }) {
|
|
1810
|
+
export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, mintGenerationDelegation, point, pinStore, capability, standingRungHashes, beforePointerEntry, now }) {
|
|
1751
1811
|
const minted = await mintCredentialClientAnnexGeneration({
|
|
1752
1812
|
was,
|
|
1753
1813
|
wasServerUrl,
|
|
@@ -1755,7 +1815,8 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
|
|
|
1755
1815
|
controller,
|
|
1756
1816
|
ladderSeed,
|
|
1757
1817
|
pinStore,
|
|
1758
|
-
...(capability !== undefined ? { capability } : {})
|
|
1818
|
+
...(capability !== undefined ? { capability } : {}),
|
|
1819
|
+
...(standingRungHashes !== undefined ? { standingRungHashes } : {})
|
|
1759
1820
|
});
|
|
1760
1821
|
const ensured = await ensureGenerationDelegationCurrent({
|
|
1761
1822
|
store: clientAnnexLogStore({
|
|
@@ -1766,7 +1827,6 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
|
|
|
1766
1827
|
...(capability !== undefined ? { capability } : {})
|
|
1767
1828
|
}),
|
|
1768
1829
|
ladderSeed,
|
|
1769
|
-
generationId: minted.generationId,
|
|
1770
1830
|
mintGenerationDelegation,
|
|
1771
1831
|
expectedDid: minted.did,
|
|
1772
1832
|
...(minted.etag !== undefined ? { published: minted } : {}),
|
|
@@ -1823,7 +1883,6 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
|
|
|
1823
1883
|
* controller-tier)
|
|
1824
1884
|
* @param options.ladderSeed {Uint8Array} the credential's ladder seed, from
|
|
1825
1885
|
* its unlock record
|
|
1826
|
-
* @param options.generationId {string} the generation collection's name
|
|
1827
1886
|
* @param options.mintGenerationDelegation {Function}
|
|
1828
1887
|
* `({ clientAnnexDid }) => Promise<IZcap>` -- mints the replacement
|
|
1829
1888
|
* delegation (ladder-signed in a transient session)
|
|
@@ -1874,8 +1933,7 @@ export async function ensureGenerationDelegationCurrent({ published: threadedHea
|
|
|
1874
1933
|
* @returns {Promise<{ delegation: IZcap, renewed: boolean,
|
|
1875
1934
|
* published?: PublishedWebvhLog }>}
|
|
1876
1935
|
*/
|
|
1877
|
-
async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed,
|
|
1878
|
-
assertGenerationId(generationId);
|
|
1936
|
+
async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, mintGenerationDelegation: mintDelegation, expectedDid, accountDoc, retiringKeyMultibases = [], now, published: alreadyRead }) {
|
|
1879
1937
|
const published = alreadyRead !== undefined
|
|
1880
1938
|
? assertPublishedLogDid({
|
|
1881
1939
|
published: alreadyRead,
|
|
@@ -1900,7 +1958,6 @@ async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, genera
|
|
|
1900
1958
|
// who cannot publish the entry that would carry it.
|
|
1901
1959
|
const rung = await admitActingRung({
|
|
1902
1960
|
ladderSeed,
|
|
1903
|
-
generationId,
|
|
1904
1961
|
updateKeys: published.updateKeys,
|
|
1905
1962
|
nextKeyHashes: published.nextKeyHashes,
|
|
1906
1963
|
message: "client annex: the log commits neither this credential's rung-0 key nor " +
|
|
@@ -1947,18 +2004,18 @@ async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, genera
|
|
|
1947
2004
|
* retired members are excluded -- so the retired credential can never sign
|
|
1948
2005
|
* its own strike) is refused with {@link ClientAnnexRungUncommittedError},
|
|
1949
2006
|
* which the caller maps to the generation-swap fallback: a fresh generation
|
|
1950
|
-
* minted from a surviving credential's seed
|
|
1951
|
-
*
|
|
2007
|
+
* minted from a surviving credential's seed restates the old generation's
|
|
2008
|
+
* standing set EXCLUDING the retired rung's hash, so the retired rung does
|
|
2009
|
+
* not reach the fresh generation (`swapClientAnnexGeneration` with
|
|
2010
|
+
* `retiredLadderSeeds`).
|
|
1952
2011
|
*
|
|
1953
2012
|
* @param options {object}
|
|
1954
2013
|
* @param options.store {ClientAnnexWriteStore} the pointed generation's log
|
|
1955
2014
|
* store (controller-tier, or delegated through a sibling delegation)
|
|
1956
2015
|
* @param options.retiredLadderSeed {Uint8Array} the RETIRED credential's
|
|
1957
|
-
* ladder seed
|
|
1958
|
-
* way to name what to strike)
|
|
2016
|
+
* ladder seed, from which its static annex rung is derived
|
|
1959
2017
|
* @param options.actingLadderSeed {Uint8Array} a surviving credential's
|
|
1960
2018
|
* ladder seed, whose committed rung 0 signs the strike entry
|
|
1961
|
-
* @param options.generationId {string} the generation collection's name
|
|
1962
2019
|
* @param [options.expectedDid] {string} the annex DID the log must
|
|
1963
2020
|
* resolve to, from the account document's pointer. The read and the publish
|
|
1964
2021
|
* run under the store's own chain-head pin
|
|
@@ -1975,16 +2032,12 @@ export async function retireClientAnnexRung(options) {
|
|
|
1975
2032
|
* @param options {object} see {@link retireClientAnnexRung}
|
|
1976
2033
|
* @returns {Promise<{ struck: boolean }>}
|
|
1977
2034
|
*/
|
|
1978
|
-
async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadderSeed,
|
|
1979
|
-
assertGenerationId(generationId);
|
|
2035
|
+
async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadderSeed, expectedDid }) {
|
|
1980
2036
|
const published = await readClientAnnexLogOrThrow({
|
|
1981
2037
|
store,
|
|
1982
2038
|
...(expectedDid !== undefined ? { expectedDid } : {})
|
|
1983
2039
|
});
|
|
1984
|
-
const retired = await clientAnnexRung({
|
|
1985
|
-
ladderSeed: retiredLadderSeed,
|
|
1986
|
-
generationId
|
|
1987
|
-
});
|
|
2040
|
+
const retired = await clientAnnexRung({ ladderSeed: retiredLadderSeed });
|
|
1988
2041
|
const retiredHash = await deriveNextKeyHash(retired.keyMultibase);
|
|
1989
2042
|
const remainingKeys = published.updateKeys.filter(key => key !== retired.keyMultibase);
|
|
1990
2043
|
const remainingHashes = published.nextKeyHashes.filter(hash => hash !== retiredHash);
|
|
@@ -1998,7 +2051,6 @@ async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadde
|
|
|
1998
2051
|
// excluded, so the retired credential can never sign its own strike.
|
|
1999
2052
|
const acting = await admitActingRung({
|
|
2000
2053
|
ladderSeed: actingLadderSeed,
|
|
2001
|
-
generationId,
|
|
2002
2054
|
updateKeys: remainingKeys,
|
|
2003
2055
|
nextKeyHashes: remainingHashes,
|
|
2004
2056
|
message: "client annex: the log commits neither the acting credential's rung-0 " +
|
|
@@ -2027,11 +2079,11 @@ async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadde
|
|
|
2027
2079
|
* hash to a generation's `nextKeyHashes` -- one atomic hash-restating entry
|
|
2028
2080
|
* signed by an already-committed credential's rung 0. The bind ceremonies'
|
|
2029
2081
|
* annex reach (passkey add, passphrase change): a bind runs from a logged-in
|
|
2030
|
-
* session whose own login credential's rung
|
|
2082
|
+
* session whose own login credential's rung is committed, so committing the
|
|
2031
2083
|
* new credential's hash here is what keeps it out of the mid-generation
|
|
2032
2084
|
* lockout ({@link ClientAnnexRungUncommittedError} at its first transient
|
|
2033
|
-
* login, otherwise standing
|
|
2034
|
-
*
|
|
2085
|
+
* login, otherwise standing). Once committed, the hash rides every later
|
|
2086
|
+
* swap's restated set.
|
|
2035
2087
|
*
|
|
2036
2088
|
* A log already committing the bound rung's hash (or carrying its revealed
|
|
2037
2089
|
* key) is a no-op (`committed: false`) -- the resumable shape. An acting rung
|
|
@@ -2044,11 +2096,9 @@ async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadde
|
|
|
2044
2096
|
* @param options.store {ClientAnnexWriteStore} the pointed generation's log
|
|
2045
2097
|
* store (controller-tier, or delegated through a sibling delegation)
|
|
2046
2098
|
* @param options.boundLadderSeed {Uint8Array} the freshly bound
|
|
2047
|
-
* credential's ladder seed
|
|
2048
|
-
* is the only way to name what to commit)
|
|
2099
|
+
* credential's ladder seed, from which its static annex rung is derived
|
|
2049
2100
|
* @param options.actingLadderSeed {Uint8Array} the logged-in session's
|
|
2050
2101
|
* login credential's ladder seed, whose committed rung 0 signs the entry
|
|
2051
|
-
* @param options.generationId {string} the generation collection's name
|
|
2052
2102
|
* @param [options.expectedDid] {string} the annex DID the log must
|
|
2053
2103
|
* resolve to, from the account document's pointer. The read and the publish
|
|
2054
2104
|
* run under the store's own chain-head pin
|
|
@@ -2065,16 +2115,12 @@ export async function commitClientAnnexRung(options) {
|
|
|
2065
2115
|
* @param options {object} see {@link commitClientAnnexRung}
|
|
2066
2116
|
* @returns {Promise<{ committed: boolean }>}
|
|
2067
2117
|
*/
|
|
2068
|
-
async function commitClientAnnexRungOnce({ store, boundLadderSeed, actingLadderSeed,
|
|
2069
|
-
assertGenerationId(generationId);
|
|
2118
|
+
async function commitClientAnnexRungOnce({ store, boundLadderSeed, actingLadderSeed, expectedDid }) {
|
|
2070
2119
|
const published = await readClientAnnexLogOrThrow({
|
|
2071
2120
|
store,
|
|
2072
2121
|
...(expectedDid !== undefined ? { expectedDid } : {})
|
|
2073
2122
|
});
|
|
2074
|
-
const bound = await clientAnnexRung({
|
|
2075
|
-
ladderSeed: boundLadderSeed,
|
|
2076
|
-
generationId
|
|
2077
|
-
});
|
|
2123
|
+
const bound = await clientAnnexRung({ ladderSeed: boundLadderSeed });
|
|
2078
2124
|
const boundHash = await deriveNextKeyHash(bound.keyMultibase);
|
|
2079
2125
|
if (published.updateKeys.includes(bound.keyMultibase) ||
|
|
2080
2126
|
published.nextKeyHashes.includes(boundHash)) {
|
|
@@ -2084,7 +2130,6 @@ async function commitClientAnnexRungOnce({ store, boundLadderSeed, actingLadderS
|
|
|
2084
2130
|
}
|
|
2085
2131
|
const acting = await admitActingRung({
|
|
2086
2132
|
ladderSeed: actingLadderSeed,
|
|
2087
|
-
generationId,
|
|
2088
2133
|
updateKeys: published.updateKeys,
|
|
2089
2134
|
nextKeyHashes: published.nextKeyHashes,
|
|
2090
2135
|
message: "client annex: the log commits neither the acting credential's rung-0 " +
|