@ouro.bot/cli 0.1.0-alpha.92 → 0.1.0-alpha.920

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 (716) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5819 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/README.txt +2997 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1254 -0
  34. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  35. package/deploy/unraid/sanctuary-replay-gate.mjs +1564 -0
  36. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  37. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -0
  38. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  39. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  40. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  41. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  42. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  43. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  44. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  45. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2231 -0
  46. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  49. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +33 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
  52. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  53. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  54. package/deploy/unraid/sanctuary.xml +30 -0
  55. package/dist/a2a/card.js +57 -0
  56. package/dist/a2a/client.js +250 -0
  57. package/dist/a2a/config.js +50 -0
  58. package/dist/a2a/delegated-command-grants.js +93 -0
  59. package/dist/a2a/delegated-command.js +197 -0
  60. package/dist/a2a/delegation-stores.js +56 -0
  61. package/dist/a2a/did-resolution.js +93 -0
  62. package/dist/a2a/escalation-grants.js +84 -0
  63. package/dist/a2a/escalation-wiring.js +60 -0
  64. package/dist/a2a/identity.js +258 -0
  65. package/dist/a2a/inbound-share.js +110 -0
  66. package/dist/a2a/mission-result-wire.js +196 -0
  67. package/dist/a2a/onboarding.js +133 -0
  68. package/dist/a2a/operator-trust.js +382 -0
  69. package/dist/a2a/outbox-client.js +57 -0
  70. package/dist/a2a/outbox-store.js +188 -0
  71. package/dist/a2a/outbox-wire.js +95 -0
  72. package/dist/a2a/pin-store.js +132 -0
  73. package/dist/a2a/replay-grant-holders.js +33 -0
  74. package/dist/a2a/replay-harness.js +188 -0
  75. package/dist/a2a/resolution-proof.js +53 -0
  76. package/dist/a2a/sealed-chat.js +113 -0
  77. package/dist/a2a/seen-ledger.js +120 -0
  78. package/dist/a2a/server.js +771 -0
  79. package/dist/a2a/task-store.js +69 -0
  80. package/dist/a2a/transport.js +45 -0
  81. package/dist/a2a/trust-commands.js +203 -0
  82. package/dist/a2a/trusted-files.js +185 -0
  83. package/dist/a2a/types.js +3 -0
  84. package/dist/arc/attention-types.js +8 -0
  85. package/dist/arc/cares.js +360 -0
  86. package/dist/arc/episodes.js +118 -0
  87. package/dist/arc/evolution.js +490 -0
  88. package/dist/arc/flight-recorder.js +1034 -0
  89. package/dist/arc/intentions.js +134 -0
  90. package/dist/arc/json-store.js +117 -0
  91. package/dist/arc/obligations.js +386 -0
  92. package/dist/arc/packets.js +336 -0
  93. package/dist/arc/presence.js +185 -0
  94. package/dist/arc/task-lifecycle.js +57 -0
  95. package/dist/commerce/store.js +755 -0
  96. package/dist/commerce/types.js +3 -0
  97. package/dist/heart/active-work.js +798 -40
  98. package/dist/heart/agent-entry.js +252 -3
  99. package/dist/heart/approval-files.js +113 -0
  100. package/dist/heart/approval-store.js +960 -0
  101. package/dist/heart/attachments/image-normalize.js +194 -0
  102. package/dist/heart/attachments/materialize.js +97 -0
  103. package/dist/heart/attachments/originals.js +88 -0
  104. package/dist/heart/attachments/render.js +29 -0
  105. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  106. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  107. package/dist/heart/attachments/sources/index.js +18 -0
  108. package/dist/heart/attachments/sources/telegram.js +71 -0
  109. package/dist/heart/attachments/store.js +132 -0
  110. package/dist/heart/attachments/types.js +93 -0
  111. package/dist/heart/auth/auth-flow.js +495 -0
  112. package/dist/heart/autonomy-budget.js +478 -0
  113. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  114. package/dist/heart/awaiting/await-alert.js +152 -0
  115. package/dist/heart/awaiting/await-expiry.js +143 -0
  116. package/dist/heart/awaiting/await-loader.js +91 -0
  117. package/dist/heart/awaiting/await-parser.js +152 -0
  118. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  119. package/dist/heart/awaiting/await-scheduler.js +391 -0
  120. package/dist/heart/background-operations.js +281 -0
  121. package/dist/heart/bluebubbles-host-account.js +78 -0
  122. package/dist/heart/bridges/manager.js +137 -17
  123. package/dist/heart/bridges/store.js +14 -2
  124. package/dist/heart/bundle-state.js +168 -0
  125. package/dist/heart/commitments.js +44 -18
  126. package/dist/heart/config-registry.js +331 -0
  127. package/dist/heart/config.js +174 -131
  128. package/dist/heart/context-loss-gauntlet.js +387 -0
  129. package/dist/heart/context-loss-sentinel.js +1159 -0
  130. package/dist/heart/core.js +2364 -578
  131. package/dist/heart/cross-chat-delivery.js +9 -22
  132. package/dist/heart/daemon/agent-config-check.js +451 -0
  133. package/dist/heart/daemon/agent-discovery.js +283 -3
  134. package/dist/heart/daemon/agent-home.js +319 -0
  135. package/dist/heart/daemon/agent-service.js +542 -0
  136. package/dist/heart/daemon/agentic-repair.js +547 -0
  137. package/dist/heart/daemon/await-private-wake.js +59 -0
  138. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  139. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  140. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  141. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  142. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  143. package/dist/heart/daemon/cadence.js +180 -0
  144. package/dist/heart/daemon/cli-arg-redaction.js +26 -0
  145. package/dist/heart/daemon/cli-defaults.js +876 -0
  146. package/dist/heart/daemon/cli-desk.js +322 -0
  147. package/dist/heart/daemon/cli-exec.js +9199 -0
  148. package/dist/heart/daemon/cli-help.js +735 -0
  149. package/dist/heart/daemon/cli-parse.js +3211 -0
  150. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  151. package/dist/heart/daemon/cli-render.js +819 -0
  152. package/dist/heart/daemon/cli-types.js +8 -0
  153. package/dist/heart/daemon/connect-bay.js +323 -0
  154. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  155. package/dist/heart/daemon/container-healthcheck.js +112 -0
  156. package/dist/heart/daemon/container-runtime.js +97 -0
  157. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  158. package/dist/heart/daemon/container-spec-auditor.js +235 -0
  159. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  160. package/dist/heart/daemon/daemon-cli.js +29 -2350
  161. package/dist/heart/daemon/daemon-entry.js +953 -11
  162. package/dist/heart/daemon/daemon-health.js +186 -0
  163. package/dist/heart/daemon/daemon-rollup.js +57 -0
  164. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  165. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  166. package/dist/heart/daemon/daemon.js +2084 -105
  167. package/dist/heart/daemon/dns-workflow.js +394 -0
  168. package/dist/heart/daemon/doctor-types.js +8 -0
  169. package/dist/heart/daemon/doctor.js +1766 -0
  170. package/dist/heart/daemon/freshness.js +345 -0
  171. package/dist/heart/daemon/habit-private-wake.js +61 -0
  172. package/dist/heart/daemon/health-monitor.js +154 -11
  173. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  174. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  175. package/dist/heart/daemon/http-health-probe.js +80 -0
  176. package/dist/heart/daemon/human-command-screens.js +234 -0
  177. package/dist/heart/daemon/human-readiness.js +114 -0
  178. package/dist/heart/daemon/inner-status.js +78 -0
  179. package/dist/heart/daemon/interactive-repair.js +394 -0
  180. package/dist/heart/daemon/launchd.js +37 -8
  181. package/dist/heart/daemon/log-tailer.js +79 -10
  182. package/dist/heart/daemon/logs-prune.js +132 -0
  183. package/dist/heart/daemon/mcp-canary.js +524 -0
  184. package/dist/heart/daemon/message-router.js +65 -5
  185. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  186. package/dist/heart/daemon/os-cron-deps.js +135 -0
  187. package/dist/heart/daemon/os-cron.js +22 -14
  188. package/dist/heart/daemon/ouro-bot-entry.js +6 -3
  189. package/dist/heart/daemon/ouro-entry.js +5 -2
  190. package/dist/heart/daemon/plugin-cli.js +432 -0
  191. package/dist/heart/daemon/process-manager.js +760 -61
  192. package/dist/heart/daemon/provider-discovery.js +137 -0
  193. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  194. package/dist/heart/daemon/prunable-bundle.js +144 -0
  195. package/dist/heart/daemon/pulse.js +511 -0
  196. package/dist/heart/daemon/readiness-repair.js +365 -0
  197. package/dist/heart/daemon/run-hooks.js +2 -0
  198. package/dist/heart/daemon/runtime-logging.js +47 -14
  199. package/dist/heart/daemon/runtime-metadata.js +2 -30
  200. package/dist/heart/daemon/runtime-mode.js +13 -2
  201. package/dist/heart/daemon/safe-mode.js +161 -0
  202. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  203. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  204. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  205. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  206. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  207. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  208. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  209. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  210. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1267 -0
  211. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  212. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  213. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  214. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  215. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  216. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  217. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  218. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  219. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  220. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  221. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  222. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  223. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  224. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  225. package/dist/heart/daemon/sense-manager.js +733 -48
  226. package/dist/heart/daemon/session-id-resolver.js +131 -0
  227. package/dist/heart/daemon/skill-management-installer.js +1 -1
  228. package/dist/heart/daemon/socket-client.js +180 -12
  229. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  230. package/dist/heart/daemon/startup-tui.js +339 -0
  231. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  232. package/dist/heart/daemon/task-scheduler.js +117 -39
  233. package/dist/heart/daemon/terminal-ui.js +503 -0
  234. package/dist/heart/daemon/thoughts.js +138 -54
  235. package/dist/heart/daemon/up-progress.js +366 -0
  236. package/dist/heart/daemon/vault-items.js +56 -0
  237. package/dist/heart/delegation.js +1 -4
  238. package/dist/heart/external-events/router.js +1516 -0
  239. package/dist/heart/failure-reports.js +336 -0
  240. package/dist/heart/file-lock.js +109 -0
  241. package/dist/heart/frontend-approval-runtime.js +506 -0
  242. package/dist/heart/frontend-journal.js +215 -0
  243. package/dist/heart/frontend-session-service.js +237 -0
  244. package/dist/heart/frontend-socket-client.js +164 -0
  245. package/dist/heart/frontend-socket.js +400 -0
  246. package/dist/heart/habits/habit-cancel.js +810 -0
  247. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  248. package/dist/heart/habits/habit-migration.js +194 -0
  249. package/dist/heart/habits/habit-parser.js +278 -0
  250. package/dist/heart/habits/habit-runtime-state.js +93 -0
  251. package/dist/heart/habits/habit-scheduler.js +653 -0
  252. package/dist/heart/habits/habit-session-summary.js +318 -0
  253. package/dist/heart/habits/habit-session.js +636 -0
  254. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  255. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  256. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  257. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  258. package/dist/heart/identity.js +230 -59
  259. package/dist/heart/kept-notes.js +289 -0
  260. package/dist/heart/kicks.js +1 -1
  261. package/dist/heart/machine-identity.js +175 -0
  262. package/dist/heart/mail-import-discovery.js +356 -0
  263. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  264. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  265. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  266. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  267. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  268. package/dist/heart/mailbox/mailbox-http.js +99 -0
  269. package/dist/heart/mailbox/mailbox-read.js +39 -0
  270. package/dist/heart/mailbox/mailbox-types.js +27 -0
  271. package/dist/heart/mailbox/mailbox-view.js +197 -0
  272. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  273. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  274. package/dist/heart/mailbox/readers/mail.js +375 -0
  275. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  276. package/dist/heart/mailbox/readers/sessions.js +231 -0
  277. package/dist/heart/mailbox/readers/shared.js +111 -0
  278. package/dist/heart/mcp/mcp-server.js +696 -0
  279. package/dist/heart/migrate-config.js +100 -0
  280. package/dist/heart/model-capabilities.js +83 -16
  281. package/dist/heart/orientation-frame.js +345 -0
  282. package/dist/heart/platform.js +81 -0
  283. package/dist/heart/primitives.js +1 -1
  284. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  285. package/dist/heart/private-runtime/index.js +18 -0
  286. package/dist/heart/private-runtime/ledger.js +221 -0
  287. package/dist/heart/private-runtime/policy.js +260 -0
  288. package/dist/heart/private-runtime/types.js +2 -0
  289. package/dist/heart/progress-story.js +1 -1
  290. package/dist/heart/provider-attempt.js +137 -0
  291. package/dist/heart/provider-binding-resolver.js +273 -0
  292. package/dist/heart/provider-credentials.js +449 -0
  293. package/dist/heart/provider-failover.js +311 -0
  294. package/dist/heart/provider-models.js +96 -0
  295. package/dist/heart/provider-ping.js +265 -0
  296. package/dist/heart/provider-readiness-cache.js +119 -0
  297. package/dist/heart/provider-visibility.js +188 -0
  298. package/dist/heart/providers/anthropic-token.js +131 -0
  299. package/dist/heart/providers/anthropic.js +173 -60
  300. package/dist/heart/providers/azure.js +23 -11
  301. package/dist/heart/providers/error-classification.js +127 -0
  302. package/dist/heart/providers/github-copilot.js +38 -39
  303. package/dist/heart/providers/minimax-vlm.js +189 -0
  304. package/dist/heart/providers/minimax.js +26 -8
  305. package/dist/heart/providers/openai-codex-token.js +349 -0
  306. package/dist/heart/providers/openai-codex.js +55 -40
  307. package/dist/heart/providers/openai-compatible.js +177 -0
  308. package/dist/heart/reply-style.js +52 -0
  309. package/dist/heart/run-ledger.js +247 -0
  310. package/dist/heart/runtime-capability-check.js +170 -0
  311. package/dist/heart/runtime-credentials.js +607 -0
  312. package/dist/heart/runtime-cwd.js +87 -0
  313. package/dist/heart/sense-truth.js +24 -4
  314. package/dist/heart/session-activity.js +92 -24
  315. package/dist/heart/session-events.js +1504 -0
  316. package/dist/heart/session-playback-cli-main.js +5 -0
  317. package/dist/heart/session-playback-cli.js +36 -0
  318. package/dist/heart/session-playback.js +231 -0
  319. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  320. package/dist/heart/session-redaction-repair.js +552 -0
  321. package/dist/heart/session-stats-cli-main.js +5 -0
  322. package/dist/heart/session-stats.js +183 -0
  323. package/dist/heart/session-transcript.js +133 -0
  324. package/dist/heart/shelf-claims.js +78 -0
  325. package/dist/heart/shepherd-config.js +113 -0
  326. package/dist/heart/source-grounding.js +297 -0
  327. package/dist/heart/start-of-turn-packet.js +372 -0
  328. package/dist/heart/steward-policy.js +656 -0
  329. package/dist/heart/streaming.js +609 -207
  330. package/dist/heart/structured-output.js +196 -0
  331. package/dist/heart/sync-classification.js +176 -0
  332. package/dist/heart/sync-health.js +152 -0
  333. package/dist/heart/sync.js +726 -0
  334. package/dist/heart/target-resolution.js +11 -7
  335. package/dist/heart/tempo.js +93 -0
  336. package/dist/heart/temporal-view.js +41 -0
  337. package/dist/heart/timeouts.js +101 -0
  338. package/dist/heart/tool-activity-callbacks.js +59 -0
  339. package/dist/heart/tool-approval.js +382 -0
  340. package/dist/heart/tool-description.js +155 -0
  341. package/dist/heart/tool-friction.js +55 -0
  342. package/dist/heart/tool-loop.js +206 -0
  343. package/dist/heart/turn-context.js +496 -0
  344. package/dist/heart/turn-execution-lease.js +30 -0
  345. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  346. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
  347. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  348. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  349. package/dist/heart/versioning/ouro-version-manager.js +432 -0
  350. package/dist/heart/versioning/release-sources.js +173 -0
  351. package/dist/heart/versioning/self-update-defaults.js +294 -0
  352. package/dist/heart/versioning/self-update.js +196 -0
  353. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  354. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  355. package/dist/heart/versioning/update-hooks.js +154 -0
  356. package/dist/heart/versioning/update-state.js +126 -0
  357. package/dist/heart/versioning/updater-launchd.js +150 -0
  358. package/dist/heart/versioning/version-intent.js +114 -0
  359. package/dist/heart/work-card.js +380 -0
  360. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  361. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  362. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  363. package/dist/mailbox-ui/index.html +16 -0
  364. package/dist/mailroom/attention.js +167 -0
  365. package/dist/mailroom/autonomy.js +209 -0
  366. package/dist/mailroom/blob-store.js +889 -0
  367. package/dist/mailroom/body-cache.js +61 -0
  368. package/dist/mailroom/cache-sync-cli.js +58 -0
  369. package/dist/mailroom/core.js +803 -0
  370. package/dist/mailroom/entry.js +160 -0
  371. package/dist/mailroom/file-store.js +568 -0
  372. package/dist/mailroom/hosted-cache-sync.js +384 -0
  373. package/dist/mailroom/mbox-import.js +393 -0
  374. package/dist/mailroom/migration.js +164 -0
  375. package/dist/mailroom/outbound.js +380 -0
  376. package/dist/mailroom/policy.js +263 -0
  377. package/dist/mailroom/reader.js +292 -0
  378. package/dist/mailroom/search-cache.js +513 -0
  379. package/dist/mailroom/search-relevance.js +319 -0
  380. package/dist/mailroom/smtp-ingress.js +176 -0
  381. package/dist/mailroom/source-state.js +176 -0
  382. package/dist/mailroom/thread.js +109 -0
  383. package/dist/mailroom/travel-extract.js +89 -0
  384. package/dist/mind/bundle-manifest.js +24 -2
  385. package/dist/mind/context.js +307 -139
  386. package/dist/mind/desk-section.js +362 -0
  387. package/dist/mind/diary-integrity.js +60 -0
  388. package/dist/mind/{memory.js → diary.js} +68 -77
  389. package/dist/mind/embedding-provider.js +60 -0
  390. package/dist/mind/file-state.js +179 -0
  391. package/dist/mind/friend-link-codes.js +209 -0
  392. package/dist/mind/friend-merge.js +330 -0
  393. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  394. package/dist/mind/obligation-steering.js +199 -3
  395. package/dist/mind/pending.js +36 -10
  396. package/dist/mind/prompt-budget.js +479 -0
  397. package/dist/mind/prompt-refresh.js +3 -2
  398. package/dist/mind/prompt.js +1085 -198
  399. package/dist/mind/provenance-trust.js +26 -0
  400. package/dist/mind/record-paths.js +312 -0
  401. package/dist/mind/scrutiny.js +173 -0
  402. package/dist/mind/session-transaction.js +564 -0
  403. package/dist/nerves/cli-logging.js +7 -1
  404. package/dist/nerves/coverage/audit-rules.js +15 -6
  405. package/dist/nerves/coverage/audit.js +28 -2
  406. package/dist/nerves/coverage/cli.js +1 -1
  407. package/dist/nerves/coverage/contract.js +5 -5
  408. package/dist/nerves/coverage/file-completeness.js +139 -5
  409. package/dist/nerves/coverage/run-artifacts.js +55 -35
  410. package/dist/nerves/coverage/source-scanner.js +4 -4
  411. package/dist/nerves/event-buffer.js +111 -0
  412. package/dist/nerves/index.js +293 -9
  413. package/dist/nerves/observation.js +20 -0
  414. package/dist/nerves/redact.js +79 -0
  415. package/dist/nerves/review/cli-main.js +5 -0
  416. package/dist/nerves/review/cli.js +156 -0
  417. package/dist/nerves/review/core.js +159 -0
  418. package/dist/nerves/runtime.js +17 -1
  419. package/dist/repertoire/ado-client.js +15 -56
  420. package/dist/repertoire/ado-semantic.js +16 -10
  421. package/dist/repertoire/api-client.js +97 -0
  422. package/dist/repertoire/bitwarden-store.js +1201 -0
  423. package/dist/repertoire/bundle-templates.js +71 -0
  424. package/dist/repertoire/bw-installer.js +231 -0
  425. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  426. package/dist/repertoire/coding/context-pack.js +331 -0
  427. package/dist/repertoire/coding/feedback.js +174 -32
  428. package/dist/repertoire/coding/index.js +15 -3
  429. package/dist/repertoire/coding/manager.js +159 -10
  430. package/dist/repertoire/coding/spawner.js +40 -11
  431. package/dist/repertoire/coding/tools.js +182 -18
  432. package/dist/repertoire/coding/workbench-client.js +272 -0
  433. package/dist/repertoire/coding/workbench-manager.js +346 -0
  434. package/dist/repertoire/commerce-errors.js +109 -0
  435. package/dist/repertoire/commerce-self-test.js +156 -0
  436. package/dist/repertoire/credential-access.js +183 -0
  437. package/dist/repertoire/desk/classifier.js +362 -0
  438. package/dist/repertoire/duffel-client.js +185 -0
  439. package/dist/repertoire/github-client.js +14 -55
  440. package/dist/repertoire/graph-client.js +11 -52
  441. package/dist/repertoire/guardrails.js +968 -20
  442. package/dist/repertoire/house-sweep.js +469 -0
  443. package/dist/repertoire/mcp-client.js +58 -5
  444. package/dist/repertoire/mcp-manager.js +427 -139
  445. package/dist/repertoire/mcp-tools.js +132 -0
  446. package/dist/repertoire/mcp-write-guard.js +46 -0
  447. package/dist/repertoire/plugin-mcp.js +175 -0
  448. package/dist/repertoire/plugins.js +253 -0
  449. package/dist/repertoire/relationship-authorization.js +322 -0
  450. package/dist/repertoire/sanctuary-container-policy.js +46 -0
  451. package/dist/repertoire/shell-sessions.js +134 -0
  452. package/dist/repertoire/skills.js +48 -4
  453. package/dist/repertoire/stripe-client.js +131 -0
  454. package/dist/repertoire/tool-arguments.js +182 -0
  455. package/dist/repertoire/tool-results.js +29 -0
  456. package/dist/repertoire/tools-a2a.js +699 -0
  457. package/dist/repertoire/tools-attachments.js +322 -0
  458. package/dist/repertoire/tools-awaiting.js +872 -0
  459. package/dist/repertoire/tools-base.js +83 -1168
  460. package/dist/repertoire/tools-bluebubbles.js +2 -0
  461. package/dist/repertoire/tools-bridge.js +144 -0
  462. package/dist/repertoire/tools-bundle.js +995 -0
  463. package/dist/repertoire/tools-commerce.js +253 -0
  464. package/dist/repertoire/tools-config.js +186 -0
  465. package/dist/repertoire/tools-continuity.js +575 -0
  466. package/dist/repertoire/tools-credential.js +383 -0
  467. package/dist/repertoire/tools-escalation.js +84 -0
  468. package/dist/repertoire/tools-evolution.js +527 -0
  469. package/dist/repertoire/tools-files.js +344 -0
  470. package/dist/repertoire/tools-flight.js +290 -0
  471. package/dist/repertoire/tools-flow.js +119 -0
  472. package/dist/repertoire/tools-friend-link.js +57 -0
  473. package/dist/repertoire/tools-github.js +3 -8
  474. package/dist/repertoire/tools-habits.js +103 -0
  475. package/dist/repertoire/tools-house-care.js +174 -0
  476. package/dist/repertoire/tools-mail.js +1828 -0
  477. package/dist/repertoire/tools-notes.js +496 -0
  478. package/dist/repertoire/tools-obligations.js +182 -0
  479. package/dist/repertoire/tools-orientation.js +31 -0
  480. package/dist/repertoire/tools-record.js +482 -0
  481. package/dist/repertoire/tools-rsvp.js +139 -0
  482. package/dist/repertoire/tools-runtime.js +238 -0
  483. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  484. package/dist/repertoire/tools-session.js +1133 -0
  485. package/dist/repertoire/tools-shell.js +149 -0
  486. package/dist/repertoire/tools-shepherd.js +262 -0
  487. package/dist/repertoire/tools-steward-policy.js +147 -0
  488. package/dist/repertoire/tools-stripe.js +224 -0
  489. package/dist/repertoire/tools-surface.js +369 -0
  490. package/dist/repertoire/tools-teams.js +12 -39
  491. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  492. package/dist/repertoire/tools-travel.js +125 -0
  493. package/dist/repertoire/tools-trip.js +982 -0
  494. package/dist/repertoire/tools-unraid.js +556 -0
  495. package/dist/repertoire/tools-user-profile.js +146 -0
  496. package/dist/repertoire/tools-vault.js +40 -0
  497. package/dist/repertoire/tools-voice-local.js +198 -0
  498. package/dist/repertoire/tools-voice.js +145 -0
  499. package/dist/repertoire/tools.js +514 -156
  500. package/dist/repertoire/travel-api-client.js +360 -0
  501. package/dist/repertoire/unraid-client.js +155 -0
  502. package/dist/repertoire/unraid-restart.js +339 -0
  503. package/dist/repertoire/user-profile.js +131 -0
  504. package/dist/repertoire/vault-setup.js +246 -0
  505. package/dist/repertoire/vault-unlock.js +686 -0
  506. package/dist/rsvp/aisleplanner-client.js +354 -0
  507. package/dist/rsvp/cli.js +936 -0
  508. package/dist/rsvp/config.js +327 -0
  509. package/dist/rsvp/cutover.js +433 -0
  510. package/dist/rsvp/diagnostics.js +232 -0
  511. package/dist/rsvp/diff-renderer.js +176 -0
  512. package/dist/rsvp/habit-policy.js +110 -0
  513. package/dist/rsvp/habit-stage.js +123 -0
  514. package/dist/rsvp/incident-bundle.js +97 -0
  515. package/dist/rsvp/migration.js +204 -0
  516. package/dist/rsvp/native-habit-runner.js +630 -0
  517. package/dist/rsvp/outbound-state.js +628 -0
  518. package/dist/rsvp/query.js +118 -0
  519. package/dist/rsvp/replay.js +233 -0
  520. package/dist/rsvp/snapshot.js +232 -0
  521. package/dist/rsvp/spend-ledger.js +175 -0
  522. package/dist/scripts/claude-code-hook.js +41 -0
  523. package/dist/scripts/claude-code-stop-hook.js +47 -0
  524. package/dist/senses/a2a-entry.js +132 -0
  525. package/dist/senses/acp-server.js +386 -0
  526. package/dist/senses/attention-queue.js +186 -0
  527. package/dist/senses/await-turn-message.js +65 -0
  528. package/dist/senses/bluebubbles/active-turns.js +216 -0
  529. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  530. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  531. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +379 -41
  532. package/dist/senses/bluebubbles/context-packet.js +207 -0
  533. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  534. package/dist/senses/bluebubbles/entry.js +90 -0
  535. package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
  536. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  537. package/dist/senses/bluebubbles/index.js +3878 -0
  538. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  539. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  540. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  541. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  542. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  543. package/dist/senses/bluebubbles/processed-log.js +133 -0
  544. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  545. package/dist/senses/bluebubbles/replay.js +284 -0
  546. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  547. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  548. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  549. package/dist/senses/bluebubbles/webhook-registration.js +257 -0
  550. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  551. package/dist/senses/cli/bracketed-paste.js +82 -0
  552. package/dist/senses/cli/image-paste.js +287 -0
  553. package/dist/senses/cli/image-ref-navigation.js +75 -0
  554. package/dist/senses/cli/ink-app.js +156 -0
  555. package/dist/senses/cli/inline-diff.js +64 -0
  556. package/dist/senses/cli/input-keys.js +174 -0
  557. package/dist/senses/cli/kill-ring.js +86 -0
  558. package/dist/senses/cli/message-list.js +51 -0
  559. package/dist/senses/cli/ouro-tui.js +607 -0
  560. package/dist/senses/cli/spinner-imperative.js +135 -0
  561. package/dist/senses/cli/spinner.js +101 -0
  562. package/dist/senses/cli/status-line.js +60 -0
  563. package/dist/senses/cli/streaming-markdown.js +526 -0
  564. package/dist/senses/cli/tool-display.js +85 -0
  565. package/dist/senses/cli/tool-render.js +85 -0
  566. package/dist/senses/cli/tui-store.js +241 -0
  567. package/dist/senses/cli/virtual-list.js +35 -0
  568. package/dist/senses/cli-entry.js +60 -8
  569. package/dist/senses/cli.js +601 -304
  570. package/dist/senses/commands.js +66 -3
  571. package/dist/senses/context-packet-ledger.js +371 -0
  572. package/dist/senses/context-packets.js +154 -0
  573. package/dist/senses/habit-lifecycle-guard.js +24 -0
  574. package/dist/senses/habit-turn-message.js +160 -0
  575. package/dist/senses/ingress-evidence.js +2 -0
  576. package/dist/senses/mail-entry.js +66 -0
  577. package/dist/senses/mail.js +524 -0
  578. package/dist/senses/pipeline.js +1158 -204
  579. package/dist/senses/private-runtime-worker.js +859 -0
  580. package/dist/senses/private-runtime.js +1627 -0
  581. package/dist/senses/proactive-content-guard.js +51 -0
  582. package/dist/senses/root-host-approval-port.js +345 -0
  583. package/dist/senses/root-host-approval-runtime.js +393 -0
  584. package/dist/senses/sanctuary-authority-resident.js +102 -0
  585. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  586. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  587. package/dist/senses/sanctuary-grounding.js +118 -0
  588. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  589. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  590. package/dist/senses/sanctuary-health-runner.js +104 -0
  591. package/dist/senses/sanctuary-health.js +422 -0
  592. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  593. package/dist/senses/sanctuary-interactive-control.js +410 -0
  594. package/dist/senses/sanctuary-media-catalog-contract.js +259 -0
  595. package/dist/senses/sanctuary-media-optimization.js +514 -0
  596. package/dist/senses/sanctuary-runtime.js +369 -0
  597. package/dist/senses/sanctuary-sab.js +85 -0
  598. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  599. package/dist/senses/shared-turn.js +793 -0
  600. package/dist/senses/shepherd/client.js +196 -0
  601. package/dist/senses/shepherd/cmux.js +344 -0
  602. package/dist/senses/shepherd/herdr.js +315 -0
  603. package/dist/senses/shepherd/host.js +14 -0
  604. package/dist/senses/shepherd/judge.js +137 -0
  605. package/dist/senses/shepherd/owner-notice.js +245 -0
  606. package/dist/senses/shepherd/redact.js +66 -0
  607. package/dist/senses/shepherd/returns.js +79 -0
  608. package/dist/senses/shepherd/sense.js +309 -0
  609. package/dist/senses/shepherd-entry.js +78 -0
  610. package/dist/senses/surface-tool.js +109 -0
  611. package/dist/senses/teams-entry.js +68 -8
  612. package/dist/senses/teams.js +598 -233
  613. package/dist/senses/telegram-admission.js +718 -0
  614. package/dist/senses/telegram-approval-runtime.js +793 -0
  615. package/dist/senses/telegram-attachments.js +186 -0
  616. package/dist/senses/telegram-audit-ledger.js +220 -0
  617. package/dist/senses/telegram-authority-transport.js +231 -0
  618. package/dist/senses/telegram-client.js +1749 -0
  619. package/dist/senses/telegram-effect-adapter.js +900 -0
  620. package/dist/senses/telegram-entry.js +83 -0
  621. package/dist/senses/telegram-handoff.js +80 -0
  622. package/dist/senses/telegram.js +2405 -0
  623. package/dist/senses/trust-gate.js +104 -9
  624. package/dist/senses/voice/audio-playback.js +237 -0
  625. package/dist/senses/voice/audio-routing.js +119 -0
  626. package/dist/senses/voice/call-auth.js +250 -0
  627. package/dist/senses/voice/elevenlabs.js +202 -0
  628. package/dist/senses/voice/floor-control.js +431 -0
  629. package/dist/senses/voice/floor-controller.js +115 -0
  630. package/dist/senses/voice/golden-path.js +116 -0
  631. package/dist/senses/voice/index.js +29 -0
  632. package/dist/senses/voice/local-audio-control.js +344 -0
  633. package/dist/senses/voice/local-audio-devices.js +516 -0
  634. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  635. package/dist/senses/voice/local-audio-identity.js +103 -0
  636. package/dist/senses/voice/local-audio-join.js +325 -0
  637. package/dist/senses/voice/local-audio-mute.js +199 -0
  638. package/dist/senses/voice/local-audio-notify.js +121 -0
  639. package/dist/senses/voice/local-audio-prompts.js +116 -0
  640. package/dist/senses/voice/local-audio-transport.js +427 -0
  641. package/dist/senses/voice/local-audio.js +281 -0
  642. package/dist/senses/voice/local-media-stream.js +145 -0
  643. package/dist/senses/voice/meeting.js +113 -0
  644. package/dist/senses/voice/outbound.js +190 -0
  645. package/dist/senses/voice/phone.js +33 -0
  646. package/dist/senses/voice/playback.js +139 -0
  647. package/dist/senses/voice/process-guards.js +51 -0
  648. package/dist/senses/voice/realtime-eval.js +496 -0
  649. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  650. package/dist/senses/voice/realtime-trace.js +531 -0
  651. package/dist/senses/voice/transcript.js +70 -0
  652. package/dist/senses/voice/turn.js +191 -0
  653. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  654. package/dist/senses/voice/twilio-phone.js +5454 -0
  655. package/dist/senses/voice/types.js +2 -0
  656. package/dist/senses/voice/whisper.js +161 -0
  657. package/dist/senses/voice-entry.js +83 -0
  658. package/dist/senses/voice-realtime-eval-command.js +99 -0
  659. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  660. package/dist/senses/voice-twilio-entry.js +87 -0
  661. package/dist/trips/core.js +138 -0
  662. package/dist/trips/store.js +265 -0
  663. package/dist/util/frontmatter.js +69 -0
  664. package/npm-shrinkwrap.json +8100 -0
  665. package/package.json +74 -13
  666. package/skills/agent-commerce.md +113 -0
  667. package/skills/browser-navigation.md +117 -0
  668. package/skills/commerce-setup-guide.md +116 -0
  669. package/skills/commerce-setup.md +84 -0
  670. package/skills/configure-dev-tools.md +99 -0
  671. package/skills/travel-planning.md +138 -0
  672. package/dist/heart/daemon/auth-flow.js +0 -430
  673. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  674. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  675. package/dist/heart/daemon/update-hooks.js +0 -138
  676. package/dist/heart/obligations.js +0 -191
  677. package/dist/heart/safe-workspace.js +0 -362
  678. package/dist/heart/session-recall.js +0 -116
  679. package/dist/mind/friends/channel.js +0 -84
  680. package/dist/mind/friends/group-context.js +0 -144
  681. package/dist/mind/friends/resolver.js +0 -84
  682. package/dist/mind/friends/store-file.js +0 -190
  683. package/dist/mind/friends/store.js +0 -4
  684. package/dist/mind/friends/tokens.js +0 -26
  685. package/dist/mind/friends/trust-explanation.js +0 -74
  686. package/dist/mind/friends/types.js +0 -29
  687. package/dist/repertoire/tasks/board.js +0 -134
  688. package/dist/repertoire/tasks/index.js +0 -224
  689. package/dist/repertoire/tasks/lifecycle.js +0 -80
  690. package/dist/repertoire/tasks/middleware.js +0 -65
  691. package/dist/repertoire/tasks/parser.js +0 -173
  692. package/dist/repertoire/tasks/scanner.js +0 -132
  693. package/dist/repertoire/tasks/transitions.js +0 -144
  694. package/dist/senses/bluebubbles-entry.js +0 -13
  695. package/dist/senses/bluebubbles.js +0 -1181
  696. package/dist/senses/debug-activity.js +0 -154
  697. package/dist/senses/inner-dialog-worker.js +0 -90
  698. package/dist/senses/inner-dialog.js +0 -525
  699. package/subagents/README.md +0 -7
  700. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  701. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  702. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  703. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  704. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  705. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  706. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  707. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  708. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  709. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  710. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  711. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  712. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  713. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  714. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  715. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  716. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canonicalAuthorityJson = canonicalAuthorityJson;
4
+ exports.authorityArtifactDigest = authorityArtifactDigest;
5
+ exports.signAuthorityPayload = signAuthorityPayload;
6
+ exports.verifyAuthorityPayload = verifyAuthorityPayload;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const runtime_1 = require("../../nerves/runtime");
9
+ const ARTIFACT_KEYS = ["domain", "keyId", "payload", "schemaVersion", "signature"];
10
+ const BASE64URL_SIGNATURE = /^[A-Za-z0-9_-]{86}$/u;
11
+ function invalidCanonicalJson() {
12
+ throw new Error("canonical authority JSON value is invalid");
13
+ }
14
+ function canonicalAuthorityJson(value) {
15
+ if (value === null || typeof value === "boolean" || typeof value === "string")
16
+ return JSON.stringify(value);
17
+ if (typeof value === "number") {
18
+ if (!Number.isSafeInteger(value) || Object.is(value, -0))
19
+ return invalidCanonicalJson();
20
+ return JSON.stringify(value);
21
+ }
22
+ if (Array.isArray(value)) {
23
+ const entries = [];
24
+ for (let index = 0; index < value.length; index += 1) {
25
+ if (!(index in value))
26
+ return invalidCanonicalJson();
27
+ entries.push(canonicalAuthorityJson(value[index]));
28
+ }
29
+ return `[${entries.join(",")}]`;
30
+ }
31
+ if (typeof value !== "object" || Object.getPrototypeOf(value) !== Object.prototype)
32
+ return invalidCanonicalJson();
33
+ const record = value;
34
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalAuthorityJson(record[key])}`).join(",")}}`;
35
+ }
36
+ function signingBytes(domain, payload) {
37
+ if (!domain)
38
+ throw new Error("authority domain is invalid");
39
+ return Buffer.from(`ouro.sanctuary.authority.v1\0${domain}\0${canonicalAuthorityJson(payload)}`, "utf8");
40
+ }
41
+ function authorityArtifactDigest(domain, payload) {
42
+ return `sha256:${(0, node_crypto_1.createHash)("sha256").update(signingBytes(domain, payload)).digest("hex")}`;
43
+ }
44
+ function signAuthorityPayload(input) {
45
+ if (!input.keyId)
46
+ throw new Error("authority key id is invalid");
47
+ return {
48
+ schemaVersion: 1,
49
+ domain: input.domain,
50
+ keyId: input.keyId,
51
+ payload: input.payload,
52
+ signature: (0, node_crypto_1.sign)(null, signingBytes(input.domain, input.payload), input.privateKey).toString("base64url"),
53
+ };
54
+ }
55
+ function authorityArtifact(value) {
56
+ if (!value || typeof value !== "object" || Array.isArray(value))
57
+ throw new Error("authority artifact shape is invalid");
58
+ const record = value;
59
+ if (JSON.stringify(Object.keys(record).sort()) !== JSON.stringify([...ARTIFACT_KEYS]))
60
+ throw new Error("authority artifact shape is invalid");
61
+ if (record.schemaVersion !== 1)
62
+ throw new Error("authority artifact schema is invalid");
63
+ if (typeof record.domain !== "string" || !record.domain)
64
+ throw new Error("authority artifact domain is invalid");
65
+ if (typeof record.keyId !== "string" || !record.keyId)
66
+ throw new Error("authority artifact key id is invalid");
67
+ if (typeof record.signature !== "string" || !BASE64URL_SIGNATURE.test(record.signature)
68
+ || Buffer.from(record.signature, "base64url").length !== 64
69
+ || Buffer.from(record.signature, "base64url").toString("base64url") !== record.signature) {
70
+ throw new Error("authority artifact signature is invalid");
71
+ }
72
+ canonicalAuthorityJson(record.payload);
73
+ return record;
74
+ }
75
+ function verifyAuthorityPayload(input) {
76
+ const artifact = authorityArtifact(input.artifact);
77
+ if (artifact.domain !== input.expectedDomain)
78
+ throw new Error("authority artifact domain changed");
79
+ if (artifact.keyId !== input.expectedKeyId)
80
+ throw new Error("authority artifact key id changed");
81
+ if (!(0, node_crypto_1.verify)(null, signingBytes(artifact.domain, artifact.payload), input.publicKey, Buffer.from(artifact.signature, "base64url"))) {
82
+ throw new Error("authority artifact signature is invalid");
83
+ }
84
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_authority_signature_verified", message: "Sanctuary authority signature verified" });
85
+ return artifact.payload;
86
+ }
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.readSanctuaryAuthorityEpoch = readSanctuaryAuthorityEpoch;
37
+ exports.prepareSanctuaryAuthorityEpoch = prepareSanctuaryAuthorityEpoch;
38
+ exports.releaseSanctuaryAuthorityToken = releaseSanctuaryAuthorityToken;
39
+ exports.rebindSanctuaryAuthorityEpochPackage = rebindSanctuaryAuthorityEpochPackage;
40
+ exports.retireSanctuaryAuthorityEpoch = retireSanctuaryAuthorityEpoch;
41
+ const node_crypto_1 = require("node:crypto");
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const session_transaction_1 = require("../../mind/session-transaction");
45
+ const runtime_1 = require("../../nerves/runtime");
46
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
47
+ const TOKEN = /^[1-9][0-9]*:[A-Za-z0-9_-]{20,}$/u;
48
+ const sha = (bytes) => `sha256:${(0, node_crypto_1.createHash)("sha256").update(bytes).digest("hex")}`;
49
+ function assertRoot(root, owner) {
50
+ const stat = fs.lstatSync(root);
51
+ if (!stat.isDirectory() || fs.realpathSync(root) !== root || stat.uid !== owner.expectedUid || stat.gid !== owner.expectedGid || (stat.mode & 0o7777) !== 0o700)
52
+ throw new Error("Sanctuary authority epoch root is unsafe");
53
+ }
54
+ function privateBytes(filePath, owner) {
55
+ if (!path.isAbsolute(filePath) || fs.realpathSync(filePath) !== filePath)
56
+ throw new Error("Sanctuary authority epoch path is unsafe");
57
+ const fd = fs.openSync(filePath, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
58
+ try {
59
+ const stat = fs.fstatSync(fd);
60
+ if (!stat.isFile() || stat.nlink !== 1 || stat.uid !== owner.expectedUid || stat.gid !== owner.expectedGid || (stat.mode & 0o7777) !== 0o600 || stat.size < 1 || stat.size > 65536)
61
+ throw new Error("Sanctuary authority epoch file metadata is unsafe");
62
+ return fs.readFileSync(fd);
63
+ }
64
+ finally {
65
+ fs.closeSync(fd);
66
+ }
67
+ }
68
+ function issuer(root, owner) {
69
+ const key = (0, node_crypto_1.createPrivateKey)(privateBytes(path.join(root, "issuer.pem"), owner));
70
+ const publicKey = (0, node_crypto_1.createPublicKey)(key);
71
+ if (publicKey.asymmetricKeyType !== "ed25519")
72
+ throw new Error("Sanctuary authority issuer is not Ed25519");
73
+ return { publicKeyPem: publicKey.export({ type: "spki", format: "pem" }).toString(), publicKeyDigest: sha(publicKey.export({ type: "spki", format: "der" })) };
74
+ }
75
+ function validate(value) {
76
+ if (!value || typeof value !== "object" || Array.isArray(value))
77
+ throw new Error("Sanctuary authority epoch is invalid");
78
+ const epoch = value;
79
+ if (Object.keys(epoch).sort().join(",") !== "botId,createdAt,epochId,ownerChatId,ownerUserId,packageDigest,predecessorCursor,previousTokenDigest,publicKeyDigest,publicKeyPem,revokedTokenStatus,schemaVersion,state,terminalCursor,tokenDigest,tokenPath"
80
+ || epoch.schemaVersion !== 1 || !["prepared", "retired"].includes(epoch.state)
81
+ || typeof epoch.epochId !== "string" || !/^[A-Za-z0-9_-]{1,128}$/u.test(epoch.epochId)
82
+ || ![epoch.botId, epoch.ownerUserId, epoch.ownerChatId].every((id) => typeof id === "string" && /^[1-9][0-9]*$/u.test(id)) || epoch.ownerUserId !== epoch.ownerChatId
83
+ || !Number.isSafeInteger(epoch.predecessorCursor) || epoch.predecessorCursor < 0
84
+ || ![epoch.packageDigest, epoch.tokenDigest, epoch.previousTokenDigest, epoch.publicKeyDigest].every((value) => typeof value === "string" && DIGEST.test(value))
85
+ || epoch.tokenDigest === epoch.previousTokenDigest || typeof epoch.tokenPath !== "string" || !path.isAbsolute(epoch.tokenPath)
86
+ || typeof epoch.publicKeyPem !== "string" || epoch.revokedTokenStatus !== 401
87
+ || typeof epoch.createdAt !== "string" || !Number.isFinite(Date.parse(epoch.createdAt)) || new Date(epoch.createdAt).toISOString() !== epoch.createdAt
88
+ || (epoch.state === "prepared" ? epoch.terminalCursor !== null : !Number.isSafeInteger(epoch.terminalCursor) || epoch.terminalCursor < epoch.predecessorCursor))
89
+ throw new Error("Sanctuary authority epoch is invalid");
90
+ return epoch;
91
+ }
92
+ function syncRoot(root) {
93
+ const fd = fs.openSync(root, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY);
94
+ try {
95
+ fs.fsyncSync(fd);
96
+ }
97
+ finally {
98
+ fs.closeSync(fd);
99
+ }
100
+ }
101
+ function writeRecord(filePath, record) {
102
+ (0, session_transaction_1.withImmediateSessionTurnLease)(filePath, (lease) => {
103
+ const transaction = (0, session_transaction_1.readSessionTransaction)(filePath, lease);
104
+ (0, session_transaction_1.writeSessionTransaction)(filePath, record, { lease, expectedRevision: transaction.revision });
105
+ });
106
+ }
107
+ function writeIssuer(root, key, owner) {
108
+ const temporary = path.join(root, "issuer.pem.tmp");
109
+ const fd = fs.openSync(temporary, fs.constants.O_CREAT | fs.constants.O_WRONLY | fs.constants.O_NOFOLLOW, 0o600);
110
+ let owned = false;
111
+ try {
112
+ try {
113
+ const stat = fs.fstatSync(fd);
114
+ if (!stat.isFile() || stat.nlink !== 1 || stat.uid !== owner.expectedUid || stat.gid !== owner.expectedGid || (stat.mode & 0o7777) !== 0o600)
115
+ throw new Error("Sanctuary issuer temporary is unsafe");
116
+ owned = true;
117
+ fs.ftruncateSync(fd, 0);
118
+ fs.writeFileSync(fd, key);
119
+ fs.fsyncSync(fd);
120
+ }
121
+ finally {
122
+ fs.closeSync(fd);
123
+ }
124
+ fs.renameSync(temporary, path.join(root, "issuer.pem"));
125
+ }
126
+ catch (error) {
127
+ if (owned)
128
+ fs.unlinkSync(temporary);
129
+ throw error;
130
+ }
131
+ syncRoot(root);
132
+ }
133
+ function readSanctuaryAuthorityEpoch(root, owner) {
134
+ assertRoot(root, owner);
135
+ const epoch = validate(JSON.parse(privateBytes(path.join(root, "epoch.json"), owner).toString("utf8")));
136
+ const publicKey = issuer(root, owner);
137
+ if (publicKey.publicKeyDigest !== epoch.publicKeyDigest || publicKey.publicKeyPem !== epoch.publicKeyPem)
138
+ throw new Error("Sanctuary authority epoch key or token changed");
139
+ if (epoch.state === "retired" && fs.existsSync(path.join(root, "handoff.json"))) {
140
+ const handoff = JSON.parse(privateBytes(path.join(root, "handoff.json"), owner).toString("utf8"));
141
+ if (JSON.stringify(handoff) !== JSON.stringify({ schemaVersion: 1, epochId: epoch.epochId, tokenDigest: epoch.tokenDigest, cursor: epoch.terminalCursor }))
142
+ throw new Error("Sanctuary authority token handoff changed");
143
+ if (fs.existsSync(epoch.tokenPath) && sha(privateBytes(epoch.tokenPath, owner).toString("utf8").trim()) !== epoch.tokenDigest)
144
+ throw new Error("Sanctuary authority epoch key or token changed");
145
+ }
146
+ else if (sha(privateBytes(epoch.tokenPath, owner).toString("utf8").trim()) !== epoch.tokenDigest)
147
+ throw new Error("Sanctuary authority epoch key or token changed");
148
+ return epoch;
149
+ }
150
+ async function prepareSanctuaryAuthorityEpoch(input, options) {
151
+ assertRoot(input.root, options);
152
+ if (typeof input.epochId !== "string" || !/^[A-Za-z0-9_-]{1,128}$/u.test(input.epochId)
153
+ || ![input.botId, input.ownerUserId, input.ownerChatId].every((id) => typeof id === "string" && /^[1-9][0-9]*$/u.test(id)) || input.ownerUserId !== input.ownerChatId
154
+ || !Number.isSafeInteger(input.predecessorCursor) || input.predecessorCursor < 0 || !DIGEST.test(input.packageDigest))
155
+ throw new Error("Sanctuary authority epoch input is invalid");
156
+ const token = privateBytes(input.tokenPath, options).toString("utf8").trim();
157
+ const previousToken = privateBytes(input.previousTokenPath, options).toString("utf8").trim();
158
+ if (!TOKEN.test(token) || !TOKEN.test(previousToken) || token.split(":")[0] !== input.botId || previousToken.split(":")[0] !== input.botId || token === previousToken)
159
+ throw new Error("Sanctuary authority requires a fresh same-bot token");
160
+ const previous = await options.probe(previousToken);
161
+ if (previous.status !== 401 || previous.botId !== null)
162
+ throw new Error("Sanctuary previous Telegram token is not proven revoked");
163
+ const current = await options.probe(token);
164
+ if (current.status !== 200 || current.botId !== input.botId)
165
+ throw new Error("Sanctuary new Telegram token identity is invalid");
166
+ const epochPath = path.join(input.root, "epoch.json");
167
+ const keyPath = path.join(input.root, "issuer.pem");
168
+ const intentPath = path.join(input.root, "issuer-intent.json");
169
+ const inputDigest = sha(JSON.stringify({ ...input, tokenDigest: sha(token), previousTokenDigest: sha(previousToken) }));
170
+ return (0, session_transaction_1.withImmediateSessionTurnLease)(epochPath, (lease) => {
171
+ const transaction = (0, session_transaction_1.readSessionTransaction)(epochPath, lease);
172
+ let existing = false;
173
+ try {
174
+ fs.lstatSync(epochPath);
175
+ existing = true;
176
+ }
177
+ catch (error) {
178
+ if (error.code !== "ENOENT")
179
+ throw error;
180
+ }
181
+ if (existing) {
182
+ const epoch = readSanctuaryAuthorityEpoch(input.root, options);
183
+ if (epoch.state === "retired")
184
+ throw new Error("Sanctuary authority epoch is retired; a fresh token and key epoch are required");
185
+ for (const key of ["epochId", "botId", "ownerUserId", "ownerChatId", "predecessorCursor", "packageDigest", "tokenPath"]) {
186
+ if (epoch[key] !== input[key])
187
+ throw new Error("Sanctuary authority epoch input changed");
188
+ }
189
+ if (epoch.previousTokenDigest !== sha(previousToken))
190
+ throw new Error("Sanctuary authority predecessor token changed");
191
+ if (fs.existsSync(intentPath)) {
192
+ const intent = JSON.parse(privateBytes(intentPath, options).toString("utf8"));
193
+ if (intent.inputDigest !== inputDigest || intent.key !== privateBytes(keyPath, options).toString("utf8"))
194
+ throw new Error("Sanctuary issuer cleanup identity changed");
195
+ fs.unlinkSync(intentPath);
196
+ syncRoot(input.root);
197
+ }
198
+ return epoch;
199
+ }
200
+ let intent;
201
+ if (fs.existsSync(intentPath)) {
202
+ intent = JSON.parse(privateBytes(intentPath, options).toString("utf8"));
203
+ if (!intent || Object.keys(intent).sort().join(",") !== "createdAt,inputDigest,key" || intent.inputDigest !== inputDigest || typeof intent.key !== "string")
204
+ throw new Error("Sanctuary issuer preparation identity changed");
205
+ }
206
+ else {
207
+ if (fs.existsSync(keyPath))
208
+ throw new Error("Sanctuary authority issuer is orphaned; a fresh epoch is required");
209
+ intent = { inputDigest, key: (0, node_crypto_1.generateKeyPairSync)("ed25519").privateKey.export({ type: "pkcs8", format: "pem" }).toString(), createdAt: options.now() };
210
+ writeRecord(intentPath, intent);
211
+ }
212
+ if (fs.existsSync(keyPath)) {
213
+ if (privateBytes(keyPath, options).toString("utf8") !== intent.key)
214
+ throw new Error("Sanctuary prepared issuer changed");
215
+ }
216
+ else {
217
+ writeIssuer(input.root, intent.key, options);
218
+ }
219
+ const epoch = validate({
220
+ schemaVersion: 1, state: "prepared", epochId: input.epochId, botId: input.botId, ownerUserId: input.ownerUserId, ownerChatId: input.ownerChatId,
221
+ predecessorCursor: input.predecessorCursor, packageDigest: input.packageDigest, tokenPath: input.tokenPath, tokenDigest: sha(token), previousTokenDigest: sha(previousToken),
222
+ ...issuer(input.root, options), revokedTokenStatus: 401, createdAt: intent.createdAt, terminalCursor: null,
223
+ });
224
+ (0, session_transaction_1.writeSessionTransaction)(epochPath, epoch, { lease, expectedRevision: transaction.revision });
225
+ fs.unlinkSync(intentPath);
226
+ syncRoot(input.root);
227
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_authority_epoch_prepared", message: "Sanctuary authority epoch prepared", meta: { epochId: epoch.epochId, publicKeyDigest: epoch.publicKeyDigest } });
228
+ return epoch;
229
+ });
230
+ }
231
+ function releaseSanctuaryAuthorityToken(root, options) {
232
+ const epoch = readSanctuaryAuthorityEpoch(root, options);
233
+ if (epoch.state !== "retired")
234
+ throw new Error("Sanctuary authority token cannot leave an unretired epoch");
235
+ if (epoch.tokenDigest !== options.tokenDigest || epoch.terminalCursor !== options.cursor || path.dirname(epoch.tokenPath) !== root)
236
+ throw new Error("Sanctuary authority token handoff is invalid");
237
+ writeRecord(path.join(root, "handoff.json"), { schemaVersion: 1, epochId: epoch.epochId, tokenDigest: epoch.tokenDigest, cursor: epoch.terminalCursor });
238
+ if (fs.existsSync(epoch.tokenPath))
239
+ fs.unlinkSync(epoch.tokenPath);
240
+ syncRoot(root);
241
+ }
242
+ /**
243
+ * Move a live epoch to a new reviewed package without replacing its token, issuer
244
+ * or cursor. An in-place upgrade (and its rollback) rebinds the package the epoch
245
+ * trusts; the gateway still refuses any config whose package differs from the epoch's.
246
+ */
247
+ function rebindSanctuaryAuthorityEpochPackage(root, options) {
248
+ if (!DIGEST.test(options.from) || !DIGEST.test(options.to))
249
+ throw new Error("Sanctuary authority package rebind is invalid");
250
+ const epochPath = path.join(root, "epoch.json");
251
+ return (0, session_transaction_1.withImmediateSessionTurnLease)(epochPath, (lease) => {
252
+ const transaction = (0, session_transaction_1.readSessionTransaction)(epochPath, lease);
253
+ const epoch = readSanctuaryAuthorityEpoch(root, options);
254
+ if (epoch.state !== "prepared")
255
+ throw new Error("Sanctuary authority epoch is retired");
256
+ if (epoch.packageDigest === options.to)
257
+ return epoch;
258
+ if (epoch.packageDigest !== options.from)
259
+ throw new Error("Sanctuary authority epoch package changed");
260
+ const rebound = { ...epoch, packageDigest: options.to };
261
+ (0, session_transaction_1.writeSessionTransaction)(epochPath, rebound, { lease, expectedRevision: transaction.revision });
262
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_authority_epoch_package_rebound", message: "Sanctuary authority epoch rebound to a reviewed package", meta: { epochId: epoch.epochId, from: options.from, to: options.to } });
263
+ return rebound;
264
+ });
265
+ }
266
+ function retireSanctuaryAuthorityEpoch(root, options) {
267
+ if (options.quiescent !== true)
268
+ throw new Error("Sanctuary authority execution state is not quiescent");
269
+ const epochPath = path.join(root, "epoch.json");
270
+ return (0, session_transaction_1.withImmediateSessionTurnLease)(epochPath, (lease) => {
271
+ const transaction = (0, session_transaction_1.readSessionTransaction)(epochPath, lease);
272
+ const epoch = readSanctuaryAuthorityEpoch(root, options);
273
+ if (!Number.isSafeInteger(options.cursor) || options.cursor < epoch.predecessorCursor || (epoch.state === "retired" && options.cursor !== epoch.terminalCursor))
274
+ throw new Error("Sanctuary authority terminal cursor is invalid");
275
+ if (epoch.state === "retired")
276
+ return epoch;
277
+ const retired = { ...epoch, state: "retired", terminalCursor: options.cursor };
278
+ (0, session_transaction_1.writeSessionTransaction)(epochPath, retired, { lease, expectedRevision: transaction.revision });
279
+ return retired;
280
+ });
281
+ }
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SANCTUARY_CGROUP_KEEP = void 0;
37
+ exports.sanctuaryCgroupChildren = sanctuaryCgroupChildren;
38
+ exports.verifySanctuaryAuthorityInstallation = verifySanctuaryAuthorityInstallation;
39
+ const node_crypto_1 = require("node:crypto");
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const runtime_1 = require("../../nerves/runtime");
43
+ function object(value) {
44
+ return value !== null && typeof value === "object" && !Array.isArray(value);
45
+ }
46
+ function digest(bytes) {
47
+ return `sha256:${(0, node_crypto_1.createHash)("sha256").update(bytes).digest("hex")}`;
48
+ }
49
+ function canonical(filePath) {
50
+ if (!path.isAbsolute(filePath) || path.normalize(filePath) !== filePath || fs.realpathSync(filePath) !== filePath) {
51
+ throw new Error("Sanctuary authority installation path is not canonical");
52
+ }
53
+ }
54
+ function directory(filePath, uid, gid, mode) {
55
+ canonical(filePath);
56
+ const stat = fs.lstatSync(filePath);
57
+ if (!stat.isDirectory() || stat.uid !== uid || stat.gid !== gid || (stat.mode & 0o7777) !== mode) {
58
+ throw new Error("Sanctuary authority installation directory metadata changed");
59
+ }
60
+ }
61
+ /** `trustedParent`: the caller already walked every parent directory without following
62
+ * symlinks, so only the leaf needs guarding, and O_NOFOLLOW does that. Resolving each
63
+ * package file's real path cost two-thirds of every verification on Unraid (D-036). */
64
+ function readOwned(filePath, uid, gid, mode, trustedParent = false) {
65
+ if (!trustedParent)
66
+ canonical(filePath);
67
+ const descriptor = fs.openSync(filePath, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
68
+ try {
69
+ const stat = fs.fstatSync(descriptor);
70
+ if (!stat.isFile() || stat.uid !== uid || stat.gid !== gid || (stat.mode & 0o7777) !== mode || stat.nlink !== 1) {
71
+ throw new Error("Sanctuary authority installation file metadata changed");
72
+ }
73
+ return fs.readFileSync(descriptor);
74
+ }
75
+ finally {
76
+ fs.closeSync(descriptor);
77
+ }
78
+ }
79
+ /**
80
+ * Unraid's cgroup2-unraid removes every top-level cgroup that reports `populated 0`,
81
+ * and the kernel refuses to remove a cgroup that has child cgroups. So the authority
82
+ * keeps one permanent empty child, and every reader of its cgroup ignores it (D-026).
83
+ */
84
+ exports.SANCTUARY_CGROUP_KEEP = "ouro-keep";
85
+ /** The authority cgroup's execution children: directories other than the keep child. */
86
+ function sanctuaryCgroupChildren(cgroupRoot) {
87
+ return fs.readdirSync(cgroupRoot).filter((name) => name !== exports.SANCTUARY_CGROUP_KEEP && fs.lstatSync(path.join(cgroupRoot, name)).isDirectory());
88
+ }
89
+ function verifySanctuaryAuthorityInstallation(input) {
90
+ const { expectedUid: uid, expectedGid: gid } = input;
91
+ for (const root of [input.packageRoot, input.stateRoot, input.stagingRoot, input.cgroupRoot])
92
+ directory(root, uid, gid, 0o700);
93
+ directory(input.socketRoot, uid, input.socketGroupId, 0o750);
94
+ const bytes = readOwned(input.manifestPath, uid, gid, 0o600);
95
+ if (digest(bytes) !== input.manifestDigest)
96
+ throw new Error("Sanctuary authority package manifest digest changed");
97
+ const manifest = JSON.parse(bytes.toString("utf8"));
98
+ if (!object(manifest) || Object.keys(manifest).sort().join(",") !== "files,schemaVersion" || manifest.schemaVersion !== 1 || !object(manifest.files) || Object.keys(manifest.files).length === 0) {
99
+ throw new Error("Sanctuary authority package manifest is invalid");
100
+ }
101
+ const expected = Object.keys(manifest.files).sort();
102
+ for (const relative of expected) {
103
+ const pin = manifest.files[relative];
104
+ if (!/^[A-Za-z0-9_@.-]+(?:\/[A-Za-z0-9_@.-]+)*$/u.test(relative) || relative.split("/").some((part) => part === "." || part === "..")
105
+ || !object(pin) || Object.keys(pin).sort().join(",") !== "digest,mode"
106
+ || typeof pin.digest !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(pin.digest) || ![0o600, 0o644, 0o700, 0o755].includes(pin.mode)) {
107
+ throw new Error("Sanctuary authority package file pin is invalid");
108
+ }
109
+ }
110
+ const actual = [];
111
+ const walk = (relative) => {
112
+ for (const entry of fs.readdirSync(path.join(input.packageRoot, relative), { withFileTypes: true })) {
113
+ const name = path.join(relative, entry.name);
114
+ const filePath = path.join(input.packageRoot, name);
115
+ if (entry.isDirectory()) {
116
+ const stat = fs.lstatSync(filePath);
117
+ canonical(filePath);
118
+ if (stat.uid !== uid || stat.gid !== gid || ![0o700, 0o755].includes(stat.mode & 0o7777))
119
+ throw new Error("Sanctuary authority package directory is unsafe");
120
+ walk(name);
121
+ }
122
+ else {
123
+ actual.push(name);
124
+ }
125
+ }
126
+ };
127
+ walk("");
128
+ if (JSON.stringify(actual.sort()) !== JSON.stringify(expected))
129
+ throw new Error("Sanctuary authority package inventory changed");
130
+ // The walk above reached every file through real (not symlinked) directories, so a
131
+ // file read only needs to refuse a symlinked leaf.
132
+ for (const relative of expected) {
133
+ const pin = manifest.files[relative];
134
+ if (digest(readOwned(path.join(input.packageRoot, relative), uid, gid, pin.mode, true)) !== pin.digest)
135
+ throw new Error("Sanctuary authority package file digest changed");
136
+ }
137
+ const controllers = ["cpu", "memory", "pids"];
138
+ const readControl = (name) => fs.readFileSync(path.join(input.cgroupRoot, name), "utf8").trim();
139
+ for (const name of ["cgroup.controllers", "cgroup.subtree_control"]) {
140
+ const enabled = readControl(name).split(/\s+/u);
141
+ if (!controllers.every((controller) => enabled.includes(controller)))
142
+ throw new Error("Sanctuary authority cgroup controllers are unavailable");
143
+ }
144
+ if (readControl("cgroup.type") !== "domain" || readControl("cgroup.procs") !== "")
145
+ throw new Error("Sanctuary authority cgroup domain is invalid");
146
+ const mounts = (input.mountInfo ?? fs.readFileSync("/proc/self/mountinfo", "utf8")).trim().split("\n").map((line) => {
147
+ const fields = line.split(" ");
148
+ const separator = fields.indexOf("-");
149
+ if (fields.length < 10 || separator < 6)
150
+ throw new Error("Sanctuary authority mount inventory is invalid");
151
+ return { target: fields[4].replace(/\\([0-7]{3})/gu, (_match, octal) => String.fromCharCode(parseInt(octal, 8))), options: fields[5].split(","), type: fields[separator + 1] };
152
+ });
153
+ const mountFor = (filePath) => mounts.filter(({ target }) => target === "/" || filePath === target || filePath.startsWith(`${target}/`)).sort((a, b) => b.target.length - a.target.length)[0];
154
+ const stagingMount = mountFor(input.stagingRoot);
155
+ const cgroupMount = mountFor(input.cgroupRoot);
156
+ if (!stagingMount || stagingMount.options.includes("noexec") || stagingMount.options.includes("ro") || cgroupMount?.type !== "cgroup2" || cgroupMount.options.includes("ro")) {
157
+ throw new Error("Sanctuary authority staging or cgroup mount prerequisites are unavailable");
158
+ }
159
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_authority_installation_verified", message: "Sanctuary authority installation prerequisites verified", meta: { packageDigest: input.manifestDigest } });
160
+ return { packageDigest: input.manifestDigest, controllers };
161
+ }