@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
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
+
import type { StartedPostgreSqlContainer } from '@testcontainers/postgresql';
|
|
3
|
+
import {
|
|
4
|
+
createDatabase,
|
|
5
|
+
createTestApp,
|
|
6
|
+
expectBootRefusal,
|
|
7
|
+
extractCookie,
|
|
8
|
+
host,
|
|
9
|
+
readJson,
|
|
10
|
+
startPostgres,
|
|
11
|
+
SETUP_TOKEN,
|
|
12
|
+
type TestApp
|
|
13
|
+
} from './helpers.js';
|
|
14
|
+
import { seedLocalWorkspace } from './sso-helpers.js';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
import { dirname, join, resolve } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
const fixturesDir = resolve(dirname(fileURLToPath(import.meta.url)), '../fixtures');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* PRDCT-1356 — cloud lifecycle & recovery, the server-side members:
|
|
23
|
+
*
|
|
24
|
+
* - CLOUD-1 / AUTH-13: POST /auth/unlink-account for the `antasphere`
|
|
25
|
+
* provider answers 403 on cloud (the /auth mount never saw the principal
|
|
26
|
+
* gate; unlinking left hub-origin memberships behind a permanent
|
|
27
|
+
* fail-open `no_link` reconcile);
|
|
28
|
+
* - EDIT-2: /sign-in/email on cloud is the OPERATOR's + allowlist's door
|
|
29
|
+
* only — every other local credential is refused with one 403 (no
|
|
30
|
+
* account oracle);
|
|
31
|
+
* - CLOUD-5: the invitation-accept account-creation branch is closed on
|
|
32
|
+
* cloud (409 sso_required), the same stance as the collaborator claim;
|
|
33
|
+
* - EDIT-1/3/4: the oss→cloud flip is REFUSED while an unprojected
|
|
34
|
+
* workspace or an unverified user exists, and the reverse flip is
|
|
35
|
+
* refused outright.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const OWNER = { email: 'operator@lifecycle.test', name: 'Operator', password: 'operator-password-123' };
|
|
39
|
+
const HUB_ENV = {
|
|
40
|
+
EDITION: 'cloud',
|
|
41
|
+
HUB_ISSUER_URL: 'http://hub.localhost:3300',
|
|
42
|
+
HUB_CLIENT_ID: host.hubClientId,
|
|
43
|
+
HUB_CLIENT_SECRET: 'integration-test-hub-secret-0001'
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
let ipCounter = 0;
|
|
47
|
+
const nextIp = () => `198.51.100.${++ipCounter % 250}`;
|
|
48
|
+
const json = (body: unknown, headers: Record<string, string> = {}) => ({
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: { 'content-type': 'application/json', 'x-forwarded-for': nextIp(), ...headers },
|
|
51
|
+
body: JSON.stringify(body)
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let container: StartedPostgreSqlContainer;
|
|
55
|
+
|
|
56
|
+
beforeAll(async () => {
|
|
57
|
+
container = await startPostgres();
|
|
58
|
+
}, 180_000);
|
|
59
|
+
|
|
60
|
+
afterAll(async () => {
|
|
61
|
+
await container?.stop();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("cloud edition: the local doors are the operator's only", () => {
|
|
65
|
+
let app: TestApp;
|
|
66
|
+
let operatorCookie: string;
|
|
67
|
+
|
|
68
|
+
beforeAll(async () => {
|
|
69
|
+
app = await createTestApp(await createDatabase(container, 'lifecycle_cloud'), HUB_ENV);
|
|
70
|
+
const setup = await app.app.request(
|
|
71
|
+
'/api/v1/setup',
|
|
72
|
+
json({ setupToken: SETUP_TOKEN, instanceName: 'LC', owner: OWNER })
|
|
73
|
+
);
|
|
74
|
+
expect(setup.status).toBe(201);
|
|
75
|
+
const signIn = await app.app.request(
|
|
76
|
+
'/api/v1/auth/sign-in/email',
|
|
77
|
+
json({ email: OWNER.email, password: OWNER.password })
|
|
78
|
+
);
|
|
79
|
+
expect(signIn.status).toBe(200);
|
|
80
|
+
operatorCookie = extractCookie(signIn);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
afterAll(async () => {
|
|
84
|
+
await app.stop();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('setup recorded the operator durably on the instance row (CLOUD-3)', async () => {
|
|
88
|
+
const { rows } = await app.db.pool.query<{ operator_user_id: string | null; email: string }>(
|
|
89
|
+
`SELECT s.operator_user_id, u.email FROM instance_settings s JOIN "user" u ON u.id = s.operator_user_id`
|
|
90
|
+
);
|
|
91
|
+
expect(rows).toHaveLength(1);
|
|
92
|
+
expect(rows[0]!.email).toBe(OWNER.email);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('migration 0036 backfills operator_user_id from the setup audit row on pre-existing instances (F2)', async () => {
|
|
96
|
+
// A cloud instance set up BEFORE the column existed: NULL — which would
|
|
97
|
+
// close the operator's local sign-in door after the upgrade.
|
|
98
|
+
await app.db.pool.query(`UPDATE instance_settings SET operator_user_id = NULL`);
|
|
99
|
+
const shut = await app.app.request(
|
|
100
|
+
'/api/v1/auth/sign-in/email',
|
|
101
|
+
json({ email: OWNER.email, password: OWNER.password })
|
|
102
|
+
);
|
|
103
|
+
expect(shut.status).toBe(403);
|
|
104
|
+
// Run the migration's backfill statement (everything after the ALTER): a
|
|
105
|
+
// fixture the chassis owns, whose header says which migration it mirrors.
|
|
106
|
+
const backfill = readFileSync(join(fixturesDir, 'operator-user-id-backfill.sql'), 'utf8');
|
|
107
|
+
expect(backfill).toMatch(/UPDATE "instance_settings"/);
|
|
108
|
+
await app.db.pool.query(backfill);
|
|
109
|
+
const { rows } = await app.db.pool.query<{ email: string }>(
|
|
110
|
+
`SELECT u.email FROM instance_settings s JOIN "user" u ON u.id = s.operator_user_id`
|
|
111
|
+
);
|
|
112
|
+
expect(rows).toEqual([{ email: OWNER.email }]);
|
|
113
|
+
const open = await app.app.request(
|
|
114
|
+
'/api/v1/auth/sign-in/email',
|
|
115
|
+
json({ email: OWNER.email, password: OWNER.password })
|
|
116
|
+
);
|
|
117
|
+
expect(open.status).toBe(200);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('refuses to unlink the antasphere provider (403 hub_unlink_forbidden), even for a signed-in caller', async () => {
|
|
121
|
+
const res = await app.app.request(
|
|
122
|
+
'/api/v1/auth/unlink-account',
|
|
123
|
+
json({ providerId: 'antasphere' }, { cookie: operatorCookie })
|
|
124
|
+
);
|
|
125
|
+
expect(res.status).toBe(403);
|
|
126
|
+
const body = await readJson(res);
|
|
127
|
+
expect(JSON.stringify(body)).toContain('hub_unlink_forbidden');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('a non-operator, non-allowlisted email is refused at the password door (403 local_signin_disabled)', async () => {
|
|
131
|
+
const res = await app.app.request(
|
|
132
|
+
'/api/v1/auth/sign-in/email',
|
|
133
|
+
json({ email: 'someone@lifecycle.test', password: 'whatever-password-123' })
|
|
134
|
+
);
|
|
135
|
+
expect(res.status).toBe(403);
|
|
136
|
+
expect(JSON.stringify(await readJson(res))).toContain('local_signin_disabled');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('the operator keeps the door (the break-glass identity)', async () => {
|
|
140
|
+
const res = await app.app.request(
|
|
141
|
+
'/api/v1/auth/sign-in/email',
|
|
142
|
+
json({ email: OWNER.email.toUpperCase(), password: OWNER.password })
|
|
143
|
+
);
|
|
144
|
+
expect(res.status).toBe(200);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('invitation accept on a cloud-LOCAL workspace never mints a local-password account (409 sso_required)', async () => {
|
|
148
|
+
const wsId = await seedLocalWorkspace(app, 'Local Host', OWNER.email);
|
|
149
|
+
const inv = await app.app.request(
|
|
150
|
+
'/api/v1/invitations',
|
|
151
|
+
json(
|
|
152
|
+
{ email: 'invitee@lifecycle.test', role: 'member' },
|
|
153
|
+
{ cookie: operatorCookie, 'x-workspace-id': wsId }
|
|
154
|
+
)
|
|
155
|
+
);
|
|
156
|
+
expect(inv.status).toBe(201);
|
|
157
|
+
const token = ((await readJson(inv)).acceptUrl as string).split('/invite/')[1]!;
|
|
158
|
+
const accepted = await app.app.request(
|
|
159
|
+
'/api/v1/invitations/accept',
|
|
160
|
+
json({ token, name: 'Invitee', password: 'invitee-password-123' })
|
|
161
|
+
);
|
|
162
|
+
expect(accepted.status).toBe(409);
|
|
163
|
+
expect((await readJson(accepted)).error.code).toBe('sso_required');
|
|
164
|
+
const users = await app.db.pool.query(`SELECT 1 FROM "user" WHERE email = 'invitee@lifecycle.test'`);
|
|
165
|
+
expect(users.rows).toHaveLength(0);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('the edition flip pre-flights (EDIT-1/3) and the reverse flip is refused (EDIT-4)', () => {
|
|
170
|
+
let connectionString: string;
|
|
171
|
+
|
|
172
|
+
beforeAll(async () => {
|
|
173
|
+
connectionString = await createDatabase(container, 'lifecycle_flip');
|
|
174
|
+
const app = await createTestApp(connectionString);
|
|
175
|
+
const res = await app.app.request(
|
|
176
|
+
'/api/v1/setup',
|
|
177
|
+
json({ setupToken: SETUP_TOKEN, instanceName: 'Flip', owner: OWNER })
|
|
178
|
+
);
|
|
179
|
+
expect(res.status).toBe(201);
|
|
180
|
+
await app.stop();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('oss→cloud with the flag is REFUSED while a workspace has no hub projection', async () => {
|
|
184
|
+
await expectBootRefusal(
|
|
185
|
+
createTestApp(connectionString, { ...HUB_ENV, EDITION_CHANGE_ALLOWED: 'true' }),
|
|
186
|
+
/refusing the edition flip 'oss' → 'cloud'.*no hub projection/
|
|
187
|
+
);
|
|
188
|
+
// Nothing moved: the stamp is still oss and a plain oss boot still works.
|
|
189
|
+
const still = await createTestApp(connectionString);
|
|
190
|
+
const { rows } = await still.db.pool.query<{ edition: string }>(`SELECT edition FROM instance_settings`);
|
|
191
|
+
expect(rows).toEqual([{ edition: 'oss' }]);
|
|
192
|
+
await still.stop();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('…and while a user has an unverified email', async () => {
|
|
196
|
+
const app = await createTestApp(connectionString);
|
|
197
|
+
// Project the workspace (what the hub onboarding would do) so only the
|
|
198
|
+
// unverified user stands in the way.
|
|
199
|
+
await app.db.pool.query(
|
|
200
|
+
`UPDATE workspaces SET central_account_id = '44444444-aaaa-4bbb-8ccc-000000000001'`
|
|
201
|
+
);
|
|
202
|
+
await app.db.pool.query(
|
|
203
|
+
`INSERT INTO "user" (id, name, email, email_verified, created_at, updated_at)
|
|
204
|
+
VALUES ('u-unverified', 'Unverified', 'unverified@lifecycle.test', false, now(), now())`
|
|
205
|
+
);
|
|
206
|
+
await app.stop();
|
|
207
|
+
await expectBootRefusal(
|
|
208
|
+
createTestApp(connectionString, { ...HUB_ENV, EDITION_CHANGE_ALLOWED: 'true' }),
|
|
209
|
+
/refusing the edition flip 'oss' → 'cloud'.*unverified email/
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('flips once the instance is in shape, then refuses the reverse flip even with the flag', async () => {
|
|
214
|
+
const app = await createTestApp(connectionString);
|
|
215
|
+
await app.db.pool.query(`DELETE FROM "user" WHERE id = 'u-unverified'`);
|
|
216
|
+
await app.stop();
|
|
217
|
+
const flipped = await createTestApp(connectionString, { ...HUB_ENV, EDITION_CHANGE_ALLOWED: 'true' });
|
|
218
|
+
const { rows } = await flipped.db.pool.query<{ edition: string }>(
|
|
219
|
+
`SELECT edition FROM instance_settings`
|
|
220
|
+
);
|
|
221
|
+
expect(rows).toEqual([{ edition: 'cloud' }]);
|
|
222
|
+
await flipped.stop();
|
|
223
|
+
await expectBootRefusal(
|
|
224
|
+
createTestApp(connectionString, { EDITION_CHANGE_ALLOWED: 'true' }),
|
|
225
|
+
/refusing the edition flip 'cloud' → 'oss'/
|
|
226
|
+
);
|
|
227
|
+
// …and still stamped cloud.
|
|
228
|
+
const cloud = await createTestApp(connectionString, HUB_ENV);
|
|
229
|
+
const after = await cloud.db.pool.query<{ edition: string }>(`SELECT edition FROM instance_settings`);
|
|
230
|
+
expect(after.rows).toEqual([{ edition: 'cloud' }]);
|
|
231
|
+
await cloud.stop();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
+
import type { StartedPostgreSqlContainer } from '@testcontainers/postgresql';
|
|
3
|
+
import { workspaceMembers } from '@antasphere/chassis-db';
|
|
4
|
+
import {
|
|
5
|
+
createDatabase,
|
|
6
|
+
createTestApp,
|
|
7
|
+
extractCookie,
|
|
8
|
+
readJson,
|
|
9
|
+
startPostgres,
|
|
10
|
+
type TestApp,
|
|
11
|
+
host
|
|
12
|
+
} from './helpers.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Adversarial verifier suite (Stage D, the user-scoped credential core):
|
|
16
|
+
* three cross-tenant / cross-user boundaries the wider workspace-scoping
|
|
17
|
+
* suite proves at MINT time but not at RESOLUTION time. Each is a named
|
|
18
|
+
* attack in the re-architecture's rollout choreography:
|
|
19
|
+
*
|
|
20
|
+
* 1. A key is its CREATOR's credential — the creator-only revoke must not
|
|
21
|
+
* let another user (even a co-owner of the pinned workspace) revoke or
|
|
22
|
+
* probe it; a foreign key answers the SAME 404 as a nonexistent one.
|
|
23
|
+
* 2. "Stale pin after the membership is deactivated": a pinned key whose
|
|
24
|
+
* creator loses their live membership of the pin fails CLOSED with the
|
|
25
|
+
* uniform 401 — never the 403 mismatch, never silently served the pin.
|
|
26
|
+
* 3. Default selection is fail-CLOSED against a non-live default: an
|
|
27
|
+
* `is_default` row that is not an ACTIVE membership is ignored, and
|
|
28
|
+
* selector-less resolution falls back to the oldest ACTIVE membership.
|
|
29
|
+
*
|
|
30
|
+
* Every machine-credential request rotates its forwarded IP so the per-IP
|
|
31
|
+
* key-failure limiter never colours a deliberate resolution miss.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const EVE = { email: 'eve@cred.test', name: 'Eve Owner', password: 'a-long-eve-password-12345' };
|
|
35
|
+
const FRANK = { email: 'frank@cred.test', name: 'Frank Owner', password: 'a-long-frank-password-123' };
|
|
36
|
+
|
|
37
|
+
let container: StartedPostgreSqlContainer;
|
|
38
|
+
let app: TestApp;
|
|
39
|
+
let eveCookie = '';
|
|
40
|
+
let frankCookie = '';
|
|
41
|
+
let eveId = '';
|
|
42
|
+
let frankId = '';
|
|
43
|
+
let wE = ''; // Eve's org, co-owned by Frank (so deactivating Eve never trips the last-owner trigger)
|
|
44
|
+
|
|
45
|
+
let ipCounter = 0;
|
|
46
|
+
const nextIp = () => `10.77.${Math.floor(ipCounter / 250)}.${(ipCounter++ % 250) + 1}`;
|
|
47
|
+
const keyHeaders = (key: string) => ({ authorization: `Bearer ${key}`, 'x-forwarded-for': nextIp() });
|
|
48
|
+
|
|
49
|
+
async function signIn(email: string, password: string): Promise<string> {
|
|
50
|
+
const res = await app.app.request('/api/v1/auth/sign-in/email', {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: { 'content-type': 'application/json' },
|
|
53
|
+
body: JSON.stringify({ email, password })
|
|
54
|
+
});
|
|
55
|
+
expect(res.status).toBe(200);
|
|
56
|
+
return extractCookie(res);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function mintKey(
|
|
60
|
+
cookie: string,
|
|
61
|
+
name: string,
|
|
62
|
+
workspaceId?: string
|
|
63
|
+
): Promise<{ key: string; id: string }> {
|
|
64
|
+
const res = await app.app.request('/api/v1/api-keys', {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: { cookie, 'content-type': 'application/json' },
|
|
67
|
+
body: JSON.stringify({ name, scopes: [host.scopes.read], ...(workspaceId ? { workspaceId } : {}) })
|
|
68
|
+
});
|
|
69
|
+
expect(res.status).toBe(201);
|
|
70
|
+
const body = await readJson(res);
|
|
71
|
+
return { key: body.key, id: body.apiKey.id };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
beforeAll(async () => {
|
|
75
|
+
container = await startPostgres();
|
|
76
|
+
const dbUrl = await createDatabase(container, 'cred_boundaries');
|
|
77
|
+
app = await createTestApp(dbUrl);
|
|
78
|
+
|
|
79
|
+
const setup = await app.app.request('/api/v1/setup', {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: { 'content-type': 'application/json' },
|
|
82
|
+
body: JSON.stringify({
|
|
83
|
+
setupToken: 'integration-test-setup-token',
|
|
84
|
+
instanceName: 'Cred Boundaries',
|
|
85
|
+
owner: EVE
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
expect(setup.status).toBe(201);
|
|
89
|
+
|
|
90
|
+
eveCookie = await signIn(EVE.email, EVE.password);
|
|
91
|
+
eveId = (await readJson(await app.app.request('/api/v1/me', { headers: { cookie: eveCookie } }))).user.id;
|
|
92
|
+
|
|
93
|
+
const frank = await app.auth.api.signUpEmail({
|
|
94
|
+
body: { email: FRANK.email, password: FRANK.password, name: FRANK.name }
|
|
95
|
+
});
|
|
96
|
+
frankId = frank.user.id;
|
|
97
|
+
|
|
98
|
+
// Setup's workspace is Eve's oldest membership (the selector-less default).
|
|
99
|
+
wE = (await readJson(await app.app.request('/api/v1/me', { headers: { cookie: eveCookie } }))).workspace.id;
|
|
100
|
+
// Frank co-owns wE — a live second owner so Eve's membership can be
|
|
101
|
+
// deactivated without the 0009 last-owner trigger firing.
|
|
102
|
+
await app.db.db.insert(workspaceMembers).values({ workspaceId: wE, userId: frankId, role: 'owner' });
|
|
103
|
+
frankCookie = await signIn(FRANK.email, FRANK.password);
|
|
104
|
+
}, 240_000);
|
|
105
|
+
|
|
106
|
+
afterAll(async () => {
|
|
107
|
+
await app?.stop();
|
|
108
|
+
await container?.stop();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('a key is its creator’s credential — revoke is creator-only (attack surface 3)', () => {
|
|
112
|
+
it('a co-owner of the pinned workspace cannot revoke another user’s key (404, and the key stays live)', async () => {
|
|
113
|
+
// Eve mints a key PINNED to wE — so the row carries workspace_id = wE and
|
|
114
|
+
// a (regressed) workspace-scoped revoke WOULD find it. The creator-scoped
|
|
115
|
+
// revoke must not.
|
|
116
|
+
const eveKey = await mintKey(eveCookie, 'eve-pinned-key', wE);
|
|
117
|
+
|
|
118
|
+
// Frank — a co-owner of the SAME workspace — tries to revoke Eve's key.
|
|
119
|
+
const foreignRevoke = await app.app.request(`/api/v1/api-keys/${eveKey.id}`, {
|
|
120
|
+
method: 'DELETE',
|
|
121
|
+
headers: { cookie: frankCookie }
|
|
122
|
+
});
|
|
123
|
+
// Existence is not probeable across users: identical to a nonexistent id.
|
|
124
|
+
expect(foreignRevoke.status).toBe(404);
|
|
125
|
+
expect((await readJson(foreignRevoke)).error.code).toBe('not_found');
|
|
126
|
+
|
|
127
|
+
// And it truly did NOT revoke: Eve's key still resolves.
|
|
128
|
+
const stillLive = await app.app.request('/api/v1/me', { headers: keyHeaders(eveKey.key) });
|
|
129
|
+
expect(stillLive.status).toBe(200);
|
|
130
|
+
|
|
131
|
+
// Sanity: the CREATOR revokes it, and only then does it die.
|
|
132
|
+
const ownRevoke = await app.app.request(`/api/v1/api-keys/${eveKey.id}`, {
|
|
133
|
+
method: 'DELETE',
|
|
134
|
+
headers: { cookie: eveCookie }
|
|
135
|
+
});
|
|
136
|
+
expect(ownRevoke.status).toBe(200);
|
|
137
|
+
const dead = await app.app.request('/api/v1/me', { headers: keyHeaders(eveKey.key) });
|
|
138
|
+
expect(dead.status).toBe(401);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('a stale pin fails closed once the creator’s membership is deactivated (attack surface 1)', () => {
|
|
143
|
+
it('the pinned key answers the uniform 401 — never the 403 mismatch, never served the pin', async () => {
|
|
144
|
+
const pinned = await mintKey(eveCookie, 'eve-stale-pin', wE);
|
|
145
|
+
// Works while Eve is a live member of the pin.
|
|
146
|
+
expect((await app.app.request('/api/v1/me', { headers: keyHeaders(pinned.key) })).status).toBe(200);
|
|
147
|
+
|
|
148
|
+
// Deactivate Eve's membership of the pinned workspace (Frank keeps wE alive).
|
|
149
|
+
await app.db.pool.query(
|
|
150
|
+
`UPDATE workspace_members SET is_active = false WHERE user_id = $1 AND workspace_id = $2`,
|
|
151
|
+
[eveId, wE]
|
|
152
|
+
);
|
|
153
|
+
try {
|
|
154
|
+
// No X-Workspace-Id header: the pin resolves to no live membership →
|
|
155
|
+
// the uniform 401 (invalid_api_key), indistinguishable from any other
|
|
156
|
+
// resolution miss. A regression that trusted the pin without the live
|
|
157
|
+
// isActive check would answer 200 here.
|
|
158
|
+
const res = await app.app.request('/api/v1/me', { headers: keyHeaders(pinned.key) });
|
|
159
|
+
expect(res.status).toBe(401);
|
|
160
|
+
expect((await readJson(res)).error.code).toBe('invalid_api_key');
|
|
161
|
+
} finally {
|
|
162
|
+
await app.db.pool.query(
|
|
163
|
+
`UPDATE workspace_members SET is_active = true WHERE user_id = $1 AND workspace_id = $2`,
|
|
164
|
+
[eveId, wE]
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
// Reactivated: the very same key resolves again (the row, not the token,
|
|
168
|
+
// is the authorization).
|
|
169
|
+
expect((await app.app.request('/api/v1/me', { headers: keyHeaders(pinned.key) })).status).toBe(200);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('default selection is fail-closed against a non-live default (attack surface 2)', () => {
|
|
174
|
+
it('an is_default flag on an INACTIVE membership is ignored; resolution falls back to the oldest ACTIVE', async () => {
|
|
175
|
+
// A second org for Eve; make it her DEFAULT but mark the membership
|
|
176
|
+
// INACTIVE. Frank co-owns it so deactivating Eve never trips the 0009
|
|
177
|
+
// last-owner trigger (this test is about default selection, not lifecycle).
|
|
178
|
+
const wE2 = (await app.registry.workspaces.create('Eve Org Two', eveId)).workspaceId;
|
|
179
|
+
await app.db.db.insert(workspaceMembers).values({ workspaceId: wE2, userId: frankId, role: 'owner' });
|
|
180
|
+
await app.db.pool.query(
|
|
181
|
+
`UPDATE workspace_members SET is_default = true, is_active = false WHERE user_id = $1 AND workspace_id = $2`,
|
|
182
|
+
[eveId, wE2]
|
|
183
|
+
);
|
|
184
|
+
try {
|
|
185
|
+
// Selector-less resolution must NOT land on the dead default; it falls
|
|
186
|
+
// back to the oldest ACTIVE membership (wE, the setup workspace).
|
|
187
|
+
const me = await readJson(await app.app.request('/api/v1/me', { headers: { cookie: eveCookie } }));
|
|
188
|
+
expect(me.activeWorkspaceId).toBe(wE);
|
|
189
|
+
// The inactive workspace is not even enumerated (the /me isActive filter).
|
|
190
|
+
expect(me.workspaces.map((w: { id: string }) => w.id)).not.toContain(wE2);
|
|
191
|
+
} finally {
|
|
192
|
+
await app.db.pool.query(`UPDATE workspace_members SET is_default = false WHERE user_id = $1`, [eveId]);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|