@antasphere/chassis-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +82 -0
- package/dist/accounts/deletion.d.ts +163 -0
- package/dist/accounts/deletion.d.ts.map +1 -0
- package/dist/accounts/deletion.js +360 -0
- package/dist/accounts/deletion.js.map +1 -0
- package/dist/accounts/erasure-log.d.ts +66 -0
- package/dist/accounts/erasure-log.d.ts.map +1 -0
- package/dist/accounts/erasure-log.js +117 -0
- package/dist/accounts/erasure-log.js.map +1 -0
- package/dist/accounts/index.d.ts +6 -0
- package/dist/accounts/index.d.ts.map +1 -0
- package/dist/accounts/index.js +6 -0
- package/dist/accounts/index.js.map +1 -0
- package/dist/accounts/mint-refusal.d.ts +47 -0
- package/dist/accounts/mint-refusal.d.ts.map +1 -0
- package/dist/accounts/mint-refusal.js +59 -0
- package/dist/accounts/mint-refusal.js.map +1 -0
- package/dist/accounts/signup-duplicate.d.ts +14 -0
- package/dist/accounts/signup-duplicate.d.ts.map +1 -0
- package/dist/accounts/signup-duplicate.js +25 -0
- package/dist/accounts/signup-duplicate.js.map +1 -0
- package/dist/accounts/superadmin.d.ts +27 -0
- package/dist/accounts/superadmin.d.ts.map +1 -0
- package/dist/accounts/superadmin.js +46 -0
- package/dist/accounts/superadmin.js.map +1 -0
- package/dist/api/apikeys.d.ts +14 -0
- package/dist/api/apikeys.d.ts.map +1 -0
- package/dist/api/apikeys.js +124 -0
- package/dist/api/apikeys.js.map +1 -0
- package/dist/api/audit.d.ts +4 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +75 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/break-glass.d.ts +48 -0
- package/dist/api/break-glass.d.ts.map +1 -0
- package/dist/api/break-glass.js +217 -0
- package/dist/api/break-glass.js.map +1 -0
- package/dist/api/cli-auth.d.ts +84 -0
- package/dist/api/cli-auth.d.ts.map +1 -0
- package/dist/api/cli-auth.js +177 -0
- package/dist/api/cli-auth.js.map +1 -0
- package/dist/api/create-api.d.ts +123 -0
- package/dist/api/create-api.d.ts.map +1 -0
- package/dist/api/create-api.js +1165 -0
- package/dist/api/create-api.js.map +1 -0
- package/dist/api/demo-passes.d.ts +45 -0
- package/dist/api/demo-passes.d.ts.map +1 -0
- package/dist/api/demo-passes.js +143 -0
- package/dist/api/demo-passes.js.map +1 -0
- package/dist/api/errors.d.ts +5 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +5 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/export.d.ts +63 -0
- package/dist/api/export.d.ts.map +1 -0
- package/dist/api/export.js +393 -0
- package/dist/api/export.js.map +1 -0
- package/dist/api/files.d.ts +40 -0
- package/dist/api/files.d.ts.map +1 -0
- package/dist/api/files.js +150 -0
- package/dist/api/files.js.map +1 -0
- package/dist/api/index.d.ts +17 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +17 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/invitations.d.ts +50 -0
- package/dist/api/invitations.d.ts.map +1 -0
- package/dist/api/invitations.js +313 -0
- package/dist/api/invitations.js.map +1 -0
- package/dist/api/members.d.ts +25 -0
- package/dist/api/members.d.ts.map +1 -0
- package/dist/api/members.js +522 -0
- package/dist/api/members.js.map +1 -0
- package/dist/api/onboarding.d.ts +26 -0
- package/dist/api/onboarding.d.ts.map +1 -0
- package/dist/api/onboarding.js +23 -0
- package/dist/api/onboarding.js.map +1 -0
- package/dist/api/openapi-doc.d.ts +21 -0
- package/dist/api/openapi-doc.d.ts.map +1 -0
- package/dist/api/openapi-doc.js +25 -0
- package/dist/api/openapi-doc.js.map +1 -0
- package/dist/api/projects.d.ts +24 -0
- package/dist/api/projects.d.ts.map +1 -0
- package/dist/api/projects.js +624 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/scope-routes.d.ts +12 -0
- package/dist/api/scope-routes.d.ts.map +1 -0
- package/dist/api/scope-routes.js +2 -0
- package/dist/api/scope-routes.js.map +1 -0
- package/dist/api/sso-connect.d.ts +70 -0
- package/dist/api/sso-connect.d.ts.map +1 -0
- package/dist/api/sso-connect.js +164 -0
- package/dist/api/sso-connect.js.map +1 -0
- package/dist/api/sso-logout.d.ts +41 -0
- package/dist/api/sso-logout.d.ts.map +1 -0
- package/dist/api/sso-logout.js +34 -0
- package/dist/api/sso-logout.js.map +1 -0
- package/dist/api/teams.d.ts +43 -0
- package/dist/api/teams.d.ts.map +1 -0
- package/dist/api/teams.js +447 -0
- package/dist/api/teams.js.map +1 -0
- package/dist/api/workspaces.d.ts +114 -0
- package/dist/api/workspaces.d.ts.map +1 -0
- package/dist/api/workspaces.js +462 -0
- package/dist/api/workspaces.js.map +1 -0
- package/dist/apikeys/index.d.ts +3 -0
- package/dist/apikeys/index.d.ts.map +1 -0
- package/dist/apikeys/index.js +3 -0
- package/dist/apikeys/index.js.map +1 -0
- package/dist/apikeys/peppers.d.ts +53 -0
- package/dist/apikeys/peppers.d.ts.map +1 -0
- package/dist/apikeys/peppers.js +97 -0
- package/dist/apikeys/peppers.js.map +1 -0
- package/dist/apikeys/service.d.ts +56 -0
- package/dist/apikeys/service.d.ts.map +1 -0
- package/dist/apikeys/service.js +196 -0
- package/dist/apikeys/service.js.map +1 -0
- package/dist/app.d.ts +65 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +142 -0
- package/dist/app.js.map +1 -0
- package/dist/audit/filters.d.ts +38 -0
- package/dist/audit/filters.d.ts.map +1 -0
- package/dist/audit/filters.js +97 -0
- package/dist/audit/filters.js.map +1 -0
- package/dist/audit/index.d.ts +3 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +3 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/service.d.ts +65 -0
- package/dist/audit/service.d.ts.map +1 -0
- package/dist/audit/service.js +103 -0
- package/dist/audit/service.js.map +1 -0
- package/dist/boot.d.ts +8 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/boot.js +822 -0
- package/dist/boot.js.map +1 -0
- package/dist/constant-time.d.ts +3 -0
- package/dist/constant-time.d.ts.map +1 -0
- package/dist/constant-time.js +10 -0
- package/dist/constant-time.js.map +1 -0
- package/dist/email/driver.d.ts +16 -0
- package/dist/email/driver.d.ts.map +1 -0
- package/dist/email/driver.js +136 -0
- package/dist/email/driver.js.map +1 -0
- package/dist/email/index.d.ts +4 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +4 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/shell.d.ts +72 -0
- package/dist/email/shell.d.ts.map +1 -0
- package/dist/email/shell.js +146 -0
- package/dist/email/shell.js.map +1 -0
- package/dist/email/templates.d.ts +83 -0
- package/dist/email/templates.d.ts.map +1 -0
- package/dist/email/templates.js +96 -0
- package/dist/email/templates.js.map +1 -0
- package/dist/entitlements/check.d.ts +140 -0
- package/dist/entitlements/check.d.ts.map +1 -0
- package/dist/entitlements/check.js +276 -0
- package/dist/entitlements/check.js.map +1 -0
- package/dist/entitlements/clock-skew.d.ts +27 -0
- package/dist/entitlements/clock-skew.d.ts.map +1 -0
- package/dist/entitlements/clock-skew.js +58 -0
- package/dist/entitlements/clock-skew.js.map +1 -0
- package/dist/entitlements/gate.d.ts +113 -0
- package/dist/entitlements/gate.d.ts.map +1 -0
- package/dist/entitlements/gate.js +430 -0
- package/dist/entitlements/gate.js.map +1 -0
- package/dist/entitlements/hub-machine-token.d.ts +83 -0
- package/dist/entitlements/hub-machine-token.d.ts.map +1 -0
- package/dist/entitlements/hub-machine-token.js +175 -0
- package/dist/entitlements/hub-machine-token.js.map +1 -0
- package/dist/entitlements/hub-subject.d.ts +32 -0
- package/dist/entitlements/hub-subject.d.ts.map +1 -0
- package/dist/entitlements/hub-subject.js +68 -0
- package/dist/entitlements/hub-subject.js.map +1 -0
- package/dist/entitlements/index.d.ts +9 -0
- package/dist/entitlements/index.d.ts.map +1 -0
- package/dist/entitlements/index.js +9 -0
- package/dist/entitlements/index.js.map +1 -0
- package/dist/entitlements/poster.d.ts +81 -0
- package/dist/entitlements/poster.d.ts.map +1 -0
- package/dist/entitlements/poster.js +169 -0
- package/dist/entitlements/poster.js.map +1 -0
- package/dist/entitlements/profiles.d.ts +121 -0
- package/dist/entitlements/profiles.d.ts.map +1 -0
- package/dist/entitlements/profiles.js +212 -0
- package/dist/entitlements/profiles.js.map +1 -0
- package/dist/entitlements/slot.d.ts +33 -0
- package/dist/entitlements/slot.d.ts.map +1 -0
- package/dist/entitlements/slot.js +75 -0
- package/dist/entitlements/slot.js.map +1 -0
- package/dist/env.d.ts +293 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +383 -0
- package/dist/env.js.map +1 -0
- package/dist/files/http.d.ts +23 -0
- package/dist/files/http.d.ts.map +1 -0
- package/dist/files/http.js +66 -0
- package/dist/files/http.js.map +1 -0
- package/dist/files/index.d.ts +5 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +5 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/serve.d.ts +43 -0
- package/dist/files/serve.d.ts.map +1 -0
- package/dist/files/serve.js +71 -0
- package/dist/files/serve.js.map +1 -0
- package/dist/files/service.d.ts +69 -0
- package/dist/files/service.d.ts.map +1 -0
- package/dist/files/service.js +188 -0
- package/dist/files/service.js.map +1 -0
- package/dist/files/spool.d.ts +21 -0
- package/dist/files/spool.d.ts.map +1 -0
- package/dist/files/spool.js +47 -0
- package/dist/files/spool.js.map +1 -0
- package/dist/identity/better-auth.d.ts +3927 -0
- package/dist/identity/better-auth.d.ts.map +1 -0
- package/dist/identity/better-auth.js +896 -0
- package/dist/identity/better-auth.js.map +1 -0
- package/dist/identity/demo-pass-plugin.d.ts +29 -0
- package/dist/identity/demo-pass-plugin.d.ts.map +1 -0
- package/dist/identity/demo-pass-plugin.js +88 -0
- package/dist/identity/demo-pass-plugin.js.map +1 -0
- package/dist/identity/demo-pass-rules.d.ts +84 -0
- package/dist/identity/demo-pass-rules.d.ts.map +1 -0
- package/dist/identity/demo-pass-rules.js +223 -0
- package/dist/identity/demo-pass-rules.js.map +1 -0
- package/dist/identity/demo-pass.d.ts +159 -0
- package/dist/identity/demo-pass.d.ts.map +1 -0
- package/dist/identity/demo-pass.js +319 -0
- package/dist/identity/demo-pass.js.map +1 -0
- package/dist/identity/hub-grant.d.ts +182 -0
- package/dist/identity/hub-grant.d.ts.map +1 -0
- package/dist/identity/hub-grant.js +594 -0
- package/dist/identity/hub-grant.js.map +1 -0
- package/dist/identity/hub-jwt.d.ts +22 -0
- package/dist/identity/hub-jwt.d.ts.map +1 -0
- package/dist/identity/hub-jwt.js +77 -0
- package/dist/identity/hub-jwt.js.map +1 -0
- package/dist/identity/hub-live-gate.d.ts +17 -0
- package/dist/identity/hub-live-gate.d.ts.map +1 -0
- package/dist/identity/hub-live-gate.js +146 -0
- package/dist/identity/hub-live-gate.js.map +1 -0
- package/dist/identity/hub-logout.d.ts +88 -0
- package/dist/identity/hub-logout.d.ts.map +1 -0
- package/dist/identity/hub-logout.js +158 -0
- package/dist/identity/hub-logout.js.map +1 -0
- package/dist/identity/hub-projection.d.ts +103 -0
- package/dist/identity/hub-projection.d.ts.map +1 -0
- package/dist/identity/hub-projection.js +130 -0
- package/dist/identity/hub-projection.js.map +1 -0
- package/dist/identity/hub-reconcile.d.ts +151 -0
- package/dist/identity/hub-reconcile.d.ts.map +1 -0
- package/dist/identity/hub-reconcile.js +400 -0
- package/dist/identity/hub-reconcile.js.map +1 -0
- package/dist/identity/hub-sso.d.ts +363 -0
- package/dist/identity/hub-sso.d.ts.map +1 -0
- package/dist/identity/hub-sso.js +536 -0
- package/dist/identity/hub-sso.js.map +1 -0
- package/dist/identity/hub-user-client.d.ts +222 -0
- package/dist/identity/hub-user-client.d.ts.map +1 -0
- package/dist/identity/hub-user-client.js +406 -0
- package/dist/identity/hub-user-client.js.map +1 -0
- package/dist/identity/index.d.ts +13 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +13 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/oauth-jwt.d.ts +32 -0
- package/dist/identity/oauth-jwt.d.ts.map +1 -0
- package/dist/identity/oauth-jwt.js +122 -0
- package/dist/identity/oauth-jwt.js.map +1 -0
- package/dist/identity/resolve-membership.d.ts +28 -0
- package/dist/identity/resolve-membership.d.ts.map +1 -0
- package/dist/identity/resolve-membership.js +69 -0
- package/dist/identity/resolve-membership.js.map +1 -0
- package/dist/identity/signing-key.d.ts +49 -0
- package/dist/identity/signing-key.d.ts.map +1 -0
- package/dist/identity/signing-key.js +144 -0
- package/dist/identity/signing-key.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/invitations/index.d.ts +2 -0
- package/dist/invitations/index.d.ts.map +1 -0
- package/dist/invitations/index.js +2 -0
- package/dist/invitations/index.js.map +1 -0
- package/dist/invitations/service.d.ts +36 -0
- package/dist/invitations/service.d.ts.map +1 -0
- package/dist/invitations/service.js +122 -0
- package/dist/invitations/service.js.map +1 -0
- package/dist/jobs/index.d.ts +3 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +3 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/pgboss.d.ts +119 -0
- package/dist/jobs/pgboss.d.ts.map +1 -0
- package/dist/jobs/pgboss.js +521 -0
- package/dist/jobs/pgboss.js.map +1 -0
- package/dist/jobs/timers.d.ts +127 -0
- package/dist/jobs/timers.d.ts.map +1 -0
- package/dist/jobs/timers.js +228 -0
- package/dist/jobs/timers.js.map +1 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +64 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/errors.d.ts +37 -0
- package/dist/mcp/errors.d.ts.map +1 -0
- package/dist/mcp/errors.js +77 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/http.d.ts +35 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.js +80 -0
- package/dist/mcp/http.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/inputs.d.ts +19 -0
- package/dist/mcp/inputs.d.ts.map +1 -0
- package/dist/mcp/inputs.js +28 -0
- package/dist/mcp/inputs.js.map +1 -0
- package/dist/mcp/projects.d.ts +31 -0
- package/dist/mcp/projects.d.ts.map +1 -0
- package/dist/mcp/projects.js +315 -0
- package/dist/mcp/projects.js.map +1 -0
- package/dist/mcp/server.d.ts +52 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +93 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/teams.d.ts +7 -0
- package/dist/mcp/teams.d.ts.map +1 -0
- package/dist/mcp/teams.js +62 -0
- package/dist/mcp/teams.js.map +1 -0
- package/dist/mcp/tool-kit.d.ts +67 -0
- package/dist/mcp/tool-kit.d.ts.map +1 -0
- package/dist/mcp/tool-kit.js +74 -0
- package/dist/mcp/tool-kit.js.map +1 -0
- package/dist/members/removal.d.ts +95 -0
- package/dist/members/removal.d.ts.map +1 -0
- package/dist/members/removal.js +143 -0
- package/dist/members/removal.js.map +1 -0
- package/dist/middleware/auth-body.d.ts +25 -0
- package/dist/middleware/auth-body.d.ts.map +1 -0
- package/dist/middleware/auth-body.js +55 -0
- package/dist/middleware/auth-body.js.map +1 -0
- package/dist/middleware/auth-context.d.ts +170 -0
- package/dist/middleware/auth-context.d.ts.map +1 -0
- package/dist/middleware/auth-context.js +251 -0
- package/dist/middleware/auth-context.js.map +1 -0
- package/dist/middleware/body-cap.d.ts +17 -0
- package/dist/middleware/body-cap.d.ts.map +1 -0
- package/dist/middleware/body-cap.js +31 -0
- package/dist/middleware/body-cap.js.map +1 -0
- package/dist/middleware/body-refusal.d.ts +20 -0
- package/dist/middleware/body-refusal.d.ts.map +1 -0
- package/dist/middleware/body-refusal.js +5 -0
- package/dist/middleware/body-refusal.js.map +1 -0
- package/dist/middleware/cross-site.d.ts +61 -0
- package/dist/middleware/cross-site.d.ts.map +1 -0
- package/dist/middleware/cross-site.js +59 -0
- package/dist/middleware/cross-site.js.map +1 -0
- package/dist/middleware/hub-managed.d.ts +45 -0
- package/dist/middleware/hub-managed.d.ts.map +1 -0
- package/dist/middleware/hub-managed.js +56 -0
- package/dist/middleware/hub-managed.js.map +1 -0
- package/dist/middleware/idempotency.d.ts +14 -0
- package/dist/middleware/idempotency.d.ts.map +1 -0
- package/dist/middleware/idempotency.js +222 -0
- package/dist/middleware/idempotency.js.map +1 -0
- package/dist/middleware/index.d.ts +12 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +12 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/json-depth.d.ts +32 -0
- package/dist/middleware/json-depth.d.ts.map +1 -0
- package/dist/middleware/json-depth.js +80 -0
- package/dist/middleware/json-depth.js.map +1 -0
- package/dist/middleware/no-store.d.ts +21 -0
- package/dist/middleware/no-store.d.ts.map +1 -0
- package/dist/middleware/no-store.js +32 -0
- package/dist/middleware/no-store.js.map +1 -0
- package/dist/middleware/oauth-public.d.ts +16 -0
- package/dist/middleware/oauth-public.d.ts.map +1 -0
- package/dist/middleware/oauth-public.js +50 -0
- package/dist/middleware/oauth-public.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +182 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +277 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/middleware/request-id.d.ts +10 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +42 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/middleware/scopes.d.ts +33 -0
- package/dist/middleware/scopes.d.ts.map +1 -0
- package/dist/middleware/scopes.js +139 -0
- package/dist/middleware/scopes.js.map +1 -0
- package/dist/middleware/security-headers.d.ts +53 -0
- package/dist/middleware/security-headers.d.ts.map +1 -0
- package/dist/middleware/security-headers.js +96 -0
- package/dist/middleware/security-headers.js.map +1 -0
- package/dist/observability/index.d.ts +3 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +3 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/metrics.d.ts +17 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +82 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/otel.d.ts +20 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +54 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/pagination.d.ts +57 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +90 -0
- package/dist/pagination.js.map +1 -0
- package/dist/platform/edition.d.ts +57 -0
- package/dist/platform/edition.d.ts.map +1 -0
- package/dist/platform/edition.js +90 -0
- package/dist/platform/edition.js.map +1 -0
- package/dist/platform/entitlements.d.ts +26 -0
- package/dist/platform/entitlements.d.ts.map +1 -0
- package/dist/platform/entitlements.js +28 -0
- package/dist/platform/entitlements.js.map +1 -0
- package/dist/platform/events.d.ts +87 -0
- package/dist/platform/events.d.ts.map +1 -0
- package/dist/platform/events.js +32 -0
- package/dist/platform/events.js.map +1 -0
- package/dist/platform/index.d.ts +8 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +8 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/local-identity.d.ts +39 -0
- package/dist/platform/local-identity.d.ts.map +1 -0
- package/dist/platform/local-identity.js +87 -0
- package/dist/platform/local-identity.js.map +1 -0
- package/dist/platform/registry.d.ts +23 -0
- package/dist/platform/registry.d.ts.map +1 -0
- package/dist/platform/registry.js +5 -0
- package/dist/platform/registry.js.map +1 -0
- package/dist/platform/usage.d.ts +11 -0
- package/dist/platform/usage.d.ts.map +1 -0
- package/dist/platform/usage.js +12 -0
- package/dist/platform/usage.js.map +1 -0
- package/dist/platform/workspaces.d.ts +25 -0
- package/dist/platform/workspaces.d.ts.map +1 -0
- package/dist/platform/workspaces.js +44 -0
- package/dist/platform/workspaces.js.map +1 -0
- package/dist/projects/access.d.ts +40 -0
- package/dist/projects/access.d.ts.map +1 -0
- package/dist/projects/access.js +133 -0
- package/dist/projects/access.js.map +1 -0
- package/dist/projects/index.d.ts +2 -0
- package/dist/projects/index.d.ts.map +1 -0
- package/dist/projects/index.js +2 -0
- package/dist/projects/index.js.map +1 -0
- package/dist/route-label.d.ts +23 -0
- package/dist/route-label.d.ts.map +1 -0
- package/dist/route-label.js +29 -0
- package/dist/route-label.js.map +1 -0
- package/dist/routes/health.d.ts +30 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +54 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +3 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/wellknown.d.ts +11 -0
- package/dist/routes/wellknown.d.ts.map +1 -0
- package/dist/routes/wellknown.js +45 -0
- package/dist/routes/wellknown.js.map +1 -0
- package/dist/secret.d.ts +30 -0
- package/dist/secret.d.ts.map +1 -0
- package/dist/secret.js +97 -0
- package/dist/secret.js.map +1 -0
- package/dist/setup-transport.d.ts +23 -0
- package/dist/setup-transport.d.ts.map +1 -0
- package/dist/setup-transport.js +52 -0
- package/dist/setup-transport.js.map +1 -0
- package/dist/state.d.ts +21 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +4 -0
- package/dist/state.js.map +1 -0
- package/dist/storage/driver.d.ts +38 -0
- package/dist/storage/driver.d.ts.map +1 -0
- package/dist/storage/driver.js +14 -0
- package/dist/storage/driver.js.map +1 -0
- package/dist/storage/factory.d.ts +4 -0
- package/dist/storage/factory.d.ts.map +1 -0
- package/dist/storage/factory.js +20 -0
- package/dist/storage/factory.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +4 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local.d.ts +21 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +88 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/s3.d.ts +29 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +82 -0
- package/dist/storage/s3.js.map +1 -0
- package/dist/testing/fake-hub.d.ts +425 -0
- package/dist/testing/fake-hub.d.ts.map +1 -0
- package/dist/testing/fake-hub.js +1074 -0
- package/dist/testing/fake-hub.js.map +1 -0
- package/dist/testing/helpers.d.ts +124 -0
- package/dist/testing/helpers.d.ts.map +1 -0
- package/dist/testing/helpers.js +174 -0
- package/dist/testing/helpers.js.map +1 -0
- package/dist/testing/index.d.ts +12 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +12 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/setup-origins.d.ts +21 -0
- package/dist/testing/setup-origins.d.ts.map +1 -0
- package/dist/testing/setup-origins.js +57 -0
- package/dist/testing/setup-origins.js.map +1 -0
- package/dist/testing/sso-helpers.d.ts +43 -0
- package/dist/testing/sso-helpers.d.ts.map +1 -0
- package/dist/testing/sso-helpers.js +159 -0
- package/dist/testing/sso-helpers.js.map +1 -0
- package/dist/tool-definition.d.ts +382 -0
- package/dist/tool-definition.d.ts.map +1 -0
- package/dist/tool-definition.js +46 -0
- package/dist/tool-definition.js.map +1 -0
- package/dist/util/index.d.ts +8 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +8 -0
- package/dist/util/index.js.map +1 -0
- package/package.json +161 -0
- package/src/accounts/deletion.ts +389 -0
- package/src/accounts/erasure-log.ts +140 -0
- package/src/accounts/index.ts +5 -0
- package/src/accounts/mint-refusal.ts +67 -0
- package/src/accounts/signup-duplicate.ts +21 -0
- package/src/accounts/superadmin.ts +46 -0
- package/src/api/apikeys.ts +147 -0
- package/src/api/audit.ts +83 -0
- package/src/api/break-glass.ts +294 -0
- package/src/api/cli-auth.ts +308 -0
- package/src/api/create-api.ts +1403 -0
- package/src/api/demo-passes.ts +207 -0
- package/src/api/errors.ts +13 -0
- package/src/api/export.ts +482 -0
- package/src/api/files.ts +200 -0
- package/src/api/index.ts +29 -0
- package/src/api/invitations.ts +396 -0
- package/src/api/members.ts +617 -0
- package/src/api/onboarding.ts +50 -0
- package/src/api/openapi-doc.ts +34 -0
- package/src/api/projects.ts +788 -0
- package/src/api/scope-routes.ts +12 -0
- package/src/api/sso-connect.ts +246 -0
- package/src/api/sso-logout.ts +76 -0
- package/src/api/teams.ts +575 -0
- package/src/api/workspaces.ts +649 -0
- package/src/apikeys/index.ts +2 -0
- package/src/apikeys/peppers.ts +118 -0
- package/src/apikeys/service.ts +223 -0
- package/src/app.ts +228 -0
- package/src/audit/filters.ts +101 -0
- package/src/audit/index.ts +9 -0
- package/src/audit/service.ts +154 -0
- package/src/boot.ts +953 -0
- package/src/constant-time.ts +9 -0
- package/src/email/driver.ts +139 -0
- package/src/email/index.ts +26 -0
- package/src/email/shell.ts +201 -0
- package/src/email/templates.ts +184 -0
- package/src/entitlements/check.ts +435 -0
- package/src/entitlements/clock-skew.ts +58 -0
- package/src/entitlements/gate.ts +636 -0
- package/src/entitlements/hub-machine-token.ts +205 -0
- package/src/entitlements/hub-subject.ts +77 -0
- package/src/entitlements/index.ts +37 -0
- package/src/entitlements/poster.ts +265 -0
- package/src/entitlements/profiles.ts +303 -0
- package/src/entitlements/slot.ts +105 -0
- package/src/env.ts +456 -0
- package/src/files/http.ts +77 -0
- package/src/files/index.ts +4 -0
- package/src/files/serve.ts +115 -0
- package/src/files/service.ts +209 -0
- package/src/files/spool.ts +58 -0
- package/src/identity/better-auth.ts +1103 -0
- package/src/identity/demo-pass-plugin.ts +121 -0
- package/src/identity/demo-pass-rules.ts +229 -0
- package/src/identity/demo-pass.ts +390 -0
- package/src/identity/hub-grant.ts +704 -0
- package/src/identity/hub-jwt.ts +78 -0
- package/src/identity/hub-live-gate.ts +167 -0
- package/src/identity/hub-logout.ts +174 -0
- package/src/identity/hub-projection.ts +251 -0
- package/src/identity/hub-reconcile.ts +572 -0
- package/src/identity/hub-sso.ts +696 -0
- package/src/identity/hub-user-client.ts +554 -0
- package/src/identity/index.ts +56 -0
- package/src/identity/oauth-jwt.ts +128 -0
- package/src/identity/resolve-membership.ts +104 -0
- package/src/identity/signing-key.ts +164 -0
- package/src/index.ts +65 -0
- package/src/invitations/index.ts +1 -0
- package/src/invitations/service.ts +171 -0
- package/src/jobs/index.ts +25 -0
- package/src/jobs/pgboss.ts +594 -0
- package/src/jobs/timers.ts +287 -0
- package/src/logger.ts +67 -0
- package/src/mcp/errors.ts +111 -0
- package/src/mcp/http.ts +129 -0
- package/src/mcp/index.ts +28 -0
- package/src/mcp/inputs.ts +33 -0
- package/src/mcp/projects.ts +480 -0
- package/src/mcp/server.ts +174 -0
- package/src/mcp/teams.ts +97 -0
- package/src/mcp/tool-kit.ts +148 -0
- package/src/members/removal.ts +216 -0
- package/src/middleware/auth-body.ts +58 -0
- package/src/middleware/auth-context.ts +384 -0
- package/src/middleware/body-cap.ts +33 -0
- package/src/middleware/body-refusal.ts +23 -0
- package/src/middleware/cross-site.ts +122 -0
- package/src/middleware/hub-managed.ts +61 -0
- package/src/middleware/idempotency.ts +264 -0
- package/src/middleware/index.ts +33 -0
- package/src/middleware/json-depth.ts +74 -0
- package/src/middleware/no-store.ts +30 -0
- package/src/middleware/oauth-public.ts +54 -0
- package/src/middleware/rate-limit.ts +432 -0
- package/src/middleware/request-id.ts +54 -0
- package/src/middleware/scopes.ts +150 -0
- package/src/middleware/security-headers.ts +129 -0
- package/src/observability/index.ts +2 -0
- package/src/observability/metrics.ts +102 -0
- package/src/observability/otel.ts +79 -0
- package/src/pagination.ts +118 -0
- package/src/platform/edition.ts +140 -0
- package/src/platform/entitlements.ts +47 -0
- package/src/platform/events.ts +71 -0
- package/src/platform/index.ts +7 -0
- package/src/platform/local-identity.ts +90 -0
- package/src/platform/registry.ts +28 -0
- package/src/platform/usage.ts +13 -0
- package/src/platform/workspaces.ts +41 -0
- package/src/projects/access.ts +160 -0
- package/src/projects/index.ts +7 -0
- package/src/route-label.ts +29 -0
- package/src/routes/health.ts +79 -0
- package/src/routes/index.ts +2 -0
- package/src/routes/wellknown.ts +67 -0
- package/src/secret.ts +115 -0
- package/src/setup-transport.ts +46 -0
- package/src/state.ts +23 -0
- package/src/storage/driver.ts +48 -0
- package/src/storage/factory.ts +34 -0
- package/src/storage/index.ts +3 -0
- package/src/storage/local.ts +93 -0
- package/src/storage/s3.ts +109 -0
- package/src/testing/fake-hub.ts +1316 -0
- package/src/testing/helpers.ts +254 -0
- package/src/testing/index.ts +11 -0
- package/src/testing/setup-origins.ts +58 -0
- package/src/testing/sso-helpers.ts +178 -0
- package/src/tool-definition.ts +463 -0
- package/src/util/index.ts +17 -0
- package/test/fixtures/onboarding-backfill.sql +13 -0
- package/test/fixtures/operator-user-id-backfill.sql +18 -0
- package/test/host/dr-lib.sh +253 -0
- package/test/host/drizzle/0000_chassis_baseline.sql +438 -0
- package/test/host/drizzle/0001_last_owner_guard.sql +42 -0
- package/test/host/drizzle/meta/0000_snapshot.json +3566 -0
- package/test/host/drizzle/meta/_journal.json +20 -0
- package/test/host/drizzle.config.ts +17 -0
- package/test/host/identity.ts +41 -0
- package/test/host/minimal-host.ts +35 -0
- package/test/host/minimal-tool.ts +123 -0
- package/test/integration/account-oracle-uniformity.test.ts +284 -0
- package/test/integration/account-recovery.test.ts +236 -0
- package/test/integration/account.test.ts +120 -0
- package/test/integration/api-quota.test.ts +208 -0
- package/test/integration/apikey-expiry.test.ts +178 -0
- package/test/integration/apikey-pepper-rotation.test.ts +190 -0
- package/test/integration/boot-posture.test.ts +169 -0
- package/test/integration/break-glass.test.ts +484 -0
- package/test/integration/cloud-lifecycle.test.ts +233 -0
- package/test/integration/credential-boundaries.test.ts +195 -0
- package/test/integration/default-workspace.test.ts +414 -0
- package/test/integration/demo-pass-rules.test.ts +332 -0
- package/test/integration/demo-pass.test.ts +1222 -0
- package/test/integration/dr-verify-real-dump.test.ts +154 -0
- package/test/integration/edition.test.ts +868 -0
- package/test/integration/email-change.test.ts +394 -0
- package/test/integration/empty-tool.test.ts +267 -0
- package/test/integration/entitlements-null-hook.test.ts +187 -0
- package/test/integration/entitlements.test.ts +693 -0
- package/test/integration/export-entries.test.ts +321 -0
- package/test/integration/files.test.ts +320 -0
- package/test/integration/first-boot-claim.test.ts +131 -0
- package/test/integration/gdpr.test.ts +532 -0
- package/test/integration/helpers.ts +29 -0
- package/test/integration/hub-grant.test.ts +505 -0
- package/test/integration/hub-live-gate.test.ts +612 -0
- package/test/integration/hub-managed-membership.test.ts +559 -0
- package/test/integration/hub-org-selector.test.ts +281 -0
- package/test/integration/hub-reconcile.test.ts +646 -0
- package/test/integration/hub-sso.test.ts +704 -0
- package/test/integration/hub-teams.test.ts +771 -0
- package/test/integration/idempotency.test.ts +261 -0
- package/test/integration/invite-verification.test.ts +210 -0
- package/test/integration/last-owner-race.test.ts +263 -0
- package/test/integration/m9-fixes.test.ts +290 -0
- package/test/integration/mcp-projects.test.ts +463 -0
- package/test/integration/member-removal-race.test.ts +466 -0
- package/test/integration/member-removal.test.ts +794 -0
- package/test/integration/oauth-mcp.test.ts +477 -0
- package/test/integration/oauth-workspace.test.ts +371 -0
- package/test/integration/observability.test.ts +183 -0
- package/test/integration/onboarding.test.ts +268 -0
- package/test/integration/orphan-purge.test.ts +451 -0
- package/test/integration/pagination.test.ts +344 -0
- package/test/integration/platform-core.test.ts +305 -0
- package/test/integration/platform.test.ts +246 -0
- package/test/integration/pool-survives-restart.test.ts +80 -0
- package/test/integration/projects-cloud.test.ts +193 -0
- package/test/integration/projects.test.ts +1310 -0
- package/test/integration/security-fixes.test.ts +190 -0
- package/test/integration/setup-transport.test.ts +118 -0
- package/test/integration/signin-wall.test.ts +103 -0
- package/test/integration/signing-key-rotation.test.ts +349 -0
- package/test/integration/sso-helpers.ts +15 -0
- package/test/integration/sso-logout.test.ts +283 -0
- package/test/integration/teams-cloud.test.ts +194 -0
- package/test/integration/teams.test.ts +551 -0
- package/test/integration/timers.test.ts +377 -0
- package/test/integration/two-factor.test.ts +301 -0
- package/test/integration/usage-window.test.ts +161 -0
- package/test/integration/workspace-create-cloud.test.ts +523 -0
- package/test/integration/workspace-create.test.ts +510 -0
- package/test/integration/workspace-scoping.test.ts +530 -0
- package/test/integration/zz-adv-replay-owner.test.ts +205 -0
- package/test/unit/apikey-peppers.test.ts +110 -0
- package/test/unit/apikey-prefix.test.ts +34 -0
- package/test/unit/audit-filters.test.ts +135 -0
- package/test/unit/auth-origins.test.ts +92 -0
- package/test/unit/body-cap.test.ts +84 -0
- package/test/unit/clock-skew.test.ts +68 -0
- package/test/unit/cross-site.test.ts +166 -0
- package/test/unit/declared-credits.test.ts +13 -0
- package/test/unit/demo-pass-rules.test.ts +192 -0
- package/test/unit/email-driver.test.ts +127 -0
- package/test/unit/end-pool.test.ts +181 -0
- package/test/unit/entitlement-check.test.ts +492 -0
- package/test/unit/entitlement-gate.test.ts +1333 -0
- package/test/unit/entitlement-profiles.test.ts +289 -0
- package/test/unit/erasure-log.test.ts +72 -0
- package/test/unit/error-mapping.test.ts +89 -0
- package/test/unit/export-entries.test.ts +85 -0
- package/test/unit/export-sanitize.test.ts +27 -0
- package/test/unit/files-head-route.test.ts +155 -0
- package/test/unit/files-http.test.ts +97 -0
- package/test/unit/head-rewrite.test.ts +72 -0
- package/test/unit/hub-create-org.test.ts +181 -0
- package/test/unit/hub-jwt.test.ts +93 -0
- package/test/unit/hub-sso-params.test.ts +39 -0
- package/test/unit/hub-subject.test.ts +83 -0
- package/test/unit/idempotency-crypto.test.ts +45 -0
- package/test/unit/json-depth.test.ts +88 -0
- package/test/unit/logger-redaction.test.ts +66 -0
- package/test/unit/mcp-errors.test.ts +110 -0
- package/test/unit/mcp-inputs.test.ts +106 -0
- package/test/unit/mcp-project-hints.test.ts +26 -0
- package/test/unit/no-store.test.ts +49 -0
- package/test/unit/no-tool-migration-filename.test.ts +70 -0
- package/test/unit/observability.test.ts +64 -0
- package/test/unit/openapi-doc.test.ts +93 -0
- package/test/unit/rate-limit-consume-on.test.ts +76 -0
- package/test/unit/rate-limit.test.ts +39 -0
- package/test/unit/readyz-storage.test.ts +157 -0
- package/test/unit/request-quota.test.ts +146 -0
- package/test/unit/scopes.test.ts +66 -0
- package/test/unit/security-headers.test.ts +131 -0
- package/test/unit/serve-content-type.test.ts +74 -0
- package/test/unit/setup-transport.test.ts +29 -0
- package/test/unit/storage-local.test.ts +53 -0
- package/test/unit/superadmin.test.ts +32 -0
- package/test/unit/timers.test.ts +287 -0
- package/test/unit/tool-definition-guards.test.ts +166 -0
- package/test/unit/tool-entitlements-guard.test.ts +168 -0
- package/test/unit/usage-poster.test.ts +542 -0
- package/test/unit/usage-window.test.ts +48 -0
- package/test/unit/workspace-create-audit.test.ts +48 -0
package/src/secret.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import type { Logger } from './logger.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the auth secret: prefer AUTH_SECRET from the environment; otherwise
|
|
8
|
+
* persist a generated one under DATA_DIR (n8n-style zero-config first run).
|
|
9
|
+
* The file is written 0600 and reused on every subsequent boot, so sessions
|
|
10
|
+
* survive restarts even when the operator never set a secret.
|
|
11
|
+
*/
|
|
12
|
+
export async function resolveAuthSecret(
|
|
13
|
+
envSecret: string | undefined,
|
|
14
|
+
dataDir: string,
|
|
15
|
+
log: Logger
|
|
16
|
+
): Promise<string> {
|
|
17
|
+
if (envSecret) return envSecret;
|
|
18
|
+
|
|
19
|
+
const secretPath = join(dataDir, 'secret');
|
|
20
|
+
try {
|
|
21
|
+
const existing = (await readFile(secretPath, 'utf8')).trim();
|
|
22
|
+
if (existing.length >= 32) return existing;
|
|
23
|
+
log.warn({ secretPath }, 'existing secret file is too short — regenerating');
|
|
24
|
+
} catch {
|
|
25
|
+
// no secret file yet
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const secret = randomBytes(32).toString('hex');
|
|
29
|
+
await mkdir(dataDir, { recursive: true });
|
|
30
|
+
// Write + rename (same dir → atomic) so a crash mid-write never leaves a
|
|
31
|
+
// truncated secret that a later boot would accept and lock everyone out.
|
|
32
|
+
const tmpPath = join(dataDir, `.secret.${randomBytes(6).toString('hex')}.tmp`);
|
|
33
|
+
try {
|
|
34
|
+
await writeFile(tmpPath, secret + '\n', { mode: 0o600 });
|
|
35
|
+
await rename(tmpPath, secretPath);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
await rm(tmpPath, { force: true });
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
log.warn(
|
|
41
|
+
{ secretPath },
|
|
42
|
+
'AUTH_SECRET was not set — generated one into the data volume. ' +
|
|
43
|
+
'Set AUTH_SECRET explicitly for multi-replica deployments; all replicas must share it.'
|
|
44
|
+
);
|
|
45
|
+
return secret;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Where a boot-generated setup token lives until the instance is claimed. */
|
|
49
|
+
export function generatedSetupTokenPath(dataDir: string): string {
|
|
50
|
+
return join(dataDir, 'setup-token');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The credential POST /api/v1/setup REQUIRES (PRDCT-1347, audit A7). The
|
|
55
|
+
* first-boot claim decides who owns the instance, so it can never be free:
|
|
56
|
+
*
|
|
57
|
+
* - `SETUP_TOKEN` set → that is the token (setup.sh writes one);
|
|
58
|
+
* - instance already set up → nothing to claim, no token needed (null);
|
|
59
|
+
* - otherwise → a token is generated ONCE into `$DATA_DIR/setup-token`
|
|
60
|
+
* (0600, atomic write, reused on every later boot until the claim) and
|
|
61
|
+
* printed to the container log, so the `docker run` / plain
|
|
62
|
+
* `docker compose up` paths — which never go through setup.sh — still
|
|
63
|
+
* produce an instance claimable only with a secret. The file is removed
|
|
64
|
+
* once setup completes (see clearGeneratedSetupToken).
|
|
65
|
+
*
|
|
66
|
+
* Optional-when-set was the hole: a minimal-env container answered the
|
|
67
|
+
* claim with 201 and no credential at all.
|
|
68
|
+
*/
|
|
69
|
+
export async function resolveSetupToken(
|
|
70
|
+
envToken: string | undefined,
|
|
71
|
+
dataDir: string,
|
|
72
|
+
alreadySetUp: boolean,
|
|
73
|
+
log: Logger
|
|
74
|
+
): Promise<string | null> {
|
|
75
|
+
if (envToken) return envToken;
|
|
76
|
+
if (alreadySetUp) return null;
|
|
77
|
+
|
|
78
|
+
const tokenPath = generatedSetupTokenPath(dataDir);
|
|
79
|
+
try {
|
|
80
|
+
const existing = (await readFile(tokenPath, 'utf8')).trim();
|
|
81
|
+
if (existing.length >= 16) {
|
|
82
|
+
log.warn(
|
|
83
|
+
{ tokenPath },
|
|
84
|
+
`SETUP_TOKEN is not set — the setup wizard requires the token generated at first boot: ${existing}`
|
|
85
|
+
);
|
|
86
|
+
return existing;
|
|
87
|
+
}
|
|
88
|
+
log.warn({ tokenPath }, 'existing setup-token file is too short — regenerating');
|
|
89
|
+
} catch {
|
|
90
|
+
// no token file yet
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const token = randomBytes(16).toString('hex');
|
|
94
|
+
await mkdir(dataDir, { recursive: true });
|
|
95
|
+
const tmpPath = join(dataDir, `.setup-token.${randomBytes(6).toString('hex')}.tmp`);
|
|
96
|
+
try {
|
|
97
|
+
await writeFile(tmpPath, token + '\n', { mode: 0o600 });
|
|
98
|
+
await rename(tmpPath, tokenPath);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
await rm(tmpPath, { force: true });
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
log.warn(
|
|
104
|
+
{ tokenPath },
|
|
105
|
+
'SETUP_TOKEN was not set — generated one for the first-boot setup wizard. ' +
|
|
106
|
+
`Use this token to claim the instance: ${token} ` +
|
|
107
|
+
'(also readable inside the container at that path; set SETUP_TOKEN explicitly to choose your own)'
|
|
108
|
+
);
|
|
109
|
+
return token;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Best-effort removal of the generated token once the claim has succeeded. */
|
|
113
|
+
export async function clearGeneratedSetupToken(dataDir: string): Promise<void> {
|
|
114
|
+
await rm(generatedSetupTokenPath(dataDir), { force: true });
|
|
115
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport guard for the one-shot first-boot wizard (PLT-10).
|
|
3
|
+
*
|
|
4
|
+
* `POST /api/v1/setup` carries the owner's password and the setup token. Over
|
|
5
|
+
* plaintext HTTP to a non-loopback origin both cross the network in the clear
|
|
6
|
+
* — and this is the single request that decides who owns the instance. The
|
|
7
|
+
* documented no-domain install path used to walk operators straight into
|
|
8
|
+
* exactly that, so the server refuses instead of trusting the runbook.
|
|
9
|
+
*
|
|
10
|
+
* Loopback is fine: nothing leaves the host, which is what makes the
|
|
11
|
+
* `ssh -L` tunnel a legitimate way to finish setup on a server with no TLS
|
|
12
|
+
* yet. `https` is fine anywhere. Everything else needs the conscious
|
|
13
|
+
* `ALLOW_INSECURE_SETUP=true` opt-in.
|
|
14
|
+
*/
|
|
15
|
+
export function isSecureSetupOrigin(publicBaseUrl: string): boolean {
|
|
16
|
+
let url: URL;
|
|
17
|
+
try {
|
|
18
|
+
url = new URL(publicBaseUrl);
|
|
19
|
+
} catch {
|
|
20
|
+
// Unparseable never reaches here (the env schema validates a URL), and a
|
|
21
|
+
// guard that cannot read the origin must fail closed.
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (url.protocol === 'https:') return true;
|
|
25
|
+
return isLoopbackHost(url.hostname);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* `URL.hostname` KEEPS the brackets around an IPv6 literal (`[::1]`), so they
|
|
30
|
+
* are stripped here. IPv4 loopback is the whole 127.0.0.0/8 block, not just
|
|
31
|
+
* 127.0.0.1. Exported for the demo sign-in's host rule
|
|
32
|
+
* (identity/demo-pass-rules.ts): one loopback test for the whole server.
|
|
33
|
+
*/
|
|
34
|
+
export function isLoopbackHost(hostname: string): boolean {
|
|
35
|
+
let host = hostname.toLowerCase();
|
|
36
|
+
if (host.startsWith('[') && host.endsWith(']')) host = host.slice(1, -1);
|
|
37
|
+
if (host === 'localhost' || host.endsWith('.localhost')) return true;
|
|
38
|
+
if (host === '::1' || host === '0:0:0:0:0:0:0:1') return true;
|
|
39
|
+
const v4 = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
|
|
40
|
+
if (v4) {
|
|
41
|
+
const octets = v4.slice(1).map(Number);
|
|
42
|
+
if (octets.some((o) => o > 255)) return false;
|
|
43
|
+
return octets[0] === 127;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
package/src/state.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-local runtime state. This is NOT application state (which lives in
|
|
3
|
+
* Postgres per the statelessness invariant) — it is the lifecycle of this one
|
|
4
|
+
* replica: readiness for /readyz and the draining flag for graceful shutdown.
|
|
5
|
+
*/
|
|
6
|
+
export interface RuntimeState {
|
|
7
|
+
ready: boolean;
|
|
8
|
+
reason: string;
|
|
9
|
+
draining: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* A fail-closed boot verdict (PRDCT-1809): when set, every route except
|
|
12
|
+
* liveness, readiness and metrics answers 503 `service_closed` with this
|
|
13
|
+
* reason. Readiness alone does not stop the API — the single-host
|
|
14
|
+
* deployment's healthcheck watches /healthz — so a boot that found
|
|
15
|
+
* something it must not serve (an erasure it could not replay) closes the
|
|
16
|
+
* surface itself until an operator resolves it and restarts.
|
|
17
|
+
*/
|
|
18
|
+
closed: string | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createRuntimeState(): RuntimeState {
|
|
22
|
+
return { ready: false, reason: 'booting', draining: false, closed: null };
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The storage seam. Postgres never holds file bytes; every write goes
|
|
5
|
+
* through a driver. `local` (default) writes under DATA_DIR — valid for
|
|
6
|
+
* single-replica deployments; `s3` covers MinIO self-hosted and AWS/R2/GCS
|
|
7
|
+
* interop in cloud. Presigned-URL methods are deliberately reserved for a
|
|
8
|
+
* later revision (through-app streaming is the v1 contract).
|
|
9
|
+
*/
|
|
10
|
+
export interface ByteRange {
|
|
11
|
+
/** Inclusive start offset. */
|
|
12
|
+
start: number;
|
|
13
|
+
/** Inclusive end offset. */
|
|
14
|
+
end: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PutOptions {
|
|
18
|
+
contentType: string;
|
|
19
|
+
sizeBytes: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface HeadResult {
|
|
23
|
+
sizeBytes: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface StorageDriver {
|
|
27
|
+
readonly name: 'local' | 's3';
|
|
28
|
+
put(key: string, data: Readable, opts: PutOptions): Promise<void>;
|
|
29
|
+
getStream(key: string, range?: ByteRange): Promise<Readable>;
|
|
30
|
+
exists(key: string): Promise<boolean>;
|
|
31
|
+
head(key: string): Promise<HeadResult | null>;
|
|
32
|
+
delete(key: string): Promise<void>;
|
|
33
|
+
/** Boot probe: throw when the backing store is not writable. */
|
|
34
|
+
healthcheck(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const SHA256_RE = /^[a-f0-9]{64}$/;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Content-addressed key layout: `ws/<workspaceId>/<ab>/<sha256>`. The sha is
|
|
41
|
+
* validated against a strict hex pattern, so a key can never smuggle path
|
|
42
|
+
* traversal; the two-char shard keeps directories small at the 200GB target.
|
|
43
|
+
*/
|
|
44
|
+
export function blobKey(workspaceId: string, sha256: string): string {
|
|
45
|
+
if (!SHA256_RE.test(sha256)) throw new Error('invalid sha256');
|
|
46
|
+
if (!/^[0-9a-f-]{36}$/.test(workspaceId)) throw new Error('invalid workspace id');
|
|
47
|
+
return `ws/${workspaceId}/${sha256.slice(0, 2)}/${sha256}`;
|
|
48
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import type { Env } from '../env.js';
|
|
3
|
+
import type { StorageDriver } from './driver.js';
|
|
4
|
+
import { LocalStorageDriver } from './local.js';
|
|
5
|
+
import { S3StorageDriver } from './s3.js';
|
|
6
|
+
|
|
7
|
+
export function createStorageDriver(
|
|
8
|
+
env: Pick<
|
|
9
|
+
Env,
|
|
10
|
+
| 'STORAGE_DRIVER'
|
|
11
|
+
| 'DATA_DIR'
|
|
12
|
+
| 'S3_BUCKET'
|
|
13
|
+
| 'S3_REGION'
|
|
14
|
+
| 'S3_ENDPOINT'
|
|
15
|
+
| 'S3_ACCESS_KEY_ID'
|
|
16
|
+
| 'S3_SECRET_ACCESS_KEY'
|
|
17
|
+
| 'S3_FORCE_PATH_STYLE'
|
|
18
|
+
>
|
|
19
|
+
): StorageDriver {
|
|
20
|
+
if (env.STORAGE_DRIVER === 's3') {
|
|
21
|
+
if (!env.S3_BUCKET || !env.S3_ACCESS_KEY_ID || !env.S3_SECRET_ACCESS_KEY) {
|
|
22
|
+
throw new Error('STORAGE_DRIVER=s3 requires S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY');
|
|
23
|
+
}
|
|
24
|
+
return new S3StorageDriver({
|
|
25
|
+
bucket: env.S3_BUCKET,
|
|
26
|
+
region: env.S3_REGION ?? 'us-east-1',
|
|
27
|
+
endpoint: env.S3_ENDPOINT,
|
|
28
|
+
accessKeyId: env.S3_ACCESS_KEY_ID,
|
|
29
|
+
secretAccessKey: env.S3_SECRET_ACCESS_KEY,
|
|
30
|
+
forcePathStyle: env.S3_FORCE_PATH_STYLE
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return new LocalStorageDriver(join(env.DATA_DIR, 'storage'));
|
|
34
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createWriteStream } from 'node:fs';
|
|
2
|
+
import { mkdir, open, rename, rm, stat, unlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join, normalize, sep } from 'node:path';
|
|
4
|
+
import { pipeline } from 'node:stream/promises';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import type { Readable } from 'node:stream';
|
|
7
|
+
import type { ByteRange, HeadResult, PutOptions, StorageDriver } from './driver.js';
|
|
8
|
+
|
|
9
|
+
/** A missing file — the only fs error head()/delete() treats as "absent". */
|
|
10
|
+
function isEnoent(err: unknown): boolean {
|
|
11
|
+
return (err as { code?: string })?.code === 'ENOENT';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Filesystem driver: blobs under `<root>/blobs`, writes staged in
|
|
16
|
+
* `<root>/.tmp` and renamed into place (atomic on one filesystem — both live
|
|
17
|
+
* under the same mount). Single-replica only, which is Profile A.
|
|
18
|
+
*/
|
|
19
|
+
export class LocalStorageDriver implements StorageDriver {
|
|
20
|
+
readonly name = 'local' as const;
|
|
21
|
+
private readonly blobRoot: string;
|
|
22
|
+
private readonly tmpRoot: string;
|
|
23
|
+
|
|
24
|
+
constructor(root: string) {
|
|
25
|
+
this.blobRoot = join(root, 'blobs');
|
|
26
|
+
this.tmpRoot = join(root, '.tmp');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private pathFor(key: string): string {
|
|
30
|
+
const path = normalize(join(this.blobRoot, key));
|
|
31
|
+
if (!path.startsWith(this.blobRoot + sep)) throw new Error('key escapes storage root');
|
|
32
|
+
return path;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async put(key: string, data: Readable, _opts: PutOptions): Promise<void> {
|
|
36
|
+
const finalPath = this.pathFor(key);
|
|
37
|
+
const tmpPath = join(this.tmpRoot, randomUUID());
|
|
38
|
+
await mkdir(this.tmpRoot, { recursive: true });
|
|
39
|
+
await mkdir(dirname(finalPath), { recursive: true });
|
|
40
|
+
try {
|
|
41
|
+
await pipeline(data, createWriteStream(tmpPath, { flags: 'wx' }));
|
|
42
|
+
await rename(tmpPath, finalPath);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
await rm(tmpPath, { force: true });
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async getStream(key: string, range?: ByteRange): Promise<Readable> {
|
|
50
|
+
const path = this.pathFor(key);
|
|
51
|
+
// Open eagerly: a missing blob must reject HERE, at the await — before
|
|
52
|
+
// the caller commits response headers — not as a late 'error' event on a
|
|
53
|
+
// lazily-opening createReadStream after a 200 is already on the wire
|
|
54
|
+
// (the s3 driver's GetObject await fails eagerly too; this matches it).
|
|
55
|
+
const handle = await open(path, 'r');
|
|
56
|
+
// autoClose (default) hands fd ownership to the stream: closed on end,
|
|
57
|
+
// error, and destroy — including the route's client-abort destroy().
|
|
58
|
+
return handle.createReadStream(range ? { start: range.start, end: range.end } : {});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async exists(key: string): Promise<boolean> {
|
|
62
|
+
return (await this.head(key)) !== null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async head(key: string): Promise<HeadResult | null> {
|
|
66
|
+
try {
|
|
67
|
+
const s = await stat(this.pathFor(key));
|
|
68
|
+
return { sizeBytes: s.size };
|
|
69
|
+
} catch (err) {
|
|
70
|
+
// A missing file is `null`; any other stat error (permissions, I/O)
|
|
71
|
+
// propagates rather than masquerading as "absent".
|
|
72
|
+
if (isEnoent(err)) return null;
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async delete(key: string): Promise<void> {
|
|
78
|
+
// Deleting an already-gone blob is a no-op; real errors propagate and the
|
|
79
|
+
// caller decides whether they are fatal.
|
|
80
|
+
try {
|
|
81
|
+
await unlink(this.pathFor(key));
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (!isEnoent(err)) throw err;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async healthcheck(): Promise<void> {
|
|
88
|
+
await mkdir(this.tmpRoot, { recursive: true });
|
|
89
|
+
const probe = join(this.tmpRoot, `.healthcheck-${randomUUID()}`);
|
|
90
|
+
await writeFile(probe, 'ok');
|
|
91
|
+
await unlink(probe);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import {
|
|
3
|
+
DeleteObjectCommand,
|
|
4
|
+
GetObjectCommand,
|
|
5
|
+
HeadObjectCommand,
|
|
6
|
+
PutObjectCommand,
|
|
7
|
+
S3Client
|
|
8
|
+
} from '@aws-sdk/client-s3';
|
|
9
|
+
import { Upload } from '@aws-sdk/lib-storage';
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
import type { ByteRange, HeadResult, PutOptions, StorageDriver } from './driver.js';
|
|
12
|
+
|
|
13
|
+
/** A missing object — the only S3 error head()/exists() treats as "absent". */
|
|
14
|
+
function isNotFound(err: unknown): boolean {
|
|
15
|
+
const e = err as { name?: string; $metadata?: { httpStatusCode?: number } };
|
|
16
|
+
return e?.name === 'NotFound' || e?.name === 'NoSuchKey' || e?.$metadata?.httpStatusCode === 404;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface S3DriverConfig {
|
|
20
|
+
bucket: string;
|
|
21
|
+
region: string;
|
|
22
|
+
endpoint?: string | undefined;
|
|
23
|
+
accessKeyId: string;
|
|
24
|
+
secretAccessKey: string;
|
|
25
|
+
/** Required for MinIO and most S3-compatibles. */
|
|
26
|
+
forcePathStyle: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* S3-compatible driver: MinIO self-hosted, AWS S3, Cloudflare R2 (and any
|
|
31
|
+
* endpoint speaking the S3 API). Multi-replica safe — this is the Profile B
|
|
32
|
+
* storage driver.
|
|
33
|
+
*/
|
|
34
|
+
export class S3StorageDriver implements StorageDriver {
|
|
35
|
+
readonly name = 's3' as const;
|
|
36
|
+
private readonly client: S3Client;
|
|
37
|
+
private readonly bucket: string;
|
|
38
|
+
|
|
39
|
+
constructor(config: S3DriverConfig) {
|
|
40
|
+
this.bucket = config.bucket;
|
|
41
|
+
this.client = new S3Client({
|
|
42
|
+
region: config.region,
|
|
43
|
+
...(config.endpoint ? { endpoint: config.endpoint } : {}),
|
|
44
|
+
forcePathStyle: config.forcePathStyle,
|
|
45
|
+
credentials: {
|
|
46
|
+
accessKeyId: config.accessKeyId,
|
|
47
|
+
secretAccessKey: config.secretAccessKey
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async put(key: string, data: Readable, opts: PutOptions): Promise<void> {
|
|
53
|
+
// lib-storage handles multipart for large bodies and backpressure.
|
|
54
|
+
const upload = new Upload({
|
|
55
|
+
client: this.client,
|
|
56
|
+
params: {
|
|
57
|
+
Bucket: this.bucket,
|
|
58
|
+
Key: key,
|
|
59
|
+
Body: data,
|
|
60
|
+
ContentType: opts.contentType,
|
|
61
|
+
ContentLength: opts.sizeBytes
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
await upload.done();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async getStream(key: string, range?: ByteRange): Promise<Readable> {
|
|
68
|
+
const res = await this.client.send(
|
|
69
|
+
new GetObjectCommand({
|
|
70
|
+
Bucket: this.bucket,
|
|
71
|
+
Key: key,
|
|
72
|
+
...(range ? { Range: `bytes=${range.start}-${range.end}` } : {})
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
if (!res.Body) throw new Error('empty S3 response body');
|
|
76
|
+
return res.Body as Readable;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async exists(key: string): Promise<boolean> {
|
|
80
|
+
return (await this.head(key)) !== null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async head(key: string): Promise<HeadResult | null> {
|
|
84
|
+
try {
|
|
85
|
+
const res = await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: key }));
|
|
86
|
+
return { sizeBytes: res.ContentLength ?? 0 };
|
|
87
|
+
} catch (err) {
|
|
88
|
+
// Only a genuine miss is `null`. A transport/permission error must
|
|
89
|
+
// propagate — swallowing it made a broken bucket look like an empty one,
|
|
90
|
+
// and exists() (upload dedup) would then re-put or 400 misleadingly.
|
|
91
|
+
if (isNotFound(err)) return null;
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async delete(key: string): Promise<void> {
|
|
97
|
+
// S3 DeleteObject is idempotent (no error on a missing key); a real
|
|
98
|
+
// failure propagates and the caller decides whether it is fatal.
|
|
99
|
+
await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async healthcheck(): Promise<void> {
|
|
103
|
+
const probe = `.healthcheck/${randomUUID()}`;
|
|
104
|
+
await this.client.send(
|
|
105
|
+
new PutObjectCommand({ Bucket: this.bucket, Key: probe, Body: 'ok', ContentLength: 2 })
|
|
106
|
+
);
|
|
107
|
+
await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: probe }));
|
|
108
|
+
}
|
|
109
|
+
}
|