@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.
Files changed (160) hide show
  1. package/README.md +14 -3
  2. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +2 -2
  3. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
  4. package/dist/clientAnnex/credentialAnchoredGenesis.js +1 -1
  5. package/dist/clientAnnex/forget.d.ts.map +1 -1
  6. package/dist/clientAnnex/forget.js +4 -3
  7. package/dist/clientAnnex/forget.js.map +1 -1
  8. package/dist/clientAnnex/forgetLast.d.ts +55 -35
  9. package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
  10. package/dist/clientAnnex/forgetLast.js +87 -35
  11. package/dist/clientAnnex/forgetLast.js.map +1 -1
  12. package/dist/clientAnnex/gc.d.ts +48 -19
  13. package/dist/clientAnnex/gc.d.ts.map +1 -1
  14. package/dist/clientAnnex/gc.js +82 -31
  15. package/dist/clientAnnex/gc.js.map +1 -1
  16. package/dist/clientAnnex/grantRevocation.d.ts +137 -0
  17. package/dist/clientAnnex/grantRevocation.d.ts.map +1 -0
  18. package/dist/clientAnnex/grantRevocation.js +135 -0
  19. package/dist/clientAnnex/grantRevocation.js.map +1 -0
  20. package/dist/clientAnnex/index.d.ts +4 -2
  21. package/dist/clientAnnex/index.d.ts.map +1 -1
  22. package/dist/clientAnnex/index.js +2 -1
  23. package/dist/clientAnnex/index.js.map +1 -1
  24. package/dist/clientAnnex/ladderAnchored.d.ts +0 -22
  25. package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
  26. package/dist/clientAnnex/ladderAnchored.js +8 -34
  27. package/dist/clientAnnex/ladderAnchored.js.map +1 -1
  28. package/dist/clientAnnex/log.d.ts +65 -13
  29. package/dist/clientAnnex/log.d.ts.map +1 -1
  30. package/dist/clientAnnex/log.js +160 -67
  31. package/dist/clientAnnex/log.js.map +1 -1
  32. package/dist/clientAnnex/mend.js +51 -24
  33. package/dist/clientAnnex/mend.js.map +1 -1
  34. package/dist/clientAnnex/zcap.d.ts.map +1 -1
  35. package/dist/clientAnnex/zcap.js +3 -10
  36. package/dist/clientAnnex/zcap.js.map +1 -1
  37. package/dist/clients/grantState.d.ts +6 -3
  38. package/dist/clients/grantState.d.ts.map +1 -1
  39. package/dist/clients/grantState.js +6 -3
  40. package/dist/clients/grantState.js.map +1 -1
  41. package/dist/clients/policy.d.ts.map +1 -1
  42. package/dist/clients/policy.js +3 -0
  43. package/dist/clients/policy.js.map +1 -1
  44. package/dist/genesis/accountGenesis.d.ts +1 -1
  45. package/dist/genesis/accountGenesis.d.ts.map +1 -1
  46. package/dist/keyring/fetch.d.ts +6 -2
  47. package/dist/keyring/fetch.d.ts.map +1 -1
  48. package/dist/keyring/fetch.js +7 -3
  49. package/dist/keyring/fetch.js.map +1 -1
  50. package/dist/keyring/index.d.ts +15 -10
  51. package/dist/keyring/index.d.ts.map +1 -1
  52. package/dist/keyring/index.js +15 -10
  53. package/dist/keyring/index.js.map +1 -1
  54. package/dist/keyring/kdf.d.ts +1 -1
  55. package/dist/keyring/kdf.d.ts.map +1 -1
  56. package/dist/keyring/kdf.js +1 -1
  57. package/dist/keyring/kdf.js.map +1 -1
  58. package/dist/keyring/record.d.ts +15 -0
  59. package/dist/keyring/record.d.ts.map +1 -1
  60. package/dist/keyring/record.js +22 -0
  61. package/dist/keyring/record.js.map +1 -1
  62. package/dist/keyring/unlockSpace.d.ts +45 -68
  63. package/dist/keyring/unlockSpace.d.ts.map +1 -1
  64. package/dist/keyring/unlockSpace.js +66 -88
  65. package/dist/keyring/unlockSpace.js.map +1 -1
  66. package/dist/keys/clientKeyRecord.d.ts +3 -4
  67. package/dist/keys/clientKeyRecord.d.ts.map +1 -1
  68. package/dist/keys/clientKeyRecord.js +6 -25
  69. package/dist/keys/clientKeyRecord.js.map +1 -1
  70. package/dist/keys/index.d.ts +6 -1
  71. package/dist/keys/index.d.ts.map +1 -1
  72. package/dist/keys/index.js +6 -1
  73. package/dist/keys/index.js.map +1 -1
  74. package/dist/keys/userKey.d.ts +57 -11
  75. package/dist/keys/userKey.d.ts.map +1 -1
  76. package/dist/keys/userKey.js +76 -11
  77. package/dist/keys/userKey.js.map +1 -1
  78. package/dist/keys/userKeyRoster.d.ts +3 -3
  79. package/dist/menders/derive.d.ts +85 -0
  80. package/dist/menders/derive.d.ts.map +1 -0
  81. package/dist/menders/derive.js +138 -0
  82. package/dist/menders/derive.js.map +1 -0
  83. package/dist/menders/ids.d.ts +20 -0
  84. package/dist/menders/ids.d.ts.map +1 -0
  85. package/dist/menders/ids.js +85 -0
  86. package/dist/menders/ids.js.map +1 -0
  87. package/dist/menders/index.d.ts +42 -0
  88. package/dist/menders/index.d.ts.map +1 -0
  89. package/dist/menders/index.js +37 -0
  90. package/dist/menders/index.js.map +1 -0
  91. package/dist/menders/registry.d.ts +84 -0
  92. package/dist/menders/registry.d.ts.map +1 -0
  93. package/dist/menders/registry.js +62 -0
  94. package/dist/menders/registry.js.map +1 -0
  95. package/dist/menders/runner.d.ts +143 -0
  96. package/dist/menders/runner.d.ts.map +1 -0
  97. package/dist/menders/runner.js +222 -0
  98. package/dist/menders/runner.js.map +1 -0
  99. package/dist/menders/types.d.ts +146 -0
  100. package/dist/menders/types.d.ts.map +1 -0
  101. package/dist/menders/types.js +2 -0
  102. package/dist/menders/types.js.map +1 -0
  103. package/dist/menders/vocabulary.d.ts +90 -0
  104. package/dist/menders/vocabulary.d.ts.map +1 -0
  105. package/dist/menders/vocabulary.js +86 -0
  106. package/dist/menders/vocabulary.js.map +1 -0
  107. package/dist/recovery/index.d.ts +1 -1
  108. package/dist/recovery/index.js +1 -1
  109. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  110. package/dist/recovery/recoveryWebvh.js +11 -17
  111. package/dist/recovery/recoveryWebvh.js.map +1 -1
  112. package/dist/resourceLog/document.d.ts.map +1 -1
  113. package/dist/resourceLog/document.js +30 -6
  114. package/dist/resourceLog/document.js.map +1 -1
  115. package/dist/space/activity.d.ts +70 -0
  116. package/dist/space/activity.d.ts.map +1 -1
  117. package/dist/space/activity.js +82 -0
  118. package/dist/space/activity.js.map +1 -1
  119. package/dist/space/deleteSpace.d.ts.map +1 -1
  120. package/dist/space/deleteSpace.js +6 -5
  121. package/dist/space/deleteSpace.js.map +1 -1
  122. package/dist/space/index.d.ts +1 -1
  123. package/dist/space/index.d.ts.map +1 -1
  124. package/dist/space/index.js +1 -1
  125. package/dist/space/index.js.map +1 -1
  126. package/dist/testing.d.ts +78 -0
  127. package/dist/testing.d.ts.map +1 -0
  128. package/dist/testing.js +89 -0
  129. package/dist/testing.js.map +1 -0
  130. package/dist/unlock/index.d.ts +2 -2
  131. package/dist/unlock/index.d.ts.map +1 -1
  132. package/dist/unlock/index.js +1 -1
  133. package/dist/unlock/retire.d.ts +20 -5
  134. package/dist/unlock/retire.d.ts.map +1 -1
  135. package/dist/unlock/retire.js.map +1 -1
  136. package/dist/unlock/standingWebvh.d.ts +22 -2
  137. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  138. package/dist/unlock/standingWebvh.js +22 -2
  139. package/dist/unlock/standingWebvh.js.map +1 -1
  140. package/dist/webvh/didWebvh.d.ts +33 -0
  141. package/dist/webvh/didWebvh.d.ts.map +1 -1
  142. package/dist/webvh/didWebvh.js +52 -18
  143. package/dist/webvh/didWebvh.js.map +1 -1
  144. package/dist/webvh/enrollClient.d.ts.map +1 -1
  145. package/dist/webvh/enrollClient.js +4 -16
  146. package/dist/webvh/enrollClient.js.map +1 -1
  147. package/dist/webvh/index.d.ts +13 -3
  148. package/dist/webvh/index.d.ts.map +1 -1
  149. package/dist/webvh/index.js +13 -3
  150. package/dist/webvh/index.js.map +1 -1
  151. package/dist/webvh/listClients.d.ts +47 -0
  152. package/dist/webvh/listClients.d.ts.map +1 -1
  153. package/dist/webvh/listClients.js +40 -1
  154. package/dist/webvh/listClients.js.map +1 -1
  155. package/dist/webvh/standingZcap.d.ts +66 -0
  156. package/dist/webvh/standingZcap.d.ts.map +1 -1
  157. package/dist/webvh/standingZcap.js +96 -0
  158. package/dist/webvh/standingZcap.js.map +1 -1
  159. package/dist/webvh/zcap.d.ts +1 -1
  160. package/package.json +22 -10
@@ -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), plus the 32-byte seed of the user key's Ed25519 signing pair. Random
6
- * per account; held in memory for the life of a session and persisted only
7
- * inside a wrapped client-key record. The signing seed is absent on a user key
8
- * adopted from a roster rotation -- the roster wraps the key-agreement secret
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
- * plus a random 32-byte Ed25519 signing seed -- a minted user key is always a
20
- * complete identity (only a rotation-adopted one lacks the signing half).
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
- * @returns {Promise<Required<UserKey>>}
64
+ * @param options {object}
65
+ * @param options.userKey {UserKey}
66
+ * @returns {Promise<string>}
23
67
  */
24
- export declare function mintUserKey(): Promise<Required<UserKey>>;
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":"AAoBA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AAIrC;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,UAAU,CAAA;IAClB,WAAW,CAAC,EAAE,UAAU,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAK9D;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"}
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"}
@@ -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 is a
16
- * second independent 32-byte seed, minted now so the user key is a complete
17
- * identity, with no consumer yet (the pair derives from the seed on demand once
18
- * one lands).
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
- * plus a random 32-byte Ed25519 signing seed -- a minted user key is always a
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<Required<UserKey>>}
53
+ * @returns {Promise<UserKey>}
30
54
  */
31
55
  export async function mintUserKey() {
32
56
  const { epochId, secret } = await mintEpoch();
33
- const signingSeed = new Uint8Array(32);
34
- crypto.getRandomValues(signingSeed);
35
- return { id: epochId, secret, signingSeed };
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
@@ -1 +1 @@
1
- {"version":3,"file":"userKey.js","sourceRoot":"","sources":["../../src/keys/userKey.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;GAeG;AACH,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;AAiBhE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;IAC7C,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAA;IACtC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAA;IACnC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;AAC7C,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"}
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; its Ed25519 signing seed does not
507
- * travel through the roster (the roster wraps the key-agreement secret
508
- * alone), so the returned user key carries none.
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"}