borgmcp 1.1.15 → 2.0.2
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.
- package/CONTRIBUTING.md +15 -0
- package/LICENSE +201 -33
- package/NOTICE +2 -0
- package/README.md +85 -36
- package/SECURITY.md +7 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +63 -1
- package/dist/agent-runtime.js.map +1 -0
- package/dist/assimilate-cmd.d.ts +96 -17
- package/dist/assimilate-cmd.d.ts.map +1 -0
- package/dist/assimilate-cmd.js +1396 -48
- package/dist/assimilate-cmd.js.map +1 -0
- package/dist/assimilate-deps.d.ts.map +1 -0
- package/dist/assimilate-deps.js +384 -3
- package/dist/assimilate-deps.js.map +1 -0
- package/dist/assimilate-guard.d.ts +5 -7
- package/dist/assimilate-guard.d.ts.map +1 -0
- package/dist/assimilate-guard.js +60 -2
- package/dist/assimilate-guard.js.map +1 -0
- package/dist/assimilate-welcome.d.ts +1 -1
- package/dist/assimilate-welcome.d.ts.map +1 -0
- package/dist/assimilate-welcome.js +32 -2
- package/dist/assimilate-welcome.js.map +1 -0
- package/dist/auth-env.d.ts +7 -50
- package/dist/auth-env.d.ts.map +1 -0
- package/dist/auth-env.js +22 -1
- package/dist/auth-env.js.map +1 -0
- package/dist/backends/launch-all-pastelist.d.ts.map +1 -0
- package/dist/backends/launch-all-pastelist.js +11 -4
- package/dist/backends/launch-all-pastelist.js.map +1 -0
- package/dist/backends/launch-all-tmux.d.ts.map +1 -0
- package/dist/backends/launch-all-tmux.js +49 -1
- package/dist/backends/launch-all-tmux.js.map +1 -0
- package/dist/backends/launch-all-windows.d.ts.map +1 -0
- package/dist/backends/launch-all-windows.js +86 -12
- package/dist/backends/launch-all-windows.js.map +1 -0
- package/dist/bare-launch-menu.d.ts.map +1 -0
- package/dist/bare-launch-menu.js +83 -6
- package/dist/bare-launch-menu.js.map +1 -0
- package/dist/claude-launch-args.d.ts.map +1 -0
- package/dist/claude-launch-args.js +34 -1
- package/dist/claude-launch-args.js.map +1 -0
- package/dist/claude.d.ts.map +1 -0
- package/dist/claude.js +486 -14
- package/dist/claude.js.map +1 -0
- package/dist/cleanup-cmd.d.ts +5 -5
- package/dist/cleanup-cmd.d.ts.map +1 -0
- package/dist/cleanup-cmd.js +453 -14
- package/dist/cleanup-cmd.js.map +1 -0
- package/dist/clear-rewake-core.d.ts.map +1 -0
- package/dist/clear-rewake-core.js +23 -2
- package/dist/clear-rewake-core.js.map +1 -0
- package/dist/clear-rewake.d.ts.map +1 -0
- package/dist/clear-rewake.js +19 -1
- package/dist/clear-rewake.js.map +1 -0
- package/dist/cli-help.d.ts +5 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +104 -56
- package/dist/cli-help.js.map +1 -0
- package/dist/cli-platform.d.ts.map +1 -0
- package/dist/cli-platform.js +106 -4
- package/dist/cli-platform.js.map +1 -0
- package/dist/cli-tool-approval.d.ts +84 -0
- package/dist/cli-tool-approval.d.ts.map +1 -0
- package/dist/cli-tool-approval.js +583 -0
- package/dist/cli-tool-approval.js.map +1 -0
- package/dist/codex-app-server.d.ts.map +1 -0
- package/dist/codex-app-server.js +228 -4
- package/dist/codex-app-server.js.map +1 -0
- package/dist/codex-app-wake.d.ts +9 -11
- package/dist/codex-app-wake.d.ts.map +1 -0
- package/dist/codex-app-wake.js +436 -2
- package/dist/codex-app-wake.js.map +1 -0
- package/dist/codex-launch.d.ts.map +1 -0
- package/dist/codex-launch.js +102 -2
- package/dist/codex-launch.js.map +1 -0
- package/dist/codex-remote.d.ts +6 -1
- package/dist/codex-remote.d.ts.map +1 -0
- package/dist/codex-remote.js +394 -1
- package/dist/codex-remote.js.map +1 -0
- package/dist/codex-wake-resolve.d.ts +4 -4
- package/dist/codex-wake-resolve.d.ts.map +1 -0
- package/dist/codex-wake-resolve.js +127 -1
- package/dist/codex-wake-resolve.js.map +1 -0
- package/dist/config-utils.d.ts +2 -2
- package/dist/config-utils.d.ts.map +1 -0
- package/dist/config-utils.js +766 -3
- package/dist/config-utils.js.map +1 -0
- package/dist/config.d.ts +98 -61
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +426 -1
- package/dist/config.js.map +1 -0
- package/dist/console-prefix.d.ts.map +1 -0
- package/dist/console-prefix.js +96 -1
- package/dist/console-prefix.js.map +1 -0
- package/dist/cube-name.d.ts.map +1 -0
- package/dist/cube-name.js +67 -1
- package/dist/cube-name.js.map +1 -0
- package/dist/cubes.d.ts +126 -18
- package/dist/cubes.d.ts.map +1 -0
- package/dist/cubes.js +412 -4
- package/dist/cubes.js.map +1 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +71 -1
- package/dist/debug.js.map +1 -0
- package/dist/direct-log.d.ts.map +1 -0
- package/dist/direct-log.js +11 -1
- package/dist/direct-log.js.map +1 -0
- package/dist/docs-sections.d.ts +11 -10
- package/dist/docs-sections.d.ts.map +1 -0
- package/dist/docs-sections.js +113 -3
- package/dist/docs-sections.js.map +1 -0
- package/dist/drone-lifecycle.d.ts +5 -21
- package/dist/drone-lifecycle.d.ts.map +1 -0
- package/dist/drone-lifecycle.js +57 -8
- package/dist/drone-lifecycle.js.map +1 -0
- package/dist/drone-management.d.ts +29 -0
- package/dist/drone-management.d.ts.map +1 -0
- package/dist/drone-management.js +109 -0
- package/dist/drone-management.js.map +1 -0
- package/dist/ensure-mcp-config.d.ts.map +1 -0
- package/dist/ensure-mcp-config.js +36 -1
- package/dist/ensure-mcp-config.js.map +1 -0
- package/dist/evict-drone.d.ts +10 -2
- package/dist/evict-drone.d.ts.map +1 -0
- package/dist/evict-drone.js +60 -1
- package/dist/evict-drone.js.map +1 -0
- package/dist/gc-orphan-inboxes.d.ts.map +1 -0
- package/dist/gc-orphan-inboxes.js +177 -1
- package/dist/gc-orphan-inboxes.js.map +1 -0
- package/dist/inbox-monitor.d.ts +1 -1
- package/dist/inbox-monitor.d.ts.map +1 -0
- package/dist/inbox-monitor.js +856 -3
- package/dist/inbox-monitor.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1034 -37
- package/dist/index.js.map +1 -0
- package/dist/launch-all-cmd.d.ts.map +1 -0
- package/dist/launch-all-cmd.js +377 -37
- package/dist/launch-all-cmd.js.map +1 -0
- package/dist/launch-all-command.d.ts.map +1 -0
- package/dist/launch-all-command.js +24 -1
- package/dist/launch-all-command.js.map +1 -0
- package/dist/launch-all-deps.d.ts +3 -8
- package/dist/launch-all-deps.d.ts.map +1 -0
- package/dist/launch-all-deps.js +99 -1
- package/dist/launch-all-deps.js.map +1 -0
- package/dist/launch-all-discovery.d.ts +1 -0
- package/dist/launch-all-discovery.d.ts.map +1 -0
- package/dist/launch-all-discovery.js +90 -4
- package/dist/launch-all-discovery.js.map +1 -0
- package/dist/launch-all-locks.d.ts.map +1 -0
- package/dist/launch-all-locks.js +54 -1
- package/dist/launch-all-locks.js.map +1 -0
- package/dist/launch-gate.d.ts +2 -2
- package/dist/launch-gate.d.ts.map +1 -0
- package/dist/launch-gate.js +73 -1
- package/dist/launch-gate.js.map +1 -0
- package/dist/lifecycle-log-guard.d.ts.map +1 -0
- package/dist/lifecycle-log-guard.js +93 -2
- package/dist/lifecycle-log-guard.js.map +1 -0
- package/dist/list-roles-render.d.ts.map +1 -0
- package/dist/list-roles-render.js +40 -6
- package/dist/list-roles-render.js.map +1 -0
- package/dist/local-log-routing.d.ts +19 -0
- package/dist/local-log-routing.d.ts.map +1 -0
- package/dist/local-log-routing.js +67 -0
- package/dist/local-log-routing.js.map +1 -0
- package/dist/local-manage-tool-result.d.ts +8 -0
- package/dist/local-manage-tool-result.d.ts.map +1 -0
- package/dist/local-manage-tool-result.js +10 -0
- package/dist/local-manage-tool-result.js.map +1 -0
- package/dist/local-server-cursor.d.ts +34 -0
- package/dist/local-server-cursor.d.ts.map +1 -0
- package/dist/local-server-cursor.js +151 -0
- package/dist/local-server-cursor.js.map +1 -0
- package/dist/log-audit.d.ts.map +1 -0
- package/dist/log-audit.js +194 -3
- package/dist/log-audit.js.map +1 -0
- package/dist/log-stream.d.ts +35 -18
- package/dist/log-stream.d.ts.map +1 -0
- package/dist/log-stream.js +1270 -12
- package/dist/log-stream.js.map +1 -0
- package/dist/model-presets.d.ts.map +1 -0
- package/dist/model-presets.js +19 -1
- package/dist/model-presets.js.map +1 -0
- package/dist/name-validator.d.ts.map +1 -0
- package/dist/name-validator.js +22 -1
- package/dist/name-validator.js.map +1 -0
- package/dist/opencode-drone.d.ts.map +1 -0
- package/dist/opencode-drone.js +438 -4
- package/dist/opencode-drone.js.map +1 -0
- package/dist/opencode-plugin.d.ts +1 -1
- package/dist/opencode-plugin.d.ts.map +1 -0
- package/dist/opencode-plugin.js +29 -4
- package/dist/opencode-plugin.js.map +1 -0
- package/dist/parse-assimilate-args.d.ts +1 -1
- package/dist/parse-assimilate-args.d.ts.map +1 -0
- package/dist/parse-assimilate-args.js +125 -1
- package/dist/parse-assimilate-args.js.map +1 -0
- package/dist/parse-launch-all-args.d.ts.map +1 -0
- package/dist/parse-launch-all-args.js +70 -1
- package/dist/parse-launch-all-args.js.map +1 -0
- package/dist/postinstall-banner.d.ts.map +1 -0
- package/dist/postinstall-banner.js +27 -2
- package/dist/postinstall-banner.js.map +1 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +32 -5
- package/dist/postinstall.js.map +1 -0
- package/dist/readiness-probe.d.ts.map +1 -0
- package/dist/readiness-probe.js +9 -1
- package/dist/readiness-probe.js.map +1 -0
- package/dist/regen-format.d.ts.map +1 -0
- package/dist/regen-format.js +545 -13
- package/dist/regen-format.js.map +1 -0
- package/dist/regen.d.ts.map +1 -0
- package/dist/regen.js +141 -5
- package/dist/regen.js.map +1 -0
- package/dist/remote-client.d.ts +88 -173
- package/dist/remote-client.d.ts.map +1 -0
- package/dist/remote-client.js +997 -1
- package/dist/remote-client.js.map +1 -0
- package/dist/reset-local-seat-cmd.d.ts +50 -0
- package/dist/reset-local-seat-cmd.d.ts.map +1 -0
- package/dist/reset-local-seat-cmd.js +169 -0
- package/dist/reset-local-seat-cmd.js.map +1 -0
- package/dist/role-match.d.ts.map +1 -0
- package/dist/role-match.js +23 -1
- package/dist/role-match.js.map +1 -0
- package/dist/role-resolver.d.ts.map +1 -0
- package/dist/role-resolver.js +60 -1
- package/dist/role-resolver.js.map +1 -0
- package/dist/roster-render.d.ts.map +1 -0
- package/dist/roster-render.js +121 -3
- package/dist/roster-render.js.map +1 -0
- package/dist/seat-probe.d.ts +32 -13
- package/dist/seat-probe.d.ts.map +1 -0
- package/dist/seat-probe.js +78 -1
- package/dist/seat-probe.js.map +1 -0
- package/dist/seat-store.d.ts +76 -0
- package/dist/seat-store.d.ts.map +1 -0
- package/dist/seat-store.js +309 -0
- package/dist/seat-store.js.map +1 -0
- package/dist/seats.d.ts +375 -0
- package/dist/seats.d.ts.map +1 -0
- package/dist/seats.js +670 -0
- package/dist/seats.js.map +1 -0
- package/dist/self-path.d.ts +27 -0
- package/dist/self-path.d.ts.map +1 -0
- package/dist/self-path.js +43 -0
- package/dist/self-path.js.map +1 -0
- package/dist/server-endpoint.d.ts +9 -0
- package/dist/server-endpoint.d.ts.map +1 -0
- package/dist/server-endpoint.js +38 -0
- package/dist/server-endpoint.js.map +1 -0
- package/dist/server-errors.d.ts +50 -0
- package/dist/server-errors.d.ts.map +1 -0
- package/dist/server-errors.js +79 -0
- package/dist/server-errors.js.map +1 -0
- package/dist/server-handshake.d.ts +197 -0
- package/dist/server-handshake.d.ts.map +1 -0
- package/dist/server-handshake.js +533 -0
- package/dist/server-handshake.js.map +1 -0
- package/dist/server-response.d.ts +3 -0
- package/dist/server-response.d.ts.map +1 -0
- package/dist/server-response.js +67 -0
- package/dist/server-response.js.map +1 -0
- package/dist/server-trust.d.ts +14 -0
- package/dist/server-trust.d.ts.map +1 -0
- package/dist/server-trust.js +225 -0
- package/dist/server-trust.js.map +1 -0
- package/dist/session-continuity.d.ts +33 -0
- package/dist/session-continuity.d.ts.map +1 -0
- package/dist/session-continuity.js +220 -0
- package/dist/session-continuity.js.map +1 -0
- package/dist/setup-confirm.d.ts +3 -3
- package/dist/setup-confirm.d.ts.map +1 -0
- package/dist/setup-confirm.js +126 -2
- package/dist/setup-confirm.js.map +1 -0
- package/dist/setup.d.ts +5 -3
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +169 -46
- package/dist/setup.js.map +1 -0
- package/dist/shell-escape.d.ts.map +1 -0
- package/dist/shell-escape.js +22 -1
- package/dist/shell-escape.js.map +1 -0
- package/dist/spawn.d.ts +2 -2
- package/dist/spawn.d.ts.map +1 -0
- package/dist/spawn.js +29 -10
- package/dist/spawn.js.map +1 -0
- package/dist/startup-services.d.ts +0 -1
- package/dist/startup-services.d.ts.map +1 -0
- package/dist/startup-services.js +26 -1
- package/dist/startup-services.js.map +1 -0
- package/dist/stream-owner.d.ts +6 -2
- package/dist/stream-owner.d.ts.map +1 -0
- package/dist/stream-owner.js +547 -2
- package/dist/stream-owner.js.map +1 -0
- package/dist/stream-status.d.ts +1 -1
- package/dist/stream-status.d.ts.map +1 -0
- package/dist/stream-status.js +268 -3
- package/dist/stream-status.js.map +1 -0
- package/dist/sync-roles-render.d.ts.map +1 -0
- package/dist/sync-roles-render.js +118 -3
- package/dist/sync-roles-render.js.map +1 -0
- package/dist/sync.d.ts +1 -1
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +286 -22
- package/dist/sync.js.map +1 -0
- package/dist/terminal-title.d.ts.map +1 -0
- package/dist/terminal-title.js +68 -1
- package/dist/terminal-title.js.map +1 -0
- package/dist/token-store.d.ts +17 -111
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +81 -1
- package/dist/token-store.js.map +1 -0
- package/dist/tool-manifest.d.ts +4 -8
- package/dist/tool-manifest.d.ts.map +1 -0
- package/dist/tool-manifest.js +554 -1
- package/dist/tool-manifest.js.map +1 -0
- package/dist/tool-scope.d.ts +8 -12
- package/dist/tool-scope.d.ts.map +1 -0
- package/dist/tool-scope.js +97 -1
- package/dist/tool-scope.js.map +1 -0
- package/dist/types.d.ts +1 -5
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/unknown-subcommand.d.ts +1 -1
- package/dist/unknown-subcommand.d.ts.map +1 -0
- package/dist/unknown-subcommand.js +37 -1
- package/dist/unknown-subcommand.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +78 -2
- package/dist/version.js.map +1 -0
- package/dist/working-repo.d.ts.map +1 -0
- package/dist/working-repo.js +81 -1
- package/dist/working-repo.js.map +1 -0
- package/dist/worktree-lifecycle.d.ts.map +1 -0
- package/dist/worktree-lifecycle.js +205 -2
- package/dist/worktree-lifecycle.js.map +1 -0
- package/docs/EXTRACTION_PROVENANCE.md +42 -0
- package/docs/LOCAL_SERVER.md +103 -0
- package/docs/RELEASING.md +129 -0
- package/package.json +52 -34
- package/src/agent-runtime.ts +69 -0
- package/src/assimilate-cmd.ts +1864 -0
- package/src/assimilate-deps.ts +444 -0
- package/src/assimilate-guard.ts +84 -0
- package/src/assimilate-welcome.ts +39 -0
- package/src/auth-env.ts +21 -0
- package/src/backends/launch-all-pastelist.ts +18 -0
- package/src/backends/launch-all-tmux.ts +75 -0
- package/src/backends/launch-all-windows.ts +110 -0
- package/src/bare-launch-menu.ts +148 -0
- package/src/claude-launch-args.ts +35 -0
- package/src/claude.ts +561 -0
- package/src/cleanup-cmd.ts +581 -0
- package/src/clear-rewake-core.ts +34 -0
- package/src/clear-rewake.ts +18 -0
- package/src/cli-help.ts +116 -0
- package/src/cli-platform.ts +127 -0
- package/src/cli-tool-approval.ts +716 -0
- package/src/codex-app-server.ts +238 -0
- package/src/codex-app-wake.ts +524 -0
- package/src/codex-launch.ts +140 -0
- package/src/codex-remote.ts +500 -0
- package/src/codex-wake-resolve.ts +155 -0
- package/src/config-utils.ts +811 -0
- package/src/config.ts +595 -0
- package/src/console-prefix.ts +99 -0
- package/src/cube-name.ts +69 -0
- package/src/cubes.ts +583 -0
- package/src/debug.ts +73 -0
- package/src/direct-log.ts +9 -0
- package/src/docs-sections.ts +129 -0
- package/src/drone-lifecycle.ts +62 -0
- package/src/drone-management.ts +162 -0
- package/src/ensure-mcp-config.ts +54 -0
- package/src/evict-drone.ts +82 -0
- package/src/gc-orphan-inboxes.ts +229 -0
- package/src/inbox-monitor.ts +1005 -0
- package/src/index.ts +1201 -0
- package/src/launch-all-cmd.ts +450 -0
- package/src/launch-all-command.ts +30 -0
- package/src/launch-all-deps.ts +188 -0
- package/src/launch-all-discovery.ts +118 -0
- package/src/launch-all-locks.ts +74 -0
- package/src/launch-gate.ts +80 -0
- package/src/lifecycle-log-guard.ts +144 -0
- package/src/list-roles-render.ts +52 -0
- package/src/local-log-routing.ts +106 -0
- package/src/local-manage-tool-result.ts +10 -0
- package/src/local-server-cursor.ts +188 -0
- package/src/log-audit.ts +207 -0
- package/src/log-stream.ts +1567 -0
- package/src/model-presets.ts +22 -0
- package/src/name-validator.ts +23 -0
- package/src/opencode-drone.ts +528 -0
- package/src/opencode-plugin.ts +38 -0
- package/src/parse-assimilate-args.ts +125 -0
- package/src/parse-launch-all-args.ts +100 -0
- package/src/postinstall-banner.ts +37 -0
- package/src/postinstall.ts +36 -0
- package/src/readiness-probe.ts +12 -0
- package/src/regen-format.ts +651 -0
- package/src/regen.ts +150 -0
- package/src/remote-client.ts +1457 -0
- package/src/reset-local-seat-cmd.ts +227 -0
- package/src/role-match.ts +29 -0
- package/src/role-resolver.ts +93 -0
- package/src/roster-render.ts +196 -0
- package/src/seat-probe.ts +115 -0
- package/src/seat-store.ts +333 -0
- package/src/seats.ts +911 -0
- package/src/self-path.ts +51 -0
- package/src/server-endpoint.ts +38 -0
- package/src/server-errors.ts +95 -0
- package/src/server-handshake.ts +816 -0
- package/src/server-response.ts +76 -0
- package/src/server-trust.ts +245 -0
- package/src/session-continuity.ts +280 -0
- package/src/setup-confirm.ts +171 -0
- package/src/setup.ts +186 -0
- package/src/shell-escape.ts +22 -0
- package/src/spawn.ts +31 -0
- package/src/startup-services.ts +36 -0
- package/src/stream-owner.ts +686 -0
- package/src/stream-status.ts +337 -0
- package/src/sync-roles-render.ts +163 -0
- package/src/sync.ts +363 -0
- package/src/terminal-title.ts +76 -0
- package/src/token-store.ts +102 -0
- package/src/tool-manifest.ts +610 -0
- package/src/tool-scope.ts +110 -0
- package/src/types.ts +5 -0
- package/src/unknown-subcommand.ts +35 -0
- package/src/version.ts +82 -0
- package/src/working-repo.ts +99 -0
- package/src/worktree-lifecycle.ts +254 -0
- package/dist/auth-recovery.d.ts +0 -33
- package/dist/auth-recovery.js +0 -1
- package/dist/auth.d.ts +0 -103
- package/dist/auth.js +0 -39
- package/dist/device-auth.d.ts +0 -75
- package/dist/device-auth.js +0 -1
- package/dist/drone-address.d.ts +0 -26
- package/dist/drone-address.js +0 -1
- package/dist/get-started.d.ts +0 -20
- package/dist/get-started.js +0 -2
- package/dist/health-beat.d.ts +0 -134
- package/dist/health-beat.js +0 -1
- package/dist/role-section.d.ts +0 -110
- package/dist/role-section.js +0 -8
- package/dist/setup-action.d.ts +0 -20
- package/dist/setup-action.js +0 -1
- package/dist/stale-version-check.d.ts +0 -40
- package/dist/stale-version-check.js +0 -1
- package/dist/subscription-retry.d.ts +0 -40
- package/dist/subscription-retry.js +0 -1
- package/dist/templates.d.ts +0 -107
- package/dist/templates.js +0 -359
- package/dist/token-crypto.d.ts +0 -50
- package/dist/token-crypto.js +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ServerFetch = typeof fetch;
|
|
2
|
+
export interface BorgServerTrust {
|
|
3
|
+
identity: string;
|
|
4
|
+
fetchImpl: ServerFetch;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Minimal fetch-compatible HTTPS transport bound to one origin and one
|
|
8
|
+
* explicit local CA. Node's global fetch cannot consume the server-owned CA,
|
|
9
|
+
* and disabling certificate validation would collapse the authority boundary.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createPinnedServerFetch(origin: string, caCertificate: string): ServerFetch;
|
|
12
|
+
export declare function loadBorgServerTrust(origin: string, dataDirectory?: string): Promise<BorgServerTrust>;
|
|
13
|
+
export declare function __clearServerTrustCacheForTest(): void;
|
|
14
|
+
//# sourceMappingURL=server-trust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-trust.d.ts","sourceRoot":"","sources":["../src/server-trust.ts"],"names":[],"mappings":"AA0CA,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,WAAW,CAAC;CACxB;AAyFD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,WAAW,CA0E1F;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,aAAa,SAAwB,GACpC,OAAO,CAAC,eAAe,CAAC,CAoB1B;AAED,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual, X509Certificate } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { open } from 'node:fs/promises';
|
|
4
|
+
import { request as httpsRequest } from 'node:https';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { join, resolve } from 'node:path';
|
|
7
|
+
import { Readable } from 'node:stream';
|
|
8
|
+
import { BorgServerTrustError } from './server-errors.js';
|
|
9
|
+
// CR5 TLS LATTICE: OpenSSL/Node TLS certificate-verification error codes. A raw
|
|
10
|
+
// CA / cert-chain / SAN failure from the pinned transport is a potential MITM and
|
|
11
|
+
// MUST be a TERMINAL trust-mismatch verdict — never a transient 'restart' blip.
|
|
12
|
+
// Connection refusal / reset / timeout are NOT in here: those stay raw transport
|
|
13
|
+
// errors so the seat probe classifies them as `unreachable` (genuinely transient).
|
|
14
|
+
const TLS_TRUST_ERROR_CODES = new Set([
|
|
15
|
+
'DEPTH_ZERO_SELF_SIGNED_CERT',
|
|
16
|
+
'SELF_SIGNED_CERT_IN_CHAIN',
|
|
17
|
+
'UNABLE_TO_GET_ISSUER_CERT',
|
|
18
|
+
'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
|
|
19
|
+
'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
|
20
|
+
'CERT_UNTRUSTED',
|
|
21
|
+
'CERT_CHAIN_TOO_LONG',
|
|
22
|
+
'HOSTNAME_MISMATCH',
|
|
23
|
+
'ERR_TLS_CERT_ALTNAME_INVALID',
|
|
24
|
+
]);
|
|
25
|
+
/**
|
|
26
|
+
* True iff `code` is a PINNED-TRANSPORT certificate-verification failure (bad CA,
|
|
27
|
+
* unverifiable chain, self-signed leaf, expired/not-yet-valid cert, or a SAN /
|
|
28
|
+
* hostname mismatch). These are terminal trust-mismatch — a restart never fixes a
|
|
29
|
+
* wrong cert. `CERT_*` covers the OpenSSL verify family (CERT_HAS_EXPIRED,
|
|
30
|
+
* CERT_NOT_YET_VALID, CERT_REVOKED, …); `ERR_TLS_CERT*` covers Node's SAN check.
|
|
31
|
+
*/
|
|
32
|
+
function isPinnedTransportTrustFailure(code) {
|
|
33
|
+
if (!code)
|
|
34
|
+
return false;
|
|
35
|
+
return (code.startsWith('CERT_') ||
|
|
36
|
+
code.startsWith('ERR_TLS_CERT') ||
|
|
37
|
+
TLS_TRUST_ERROR_CODES.has(code));
|
|
38
|
+
}
|
|
39
|
+
const trustCache = new Map();
|
|
40
|
+
function serverDataDirectory() {
|
|
41
|
+
return resolve(process.env.BORG_SERVER_DATA_DIR ?? join(homedir(), '.borg', 'server'));
|
|
42
|
+
}
|
|
43
|
+
async function readTrustFile(path) {
|
|
44
|
+
let handle;
|
|
45
|
+
try {
|
|
46
|
+
handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error.code === 'ENOENT') {
|
|
50
|
+
throw new Error('Borg server trust files were not found');
|
|
51
|
+
}
|
|
52
|
+
throw new Error('Borg server trust files could not be opened safely');
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const metadata = await handle.stat();
|
|
56
|
+
if (!metadata.isFile() || (metadata.mode & 0o077) !== 0) {
|
|
57
|
+
throw new Error('Borg server trust files must be private regular files');
|
|
58
|
+
}
|
|
59
|
+
if (typeof process.getuid === 'function' && metadata.uid !== process.getuid()) {
|
|
60
|
+
throw new Error('Borg server trust files must be owned by the current user');
|
|
61
|
+
}
|
|
62
|
+
return await handle.readFile('utf8');
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await handle.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function decodeTrustConfig(value) {
|
|
69
|
+
let parsed;
|
|
70
|
+
try {
|
|
71
|
+
parsed = JSON.parse(value);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw new Error('Borg server trust metadata is invalid');
|
|
75
|
+
}
|
|
76
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
77
|
+
throw new Error('Borg server trust metadata is invalid');
|
|
78
|
+
}
|
|
79
|
+
const fingerprint = parsed.ca_spki_sha256;
|
|
80
|
+
if (typeof fingerprint !== 'string' || !/^[a-f0-9]{64}$/i.test(fingerprint)) {
|
|
81
|
+
throw new Error('Borg server trust metadata is missing a valid CA identity');
|
|
82
|
+
}
|
|
83
|
+
return { ca_spki_sha256: fingerprint.toLowerCase() };
|
|
84
|
+
}
|
|
85
|
+
function verifyCaIdentity(certificate, expected) {
|
|
86
|
+
let parsed;
|
|
87
|
+
try {
|
|
88
|
+
parsed = new X509Certificate(certificate);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
throw new Error('Borg server CA certificate is invalid');
|
|
92
|
+
}
|
|
93
|
+
if (!parsed.ca)
|
|
94
|
+
throw new Error('Borg server trust anchor is not a CA certificate');
|
|
95
|
+
const actual = createHash('sha256')
|
|
96
|
+
.update(parsed.publicKey.export({ type: 'spki', format: 'der' }))
|
|
97
|
+
.digest();
|
|
98
|
+
const expectedBytes = Buffer.from(expected, 'hex');
|
|
99
|
+
if (expectedBytes.length !== actual.length || !timingSafeEqual(actual, expectedBytes)) {
|
|
100
|
+
throw new Error('Borg server CA certificate does not match its pinned identity');
|
|
101
|
+
}
|
|
102
|
+
return `spki-sha256:${actual.toString('hex')}`;
|
|
103
|
+
}
|
|
104
|
+
function responseHeaders(rawHeaders) {
|
|
105
|
+
const headers = new Headers();
|
|
106
|
+
for (let index = 0; index < rawHeaders.length; index += 2) {
|
|
107
|
+
const name = rawHeaders[index];
|
|
108
|
+
const value = rawHeaders[index + 1];
|
|
109
|
+
if (name !== undefined && value !== undefined)
|
|
110
|
+
headers.append(name, value);
|
|
111
|
+
}
|
|
112
|
+
return headers;
|
|
113
|
+
}
|
|
114
|
+
function requestBody(value) {
|
|
115
|
+
if (value === null || value === undefined)
|
|
116
|
+
return undefined;
|
|
117
|
+
if (typeof value === 'string')
|
|
118
|
+
return value;
|
|
119
|
+
if (value instanceof Uint8Array)
|
|
120
|
+
return value;
|
|
121
|
+
if (value instanceof ArrayBuffer)
|
|
122
|
+
return new Uint8Array(value);
|
|
123
|
+
throw new Error('Borg server transport received an unsupported request body');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Minimal fetch-compatible HTTPS transport bound to one origin and one
|
|
127
|
+
* explicit local CA. Node's global fetch cannot consume the server-owned CA,
|
|
128
|
+
* and disabling certificate validation would collapse the authority boundary.
|
|
129
|
+
*/
|
|
130
|
+
export function createPinnedServerFetch(origin, caCertificate) {
|
|
131
|
+
const authority = new URL(origin);
|
|
132
|
+
if (authority.protocol !== 'https:' || authority.origin !== origin) {
|
|
133
|
+
throw new Error('Borg server trust requires a canonical HTTPS origin');
|
|
134
|
+
}
|
|
135
|
+
return (async (input, init = {}) => {
|
|
136
|
+
const url = input instanceof Request ? new URL(input.url) : new URL(input.toString());
|
|
137
|
+
if (url.origin !== authority.origin || url.protocol !== 'https:') {
|
|
138
|
+
throw new Error('Borg server transport refused a cross-authority request');
|
|
139
|
+
}
|
|
140
|
+
if (input instanceof Request) {
|
|
141
|
+
throw new Error('Borg server transport requires an explicit URL and request options');
|
|
142
|
+
}
|
|
143
|
+
if (init.signal?.aborted)
|
|
144
|
+
throw new DOMException('This operation was aborted', 'AbortError');
|
|
145
|
+
const body = requestBody(init.body);
|
|
146
|
+
const headers = new Headers(init.headers);
|
|
147
|
+
return await new Promise((resolvePromise, rejectPromise) => {
|
|
148
|
+
const request = httpsRequest({
|
|
149
|
+
protocol: 'https:',
|
|
150
|
+
hostname: url.hostname.replace(/^\[(.*)\]$/, '$1'),
|
|
151
|
+
port: url.port || 443,
|
|
152
|
+
path: `${url.pathname}${url.search}`,
|
|
153
|
+
method: init.method ?? 'GET',
|
|
154
|
+
headers: Object.fromEntries(headers.entries()),
|
|
155
|
+
ca: caCertificate,
|
|
156
|
+
rejectUnauthorized: true,
|
|
157
|
+
minVersion: 'TLSv1.3',
|
|
158
|
+
}, (incoming) => {
|
|
159
|
+
const status = incoming.statusCode ?? 500;
|
|
160
|
+
if (init.redirect === 'error' && status >= 300 && status < 400) {
|
|
161
|
+
incoming.resume();
|
|
162
|
+
rejectPromise(new Error('Borg server redirect refused'));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const noBody = init.method === 'HEAD' || status === 204 || status === 304;
|
|
166
|
+
const stream = noBody
|
|
167
|
+
? null
|
|
168
|
+
: Readable.toWeb(incoming);
|
|
169
|
+
if (noBody)
|
|
170
|
+
incoming.resume();
|
|
171
|
+
resolvePromise(new Response(stream, {
|
|
172
|
+
status,
|
|
173
|
+
statusText: incoming.statusMessage,
|
|
174
|
+
headers: responseHeaders(incoming.rawHeaders),
|
|
175
|
+
}));
|
|
176
|
+
});
|
|
177
|
+
const abort = () => {
|
|
178
|
+
request.destroy(new DOMException('This operation was aborted', 'AbortError'));
|
|
179
|
+
};
|
|
180
|
+
init.signal?.addEventListener('abort', abort, { once: true });
|
|
181
|
+
request.once('close', () => init.signal?.removeEventListener('abort', abort));
|
|
182
|
+
request.once('error', (error) => {
|
|
183
|
+
// CR5: a pinned-transport CERT/CA/SAN verification failure is TERMINAL trust
|
|
184
|
+
// — type it as BorgServerTrustError so the seat probe returns `trust-mismatch`
|
|
185
|
+
// (never `indeterminate` → "restart"). Connection refusal/reset/timeout carry
|
|
186
|
+
// a transport errno (or an AbortError) and are rethrown RAW so the probe
|
|
187
|
+
// classifies them as `unreachable`.
|
|
188
|
+
const code = error.code;
|
|
189
|
+
if (isPinnedTransportTrustFailure(code)) {
|
|
190
|
+
rejectPromise(new BorgServerTrustError(`Borg server presented a certificate that failed pinned verification (${code})`));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
rejectPromise(error);
|
|
194
|
+
});
|
|
195
|
+
if (body !== undefined)
|
|
196
|
+
request.write(body);
|
|
197
|
+
request.end();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
export async function loadBorgServerTrust(origin, dataDirectory = serverDataDirectory()) {
|
|
202
|
+
const key = `${dataDirectory}\0${origin}`;
|
|
203
|
+
let pending = trustCache.get(key);
|
|
204
|
+
if (!pending) {
|
|
205
|
+
pending = (async () => {
|
|
206
|
+
const [certificate, configText] = await Promise.all([
|
|
207
|
+
readTrustFile(join(dataDirectory, 'ca.crt')),
|
|
208
|
+
readTrustFile(join(dataDirectory, 'server.json')),
|
|
209
|
+
]);
|
|
210
|
+
const config = decodeTrustConfig(configText);
|
|
211
|
+
const identity = verifyCaIdentity(certificate, config.ca_spki_sha256);
|
|
212
|
+
return {
|
|
213
|
+
identity,
|
|
214
|
+
fetchImpl: createPinnedServerFetch(origin, certificate),
|
|
215
|
+
};
|
|
216
|
+
})();
|
|
217
|
+
trustCache.set(key, pending);
|
|
218
|
+
pending.catch(() => trustCache.delete(key));
|
|
219
|
+
}
|
|
220
|
+
return pending;
|
|
221
|
+
}
|
|
222
|
+
export function __clearServerTrustCacheForTest() {
|
|
223
|
+
trustCache.clear();
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=server-trust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-trust.js","sourceRoot":"","sources":["../src/server-trust.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ActiveCube } from './cubes.js';
|
|
2
|
+
import { prepareSeatReplacement, promoteSeatReplacement, refreshActiveSeatSession, scrubSeatReplacement, type SeatRecord } from './seats.js';
|
|
3
|
+
export declare const SESSION_RENEWAL_LEAD_MS: number;
|
|
4
|
+
interface AttachOutcome {
|
|
5
|
+
result: 'created' | 'reused';
|
|
6
|
+
droneId: string;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
expiresAt: string;
|
|
9
|
+
}
|
|
10
|
+
interface SessionContinuityDeps {
|
|
11
|
+
now(): number;
|
|
12
|
+
randomCredential(): string;
|
|
13
|
+
getSeat(ref: string, binding: {
|
|
14
|
+
origin: string;
|
|
15
|
+
trustIdentity: string;
|
|
16
|
+
cubeId: string;
|
|
17
|
+
}): Promise<SeatRecord | null>;
|
|
18
|
+
getActive(): Promise<ActiveCube | null>;
|
|
19
|
+
getParentCredential(origin: string, trustIdentity: string): Promise<string | null>;
|
|
20
|
+
sendAttach(record: SeatRecord, bearer: string, parentCredential: string): Promise<AttachOutcome>;
|
|
21
|
+
prepareReplacement: typeof prepareSeatReplacement;
|
|
22
|
+
refreshSession: typeof refreshActiveSeatSession;
|
|
23
|
+
promoteReplacement: typeof promoteSeatReplacement;
|
|
24
|
+
scrubReplacement: typeof scrubSeatReplacement;
|
|
25
|
+
}
|
|
26
|
+
export declare function ensureLocalSessionFresh(active: ActiveCube): Promise<ActiveCube>;
|
|
27
|
+
export declare function recoverExpiredLocalSession(active: ActiveCube): Promise<ActiveCube>;
|
|
28
|
+
/** @internal */
|
|
29
|
+
export declare function __renewLocalSessionForTest(active: ActiveCube, mode: 'proactive' | 'expired', deps: SessionContinuityDeps): Promise<ActiveCube>;
|
|
30
|
+
/** @internal */
|
|
31
|
+
export declare function __resetSessionContinuityForTest(): void;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=session-continuity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-continuity.d.ts","sourceRoot":"","sources":["../src/session-continuity.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAK5D,OAAO,EAEL,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,oBAAoB,EAEpB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,uBAAuB,QAAa,CAAC;AAElD,UAAU,aAAa;IACrB,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,qBAAqB;IAC7B,GAAG,IAAI,MAAM,CAAC;IACd,gBAAgB,IAAI,MAAM,CAAC;IAC3B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACrH,SAAS,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACxC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnF,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjG,kBAAkB,EAAE,OAAO,sBAAsB,CAAC;IAClD,cAAc,EAAE,OAAO,wBAAwB,CAAC;IAChD,kBAAkB,EAAE,OAAO,sBAAsB,CAAC;IAClD,gBAAgB,EAAE,OAAO,oBAAoB,CAAC;CAC/C;AA8ND,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAE/E;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAElF;AAED,gBAAgB;AAChB,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,gBAAgB;AAChB,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { getServerCredential } from './config.js';
|
|
3
|
+
import { getActiveCube } from './cubes.js';
|
|
4
|
+
import { DroneEvictedError } from './drone-lifecycle.js';
|
|
5
|
+
import { sendBorgServerAttach } from './server-handshake.js';
|
|
6
|
+
import { BorgServerError, BorgServerTrustError } from './server-errors.js';
|
|
7
|
+
import { loadBorgServerTrust } from './server-trust.js';
|
|
8
|
+
import { getActiveSeat, prepareSeatReplacement, promoteSeatReplacement, refreshActiveSeatSession, scrubSeatReplacement, seatRef, } from './seats.js';
|
|
9
|
+
export const SESSION_RENEWAL_LEAD_MS = 5 * 60_000;
|
|
10
|
+
const defaultDeps = {
|
|
11
|
+
now: Date.now,
|
|
12
|
+
randomCredential: () => randomBytes(32).toString('base64url'),
|
|
13
|
+
getSeat: getActiveSeat,
|
|
14
|
+
getActive: getActiveCube,
|
|
15
|
+
getParentCredential: getServerCredential,
|
|
16
|
+
async sendAttach(record, bearer, parentCredential) {
|
|
17
|
+
const trust = await loadBorgServerTrust(record.origin);
|
|
18
|
+
if (trust.identity !== record.trustIdentity) {
|
|
19
|
+
throw new BorgServerTrustError('Borg server trust identity changed; refusing session renewal');
|
|
20
|
+
}
|
|
21
|
+
const attached = await sendBorgServerAttach(record.origin, record.trustIdentity, parentCredential, {
|
|
22
|
+
cubeId: record.cubeId,
|
|
23
|
+
roleId: record.roleId,
|
|
24
|
+
operation: record.operation,
|
|
25
|
+
priorDroneId: record.droneId,
|
|
26
|
+
}, bearer, { fetchImpl: trust.fetchImpl });
|
|
27
|
+
return {
|
|
28
|
+
result: attached.result,
|
|
29
|
+
droneId: attached.drone.id,
|
|
30
|
+
sessionId: attached.session.sessionId,
|
|
31
|
+
expiresAt: attached.session.expiresAt,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
prepareReplacement: prepareSeatReplacement,
|
|
35
|
+
refreshSession: refreshActiveSeatSession,
|
|
36
|
+
promoteReplacement: promoteSeatReplacement,
|
|
37
|
+
scrubReplacement: scrubSeatReplacement,
|
|
38
|
+
};
|
|
39
|
+
const inflight = new Map();
|
|
40
|
+
const digestOf = (value) => createHash('sha256').update(value).digest('hex');
|
|
41
|
+
function sameSeat(active, candidate) {
|
|
42
|
+
return candidate !== null &&
|
|
43
|
+
candidate.apiUrl === active.apiUrl &&
|
|
44
|
+
candidate.serverTrustIdentity === active.serverTrustIdentity &&
|
|
45
|
+
candidate.cubeId === active.cubeId &&
|
|
46
|
+
candidate.droneId === active.droneId &&
|
|
47
|
+
candidate.localSessionCredentialRef === active.localSessionCredentialRef;
|
|
48
|
+
}
|
|
49
|
+
function seatBinding(record) {
|
|
50
|
+
return {
|
|
51
|
+
origin: record.origin,
|
|
52
|
+
trustIdentity: record.trustIdentity,
|
|
53
|
+
cubeId: record.cubeId,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function validActiveRecord(active, record) {
|
|
57
|
+
return record !== null &&
|
|
58
|
+
record.state === 'active' &&
|
|
59
|
+
record.origin === active.apiUrl &&
|
|
60
|
+
record.trustIdentity === active.serverTrustIdentity &&
|
|
61
|
+
record.cubeId === active.cubeId &&
|
|
62
|
+
record.droneId === active.droneId &&
|
|
63
|
+
seatRef(record) === active.localSessionCredentialRef;
|
|
64
|
+
}
|
|
65
|
+
function deterministicAttachFailure(error) {
|
|
66
|
+
return error instanceof BorgServerError ||
|
|
67
|
+
error instanceof BorgServerTrustError ||
|
|
68
|
+
error instanceof DroneEvictedError;
|
|
69
|
+
}
|
|
70
|
+
async function reloadSameSeat(active, deps, requireFreshCredential = false) {
|
|
71
|
+
const current = await deps.getActive();
|
|
72
|
+
if (!sameSeat(active, current) || (requireFreshCredential && current.sessionToken === active.sessionToken)) {
|
|
73
|
+
throw new Error('Session renewal no longer targets the same saved seat');
|
|
74
|
+
}
|
|
75
|
+
return current;
|
|
76
|
+
}
|
|
77
|
+
async function performRenewal(active, mode, deps) {
|
|
78
|
+
if (!active.serverTrustIdentity || !active.localSessionCredentialRef) {
|
|
79
|
+
throw new Error('Selected Borg server authority state is missing or unreadable');
|
|
80
|
+
}
|
|
81
|
+
const binding = {
|
|
82
|
+
origin: active.apiUrl,
|
|
83
|
+
trustIdentity: active.serverTrustIdentity,
|
|
84
|
+
cubeId: active.cubeId,
|
|
85
|
+
};
|
|
86
|
+
const record = await deps.getSeat(active.localSessionCredentialRef, binding);
|
|
87
|
+
if (!validActiveRecord(active, record)) {
|
|
88
|
+
throw new Error('Session renewal no longer targets the same saved seat');
|
|
89
|
+
}
|
|
90
|
+
const activeDigest = digestOf(active.sessionToken);
|
|
91
|
+
if (digestOf(record.credential) !== activeDigest) {
|
|
92
|
+
return reloadSameSeat(active, deps, true);
|
|
93
|
+
}
|
|
94
|
+
const expiresIn = Date.parse(record.expiresAt) - deps.now();
|
|
95
|
+
if (mode === 'proactive' && expiresIn > SESSION_RENEWAL_LEAD_MS && record.replacement === undefined) {
|
|
96
|
+
return active;
|
|
97
|
+
}
|
|
98
|
+
const parentCredential = await deps.getParentCredential(record.origin, record.trustIdentity);
|
|
99
|
+
if (!parentCredential)
|
|
100
|
+
throw new Error('Selected Borg server parent credential is missing or unreadable');
|
|
101
|
+
const recordBinding = seatBinding(record);
|
|
102
|
+
let restoreRequired = mode === 'expired' || expiresIn <= 0 || record.replacement !== undefined;
|
|
103
|
+
if (!restoreRequired) {
|
|
104
|
+
let attached = null;
|
|
105
|
+
try {
|
|
106
|
+
attached = await deps.sendAttach(record, record.credential, parentCredential);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (error instanceof BorgServerError && error.code === 'AUTH_EXPIRED') {
|
|
110
|
+
restoreRequired = true;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!restoreRequired) {
|
|
117
|
+
if (!attached)
|
|
118
|
+
throw new Error('Session renewal returned no result');
|
|
119
|
+
const renewedExpiry = Date.parse(attached.expiresAt);
|
|
120
|
+
if (attached.result !== 'reused' ||
|
|
121
|
+
attached.droneId !== record.droneId ||
|
|
122
|
+
attached.sessionId !== record.sessionId ||
|
|
123
|
+
!Number.isFinite(renewedExpiry) ||
|
|
124
|
+
renewedExpiry <= Date.parse(record.expiresAt)) {
|
|
125
|
+
throw new Error('Session renewal did not preserve the same saved seat');
|
|
126
|
+
}
|
|
127
|
+
const refreshed = await deps.refreshSession({
|
|
128
|
+
ref: active.localSessionCredentialRef,
|
|
129
|
+
binding: recordBinding,
|
|
130
|
+
expectedDroneId: record.droneId,
|
|
131
|
+
expectedActiveDigest: activeDigest,
|
|
132
|
+
expectedSessionId: record.sessionId,
|
|
133
|
+
expiresAt: attached.expiresAt,
|
|
134
|
+
});
|
|
135
|
+
if (!refreshed)
|
|
136
|
+
return reloadSameSeat(active, deps);
|
|
137
|
+
return reloadSameSeat(active, deps);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const replacement = await deps.prepareReplacement({
|
|
141
|
+
ref: active.localSessionCredentialRef,
|
|
142
|
+
binding: recordBinding,
|
|
143
|
+
expectedDroneId: record.droneId,
|
|
144
|
+
expectedActiveDigest: activeDigest,
|
|
145
|
+
replacementCredential: deps.randomCredential(),
|
|
146
|
+
});
|
|
147
|
+
if (!replacement.ok)
|
|
148
|
+
return reloadSameSeat(active, deps, true);
|
|
149
|
+
let attached;
|
|
150
|
+
try {
|
|
151
|
+
attached = await deps.sendAttach(record, replacement.credential, parentCredential);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (deterministicAttachFailure(error)) {
|
|
155
|
+
await deps.scrubReplacement({
|
|
156
|
+
ref: active.localSessionCredentialRef,
|
|
157
|
+
binding: recordBinding,
|
|
158
|
+
expectedActiveDigest: activeDigest,
|
|
159
|
+
expectedReplacementDigest: replacement.digest,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
const restoredExpiry = Date.parse(attached.expiresAt);
|
|
165
|
+
if ((attached.result !== 'created' && attached.result !== 'reused') ||
|
|
166
|
+
attached.droneId !== record.droneId ||
|
|
167
|
+
attached.sessionId === record.sessionId ||
|
|
168
|
+
!Number.isFinite(restoredExpiry) ||
|
|
169
|
+
restoredExpiry <= deps.now()) {
|
|
170
|
+
await deps.scrubReplacement({
|
|
171
|
+
ref: active.localSessionCredentialRef,
|
|
172
|
+
binding: recordBinding,
|
|
173
|
+
expectedActiveDigest: activeDigest,
|
|
174
|
+
expectedReplacementDigest: replacement.digest,
|
|
175
|
+
});
|
|
176
|
+
throw new Error('Session renewal did not preserve the same saved seat');
|
|
177
|
+
}
|
|
178
|
+
const promoted = await deps.promoteReplacement({
|
|
179
|
+
ref: active.localSessionCredentialRef,
|
|
180
|
+
binding: recordBinding,
|
|
181
|
+
expectedDroneId: record.droneId,
|
|
182
|
+
expectedActiveDigest: activeDigest,
|
|
183
|
+
expectedReplacementDigest: replacement.digest,
|
|
184
|
+
sessionId: attached.sessionId,
|
|
185
|
+
expiresAt: attached.expiresAt,
|
|
186
|
+
});
|
|
187
|
+
if (promoted !== 'promoted')
|
|
188
|
+
return reloadSameSeat(active, deps, true);
|
|
189
|
+
return reloadSameSeat(active, deps, true);
|
|
190
|
+
}
|
|
191
|
+
function renewLocalSession(active, mode, deps) {
|
|
192
|
+
const key = active.localSessionCredentialRef;
|
|
193
|
+
if (!key)
|
|
194
|
+
return Promise.reject(new Error('Selected Borg server authority state is missing or unreadable'));
|
|
195
|
+
const existing = inflight.get(key);
|
|
196
|
+
if (existing)
|
|
197
|
+
return existing;
|
|
198
|
+
const renewal = performRenewal(active, mode, deps);
|
|
199
|
+
inflight.set(key, renewal);
|
|
200
|
+
void renewal.finally(() => {
|
|
201
|
+
if (inflight.get(key) === renewal)
|
|
202
|
+
inflight.delete(key);
|
|
203
|
+
}).catch(() => { });
|
|
204
|
+
return renewal;
|
|
205
|
+
}
|
|
206
|
+
export function ensureLocalSessionFresh(active) {
|
|
207
|
+
return renewLocalSession(active, 'proactive', defaultDeps);
|
|
208
|
+
}
|
|
209
|
+
export function recoverExpiredLocalSession(active) {
|
|
210
|
+
return renewLocalSession(active, 'expired', defaultDeps);
|
|
211
|
+
}
|
|
212
|
+
/** @internal */
|
|
213
|
+
export function __renewLocalSessionForTest(active, mode, deps) {
|
|
214
|
+
return renewLocalSession(active, mode, deps);
|
|
215
|
+
}
|
|
216
|
+
/** @internal */
|
|
217
|
+
export function __resetSessionContinuityForTest() {
|
|
218
|
+
inflight.clear();
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=session-continuity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-continuity.js","sourceRoot":"","sources":["../src/session-continuity.ts"],"names":[],"mappings":"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"}
|
package/dist/setup-confirm.d.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*
|
|
13
13
|
* SECURITY (SR-light, gh#818 221c43df): the disclosure lists file PATHS +
|
|
14
14
|
* at most the PUBLIC `BORG_API_URL` — there is NO token/secret in the
|
|
15
|
-
* written config to echo.
|
|
16
|
-
*
|
|
15
|
+
* written config to echo. Local credentials live in the local 0600-permission
|
|
16
|
+
* seat store, and the written config never contains a token or secret.
|
|
17
17
|
*/
|
|
18
18
|
export interface ConfigMutationTarget {
|
|
19
19
|
/** Human-readable config file path (tilde form). */
|
|
@@ -77,7 +77,7 @@ export declare function parseYesFlag(argv: string[]): boolean;
|
|
|
77
77
|
*
|
|
78
78
|
* The disclosure + confirm prompt exists to obtain informed consent for the
|
|
79
79
|
* config writes Step-1 performs (gh#818). On a pure refresh — the normal
|
|
80
|
-
*
|
|
80
|
+
* setup re-run where every DETECTED agent CLI already has the full
|
|
81
81
|
* borg setup (MCP server registered AND every hook write already applied) —
|
|
82
82
|
* there is no mutation to consent to, so the prompt is redundant and skipped.
|
|
83
83
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-confirm.d.ts","sourceRoot":"","sources":["../src/setup-confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,oBAAoB,EAAE,CA6BzB;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,oBAAoB,EAAE,GAC9B,MAAM,CAUR;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACxC,sCAAsC;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,sCAAsC;IACtC,GAAG,EAAE,OAAO,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAK1B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAEpD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAMV"}
|