@interop/wallet-core 0.71.0 → 0.73.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 +14 -3
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +2 -2
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
- package/dist/clientAnnex/credentialAnchoredGenesis.js +1 -1
- package/dist/clientAnnex/forget.d.ts.map +1 -1
- package/dist/clientAnnex/forget.js +4 -3
- package/dist/clientAnnex/forget.js.map +1 -1
- package/dist/clientAnnex/forgetLast.d.ts +55 -35
- package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
- package/dist/clientAnnex/forgetLast.js +87 -35
- package/dist/clientAnnex/forgetLast.js.map +1 -1
- package/dist/clientAnnex/gc.d.ts +48 -19
- package/dist/clientAnnex/gc.d.ts.map +1 -1
- package/dist/clientAnnex/gc.js +82 -31
- package/dist/clientAnnex/gc.js.map +1 -1
- package/dist/clientAnnex/grantRevocation.d.ts +137 -0
- package/dist/clientAnnex/grantRevocation.d.ts.map +1 -0
- package/dist/clientAnnex/grantRevocation.js +135 -0
- package/dist/clientAnnex/grantRevocation.js.map +1 -0
- package/dist/clientAnnex/index.d.ts +4 -2
- package/dist/clientAnnex/index.d.ts.map +1 -1
- package/dist/clientAnnex/index.js +2 -1
- package/dist/clientAnnex/index.js.map +1 -1
- package/dist/clientAnnex/ladderAnchored.d.ts +0 -22
- package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/ladderAnchored.js +8 -34
- package/dist/clientAnnex/ladderAnchored.js.map +1 -1
- package/dist/clientAnnex/log.d.ts +65 -13
- package/dist/clientAnnex/log.d.ts.map +1 -1
- package/dist/clientAnnex/log.js +160 -67
- package/dist/clientAnnex/log.js.map +1 -1
- package/dist/clientAnnex/mend.js +51 -24
- package/dist/clientAnnex/mend.js.map +1 -1
- package/dist/clientAnnex/zcap.d.ts.map +1 -1
- package/dist/clientAnnex/zcap.js +3 -10
- package/dist/clientAnnex/zcap.js.map +1 -1
- package/dist/clients/grantState.d.ts +6 -3
- package/dist/clients/grantState.d.ts.map +1 -1
- package/dist/clients/grantState.js +6 -3
- package/dist/clients/grantState.js.map +1 -1
- package/dist/clients/policy.d.ts.map +1 -1
- package/dist/clients/policy.js +3 -0
- package/dist/clients/policy.js.map +1 -1
- package/dist/genesis/accountGenesis.d.ts +1 -1
- package/dist/genesis/accountGenesis.d.ts.map +1 -1
- package/dist/keyring/fetch.d.ts +6 -2
- package/dist/keyring/fetch.d.ts.map +1 -1
- package/dist/keyring/fetch.js +7 -3
- package/dist/keyring/fetch.js.map +1 -1
- package/dist/keyring/index.d.ts +15 -10
- package/dist/keyring/index.d.ts.map +1 -1
- package/dist/keyring/index.js +15 -10
- package/dist/keyring/index.js.map +1 -1
- package/dist/keyring/kdf.d.ts +1 -1
- package/dist/keyring/kdf.d.ts.map +1 -1
- package/dist/keyring/kdf.js +1 -1
- package/dist/keyring/kdf.js.map +1 -1
- package/dist/keyring/record.d.ts +15 -0
- package/dist/keyring/record.d.ts.map +1 -1
- package/dist/keyring/record.js +22 -0
- package/dist/keyring/record.js.map +1 -1
- package/dist/keyring/unlockSpace.d.ts +45 -68
- package/dist/keyring/unlockSpace.d.ts.map +1 -1
- package/dist/keyring/unlockSpace.js +66 -88
- package/dist/keyring/unlockSpace.js.map +1 -1
- package/dist/keys/clientKeyRecord.d.ts +3 -4
- package/dist/keys/clientKeyRecord.d.ts.map +1 -1
- package/dist/keys/clientKeyRecord.js +6 -25
- package/dist/keys/clientKeyRecord.js.map +1 -1
- package/dist/keys/index.d.ts +6 -1
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +6 -1
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/userKey.d.ts +57 -11
- package/dist/keys/userKey.d.ts.map +1 -1
- package/dist/keys/userKey.js +76 -11
- package/dist/keys/userKey.js.map +1 -1
- package/dist/keys/userKeyRoster.d.ts +3 -3
- package/dist/menders/derive.d.ts +85 -0
- package/dist/menders/derive.d.ts.map +1 -0
- package/dist/menders/derive.js +138 -0
- package/dist/menders/derive.js.map +1 -0
- package/dist/menders/ids.d.ts +20 -0
- package/dist/menders/ids.d.ts.map +1 -0
- package/dist/menders/ids.js +85 -0
- package/dist/menders/ids.js.map +1 -0
- package/dist/menders/index.d.ts +42 -0
- package/dist/menders/index.d.ts.map +1 -0
- package/dist/menders/index.js +37 -0
- package/dist/menders/index.js.map +1 -0
- package/dist/menders/registry.d.ts +84 -0
- package/dist/menders/registry.d.ts.map +1 -0
- package/dist/menders/registry.js +62 -0
- package/dist/menders/registry.js.map +1 -0
- package/dist/menders/runner.d.ts +143 -0
- package/dist/menders/runner.d.ts.map +1 -0
- package/dist/menders/runner.js +222 -0
- package/dist/menders/runner.js.map +1 -0
- package/dist/menders/types.d.ts +146 -0
- package/dist/menders/types.d.ts.map +1 -0
- package/dist/menders/types.js +2 -0
- package/dist/menders/types.js.map +1 -0
- package/dist/menders/vocabulary.d.ts +90 -0
- package/dist/menders/vocabulary.d.ts.map +1 -0
- package/dist/menders/vocabulary.js +86 -0
- package/dist/menders/vocabulary.js.map +1 -0
- package/dist/recovery/index.d.ts +1 -1
- package/dist/recovery/index.js +1 -1
- package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
- package/dist/recovery/recoveryWebvh.js +11 -17
- package/dist/recovery/recoveryWebvh.js.map +1 -1
- package/dist/resourceLog/document.d.ts.map +1 -1
- package/dist/resourceLog/document.js +30 -6
- package/dist/resourceLog/document.js.map +1 -1
- package/dist/space/activity.d.ts +70 -0
- package/dist/space/activity.d.ts.map +1 -1
- package/dist/space/activity.js +82 -0
- package/dist/space/activity.js.map +1 -1
- package/dist/space/deleteSpace.d.ts.map +1 -1
- package/dist/space/deleteSpace.js +6 -5
- package/dist/space/deleteSpace.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/testing.d.ts +78 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +89 -0
- package/dist/testing.js.map +1 -0
- package/dist/unlock/index.d.ts +2 -2
- package/dist/unlock/index.d.ts.map +1 -1
- package/dist/unlock/index.js +1 -1
- package/dist/unlock/retire.d.ts +20 -5
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/retire.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts +22 -2
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +22 -2
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +33 -0
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +52 -18
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/enrollClient.d.ts.map +1 -1
- package/dist/webvh/enrollClient.js +4 -16
- package/dist/webvh/enrollClient.js.map +1 -1
- package/dist/webvh/index.d.ts +13 -3
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +13 -3
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/listClients.d.ts +47 -0
- package/dist/webvh/listClients.d.ts.map +1 -1
- package/dist/webvh/listClients.js +40 -1
- package/dist/webvh/listClients.js.map +1 -1
- package/dist/webvh/standingZcap.d.ts +66 -0
- package/dist/webvh/standingZcap.d.ts.map +1 -1
- package/dist/webvh/standingZcap.js +96 -0
- package/dist/webvh/standingZcap.js.map +1 -1
- package/dist/webvh/zcap.d.ts +1 -1
- package/package.json +22 -10
package/dist/keys/userKey.d.ts
CHANGED
|
@@ -1,27 +1,73 @@
|
|
|
1
1
|
import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
|
|
2
|
+
import type { RecordSigner } from '../keyring/record.js';
|
|
3
|
+
/**
|
|
4
|
+
* The HKDF salt for the user key's client-side expansions, and the one info
|
|
5
|
+
* label under it. Both permanent: two wallet apps must expand the same user
|
|
6
|
+
* key to byte-identical output, or a record one of them signs is a record the
|
|
7
|
+
* other refuses.
|
|
8
|
+
*/
|
|
9
|
+
export declare const USER_KEY_SALT = "freewallet/keys/user-key/v1";
|
|
2
10
|
/**
|
|
3
11
|
* The user key material: the X25519 key-agreement half as minted by the epoch
|
|
4
12
|
* construction (`id` is the key's own did:key; `secret` its raw 32-byte private
|
|
5
|
-
* key)
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* alone, and the signing half has no consumer yet.
|
|
13
|
+
* key). Random per account; held in memory for the life of a session and
|
|
14
|
+
* persisted only inside a wrapped client-key record. The Ed25519 signing half
|
|
15
|
+
* is not a member: it derives from `secret`, so a user key adopted from a
|
|
16
|
+
* roster rotation is as complete an identity as a freshly minted one.
|
|
10
17
|
*/
|
|
11
18
|
export interface UserKey {
|
|
12
19
|
id: string;
|
|
13
20
|
secret: Uint8Array;
|
|
14
|
-
signingSeed?: Uint8Array;
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
17
23
|
* Mints a fresh user key: the X25519 key-agreement pair via the was-client
|
|
18
|
-
* epoch construction (its did:key is the key id, its raw secret is what wraps)
|
|
19
|
-
*
|
|
20
|
-
*
|
|
24
|
+
* epoch construction (its did:key is the key id, its raw secret is what wraps).
|
|
25
|
+
* The signing half needs no minting -- it derives from the same secret.
|
|
26
|
+
*
|
|
27
|
+
* @returns {Promise<UserKey>}
|
|
28
|
+
*/
|
|
29
|
+
export declare function mintUserKey(): Promise<UserKey>;
|
|
30
|
+
/**
|
|
31
|
+
* Derives the 32-byte Ed25519 seed of the user key's signing half from the
|
|
32
|
+
* key-agreement half's raw secret: HKDF-SHA256 under {@link USER_KEY_SALT},
|
|
33
|
+
* info `signing`. Deterministic and wire-level -- the same user key always
|
|
34
|
+
* yields the same signing key, which is what lets one holder sign a record
|
|
35
|
+
* another holder verifies with nothing server-served in hand.
|
|
36
|
+
*
|
|
37
|
+
* @param options {object}
|
|
38
|
+
* @param options.userKey {UserKey}
|
|
39
|
+
* @returns {Uint8Array}
|
|
40
|
+
*/
|
|
41
|
+
export declare function userKeySigningSeed({ userKey }: {
|
|
42
|
+
userKey: UserKey;
|
|
43
|
+
}): Uint8Array;
|
|
44
|
+
/**
|
|
45
|
+
* The user key's record signer: the keyring record's signing seam over the
|
|
46
|
+
* derived Ed25519 half, for an app-side record sealed to the vault KAK
|
|
47
|
+
* (`signRecordFrame`). Its `keyMultibase` is exactly what a reader's
|
|
48
|
+
* allowlist holds, so a writer that already has the signer reads the multibase
|
|
49
|
+
* off it rather than calling {@link userKeySigningKeyMultibase} as well.
|
|
50
|
+
*
|
|
51
|
+
* @param options {object}
|
|
52
|
+
* @param options.userKey {UserKey}
|
|
53
|
+
* @returns {Promise<RecordSigner>}
|
|
54
|
+
*/
|
|
55
|
+
export declare function userKeyRecordSigner({ userKey }: {
|
|
56
|
+
userKey: UserKey;
|
|
57
|
+
}): Promise<RecordSigner>;
|
|
58
|
+
/**
|
|
59
|
+
* The public multibase of the user key's signing half: the one key a reader
|
|
60
|
+
* accepts on a record sealed under this user key, handed to
|
|
61
|
+
* `verifyRecordProof` as its allowlist. For a reader alone -- a writer takes
|
|
62
|
+
* the same value off {@link userKeyRecordSigner}'s `keyMultibase`.
|
|
21
63
|
*
|
|
22
|
-
* @
|
|
64
|
+
* @param options {object}
|
|
65
|
+
* @param options.userKey {UserKey}
|
|
66
|
+
* @returns {Promise<string>}
|
|
23
67
|
*/
|
|
24
|
-
export declare function
|
|
68
|
+
export declare function userKeySigningKeyMultibase({ userKey }: {
|
|
69
|
+
userKey: UserKey;
|
|
70
|
+
}): Promise<string>;
|
|
25
71
|
/**
|
|
26
72
|
* Reconstructs the user key's key-agreement key and its single-key resolver
|
|
27
73
|
* from the stored material -- the vault-key pair a session supplies to the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userKey.d.ts","sourceRoot":"","sources":["../../src/keys/userKey.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"userKey.d.ts","sourceRoot":"","sources":["../../src/keys/userKey.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AAIrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAExD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,gCAAgC,CAAA;AAQ1D;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,UAAU,CAAA;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAGpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;CACjB,GAAG,UAAU,CASb;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,OAAO,EACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;CACjB,GAAG,OAAO,CAAC,YAAY,CAAC,CAExB;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,OAAO,EACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;CACjB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG;IACnE,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;CAC1B,CAQA"}
|
package/dist/keys/userKey.js
CHANGED
|
@@ -12,27 +12,92 @@
|
|
|
12
12
|
* The key-agreement half is exactly what `@interop/was-client`'s epoch
|
|
13
13
|
* construction mints: a fresh X25519 pair whose did:key is the key's id and
|
|
14
14
|
* whose raw 32-byte secret is what gets wrapped to recipients -- so the roster
|
|
15
|
-
* machinery consumes the user key unchanged. The Ed25519 signing half
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* one
|
|
15
|
+
* machinery consumes the user key unchanged. The Ed25519 signing half DERIVES
|
|
16
|
+
* from that same secret ({@link userKeySigningSeed}), so it needs no storage
|
|
17
|
+
* and no delivery channel of its own: every holder of the user key holds it,
|
|
18
|
+
* an enrolled session, a transient one, and a session-less signup or recovery
|
|
19
|
+
* writer alike, and a roster rotation that hands a client the fresh
|
|
20
|
+
* key-agreement secret hands it the fresh signing half with it.
|
|
21
|
+
*
|
|
22
|
+
* Its consumer is record authenticity. An app-side record sealed to the vault
|
|
23
|
+
* KAK is not authenticated by being decryptable -- a storage host that knows
|
|
24
|
+
* the epoch's public half can seal a body of its own that decrypts perfectly,
|
|
25
|
+
* which is the property the keyring record's `proof` member exists to defeat.
|
|
26
|
+
* So such a record carries the same proof, signed by {@link
|
|
27
|
+
* userKeyRecordSigner} and verified against {@link
|
|
28
|
+
* userKeySigningKeyMultibase} before it is decrypted.
|
|
19
29
|
*/
|
|
30
|
+
import { hkdf } from '@noble/hashes/hkdf.js';
|
|
31
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
20
32
|
import { X25519KeyAgreementKey2020 } from '@interop/x25519-key-agreement-key';
|
|
21
33
|
import { epochKeyIdFor, mintEpoch } from '@interop/was-client/edv';
|
|
22
34
|
import { singleKeyResolver } from '@interop/was-client/identity';
|
|
35
|
+
import { recordSignerFromSeed } from '../keyring/record.js';
|
|
36
|
+
/**
|
|
37
|
+
* The HKDF salt for the user key's client-side expansions, and the one info
|
|
38
|
+
* label under it. Both permanent: two wallet apps must expand the same user
|
|
39
|
+
* key to byte-identical output, or a record one of them signs is a record the
|
|
40
|
+
* other refuses.
|
|
41
|
+
*/
|
|
42
|
+
export const USER_KEY_SALT = 'freewallet/keys/user-key/v1';
|
|
43
|
+
const USER_KEY_SIGNING_INFO = 'signing';
|
|
44
|
+
/**
|
|
45
|
+
* The number of bytes the signing expansion produces (a 32-byte Ed25519 seed).
|
|
46
|
+
*/
|
|
47
|
+
const USER_KEY_SIGNING_SEED_BYTES = 32;
|
|
23
48
|
/**
|
|
24
49
|
* Mints a fresh user key: the X25519 key-agreement pair via the was-client
|
|
25
|
-
* epoch construction (its did:key is the key id, its raw secret is what wraps)
|
|
26
|
-
*
|
|
27
|
-
* complete identity (only a rotation-adopted one lacks the signing half).
|
|
50
|
+
* epoch construction (its did:key is the key id, its raw secret is what wraps).
|
|
51
|
+
* The signing half needs no minting -- it derives from the same secret.
|
|
28
52
|
*
|
|
29
|
-
* @returns {Promise<
|
|
53
|
+
* @returns {Promise<UserKey>}
|
|
30
54
|
*/
|
|
31
55
|
export async function mintUserKey() {
|
|
32
56
|
const { epochId, secret } = await mintEpoch();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
57
|
+
return { id: epochId, secret };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Derives the 32-byte Ed25519 seed of the user key's signing half from the
|
|
61
|
+
* key-agreement half's raw secret: HKDF-SHA256 under {@link USER_KEY_SALT},
|
|
62
|
+
* info `signing`. Deterministic and wire-level -- the same user key always
|
|
63
|
+
* yields the same signing key, which is what lets one holder sign a record
|
|
64
|
+
* another holder verifies with nothing server-served in hand.
|
|
65
|
+
*
|
|
66
|
+
* @param options {object}
|
|
67
|
+
* @param options.userKey {UserKey}
|
|
68
|
+
* @returns {Uint8Array}
|
|
69
|
+
*/
|
|
70
|
+
export function userKeySigningSeed({ userKey }) {
|
|
71
|
+
const encoder = new TextEncoder();
|
|
72
|
+
return hkdf(sha256, userKey.secret, encoder.encode(USER_KEY_SALT), encoder.encode(USER_KEY_SIGNING_INFO), USER_KEY_SIGNING_SEED_BYTES);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The user key's record signer: the keyring record's signing seam over the
|
|
76
|
+
* derived Ed25519 half, for an app-side record sealed to the vault KAK
|
|
77
|
+
* (`signRecordFrame`). Its `keyMultibase` is exactly what a reader's
|
|
78
|
+
* allowlist holds, so a writer that already has the signer reads the multibase
|
|
79
|
+
* off it rather than calling {@link userKeySigningKeyMultibase} as well.
|
|
80
|
+
*
|
|
81
|
+
* @param options {object}
|
|
82
|
+
* @param options.userKey {UserKey}
|
|
83
|
+
* @returns {Promise<RecordSigner>}
|
|
84
|
+
*/
|
|
85
|
+
export async function userKeyRecordSigner({ userKey }) {
|
|
86
|
+
return recordSignerFromSeed({ seed: userKeySigningSeed({ userKey }) });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The public multibase of the user key's signing half: the one key a reader
|
|
90
|
+
* accepts on a record sealed under this user key, handed to
|
|
91
|
+
* `verifyRecordProof` as its allowlist. For a reader alone -- a writer takes
|
|
92
|
+
* the same value off {@link userKeyRecordSigner}'s `keyMultibase`.
|
|
93
|
+
*
|
|
94
|
+
* @param options {object}
|
|
95
|
+
* @param options.userKey {UserKey}
|
|
96
|
+
* @returns {Promise<string>}
|
|
97
|
+
*/
|
|
98
|
+
export async function userKeySigningKeyMultibase({ userKey }) {
|
|
99
|
+
const { keyMultibase } = await userKeyRecordSigner({ userKey });
|
|
100
|
+
return keyMultibase;
|
|
36
101
|
}
|
|
37
102
|
/**
|
|
38
103
|
* Reconstructs the user key's key-agreement key and its single-key resolver
|
package/dist/keys/userKey.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userKey.js","sourceRoot":"","sources":["../../src/keys/userKey.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"userKey.js","sourceRoot":"","sources":["../../src/keys/userKey.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAK7E,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAG3D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,6BAA6B,CAAA;AAC1D,MAAM,qBAAqB,GAAG,SAAS,CAAA;AAEvC;;GAEG;AACH,MAAM,2BAA2B,GAAG,EAAE,CAAA;AAetC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;IAC7C,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;AAChC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,OAAO,EAGR;IACC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;IACjC,OAAO,IAAI,CACT,MAAM,EACN,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,EAC7B,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,EACrC,2BAA2B,CAC5B,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EACxC,OAAO,EAGR;IACC,OAAO,oBAAoB,CAAC,EAAE,IAAI,EAAE,kBAAkB,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,EAC/C,OAAO,EAGR;IACC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,mBAAmB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IAC/D,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAAwB;IAIhE,MAAM,eAAe,GAAG,yBAAyB,CAAC,aAAa,CAAC;QAC9D,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,EAAE;QACtB,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;KAC9B,CAAqB,CAAA;IACtB,MAAM,WAAW,GAAG,iBAAiB,CAAC,EAAE,eAAe,EAAE,CAAC,CAAA;IAC1D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,CAAA;AACzC,CAAC"}
|
|
@@ -503,9 +503,9 @@ export interface UserKeyRosterReadResult {
|
|
|
503
503
|
* this client's wrap is unwrapped with its own key-agreement key
|
|
504
504
|
* (`UserKeyRosterUnwrapError` when it holds none).
|
|
505
505
|
*
|
|
506
|
-
* A rotated read returns the fresh user key
|
|
507
|
-
*
|
|
508
|
-
*
|
|
506
|
+
* A rotated read returns the fresh user key, and with it the fresh signing
|
|
507
|
+
* half: the roster wraps the key-agreement secret alone, and the Ed25519 half
|
|
508
|
+
* derives from that secret, so a rotation delivers a complete identity.
|
|
509
509
|
*
|
|
510
510
|
* A caller with no cached user key at all -- a freshly enrolled client making
|
|
511
511
|
* its first post-enrollment read -- omits `userKey` and always takes the unwrap
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The derived sets a wallet's audit tests assert: the invariants a transient
|
|
6
|
+
* visit reaches, the gaps the registration index implies, and census
|
|
7
|
+
* completeness. Each is computed from the table and the sites alone, so a
|
|
8
|
+
* converger that quietly loses a trigger a transient visit fires, or an
|
|
9
|
+
* invariant no registration reports any more, moves a derived set and fails
|
|
10
|
+
* the wallet's pin.
|
|
11
|
+
*/
|
|
12
|
+
import { type InvariantId } from './ids.js';
|
|
13
|
+
import type { MenderRegistry } from './registry.js';
|
|
14
|
+
import type { InvariantGap, RegistrationSite } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* One derived gap: the declared row's key and kind, without its prose.
|
|
17
|
+
*/
|
|
18
|
+
type DerivedGap = Pick<InvariantGap, 'invariant' | 'kind'>;
|
|
19
|
+
/**
|
|
20
|
+
* The invariants a transient visit on a standing credential reaches. The
|
|
21
|
+
* two chain triggers are read through `dueAt` over the ladder held set; a
|
|
22
|
+
* `login-routing` site counts unless the client-key-record probe guards it;
|
|
23
|
+
* a `ceremony-tail` entry counts, every such ceremony running on any
|
|
24
|
+
* session type; and a detector no site reports (a declaration carrying
|
|
25
|
+
* `holdsWhen`) counts when it is checked at a trigger a transient visit
|
|
26
|
+
* fires and, on the chain, under an authority the ladder held set carries.
|
|
27
|
+
* An unreported declaration with no detector is reached by nothing.
|
|
28
|
+
*
|
|
29
|
+
* @param options {object}
|
|
30
|
+
* @param options.registry {MenderRegistry}
|
|
31
|
+
* @returns {ReadonlyArray<InvariantId>} in table order
|
|
32
|
+
*/
|
|
33
|
+
export declare function transientReachableInvariants({ registry }: {
|
|
34
|
+
registry: MenderRegistry<RegistrationSite, never>;
|
|
35
|
+
}): ReadonlyArray<InvariantId>;
|
|
36
|
+
/**
|
|
37
|
+
* The gaps the index implies. An invariant no site reports derives `none`,
|
|
38
|
+
* unless it is checked at ceremony tails alone (converged by the ceremony's
|
|
39
|
+
* own sequenced code, which is never registered). A detector is not a
|
|
40
|
+
* mender: a declaration carrying `holdsWhen` and no registration derives
|
|
41
|
+
* `none` like any other unreported one, so adding a detector never retires
|
|
42
|
+
* a gap. A declaration naming a chain or routing trigger no site backs
|
|
43
|
+
* derives `none` whatever else it names. An invariant reported only at sites
|
|
44
|
+
* a transient visit cannot reach, on an account shape the violation can
|
|
45
|
+
* stand on, derives `unreachable`. Nothing else derives a gap.
|
|
46
|
+
*
|
|
47
|
+
* @param options {object}
|
|
48
|
+
* @param options.registry {MenderRegistry}
|
|
49
|
+
* @returns {ReadonlyArray<DerivedGap>}
|
|
50
|
+
*/
|
|
51
|
+
export declare function deriveGaps({ registry }: {
|
|
52
|
+
registry: MenderRegistry<RegistrationSite, never>;
|
|
53
|
+
}): ReadonlyArray<DerivedGap>;
|
|
54
|
+
/**
|
|
55
|
+
* Compares the derived gaps with a wallet's declared allowlist. The
|
|
56
|
+
* derivation admits gaps and retires none: a declared row the derivation no
|
|
57
|
+
* longer produces passes, and a derived gap with no declaration fails. A
|
|
58
|
+
* derived `none` needs a declared `none` row for its invariant; a derived
|
|
59
|
+
* `unreachable` needs any declared row for it, since a declared `none` may
|
|
60
|
+
* be scoped to a different torn state of the same predicate.
|
|
61
|
+
*
|
|
62
|
+
* @param options {object}
|
|
63
|
+
* @param options.derived {ReadonlyArray<DerivedGap>}
|
|
64
|
+
* @param options.declared {ReadonlyArray<InvariantGap>}
|
|
65
|
+
* @returns {ReadonlyArray<DerivedGap>} the
|
|
66
|
+
* derived gaps no declaration covers; empty when the allowlist is complete
|
|
67
|
+
*/
|
|
68
|
+
export declare function undeclaredGaps({ derived, declared }: {
|
|
69
|
+
derived: ReadonlyArray<DerivedGap>;
|
|
70
|
+
declared: ReadonlyArray<InvariantGap>;
|
|
71
|
+
}): ReadonlyArray<DerivedGap>;
|
|
72
|
+
/**
|
|
73
|
+
* Census completeness: the ids in {@link INVARIANT_IDS} the table does not
|
|
74
|
+
* declare. Duplicated ids and undeclared reports are refused by
|
|
75
|
+
* `menderRegistry` at construction, so a registry in hand has neither.
|
|
76
|
+
*
|
|
77
|
+
* @param options {object}
|
|
78
|
+
* @param options.registry {MenderRegistry}
|
|
79
|
+
* @returns {ReadonlyArray<InvariantId>} empty when the census is complete
|
|
80
|
+
*/
|
|
81
|
+
export declare function undeclaredInvariants({ registry }: {
|
|
82
|
+
registry: MenderRegistry<RegistrationSite, never>;
|
|
83
|
+
}): ReadonlyArray<InvariantId>;
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=derive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/menders/derive.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAEhE;;GAEG;AACH,KAAK,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,MAAM,CAAC,CAAA;AAW1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,QAAQ,EACT,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA;CAClD,GAAG,aAAa,CAAC,WAAW,CAAC,CAuC7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACT,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA;CAClD,GAAG,aAAa,CAAC,UAAU,CAAC,CAoB5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,QAAQ,EACT,EAAE;IACD,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IAClC,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;CACtC,GAAG,aAAa,CAAC,UAAU,CAAC,CAS5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACT,EAAE;IACD,QAAQ,EAAE,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA;CAClD,GAAG,aAAa,CAAC,WAAW,CAAC,CAG7B"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The derived sets a wallet's audit tests assert: the invariants a transient
|
|
6
|
+
* visit reaches, the gaps the registration index implies, and census
|
|
7
|
+
* completeness. Each is computed from the table and the sites alone, so a
|
|
8
|
+
* converger that quietly loses a trigger a transient visit fires, or an
|
|
9
|
+
* invariant no registration reports any more, moves a derived set and fails
|
|
10
|
+
* the wallet's pin.
|
|
11
|
+
*/
|
|
12
|
+
import { INVARIANT_IDS } from './ids.js';
|
|
13
|
+
import { heldAuthorities } from './registry.js';
|
|
14
|
+
/**
|
|
15
|
+
* The ids some site reports, whatever its trigger.
|
|
16
|
+
*/
|
|
17
|
+
function reportedIds(registry) {
|
|
18
|
+
return new Set(registry.sites().flatMap(site => site.reports));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The invariants a transient visit on a standing credential reaches. The
|
|
22
|
+
* two chain triggers are read through `dueAt` over the ladder held set; a
|
|
23
|
+
* `login-routing` site counts unless the client-key-record probe guards it;
|
|
24
|
+
* a `ceremony-tail` entry counts, every such ceremony running on any
|
|
25
|
+
* session type; and a detector no site reports (a declaration carrying
|
|
26
|
+
* `holdsWhen`) counts when it is checked at a trigger a transient visit
|
|
27
|
+
* fires and, on the chain, under an authority the ladder held set carries.
|
|
28
|
+
* An unreported declaration with no detector is reached by nothing.
|
|
29
|
+
*
|
|
30
|
+
* @param options {object}
|
|
31
|
+
* @param options.registry {MenderRegistry}
|
|
32
|
+
* @returns {ReadonlyArray<InvariantId>} in table order
|
|
33
|
+
*/
|
|
34
|
+
export function transientReachableInvariants({ registry }) {
|
|
35
|
+
const reached = new Set();
|
|
36
|
+
const held = heldAuthorities({ kind: 'ladder' });
|
|
37
|
+
for (const site of registry.dueAt({
|
|
38
|
+
held,
|
|
39
|
+
trigger: 'transient-login-chain'
|
|
40
|
+
})) {
|
|
41
|
+
for (const id of site.reports) {
|
|
42
|
+
reached.add(id);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const site of registry.sites()) {
|
|
46
|
+
if (site.trigger === 'login-routing' && !site.guardedBy) {
|
|
47
|
+
for (const id of site.reports) {
|
|
48
|
+
reached.add(id);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const reported = reportedIds(registry);
|
|
53
|
+
for (const decl of registry.all()) {
|
|
54
|
+
if (decl.triggers.includes('ceremony-tail')) {
|
|
55
|
+
reached.add(decl.id);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (reported.has(decl.id) || !decl.holdsWhen) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const checkedOnVisit = decl.triggers.includes('login-routing') ||
|
|
62
|
+
(decl.triggers.includes('transient-login-chain') &&
|
|
63
|
+
held.includes(decl.authority));
|
|
64
|
+
if (checkedOnVisit) {
|
|
65
|
+
reached.add(decl.id);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return registry
|
|
69
|
+
.all()
|
|
70
|
+
.filter(decl => reached.has(decl.id))
|
|
71
|
+
.map(decl => decl.id);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The gaps the index implies. An invariant no site reports derives `none`,
|
|
75
|
+
* unless it is checked at ceremony tails alone (converged by the ceremony's
|
|
76
|
+
* own sequenced code, which is never registered). A detector is not a
|
|
77
|
+
* mender: a declaration carrying `holdsWhen` and no registration derives
|
|
78
|
+
* `none` like any other unreported one, so adding a detector never retires
|
|
79
|
+
* a gap. A declaration naming a chain or routing trigger no site backs
|
|
80
|
+
* derives `none` whatever else it names. An invariant reported only at sites
|
|
81
|
+
* a transient visit cannot reach, on an account shape the violation can
|
|
82
|
+
* stand on, derives `unreachable`. Nothing else derives a gap.
|
|
83
|
+
*
|
|
84
|
+
* @param options {object}
|
|
85
|
+
* @param options.registry {MenderRegistry}
|
|
86
|
+
* @returns {ReadonlyArray<DerivedGap>}
|
|
87
|
+
*/
|
|
88
|
+
export function deriveGaps({ registry }) {
|
|
89
|
+
const reported = reportedIds(registry);
|
|
90
|
+
const reachable = new Set(transientReachableInvariants({ registry }));
|
|
91
|
+
const gaps = [];
|
|
92
|
+
for (const decl of registry.all()) {
|
|
93
|
+
if (!reported.has(decl.id)) {
|
|
94
|
+
const tailOnly = decl.triggers.length > 0 &&
|
|
95
|
+
decl.triggers.every(trigger => trigger === 'ceremony-tail');
|
|
96
|
+
if (!tailOnly) {
|
|
97
|
+
gaps.push({ invariant: decl.id, kind: 'none' });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (!reachable.has(decl.id) &&
|
|
101
|
+
decl.standsOn.includes('client-less')) {
|
|
102
|
+
gaps.push({ invariant: decl.id, kind: 'unreachable' });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return gaps;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Compares the derived gaps with a wallet's declared allowlist. The
|
|
109
|
+
* derivation admits gaps and retires none: a declared row the derivation no
|
|
110
|
+
* longer produces passes, and a derived gap with no declaration fails. A
|
|
111
|
+
* derived `none` needs a declared `none` row for its invariant; a derived
|
|
112
|
+
* `unreachable` needs any declared row for it, since a declared `none` may
|
|
113
|
+
* be scoped to a different torn state of the same predicate.
|
|
114
|
+
*
|
|
115
|
+
* @param options {object}
|
|
116
|
+
* @param options.derived {ReadonlyArray<DerivedGap>}
|
|
117
|
+
* @param options.declared {ReadonlyArray<InvariantGap>}
|
|
118
|
+
* @returns {ReadonlyArray<DerivedGap>} the
|
|
119
|
+
* derived gaps no declaration covers; empty when the allowlist is complete
|
|
120
|
+
*/
|
|
121
|
+
export function undeclaredGaps({ derived, declared }) {
|
|
122
|
+
return derived.filter(({ invariant, kind }) => !declared.some(gap => gap.invariant === invariant &&
|
|
123
|
+
(kind === 'unreachable' || gap.kind === 'none')));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Census completeness: the ids in {@link INVARIANT_IDS} the table does not
|
|
127
|
+
* declare. Duplicated ids and undeclared reports are refused by
|
|
128
|
+
* `menderRegistry` at construction, so a registry in hand has neither.
|
|
129
|
+
*
|
|
130
|
+
* @param options {object}
|
|
131
|
+
* @param options.registry {MenderRegistry}
|
|
132
|
+
* @returns {ReadonlyArray<InvariantId>} empty when the census is complete
|
|
133
|
+
*/
|
|
134
|
+
export function undeclaredInvariants({ registry }) {
|
|
135
|
+
const declared = new Set(registry.all().map(decl => decl.id));
|
|
136
|
+
return INVARIANT_IDS.filter(id => !declared.has(id));
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=derive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.js","sourceRoot":"","sources":["../../src/menders/derive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The invariant ids: the closed census both wallets declare against and the
|
|
6
|
+
* mender event channel keys on. Each names the predicate an entry makes
|
|
7
|
+
* true rather than the code that converges it, so moving a converger between
|
|
8
|
+
* modules renames nothing. The ids are code-only; nothing persists them.
|
|
9
|
+
* Numbered in the order the design table assigned them, and a new one takes
|
|
10
|
+
* the next free number rather than renumbering.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Every invariant id, in design-table order.
|
|
14
|
+
*/
|
|
15
|
+
export declare const INVARIANT_IDS: readonly ["roster-wraps-exactly-the-document-key-set", "governed-log-heads-anchor-past-the-membership-change", "collection-epochs-name-the-current-user-key", "unlock-registry-opens-under-the-current-user-key", "registry-passphrase-entry-names-the-standing-credential", "passkey-entry-carries-its-standing-configuration", "registry-lists-the-passphrase-method", "standing-delegations-verify-under-the-current-document", "registry-records-the-committed-ladder-rung", "unlock-record-points-at-the-account-did", "account-pointer-names-the-account-did", "space-controller-is-the-account-did", "roster-and-collection-epochs-exist", "registry-records-the-establishing-credential", "annex-generation-is-reachable", "generation-delegation-is-current", "acting-credential-manage-zcap-is-current", "did-web-projection-matches-the-log", "no-annex-generation-outlives-its-pointer", "app-keys-live-only-in-app-connections", "client-key-record-matches-the-pointed-account", "this-browser-is-still-an-enrolled-client", "no-client-key-record-stays-pending", "recovery-spend-is-completed", "retired-credential-leaves-no-annex-inventory", "document-lists-the-acting-credential", "keystore-controller-is-the-account-did", "account-document-publishes-an-authentication-key", "every-document-key-agreement-entry-has-a-locatable-credential", "no-unlock-space-outlives-its-credential", "no-keystore-outlives-its-account", "saved-recovery-codes-locate-their-account", "standard-collections-are-provisioned", "no-auxiliary-space-stands-unnamed"];
|
|
16
|
+
/**
|
|
17
|
+
* One id from {@link INVARIANT_IDS}.
|
|
18
|
+
*/
|
|
19
|
+
export type InvariantId = (typeof INVARIANT_IDS)[number];
|
|
20
|
+
//# sourceMappingURL=ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/menders/ids.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,i/CAqEhB,CAAA;AAEV;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The invariant ids: the closed census both wallets declare against and the
|
|
6
|
+
* mender event channel keys on. Each names the predicate an entry makes
|
|
7
|
+
* true rather than the code that converges it, so moving a converger between
|
|
8
|
+
* modules renames nothing. The ids are code-only; nothing persists them.
|
|
9
|
+
* Numbered in the order the design table assigned them, and a new one takes
|
|
10
|
+
* the next free number rather than renumbering.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Every invariant id, in design-table order.
|
|
14
|
+
*/
|
|
15
|
+
export const INVARIANT_IDS = [
|
|
16
|
+
// 1
|
|
17
|
+
'roster-wraps-exactly-the-document-key-set',
|
|
18
|
+
// 2
|
|
19
|
+
'governed-log-heads-anchor-past-the-membership-change',
|
|
20
|
+
// 3
|
|
21
|
+
'collection-epochs-name-the-current-user-key',
|
|
22
|
+
// 4
|
|
23
|
+
'unlock-registry-opens-under-the-current-user-key',
|
|
24
|
+
// 5
|
|
25
|
+
'registry-passphrase-entry-names-the-standing-credential',
|
|
26
|
+
// 6
|
|
27
|
+
'passkey-entry-carries-its-standing-configuration',
|
|
28
|
+
// 7
|
|
29
|
+
'registry-lists-the-passphrase-method',
|
|
30
|
+
// 8
|
|
31
|
+
'standing-delegations-verify-under-the-current-document',
|
|
32
|
+
// 9
|
|
33
|
+
'registry-records-the-committed-ladder-rung',
|
|
34
|
+
// 10
|
|
35
|
+
'unlock-record-points-at-the-account-did',
|
|
36
|
+
// 11
|
|
37
|
+
'account-pointer-names-the-account-did',
|
|
38
|
+
// 12
|
|
39
|
+
'space-controller-is-the-account-did',
|
|
40
|
+
// 13
|
|
41
|
+
'roster-and-collection-epochs-exist',
|
|
42
|
+
// 14
|
|
43
|
+
'registry-records-the-establishing-credential',
|
|
44
|
+
// 15
|
|
45
|
+
'annex-generation-is-reachable',
|
|
46
|
+
// 16
|
|
47
|
+
'generation-delegation-is-current',
|
|
48
|
+
// 17
|
|
49
|
+
'acting-credential-manage-zcap-is-current',
|
|
50
|
+
// 18
|
|
51
|
+
'did-web-projection-matches-the-log',
|
|
52
|
+
// 19
|
|
53
|
+
'no-annex-generation-outlives-its-pointer',
|
|
54
|
+
// 20
|
|
55
|
+
'app-keys-live-only-in-app-connections',
|
|
56
|
+
// 21
|
|
57
|
+
'client-key-record-matches-the-pointed-account',
|
|
58
|
+
// 22
|
|
59
|
+
'this-browser-is-still-an-enrolled-client',
|
|
60
|
+
// 23
|
|
61
|
+
'no-client-key-record-stays-pending',
|
|
62
|
+
// 24
|
|
63
|
+
'recovery-spend-is-completed',
|
|
64
|
+
// 25
|
|
65
|
+
'retired-credential-leaves-no-annex-inventory',
|
|
66
|
+
// 26
|
|
67
|
+
'document-lists-the-acting-credential',
|
|
68
|
+
// 27
|
|
69
|
+
'keystore-controller-is-the-account-did',
|
|
70
|
+
// 28
|
|
71
|
+
'account-document-publishes-an-authentication-key',
|
|
72
|
+
// 29
|
|
73
|
+
'every-document-key-agreement-entry-has-a-locatable-credential',
|
|
74
|
+
// 30
|
|
75
|
+
'no-unlock-space-outlives-its-credential',
|
|
76
|
+
// 31
|
|
77
|
+
'no-keystore-outlives-its-account',
|
|
78
|
+
// 32
|
|
79
|
+
'saved-recovery-codes-locate-their-account',
|
|
80
|
+
// 33
|
|
81
|
+
'standard-collections-are-provisioned',
|
|
82
|
+
// 34
|
|
83
|
+
'no-auxiliary-space-stands-unnamed'
|
|
84
|
+
];
|
|
85
|
+
//# sourceMappingURL=ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.js","sourceRoot":"","sources":["../../src/menders/ids.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI;IACJ,2CAA2C;IAC3C,IAAI;IACJ,sDAAsD;IACtD,IAAI;IACJ,6CAA6C;IAC7C,IAAI;IACJ,kDAAkD;IAClD,IAAI;IACJ,yDAAyD;IACzD,IAAI;IACJ,kDAAkD;IAClD,IAAI;IACJ,sCAAsC;IACtC,IAAI;IACJ,wDAAwD;IACxD,IAAI;IACJ,4CAA4C;IAC5C,KAAK;IACL,yCAAyC;IACzC,KAAK;IACL,uCAAuC;IACvC,KAAK;IACL,qCAAqC;IACrC,KAAK;IACL,oCAAoC;IACpC,KAAK;IACL,8CAA8C;IAC9C,KAAK;IACL,+BAA+B;IAC/B,KAAK;IACL,kCAAkC;IAClC,KAAK;IACL,0CAA0C;IAC1C,KAAK;IACL,oCAAoC;IACpC,KAAK;IACL,0CAA0C;IAC1C,KAAK;IACL,uCAAuC;IACvC,KAAK;IACL,+CAA+C;IAC/C,KAAK;IACL,0CAA0C;IAC1C,KAAK;IACL,oCAAoC;IACpC,KAAK;IACL,6BAA6B;IAC7B,KAAK;IACL,8CAA8C;IAC9C,KAAK;IACL,sCAAsC;IACtC,KAAK;IACL,wCAAwC;IACxC,KAAK;IACL,kDAAkD;IAClD,KAAK;IACL,+DAA+D;IAC/D,KAAK;IACL,yCAAyC;IACzC,KAAK;IACL,kCAAkC;IAClC,KAAK;IACL,2CAA2C;IAC3C,KAAK;IACL,sCAAsC;IACtC,KAAK;IACL,mCAAmC;CAC3B,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/wallet-core/menders` subpath: the mender registry keyed by
|
|
6
|
+
* invariant. A wallet declares its own table of invariants (data: what must
|
|
7
|
+
* hold between ceremonies) and its own registrations (code: what converges a
|
|
8
|
+
* violated one); this module carries the structure both wallets share.
|
|
9
|
+
*
|
|
10
|
+
* - the vocabularies: `AUTHORITIES`, `TRIGGERS`, `CHAIN_TRIGGERS`,
|
|
11
|
+
* `ACCOUNT_SHAPES`, `EVIDENCE`, `MEND_OUTCOMES`, `GAP_KINDS`, and
|
|
12
|
+
* `INVARIANT_IDS`, each an `as const` array with its union
|
|
13
|
+
* - the types: `InvariantDeclaration`, `RegistrationSite`, `Registration`,
|
|
14
|
+
* `MendOutcome`, `MendReportEntry`, `MendReport`, `InvariantGap`,
|
|
15
|
+
* `LoginRoute`
|
|
16
|
+
* - the readers: `menderRegistry` (`all`, `byId`, `sites`, `admits`,
|
|
17
|
+
* `dueAt`), which refuses a duplicated id, an undeclared report, or a
|
|
18
|
+
* guard on a non-routing site at construction, and `heldAuthorities`, the
|
|
19
|
+
* held set a session's account-ceremony context derives
|
|
20
|
+
* - the runner: `runMenderBlock`, one try, warn, and skip discipline over
|
|
21
|
+
* one chain trigger's registrations, `mendReportAccumulator`, the
|
|
22
|
+
* pre-session report collector its `onOutcome` feeds, and `errorNameOf`,
|
|
23
|
+
* the name a report carries for a thrown value of any shape
|
|
24
|
+
* - the derived sets a wallet's audit tests pin:
|
|
25
|
+
* `transientReachableInvariants`, `deriveGaps`, `undeclaredGaps`, and
|
|
26
|
+
* `undeclaredInvariants`
|
|
27
|
+
*
|
|
28
|
+
* Nothing here executes a ceremony. The runner calls the convergers a
|
|
29
|
+
* wallet registers and nothing else; the ceremonies stay explicit sequenced
|
|
30
|
+
* code, and the registry describes the menders from the outside.
|
|
31
|
+
*/
|
|
32
|
+
export { deriveGaps, transientReachableInvariants, undeclaredGaps, undeclaredInvariants } from './derive.js';
|
|
33
|
+
export { INVARIANT_IDS } from './ids.js';
|
|
34
|
+
export type { InvariantId } from './ids.js';
|
|
35
|
+
export { heldAuthorities, menderRegistry } from './registry.js';
|
|
36
|
+
export type { MenderRegistry, ResolvedAuthority } from './registry.js';
|
|
37
|
+
export { errorNameOf, MEND_REPORT_SHAPE_ERROR, mendReportAccumulator, runMenderBlock } from './runner.js';
|
|
38
|
+
export type { MendReportAccumulator } from './runner.js';
|
|
39
|
+
export type { InvariantDeclaration, InvariantGap, LoginRoute, MendOutcome, MendReport, MendReportEntry, Registration, RegistrationSite } from './types.js';
|
|
40
|
+
export { ACCOUNT_SHAPES, AUTHORITIES, CHAIN_TRIGGERS, EVIDENCE, GAP_KINDS, MEND_OUTCOMES, TRIGGERS } from './vocabulary.js';
|
|
41
|
+
export type { AccountShape, Authority, ChainTrigger, Evidence, GapKind, MendOutcomeKind, Trigger } from './vocabulary.js';
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/menders/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EACL,UAAU,EACV,4BAA4B,EAC5B,cAAc,EACd,oBAAoB,EACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC/D,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACf,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,UAAU,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,cAAc,EACd,WAAW,EACX,cAAc,EACd,QAAQ,EACR,SAAS,EACT,aAAa,EACb,QAAQ,EACT,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,eAAe,EACf,OAAO,EACR,MAAM,iBAAiB,CAAA"}
|