@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,29 +1,15 @@
1
1
  /**
2
- * /api/nodes — list managed cadre nodes, look up details, and control
3
- * lifecycle.
4
- *
5
- * Bus events for lifecycle transitions are emitted by the orchestrator's
6
- * `onStateChange` (forwarded by `createLocalUiServer.start`) — the route
7
- * handlers don't re-publish.
8
- *
9
- * start/stop/restart are real for the admin's owner node only (start/restart
10
- * re-spawn it from the persisted `OwnerSpawnConfig`). Every other node this
11
- * route can see is a donated node, whose lifecycle belongs to the donation
12
- * surface — this route no longer spawns generic nodes, and a stop here would
13
- * be undone at once by the donation supervisor's respawn. So all three verbs
14
- * answer a known non-owner node with 501, pointing at the donation teardown.
15
- *
16
- * Owner start/restart are founder-only: a donor-only host that once ran as a
17
- * founder still holds the owner handle and saved config (so re-enabling
18
- * `ownCadre` can resume it), but spawning it here would bring the owner node
19
- * back without its trust circle, NAT or strand services — so those answer 409.
2
+ * /api/nodes — list managed cadre nodes (orchestrator handles), look up one
3
+ * node's details, and tail its log. Read-only: every node's lifecycle belongs to
4
+ * `/api/hosted-nodes`, whose supervisor would undo at once a stop issued
5
+ * anywhere else. A handle's `partyId` is the placeholder an unclaimed node was
6
+ * started with until its first respawn after the claim; the hosted-node record
7
+ * carries the real party.
20
8
  */
21
9
  import type { FastifyInstance } from 'fastify';
22
10
  import type { HostProcessOrchestrator } from '../../orchestrator/index.js';
23
- import type { HostRole } from './status.js';
24
11
  export interface NodesRoutesOptions {
25
12
  orchestrator: HostProcessOrchestrator;
26
- role: HostRole;
27
13
  }
28
14
  export declare function registerNodesRoutes(app: FastifyInstance, opts: NodesRoutesOptions): void;
29
15
  /**
@@ -1,29 +1,17 @@
1
1
  /**
2
- * /api/nodes — list managed cadre nodes, look up details, and control
3
- * lifecycle.
4
- *
5
- * Bus events for lifecycle transitions are emitted by the orchestrator's
6
- * `onStateChange` (forwarded by `createLocalUiServer.start`) — the route
7
- * handlers don't re-publish.
8
- *
9
- * start/stop/restart are real for the admin's owner node only (start/restart
10
- * re-spawn it from the persisted `OwnerSpawnConfig`). Every other node this
11
- * route can see is a donated node, whose lifecycle belongs to the donation
12
- * surface — this route no longer spawns generic nodes, and a stop here would
13
- * be undone at once by the donation supervisor's respawn. So all three verbs
14
- * answer a known non-owner node with 501, pointing at the donation teardown.
15
- *
16
- * Owner start/restart are founder-only: a donor-only host that once ran as a
17
- * founder still holds the owner handle and saved config (so re-enabling
18
- * `ownCadre` can resume it), but spawning it here would bring the owner node
19
- * back without its trust circle, NAT or strand services — so those answer 409.
2
+ * /api/nodes — list managed cadre nodes (orchestrator handles), look up one
3
+ * node's details, and tail its log. Read-only: every node's lifecycle belongs to
4
+ * `/api/hosted-nodes`, whose supervisor would undo at once a stop issued
5
+ * anywhere else. A handle's `partyId` is the placeholder an unclaimed node was
6
+ * started with until its first respawn after the claim; the hosted-node record
7
+ * carries the real party.
20
8
  */
21
9
  import { existsSync, openSync, readSync, closeSync, statSync } from 'node:fs';
22
10
  import { defaultLogPath } from '../../orchestrator/log-rotator.js';
23
11
  const DEFAULT_LOG_LINES = 200;
24
12
  const MAX_LOG_LINES = 2000;
25
13
  export function registerNodesRoutes(app, opts) {
26
- const { orchestrator, role } = opts;
14
+ const { orchestrator } = opts;
27
15
  app.get('/api/nodes', async () => {
28
16
  return { ok: true, data: { nodes: orchestrator.listNodes() } };
29
17
  });
@@ -51,61 +39,6 @@ export function registerNodesRoutes(app, opts) {
51
39
  const lines = tailLogFile(defaultLogPath(node.workdir), tail);
52
40
  return { ok: true, data: { lines } };
53
41
  });
54
- // start / stop / restart: real for the admin's owner node (started from the
55
- // persisted OwnerSpawnConfig). Donated-node lifecycle belongs to the donation
56
- // surface — those ids return a clear not_implemented that points there;
57
- // unknown ids 404.
58
- app.post('/api/nodes/:id/stop', async (request, reply) => {
59
- const { id } = request.params;
60
- if (!orchestrator.isOwnerNode(id)) {
61
- return ownerOnlyFallback(reply, orchestrator, id, 'stop');
62
- }
63
- const dockerId = orchestrator.resolveDockerId(id);
64
- if (!dockerId)
65
- return notFound(reply, id);
66
- await orchestrator.stopContainer(dockerId);
67
- // The orchestrator emits its own onStateChange — createLocalUiServer
68
- // forwards that to the bus. Don't double-publish here.
69
- return { ok: true };
70
- });
71
- app.post('/api/nodes/:id/start', async (request, reply) => {
72
- const { id } = request.params;
73
- if (orchestrator.isOwnerNode(id)) {
74
- if (role === 'donor')
75
- return ownCadreDisabled(reply, 'start');
76
- if (!orchestrator.hasOwnerConfig()) {
77
- return notImplemented(reply, `start ${id}: owner node has no saved spawn config.`);
78
- }
79
- const node = await orchestrator.ensureOwnerNode();
80
- return { ok: true, data: { node } };
81
- }
82
- return ownerOnlyFallback(reply, orchestrator, id, 'start');
83
- });
84
- app.post('/api/nodes/:id/restart', async (request, reply) => {
85
- const { id } = request.params;
86
- if (orchestrator.isOwnerNode(id)) {
87
- if (role === 'donor')
88
- return ownCadreDisabled(reply, 'restart');
89
- if (!orchestrator.hasOwnerConfig()) {
90
- return notImplemented(reply, `restart ${id}: owner node has no saved spawn config.`);
91
- }
92
- const node = await orchestrator.restartOwnerNode();
93
- return { ok: true, data: { node } };
94
- }
95
- return ownerOnlyFallback(reply, orchestrator, id, 'restart');
96
- });
97
- }
98
- /**
99
- * 404 for unknown ids; 501 not_implemented for known non-owner nodes — all of
100
- * them donated. A donated node's containerId is its donation id, so the
101
- * message names `node.id` rather than the route param, which may be the
102
- * opaque dockerId — only the donation id is what the terminate command takes.
103
- */
104
- function ownerOnlyFallback(reply, orchestrator, id, verb) {
105
- const node = orchestrator.getNode(id);
106
- if (!node)
107
- return notFound(reply, id);
108
- return notImplemented(reply, `${verb} ${id}: only the owner node can be started, stopped or restarted here; a donated node's lifecycle is owned by the donation surface — end it with 'cadre-host grant terminate ${node.id}' (DELETE /grants-admin/donations/${node.id}).`);
109
42
  }
110
43
  function notFound(reply, id) {
111
44
  return reply.code(404).send({
@@ -113,18 +46,6 @@ function notFound(reply, id) {
113
46
  error: { code: 'not_found', message: `Unknown node: ${id}` },
114
47
  });
115
48
  }
116
- function notImplemented(reply, message) {
117
- return reply.code(501).send({ ok: false, error: { code: 'not_implemented', message } });
118
- }
119
- function ownCadreDisabled(reply, verb) {
120
- return reply.code(409).send({
121
- ok: false,
122
- error: {
123
- code: 'own_cadre_disabled',
124
- message: `${verb} owner: this host's own cadre is turned off (donor-only mode). Set ownCadre.enabled in host.config.json and restart cadre-host to run it again.`,
125
- },
126
- });
127
- }
128
49
  /**
129
50
  * Read the last `n` lines from a log file by walking the tail in chunks.
130
51
  * Returns [] for a missing file.
@@ -1 +1 @@
1
- {"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../../src/server/routes/nodes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../../src/server/routes/nodes.ts"],"names":[],"mappings":"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"}
@@ -5,10 +5,10 @@
5
5
  * This route is a thin passthrough plus a write-whitelist:
6
6
  *
7
7
  * - uiPort rejected (restart required; only edit at install time)
8
- * - libp2pPort rejected (restart required)
9
8
  * - upnpEnabled accepted → also propagated to NatService.putSettings
10
9
  * - updates.autoApply accepted → propagated to UpdateService.putSettings
11
10
  * - updates.manifestUrl accepted → propagated to UpdateService.putSettings
11
+ * - claimAddresses accepted (replaced whole) → read by the next claim code
12
12
  * - anything else 400 invalid_setting
13
13
  *
14
14
  * GET returns the full `HostConfigFile` (the SPA wants the full shape so it
@@ -20,12 +20,8 @@ import type { UpdateService } from '../../update/index.js';
20
20
  import type { HostSettingsStore } from '../settings-store.js';
21
21
  export interface SettingsRoutesOptions {
22
22
  settingsStore: HostSettingsStore;
23
- /**
24
- * Present only when the host runs its own personal cadre. In donor-only mode
25
- * an `upnpEnabled` write still persists to host.config.json but has no running
26
- * NatService to propagate into.
27
- */
28
- nat?: NatService;
23
+ /** An `upnpEnabled` write takes effect on it at once. */
24
+ nat: NatService;
29
25
  update?: UpdateService;
30
26
  }
31
27
  export declare function registerSettingsRoutes(app: FastifyInstance, opts: SettingsRoutesOptions): void;
@@ -5,17 +5,18 @@
5
5
  * This route is a thin passthrough plus a write-whitelist:
6
6
  *
7
7
  * - uiPort rejected (restart required; only edit at install time)
8
- * - libp2pPort rejected (restart required)
9
8
  * - upnpEnabled accepted → also propagated to NatService.putSettings
10
9
  * - updates.autoApply accepted → propagated to UpdateService.putSettings
11
10
  * - updates.manifestUrl accepted → propagated to UpdateService.putSettings
11
+ * - claimAddresses accepted (replaced whole) → read by the next claim code
12
12
  * - anything else 400 invalid_setting
13
13
  *
14
14
  * GET returns the full `HostConfigFile` (the SPA wants the full shape so it
15
15
  * can render a read-only view of the rejected keys).
16
16
  */
17
- const FORBIDDEN_KEYS = new Set(['uiPort', 'libp2pPort', 'dataDir', 'identityPath', 'installId', 'installedAt', 'installerVersion', 'version', 'ownCadre']);
18
- const WRITABLE_TOP_KEYS = new Set(['upnpEnabled', 'updates']);
17
+ import { claimAddressSettingsProblem } from '../../installer/config.js';
18
+ const FORBIDDEN_KEYS = new Set(['uiPort', 'dataDir', 'installId', 'installedAt', 'installerVersion', 'version']);
19
+ const WRITABLE_TOP_KEYS = new Set(['upnpEnabled', 'updates', 'claimAddresses']);
19
20
  const WRITABLE_UPDATES_KEYS = new Set(['autoApply', 'manifestUrl']);
20
21
  export function registerSettingsRoutes(app, opts) {
21
22
  const { settingsStore, nat, update } = opts;
@@ -35,14 +36,11 @@ export function registerSettingsRoutes(app, opts) {
35
36
  const patch = {};
36
37
  if ('upnpEnabled' in body) {
37
38
  patch.upnpEnabled = body.upnpEnabled;
38
- // Propagate UPnP toggle into the running NatService so the change
39
+ // Propagate the UPnP toggle into the running NatService so the change
39
40
  // takes effect immediately. NatService persists into nat.json — that's
40
41
  // independent of host.config.json's `upnpEnabled` (which the installer
41
42
  // uses on first run to seed nat.json). Update both for consistency.
42
- // In donor-only mode there is no NatService — the write still persists.
43
- if (nat) {
44
- await nat.putSettings({ upnpEnabled: body.upnpEnabled });
45
- }
43
+ await nat.putSettings({ upnpEnabled: body.upnpEnabled });
46
44
  }
47
45
  if ('updates' in body) {
48
46
  const updates = body.updates;
@@ -61,6 +59,13 @@ export function registerSettingsRoutes(app, opts) {
61
59
  await update.putSettings(propagate);
62
60
  }
63
61
  }
62
+ if ('claimAddresses' in body) {
63
+ const { lan, addrs } = body.claimAddresses;
64
+ patch.claimAddresses = {
65
+ ...(lan !== undefined ? { lan } : {}),
66
+ ...(addrs !== undefined ? { addrs: addrs.map((a) => a.trim()).filter((a) => a.length > 0) } : {}),
67
+ };
68
+ }
64
69
  const next = settingsStore.update(patch);
65
70
  return { ok: true, data: next };
66
71
  });
@@ -77,6 +82,11 @@ function validatePatch(body) {
77
82
  if ('upnpEnabled' in body && typeof body.upnpEnabled !== 'boolean') {
78
83
  return { error: '"upnpEnabled" must be a boolean' };
79
84
  }
85
+ if ('claimAddresses' in body) {
86
+ const problem = claimAddressSettingsProblem(body.claimAddresses);
87
+ if (problem)
88
+ return { error: problem };
89
+ }
80
90
  if ('updates' in body) {
81
91
  if (!body.updates || typeof body.updates !== 'object') {
82
92
  return { error: '"updates" must be an object' };
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/server/routes/settings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/server/routes/settings.ts"],"names":[],"mappings":"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"}
@@ -7,22 +7,12 @@
7
7
  import type { FastifyInstance } from 'fastify';
8
8
  import type { HostProcessOrchestrator } from '../../orchestrator/index.js';
9
9
  import type { ManagedNodeInfo } from '../../orchestrator/types.js';
10
- import type { TrustCircleService } from '../../auth/index.js';
11
10
  import type { NatService } from '../../nat/index.js';
12
11
  import type { NatStatusSnapshot } from '../../nat/types.js';
13
12
  import type { UpdateService } from '../../update/index.js';
14
- /**
15
- * Which role the running process is in: `'founder'` also runs the host's own
16
- * cadre (`ownCadre.enabled` at start), `'donor'` only donates nodes.
17
- */
18
- export type HostRole = 'founder' | 'donor';
19
13
  export interface StatusRouteOptions {
20
14
  orchestrator: HostProcessOrchestrator;
21
- role: HostRole;
22
- /** Present only when the host runs its own personal cadre (`ownCadre.enabled`). */
23
- trustCircle?: TrustCircleService;
24
- /** Present only when the host runs its own personal cadre (`ownCadre.enabled`). */
25
- nat?: NatService;
15
+ nat: NatService;
26
16
  update?: UpdateService;
27
17
  }
28
18
  export interface StatusResponse {
@@ -31,26 +21,13 @@ export interface StatusResponse {
31
21
  version: string;
32
22
  uptimeSeconds: number;
33
23
  };
34
- /**
35
- * Decided at start from `ownCadre.enabled` — the running process, not the file
36
- * on disk, which may have been edited since without a restart.
37
- */
38
- role: HostRole;
39
24
  nodes: Array<{
40
25
  id: string;
41
26
  partyId: string;
42
27
  status: ManagedNodeInfo['status'];
43
28
  profile: ManagedNodeInfo['profile'];
44
- /** Present (true) only on the host's own owner node; every other node is donated. */
45
- owner?: true;
46
29
  }>;
47
- /** Omitted in donor-only mode (no host-own trust circle). */
48
- trustCircle?: {
49
- members: number;
50
- pending: number;
51
- };
52
- /** Omitted in donor-only mode (no NAT service). */
53
- connectivity?: NatStatusSnapshot;
30
+ connectivity: NatStatusSnapshot;
54
31
  update?: {
55
32
  available?: string;
56
33
  lastChecked?: string;
@@ -4,38 +4,25 @@
4
4
  * All inputs are in-memory subsystem state — no disk reads on each call.
5
5
  * The response budget is < 5 ms; favour `getStatus()` over `testReachability()`.
6
6
  */
7
- import { readFileSync } from 'node:fs';
8
- import { dirname, resolve } from 'node:path';
9
- import { fileURLToPath } from 'node:url';
7
+ import { packageVersion } from '../../package-version.js';
10
8
  const PROCESS_STARTED_AT = process.hrtime.bigint();
11
9
  export function registerStatusRoute(app, opts) {
12
- const version = readPackageVersion();
13
10
  app.get('/api/status', async () => {
14
11
  const nodes = opts.orchestrator.listNodes().map((n) => ({
15
12
  id: n.id,
16
13
  partyId: n.partyId,
17
14
  status: n.status,
18
15
  profile: n.profile,
19
- ...(n.owner ? { owner: true } : {}),
20
16
  }));
21
17
  const response = {
22
18
  service: {
23
19
  name: 'cadre-host',
24
- version,
20
+ version: packageVersion,
25
21
  uptimeSeconds: secondsSince(PROCESS_STARTED_AT),
26
22
  },
27
- role: opts.role,
28
23
  nodes,
24
+ connectivity: opts.nat.getStatus(),
29
25
  };
30
- // Trust-circle + connectivity exist only when the host runs its own
31
- // personal cadre; donor-only mode omits both.
32
- if (opts.trustCircle) {
33
- const tc = await opts.trustCircle.list();
34
- response.trustCircle = { members: tc.members.length, pending: tc.pending.length };
35
- }
36
- if (opts.nat) {
37
- response.connectivity = opts.nat.getStatus();
38
- }
39
26
  if (opts.update) {
40
27
  const state = await opts.update.getState();
41
28
  const update = {};
@@ -53,31 +40,4 @@ function secondsSince(start) {
53
40
  const elapsedNs = now - start;
54
41
  return Number(elapsedNs / 1000000000n);
55
42
  }
56
- let cachedVersion = null;
57
- function readPackageVersion() {
58
- if (cachedVersion)
59
- return cachedVersion;
60
- try {
61
- // dist/server/routes/status.js -> ../../../package.json
62
- // src/server/routes/status.ts -> ../../../package.json (vitest)
63
- const here = dirname(fileURLToPath(import.meta.url));
64
- const candidates = [
65
- resolve(here, '..', '..', '..', 'package.json'),
66
- resolve(here, '..', '..', 'package.json'),
67
- ];
68
- for (const p of candidates) {
69
- try {
70
- const parsed = JSON.parse(readFileSync(p, 'utf8'));
71
- if (parsed.version) {
72
- cachedVersion = parsed.version;
73
- return cachedVersion;
74
- }
75
- }
76
- catch { /* try next */ }
77
- }
78
- }
79
- catch { /* ignore */ }
80
- cachedVersion = '0.0.0-unknown';
81
- return cachedVersion;
82
- }
83
43
  //# sourceMappingURL=status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/server/routes/status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/server/routes/status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AAoBnD,MAAM,UAAU,mBAAmB,CAAC,GAAoB,EAAE,IAAwB;IAChF,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,IAA6B,EAAE;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtD,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAmB;YAC/B,OAAO,EAAE;gBACP,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,cAAc;gBACvB,aAAa,EAAE,YAAY,CAAC,kBAAkB,CAAC;aAChD;YACD,KAAK;YACL,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE;SACnC,CAAC;QAEF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAiD,EAAE,CAAC;YAChE,IAAI,KAAK,CAAC,SAAS,EAAE,OAAO;gBAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC;YACzE,IAAI,KAAK,CAAC,WAAW;gBAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;YAC9D,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;QAC3B,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,GAAG,GAAG,KAAK,CAAC;IAC9B,OAAO,MAAM,CAAC,SAAS,GAAG,WAAc,CAAC,CAAC;AAC5C,CAAC"}
@@ -90,14 +90,14 @@ export function buildFastify() {
90
90
  * request with no body (`request.body === undefined`), instead of Fastify's
91
91
  * default `400 FST_ERR_CTP_EMPTY_JSON_BODY`.
92
92
  *
93
- * `/grants` is served to other people's clients, and sending the JSON content
94
- * type on every request, body or not, is a common client habit — the phone app
95
- * did it, and the refused body-less `DELETE /grants/:id` left the loan and its
96
- * node running. Every route that reads a body already reads `request.body ?? {}`,
97
- * so a route that needs a field still answers its own `invalid_request` naming it.
98
- * A non-empty body goes to Fastify's own parser, so malformed JSON is still a 400
99
- * and the prototype-poisoning checks are unchanged (`'error'` is Fastify's default
100
- * for both).
93
+ * Sending the JSON content type on every request, body or not, is a common
94
+ * client habit (`POST /api/hosted-nodes` takes no body today, and a body-less
95
+ * `DELETE` is the norm), and a refused request here is a node left running.
96
+ * Every route that reads a body already reads `request.body ?? {}`, so a route
97
+ * that needs a field still answers its own `invalid_request` naming it. A
98
+ * non-empty body goes to Fastify's own parser, so malformed JSON is still a 400
99
+ * and the prototype-poisoning checks are unchanged (`'error'` is Fastify's
100
+ * default for both).
101
101
  */
102
102
  function acceptEmptyJsonBodies(app) {
103
103
  // NOTE: 'error', 'error' mirrors Fastify's defaults for proto/constructor poisoning; if
@@ -2,7 +2,7 @@
2
2
  * Settings store — read-write facade around `host.config.json` for the
3
3
  * /api/settings route.
4
4
  *
5
- * The installer (`6.4.1`) owns the schema (`HostConfigFile` v2). This module
5
+ * The installer (`6.4.1`) owns the schema (`HostConfigFile` v3). This module
6
6
  * just delegates load/persist to that file's helpers; it exists so route
7
7
  * handlers can read/write without each one re-resolving `configPath(dataDir)`.
8
8
  *
@@ -17,7 +17,7 @@ export interface HostSettingsStoreOptions {
17
17
  export declare class HostSettingsStore {
18
18
  private readonly configPath;
19
19
  constructor(opts: HostSettingsStoreOptions);
20
- /** Read the current host.config.json. Throws if absent, malformed, or not version 2. */
20
+ /** Read the current host.config.json. Throws if absent, malformed, or not version 3. */
21
21
  read(): HostConfigFile;
22
22
  /** Patch and persist. */
23
23
  update(patch: Partial<Omit<HostConfigFile, 'version'>>): HostConfigFile;
@@ -2,7 +2,7 @@
2
2
  * Settings store — read-write facade around `host.config.json` for the
3
3
  * /api/settings route.
4
4
  *
5
- * The installer (`6.4.1`) owns the schema (`HostConfigFile` v2). This module
5
+ * The installer (`6.4.1`) owns the schema (`HostConfigFile` v3). This module
6
6
  * just delegates load/persist to that file's helpers; it exists so route
7
7
  * handlers can read/write without each one re-resolving `configPath(dataDir)`.
8
8
  *
@@ -19,7 +19,7 @@ export class HostSettingsStore {
19
19
  // /api/settings answers 500 code "internal" with the read message passed through.
20
20
  // Fine while the UI just surfaces the text; if it ever needs to tell "your config
21
21
  // file is unreadable" apart from a genuine server bug, give this a typed error.
22
- /** Read the current host.config.json. Throws if absent, malformed, or not version 2. */
22
+ /** Read the current host.config.json. Throws if absent, malformed, or not version 3. */
23
23
  read() {
24
24
  return readHostConfig(this.configPath);
25
25
  }
@@ -52,7 +52,6 @@ export function registerStaticMount(app, opts = {}) {
52
52
  }
53
53
  // Don't try to serve API paths as static.
54
54
  if (request.url.startsWith('/api') ||
55
- request.url.startsWith('/auth') ||
56
55
  request.url.startsWith('/nat') ||
57
56
  request.url.startsWith('/update')) {
58
57
  return reply.code(404).send({
@@ -184,7 +183,7 @@ function placeholderHtml() {
184
183
  <li><span class="endpoint">GET /api/nodes</span></li>
185
184
  <li><span class="endpoint">GET /api/settings</span></li>
186
185
  <li><span class="endpoint">GET /api/events</span> (Server-Sent Events)</li>
187
- <li><span class="endpoint">/auth/*</span>, <span class="endpoint">/nat/*</span>, <span class="endpoint">/update/*</span></li>
186
+ <li><span class="endpoint">/nat/*</span>, <span class="endpoint">/update/*</span></li>
188
187
  </ul>
189
188
  <p>See <a href="https://github.com/gotchoices/sereus/blob/master/docs/cadre-host.md">docs/cadre-host.md</a>.</p>
190
189
  </body>
@@ -1 +1 @@
1
- {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .dot.svelte-1qa2kn2{display:inline-flex;align-items:center;gap:.5rem;font-weight:500}.bulb.svelte-1qa2kn2{display:inline-block;border-radius:999px;flex:0 0 auto;background:var(--color-text-soft);box-shadow:0 0 0 3px #0000000f}.dot-ok.svelte-1qa2kn2 .bulb:where(.svelte-1qa2kn2){background:var(--color-success);box-shadow:0 0 0 3px var(--color-success-bg)}.dot-warn.svelte-1qa2kn2 .bulb:where(.svelte-1qa2kn2){background:var(--color-warn);box-shadow:0 0 0 3px var(--color-warn-bg)}.dot-err.svelte-1qa2kn2 .bulb:where(.svelte-1qa2kn2){background:var(--color-danger);box-shadow:0 0 0 3px var(--color-danger-bg)}.dot-muted.svelte-1qa2kn2 .bulb:where(.svelte-1qa2kn2){background:var(--color-text-soft)}.dot-ok.svelte-1qa2kn2{color:var(--color-success)}.dot-warn.svelte-1qa2kn2{color:var(--color-warn)}.dot-err.svelte-1qa2kn2{color:var(--color-danger)}.banner.svelte-15mtls8{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-radius:var(--radius);background:var(--color-info-bg);color:var(--color-info);border:1px solid var(--color-info)}.summary.svelte-15mtls8{grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))}.kv.svelte-15mtls8{margin:var(--space-3) 0 0 0;display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1) var(--space-3);font-size:.9rem}.kv.svelte-15mtls8>div:where(.svelte-15mtls8){display:contents}.kv.svelte-15mtls8 dt:where(.svelte-15mtls8){color:var(--color-text-muted)}.kv.svelte-15mtls8 dd:where(.svelte-15mtls8){margin:0}.big.svelte-15mtls8{font-size:1.75rem;font-weight:600;margin:var(--space-2) 0}.big.svelte-15mtls8 .muted:where(.svelte-15mtls8){font-size:.95rem;font-weight:400}.none.svelte-15mtls8{margin:var(--space-2) 0;color:var(--color-warn);font-weight:500}.link.svelte-15mtls8{display:inline-block;margin-top:var(--space-2);font-weight:500}.row.svelte-io9f1k{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.kv.svelte-io9f1k{margin:0;display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1) var(--space-3);font-size:.9rem}.kv.svelte-io9f1k>div:where(.svelte-io9f1k){display:contents}.kv.svelte-io9f1k dt:where(.svelte-io9f1k){color:var(--color-text-muted)}.kv.svelte-io9f1k dd:where(.svelte-io9f1k){margin:0;min-width:0}.addrs.svelte-io9f1k{list-style:none;margin:0;padding:0}.addrs.svelte-io9f1k li:where(.svelte-io9f1k){display:flex;align-items:center;gap:.25rem}.addrs.svelte-io9f1k code:where(.svelte-io9f1k){word-break:break-all}.reach.svelte-io9f1k p:where(.svelte-io9f1k){margin:0}.instruction.svelte-io9f1k{font-weight:500}summary.svelte-io9f1k{cursor:pointer;font-size:.9rem;font-weight:500}.forward.svelte-io9f1k{display:grid;gap:var(--space-2);margin-top:var(--space-2)}.fields.svelte-io9f1k{display:grid;gap:var(--space-2);grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))}.actions.svelte-io9f1k{display:flex;justify-content:flex-end;gap:.5rem}.small.svelte-io9f1k{font-size:.85rem}.error.svelte-io9f1k{color:var(--color-danger)}.grid.two.svelte-hh3bto{grid-template-columns:repeat(auto-fit,minmax(20rem,1fr))}.kv.svelte-hh3bto{margin:var(--space-3) 0;display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1) var(--space-3);font-size:.9rem}.kv.svelte-hh3bto>div:where(.svelte-hh3bto){display:contents}.kv.svelte-hh3bto dt:where(.svelte-hh3bto){color:var(--color-text-muted)}.kv.svelte-hh3bto dd:where(.svelte-hh3bto){margin:0}.row.inline.svelte-hh3bto{gap:.5rem}.row.inline.svelte-hh3bto input[type=checkbox]:where(.svelte-hh3bto),.row.inline.svelte-hh3bto input[type=radio]:where(.svelte-hh3bto){width:auto}fieldset.svelte-hh3bto{border:none;padding:0;margin:0}.nodes.svelte-hh3bto{list-style:none;margin:0;padding:0;display:grid;gap:var(--space-3)}.nodes.svelte-hh3bto li:where(.svelte-hh3bto){border-top:1px solid var(--color-border);padding-top:var(--space-3)}.nodes.svelte-hh3bto li:where(.svelte-hh3bto):first-child{border-top:0;padding-top:0}.warning.svelte-hh3bto{background:var(--color-warn-bg);border-color:var(--color-warn)}.actions.svelte-hh3bto{display:flex;justify-content:flex-end;gap:.5rem}.small.svelte-hh3bto{font-size:.85rem}.scroll.svelte-7tcksg{overflow-x:auto}table.svelte-7tcksg{width:100%;border-collapse:collapse;font-size:.92rem}th.svelte-7tcksg,td.svelte-7tcksg{padding:.5rem .75rem;text-align:left;border-bottom:1px solid var(--color-border);white-space:nowrap}th.svelte-7tcksg{font-weight:600;font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-muted);border-bottom-color:var(--color-border-strong)}tr.svelte-7tcksg:last-child td:where(.svelte-7tcksg){border-bottom:none}.badges.svelte-7tcksg{display:inline-flex;gap:.25rem}.error.svelte-7tcksg{color:var(--color-danger)}.qr.svelte-1uqetyj{background:#fff;border-radius:var(--radius);padding:.5rem;display:inline-block;line-height:0}.qr.svelte-1uqetyj svg{width:100%;height:100%;display:block}.placeholder.svelte-1uqetyj{background:var(--color-surface-alt)}.qr-wrap.svelte-sddtr9{display:flex;justify-content:center;margin:var(--space-3) 0}.token.svelte-sddtr9{display:flex;flex-direction:column;gap:.5rem}.token.svelte-sddtr9 textarea:where(.svelte-sddtr9){font-family:var(--font-mono);font-size:.78rem;word-break:break-all;resize:vertical}.token.svelte-sddtr9 button:where(.svelte-sddtr9){align-self:flex-end;display:inline-flex;align-items:center;gap:.375rem}p.svelte-1jht8du{margin:0}.small.svelte-1jht8du{font-size:.85rem}.error.svelte-1jht8du{color:var(--color-danger)}.warn.svelte-1jht8du{color:var(--color-warn);font-weight:500}.backdrop.svelte-80vbit{position:fixed;inset:0;background:#0f111673;z-index:1000}.dialog.svelte-80vbit{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);padding:var(--space-5);min-width:min(24rem,calc(100vw - 2rem));max-width:min(32rem,calc(100vw - 2rem));overflow-wrap:anywhere;z-index:1010}.note.svelte-80vbit{background:var(--color-warn-bg);color:var(--color-warn);border-radius:var(--radius);padding:var(--space-2) var(--space-3);font-size:.9rem}.actions.svelte-80vbit{display:flex;justify-content:flex-end;gap:.5rem;margin-top:var(--space-4)}.log-card.svelte-15ufwrh{display:flex;flex-direction:column;gap:var(--space-3)}.header.svelte-15ufwrh{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}.logs.svelte-15ufwrh{max-height:24rem;font-size:.78rem;line-height:1.45;white-space:pre}.small.svelte-15ufwrh{font-size:.85rem}button.svelte-15ufwrh{display:inline-flex;align-items:center;gap:.375rem}.back.svelte-1eq4g96{font-size:.92rem}.page-header.svelte-1eq4g96{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:var(--space-3)}.page-header.svelte-1eq4g96 h2:where(.svelte-1eq4g96) code:where(.svelte-1eq4g96){word-break:break-all}.card-head.svelte-1eq4g96{display:flex;align-items:center;gap:.5rem}.card-head.svelte-1eq4g96 h3:where(.svelte-1eq4g96){margin:0}.state.svelte-1eq4g96{margin:0;font-weight:500}.small.svelte-1eq4g96{font-size:.85rem;margin:0}.error.svelte-1eq4g96{color:var(--color-danger)}.kv.svelte-1eq4g96{margin:var(--space-3) 0;display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1) var(--space-3);font-size:.92rem}.kv.svelte-1eq4g96>div:where(.svelte-1eq4g96){display:contents}.kv.svelte-1eq4g96 dt:where(.svelte-1eq4g96){color:var(--color-text-muted)}.kv.svelte-1eq4g96 dd:where(.svelte-1eq4g96){margin:0;min-width:0;overflow-wrap:anywhere}.actions.svelte-1eq4g96{display:flex;justify-content:flex-end;gap:.5rem;flex-wrap:wrap}.page-header.svelte-cshs6v{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:var(--space-3)}.page-header.svelte-cshs6v>div:where(.svelte-cshs6v){flex:1 1 20rem}.invitation.svelte-cshs6v p:where(.svelte-cshs6v){margin:0}.invitation.svelte-cshs6v textarea:where(.svelte-cshs6v){width:100%;box-sizing:border-box;font-family:var(--font-mono);font-size:.85rem;word-break:break-all}.node-head.svelte-cshs6v{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.node-head.svelte-cshs6v code:where(.svelte-cshs6v){word-break:break-all}.state.svelte-cshs6v{margin:0;font-weight:500}.small.svelte-cshs6v{font-size:.85rem;margin:0}.actions.svelte-cshs6v{display:flex;justify-content:flex-end;gap:.5rem;flex-wrap:wrap}.error.svelte-cshs6v{color:var(--color-danger)}.row.inline.svelte-1cl3wo6{gap:.5rem}.row.inline.svelte-1cl3wo6 input[type=checkbox]:where(.svelte-1cl3wo6),.row.inline.svelte-1cl3wo6 input[type=radio]:where(.svelte-1cl3wo6){width:auto}fieldset.svelte-1cl3wo6{border:none;padding:0;margin:0}legend.svelte-1cl3wo6{font-weight:600;margin-bottom:var(--space-1)}.banner.svelte-1cl3wo6{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3);border-radius:var(--radius);background:var(--color-info-bg);color:var(--color-info);border:1px solid var(--color-info);flex-wrap:wrap}.kv.svelte-1cl3wo6{margin:var(--space-3) 0;display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1) var(--space-3);font-size:.92rem}.kv.svelte-1cl3wo6>div:where(.svelte-1cl3wo6){display:contents}.kv.svelte-1cl3wo6 dt:where(.svelte-1cl3wo6){color:var(--color-text-muted)}.kv.svelte-1cl3wo6 dd:where(.svelte-1cl3wo6){margin:0}.copy-row.svelte-1cl3wo6{display:flex;align-items:center;gap:.375rem}.actions.svelte-1cl3wo6{display:flex;justify-content:flex-end}.small.svelte-1cl3wo6{font-size:.85rem}.error.svelte-1cl3wo6{color:var(--color-danger)}.toast-stack.svelte-g7yjw8{position:fixed;right:1rem;bottom:1rem;display:flex;flex-direction:column;gap:.5rem;max-width:min(30rem,calc(100vw - 2rem));z-index:1100}.toast.svelte-g7yjw8{background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border-strong);border-radius:var(--radius);padding:.625rem .75rem;display:flex;align-items:center;gap:.5rem;box-shadow:var(--shadow);font-size:.92rem}.toast-error.svelte-g7yjw8{border-color:var(--color-danger);background:var(--color-danger-bg);color:var(--color-danger)}.toast-success.svelte-g7yjw8{border-color:var(--color-success);background:var(--color-success-bg);color:var(--color-success)}.text.svelte-g7yjw8{flex:1 1 auto}button.svelte-g7yjw8{font-size:1.1rem;line-height:1;padding:.125rem .5rem;color:currentColor}.topbar.svelte-1r8vfx3{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);padding:var(--space-3) var(--space-5);background:var(--color-surface);border-bottom:1px solid var(--color-border);backdrop-filter:saturate(180%) blur(8px)}.brand.svelte-1r8vfx3{display:flex;align-items:center;gap:.6rem;font-weight:600}.logo.svelte-1r8vfx3{color:var(--color-accent);font-size:1.1rem}nav.svelte-1r8vfx3{display:flex;gap:.125rem}nav.svelte-1r8vfx3 a:where(.svelte-1r8vfx3){font-size:.92rem;color:var(--color-text-muted);padding:.375rem .75rem;border-radius:var(--radius);text-decoration:none}nav.svelte-1r8vfx3 a:where(.svelte-1r8vfx3):hover{background:var(--color-surface-alt);color:var(--color-text)}nav.svelte-1r8vfx3 a.active:where(.svelte-1r8vfx3){color:var(--color-accent-on);background:var(--color-accent)}main.svelte-1r8vfx3{flex:1 1 auto;width:min(64rem,100%);margin:0 auto;padding:var(--space-5)}@media(max-width:640px){.topbar.svelte-1r8vfx3{flex-direction:column;align-items:flex-start;gap:var(--space-2);padding:var(--space-2) var(--space-3)}nav.svelte-1r8vfx3{width:100%;overflow-x:auto}main.svelte-1r8vfx3{padding:var(--space-3)}}:root{color-scheme:light dark;--font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", Menlo, monospace;--radius-sm: .25rem;--radius: .5rem;--radius-lg: .75rem;--space-1: .25rem;--space-2: .5rem;--space-3: .75rem;--space-4: 1rem;--space-5: 1.5rem;--space-6: 2rem;--space-7: 3rem;--color-bg: #f7f8fa;--color-surface: #ffffff;--color-surface-alt: #f0f2f6;--color-border: #d9dde3;--color-border-strong: #b8bec7;--color-text: #1d1f24;--color-text-muted: #5b626d;--color-text-soft: #8a8f99;--color-accent: #1d4ed8;--color-accent-strong: #1e3a8a;--color-accent-on: #ffffff;--color-accent-soft: #e0e7ff;--color-success: #15803d;--color-success-bg: #dcfce7;--color-warn: #b45309;--color-warn-bg: #fef3c7;--color-danger: #b91c1c;--color-danger-bg: #fee2e2;--color-info: #1d4ed8;--color-info-bg: #dbeafe;--shadow-sm: 0 1px 2px rgba(15, 23, 42, .05);--shadow: 0 4px 12px rgba(15, 23, 42, .08);--shadow-lg: 0 12px 32px rgba(15, 23, 42, .16)}@media(prefers-color-scheme:dark){:root{--color-bg: #0f1116;--color-surface: #181b22;--color-surface-alt: #20242d;--color-border: #2c313c;--color-border-strong: #3b424f;--color-text: #e8eaf0;--color-text-muted: #a4abb8;--color-text-soft: #777e8b;--color-accent: #93c5fd;--color-accent-strong: #bfdbfe;--color-accent-on: #0f1116;--color-accent-soft: #1e293b;--color-success: #4ade80;--color-success-bg: #14532d;--color-warn: #fbbf24;--color-warn-bg: #78350f;--color-danger: #f87171;--color-danger-bg: #7f1d1d;--color-info: #93c5fd;--color-info-bg: #1e3a8a;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--shadow: 0 4px 12px rgba(0, 0, 0, .45);--shadow-lg: 0 12px 32px rgba(0, 0, 0, .6)}}*,*:before,*:after{box-sizing:border-box}html,body{margin:0;padding:0;background:var(--color-bg);color:var(--color-text);font-family:var(--font-sans);font-size:15px;line-height:1.5;-webkit-font-smoothing:antialiased;min-height:100vh}#app{min-height:100vh;display:flex;flex-direction:column}h1,h2,h3,h4,h5,h6{margin:0 0 var(--space-2) 0;font-weight:600;line-height:1.25;letter-spacing:-.01em}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.05rem}p{margin:0 0 var(--space-3) 0}a{color:var(--color-accent);text-decoration:none}a:hover{text-decoration:underline}button{font:inherit;cursor:pointer;border:1px solid var(--color-border-strong);background:var(--color-surface);color:var(--color-text);padding:var(--space-2) var(--space-3);border-radius:var(--radius);transition:background-color .12s ease,border-color .12s ease}button:hover:not(:disabled){background:var(--color-surface-alt);border-color:var(--color-text-muted)}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px}button:disabled{opacity:.55;cursor:not-allowed}button.primary{background:var(--color-accent);border-color:var(--color-accent);color:var(--color-accent-on)}button.primary:hover:not(:disabled){background:var(--color-accent-strong);border-color:var(--color-accent-strong)}button.danger{background:var(--color-danger);border-color:var(--color-danger);color:#fff}button.ghost{background:transparent;border-color:transparent;color:var(--color-text-muted);padding:var(--space-1) var(--space-2)}button.ghost:hover:not(:disabled){color:var(--color-text);background:var(--color-surface-alt)}input[type=text],input[type=url],input[type=number],input[type=password],select,textarea{font:inherit;color:var(--color-text);background:var(--color-surface);border:1px solid var(--color-border-strong);border-radius:var(--radius);padding:var(--space-2) var(--space-3);width:100%}label{display:block;font-size:.85rem;color:var(--color-text-muted);font-weight:500;margin-bottom:var(--space-1)}code,pre{font-family:var(--font-mono);font-size:.85rem}pre{background:var(--color-surface-alt);padding:var(--space-3);border-radius:var(--radius);overflow:auto;margin:0}hr{border:none;border-top:1px solid var(--color-border);margin:var(--space-5) 0}.card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:var(--space-5);box-shadow:var(--shadow-sm)}.muted{color:var(--color-text-muted)}.row{display:flex;gap:var(--space-3);align-items:center;flex-wrap:wrap}.stack{display:flex;flex-direction:column;gap:var(--space-3)}.grid{display:grid;gap:var(--space-4)}.badge{display:inline-flex;align-items:center;gap:var(--space-1);font-size:.78rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase;padding:.125rem .5rem;border-radius:999px;background:var(--color-surface-alt);color:var(--color-text-muted)}.badge.ok{background:var(--color-success-bg);color:var(--color-success)}.badge.warn{background:var(--color-warn-bg);color:var(--color-warn)}.badge.err{background:var(--color-danger-bg);color:var(--color-danger)}.badge.info{background:var(--color-info-bg);color:var(--color-info)}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}