@serfab/cadre-core 1.16.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/README.md +4 -3
  2. package/dist/bootstrap-peer-store-file.js +1 -1
  3. package/dist/bootstrap-peer-store.d.ts +1 -1
  4. package/dist/bootstrap-peer-store.js +4 -4
  5. package/dist/cadre-invite-protocol.d.ts +81 -142
  6. package/dist/cadre-invite-protocol.js +168 -458
  7. package/dist/cadre-invite-protocol.js.map +1 -1
  8. package/dist/cadre-join-request.d.ts +15 -2
  9. package/dist/cadre-join-request.js +22 -3
  10. package/dist/cadre-join-request.js.map +1 -1
  11. package/dist/cadre-node.d.ts +1089 -475
  12. package/dist/cadre-node.js +2170 -1037
  13. package/dist/cadre-node.js.map +1 -1
  14. package/dist/control-authorization.d.ts +36 -14
  15. package/dist/control-authorization.js +20 -3
  16. package/dist/control-authorization.js.map +1 -1
  17. package/dist/control-cohort.d.ts +88 -32
  18. package/dist/control-cohort.js +91 -33
  19. package/dist/control-cohort.js.map +1 -1
  20. package/dist/control-database.d.ts +856 -318
  21. package/dist/control-database.js +1422 -701
  22. package/dist/control-database.js.map +1 -1
  23. package/dist/control-formation-recorder.d.ts +46 -43
  24. package/dist/control-formation-recorder.js +77 -78
  25. package/dist/control-formation-recorder.js.map +1 -1
  26. package/dist/control-protocol-guard.d.ts +11 -4
  27. package/dist/control-protocol-guard.js +20 -5
  28. package/dist/control-protocol-guard.js.map +1 -1
  29. package/dist/control-schema-version.d.ts +97 -0
  30. package/dist/control-schema-version.js +225 -0
  31. package/dist/control-schema-version.js.map +1 -0
  32. package/dist/control-schema.d.ts +45 -5
  33. package/dist/control-schema.js +262 -78
  34. package/dist/control-schema.js.map +1 -1
  35. package/dist/control-write-retry.d.ts +45 -10
  36. package/dist/control-write-retry.js +92 -22
  37. package/dist/control-write-retry.js.map +1 -1
  38. package/dist/delegate-admission.d.ts +13 -0
  39. package/dist/delegate-admission.js +27 -0
  40. package/dist/delegate-admission.js.map +1 -1
  41. package/dist/ed25519-key.d.ts +10 -7
  42. package/dist/ed25519-key.js +23 -20
  43. package/dist/ed25519-key.js.map +1 -1
  44. package/dist/edge-node/config.d.ts +122 -0
  45. package/dist/edge-node/config.js +199 -0
  46. package/dist/edge-node/config.js.map +1 -0
  47. package/dist/edge-node/dissolve.d.ts +95 -0
  48. package/dist/edge-node/dissolve.js +184 -0
  49. package/dist/edge-node/dissolve.js.map +1 -0
  50. package/dist/edge-node/edge-join.d.ts +44 -0
  51. package/dist/edge-node/edge-join.js +227 -0
  52. package/dist/edge-node/edge-join.js.map +1 -0
  53. package/dist/edge-node/edge-node.d.ts +295 -0
  54. package/dist/edge-node/edge-node.js +704 -0
  55. package/dist/edge-node/edge-node.js.map +1 -0
  56. package/dist/edge-node/index.d.ts +18 -0
  57. package/dist/edge-node/index.js +18 -0
  58. package/dist/edge-node/index.js.map +1 -0
  59. package/dist/edge-node/join-credential.d.ts +11 -0
  60. package/dist/edge-node/join-credential.js +11 -0
  61. package/dist/edge-node/join-credential.js.map +1 -0
  62. package/dist/edge-node/lazy-raw-storage.d.ts +40 -0
  63. package/dist/edge-node/lazy-raw-storage.js +134 -0
  64. package/dist/edge-node/lazy-raw-storage.js.map +1 -0
  65. package/dist/edge-node/node-local.d.ts +60 -0
  66. package/dist/edge-node/node-local.js +58 -0
  67. package/dist/edge-node/node-local.js.map +1 -0
  68. package/dist/edge-node/options.d.ts +83 -0
  69. package/dist/edge-node/options.js +110 -0
  70. package/dist/edge-node/options.js.map +1 -0
  71. package/dist/edge-node/owner-grant.d.ts +41 -0
  72. package/dist/edge-node/owner-grant.js +38 -0
  73. package/dist/edge-node/owner-grant.js.map +1 -0
  74. package/dist/edge-node/platform.d.ts +140 -0
  75. package/dist/edge-node/platform.js +12 -0
  76. package/dist/edge-node/platform.js.map +1 -0
  77. package/dist/edge-node/strand-move.d.ts +115 -0
  78. package/dist/edge-node/strand-move.js +223 -0
  79. package/dist/edge-node/strand-move.js.map +1 -0
  80. package/dist/edge-node/strands.d.ts +28 -0
  81. package/dist/edge-node/strands.js +60 -0
  82. package/dist/edge-node/strands.js.map +1 -0
  83. package/dist/enrolled-machine-store.d.ts +3 -3
  84. package/dist/enrolled-machine-store.js +3 -3
  85. package/dist/formation-token.d.ts +48 -0
  86. package/dist/formation-token.js +26 -0
  87. package/dist/formation-token.js.map +1 -0
  88. package/dist/index.d.ts +27 -17
  89. package/dist/index.js +39 -17
  90. package/dist/index.js.map +1 -1
  91. package/dist/joined-strand-store.d.ts +29 -12
  92. package/dist/joined-strand-store.js +66 -27
  93. package/dist/joined-strand-store.js.map +1 -1
  94. package/dist/key-store.d.ts +9 -4
  95. package/dist/key-store.js +9 -4
  96. package/dist/key-store.js.map +1 -1
  97. package/dist/link-budget.d.ts +9 -7
  98. package/dist/link-budget.js +9 -7
  99. package/dist/link-budget.js.map +1 -1
  100. package/dist/machine-removal.d.ts +19 -39
  101. package/dist/machine-removal.js +24 -98
  102. package/dist/machine-removal.js.map +1 -1
  103. package/dist/member-redemption.d.ts +256 -0
  104. package/dist/member-redemption.js +490 -0
  105. package/dist/member-redemption.js.map +1 -0
  106. package/dist/membership-view.d.ts +91 -0
  107. package/dist/membership-view.js +110 -0
  108. package/dist/membership-view.js.map +1 -0
  109. package/dist/owner-anchor-sync.d.ts +4 -4
  110. package/dist/owner-anchor-sync.js +16 -15
  111. package/dist/owner-anchor-sync.js.map +1 -1
  112. package/dist/owner-grant-protocol.d.ts +251 -0
  113. package/dist/owner-grant-protocol.js +344 -0
  114. package/dist/owner-grant-protocol.js.map +1 -0
  115. package/dist/owner-key-export.d.ts +70 -0
  116. package/dist/owner-key-export.js +279 -0
  117. package/dist/owner-key-export.js.map +1 -0
  118. package/dist/owner-key-flows.d.ts +55 -0
  119. package/dist/owner-key-flows.js +60 -0
  120. package/dist/owner-key-flows.js.map +1 -0
  121. package/dist/owner-key-store.d.ts +31 -0
  122. package/dist/owner-key-store.js +81 -0
  123. package/dist/owner-key-store.js.map +1 -0
  124. package/dist/owner-keys.d.ts +78 -0
  125. package/dist/owner-keys.js +133 -0
  126. package/dist/owner-keys.js.map +1 -0
  127. package/dist/owner-signer.d.ts +54 -0
  128. package/dist/owner-signer.js +51 -0
  129. package/dist/owner-signer.js.map +1 -0
  130. package/dist/peer-addr-book.d.ts +10 -1
  131. package/dist/peer-addr-book.js +4 -3
  132. package/dist/peer-addr-book.js.map +1 -1
  133. package/dist/peer-authorization.d.ts +83 -18
  134. package/dist/peer-authorization.js +123 -53
  135. package/dist/peer-authorization.js.map +1 -1
  136. package/dist/peer-join-backfill.d.ts +89 -20
  137. package/dist/peer-join-backfill.js +265 -108
  138. package/dist/peer-join-backfill.js.map +1 -1
  139. package/dist/pending-join-runner.d.ts +48 -18
  140. package/dist/pending-join-runner.js +74 -56
  141. package/dist/pending-join-runner.js.map +1 -1
  142. package/dist/provider/rent-node.js +1 -1
  143. package/dist/provider/rent-node.js.map +1 -1
  144. package/dist/seed-bootstrap.d.ts +162 -133
  145. package/dist/seed-bootstrap.js +300 -283
  146. package/dist/seed-bootstrap.js.map +1 -1
  147. package/dist/seed-trust-policy.js +4 -4
  148. package/dist/strand-addr-protocol.d.ts +4 -1
  149. package/dist/strand-addr-protocol.js +8 -2
  150. package/dist/strand-addr-protocol.js.map +1 -1
  151. package/dist/strand-cohort.d.ts +3 -0
  152. package/dist/strand-cohort.js.map +1 -1
  153. package/dist/strand-database.d.ts +24 -2
  154. package/dist/strand-database.js +29 -6
  155. package/dist/strand-database.js.map +1 -1
  156. package/dist/strand-first-sync-gate.d.ts +176 -88
  157. package/dist/strand-first-sync-gate.js +288 -121
  158. package/dist/strand-first-sync-gate.js.map +1 -1
  159. package/dist/strand-formation-deadlines.d.ts +9 -9
  160. package/dist/strand-formation-deadlines.js +9 -9
  161. package/dist/strand-formation-manager.d.ts +23 -17
  162. package/dist/strand-formation-manager.js +46 -44
  163. package/dist/strand-formation-manager.js.map +1 -1
  164. package/dist/strand-formation-protocol.d.ts +5 -8
  165. package/dist/strand-formation-protocol.js +101 -16
  166. package/dist/strand-formation-protocol.js.map +1 -1
  167. package/dist/strand-instance-manager.d.ts +27 -18
  168. package/dist/strand-instance-manager.js +119 -50
  169. package/dist/strand-instance-manager.js.map +1 -1
  170. package/dist/strand-membership-reconciler.d.ts +16 -13
  171. package/dist/strand-membership-reconciler.js +30 -22
  172. package/dist/strand-membership-reconciler.js.map +1 -1
  173. package/dist/strand-membership-writer.d.ts +45 -22
  174. package/dist/strand-membership-writer.js +226 -131
  175. package/dist/strand-membership-writer.js.map +1 -1
  176. package/dist/strand-move.d.ts +6 -5
  177. package/dist/strand-move.js +36 -32
  178. package/dist/strand-move.js.map +1 -1
  179. package/dist/strand-peer-redial.js +2 -3
  180. package/dist/strand-peer-redial.js.map +1 -1
  181. package/dist/strand-revocation-enforcer.d.ts +134 -60
  182. package/dist/strand-revocation-enforcer.js +144 -71
  183. package/dist/strand-revocation-enforcer.js.map +1 -1
  184. package/dist/strand-solicitation.d.ts +50 -39
  185. package/dist/strand-solicitation.js +10 -3
  186. package/dist/strand-solicitation.js.map +1 -1
  187. package/dist/strand-watcher.d.ts +80 -13
  188. package/dist/strand-watcher.js +152 -48
  189. package/dist/strand-watcher.js.map +1 -1
  190. package/dist/table-change-watch.d.ts +63 -0
  191. package/dist/table-change-watch.js +209 -0
  192. package/dist/table-change-watch.js.map +1 -0
  193. package/dist/timeout-scheduler.d.ts +4 -3
  194. package/dist/timeout-scheduler.js +4 -3
  195. package/dist/timeout-scheduler.js.map +1 -1
  196. package/dist/types.d.ts +374 -150
  197. package/dist/types.js +4 -4
  198. package/dist/types.js.map +1 -1
  199. package/package.json +17 -8
  200. package/src/bootstrap-peer-store-file.ts +44 -44
  201. package/src/bootstrap-peer-store.ts +214 -214
  202. package/src/cadre-invite-protocol.ts +740 -1052
  203. package/src/cadre-join-request.ts +24 -3
  204. package/src/cadre-node.ts +2402 -1079
  205. package/src/control-authorization.ts +47 -14
  206. package/src/control-cohort.ts +204 -128
  207. package/src/control-database.ts +1749 -820
  208. package/src/control-formation-recorder.ts +359 -353
  209. package/src/control-protocol-guard.ts +23 -6
  210. package/src/control-schema-version.ts +301 -0
  211. package/src/control-schema.ts +273 -78
  212. package/src/control-write-retry.ts +641 -567
  213. package/src/delegate-admission.ts +351 -314
  214. package/src/ed25519-key.ts +174 -171
  215. package/src/edge-node/config.ts +277 -0
  216. package/src/edge-node/dissolve.ts +251 -0
  217. package/src/edge-node/edge-join.ts +319 -0
  218. package/src/edge-node/edge-node.ts +1045 -0
  219. package/src/edge-node/index.ts +59 -0
  220. package/src/edge-node/join-credential.ts +16 -0
  221. package/src/edge-node/lazy-raw-storage.ts +178 -0
  222. package/src/edge-node/node-local.ts +84 -0
  223. package/src/edge-node/options.ts +179 -0
  224. package/src/edge-node/owner-grant.ts +63 -0
  225. package/src/edge-node/platform.ts +151 -0
  226. package/src/edge-node/strand-move.ts +270 -0
  227. package/src/edge-node/strands.ts +72 -0
  228. package/src/enrolled-machine-store.ts +3 -3
  229. package/src/formation-token.ts +63 -0
  230. package/src/index.ts +899 -789
  231. package/src/joined-strand-store.ts +73 -28
  232. package/src/key-store.ts +10 -4
  233. package/src/link-budget.ts +9 -7
  234. package/src/machine-removal.ts +26 -111
  235. package/src/member-redemption.ts +649 -0
  236. package/src/membership-view.ts +144 -0
  237. package/src/owner-anchor-sync.ts +19 -18
  238. package/src/owner-grant-protocol.ts +547 -0
  239. package/src/owner-key-export.ts +348 -0
  240. package/src/owner-key-flows.ts +109 -0
  241. package/src/owner-key-store.ts +85 -0
  242. package/src/owner-keys.ts +178 -0
  243. package/src/owner-signer.ts +94 -0
  244. package/src/peer-addr-book.ts +4 -3
  245. package/src/peer-authorization.ts +558 -488
  246. package/src/peer-join-backfill.ts +971 -761
  247. package/src/pending-join-runner.ts +76 -53
  248. package/src/provider/rent-node.ts +1 -1
  249. package/src/seed-bootstrap.ts +343 -349
  250. package/src/seed-trust-policy.ts +4 -4
  251. package/src/strand-addr-protocol.ts +547 -538
  252. package/src/strand-cohort.ts +4 -0
  253. package/src/strand-database.ts +352 -319
  254. package/src/strand-first-sync-gate.ts +334 -133
  255. package/src/strand-formation-deadlines.ts +227 -227
  256. package/src/strand-formation-manager.ts +731 -725
  257. package/src/strand-formation-protocol.ts +122 -24
  258. package/src/strand-instance-manager.ts +2092 -2026
  259. package/src/strand-membership-reconciler.ts +33 -25
  260. package/src/strand-membership-writer.ts +2093 -1974
  261. package/src/strand-move.ts +50 -38
  262. package/src/strand-peer-redial.ts +2 -3
  263. package/src/strand-revocation-enforcer.ts +740 -654
  264. package/src/strand-solicitation.ts +61 -34
  265. package/src/strand-watcher.ts +175 -56
  266. package/src/table-change-watch.ts +285 -0
  267. package/src/timeout-scheduler.ts +29 -28
  268. package/src/types.ts +391 -152
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Owner keys as an app lists, adds and removes them (`CadreNode.listOwnerKeys`,
3
+ * `CadreNode.addOwner`, `CadreNode.planOwnerKeyRemoval`, `CadreNode.removeOwner`): the
4
+ * projection of the live `OwnerKey` rows an owner-key screen shows, the read-only plan behind a
5
+ * removal's confirmation step, the check that a requested re-vouch stays inside that plan, and
6
+ * the by-name refusals. Pure; the reads and writes themselves are `CadreNode`'s and
7
+ * `ControlDatabase`'s.
8
+ */
9
+ /**
10
+ * `CadreNode.addOwner` refused by name, before any write. `code` says which rule
11
+ * ({@link OwnerKeyAddRefusal}), for an app to switch on; the message is for a log.
12
+ */
13
+ export class OwnerKeyAddRefusedError extends Error {
14
+ constructor(key, code) {
15
+ super(`Cannot add owner key ${key}: ${OWNER_KEY_ADD_REFUSAL_REASON[code]}`);
16
+ this.name = 'OwnerKeyAddRefusedError';
17
+ this.code = code;
18
+ this.key = key;
19
+ }
20
+ }
21
+ const OWNER_KEY_ADD_REFUSAL_REASON = {
22
+ 'alone': 'this node has no connection to the rest of the cadre, and an owner key added now would reach no other machine; try again once connected',
23
+ };
24
+ /**
25
+ * `CadreNode.removeOwner` refused by name, before any write. `code` says which rule
26
+ * ({@link OwnerKeyRemovalRefusal}), for an app to switch on; the message is for a log.
27
+ */
28
+ export class OwnerKeyRemovalRefusedError extends Error {
29
+ constructor(key, code) {
30
+ super(`Cannot remove owner key ${key}: ${OWNER_KEY_REMOVAL_REFUSAL_REASON[code]}`);
31
+ this.name = 'OwnerKeyRemovalRefusedError';
32
+ this.code = code;
33
+ this.key = key;
34
+ }
35
+ }
36
+ const OWNER_KEY_REMOVAL_REFUSAL_REASON = {
37
+ 'not-an-owner': 'this node holds no enrolled owner key',
38
+ 'unknown': 'it is not a live owner key here',
39
+ 'last-owner': 'it is the only live owner key',
40
+ 'self': 'it is the owner key of this node, and an owner key cannot sign its own removal; ask another owner key',
41
+ 'alone': 'this node has no connection to the rest of the cadre, and an owner key re-vouched now would reach no other machine; try again once connected',
42
+ };
43
+ /** An owner key as an approval prompt names it: `"label" (key)`, or the key alone when it has no label. */
44
+ export function namedOwnerKey(key, label) {
45
+ return label === null ? key : `"${label}" (${key})`;
46
+ }
47
+ /**
48
+ * One {@link CadreOwnerKey} per live row, in the rows' order. `heldKey` is the key of this
49
+ * node's owner signer, if one is wired; `anchor` is this node's trusted-owner anchor.
50
+ */
51
+ export function describeOwnerKeys(rows, heldKey, anchor) {
52
+ return rows.map((row) => ({
53
+ key: row.key,
54
+ label: row.label,
55
+ vouchedBy: row.vouchOwner,
56
+ heldHere: row.key === heldKey,
57
+ trusted: anchor.has(row.key),
58
+ }));
59
+ }
60
+ /**
61
+ * The plan for removing owner key `key` from these rows. The refusals come first and by name: a
62
+ * node that cannot sign; a key with no live row; the only live owner key (`MinOneOwner`), ahead
63
+ * of `self` so a sole owner asking to remove its own key hears the rule no other owner could
64
+ * get past either; and this node's own key, since the schema's remove branch wants a signer
65
+ * other than the removed key. With this node enrolled, a different live key always leaves two
66
+ * owners in one read, so `last-owner` reaches only that case, and concurrent removals elsewhere
67
+ * leave the schema to decide.
68
+ *
69
+ * `dependents` are the rows the key vouched, which every reader judges against its anchor
70
+ * through `VouchOwner`: once the key is removed they stop passing the membership predicate on
71
+ * every machine unless re-vouched first. This node's own rows are not among them. Its own
72
+ * `CadrePeer` row is re-vouched unasked (`revouchesOwnRow`): left on the removed key, every other
73
+ * machine would drop the remover. Its own `OwnerKey` row is reported as `ownDependency`, since
74
+ * re-vouching it would mean signing its own removal.
75
+ *
76
+ * `grants` are the live owner grants the key issued: a redemption wants a live issuer, so they
77
+ * stop working with the removal. They are listed, not withdrawn (`removeOwner` leaves them: a
78
+ * tombstone over a grant that can no longer be redeemed would add nothing).
79
+ */
80
+ export function planOwnerKeyRemoval(input) {
81
+ const row = input.owners.find((owner) => owner.key === input.key) ?? null;
82
+ return {
83
+ ownerKey: row === null ? null : describeOwnerKeys([row], input.selfOwnerKey, input.anchor)[0],
84
+ refusal: removalRefusalFor(input, row !== null),
85
+ dependents: dependentsOf(input),
86
+ revouchesOwnRow: input.rows.some((own) => own.peerId === input.selfPeerId && own.vouchOwner === input.key),
87
+ ownDependency: input.owners.some((own) => own.key === input.selfOwnerKey && own.vouchOwner === input.key),
88
+ grants: input.grants.filter((status) => status.live && status.grant.issuerKey === input.key).map((status) => status.grant),
89
+ };
90
+ }
91
+ function removalRefusalFor(input, live) {
92
+ if (input.selfOwnerKey === null) {
93
+ return 'not-an-owner';
94
+ }
95
+ if (!live) {
96
+ return 'unknown';
97
+ }
98
+ if (input.owners.length <= 1) {
99
+ return 'last-owner';
100
+ }
101
+ if (input.key === input.selfOwnerKey) {
102
+ return 'self';
103
+ }
104
+ return null;
105
+ }
106
+ function dependentsOf(input) {
107
+ return {
108
+ owners: input.owners
109
+ .filter((owner) => owner.vouchOwner === input.key && owner.key !== input.key && owner.key !== input.selfOwnerKey)
110
+ .map((owner) => owner.key),
111
+ peers: input.rows
112
+ .filter((row) => row.vouchOwner === input.key && row.peerId !== input.selfPeerId)
113
+ .map((row) => row.peerId),
114
+ };
115
+ }
116
+ /**
117
+ * The re-vouch `CadreNode.removeOwner` makes: what the caller asked for, checked against the
118
+ * plan, plus this node's own row (`selfPeerId`, first) when `plan.revouchesOwnRow`. Every
119
+ * requested key and peer must be in `plan.dependents`, so a caller cannot re-vouch a row the
120
+ * removed key never vouched. Throws naming the offenders, before anything is written.
121
+ * Duplicates are dropped.
122
+ */
123
+ export function revouchWithinPlan(plan, revouch, selfPeerId) {
124
+ const owners = [...new Set(revouch?.owners ?? [])];
125
+ const peers = [...new Set(revouch?.peers ?? [])];
126
+ const strayOwners = owners.filter((key) => !plan.dependents.owners.includes(key));
127
+ const strayPeers = peers.filter((peerId) => !plan.dependents.peers.includes(peerId));
128
+ if (strayOwners.length > 0 || strayPeers.length > 0) {
129
+ throw new Error(`removeOwner: re-vouch names rows the removed owner key did not vouch: ${[...strayOwners, ...strayPeers].join(', ')}`);
130
+ }
131
+ return { owners, peers: plan.revouchesOwnRow && selfPeerId !== null ? [selfPeerId, ...peers] : peers };
132
+ }
133
+ //# sourceMappingURL=owner-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-keys.js","sourceRoot":"","sources":["../src/owner-keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /** What a backend that asks the user shows them. */
2
+ export interface OwnerSigningRequest {
3
+ /** The cadre the signatures are for. Every owner digest already binds it (`party_id()`); a prompting backend shows it. */
4
+ partyId: string;
5
+ /** What the user is approving, in plain words ("Remove the machine 12D3…", "Add owner key ‹label›"). */
6
+ action: string;
7
+ }
8
+ /** Signs one message (the raw bytes of an owner digest, e.g. `buildAuthorizationMessage` output); resolves to a base64url Ed25519 signature. */
9
+ export type OwnerSign = (message: Uint8Array) => Promise<string>;
10
+ /**
11
+ * An owner key the node can ask for signatures.
12
+ *
13
+ * One action, one {@link approve} call, however many rows it signs: the control schema verifies
14
+ * one signature per row, and one owner action writes several (a removal signs the delete and its
15
+ * `Revocation` tombstone; a machine removal signs many). A hardware or biometric backend prompts
16
+ * once per call, as PIV touch caching and the platform vaults' authentication-validity windows
17
+ * allow. Handing the signer every digest up front was declined: each writer reads the stamps it
18
+ * signs inside its write lock, so precomputing them would duplicate each writer's digest
19
+ * construction outside it.
20
+ */
21
+ export interface OwnerSigner {
22
+ /** base64url Ed25519 public key — the `OwnerKey.Key` this signer signs for. */
23
+ readonly publicKey: string;
24
+ /**
25
+ * Run one user-approved action. A backend that prompts does so at most once per call and may
26
+ * keep the user's presence until `body` settles. Rejects with {@link OwnerSigningDeclinedError}
27
+ * when the user declines, and with whatever `body` rejects with otherwise.
28
+ */
29
+ approve<T>(request: OwnerSigningRequest, body: (sign: OwnerSign) => Promise<T>): Promise<T>;
30
+ }
31
+ /**
32
+ * Run `body` inside the caller's open approval when it passes `sign`, else inside one new
33
+ * approval of `signer` for `request`. An owner write that is sometimes a whole action and
34
+ * sometimes one step of a larger one takes an optional `sign` and goes through this, so the
35
+ * larger action still asks once.
36
+ */
37
+ export declare function withinOwnerApproval<T>(signer: OwnerSigner, request: OwnerSigningRequest, sign: OwnerSign | undefined, body: (sign: OwnerSign) => Promise<T>): Promise<T>;
38
+ /** Thrown by a prompting backend when the user declines or the prompt times out. */
39
+ export declare class OwnerSigningDeclinedError extends Error {
40
+ readonly request: OwnerSigningRequest;
41
+ constructor(request: OwnerSigningRequest, options?: {
42
+ cause?: unknown;
43
+ });
44
+ }
45
+ /**
46
+ * An {@link OwnerSigner} over a private key held in memory: never prompts, signs whatever its
47
+ * `approve` body asks. Its signed input is the digest bytes, base64url-encoded, so its signatures
48
+ * are byte-for-byte those of any signer that signs the raw bytes with the same key (Ed25519 is
49
+ * deterministic).
50
+ *
51
+ * @param privateKeyB64 - The owner key's 32-byte Ed25519 seed, base64url.
52
+ * @throws If `privateKeyB64` is not a 32-byte seed in base64url.
53
+ */
54
+ export declare function softwareOwnerSigner(privateKeyB64: string): OwnerSigner;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The owner signer: the one interface a node's owner signatures go through
3
+ * (`docs/architecture.md` → Owner Keys → The owner signer).
4
+ *
5
+ * cadre-core needs owner signatures, never an owner private key, so a backend that keeps the
6
+ * key where the node cannot read it (a hardware key, a vault behind biometrics) fits the same
7
+ * seam as {@link softwareOwnerSigner}.
8
+ *
9
+ * Imports only `@optimystic/quereus-plugin-crypto` and `uint8arrays`, so it loads on React
10
+ * Native and in the browser.
11
+ */
12
+ import { toString as uint8ArrayToString } from 'uint8arrays';
13
+ import { sign } from '@optimystic/quereus-plugin-crypto';
14
+ import { ed25519PublicKeyFromPrivate, requireEd25519PrivateKeyB64 } from './ed25519-key.js';
15
+ /**
16
+ * Run `body` inside the caller's open approval when it passes `sign`, else inside one new
17
+ * approval of `signer` for `request`. An owner write that is sometimes a whole action and
18
+ * sometimes one step of a larger one takes an optional `sign` and goes through this, so the
19
+ * larger action still asks once.
20
+ */
21
+ export async function withinOwnerApproval(signer, request, sign, body) {
22
+ return sign ? await body(sign) : await signer.approve(request, body);
23
+ }
24
+ /** Thrown by a prompting backend when the user declines or the prompt times out. */
25
+ export class OwnerSigningDeclinedError extends Error {
26
+ constructor(request, options) {
27
+ super(`Owner approval was declined or timed out: ${request.action}`, options);
28
+ this.name = 'OwnerSigningDeclinedError';
29
+ this.request = request;
30
+ }
31
+ }
32
+ /**
33
+ * An {@link OwnerSigner} over a private key held in memory: never prompts, signs whatever its
34
+ * `approve` body asks. Its signed input is the digest bytes, base64url-encoded, so its signatures
35
+ * are byte-for-byte those of any signer that signs the raw bytes with the same key (Ed25519 is
36
+ * deterministic).
37
+ *
38
+ * @param privateKeyB64 - The owner key's 32-byte Ed25519 seed, base64url.
39
+ * @throws If `privateKeyB64` is not a 32-byte seed in base64url.
40
+ */
41
+ export function softwareOwnerSigner(privateKeyB64) {
42
+ const privateKey = requireEd25519PrivateKeyB64(privateKeyB64, 'owner private key');
43
+ const signMessage = async (message) => sign(uint8ArrayToString(message, 'base64url'), privateKey, 'ed25519', 'base64url', 'base64url', 'base64url');
44
+ return {
45
+ publicKey: ed25519PublicKeyFromPrivate(privateKey),
46
+ async approve(_request, body) {
47
+ return await body(signMessage);
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=owner-signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-signer.js","sourceRoot":"","sources":["../src/owner-signer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,mCAAmC,CAAC;AACzD,OAAO,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAmC5F;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,MAAmB,EACnB,OAA4B,EAC5B,IAA2B,EAC3B,IAAqC;IAErC,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACtE,CAAC;AAED,oFAAoF;AACpF,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAGnD,YAAY,OAA4B,EAAE,OAA6B;QACtE,KAAK,CAAC,6CAA6C,OAAO,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,aAAqB;IACxD,MAAM,UAAU,GAAG,2BAA2B,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;IACnF,MAAM,WAAW,GAAc,KAAK,EAAE,OAAO,EAAE,EAAE,CAChD,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAW,CAAC;IACxH,OAAO;QACN,SAAS,EAAE,2BAA2B,CAAC,UAAU,CAAC;QAClD,KAAK,CAAC,OAAO,CAAI,QAA6B,EAAE,IAAqC;YACpF,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;QAChC,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -4,7 +4,7 @@
4
4
  * — Optimystic's cluster client, repo client, FRET ping/announce, all funnelling
5
5
  * into `libp2p.dialProtocol(peerId, …)` — has an address to use for a sibling
6
6
  * whose connection has dropped, instead of failing with `NoValidAddressesError`
7
- * until the next reconcile pass happens to re-dial it.
7
+ * until the reconcile pass the drop starts re-dials it.
8
8
  *
9
9
  * Shared by the control-cohort reconcile pass and the strand one (both in
10
10
  * `CadreNode`): each resolves a peer's addresses its own way and then needs
@@ -90,3 +90,12 @@ export declare function mergePeerAddrs(host: PeerAddrBookHost, peerId: PeerId |
90
90
  * order is preserved, both between groups and inside one.
91
91
  */
92
92
  export declare function groupAddrsByPeerId(addrs: string[]): Map<string, Multiaddr[]>;
93
+ /**
94
+ * The peerStore strips a trailing `/p2p/<peerId>` from an address it stores when
95
+ * that id is the address's FIRST `/p2p/` component (`dedupe-addresses.js`), so a
96
+ * plain address round-trips without its suffix while a relayed one — whose first
97
+ * `/p2p/` names the relay — keeps it. Comparing and de-duplicating on this
98
+ * suffix-stripped form matches either shape. `CadreNode.claimNode` compares a QR
99
+ * code's addresses with a connection's remote address on it for the same reason.
100
+ */
101
+ export declare function addrKey(addr: string, peerId: PeerId): string;
@@ -4,7 +4,7 @@
4
4
  * — Optimystic's cluster client, repo client, FRET ping/announce, all funnelling
5
5
  * into `libp2p.dialProtocol(peerId, …)` — has an address to use for a sibling
6
6
  * whose connection has dropped, instead of failing with `NoValidAddressesError`
7
- * until the next reconcile pass happens to re-dial it.
7
+ * until the reconcile pass the drop starts re-dials it.
8
8
  *
9
9
  * Shared by the control-cohort reconcile pass and the strand one (both in
10
10
  * `CadreNode`): each resolves a peer's addresses its own way and then needs
@@ -169,9 +169,10 @@ function lastAddressedPeerId(parsed) {
169
169
  * that id is the address's FIRST `/p2p/` component (`dedupe-addresses.js`), so a
170
170
  * plain address round-trips without its suffix while a relayed one — whose first
171
171
  * `/p2p/` names the relay — keeps it. Comparing and de-duplicating on this
172
- * suffix-stripped form matches either shape.
172
+ * suffix-stripped form matches either shape. `CadreNode.claimNode` compares a QR
173
+ * code's addresses with a connection's remote address on it for the same reason.
173
174
  */
174
- function addrKey(addr, peerId) {
175
+ export function addrKey(addr, peerId) {
175
176
  const suffix = `/p2p/${peerId.toString()}`;
176
177
  return addr.endsWith(suffix) ? addr.slice(0, -suffix.length) : addr;
177
178
  }
@@ -1 +1 @@
1
- {"version":3,"file":"peer-addr-book.js","sourceRoot":"","sources":["../src/peer-addr-book.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"peer-addr-book.js","sourceRoot":"","sources":["../src/peer-addr-book.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { CadreInviteSignedFields, RevocableTable } from './control-authorization.js';
2
- import type { CadreInviteRow, CadreInviteUsageRow, CadrePeerVoucherFields, OwnerKeyRow, RevocationRow } from './types.js';
1
+ import type { CadreInviteSignedFields, OwnerGrantSignedFields, RevocableTable } from './control-authorization.js';
2
+ import type { CadreInviteRow, CadreInviteUsageRow, CadrePeerVoucherFields, OwnerGrantRow, OwnerGrantUsageRow, OwnerKeyRow, RevocationRow } from './types.js';
3
3
  /**
4
4
  * Canonical digest an owner signs to vouch a peer's ENROLLMENT — the offline
5
5
  * credential `cadre enroll register` verifies. No table checks this digest, so it
@@ -117,16 +117,18 @@ export declare function verifyRevocationSigner(partyId: string, row: RevocationR
117
117
  /**
118
118
  * Canonical digest an owner signs to seat a further `OwnerKey` row — the signed-add branch
119
119
  * of `OwnerKey.Authorized`, which stores the pair as `VouchOwner` / `VouchSig`. SQL mirror:
120
- * `digest('CadreControl.OwnerKey', 'add', party_id(), new.Key, new.StampId)`. The removal
121
- * digest needs no builder here: it is the generic guarded `'remove'` digest over (Key, StampId).
120
+ * `digest('CadreControl.OwnerKey', 'add', party_id(), new.Key, coalesce(new.Label, ''), new.StampId)`.
121
+ * The removal digest needs no builder here: it is the generic guarded `'remove'` digest over
122
+ * (Key, StampId).
122
123
  */
123
- export declare function ownerKeyAddDigest(partyId: string, key: string, stampId: string): string;
124
+ export declare function ownerKeyAddDigest(partyId: string, key: string, label: string | null, stampId: string): string;
124
125
  /**
125
126
  * Does an owner-signed `OwnerKey` row's stored voucher verify — `vouchSig` by `vouchOwner`
126
- * over {@link ownerKeyAddDigest} for (`partyId`, `key`, `stampId`)? Whether `vouchOwner` is
127
- * anchored is the caller's question, as for {@link verifyCadrePeerVoucher}. Never throws.
127
+ * over {@link ownerKeyAddDigest} for (`partyId`, `key`, `label`, `stampId`)? Whether
128
+ * `vouchOwner` is anchored is the caller's question, as for {@link verifyCadrePeerVoucher}.
129
+ * Never throws.
128
130
  */
129
- export declare function verifyOwnerKeyVoucher(partyId: string, key: string, stampId: string, vouchOwner: string, vouchSig: string): boolean;
131
+ export declare function verifyOwnerKeyVoucher(partyId: string, key: string, label: string | null, stampId: string, vouchOwner: string, vouchSig: string): boolean;
130
132
  /**
131
133
  * Verify that `signature` is a valid owner ed25519 signature over `peerId`'s
132
134
  * authorization digest, using `ownerPublicKey` (base64url).
@@ -236,8 +238,20 @@ export declare function verifyCadreInviteRedemption(partyId: string, fields: {
236
238
  * Is an invitation-admitted `CadrePeer` row (`vouchSig` null, `vouchUsage` set) a
237
239
  * member this node should trust? The read-side mirror of the consent branch of
238
240
  * `CadrePeer.AuthorizedInsert`, re-checked against THIS node's anchor because the
239
- * replicated `OwnerKey` table can be polluted. The usage must name this peer id and this
240
- * exact row incarnation (`peerStampId`); every other link is {@link verifyAdmissionChain}.
241
+ * replicated `OwnerKey` table can be polluted. The chain is
242
+ *
243
+ * row --vouchUsage--> usage --inviteKey--> invitation --issuerKey--> anchored owner
244
+ *
245
+ * and every link is verified: the issuer is anchored (`isAnchored`) and is the row's
246
+ * `vouchOwner`; the usage is the row's `vouchUsage`, names this peer id and this exact row
247
+ * incarnation (`peerStampId`), and names this invitation; a targeted invitation names the
248
+ * redeeming device; the stored `peerKey` really is the key behind the usage's `peerId` (the
249
+ * schema cannot unwrap a multihash, so a writer could assert any pair); the invitation's
250
+ * stored `'add'` signature verifies over the row rebuilt from its columns; the holder's
251
+ * `'redeem'` signature verifies with the invitation key and the device's `'consent'`
252
+ * signature with its own key. All three signatures are judged for `partyId`. A machine
253
+ * invitation admits a machine and nothing else, so no `OwnerKey` row is ever verified
254
+ * through this chain; a grant-seated owner row is {@link verifyOwnerGrantAdmission}'s.
241
255
  *
242
256
  * Expiry, use count and withdrawal are deliberately NOT re-checked: they were conditions
243
257
  * at redemption (`CadreInviteUsage.Authorized`), and membership persists until an owner
@@ -249,12 +263,63 @@ export declare function verifyCadreInviteRedemption(partyId: string, fields: {
249
263
  */
250
264
  export declare function verifyInvitationAdmission(partyId: string, row: CadrePeerVoucherFields, usage: CadreInviteUsageRow, invite: CadreInviteRow, isAnchored: (ownerKey: string) => boolean): boolean;
251
265
  /**
252
- * Is an invitation-admitted `OwnerKey` row (`vouchSig` null, `vouchUsage` set) an owner
253
- * this node should derive into its anchor? The read-side mirror of the consent branch of
254
- * `OwnerKey.Authorized` (`owner-anchor-sync.ts` → `deriveOwnerAnchor`): the invitation
255
- * must grant ownership, and the usage must name this key (`peerKey`) and this exact row
256
- * incarnation (`ownerStampId`); every other link is {@link verifyAdmissionChain}. Same
257
- * never-throws contract and the same deliberate omissions as
258
- * {@link verifyInvitationAdmission}.
266
+ * Canonical digest an owner signs to seat an `OwnerGrant` row — the read-side mirror of
267
+ * `ownerGrantAddMessage` in control-database.ts, base64url instead of raw bytes. The whole
268
+ * row is bound, the label included, through the one field builder both sides share
269
+ * (`ownerGrantRowFields`). SQL mirror: `OwnerGrant.AuthorizedInsert`.
270
+ */
271
+ export declare function ownerGrantAddDigest(partyId: string, row: OwnerGrantSignedFields): string;
272
+ /**
273
+ * Canonical digest the HOLDER of an `OwnerGrant`'s private key signs to redeem it once:
274
+ * proof of possession, verified against the grant key itself
275
+ * (`OwnerGrantUsage.GrantPossessed`). Binds the redemption's nonce and the key being seated,
276
+ * so one redemption cannot be re-presented for another key or another use. Mirror of
277
+ * `ownerGrantRedeemMessage` in control-database.ts.
278
+ */
279
+ export declare function ownerGrantRedeemDigest(partyId: string, grantKey: string, usageStampId: string, seatedKey: string): string;
280
+ /**
281
+ * Canonical digest the key being SEATED signs to prove it is held by the redeemer
282
+ * (`OwnerGrantUsage.OwnerConsented`), over the same fields as {@link ownerGrantRedeemDigest}
283
+ * under a distinct action tag, so the holder's and the key's signatures are never
284
+ * interchangeable. Mirror of `ownerGrantConsentMessage` in control-database.ts.
285
+ */
286
+ export declare function ownerGrantConsentDigest(partyId: string, grantKey: string, usageStampId: string, seatedKey: string): string;
287
+ /**
288
+ * Does an `OwnerGrant` row carry a valid `'add'` signature by its own `issuerKey`, for
289
+ * `partyId`? The grant twin of {@link verifyCadreInviteRow}, with the same contract: whether
290
+ * that issuer IS an owner is the caller's question, and a malformed row verifies as `false`.
291
+ */
292
+ export declare function verifyOwnerGrantRow(partyId: string, grant: OwnerGrantRow): boolean;
293
+ /**
294
+ * The two signatures an owner-grant redemption carries, checked before any database work:
295
+ * the holder's `'redeem'` signature with the grant key and the seated key's `'consent'`
296
+ * signature with itself, both over (`grantKey`, `usageStampId`, `seatedKey`). The grant twin
297
+ * of {@link verifyCadreInviteRedemption}, with the same contract: the schema
298
+ * (`OwnerGrantUsage.GrantPossessed` / `OwnerConsented`) stays the authority, this turns a bad
299
+ * signature into a clean refusal instead of a constraint failure at commit. Never throws.
300
+ */
301
+ export declare function verifyOwnerGrantRedemption(partyId: string, fields: {
302
+ grantKey: string;
303
+ usageStampId: string;
304
+ seatedKey: string;
305
+ }, grantSig: string, ownerSig: string): boolean;
306
+ /**
307
+ * Is a grant-seated `OwnerKey` row (`vouchSig` null, `vouchUsage` naming an `OwnerGrantUsage`
308
+ * row) an owner this node should derive into its anchor? The read-side mirror of the grant
309
+ * branch of `OwnerKey.Authorized` (`owner-anchor-sync.ts` → `deriveOwnerAnchor`). The chain is
310
+ *
311
+ * row --vouchUsage--> usage --grantKey--> grant --issuerKey--> anchored owner
312
+ *
313
+ * and every link is verified: the issuer is anchored and is the row's `vouchOwner`; the usage
314
+ * is the row's `vouchUsage` and names this key and this exact row incarnation
315
+ * (`seatedStampId`); the usage names this grant; the row carries the grant's label; the
316
+ * grant's stored `'add'` signature verifies over the row rebuilt from its columns; the
317
+ * holder's `'redeem'` signature verifies with the grant key and the seated key's `'consent'`
318
+ * signature with itself. All three signatures are judged for `partyId`.
319
+ *
320
+ * Expiry, use count and withdrawal are deliberately NOT re-checked, as
321
+ * {@link verifyInvitationAdmission} omits them: they were conditions at redemption
322
+ * (`OwnerGrantUsage.Authorized`), and ownership persists until an owner removes the row.
323
+ * Same never-throws contract as the siblings.
259
324
  */
260
- export declare function verifyInvitationOwnerAdmission(partyId: string, row: OwnerKeyRow, usage: CadreInviteUsageRow, invite: CadreInviteRow, isAnchored: (ownerKey: string) => boolean): boolean;
325
+ export declare function verifyOwnerGrantAdmission(partyId: string, row: OwnerKeyRow, usage: OwnerGrantUsageRow, grant: OwnerGrantRow, isAnchored: (ownerKey: string) => boolean): boolean;