@serfab/cadre-host 1.13.0 → 1.15.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 (352) hide show
  1. package/README.md +347 -423
  2. package/dist/bin/host.d.ts +6 -3
  3. package/dist/bin/host.js +332 -524
  4. package/dist/bin/host.js.map +1 -1
  5. package/dist/bin/join-output.d.ts +56 -0
  6. package/dist/bin/join-output.js +92 -0
  7. package/dist/bin/join-output.js.map +1 -0
  8. package/dist/bin/nat-output.d.ts +54 -0
  9. package/dist/bin/nat-output.js +138 -0
  10. package/dist/bin/nat-output.js.map +1 -0
  11. package/dist/bin/ui-access.d.ts +22 -0
  12. package/dist/bin/ui-access.js +44 -0
  13. package/dist/bin/ui-access.js.map +1 -0
  14. package/dist/hosted/claim-details.d.ts +66 -0
  15. package/dist/hosted/claim-details.js +60 -0
  16. package/dist/hosted/claim-details.js.map +1 -0
  17. package/dist/hosted/hosted-node-service.d.ts +325 -0
  18. package/dist/hosted/hosted-node-service.js +678 -0
  19. package/dist/hosted/hosted-node-service.js.map +1 -0
  20. package/dist/hosted/hosted-node-store.d.ts +40 -0
  21. package/dist/hosted/hosted-node-store.js +126 -0
  22. package/dist/hosted/hosted-node-store.js.map +1 -0
  23. package/dist/{donation/donation-supervisor.d.ts → hosted/hosted-node-supervisor.d.ts} +70 -53
  24. package/dist/hosted/hosted-node-supervisor.js +396 -0
  25. package/dist/hosted/hosted-node-supervisor.js.map +1 -0
  26. package/dist/hosted/hosted-node-watcher.d.ts +95 -0
  27. package/dist/hosted/hosted-node-watcher.js +260 -0
  28. package/dist/hosted/hosted-node-watcher.js.map +1 -0
  29. package/dist/hosted/index.d.ts +16 -0
  30. package/dist/hosted/index.js +13 -0
  31. package/dist/hosted/index.js.map +1 -0
  32. package/dist/hosted/node-status.d.ts +51 -0
  33. package/dist/hosted/node-status.js +77 -0
  34. package/dist/hosted/node-status.js.map +1 -0
  35. package/dist/hosted/types.d.ts +141 -0
  36. package/dist/hosted/types.js +22 -0
  37. package/dist/hosted/types.js.map +1 -0
  38. package/dist/index.d.ts +12 -24
  39. package/dist/index.js +9 -19
  40. package/dist/index.js.map +1 -1
  41. package/dist/installer/config.d.ts +27 -34
  42. package/dist/installer/config.js +46 -15
  43. package/dist/installer/config.js.map +1 -1
  44. package/dist/installer/index.d.ts +9 -19
  45. package/dist/installer/index.js +21 -85
  46. package/dist/installer/index.js.map +1 -1
  47. package/dist/installer/paths.d.ts +0 -2
  48. package/dist/installer/paths.js +0 -4
  49. package/dist/installer/paths.js.map +1 -1
  50. package/dist/installer/wizard.d.ts +12 -9
  51. package/dist/installer/wizard.js +15 -14
  52. package/dist/installer/wizard.js.map +1 -1
  53. package/dist/nat/address-resolver.d.ts +18 -17
  54. package/dist/nat/address-resolver.js +79 -25
  55. package/dist/nat/address-resolver.js.map +1 -1
  56. package/dist/nat/address-watch.d.ts +37 -0
  57. package/dist/nat/address-watch.js +84 -0
  58. package/dist/nat/address-watch.js.map +1 -0
  59. package/dist/nat/ddns/duckdns.d.ts +2 -1
  60. package/dist/nat/ddns/duckdns.js +5 -1
  61. package/dist/nat/ddns/duckdns.js.map +1 -1
  62. package/dist/nat/ddns/index.d.ts +6 -0
  63. package/dist/nat/ddns/index.js.map +1 -1
  64. package/dist/nat/index.d.ts +13 -9
  65. package/dist/nat/index.js +7 -5
  66. package/dist/nat/index.js.map +1 -1
  67. package/dist/nat/nat-service.d.ts +220 -77
  68. package/dist/nat/nat-service.js +653 -239
  69. package/dist/nat/nat-service.js.map +1 -1
  70. package/dist/nat/nat-store.d.ts +12 -5
  71. package/dist/nat/nat-store.js +124 -29
  72. package/dist/nat/nat-store.js.map +1 -1
  73. package/dist/nat/network-mode.d.ts +19 -0
  74. package/dist/nat/network-mode.js +32 -0
  75. package/dist/nat/network-mode.js.map +1 -0
  76. package/dist/nat/port-mapper.d.ts +83 -79
  77. package/dist/nat/port-mapper.js +148 -189
  78. package/dist/nat/port-mapper.js.map +1 -1
  79. package/dist/nat/reachability.d.ts +32 -15
  80. package/dist/nat/reachability.js +110 -22
  81. package/dist/nat/reachability.js.map +1 -1
  82. package/dist/nat/types.d.ts +98 -27
  83. package/dist/nat/types.js +8 -5
  84. package/dist/nat/types.js.map +1 -1
  85. package/dist/orchestrator/host-process-orchestrator.d.ts +32 -74
  86. package/dist/orchestrator/host-process-orchestrator.js +84 -233
  87. package/dist/orchestrator/host-process-orchestrator.js.map +1 -1
  88. package/dist/{installer/identity.d.ts → orchestrator/identity-file.d.ts} +5 -5
  89. package/dist/{installer/identity.js → orchestrator/identity-file.js} +6 -6
  90. package/dist/orchestrator/identity-file.js.map +1 -0
  91. package/dist/orchestrator/index.d.ts +2 -3
  92. package/dist/orchestrator/index.js +1 -1
  93. package/dist/orchestrator/index.js.map +1 -1
  94. package/dist/orchestrator/node-identity.d.ts +6 -6
  95. package/dist/orchestrator/node-identity.js +7 -7
  96. package/dist/orchestrator/node-identity.js.map +1 -1
  97. package/dist/orchestrator/port-allocator.d.ts +5 -6
  98. package/dist/orchestrator/port-allocator.js +9 -11
  99. package/dist/orchestrator/port-allocator.js.map +1 -1
  100. package/dist/orchestrator/state-store.d.ts +3 -5
  101. package/dist/orchestrator/state-store.js +2 -10
  102. package/dist/orchestrator/state-store.js.map +1 -1
  103. package/dist/orchestrator/types.d.ts +33 -22
  104. package/dist/orchestrator/types.js.map +1 -1
  105. package/dist/package-version.d.ts +1 -0
  106. package/dist/package-version.js +4 -0
  107. package/dist/package-version.js.map +1 -0
  108. package/dist/server/error-handler.d.ts +5 -25
  109. package/dist/server/error-handler.js +11 -74
  110. package/dist/server/error-handler.js.map +1 -1
  111. package/dist/server/events/types.d.ts +7 -11
  112. package/dist/server/events/types.js +2 -1
  113. package/dist/server/events/types.js.map +1 -1
  114. package/dist/server/index.d.ts +11 -37
  115. package/dist/server/index.js +30 -48
  116. package/dist/server/index.js.map +1 -1
  117. package/dist/server/routes/hosted-nodes.d.ts +28 -0
  118. package/dist/server/routes/hosted-nodes.js +68 -0
  119. package/dist/server/routes/hosted-nodes.js.map +1 -0
  120. package/dist/server/routes/nat.d.ts +4 -1
  121. package/dist/server/routes/nat.js +13 -2
  122. package/dist/server/routes/nat.js.map +1 -1
  123. package/dist/server/routes/nodes.d.ts +6 -20
  124. package/dist/server/routes/nodes.js +7 -86
  125. package/dist/server/routes/nodes.js.map +1 -1
  126. package/dist/server/routes/settings.d.ts +3 -7
  127. package/dist/server/routes/settings.js +18 -8
  128. package/dist/server/routes/settings.js.map +1 -1
  129. package/dist/server/routes/status.d.ts +2 -25
  130. package/dist/server/routes/status.js +3 -43
  131. package/dist/server/routes/status.js.map +1 -1
  132. package/dist/server/server.js +8 -8
  133. package/dist/server/settings-store.d.ts +2 -2
  134. package/dist/server/settings-store.js +2 -2
  135. package/dist/server/static.js +1 -2
  136. package/dist/server/static.js.map +1 -1
  137. package/dist/ui/assets/index-BHd8CWZA.css +1 -0
  138. package/dist/ui/assets/index-Ccr2GjPT.js +23 -0
  139. package/dist/ui/assets/index-Ccr2GjPT.js.map +1 -0
  140. package/dist/ui/index.html +2 -2
  141. package/dist/update/index.d.ts +2 -2
  142. package/dist/update/index.js +2 -2
  143. package/dist/update/store.d.ts +1 -1
  144. package/dist/update/store.js +1 -1
  145. package/dist/update/types.d.ts +1 -1
  146. package/dist/update/types.js +1 -1
  147. package/package.json +5 -7
  148. package/src/__tests__/cli-nat.smoke.test.ts +219 -212
  149. package/src/__tests__/cli.smoke.test.ts +2 -2
  150. package/src/__tests__/global-setup.ts +2 -3
  151. package/src/__tests__/orchestrator-claim-secret.test.ts +111 -0
  152. package/src/__tests__/orchestrator-env-scrub.test.ts +160 -163
  153. package/src/__tests__/orchestrator-handle-contract.ts +134 -134
  154. package/src/__tests__/orchestrator-node-identity.test.ts +177 -203
  155. package/src/__tests__/orchestrator-ports.test.ts +124 -143
  156. package/src/__tests__/orchestrator-push.test.ts +138 -146
  157. package/src/__tests__/orchestrator.test.ts +1017 -1063
  158. package/src/__tests__/ui-access.test.ts +30 -0
  159. package/src/bin/host.ts +397 -572
  160. package/src/bin/join-output.ts +120 -0
  161. package/src/bin/nat-output.ts +188 -0
  162. package/src/bin/ui-access.ts +50 -0
  163. package/src/{donation → hosted}/__tests__/fake-orchestrator.test.ts +172 -173
  164. package/src/{donation → hosted}/__tests__/fake-orchestrator.ts +43 -23
  165. package/src/hosted/__tests__/hosted-node-service.test.ts +708 -0
  166. package/src/hosted/__tests__/hosted-node-supervisor.test.ts +475 -0
  167. package/src/hosted/__tests__/test-invitation.ts +33 -0
  168. package/src/hosted/claim-details.ts +103 -0
  169. package/src/hosted/hosted-node-service.ts +814 -0
  170. package/src/hosted/hosted-node-store.ts +144 -0
  171. package/src/hosted/hosted-node-supervisor.ts +439 -0
  172. package/src/hosted/hosted-node-watcher.ts +288 -0
  173. package/src/hosted/index.ts +53 -0
  174. package/src/hosted/node-status.ts +97 -0
  175. package/src/hosted/types.ts +160 -0
  176. package/src/index.ts +72 -91
  177. package/src/installer/__tests__/config.test.ts +15 -40
  178. package/src/installer/__tests__/installer.smoke.test.ts +184 -263
  179. package/src/installer/__tests__/wizard.test.ts +25 -13
  180. package/src/installer/config.ts +201 -175
  181. package/src/installer/index.ts +252 -327
  182. package/src/installer/paths.ts +104 -109
  183. package/src/installer/wizard.ts +24 -26
  184. package/src/nat/__tests__/address-resolver.test.ts +107 -82
  185. package/src/nat/__tests__/nat-service.test.ts +608 -515
  186. package/src/nat/__tests__/nat-store.test.ts +49 -12
  187. package/src/nat/__tests__/network-mode.test.ts +38 -0
  188. package/src/nat/__tests__/port-mapper.test.ts +30 -191
  189. package/src/nat/__tests__/reachability.test.ts +96 -13
  190. package/src/nat/address-resolver.ts +94 -52
  191. package/src/nat/address-watch.ts +92 -0
  192. package/src/nat/ddns/duckdns.ts +5 -1
  193. package/src/nat/ddns/index.ts +6 -0
  194. package/src/nat/index.ts +33 -13
  195. package/src/nat/nat-service.ts +942 -501
  196. package/src/nat/nat-store.ts +126 -31
  197. package/src/nat/network-mode.ts +36 -0
  198. package/src/nat/port-mapper.ts +241 -329
  199. package/src/nat/reachability.ts +155 -34
  200. package/src/nat/types.ts +110 -37
  201. package/src/{installer/__tests__/identity.test.ts → orchestrator/__tests__/identity-file.test.ts} +34 -34
  202. package/src/orchestrator/__tests__/node-identity.test.ts +62 -62
  203. package/src/orchestrator/host-process-orchestrator.ts +1089 -1260
  204. package/src/{installer/identity.ts → orchestrator/identity-file.ts} +56 -56
  205. package/src/orchestrator/index.ts +9 -10
  206. package/src/orchestrator/node-identity.ts +41 -41
  207. package/src/orchestrator/port-allocator.ts +71 -73
  208. package/src/orchestrator/state-store.ts +76 -90
  209. package/src/orchestrator/types.ts +34 -23
  210. package/src/package-version.ts +4 -0
  211. package/src/server/__tests__/bus.test.ts +38 -38
  212. package/src/server/__tests__/error-handler.test.ts +81 -118
  213. package/src/server/__tests__/fakes.ts +15 -18
  214. package/src/server/__tests__/hosted-nodes-route.test.ts +161 -0
  215. package/src/server/__tests__/nodes-route.test.ts +114 -283
  216. package/src/server/__tests__/publishers.test.ts +193 -180
  217. package/src/server/__tests__/server.smoke.test.ts +134 -223
  218. package/src/server/__tests__/settings-route.test.ts +210 -195
  219. package/src/server/__tests__/sse-route.test.ts +119 -119
  220. package/src/server/__tests__/status-route.test.ts +82 -121
  221. package/src/server/error-handler.ts +112 -178
  222. package/src/server/events/types.ts +20 -24
  223. package/src/server/index.ts +223 -267
  224. package/src/server/routes/hosted-nodes.ts +83 -0
  225. package/src/server/routes/nat.ts +75 -63
  226. package/src/server/routes/nodes.ts +96 -188
  227. package/src/server/routes/settings.ts +20 -15
  228. package/src/server/routes/status.ts +5 -67
  229. package/src/server/server.ts +8 -8
  230. package/src/server/settings-store.ts +2 -2
  231. package/src/server/static.ts +1 -2
  232. package/src/update/index.ts +2 -2
  233. package/src/update/store.ts +1 -1
  234. package/src/update/types.ts +1 -1
  235. package/dist/auth/duration.d.ts +0 -1
  236. package/dist/auth/duration.js +0 -32
  237. package/dist/auth/duration.js.map +0 -1
  238. package/dist/auth/index.d.ts +0 -11
  239. package/dist/auth/index.js +0 -9
  240. package/dist/auth/index.js.map +0 -1
  241. package/dist/auth/self-label.d.ts +0 -36
  242. package/dist/auth/self-label.js +0 -57
  243. package/dist/auth/self-label.js.map +0 -1
  244. package/dist/auth/trust-circle-store.d.ts +0 -26
  245. package/dist/auth/trust-circle-store.js +0 -129
  246. package/dist/auth/trust-circle-store.js.map +0 -1
  247. package/dist/auth/trust-circle.d.ts +0 -156
  248. package/dist/auth/trust-circle.js +0 -307
  249. package/dist/auth/trust-circle.js.map +0 -1
  250. package/dist/auth/types.d.ts +0 -84
  251. package/dist/auth/types.js +0 -24
  252. package/dist/auth/types.js.map +0 -1
  253. package/dist/donation/donation-service.d.ts +0 -389
  254. package/dist/donation/donation-service.js +0 -828
  255. package/dist/donation/donation-service.js.map +0 -1
  256. package/dist/donation/donation-store.d.ts +0 -51
  257. package/dist/donation/donation-store.js +0 -152
  258. package/dist/donation/donation-store.js.map +0 -1
  259. package/dist/donation/donation-supervisor.js +0 -364
  260. package/dist/donation/donation-supervisor.js.map +0 -1
  261. package/dist/donation/grant-service.d.ts +0 -80
  262. package/dist/donation/grant-service.js +0 -210
  263. package/dist/donation/grant-service.js.map +0 -1
  264. package/dist/donation/grant-store.d.ts +0 -38
  265. package/dist/donation/grant-store.js +0 -135
  266. package/dist/donation/grant-store.js.map +0 -1
  267. package/dist/donation/index.d.ts +0 -20
  268. package/dist/donation/index.js +0 -17
  269. package/dist/donation/index.js.map +0 -1
  270. package/dist/donation/types.d.ts +0 -224
  271. package/dist/donation/types.js +0 -40
  272. package/dist/donation/types.js.map +0 -1
  273. package/dist/installer/identity.js.map +0 -1
  274. package/dist/owner/index.d.ts +0 -11
  275. package/dist/owner/index.js +0 -11
  276. package/dist/owner/index.js.map +0 -1
  277. package/dist/owner/owner-node-client.d.ts +0 -110
  278. package/dist/owner/owner-node-client.js +0 -184
  279. package/dist/owner/owner-node-client.js.map +0 -1
  280. package/dist/server/routes/bootstrap-node-validation.d.ts +0 -115
  281. package/dist/server/routes/bootstrap-node-validation.js +0 -197
  282. package/dist/server/routes/bootstrap-node-validation.js.map +0 -1
  283. package/dist/server/routes/grants-admin.d.ts +0 -29
  284. package/dist/server/routes/grants-admin.js +0 -58
  285. package/dist/server/routes/grants-admin.js.map +0 -1
  286. package/dist/server/routes/grants.d.ts +0 -28
  287. package/dist/server/routes/grants.js +0 -165
  288. package/dist/server/routes/grants.js.map +0 -1
  289. package/dist/server/routes/provision-request-validation.d.ts +0 -45
  290. package/dist/server/routes/provision-request-validation.js +0 -97
  291. package/dist/server/routes/provision-request-validation.js.map +0 -1
  292. package/dist/server/routes/strands.d.ts +0 -20
  293. package/dist/server/routes/strands.js +0 -38
  294. package/dist/server/routes/strands.js.map +0 -1
  295. package/dist/server/routes/trust-circle.d.ts +0 -17
  296. package/dist/server/routes/trust-circle.js +0 -35
  297. package/dist/server/routes/trust-circle.js.map +0 -1
  298. package/dist/strands/index.d.ts +0 -7
  299. package/dist/strands/index.js +0 -6
  300. package/dist/strands/index.js.map +0 -1
  301. package/dist/strands/strand-service.d.ts +0 -50
  302. package/dist/strands/strand-service.js +0 -103
  303. package/dist/strands/strand-service.js.map +0 -1
  304. package/dist/strands/types.d.ts +0 -93
  305. package/dist/strands/types.js +0 -23
  306. package/dist/strands/types.js.map +0 -1
  307. package/dist/ui/assets/index-C6nELNfC.js +0 -23
  308. package/dist/ui/assets/index-C6nELNfC.js.map +0 -1
  309. package/dist/ui/assets/index-TtIYSeZO.css +0 -1
  310. package/src/__tests__/cli-invite.smoke.test.ts +0 -192
  311. package/src/__tests__/host-owner.smoke.test.ts +0 -123
  312. package/src/__tests__/orchestrator-owner.test.ts +0 -234
  313. package/src/__tests__/orchestrator-pin-keys.test.ts +0 -152
  314. package/src/auth/__tests__/duration.test.ts +0 -28
  315. package/src/auth/__tests__/self-label.test.ts +0 -85
  316. package/src/auth/__tests__/trust-circle-integration.test.ts +0 -152
  317. package/src/auth/__tests__/trust-circle-store.test.ts +0 -115
  318. package/src/auth/__tests__/trust-circle.test.ts +0 -445
  319. package/src/auth/duration.ts +0 -33
  320. package/src/auth/index.ts +0 -21
  321. package/src/auth/self-label.ts +0 -74
  322. package/src/auth/trust-circle-store.ts +0 -155
  323. package/src/auth/trust-circle.ts +0 -395
  324. package/src/auth/types.ts +0 -99
  325. package/src/donation/__tests__/donation-service.test.ts +0 -1193
  326. package/src/donation/__tests__/donation-supervisor.test.ts +0 -548
  327. package/src/donation/__tests__/grant-service.test.ts +0 -213
  328. package/src/donation/__tests__/grant-store.test.ts +0 -113
  329. package/src/donation/donation-service.ts +0 -1033
  330. package/src/donation/donation-store.ts +0 -176
  331. package/src/donation/donation-supervisor.ts +0 -411
  332. package/src/donation/grant-service.ts +0 -252
  333. package/src/donation/grant-store.ts +0 -152
  334. package/src/donation/index.ts +0 -65
  335. package/src/donation/types.ts +0 -260
  336. package/src/owner/__tests__/owner-node-client.test.ts +0 -194
  337. package/src/owner/index.ts +0 -12
  338. package/src/owner/owner-node-client.ts +0 -259
  339. package/src/server/__tests__/bootstrap-node-validation.test.ts +0 -138
  340. package/src/server/__tests__/grants-admin-route.test.ts +0 -171
  341. package/src/server/__tests__/grants-route.test.ts +0 -394
  342. package/src/server/__tests__/strands-route.test.ts +0 -234
  343. package/src/server/routes/bootstrap-node-validation.ts +0 -206
  344. package/src/server/routes/grants-admin.ts +0 -74
  345. package/src/server/routes/grants.ts +0 -193
  346. package/src/server/routes/provision-request-validation.ts +0 -105
  347. package/src/server/routes/strands.ts +0 -54
  348. package/src/server/routes/trust-circle.ts +0 -49
  349. package/src/strands/__tests__/strand-service.test.ts +0 -165
  350. package/src/strands/index.ts +0 -14
  351. package/src/strands/strand-service.ts +0 -135
  352. package/src/strands/types.ts +0 -102
@@ -1,307 +0,0 @@
1
- import { randomBytes } from 'node:crypto';
2
- import debug from 'debug';
3
- import { OwnerNodeUnavailableError } from '../owner/owner-node-client.js';
4
- import { TrustCircleError } from './types.js';
5
- const log = debug('cadre:host:trust-circle');
6
- /** Default invite lifetime: 24 hours. */
7
- export const DEFAULT_INVITE_TTL_MS = 24 * 60 * 60 * 1000;
8
- /** Token byte length (base64url-encoded; ~43 chars). */
9
- const TOKEN_BYTES = 32;
10
- /**
11
- * TrustCircleService — orchestrates invite issuance, redemption, and
12
- * membership management.
13
- *
14
- * Membership is canonical in the cadre control DB (`CadrePeer` table),
15
- * reached over the owner node's admin channel; labels and pending tokens
16
- * live in the host-local `TrustCircleStore`. When the node is unreachable,
17
- * owner operations surface `node_unavailable` (→ 503) and `list()`
18
- * degrades to the local labels file.
19
- */
20
- export class TrustCircleService {
21
- constructor(opts) {
22
- /**
23
- * In-flight redemption claims (by token). Serialises concurrent redeems
24
- * for the same token without burning the durable pending row before
25
- * `acceptPhone` succeeds. Intra-process only — the orchestrator enforces
26
- * single-process ownership of a given rootDir, so no file lock is needed.
27
- */
28
- this.inFlightRedemptions = new Set();
29
- this.cadreNode = opts.cadreNode;
30
- this.store = opts.store;
31
- this.now = opts.now ?? (() => new Date());
32
- }
33
- /**
34
- * Issue a new invite. Generates a token, persists a pending row, and
35
- * delegates to cadre-core to embed the host's owner addresses.
36
- */
37
- async issueInvite(opts) {
38
- const label = normaliseLabel(opts.label);
39
- const ttlMs = opts.ttlMs ?? DEFAULT_INVITE_TTL_MS;
40
- if (!Number.isFinite(ttlMs) || ttlMs <= 0) {
41
- throw new TrustCircleError('invalid_token', `Invalid ttlMs: ${ttlMs}`);
42
- }
43
- const token = generateToken();
44
- const created = this.now();
45
- const expiresAt = new Date(created.getTime() + ttlMs);
46
- const { invite, encodedInvite } = await this.cadreNode
47
- .createInvite(token, ttlMs)
48
- .catch((err) => this.toDomainError(err));
49
- const pending = {
50
- token,
51
- label,
52
- createdAt: created.toISOString(),
53
- expiresAt: expiresAt.toISOString(),
54
- };
55
- this.store.addPending(pending);
56
- log('issued invite for "%s" (token=%s, expires=%s)', label, token, expiresAt.toISOString());
57
- return { encodedInvite, invite, token, expiresAt };
58
- }
59
- /**
60
- * Redeem an invite for an incoming peer ID. On success:
61
- * - cadre-core authorizes the peer (inserts CadrePeer row).
62
- * - The pending row is consumed (one-time enforcement).
63
- * - A labelled member row is written locally.
64
- *
65
- * Ordering: the synchronous *claim* against `inFlightRedemptions` serialises
66
- * concurrent redeems for the same token (second concurrent caller rejects
67
- * synchronously before its first await). The durable `removePending` only
68
- * runs *after* `acceptPhone` succeeds — so a transient `node_unavailable`
69
- * leaves the token re-redeemable rather than permanently burning it.
70
- *
71
- * Crash-safety tradeoff: if the host crashes between `acceptPhone` success
72
- * and the durable `removePending`, a retry will dial in fine but the
73
- * owner node's `acceptPhone` will reject the second `CadrePeer` insert
74
- * with a PK constraint error (cadre-core does not upsert). That surfaces to
75
- * the redeemer as a non-`node_unavailable` failure; the admin can revoke
76
- * the lingering pending row. This is a narrower window than the prior
77
- * behaviour, where *any* transient node outage burned the token.
78
- */
79
- async redeemInvite(opts) {
80
- const { token, peerId } = opts;
81
- if (!token || !peerId) {
82
- throw new TrustCircleError('invalid_token', 'token and peerId are required');
83
- }
84
- const pending = this.store.getPending(token);
85
- if (!pending) {
86
- throw new TrustCircleError('already_redeemed', 'Invite not found or already redeemed');
87
- }
88
- if (pending.expiresAt) {
89
- const expiresAt = new Date(pending.expiresAt);
90
- if (Number.isFinite(expiresAt.getTime()) && this.now() > expiresAt) {
91
- // Expiry is permanent — reap the pending row durably.
92
- this.store.removePending(token);
93
- throw new TrustCircleError('expired', 'Invite has expired');
94
- }
95
- }
96
- // Synchronous in-memory claim. Closes the race between two concurrent
97
- // redemption requests for the same token — the loser sees the token in
98
- // the set and rejects synchronously before its first `await`.
99
- if (this.inFlightRedemptions.has(token)) {
100
- throw new TrustCircleError('already_redeemed', 'Invite not found or already redeemed');
101
- }
102
- this.inFlightRedemptions.add(token);
103
- try {
104
- // Reconstruct the CadreInvite that was originally issued. cadre-core's
105
- // acceptPhone validates `issuedInvite.token === options.token` (already
106
- // matches by construction) and re-checks expiration.
107
- const reconstructed = {
108
- partyId: '',
109
- ownerAddrs: [],
110
- token: pending.token,
111
- createdAt: new Date(pending.createdAt).getTime(),
112
- ...(pending.expiresAt ? { expiresAt: new Date(pending.expiresAt).getTime() } : {}),
113
- };
114
- await this.cadreNode
115
- .acceptPhone({ phonePeerId: peerId, token }, reconstructed)
116
- .catch((err) => this.toDomainError(err));
117
- // acceptPhone succeeded → durably consume the pending row. If we crash
118
- // between here and the next line, the token stays pending (re-redeem
119
- // would fail at acceptPhone with a duplicate-CadrePeer error, not
120
- // node_unavailable, and the admin can revoke).
121
- this.store.removePending(token);
122
- // If the member write fails the peer is still authorized in CadrePeer —
123
- // the next call to list() will pick it up unlabeled, which is the
124
- // documented graceful degradation.
125
- const member = {
126
- peerId,
127
- label: pending.label,
128
- addedAt: this.now().toISOString(),
129
- };
130
- this.store.addMember(member);
131
- log('redeemed invite for "%s" (peerId=%s, token=%s)', pending.label, peerId, token);
132
- return { peerId, label: pending.label };
133
- }
134
- finally {
135
- this.inFlightRedemptions.delete(token);
136
- }
137
- }
138
- /** Revoke a pending invite by token. No-op if not found. */
139
- async revokePending(token) {
140
- if (!this.store.removePending(token)) {
141
- throw new TrustCircleError('not_found', `Unknown pending invite: ${token}`);
142
- }
143
- log('revoked pending invite (token=%s)', token);
144
- }
145
- /**
146
- * Remove an authorised member. Deletes the CadrePeer row and the local
147
- * label. Throws not_found when the peer is in neither place.
148
- *
149
- * NOTE: no special case for the host's own peer ID — the local UI hides the
150
- * Remove button on the `self` row, but `DELETE /auth/members/<ownPeerId>`
151
- * (or `cadre-host trust revoke <ownPeerId>`) will delete the node's own
152
- * `CadrePeer` row. cadre-core re-registers self on node start, so a restart
153
- * heals it. If that stops being true, or the removal path grows a
154
- * non-loopback caller, guard `self` rows here.
155
- */
156
- async removeMember(peerId) {
157
- const inLocal = this.store.getMember(peerId);
158
- const inControl = await this.isMember(peerId);
159
- if (!inLocal && !inControl) {
160
- throw new TrustCircleError('not_found', `Unknown member: ${peerId}`);
161
- }
162
- if (inControl) {
163
- await this.cadreNode.removePeer(peerId).catch((err) => this.toDomainError(err));
164
- }
165
- if (inLocal) {
166
- this.store.removeMember(peerId);
167
- }
168
- log('removed member peerId=%s', peerId);
169
- }
170
- /** Whether the peer is present in the cadre's CadrePeer table. */
171
- async isMember(peerId) {
172
- try {
173
- return await this.cadreNode.isMember(peerId);
174
- }
175
- catch (err) {
176
- this.toDomainError(err);
177
- }
178
- }
179
- /**
180
- * UI snapshot. Joins the *authorized* membership (fetched over the admin
181
- * channel) with local labels; prunes any orphan labels (peer is no longer
182
- * authorised). Addressable-but-unauthorized peers — devices that merely
183
- * published an address record without an owner voucher — are deliberately
184
- * excluded; this is the listing an operator uses to decide who belongs.
185
- * The node's own self-published row is spliced back in from the local
186
- * label, since the authorized set excludes self by design. When the owner
187
- * node is unreachable, degrades to the local labels file so listing keeps
188
- * working while the node is down.
189
- */
190
- async list() {
191
- const labels = new Map();
192
- for (const m of this.store.listMembers()) {
193
- labels.set(m.peerId, { label: m.label, addedAt: m.addedAt, ...(m.self ? { self: true } : {}) });
194
- }
195
- const members = [];
196
- // Consult the control DB over the admin channel. A node-unavailable error
197
- // is non-fatal — fall back to the local labels rather than 503-ing a
198
- // read-only listing.
199
- let authorizedMembers;
200
- try {
201
- authorizedMembers = await this.cadreNode.listAuthorizedMembers();
202
- }
203
- catch (err) {
204
- if (!(err instanceof OwnerNodeUnavailableError))
205
- throw err;
206
- authorizedMembers = null;
207
- }
208
- if (authorizedMembers) {
209
- const seenPeerIds = new Set();
210
- for (const { peerId } of authorizedMembers) {
211
- seenPeerIds.add(peerId);
212
- const label = labels.get(peerId);
213
- members.push({
214
- peerId,
215
- label: label?.label ?? peerId,
216
- addedAt: label?.addedAt ?? '',
217
- ...(label?.self ? { self: true } : {}),
218
- });
219
- }
220
- // The authorized set excludes the node's own self-published row —
221
- // splice it back in from the local label rather than dropping it.
222
- for (const [peerId, row] of labels) {
223
- if (row.self && !seenPeerIds.has(peerId)) {
224
- seenPeerIds.add(peerId);
225
- members.push({ peerId, ...row });
226
- }
227
- }
228
- // Prune labels for peers that are neither authorized nor self. Only
229
- // when we successfully consulted the node — otherwise a transient
230
- // outage would wipe labels.
231
- for (const peerId of labels.keys()) {
232
- if (!seenPeerIds.has(peerId)) {
233
- this.store.removeMember(peerId);
234
- }
235
- }
236
- }
237
- else {
238
- // Node down: return labels as-is (degradation; no pruning).
239
- for (const [peerId, row] of labels) {
240
- members.push({ peerId, ...row });
241
- }
242
- }
243
- const pending = this.store.listPending();
244
- // Sort for stable UI ordering.
245
- members.sort((a, b) => a.peerId.localeCompare(b.peerId));
246
- pending.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
247
- return { members, pending };
248
- }
249
- /**
250
- * Translate an admin-channel transport failure into a `node_unavailable`
251
- * TrustCircleError (→ 503). Re-throws anything else unchanged. Returns
252
- * `never` so callers can `.catch(err => this.toDomainError(err))`.
253
- */
254
- toDomainError(err) {
255
- if (err instanceof OwnerNodeUnavailableError) {
256
- throw new TrustCircleError('node_unavailable', `Owner node unavailable: ${err.message}`);
257
- }
258
- throw err instanceof Error ? err : new Error(String(err));
259
- }
260
- }
261
- /**
262
- * Wrap a TrustCircleService into the typed handler shape consumed by
263
- * `cadre-host-local-ui`. Errors propagate as TrustCircleError; the UI ticket
264
- * maps `.code` → HTTP status.
265
- */
266
- export function createTrustCircleHandlers(service) {
267
- return {
268
- async postInvite(body) {
269
- if (!body || typeof body.label !== 'string') {
270
- throw new TrustCircleError('invalid_label', 'label is required');
271
- }
272
- const result = await service.issueInvite({ label: body.label, ttlMs: body.ttlMs });
273
- return {
274
- encodedInvite: result.encodedInvite,
275
- token: result.token,
276
- ...(result.expiresAt ? { expiresAt: result.expiresAt.toISOString() } : {}),
277
- };
278
- },
279
- async deleteInvite(token) {
280
- await service.revokePending(token);
281
- },
282
- async deleteMember(peerId) {
283
- await service.removeMember(peerId);
284
- },
285
- async listTrustCircle() {
286
- return await service.list();
287
- },
288
- };
289
- }
290
- function generateToken() {
291
- // base64url so it survives in URLs, QR codes, and shell arguments.
292
- return randomBytes(TOKEN_BYTES).toString('base64url');
293
- }
294
- function normaliseLabel(label) {
295
- if (typeof label !== 'string') {
296
- throw new TrustCircleError('invalid_label', 'label must be a string');
297
- }
298
- const trimmed = label.trim();
299
- if (trimmed.length === 0) {
300
- throw new TrustCircleError('invalid_label', 'label must not be empty');
301
- }
302
- if (trimmed.length > 200) {
303
- throw new TrustCircleError('invalid_label', 'label must be 200 characters or fewer');
304
- }
305
- return trimmed;
306
- }
307
- //# sourceMappingURL=trust-circle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trust-circle.js","sourceRoot":"","sources":["../../src/auth/trust-circle.ts"],"names":[],"mappings":"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"}
@@ -1,84 +0,0 @@
1
- /**
2
- * Trust-circle types for cadre-host.
3
- *
4
- * The trust circle is the set of devices (peers) authorised to participate
5
- * in the host's cadre. Membership is stored canonically in the cadre control
6
- * network's `CadrePeer` table (via cadre-core). This module layers two pieces
7
- * of *host-local* state on top:
8
- *
9
- * - **Labels**: human-readable names ("Mom's phone") assigned by the host
10
- * admin. Display-only; loss just shows the bare peer ID.
11
- * - **Pending invites**: tokens that have been issued but not yet redeemed.
12
- * Operational state — lives on the issuing node, doesn't replicate.
13
- *
14
- * Both live in `<rootDir>/trust-circle.json`, written atomically.
15
- */
16
- /** An authorised member of the trust circle (matches a `CadrePeer` row). */
17
- export interface TrustCircleMember {
18
- /** libp2p peer ID. */
19
- peerId: string;
20
- /** Display label assigned by the host admin. */
21
- label: string;
22
- /** ISO timestamp when the peer was added. */
23
- addedAt: string;
24
- /** True if this row represents the host's own cadre node (self-enrolment). */
25
- self?: boolean;
26
- }
27
- /** An invite that has been issued but not yet redeemed. */
28
- export interface PendingInvite {
29
- /** Random token (base64url) used to match the redemption. */
30
- token: string;
31
- /** Display label that will be assigned to the redeemer on success. */
32
- label: string;
33
- /** ISO timestamp when the invite was issued. */
34
- createdAt: string;
35
- /** Optional ISO expiration timestamp. */
36
- expiresAt?: string;
37
- }
38
- /** On-disk shape of `trust-circle.json`. */
39
- export interface TrustCircleFile {
40
- version: 1;
41
- /** keyed by peer ID. */
42
- members: Record<string, Omit<TrustCircleMember, 'peerId'>>;
43
- /** keyed by token. */
44
- pendingInvites: Record<string, Omit<PendingInvite, 'token'>>;
45
- }
46
- /** Snapshot returned to the management UI. */
47
- export interface TrustCircleSnapshot {
48
- members: TrustCircleMember[];
49
- pending: PendingInvite[];
50
- }
51
- /**
52
- * Typed HTTP handlers exposed to `cadre-host-local-ui` for Fastify wiring.
53
- *
54
- * Handlers take typed objects and either return typed results or throw a
55
- * `TrustCircleError` whose `.code` the UI ticket maps to an HTTP status:
56
- *
57
- * - `not_found` → 404 (unknown token / unknown peer)
58
- * - `expired` → 410 (invite past expiresAt)
59
- * - `already_redeemed` → 409 (token was used and is gone)
60
- * - `node_unavailable` → 503 (owner node admin channel down/not ready)
61
- * - default → 500
62
- */
63
- export interface TrustCircleHandlers {
64
- postInvite(body: {
65
- label: string;
66
- ttlMs?: number;
67
- }): Promise<{
68
- encodedInvite: string;
69
- token: string;
70
- expiresAt?: string;
71
- }>;
72
- deleteInvite(token: string): Promise<void>;
73
- deleteMember(peerId: string): Promise<void>;
74
- listTrustCircle(): Promise<TrustCircleSnapshot>;
75
- }
76
- /** Error codes thrown by TrustCircleService. */
77
- export type TrustCircleErrorCode = 'not_found' | 'expired' | 'already_redeemed' | 'invalid_label' | 'invalid_token' | 'storage_error'
78
- /** The owner node's admin channel is unreachable / not ready. */
79
- | 'node_unavailable';
80
- /** Typed error carrying a stable `code` for HTTP mapping. */
81
- export declare class TrustCircleError extends Error {
82
- readonly code: TrustCircleErrorCode;
83
- constructor(code: TrustCircleErrorCode, message: string);
84
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Trust-circle types for cadre-host.
3
- *
4
- * The trust circle is the set of devices (peers) authorised to participate
5
- * in the host's cadre. Membership is stored canonically in the cadre control
6
- * network's `CadrePeer` table (via cadre-core). This module layers two pieces
7
- * of *host-local* state on top:
8
- *
9
- * - **Labels**: human-readable names ("Mom's phone") assigned by the host
10
- * admin. Display-only; loss just shows the bare peer ID.
11
- * - **Pending invites**: tokens that have been issued but not yet redeemed.
12
- * Operational state — lives on the issuing node, doesn't replicate.
13
- *
14
- * Both live in `<rootDir>/trust-circle.json`, written atomically.
15
- */
16
- /** Typed error carrying a stable `code` for HTTP mapping. */
17
- export class TrustCircleError extends Error {
18
- constructor(code, message) {
19
- super(message);
20
- this.name = 'TrustCircleError';
21
- this.code = code;
22
- }
23
- }
24
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA2EH,6DAA6D;AAC7D,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAGzC,YAAY,IAA0B,EAAE,OAAe;QACrD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}