@paperclipai/server 2026.817.0 → 2026.818.0-beta.1
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/dist/adapters/hermes-gateway-doc.d.ts +1 -1
- package/dist/adapters/hermes-gateway-doc.d.ts.map +1 -1
- package/dist/adapters/hermes-gateway-doc.js +1 -1
- package/dist/adapters/plugin-loader.d.ts.map +1 -1
- package/dist/adapters/plugin-loader.js +3 -2
- package/dist/adapters/plugin-loader.js.map +1 -1
- package/dist/agent-auth-jwt.d.ts.map +1 -1
- package/dist/agent-auth-jwt.js +8 -2
- package/dist/agent-auth-jwt.js.map +1 -1
- package/dist/app.d.ts +5 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +202 -15
- package/dist/app.js.map +1 -1
- package/dist/built-ins/agents/summarizer/AGENTS.md +2 -2
- package/dist/built-ins/agents/summarizer/routines/refresh-stale-summaries.md +1 -0
- package/dist/db-errors.d.ts +9 -0
- package/dist/db-errors.d.ts.map +1 -1
- package/dist/db-errors.js +19 -0
- package/dist/db-errors.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +162 -38
- package/dist/index.js.map +1 -1
- package/dist/lib/request-promise-memo.d.ts +6 -0
- package/dist/lib/request-promise-memo.d.ts.map +1 -0
- package/dist/lib/request-promise-memo.js +25 -0
- package/dist/lib/request-promise-memo.js.map +1 -0
- package/dist/lib/request-promise-memo.test.d.ts +2 -0
- package/dist/lib/request-promise-memo.test.d.ts.map +1 -0
- package/dist/lib/request-promise-memo.test.js +74 -0
- package/dist/lib/request-promise-memo.test.js.map +1 -0
- package/dist/middleware/auth.d.ts +13 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +92 -41
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/cloud-tenant-actor.test.js +26 -1
- package/dist/middleware/cloud-tenant-actor.test.js.map +1 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +11 -2
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +7 -33
- package/dist/middleware/logger.js.map +1 -1
- package/dist/middleware/private-hostname-guard.d.ts.map +1 -1
- package/dist/middleware/private-hostname-guard.js +11 -6
- package/dist/middleware/private-hostname-guard.js.map +1 -1
- package/dist/middleware/private-json-etag.d.ts +3 -0
- package/dist/middleware/private-json-etag.d.ts.map +1 -0
- package/dist/middleware/private-json-etag.js +37 -0
- package/dist/middleware/private-json-etag.js.map +1 -0
- package/dist/middleware/redact-sensitive.d.ts.map +1 -1
- package/dist/middleware/redact-sensitive.js +11 -0
- package/dist/middleware/redact-sensitive.js.map +1 -1
- package/dist/realtime/live-events-ws.d.ts +12 -0
- package/dist/realtime/live-events-ws.d.ts.map +1 -1
- package/dist/realtime/live-events-ws.js +20 -0
- package/dist/realtime/live-events-ws.js.map +1 -1
- package/dist/redaction.js +1 -1
- package/dist/redaction.js.map +1 -1
- package/dist/routes/access.d.ts +2 -0
- package/dist/routes/access.d.ts.map +1 -1
- package/dist/routes/access.js +21 -10
- package/dist/routes/access.js.map +1 -1
- package/dist/routes/agents.d.ts +42 -0
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +875 -8
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/companies.d.ts +5 -1
- package/dist/routes/companies.d.ts.map +1 -1
- package/dist/routes/companies.js +467 -30
- package/dist/routes/companies.js.map +1 -1
- package/dist/routes/environments.d.ts +12 -3
- package/dist/routes/environments.d.ts.map +1 -1
- package/dist/routes/environments.js +139 -23
- package/dist/routes/environments.js.map +1 -1
- package/dist/routes/execution-workspaces.d.ts.map +1 -1
- package/dist/routes/execution-workspaces.js +240 -70
- package/dist/routes/execution-workspaces.js.map +1 -1
- package/dist/routes/file-resources.d.ts +14 -1
- package/dist/routes/file-resources.d.ts.map +1 -1
- package/dist/routes/file-resources.js +182 -3
- package/dist/routes/file-resources.js.map +1 -1
- package/dist/routes/index.d.ts +2 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +2 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/instance-settings.d.ts.map +1 -1
- package/dist/routes/instance-settings.js +20 -1
- package/dist/routes/instance-settings.js.map +1 -1
- package/dist/routes/issues.d.ts.map +1 -1
- package/dist/routes/issues.js +750 -235
- package/dist/routes/issues.js.map +1 -1
- package/dist/routes/onboarding-seed.d.ts +27 -0
- package/dist/routes/onboarding-seed.d.ts.map +1 -0
- package/dist/routes/onboarding-seed.js +56 -0
- package/dist/routes/onboarding-seed.js.map +1 -0
- package/dist/routes/openapi.d.ts.map +1 -1
- package/dist/routes/openapi.js +316 -2
- package/dist/routes/openapi.js.map +1 -1
- package/dist/routes/secrets.d.ts.map +1 -1
- package/dist/routes/secrets.js +11 -1
- package/dist/routes/secrets.js.map +1 -1
- package/dist/routes/setup-token-route.test.d.ts +2 -0
- package/dist/routes/setup-token-route.test.d.ts.map +1 -0
- package/dist/routes/setup-token-route.test.js +896 -0
- package/dist/routes/setup-token-route.test.js.map +1 -0
- package/dist/routes/tool-access.d.ts.map +1 -1
- package/dist/routes/tool-access.js +87 -52
- package/dist/routes/tool-access.js.map +1 -1
- package/dist/routes/workspace-runtime-service-authz.d.ts +11 -1
- package/dist/routes/workspace-runtime-service-authz.d.ts.map +1 -1
- package/dist/routes/workspace-runtime-service-authz.js +18 -16
- package/dist/routes/workspace-runtime-service-authz.js.map +1 -1
- package/dist/services/access.d.ts.map +1 -1
- package/dist/services/activity.d.ts +1 -1
- package/dist/services/agents.d.ts +21 -0
- package/dist/services/agents.d.ts.map +1 -1
- package/dist/services/agents.js +121 -1
- package/dist/services/agents.js.map +1 -1
- package/dist/services/attention-resolver-audience.test.d.ts +2 -0
- package/dist/services/attention-resolver-audience.test.d.ts.map +1 -0
- package/dist/services/attention-resolver-audience.test.js +81 -0
- package/dist/services/attention-resolver-audience.test.js.map +1 -0
- package/dist/services/attention.d.ts +20 -1
- package/dist/services/attention.d.ts.map +1 -1
- package/dist/services/attention.js +45 -1
- package/dist/services/attention.js.map +1 -1
- package/dist/services/authorization.d.ts +2 -2
- package/dist/services/authorization.d.ts.map +1 -1
- package/dist/services/authorization.js +89 -46
- package/dist/services/authorization.js.map +1 -1
- package/dist/services/board-auth.d.ts.map +1 -1
- package/dist/services/board-auth.js +40 -1
- package/dist/services/board-auth.js.map +1 -1
- package/dist/services/board-auth.test.d.ts +2 -0
- package/dist/services/board-auth.test.d.ts.map +1 -0
- package/dist/services/board-auth.test.js +34 -0
- package/dist/services/board-auth.test.js.map +1 -0
- package/dist/services/built-in-agents.d.ts.map +1 -1
- package/dist/services/built-in-agents.js +20 -4
- package/dist/services/built-in-agents.js.map +1 -1
- package/dist/services/bundled-plugins.d.ts +11 -1
- package/dist/services/bundled-plugins.d.ts.map +1 -1
- package/dist/services/bundled-plugins.js +46 -1
- package/dist/services/bundled-plugins.js.map +1 -1
- package/dist/services/codex-device-login-reaper.d.ts +61 -0
- package/dist/services/codex-device-login-reaper.d.ts.map +1 -0
- package/dist/services/codex-device-login-reaper.js +219 -0
- package/dist/services/codex-device-login-reaper.js.map +1 -0
- package/dist/services/codex-device-login-service.d.ts +355 -0
- package/dist/services/codex-device-login-service.d.ts.map +1 -0
- package/dist/services/codex-device-login-service.js +775 -0
- package/dist/services/codex-device-login-service.js.map +1 -0
- package/dist/services/companies.d.ts.map +1 -1
- package/dist/services/companies.js +7 -0
- package/dist/services/companies.js.map +1 -1
- package/dist/services/company-export-readme.js +1 -1
- package/dist/services/company-export-readme.js.map +1 -1
- package/dist/services/company-import-transfers.d.ts +55 -0
- package/dist/services/company-import-transfers.d.ts.map +1 -0
- package/dist/services/company-import-transfers.js +151 -0
- package/dist/services/company-import-transfers.js.map +1 -0
- package/dist/services/company-portability.d.ts.map +1 -1
- package/dist/services/company-portability.js +128 -3
- package/dist/services/company-portability.js.map +1 -1
- package/dist/services/company-transfer-runs.d.ts +136 -0
- package/dist/services/company-transfer-runs.d.ts.map +1 -0
- package/dist/services/company-transfer-runs.js +243 -0
- package/dist/services/company-transfer-runs.js.map +1 -0
- package/dist/services/cross-issue-influence-limit.d.ts +7 -1
- package/dist/services/cross-issue-influence-limit.d.ts.map +1 -1
- package/dist/services/cross-issue-influence-limit.js.map +1 -1
- package/dist/services/environment-config.d.ts +15 -0
- package/dist/services/environment-config.d.ts.map +1 -1
- package/dist/services/environment-config.js +56 -10
- package/dist/services/environment-config.js.map +1 -1
- package/dist/services/environment-execution-target.d.ts.map +1 -1
- package/dist/services/environment-execution-target.js +61 -11
- package/dist/services/environment-execution-target.js.map +1 -1
- package/dist/services/environment-run-orchestrator.d.ts +16 -1
- package/dist/services/environment-run-orchestrator.d.ts.map +1 -1
- package/dist/services/environment-run-orchestrator.js +1 -1
- package/dist/services/environment-run-orchestrator.js.map +1 -1
- package/dist/services/environment-runtime.d.ts +178 -2
- package/dist/services/environment-runtime.d.ts.map +1 -1
- package/dist/services/environment-runtime.js +1035 -96
- package/dist/services/environment-runtime.js.map +1 -1
- package/dist/services/environments.d.ts +75 -0
- package/dist/services/environments.d.ts.map +1 -1
- package/dist/services/environments.js +199 -8
- package/dist/services/environments.js.map +1 -1
- package/dist/services/execution-allowlist.d.ts +16 -4
- package/dist/services/execution-allowlist.d.ts.map +1 -1
- package/dist/services/execution-allowlist.js +35 -16
- package/dist/services/execution-allowlist.js.map +1 -1
- package/dist/services/execution-allowlist.test.js +33 -0
- package/dist/services/execution-allowlist.test.js.map +1 -1
- package/dist/services/execution-workspace-policy.d.ts +14 -1
- package/dist/services/execution-workspace-policy.d.ts.map +1 -1
- package/dist/services/execution-workspace-policy.js +29 -12
- package/dist/services/execution-workspace-policy.js.map +1 -1
- package/dist/services/execution-workspaces.d.ts +89 -0
- package/dist/services/execution-workspaces.d.ts.map +1 -1
- package/dist/services/execution-workspaces.js +997 -125
- package/dist/services/execution-workspaces.js.map +1 -1
- package/dist/services/heartbeat-run-summary.d.ts +1 -0
- package/dist/services/heartbeat-run-summary.d.ts.map +1 -1
- package/dist/services/heartbeat-run-summary.js +19 -3
- package/dist/services/heartbeat-run-summary.js.map +1 -1
- package/dist/services/heartbeat.d.ts +18 -2
- package/dist/services/heartbeat.d.ts.map +1 -1
- package/dist/services/heartbeat.js +369 -16
- package/dist/services/heartbeat.js.map +1 -1
- package/dist/services/import-write-types.d.ts +12 -0
- package/dist/services/import-write-types.d.ts.map +1 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +2 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/instance-settings.d.ts +10 -1
- package/dist/services/instance-settings.d.ts.map +1 -1
- package/dist/services/instance-settings.js +16 -9
- package/dist/services/instance-settings.js.map +1 -1
- package/dist/services/issue-review-policy.d.ts +4 -0
- package/dist/services/issue-review-policy.d.ts.map +1 -1
- package/dist/services/issue-review-policy.js +18 -7
- package/dist/services/issue-review-policy.js.map +1 -1
- package/dist/services/issue-thread-interaction-resolution.d.ts +92 -0
- package/dist/services/issue-thread-interaction-resolution.d.ts.map +1 -0
- package/dist/services/issue-thread-interaction-resolution.js +198 -0
- package/dist/services/issue-thread-interaction-resolution.js.map +1 -0
- package/dist/services/issue-thread-interaction-resolution.test.d.ts +2 -0
- package/dist/services/issue-thread-interaction-resolution.test.d.ts.map +1 -0
- package/dist/services/issue-thread-interaction-resolution.test.js +152 -0
- package/dist/services/issue-thread-interaction-resolution.test.js.map +1 -0
- package/dist/services/issue-thread-interactions.d.ts +24 -4
- package/dist/services/issue-thread-interactions.d.ts.map +1 -1
- package/dist/services/issue-thread-interactions.js +360 -145
- package/dist/services/issue-thread-interactions.js.map +1 -1
- package/dist/services/issue-thread-interactions.test.js +18 -11
- package/dist/services/issue-thread-interactions.test.js.map +1 -1
- package/dist/services/issues.d.ts +3 -0
- package/dist/services/issues.d.ts.map +1 -1
- package/dist/services/issues.js +157 -33
- package/dist/services/issues.js.map +1 -1
- package/dist/services/local-service-supervisor.d.ts +2 -0
- package/dist/services/local-service-supervisor.d.ts.map +1 -1
- package/dist/services/local-service-supervisor.js +53 -3
- package/dist/services/local-service-supervisor.js.map +1 -1
- package/dist/services/managed-environments.d.ts +4 -1
- package/dist/services/managed-environments.d.ts.map +1 -1
- package/dist/services/managed-environments.js +86 -2
- package/dist/services/managed-environments.js.map +1 -1
- package/dist/services/managed-environments.test.js +164 -0
- package/dist/services/managed-environments.test.js.map +1 -1
- package/dist/services/onboarding-greeting.d.ts +7 -0
- package/dist/services/onboarding-greeting.d.ts.map +1 -0
- package/dist/services/onboarding-greeting.js +27 -0
- package/dist/services/onboarding-greeting.js.map +1 -0
- package/dist/services/onboarding-greeting.test.d.ts +2 -0
- package/dist/services/onboarding-greeting.test.d.ts.map +1 -0
- package/dist/services/onboarding-greeting.test.js +32 -0
- package/dist/services/onboarding-greeting.test.js.map +1 -0
- package/dist/services/onboarding-seed.d.ts +57 -0
- package/dist/services/onboarding-seed.d.ts.map +1 -0
- package/dist/services/onboarding-seed.js +344 -0
- package/dist/services/onboarding-seed.js.map +1 -0
- package/dist/services/plan-review-context.d.ts +9 -1
- package/dist/services/plan-review-context.d.ts.map +1 -1
- package/dist/services/plan-review-context.js +192 -0
- package/dist/services/plan-review-context.js.map +1 -1
- package/dist/services/plugin-environment-driver.d.ts +46 -0
- package/dist/services/plugin-environment-driver.d.ts.map +1 -1
- package/dist/services/plugin-environment-driver.js +50 -0
- package/dist/services/plugin-environment-driver.js.map +1 -1
- package/dist/services/plugin-host-services.d.ts +1 -0
- package/dist/services/plugin-host-services.d.ts.map +1 -1
- package/dist/services/plugin-host-services.js +51 -28
- package/dist/services/plugin-host-services.js.map +1 -1
- package/dist/services/plugin-loader.d.ts +10 -1
- package/dist/services/plugin-loader.d.ts.map +1 -1
- package/dist/services/plugin-loader.js +43 -2
- package/dist/services/plugin-loader.js.map +1 -1
- package/dist/services/plugin-worker-manager.d.ts +61 -0
- package/dist/services/plugin-worker-manager.d.ts.map +1 -1
- package/dist/services/plugin-worker-manager.js +248 -1
- package/dist/services/plugin-worker-manager.js.map +1 -1
- package/dist/services/productivity-review.d.ts.map +1 -1
- package/dist/services/productivity-review.js +5 -0
- package/dist/services/productivity-review.js.map +1 -1
- package/dist/services/recovery/service.d.ts.map +1 -1
- package/dist/services/recovery/service.js +5 -1
- package/dist/services/recovery/service.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.d.ts +16 -1
- package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
- package/dist/services/recovery/successful-run-handoff.js +32 -0
- package/dist/services/recovery/successful-run-handoff.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.test.js +51 -1
- package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
- package/dist/services/routines.d.ts.map +1 -1
- package/dist/services/routines.js +48 -4
- package/dist/services/routines.js.map +1 -1
- package/dist/services/runtime-exposure/broker-client.d.ts +88 -0
- package/dist/services/runtime-exposure/broker-client.d.ts.map +1 -0
- package/dist/services/runtime-exposure/broker-client.js +217 -0
- package/dist/services/runtime-exposure/broker-client.js.map +1 -0
- package/dist/services/runtime-exposure/broker-client.test.d.ts +2 -0
- package/dist/services/runtime-exposure/broker-client.test.d.ts.map +1 -0
- package/dist/services/runtime-exposure/broker-client.test.js +185 -0
- package/dist/services/runtime-exposure/broker-client.test.js.map +1 -0
- package/dist/services/runtime-exposure/exposure-manager.d.ts +135 -0
- package/dist/services/runtime-exposure/exposure-manager.d.ts.map +1 -0
- package/dist/services/runtime-exposure/exposure-manager.js +247 -0
- package/dist/services/runtime-exposure/exposure-manager.js.map +1 -0
- package/dist/services/runtime-exposure/exposure-manager.test.d.ts +2 -0
- package/dist/services/runtime-exposure/exposure-manager.test.d.ts.map +1 -0
- package/dist/services/runtime-exposure/exposure-manager.test.js +384 -0
- package/dist/services/runtime-exposure/exposure-manager.test.js.map +1 -0
- package/dist/services/runtime-exposure/loopback-listener.d.ts +33 -0
- package/dist/services/runtime-exposure/loopback-listener.d.ts.map +1 -0
- package/dist/services/runtime-exposure/loopback-listener.js +146 -0
- package/dist/services/runtime-exposure/loopback-listener.js.map +1 -0
- package/dist/services/runtime-exposure/loopback-listener.test.d.ts +2 -0
- package/dist/services/runtime-exposure/loopback-listener.test.d.ts.map +1 -0
- package/dist/services/runtime-exposure/loopback-listener.test.js +116 -0
- package/dist/services/runtime-exposure/loopback-listener.test.js.map +1 -0
- package/dist/services/runtime-exposure/port-pair.d.ts +47 -0
- package/dist/services/runtime-exposure/port-pair.d.ts.map +1 -0
- package/dist/services/runtime-exposure/port-pair.js +57 -0
- package/dist/services/runtime-exposure/port-pair.js.map +1 -0
- package/dist/services/runtime-exposure/port-pair.test.d.ts +2 -0
- package/dist/services/runtime-exposure/port-pair.test.d.ts.map +1 -0
- package/dist/services/runtime-exposure/port-pair.test.js +92 -0
- package/dist/services/runtime-exposure/port-pair.test.js.map +1 -0
- package/dist/services/runtime-exposure/port-reservation.d.ts +211 -0
- package/dist/services/runtime-exposure/port-reservation.d.ts.map +1 -0
- package/dist/services/runtime-exposure/port-reservation.js +380 -0
- package/dist/services/runtime-exposure/port-reservation.js.map +1 -0
- package/dist/services/runtime-exposure/port-reservation.test.d.ts +2 -0
- package/dist/services/runtime-exposure/port-reservation.test.d.ts.map +1 -0
- package/dist/services/runtime-exposure/port-reservation.test.js +456 -0
- package/dist/services/runtime-exposure/port-reservation.test.js.map +1 -0
- package/dist/services/runtime-exposure/tailscale-hostname.d.ts +11 -0
- package/dist/services/runtime-exposure/tailscale-hostname.d.ts.map +1 -0
- package/dist/services/runtime-exposure/tailscale-hostname.js +36 -0
- package/dist/services/runtime-exposure/tailscale-hostname.js.map +1 -0
- package/dist/services/runtime-exposure/tailscale-hostname.test.d.ts +2 -0
- package/dist/services/runtime-exposure/tailscale-hostname.test.d.ts.map +1 -0
- package/dist/services/runtime-exposure/tailscale-hostname.test.js +14 -0
- package/dist/services/runtime-exposure/tailscale-hostname.test.js.map +1 -0
- package/dist/services/sandbox-orphan-cleanup-spool.d.ts +64 -0
- package/dist/services/sandbox-orphan-cleanup-spool.d.ts.map +1 -0
- package/dist/services/sandbox-orphan-cleanup-spool.js +134 -0
- package/dist/services/sandbox-orphan-cleanup-spool.js.map +1 -0
- package/dist/services/sandbox-provider-runtime.d.ts +15 -0
- package/dist/services/sandbox-provider-runtime.d.ts.map +1 -1
- package/dist/services/sandbox-provider-runtime.js +1 -0
- package/dist/services/sandbox-provider-runtime.js.map +1 -1
- package/dist/services/secrets.d.ts +103 -0
- package/dist/services/secrets.d.ts.map +1 -1
- package/dist/services/secrets.js +432 -10
- package/dist/services/secrets.js.map +1 -1
- package/dist/services/setup-token-session.d.ts +630 -0
- package/dist/services/setup-token-session.d.ts.map +1 -0
- package/dist/services/setup-token-session.js +1005 -0
- package/dist/services/setup-token-session.js.map +1 -0
- package/dist/services/setup-token-session.test.d.ts +2 -0
- package/dist/services/setup-token-session.test.d.ts.map +1 -0
- package/dist/services/setup-token-session.test.js +1143 -0
- package/dist/services/setup-token-session.test.js.map +1 -0
- package/dist/services/setup-token-transport-binding.d.ts +202 -0
- package/dist/services/setup-token-transport-binding.d.ts.map +1 -0
- package/dist/services/setup-token-transport-binding.js +386 -0
- package/dist/services/setup-token-transport-binding.js.map +1 -0
- package/dist/services/setup-token-transport-binding.test.d.ts +2 -0
- package/dist/services/setup-token-transport-binding.test.d.ts.map +1 -0
- package/dist/services/setup-token-transport-binding.test.js +761 -0
- package/dist/services/setup-token-transport-binding.test.js.map +1 -0
- package/dist/services/summary-slots.d.ts.map +1 -1
- package/dist/services/summary-slots.js +40 -6
- package/dist/services/summary-slots.js.map +1 -1
- package/dist/services/task-watchdogs.js +2 -2
- package/dist/services/task-watchdogs.js.map +1 -1
- package/dist/services/tool-access-policy.d.ts +1 -1
- package/dist/services/tool-access.d.ts.map +1 -1
- package/dist/services/tool-access.js +29 -11
- package/dist/services/tool-access.js.map +1 -1
- package/dist/services/tool-gateway.d.ts +1 -1
- package/dist/services/tool-gateway.d.ts.map +1 -1
- package/dist/services/tool-gateway.js +56 -5
- package/dist/services/tool-gateway.js.map +1 -1
- package/dist/services/workspace-file-resources.d.ts +10 -1
- package/dist/services/workspace-file-resources.d.ts.map +1 -1
- package/dist/services/workspace-file-resources.js +258 -6
- package/dist/services/workspace-file-resources.js.map +1 -1
- package/dist/services/workspace-git-operation-scheduler.d.ts +135 -0
- package/dist/services/workspace-git-operation-scheduler.d.ts.map +1 -0
- package/dist/services/workspace-git-operation-scheduler.js +655 -0
- package/dist/services/workspace-git-operation-scheduler.js.map +1 -0
- package/dist/services/workspace-git-operation-scheduler.test.d.ts +2 -0
- package/dist/services/workspace-git-operation-scheduler.test.d.ts.map +1 -0
- package/dist/services/workspace-git-operation-scheduler.test.js +367 -0
- package/dist/services/workspace-git-operation-scheduler.test.js.map +1 -0
- package/dist/services/workspace-operations.d.ts +60 -0
- package/dist/services/workspace-operations.d.ts.map +1 -1
- package/dist/services/workspace-operations.js +384 -19
- package/dist/services/workspace-operations.js.map +1 -1
- package/dist/services/workspace-runtime-exposure-backfill.test.d.ts +2 -0
- package/dist/services/workspace-runtime-exposure-backfill.test.d.ts.map +1 -0
- package/dist/services/workspace-runtime-exposure-backfill.test.js +149 -0
- package/dist/services/workspace-runtime-exposure-backfill.test.js.map +1 -0
- package/dist/services/workspace-runtime-exposure.test.d.ts +2 -0
- package/dist/services/workspace-runtime-exposure.test.d.ts.map +1 -0
- package/dist/services/workspace-runtime-exposure.test.js +517 -0
- package/dist/services/workspace-runtime-exposure.test.js.map +1 -0
- package/dist/services/workspace-runtime-leases.d.ts +90 -0
- package/dist/services/workspace-runtime-leases.d.ts.map +1 -0
- package/dist/services/workspace-runtime-leases.js +252 -0
- package/dist/services/workspace-runtime-leases.js.map +1 -0
- package/dist/services/workspace-runtime-read-model.d.ts +12 -0
- package/dist/services/workspace-runtime-read-model.d.ts.map +1 -1
- package/dist/services/workspace-runtime-read-model.test.js +3 -0
- package/dist/services/workspace-runtime-read-model.test.js.map +1 -1
- package/dist/services/workspace-runtime-ready-comment.test.js +1 -0
- package/dist/services/workspace-runtime-ready-comment.test.js.map +1 -1
- package/dist/services/workspace-runtime.d.ts +160 -2
- package/dist/services/workspace-runtime.d.ts.map +1 -1
- package/dist/services/workspace-runtime.js +1693 -141
- package/dist/services/workspace-runtime.js.map +1 -1
- package/dist/shutdown.d.ts +24 -0
- package/dist/shutdown.d.ts.map +1 -1
- package/dist/shutdown.js +37 -0
- package/dist/shutdown.js.map +1 -1
- package/dist/shutdown.test.js +113 -1
- package/dist/shutdown.test.js.map +1 -1
- package/dist/startup-banner.js +1 -1
- package/dist/startup-banner.js.map +1 -1
- package/dist/url-utils.d.ts +26 -0
- package/dist/url-utils.d.ts.map +1 -0
- package/dist/url-utils.js +59 -0
- package/dist/url-utils.js.map +1 -0
- package/dist/url-utils.test.d.ts +2 -0
- package/dist/url-utils.test.d.ts.map +1 -0
- package/dist/url-utils.test.js +55 -0
- package/dist/url-utils.test.js.map +1 -0
- package/dist/worktree-config.d.ts.map +1 -1
- package/dist/worktree-config.js +3 -17
- package/dist/worktree-config.js.map +1 -1
- package/package.json +20 -20
- package/skills/paperclip/SKILL.md +16 -11
- package/skills/paperclip/references/api-reference.md +8 -5
- package/skills/paperclip-board/SKILL.md +1 -1
- package/ui-dist/assets/{abnfDiagram-VRR7QNED-wvSnvD6-.js → abnfDiagram-N423BO3Z-BvgoV-u5.js} +1 -1
- package/ui-dist/assets/{arc-Bx0V1JsN.js → arc-BInnUBUU.js} +1 -1
- package/ui-dist/assets/architectureDiagram-T3A2C74G-Dg4MziOm.js +36 -0
- package/ui-dist/assets/{blockDiagram-677ZJIJ3-BROcLaUk.js → blockDiagram-VBNYF7ZC-D9kzAkLN.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-D-V3kgju.js → c4Diagram-5PPSVZJV-BwzsgV_0.js} +1 -1
- package/ui-dist/assets/channel-qoSYbCn0.js +1 -0
- package/ui-dist/assets/{chunk-32BRIVSS-qillH3H6.js → chunk-2GRJ4B5K-D2EQ9vrl.js} +1 -1
- package/ui-dist/assets/{chunk-2Q5K7J3B-D19cVnii.js → chunk-2Q5K7J3B-DOA_8fSd.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-CLUswrZg.js → chunk-5RXB4S5H-CT5ukRiT.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-Cwlp02Lx.js → chunk-5VM5RSS4-D2gOlkyB.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-yKciyq6E.js → chunk-6Q2QTUOP-DUb6aG8c.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-DjJ75g0_.js → chunk-GF5L2VYU-BPabG3Cx.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-BjepyzEb.js → chunk-JWPE2WC7-scNfhlZz.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-CiEmy8-R.js → chunk-KBJHAD2P-BcRAzRpq.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-ed7mQM9j.js → chunk-RYQCIY6F-BiZ0-EGh.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-BiI83zoO.js → chunk-XXDRQBXY-lJULxFIE.js} +1 -1
- package/ui-dist/assets/classDiagram-JCYQIIEL-B24u1REs.js +1 -0
- package/ui-dist/assets/classDiagram-v2-OCEON4UE-B24u1REs.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-DIdQf5ta.js → cose-bilkent-JH36ORCC-Do8pe8JB.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-B2m9xxh8.js → cynefin-VYW2F7L2-B34jJY1x.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-CGVdB0kX.js → cynefinDiagram-MW4NZA55-DQ8QK8JK.js} +1 -1
- package/ui-dist/assets/cytoscape.esm-DShqj__B.js +321 -0
- package/ui-dist/assets/{dagre-VKFMJZFB-CskKiZwJ.js → dagre-VZM6K2ZE-B7lSKgxH.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-D2cn5eIN.js → diagram-7IWD3JNH-B3hLAFGE.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-oa5Zu0XG.js → diagram-B4RE2ZJO-CH9Ro9e0.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-fymti5Js.js → diagram-LBJQPF4R-DdPVMii7.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-BWF2ZCsw.js → diagram-Q27KOJAE-f5VXswjc.js} +1 -1
- package/ui-dist/assets/diagram-UB23O5K3-DGqxixsR.js +41 -0
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-CJ1d3D5q.js → ebnfDiagram-BXEA7PRR-C-1klg_w.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-BJCPa7kK.js → erDiagram-JOGREHBK-Dt4qK4gv.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-BWjWuz6r.js → flowDiagram-UKHOOZJN-9ZlrTuET.js} +5 -5
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP-Dv1KKjoM.js → ganttDiagram-PKOTCBZU-CE3lyvFq.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-9X7vgL0A.js → gitGraphDiagram-DS77QQ5N-HH2fSgad.js} +1 -1
- package/ui-dist/assets/{index-CpaK48ok.js → index-B61ORkIb.js} +1 -1
- package/ui-dist/assets/index-BHiUiToL.css +1 -0
- package/ui-dist/assets/{index-D2YCrA-D.js → index-BY5ITKmG.js} +1 -1
- package/ui-dist/assets/{index-9JMDmXc5.js → index-BbAhzCq8.js} +1 -1
- package/ui-dist/assets/{index-C5qHatpp.js → index-Bc9g6q63.js} +1 -1
- package/ui-dist/assets/{index-DuI6e5mP.js → index-Bf7tyGxE.js} +1 -1
- package/ui-dist/assets/{index-BahRsj0s.js → index-BvFx-4KW.js} +1 -1
- package/ui-dist/assets/{index-DKlsEDV7.js → index-C1mpWCcn.js} +1 -1
- package/ui-dist/assets/{index-DIXaXZrW.js → index-CHXG4GPL.js} +1 -1
- package/ui-dist/assets/{index-DcfO6NoY.js → index-CLu3Tfpv.js} +1 -1
- package/ui-dist/assets/{index-Cfz6P0Qq.js → index-CQhaM6qd.js} +1 -1
- package/ui-dist/assets/{index-D9d3sl6K.js → index-CVTL3aAL.js} +1 -1
- package/ui-dist/assets/{index-BexA3NAl.js → index-CcRTJ93J.js} +1 -1
- package/ui-dist/assets/{index-CnBrDwGT.js → index-Cm6iEYPt.js} +247 -223
- package/ui-dist/assets/{index-ByGcu-MB.js → index-DQIrrn2L.js} +1 -1
- package/ui-dist/assets/{index-DKEzHO7c.js → index-DU4U1fuv.js} +1 -1
- package/ui-dist/assets/{index-pqJO8FsV.js → index-DV2FOgyD.js} +1 -1
- package/ui-dist/assets/{index-tDuieU3u.js → index-DceuCrr8.js} +1 -1
- package/ui-dist/assets/{index-CjN2lm_w.js → index-DlVBBF8o.js} +1 -1
- package/ui-dist/assets/{index-0yJtUsFh.js → index-DsdVneqe.js} +1 -1
- package/ui-dist/assets/{index-C2a4_IKU.js → index-DvFUXI-Q.js} +1 -1
- package/ui-dist/assets/{index-BTMiDMYv.js → index-FHzrJ7iQ.js} +1 -1
- package/ui-dist/assets/{index-cUQXJtLK.js → index-diFs0CNC.js} +1 -1
- package/ui-dist/assets/{index-C96LHV1A.js → index-hkanj4t6.js} +1 -1
- package/ui-dist/assets/{index-rDI1Q4r9.js → index-yRJnh4vx.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-CHIhutSb.js → infoDiagram-6WML65LV-2jai2fw-.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-ChaD7-5_.js → ishikawaDiagram-WSZJBQD7-CUmGhmEb.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-M5T2sMgn.js → journeyDiagram-NVQOT4AX-CGQuPDO1.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-B8H6R_Wc.js → kanban-definition-27J2QSJJ-zgEPcbHl.js} +1 -1
- package/ui-dist/assets/{linear-cpPKlVCq.js → linear-BVf5VtLS.js} +1 -1
- package/ui-dist/assets/mermaid.core-D2TFkGfI.js +308 -0
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-Bf6POzvm.js → mindmap-definition-FAOFIHXS-xoAQ0Lb_.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-BJbGktAV.js → pegDiagram-VL7TDLO6-CBR1PWLr.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-BmSN9Bio.js → pieDiagram-7S7Q4E2Y-BMPnzK_e.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-JUpqQCx_.js → quadrantDiagram-CIZ2JOQS-CPtVUPkR.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-B8k8T4-2.js → railroadDiagram-AXF67PYL-DC0lsZV1.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-b32heq7Q.js → requirementDiagram-LRYGKXZP-BF6k05SB.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-DC3s-xgf.js → sankeyDiagram-W5VNT64P-CRN0ibiP.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-BsCFyv_E.js → sequenceDiagram-SI44F4Z6-CQtTiPWm.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-S7xeCud3.js → sizeCapture-X5ZJPWSS-BdjuGZd1.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-58O3ofoS.js → stateDiagram-OKZ733FA-B99onxyh.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-UEYNNEHI-bzFlYBZ1.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-DFCVG0iF.js → swimlanes-SLNWSIFB-BIByPbrL.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-ULZ7WXOC-DgdkBnuK.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-C0c0SkQu.js → timeline-definition-Z64GVDOM-I1NgOcn9.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-B1cEx8GQ.js → vennDiagram-T6HMQDX7-D6t2Njcl.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-BQhDkOx9.js → wardleyDiagram-T6FBY63Y-BiYKm9gh.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-YSQp1N0i.js → xychartDiagram-ELKLHX3M-BhwXKWIa.js} +4 -4
- package/ui-dist/index.html +3 -3
- package/ui-dist/sw.js +8 -3
- package/ui-dist/assets/architectureDiagram-ZJ3FMSHR-BcJt8Ia1.js +0 -36
- package/ui-dist/assets/channel-ZRpjyNiZ.js +0 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CCzzzCgk.js +0 -1
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CCzzzCgk.js +0 -1
- package/ui-dist/assets/cytoscape.esm-D8joxN9f.js +0 -321
- package/ui-dist/assets/diagram-WEI45ONY-M3WOC2tK.js +0 -41
- package/ui-dist/assets/index-BqfqfoQX.css +0 -1
- package/ui-dist/assets/mermaid.core-MCazc_od.js +0 -308
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-_VY5dpDG.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BJhUjfns.js +0 -8
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who holds (or wants) a port pair. Every field is optional evidence — a
|
|
3
|
+
* conflict report is only as specific as the views that produced it — but
|
|
4
|
+
* `executionWorkspaceId` is the identity that governs adoption.
|
|
5
|
+
*/
|
|
6
|
+
export interface ExposureOwnerIdentity {
|
|
7
|
+
runtimeServiceId: string | null;
|
|
8
|
+
executionWorkspaceId: string | null;
|
|
9
|
+
projectWorkspaceId: string | null;
|
|
10
|
+
issueId: string | null;
|
|
11
|
+
}
|
|
12
|
+
/** Where a reservation came from, ordered by strength of evidence below. */
|
|
13
|
+
export type ExposureReservationSource =
|
|
14
|
+
/** This process is running the runtime that owns the pair. */
|
|
15
|
+
"in_memory_runtime"
|
|
16
|
+
/** The broker reports a live Paperclip-owned Serve mapping on the port. */
|
|
17
|
+
| "broker_mapping"
|
|
18
|
+
/** A persisted row still claims an exposure that is not `removed`. */
|
|
19
|
+
| "persisted_exposure"
|
|
20
|
+
/** A stopped/removed row whose execution-workspace lease is still open. */
|
|
21
|
+
| "leased_workspace"
|
|
22
|
+
/** Quarantined after an ambiguous cleanup; never reusable by anyone. */
|
|
23
|
+
| "quarantine";
|
|
24
|
+
export interface ExposurePortReservation {
|
|
25
|
+
port: number;
|
|
26
|
+
source: ExposureReservationSource;
|
|
27
|
+
owner: ExposureOwnerIdentity;
|
|
28
|
+
}
|
|
29
|
+
export interface ExposureReservationLedger {
|
|
30
|
+
/** Every port currently spoken for, whoever holds it. */
|
|
31
|
+
reservedPorts: ReadonlySet<number>;
|
|
32
|
+
/** Strongest-evidence reservation per port. */
|
|
33
|
+
reservationByPort: ReadonlyMap<number, ExposurePortReservation>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The subset of a `workspace_runtime_services` row this module reasons about.
|
|
37
|
+
* Deliberately structural rather than the Drizzle row type: startup
|
|
38
|
+
* reconciliation, allocation, and tests all project into it from different
|
|
39
|
+
* queries.
|
|
40
|
+
*/
|
|
41
|
+
export interface PersistedExposureRowSnapshot {
|
|
42
|
+
id: string;
|
|
43
|
+
status: string;
|
|
44
|
+
executionWorkspaceId: string | null;
|
|
45
|
+
projectWorkspaceId: string | null;
|
|
46
|
+
issueId: string | null;
|
|
47
|
+
/** App port column; survives teardown and is the lease's durable claim. */
|
|
48
|
+
port: number | null;
|
|
49
|
+
exposure: {
|
|
50
|
+
state: string;
|
|
51
|
+
listeners: ReadonlyArray<{
|
|
52
|
+
targetPort: number;
|
|
53
|
+
}>;
|
|
54
|
+
} | null;
|
|
55
|
+
}
|
|
56
|
+
/** A runtime this process is currently running with an exposure attached. */
|
|
57
|
+
export interface InMemoryExposureSnapshot {
|
|
58
|
+
runtimeServiceId: string;
|
|
59
|
+
executionWorkspaceId: string | null;
|
|
60
|
+
projectWorkspaceId: string | null;
|
|
61
|
+
issueId: string | null;
|
|
62
|
+
ports: ReadonlyArray<number>;
|
|
63
|
+
}
|
|
64
|
+
/** One Paperclip-owned listener as reported by the broker's `list()`. */
|
|
65
|
+
export interface BrokerMappingSnapshot {
|
|
66
|
+
runtimeId: string;
|
|
67
|
+
port: number;
|
|
68
|
+
}
|
|
69
|
+
export interface BuildExposureReservationLedgerInput {
|
|
70
|
+
persistedRows?: Iterable<PersistedExposureRowSnapshot>;
|
|
71
|
+
inMemoryRuntimes?: Iterable<InMemoryExposureSnapshot>;
|
|
72
|
+
brokerMappings?: Iterable<BrokerMappingSnapshot>;
|
|
73
|
+
quarantinedPorts?: Iterable<number>;
|
|
74
|
+
/**
|
|
75
|
+
* Execution workspaces whose exclusive lease is still open. A row belonging
|
|
76
|
+
* to one of these reserves its pair regardless of process or exposure state;
|
|
77
|
+
* that is the whole fix for "stopped-but-leased pair reuse".
|
|
78
|
+
*/
|
|
79
|
+
activeExecutionWorkspaceIds?: Iterable<string>;
|
|
80
|
+
/** In-process pair claims held by starts that have not bound a listener yet. */
|
|
81
|
+
inFlightClaimedPorts?: Iterable<number>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Every port a row's pair covers.
|
|
85
|
+
*
|
|
86
|
+
* The union of the exposure's declared listeners and the pair derived from the
|
|
87
|
+
* `port` column matters: `deprovisionExposure` replaces the status with a fresh
|
|
88
|
+
* `removed` one whose `listeners` is `[]`, so a torn-down row would otherwise
|
|
89
|
+
* contribute nothing at all. The `port` column is what still names the pair the
|
|
90
|
+
* lease paid for.
|
|
91
|
+
*/
|
|
92
|
+
export declare function collectRowExposurePorts(row: PersistedExposureRowSnapshot): Set<number>;
|
|
93
|
+
/**
|
|
94
|
+
* Merge every reservation view into one ledger. Later, weaker evidence never
|
|
95
|
+
* overwrites a stronger claim already recorded for the same port.
|
|
96
|
+
*/
|
|
97
|
+
export declare function buildExposureReservationLedger(input: BuildExposureReservationLedgerInput): ExposureReservationLedger;
|
|
98
|
+
/**
|
|
99
|
+
* May `claimant` take over a port currently attributed to `holder`?
|
|
100
|
+
*
|
|
101
|
+
* The rule is deliberately narrow, because the failure this prevents is a
|
|
102
|
+
* managed start silently adopting another issue's live service and then
|
|
103
|
+
* generating security evidence attributed to the wrong workspace:
|
|
104
|
+
*
|
|
105
|
+
* - the same runtime service reclaiming its own port is fine (restart);
|
|
106
|
+
* - otherwise both sides must name the *same, non-null* execution workspace.
|
|
107
|
+
*
|
|
108
|
+
* An unknown identity on either side is never adopted. "We could not tell whose
|
|
109
|
+
* it is" is a reason to fail closed, not a reason to assume it is ours.
|
|
110
|
+
*/
|
|
111
|
+
export declare function isExposureAdoptionPermitted(holder: ExposureOwnerIdentity | null, claimant: ExposureOwnerIdentity): boolean;
|
|
112
|
+
export type ExposurePortConflictCode = "quarantined_port" | "reserved_by_other_workspace" | "listener_owned_by_other_workspace" | "serve_mapping_owned_by_other_workspace";
|
|
113
|
+
export interface ExposurePortConflict {
|
|
114
|
+
code: ExposurePortConflictCode;
|
|
115
|
+
port: number;
|
|
116
|
+
claimant: ExposureOwnerIdentity;
|
|
117
|
+
holder: ExposureOwnerIdentity | null;
|
|
118
|
+
source: ExposureReservationSource | null;
|
|
119
|
+
}
|
|
120
|
+
export interface FindExposurePairConflictInput {
|
|
121
|
+
pair: {
|
|
122
|
+
appPort: number;
|
|
123
|
+
hmrPort: number;
|
|
124
|
+
};
|
|
125
|
+
claimant: ExposureOwnerIdentity;
|
|
126
|
+
ledger: ExposureReservationLedger;
|
|
127
|
+
/**
|
|
128
|
+
* Identity behind the process actually listening on each port, when one could
|
|
129
|
+
* be resolved. `null` for a port with a live listener whose owner is unknown —
|
|
130
|
+
* which is itself a conflict, since an unattributable listener must never be
|
|
131
|
+
* adopted.
|
|
132
|
+
*/
|
|
133
|
+
listenerOwners?: ReadonlyMap<number, ExposureOwnerIdentity | null>;
|
|
134
|
+
/** Identity behind each live Serve mapping, keyed by port. */
|
|
135
|
+
serveMappingOwners?: ReadonlyMap<number, ExposureOwnerIdentity | null>;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Complete mediation for one candidate pair: the first conflict across the
|
|
139
|
+
* persisted ledger, the live listeners, and the Serve mappings — or null when
|
|
140
|
+
* all three agree the claimant may have it.
|
|
141
|
+
*/
|
|
142
|
+
export declare function findExposurePairConflict(input: FindExposurePairConflictInput): ExposurePortConflict | null;
|
|
143
|
+
/**
|
|
144
|
+
* Operator-facing conflict text. Always names the port and the conflicting
|
|
145
|
+
* workspace/issue identity: a bare "port unavailable" is what made the original
|
|
146
|
+
* incident take a manual `tailscale serve status` read to attribute.
|
|
147
|
+
*/
|
|
148
|
+
export declare function describeExposurePortConflict(conflict: ExposurePortConflict): string;
|
|
149
|
+
/** Thrown on the allocation/start path so the failure is terminal and attributed. */
|
|
150
|
+
export declare class ExposurePortOwnershipConflictError extends Error {
|
|
151
|
+
readonly conflict: ExposurePortConflict;
|
|
152
|
+
readonly code: "exposure_port_ownership_conflict";
|
|
153
|
+
constructor(conflict: ExposurePortConflict);
|
|
154
|
+
}
|
|
155
|
+
export interface ExposureReservationDrift {
|
|
156
|
+
/** The row Paperclip believes is stopped/removed. */
|
|
157
|
+
runtimeServiceId: string;
|
|
158
|
+
owner: ExposureOwnerIdentity;
|
|
159
|
+
port: number;
|
|
160
|
+
reason: "live_listener" | "serve_mapping";
|
|
161
|
+
/** Who actually holds it, when that could be attributed. */
|
|
162
|
+
conflictingOwner: ExposureOwnerIdentity | null;
|
|
163
|
+
}
|
|
164
|
+
export interface FindExposureReservationDriftInput {
|
|
165
|
+
persistedRows: Iterable<PersistedExposureRowSnapshot>;
|
|
166
|
+
/** Ports with a live loopback listener right now. */
|
|
167
|
+
livePorts?: ReadonlySet<number>;
|
|
168
|
+
listenerOwners?: ReadonlyMap<number, ExposureOwnerIdentity | null>;
|
|
169
|
+
brokerMappings?: Iterable<BrokerMappingSnapshot>;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Rows whose state says "nothing here" while the host says otherwise.
|
|
173
|
+
*
|
|
174
|
+
* Reconciliation calls this so a lane reported `stopped` with its exposure
|
|
175
|
+
* `removed` — but whose reserved ports are live, or mapped to some other
|
|
176
|
+
* runtime — becomes a visible, attributable finding instead of a pair that
|
|
177
|
+
* quietly returns to the free list. A port still held by the row's *own*
|
|
178
|
+
* runtime is not drift; that is just a lane the sweep has yet to adopt.
|
|
179
|
+
*/
|
|
180
|
+
export declare function findExposureReservationDrift(input: FindExposureReservationDriftInput): ExposureReservationDrift[];
|
|
181
|
+
/** Human-readable drift line for reconciliation logs and operator evidence. */
|
|
182
|
+
export declare function describeExposureReservationDrift(entry: ExposureReservationDrift): string;
|
|
183
|
+
/**
|
|
184
|
+
* In-process, pair-atomic claims for starts that have not bound a listener yet.
|
|
185
|
+
*
|
|
186
|
+
* Two concurrent allocators see identical persisted state and identical probe
|
|
187
|
+
* results, so without a claim they both walk away with the lowest free pair.
|
|
188
|
+
* Claiming is all-or-nothing across the two ports: a half-claimed pair would
|
|
189
|
+
* let one start own the app port and another the HMR port, which is the
|
|
190
|
+
* orphaned-companion failure the pairing exists to prevent.
|
|
191
|
+
*/
|
|
192
|
+
export declare class ExposurePortPairClaims {
|
|
193
|
+
private readonly ttlMs;
|
|
194
|
+
private readonly heldUntilByPort;
|
|
195
|
+
constructor(ttlMs?: number);
|
|
196
|
+
private isHeld;
|
|
197
|
+
/** Claim both ports, or neither. Returns false when either is already held. */
|
|
198
|
+
claim(pair: {
|
|
199
|
+
appPort: number;
|
|
200
|
+
hmrPort: number;
|
|
201
|
+
}, nowMs?: number): boolean;
|
|
202
|
+
/** Release on lease release/teardown, or when a start reaches a terminal state. */
|
|
203
|
+
release(pair: {
|
|
204
|
+
appPort: number;
|
|
205
|
+
hmrPort: number;
|
|
206
|
+
}): void;
|
|
207
|
+
/** Ports still claimed, for folding into an allocator's reserved set. */
|
|
208
|
+
activePorts(nowMs?: number): Set<number>;
|
|
209
|
+
clear(): void;
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=port-reservation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-reservation.d.ts","sourceRoot":"","sources":["../../../src/services/runtime-exposure/port-reservation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central reservation + ownership mediation for `tailscale_https` app/HMR port
|
|
3
|
+
* pairs (PAP-17419, from the PAP-17251 finding).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this module exists
|
|
6
|
+
*
|
|
7
|
+
* Before it, "is this pair free?" was answered by three unrelated views that
|
|
8
|
+
* never had to agree:
|
|
9
|
+
*
|
|
10
|
+
* 1. the allocator's liveness probe — is anything *listening* right now,
|
|
11
|
+
* 2. `collectReservedExposurePorts` — persisted rows, but only those whose
|
|
12
|
+
* `exposure.state` was not yet `removed`,
|
|
13
|
+
* 3. the broker's Serve mapping — consulted nowhere on the allocation path.
|
|
14
|
+
*
|
|
15
|
+
* A workspace can hold an exclusive lease on a pair while satisfying none of
|
|
16
|
+
* those: stop the backend and the listener is gone; tear the exposure down and
|
|
17
|
+
* the row goes `stopped` with `exposure.state = "removed"` **and an emptied
|
|
18
|
+
* `listeners` array**, so the row stops contributing anything to the reserved
|
|
19
|
+
* set even though its `port` column still names the pair the lease owns. That
|
|
20
|
+
* is exactly how the pair leased to workspace `b7ce28b4` (`42001/52001`) was
|
|
21
|
+
* handed to the unrelated workspace `PAP-16986-add-posthog-mcp`, while
|
|
22
|
+
* Paperclip went on reporting the leased lane `stopped` and its exposure
|
|
23
|
+
* `removed`.
|
|
24
|
+
*
|
|
25
|
+
* ## The mediation this module centralizes
|
|
26
|
+
*
|
|
27
|
+
* - **Reservation follows the lease, not the process.** An execution workspace
|
|
28
|
+
* whose lease is still open reserves its pair through stop, teardown, and
|
|
29
|
+
* `removed` — until the lease is explicitly released. {@link
|
|
30
|
+
* buildExposureReservationLedger} derives the pair from the row's `port`
|
|
31
|
+
* column precisely because teardown erases `exposure.listeners`.
|
|
32
|
+
* - **Complete mediation on allocation.** {@link findExposurePairConflict}
|
|
33
|
+
* checks the persisted ledger *and* the live listener owner *and* the Serve
|
|
34
|
+
* mapping owner. Any of the three disagreeing fails the allocation closed,
|
|
35
|
+
* naming the conflicting workspace/issue.
|
|
36
|
+
* - **No adoption across execution workspaces, ever.** {@link
|
|
37
|
+
* isExposureAdoptionPermitted} is the single predicate for "may this claimant
|
|
38
|
+
* take over that holder's port", and it answers no whenever the two execution
|
|
39
|
+
* workspace IDs are not the identical, non-null value.
|
|
40
|
+
* - **Drift is surfaced, not silently reused.** {@link
|
|
41
|
+
* findExposureReservationDrift} reports a `stopped`/`removed` row whose
|
|
42
|
+
* reserved ports are live or mapped by someone else, so reconciliation can
|
|
43
|
+
* report a false-`stopped` lane instead of recycling it.
|
|
44
|
+
*
|
|
45
|
+
* Pure functions and one in-process claim registry: no sockets, no DB, no
|
|
46
|
+
* broker. Every caller injects its own view, which is what makes all five
|
|
47
|
+
* PAP-17419 regression cases testable without touching host Serve state.
|
|
48
|
+
*/
|
|
49
|
+
import { deriveViteHmrPort, isRuntimeExposureAppPort } from "@paperclipai/shared";
|
|
50
|
+
/**
|
|
51
|
+
* Precedence when several views claim one port. Strongest first: the report
|
|
52
|
+
* should name the most concrete evidence available, so an operator reading
|
|
53
|
+
* "held by the live Serve mapping for workspace X" is not told "reserved by a
|
|
54
|
+
* lease" when both are true.
|
|
55
|
+
*/
|
|
56
|
+
const RESERVATION_SOURCE_RANK = {
|
|
57
|
+
quarantine: 0,
|
|
58
|
+
in_memory_runtime: 1,
|
|
59
|
+
broker_mapping: 2,
|
|
60
|
+
persisted_exposure: 3,
|
|
61
|
+
leased_workspace: 4,
|
|
62
|
+
};
|
|
63
|
+
function emptyIdentity() {
|
|
64
|
+
return {
|
|
65
|
+
runtimeServiceId: null,
|
|
66
|
+
executionWorkspaceId: null,
|
|
67
|
+
projectWorkspaceId: null,
|
|
68
|
+
issueId: null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Every port a row's pair covers.
|
|
73
|
+
*
|
|
74
|
+
* The union of the exposure's declared listeners and the pair derived from the
|
|
75
|
+
* `port` column matters: `deprovisionExposure` replaces the status with a fresh
|
|
76
|
+
* `removed` one whose `listeners` is `[]`, so a torn-down row would otherwise
|
|
77
|
+
* contribute nothing at all. The `port` column is what still names the pair the
|
|
78
|
+
* lease paid for.
|
|
79
|
+
*/
|
|
80
|
+
export function collectRowExposurePorts(row) {
|
|
81
|
+
const ports = new Set();
|
|
82
|
+
for (const listener of row.exposure?.listeners ?? []) {
|
|
83
|
+
if (Number.isInteger(listener.targetPort))
|
|
84
|
+
ports.add(listener.targetPort);
|
|
85
|
+
}
|
|
86
|
+
if (row.port !== null && isRuntimeExposureAppPort(row.port)) {
|
|
87
|
+
ports.add(row.port);
|
|
88
|
+
ports.add(deriveViteHmrPort(row.port));
|
|
89
|
+
}
|
|
90
|
+
return ports;
|
|
91
|
+
}
|
|
92
|
+
/** True when the row's own exposure state still claims the mapping. */
|
|
93
|
+
function rowClaimsLiveExposure(row) {
|
|
94
|
+
return Boolean(row.exposure) && row.exposure.state !== "removed";
|
|
95
|
+
}
|
|
96
|
+
function rowIdentity(row) {
|
|
97
|
+
return {
|
|
98
|
+
runtimeServiceId: row.id,
|
|
99
|
+
executionWorkspaceId: row.executionWorkspaceId,
|
|
100
|
+
projectWorkspaceId: row.projectWorkspaceId,
|
|
101
|
+
issueId: row.issueId,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Merge every reservation view into one ledger. Later, weaker evidence never
|
|
106
|
+
* overwrites a stronger claim already recorded for the same port.
|
|
107
|
+
*/
|
|
108
|
+
export function buildExposureReservationLedger(input) {
|
|
109
|
+
const reservationByPort = new Map();
|
|
110
|
+
const record = (port, source, owner) => {
|
|
111
|
+
if (!Number.isInteger(port))
|
|
112
|
+
return;
|
|
113
|
+
const existing = reservationByPort.get(port);
|
|
114
|
+
if (existing && RESERVATION_SOURCE_RANK[existing.source] <= RESERVATION_SOURCE_RANK[source])
|
|
115
|
+
return;
|
|
116
|
+
reservationByPort.set(port, { port, source, owner });
|
|
117
|
+
};
|
|
118
|
+
const activeLeases = new Set(input.activeExecutionWorkspaceIds ?? []);
|
|
119
|
+
for (const port of input.quarantinedPorts ?? [])
|
|
120
|
+
record(port, "quarantine", emptyIdentity());
|
|
121
|
+
// An in-flight claim has no identity yet by construction — the claiming start
|
|
122
|
+
// has not persisted a row. It still must block a concurrent allocator.
|
|
123
|
+
for (const port of input.inFlightClaimedPorts ?? [])
|
|
124
|
+
record(port, "in_memory_runtime", emptyIdentity());
|
|
125
|
+
for (const runtime of input.inMemoryRuntimes ?? []) {
|
|
126
|
+
const owner = {
|
|
127
|
+
runtimeServiceId: runtime.runtimeServiceId,
|
|
128
|
+
executionWorkspaceId: runtime.executionWorkspaceId,
|
|
129
|
+
projectWorkspaceId: runtime.projectWorkspaceId,
|
|
130
|
+
issueId: runtime.issueId,
|
|
131
|
+
};
|
|
132
|
+
for (const port of runtime.ports)
|
|
133
|
+
record(port, "in_memory_runtime", owner);
|
|
134
|
+
}
|
|
135
|
+
// Broker mappings identify a runtime, not a workspace; resolve the workspace
|
|
136
|
+
// from the persisted rows when we can so a conflict can name it.
|
|
137
|
+
const rows = [...(input.persistedRows ?? [])];
|
|
138
|
+
const identityByRuntimeId = new Map(rows.map((row) => [row.id, rowIdentity(row)]));
|
|
139
|
+
for (const mapping of input.brokerMappings ?? []) {
|
|
140
|
+
record(mapping.port, "broker_mapping", identityByRuntimeId.get(mapping.runtimeId)
|
|
141
|
+
?? { ...emptyIdentity(), runtimeServiceId: mapping.runtimeId });
|
|
142
|
+
}
|
|
143
|
+
for (const row of rows) {
|
|
144
|
+
const leaseOpen = Boolean(row.executionWorkspaceId) && activeLeases.has(row.executionWorkspaceId);
|
|
145
|
+
const claimsExposure = rowClaimsLiveExposure(row);
|
|
146
|
+
if (!leaseOpen && !claimsExposure)
|
|
147
|
+
continue;
|
|
148
|
+
const source = claimsExposure ? "persisted_exposure" : "leased_workspace";
|
|
149
|
+
for (const port of collectRowExposurePorts(row))
|
|
150
|
+
record(port, source, rowIdentity(row));
|
|
151
|
+
}
|
|
152
|
+
return { reservationByPort, reservedPorts: new Set(reservationByPort.keys()) };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* May `claimant` take over a port currently attributed to `holder`?
|
|
156
|
+
*
|
|
157
|
+
* The rule is deliberately narrow, because the failure this prevents is a
|
|
158
|
+
* managed start silently adopting another issue's live service and then
|
|
159
|
+
* generating security evidence attributed to the wrong workspace:
|
|
160
|
+
*
|
|
161
|
+
* - the same runtime service reclaiming its own port is fine (restart);
|
|
162
|
+
* - otherwise both sides must name the *same, non-null* execution workspace.
|
|
163
|
+
*
|
|
164
|
+
* An unknown identity on either side is never adopted. "We could not tell whose
|
|
165
|
+
* it is" is a reason to fail closed, not a reason to assume it is ours.
|
|
166
|
+
*/
|
|
167
|
+
export function isExposureAdoptionPermitted(holder, claimant) {
|
|
168
|
+
if (!holder)
|
|
169
|
+
return true;
|
|
170
|
+
if (holder.runtimeServiceId !== null
|
|
171
|
+
&& claimant.runtimeServiceId !== null
|
|
172
|
+
&& holder.runtimeServiceId === claimant.runtimeServiceId) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (holder.executionWorkspaceId === null || claimant.executionWorkspaceId === null)
|
|
176
|
+
return false;
|
|
177
|
+
return holder.executionWorkspaceId === claimant.executionWorkspaceId;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Complete mediation for one candidate pair: the first conflict across the
|
|
181
|
+
* persisted ledger, the live listeners, and the Serve mappings — or null when
|
|
182
|
+
* all three agree the claimant may have it.
|
|
183
|
+
*/
|
|
184
|
+
export function findExposurePairConflict(input) {
|
|
185
|
+
const ports = [input.pair.appPort, input.pair.hmrPort];
|
|
186
|
+
for (const port of ports) {
|
|
187
|
+
const reservation = input.ledger.reservationByPort.get(port);
|
|
188
|
+
if (!reservation)
|
|
189
|
+
continue;
|
|
190
|
+
if (reservation.source === "quarantine") {
|
|
191
|
+
return { code: "quarantined_port", port, claimant: input.claimant, holder: null, source: "quarantine" };
|
|
192
|
+
}
|
|
193
|
+
if (!isExposureAdoptionPermitted(reservation.owner, input.claimant)) {
|
|
194
|
+
return {
|
|
195
|
+
code: "reserved_by_other_workspace",
|
|
196
|
+
port,
|
|
197
|
+
claimant: input.claimant,
|
|
198
|
+
holder: reservation.owner,
|
|
199
|
+
source: reservation.source,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Presence in these maps means the host has something on the port. A `null`
|
|
204
|
+
// value is therefore NOT "no holder" — it is "a holder we could not name",
|
|
205
|
+
// which is the one case that must never be adopted. `isExposureAdoptionPermitted`
|
|
206
|
+
// is only consulted once we have an identity to compare.
|
|
207
|
+
for (const port of ports) {
|
|
208
|
+
if (!input.listenerOwners?.has(port))
|
|
209
|
+
continue;
|
|
210
|
+
const owner = input.listenerOwners.get(port) ?? null;
|
|
211
|
+
if (owner === null || !isExposureAdoptionPermitted(owner, input.claimant)) {
|
|
212
|
+
return {
|
|
213
|
+
code: "listener_owned_by_other_workspace",
|
|
214
|
+
port,
|
|
215
|
+
claimant: input.claimant,
|
|
216
|
+
holder: owner,
|
|
217
|
+
source: null,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
for (const port of ports) {
|
|
222
|
+
if (!input.serveMappingOwners?.has(port))
|
|
223
|
+
continue;
|
|
224
|
+
const owner = input.serveMappingOwners.get(port) ?? null;
|
|
225
|
+
if (owner === null || !isExposureAdoptionPermitted(owner, input.claimant)) {
|
|
226
|
+
return {
|
|
227
|
+
code: "serve_mapping_owned_by_other_workspace",
|
|
228
|
+
port,
|
|
229
|
+
claimant: input.claimant,
|
|
230
|
+
holder: owner,
|
|
231
|
+
source: null,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
function describeIdentity(identity) {
|
|
238
|
+
if (!identity)
|
|
239
|
+
return "an unidentified owner";
|
|
240
|
+
const parts = [];
|
|
241
|
+
if (identity.executionWorkspaceId)
|
|
242
|
+
parts.push(`execution workspace ${identity.executionWorkspaceId}`);
|
|
243
|
+
if (identity.issueId)
|
|
244
|
+
parts.push(`issue ${identity.issueId}`);
|
|
245
|
+
if (identity.runtimeServiceId)
|
|
246
|
+
parts.push(`runtime service ${identity.runtimeServiceId}`);
|
|
247
|
+
if (identity.projectWorkspaceId && parts.length === 0) {
|
|
248
|
+
parts.push(`project workspace ${identity.projectWorkspaceId}`);
|
|
249
|
+
}
|
|
250
|
+
return parts.length > 0 ? parts.join(", ") : "an unidentified owner";
|
|
251
|
+
}
|
|
252
|
+
const CONFLICT_REASONS = {
|
|
253
|
+
quarantined_port: "is quarantined after an ambiguous exposure cleanup and can never be reused",
|
|
254
|
+
reserved_by_other_workspace: "is reserved by",
|
|
255
|
+
listener_owned_by_other_workspace: "has a live loopback listener owned by",
|
|
256
|
+
serve_mapping_owned_by_other_workspace: "is published by a Tailscale Serve mapping owned by",
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Operator-facing conflict text. Always names the port and the conflicting
|
|
260
|
+
* workspace/issue identity: a bare "port unavailable" is what made the original
|
|
261
|
+
* incident take a manual `tailscale serve status` read to attribute.
|
|
262
|
+
*/
|
|
263
|
+
export function describeExposurePortConflict(conflict) {
|
|
264
|
+
const subject = `port ${conflict.port}`;
|
|
265
|
+
if (conflict.code === "quarantined_port") {
|
|
266
|
+
return `${subject} ${CONFLICT_REASONS.quarantined_port}`;
|
|
267
|
+
}
|
|
268
|
+
const suffix = conflict.source === "leased_workspace"
|
|
269
|
+
? " (the lane is stopped, but its lease is still open)"
|
|
270
|
+
: "";
|
|
271
|
+
return `${subject} ${CONFLICT_REASONS[conflict.code]} ${describeIdentity(conflict.holder)}${suffix}`;
|
|
272
|
+
}
|
|
273
|
+
/** Thrown on the allocation/start path so the failure is terminal and attributed. */
|
|
274
|
+
export class ExposurePortOwnershipConflictError extends Error {
|
|
275
|
+
conflict;
|
|
276
|
+
code = "exposure_port_ownership_conflict";
|
|
277
|
+
constructor(conflict) {
|
|
278
|
+
super(`HTTPS exposure allocation denied: ${describeExposurePortConflict(conflict)}`);
|
|
279
|
+
this.conflict = conflict;
|
|
280
|
+
this.name = "ExposurePortOwnershipConflictError";
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Rows whose state says "nothing here" while the host says otherwise.
|
|
285
|
+
*
|
|
286
|
+
* Reconciliation calls this so a lane reported `stopped` with its exposure
|
|
287
|
+
* `removed` — but whose reserved ports are live, or mapped to some other
|
|
288
|
+
* runtime — becomes a visible, attributable finding instead of a pair that
|
|
289
|
+
* quietly returns to the free list. A port still held by the row's *own*
|
|
290
|
+
* runtime is not drift; that is just a lane the sweep has yet to adopt.
|
|
291
|
+
*/
|
|
292
|
+
export function findExposureReservationDrift(input) {
|
|
293
|
+
const rows = [...input.persistedRows];
|
|
294
|
+
const identityByRuntimeId = new Map(rows.map((row) => [row.id, rowIdentity(row)]));
|
|
295
|
+
const mappingOwnerByPort = new Map();
|
|
296
|
+
for (const mapping of input.brokerMappings ?? []) {
|
|
297
|
+
mappingOwnerByPort.set(mapping.port, identityByRuntimeId.get(mapping.runtimeId)
|
|
298
|
+
?? { ...emptyIdentity(), runtimeServiceId: mapping.runtimeId });
|
|
299
|
+
}
|
|
300
|
+
const drift = [];
|
|
301
|
+
for (const row of rows) {
|
|
302
|
+
const dormant = row.status === "stopped" || row.status === "failed" || !rowClaimsLiveExposure(row);
|
|
303
|
+
if (!dormant)
|
|
304
|
+
continue;
|
|
305
|
+
const owner = rowIdentity(row);
|
|
306
|
+
for (const port of collectRowExposurePorts(row)) {
|
|
307
|
+
const mappingOwner = mappingOwnerByPort.get(port) ?? null;
|
|
308
|
+
if (mappingOwner && mappingOwner.runtimeServiceId !== row.id) {
|
|
309
|
+
drift.push({ runtimeServiceId: row.id, owner, port, reason: "serve_mapping", conflictingOwner: mappingOwner });
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (!input.livePorts?.has(port))
|
|
313
|
+
continue;
|
|
314
|
+
const listenerOwner = input.listenerOwners?.get(port) ?? null;
|
|
315
|
+
if (listenerOwner && listenerOwner.runtimeServiceId === row.id)
|
|
316
|
+
continue;
|
|
317
|
+
drift.push({ runtimeServiceId: row.id, owner, port, reason: "live_listener", conflictingOwner: listenerOwner });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return drift;
|
|
321
|
+
}
|
|
322
|
+
/** Human-readable drift line for reconciliation logs and operator evidence. */
|
|
323
|
+
export function describeExposureReservationDrift(entry) {
|
|
324
|
+
const held = entry.reason === "serve_mapping"
|
|
325
|
+
? "is still published by a Tailscale Serve mapping"
|
|
326
|
+
: "still has a live loopback listener";
|
|
327
|
+
return (`runtime service ${entry.runtimeServiceId} (${describeIdentity(entry.owner)}) is recorded stopped/removed, `
|
|
328
|
+
+ `but its reserved port ${entry.port} ${held} owned by ${describeIdentity(entry.conflictingOwner)}`);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* In-process, pair-atomic claims for starts that have not bound a listener yet.
|
|
332
|
+
*
|
|
333
|
+
* Two concurrent allocators see identical persisted state and identical probe
|
|
334
|
+
* results, so without a claim they both walk away with the lowest free pair.
|
|
335
|
+
* Claiming is all-or-nothing across the two ports: a half-claimed pair would
|
|
336
|
+
* let one start own the app port and another the HMR port, which is the
|
|
337
|
+
* orphaned-companion failure the pairing exists to prevent.
|
|
338
|
+
*/
|
|
339
|
+
export class ExposurePortPairClaims {
|
|
340
|
+
ttlMs;
|
|
341
|
+
heldUntilByPort = new Map();
|
|
342
|
+
constructor(ttlMs = 120_000) {
|
|
343
|
+
this.ttlMs = ttlMs;
|
|
344
|
+
}
|
|
345
|
+
isHeld(port, nowMs) {
|
|
346
|
+
const heldUntil = this.heldUntilByPort.get(port);
|
|
347
|
+
if (heldUntil === undefined)
|
|
348
|
+
return false;
|
|
349
|
+
if (heldUntil > nowMs)
|
|
350
|
+
return true;
|
|
351
|
+
this.heldUntilByPort.delete(port);
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
/** Claim both ports, or neither. Returns false when either is already held. */
|
|
355
|
+
claim(pair, nowMs = Date.now()) {
|
|
356
|
+
if (this.isHeld(pair.appPort, nowMs) || this.isHeld(pair.hmrPort, nowMs))
|
|
357
|
+
return false;
|
|
358
|
+
this.heldUntilByPort.set(pair.appPort, nowMs + this.ttlMs);
|
|
359
|
+
this.heldUntilByPort.set(pair.hmrPort, nowMs + this.ttlMs);
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
/** Release on lease release/teardown, or when a start reaches a terminal state. */
|
|
363
|
+
release(pair) {
|
|
364
|
+
this.heldUntilByPort.delete(pair.appPort);
|
|
365
|
+
this.heldUntilByPort.delete(pair.hmrPort);
|
|
366
|
+
}
|
|
367
|
+
/** Ports still claimed, for folding into an allocator's reserved set. */
|
|
368
|
+
activePorts(nowMs = Date.now()) {
|
|
369
|
+
const active = new Set();
|
|
370
|
+
for (const port of [...this.heldUntilByPort.keys()]) {
|
|
371
|
+
if (this.isHeld(port, nowMs))
|
|
372
|
+
active.add(port);
|
|
373
|
+
}
|
|
374
|
+
return active;
|
|
375
|
+
}
|
|
376
|
+
clear() {
|
|
377
|
+
this.heldUntilByPort.clear();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
//# sourceMappingURL=port-reservation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-reservation.js","sourceRoot":"","sources":["../../../src/services/runtime-exposure/port-reservation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-reservation.test.d.ts","sourceRoot":"","sources":["../../../src/services/runtime-exposure/port-reservation.test.ts"],"names":[],"mappings":""}
|