@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/LICENSE
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
The Antasphere chassis
|
|
4
|
+
Copyright (c) 2026 Antasphere
|
|
5
|
+
|
|
6
|
+
The Antasphere chassis is made available by Antasphere, the licensor, under the "Sustainable Use License" as
|
|
7
|
+
defined below. All third party components incorporated into the Antasphere chassis are licensed under the
|
|
8
|
+
original license provided by the owner of the applicable component.
|
|
9
|
+
|
|
10
|
+
## Sustainable Use License
|
|
11
|
+
|
|
12
|
+
Version 1.0
|
|
13
|
+
|
|
14
|
+
### Acceptance
|
|
15
|
+
|
|
16
|
+
By using the software, you agree to all of the terms and conditions below.
|
|
17
|
+
|
|
18
|
+
### Copyright License
|
|
19
|
+
|
|
20
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license
|
|
21
|
+
to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject
|
|
22
|
+
to the limitations below.
|
|
23
|
+
|
|
24
|
+
### Limitations
|
|
25
|
+
|
|
26
|
+
You may use or modify the software only for your own internal business purposes or for non-commercial or
|
|
27
|
+
personal use. You may distribute the software or provide it to others only if you do so free of charge for
|
|
28
|
+
non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of
|
|
29
|
+
the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
|
|
30
|
+
|
|
31
|
+
### Patents
|
|
32
|
+
|
|
33
|
+
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to
|
|
34
|
+
license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case
|
|
35
|
+
subject to the limitations and conditions in this license. This license does not cover any patent claims that
|
|
36
|
+
you cause to be infringed by modifications or additions to the software. If you or your company make any
|
|
37
|
+
written claim that the software infringes or contributes to infringement of any patent, your patent license
|
|
38
|
+
for the software granted under these terms ends immediately. If your company makes such a claim, your patent
|
|
39
|
+
license ends immediately for work on behalf of your company.
|
|
40
|
+
|
|
41
|
+
### Notices
|
|
42
|
+
|
|
43
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these
|
|
44
|
+
terms. If you modify the software, you must include in any modified copies of the software a prominent notice
|
|
45
|
+
stating that you have modified the software.
|
|
46
|
+
|
|
47
|
+
### No Other Rights
|
|
48
|
+
|
|
49
|
+
These terms do not imply any licenses other than those expressly granted in these terms.
|
|
50
|
+
|
|
51
|
+
### Termination
|
|
52
|
+
|
|
53
|
+
If you use the software in violation of these terms, such use is not licensed, and your license will
|
|
54
|
+
automatically terminate. If the licensor provides you with a notice of your violation, and you cease all
|
|
55
|
+
violation of this license no later than 30 days after you receive that notice, your license will be reinstated
|
|
56
|
+
retroactively. However, if you violate these terms after such reinstatement, any additional violation of these
|
|
57
|
+
terms will cause your license to terminate automatically and permanently.
|
|
58
|
+
|
|
59
|
+
### No Liability
|
|
60
|
+
|
|
61
|
+
As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will
|
|
62
|
+
not be liable to you for any damages arising out of these terms or the use or nature of the software, under
|
|
63
|
+
any kind of legal claim.
|
|
64
|
+
|
|
65
|
+
### Definitions
|
|
66
|
+
|
|
67
|
+
The “licensor” is the entity offering these terms.
|
|
68
|
+
|
|
69
|
+
The “software” is the software the licensor makes available under these terms, including any portion of it.
|
|
70
|
+
|
|
71
|
+
“You” refers to the individual or entity agreeing to these terms.
|
|
72
|
+
|
|
73
|
+
“Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus
|
|
74
|
+
all organizations that have control over, are under the control of, or are under common control with that
|
|
75
|
+
organization. Control means ownership of substantially all the assets of an entity, or the power to direct its
|
|
76
|
+
management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
77
|
+
|
|
78
|
+
“Your license” is the license granted to you for the software under these terms.
|
|
79
|
+
|
|
80
|
+
“Use” means anything you do with the software requiring your license.
|
|
81
|
+
|
|
82
|
+
“Trademark” means trademarks, service marks, and similar rights.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { type Db } from '@antasphere/chassis-db';
|
|
2
|
+
import type { AuditService } from '../audit/service.js';
|
|
3
|
+
import type { Logger } from '../logger.js';
|
|
4
|
+
import type { ErasureLog } from './erasure-log.js';
|
|
5
|
+
/**
|
|
6
|
+
* Account deletion (GDPR erasure), shared by both delete surfaces: the
|
|
7
|
+
* self-service Better Auth `/delete-user` route (via the boot-wired
|
|
8
|
+
* before/after hooks) and the admin `DELETE /members/{id}` endpoint.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately NO storage dependency: files are WORKSPACE data, not the
|
|
11
|
+
* uploader's personal data — they survive the delete with `created_by`
|
|
12
|
+
* nulled by the FK (migration 0008, ADR 006). Blobs are never touched here.
|
|
13
|
+
*
|
|
14
|
+
* Multi-workspace (ADR 014): a user owning N workspaces has N last-owner
|
|
15
|
+
* obligations — the guard runs for EVERY workspace where they are an
|
|
16
|
+
* active owner, with the per-workspace locks acquired in deterministic
|
|
17
|
+
* order (sorted workspace id) so two concurrent deletes of co-owners can
|
|
18
|
+
* never deadlock. The completion audit row lands in every workspace the
|
|
19
|
+
* user belonged to.
|
|
20
|
+
*
|
|
21
|
+
* Projection exemption (D11, the cloud-binding plan): the guard
|
|
22
|
+
* applies ONLY to workspaces this instance owns (centralAccountId IS
|
|
23
|
+
* NULL). A projected (hub-origin) workspace asserts ownership hub-side —
|
|
24
|
+
* its local membership rows are a re-syncable projection, so a
|
|
25
|
+
* zero-local-owner state is legal there and the guard (app layer AND the
|
|
26
|
+
* 0009 trigger, migration 0019) stands aside. Structured now, inert until
|
|
27
|
+
* the cloud edition creates the first projection (Phase 3).
|
|
28
|
+
*
|
|
29
|
+
* Last-owner race hardening (ADR 006, M9): a zero-active-owner workspace is
|
|
30
|
+
* unrecoverable (setup is one-shot), so the guard is enforced in two layers:
|
|
31
|
+
*
|
|
32
|
+
* 1. A `BEFORE DELETE OR UPDATE` trigger on workspace_members (migration
|
|
33
|
+
* 0009) raises SQLSTATE {@link LAST_OWNER_SQLSTATE} whenever an operation
|
|
34
|
+
* would drop the workspace's ACTIVE owners to zero — serialized inside
|
|
35
|
+
* the trigger by a per-workspace `pg_advisory_xact_lock`, so it holds
|
|
36
|
+
* under ANY concurrency and on any code path. This is the guarantee.
|
|
37
|
+
* 2. A per-workspace session-scoped advisory lock (dedicated `pg.Client`,
|
|
38
|
+
* mirroring the migration-lock pattern) serializes the HTTP surfaces
|
|
39
|
+
* around their guard re-check, so the LOSER of a race is rejected at the
|
|
40
|
+
* guard with a clean `LastOwnerError` (→ 400) instead of tripping the
|
|
41
|
+
* trigger mid-cascade (→ 500).
|
|
42
|
+
*/
|
|
43
|
+
/** Deleting this account would leave the workspace without an active owner. */
|
|
44
|
+
export declare class LastOwnerError extends Error {
|
|
45
|
+
constructor();
|
|
46
|
+
}
|
|
47
|
+
/** SQLSTATE raised by the workspace_members last-owner trigger (migration 0009). */
|
|
48
|
+
export declare const LAST_OWNER_SQLSTATE = "P0409";
|
|
49
|
+
/**
|
|
50
|
+
* True when `cause` (or anything on its `cause` chain — drizzle wraps pg's
|
|
51
|
+
* DatabaseError) is the last-owner trigger rejection.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isLastOwnerDbError(cause: unknown): boolean;
|
|
54
|
+
/** True when the workspace keeps ≥1 ACTIVE owner besides excludeUserId. */
|
|
55
|
+
export declare function hasOtherActiveOwner(db: Db, workspaceId: string, excludeUserId: string): Promise<boolean>;
|
|
56
|
+
export declare class AccountDeletionService {
|
|
57
|
+
private readonly db;
|
|
58
|
+
private readonly audit;
|
|
59
|
+
private readonly logger;
|
|
60
|
+
/** Dedicated advisory-lock connections (mirrors packages/chassis-db migrate.ts). */
|
|
61
|
+
private readonly connectionString;
|
|
62
|
+
/** The append-only erasure tombstone (OPS-3): every completed erasure lands a line. */
|
|
63
|
+
private readonly erasureLog?;
|
|
64
|
+
/**
|
|
65
|
+
* before/after stash: beforeUserDelete runs with the user row still
|
|
66
|
+
* present (memberships + email are readable); afterUserDelete runs after
|
|
67
|
+
* the FK cascade, when neither is — so the system-actor audit rows pop
|
|
68
|
+
* their context from here. In-process by design: both hooks run in the
|
|
69
|
+
* same request on the same replica.
|
|
70
|
+
*/
|
|
71
|
+
private readonly stash;
|
|
72
|
+
/** Locks parked across Better Auth's cascade (beforeUserDelete → afterUserDelete). */
|
|
73
|
+
private readonly heldLocks;
|
|
74
|
+
constructor(db: Db, audit: AuditService, logger: Logger,
|
|
75
|
+
/** Dedicated advisory-lock connections (mirrors packages/chassis-db migrate.ts). */
|
|
76
|
+
connectionString: string,
|
|
77
|
+
/** The append-only erasure tombstone (OPS-3): every completed erasure lands a line. */
|
|
78
|
+
erasureLog?: ErasureLog | undefined);
|
|
79
|
+
/**
|
|
80
|
+
* Throws LastOwnerError when the user is the last ACTIVE owner of ANY of
|
|
81
|
+
* their non-projected workspaces (ADR 014: N owned workspaces = N
|
|
82
|
+
* obligations; projected ones are exempt, D11). Unlocked fast-path check —
|
|
83
|
+
* the race-free enforcement is withLastOwnerGuard + the 0009/0019 trigger.
|
|
84
|
+
*/
|
|
85
|
+
assertDeletable(userId: string): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Serialize an owner-removing operation and enforce the last-owner rule
|
|
88
|
+
* race-free: the per-workspace advisory lock makes the guard re-check see
|
|
89
|
+
* every previously committed removal (the loser of a race rejects with
|
|
90
|
+
* LastOwnerError → 400), and the migration-0009 trigger — surfaced here as
|
|
91
|
+
* LastOwnerError too — backstops anything that slips past. The lock is
|
|
92
|
+
* released on EVERY path (finally). Projected workspaces skip the guard
|
|
93
|
+
* entirely (D11): ownership is asserted hub-side and the trigger stands
|
|
94
|
+
* aside there too (migration 0019).
|
|
95
|
+
*/
|
|
96
|
+
withLastOwnerGuard<T>(workspaceId: string, excludeUserId: string, op: () => Promise<T>): Promise<T>;
|
|
97
|
+
/**
|
|
98
|
+
* Guard + stash. Runs while the user row still exists. For EVERY
|
|
99
|
+
* non-projected workspace where the user is an ACTIVE OWNER the guard
|
|
100
|
+
* re-check runs under that workspace's lock — locks acquired in
|
|
101
|
+
* deterministic order (sorted workspace id) so concurrent deletes never
|
|
102
|
+
* deadlock — and the locks are parked across Better Auth's cascade
|
|
103
|
+
* (released by afterUserDelete, or by the watchdog if the cascade dies in
|
|
104
|
+
* between). Of two concurrent last-owner self-deletes, the loser blocks
|
|
105
|
+
* here until the winner's cascade commits, re-checks, and rejects with a
|
|
106
|
+
* clean LastOwnerError.
|
|
107
|
+
*/
|
|
108
|
+
beforeUserDelete(userId: string): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Run an erasure under EVERY last-owner guard the user is subject to, with
|
|
111
|
+
* nothing touched when any guard refuses (PRDCT-1809). The boot-time
|
|
112
|
+
* tombstone replay uses this: Better Auth's cascade deletes the account
|
|
113
|
+
* rows BEFORE the user row, so a delete the 0009 trigger refuses mid-way
|
|
114
|
+
* leaves a half-erased owner (no credential, PII intact, membership
|
|
115
|
+
* intact). The locks are acquired in sorted order (as beforeUserDelete)
|
|
116
|
+
* and released on every path; a refusal surfaces as LastOwnerError before
|
|
117
|
+
* `op` runs, and a trigger refusal inside `op` is mapped to the same.
|
|
118
|
+
*/
|
|
119
|
+
withAllLastOwnerGuards<T>(userId: string, op: () => Promise<T>): Promise<T>;
|
|
120
|
+
/**
|
|
121
|
+
* Land the erasure tombstone (OPS-3) for a deletion that did NOT run
|
|
122
|
+
* through Better Auth's deleteUser hooks — the admin DELETE /members/{id}
|
|
123
|
+
* cascade calls the internal adapter directly, so afterUserDelete never
|
|
124
|
+
* fires there. Every GDPR surface must end here or in afterUserDelete.
|
|
125
|
+
*/
|
|
126
|
+
recordErasure(user: {
|
|
127
|
+
id: string;
|
|
128
|
+
email: string;
|
|
129
|
+
}): Promise<void>;
|
|
130
|
+
/** Pop the stash and record the system-actor completion rows (FK-safe: the user is gone). */
|
|
131
|
+
afterUserDelete(user: {
|
|
132
|
+
id: string;
|
|
133
|
+
email: string;
|
|
134
|
+
}): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Acquire the per-workspace lock and run the guard re-check for EVERY
|
|
137
|
+
* non-projected workspace where the user is an active owner, in sorted
|
|
138
|
+
* order (deterministic → no deadlock between concurrent deletes). On a
|
|
139
|
+
* refusal every lock taken so far is released and LastOwnerError is
|
|
140
|
+
* thrown; on success the caller owns the locks.
|
|
141
|
+
*/
|
|
142
|
+
private acquireOwnerLocks;
|
|
143
|
+
/**
|
|
144
|
+
* Session-scoped pg_advisory_lock on a dedicated client — never the pool:
|
|
145
|
+
* a session lock parked on a pooled connection would poison the pool.
|
|
146
|
+
*/
|
|
147
|
+
private acquireOwnerLock;
|
|
148
|
+
/** Idempotent; closing the client guarantees the session lock dies with it. */
|
|
149
|
+
private releaseOwnerLock;
|
|
150
|
+
/** Park the locks across the cascade, each watchdogged against a hook-gap leak. */
|
|
151
|
+
private parkLocks;
|
|
152
|
+
/** Every membership row the user holds, active or not. */
|
|
153
|
+
private membershipsOf;
|
|
154
|
+
/**
|
|
155
|
+
* Workspaces where the user is an ACTIVE OWNER and the last-owner guard
|
|
156
|
+
* applies — i.e. NON-PROJECTED ones (centralAccountId IS NULL, D11).
|
|
157
|
+
* Sorted for deterministic lock ordering.
|
|
158
|
+
*/
|
|
159
|
+
private ownedGuardedWorkspaceIds;
|
|
160
|
+
/** True when the workspace is a hub projection (ownership asserted hub-side, D11). */
|
|
161
|
+
private isProjectedWorkspace;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=deletion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deletion.d.ts","sourceRoot":"","sources":["../../src/accounts/deletion.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmD,KAAK,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,+EAA+E;AAC/E,qBAAa,cAAe,SAAQ,KAAK;;CAKxC;AAED,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK1D;AA0BD,2EAA2E;AAC3E,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC,CAclB;AAED,qBAAa,sBAAsB;IAc/B,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAnB9B;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgE;IAEtF,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;gBAGzC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM;IAC/B,oFAAoF;IACnE,gBAAgB,EAAE,MAAM;IACzC,uFAAuF;IACtE,UAAU,CAAC,EAAE,UAAU,YAAA;IAG1C;;;;;OAKG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpD;;;;;;;;;OASG;IACG,kBAAkB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBzG;;;;;;;;;;OAUG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBrD;;;;;;;;;OASG;IACG,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYjF;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,6FAA6F;IACvF,eAAe,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzE;;;;;;OAMG;YACW,iBAAiB;IAgB/B;;;OAGG;YACW,gBAAgB;IAa9B,+EAA+E;YACjE,gBAAgB;IAe9B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAmBjB,0DAA0D;YAC5C,aAAa;IAa3B;;;;OAIG;YACW,wBAAwB;IAgBtC,sFAAsF;YACxE,oBAAoB;CAQnC"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import pg from 'pg';
|
|
2
|
+
import { and, eq, isNull, ne } from 'drizzle-orm';
|
|
3
|
+
import { user as userTable, workspaceMembers, workspaces } from '@antasphere/chassis-db';
|
|
4
|
+
/**
|
|
5
|
+
* Account deletion (GDPR erasure), shared by both delete surfaces: the
|
|
6
|
+
* self-service Better Auth `/delete-user` route (via the boot-wired
|
|
7
|
+
* before/after hooks) and the admin `DELETE /members/{id}` endpoint.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately NO storage dependency: files are WORKSPACE data, not the
|
|
10
|
+
* uploader's personal data — they survive the delete with `created_by`
|
|
11
|
+
* nulled by the FK (migration 0008, ADR 006). Blobs are never touched here.
|
|
12
|
+
*
|
|
13
|
+
* Multi-workspace (ADR 014): a user owning N workspaces has N last-owner
|
|
14
|
+
* obligations — the guard runs for EVERY workspace where they are an
|
|
15
|
+
* active owner, with the per-workspace locks acquired in deterministic
|
|
16
|
+
* order (sorted workspace id) so two concurrent deletes of co-owners can
|
|
17
|
+
* never deadlock. The completion audit row lands in every workspace the
|
|
18
|
+
* user belonged to.
|
|
19
|
+
*
|
|
20
|
+
* Projection exemption (D11, the cloud-binding plan): the guard
|
|
21
|
+
* applies ONLY to workspaces this instance owns (centralAccountId IS
|
|
22
|
+
* NULL). A projected (hub-origin) workspace asserts ownership hub-side —
|
|
23
|
+
* its local membership rows are a re-syncable projection, so a
|
|
24
|
+
* zero-local-owner state is legal there and the guard (app layer AND the
|
|
25
|
+
* 0009 trigger, migration 0019) stands aside. Structured now, inert until
|
|
26
|
+
* the cloud edition creates the first projection (Phase 3).
|
|
27
|
+
*
|
|
28
|
+
* Last-owner race hardening (ADR 006, M9): a zero-active-owner workspace is
|
|
29
|
+
* unrecoverable (setup is one-shot), so the guard is enforced in two layers:
|
|
30
|
+
*
|
|
31
|
+
* 1. A `BEFORE DELETE OR UPDATE` trigger on workspace_members (migration
|
|
32
|
+
* 0009) raises SQLSTATE {@link LAST_OWNER_SQLSTATE} whenever an operation
|
|
33
|
+
* would drop the workspace's ACTIVE owners to zero — serialized inside
|
|
34
|
+
* the trigger by a per-workspace `pg_advisory_xact_lock`, so it holds
|
|
35
|
+
* under ANY concurrency and on any code path. This is the guarantee.
|
|
36
|
+
* 2. A per-workspace session-scoped advisory lock (dedicated `pg.Client`,
|
|
37
|
+
* mirroring the migration-lock pattern) serializes the HTTP surfaces
|
|
38
|
+
* around their guard re-check, so the LOSER of a race is rejected at the
|
|
39
|
+
* guard with a clean `LastOwnerError` (→ 400) instead of tripping the
|
|
40
|
+
* trigger mid-cascade (→ 500).
|
|
41
|
+
*/
|
|
42
|
+
/** Deleting this account would leave the workspace without an active owner. */
|
|
43
|
+
export class LastOwnerError extends Error {
|
|
44
|
+
constructor() {
|
|
45
|
+
super('The workspace must keep at least one active owner');
|
|
46
|
+
this.name = 'LastOwnerError';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** SQLSTATE raised by the workspace_members last-owner trigger (migration 0009). */
|
|
50
|
+
export const LAST_OWNER_SQLSTATE = 'P0409';
|
|
51
|
+
/**
|
|
52
|
+
* True when `cause` (or anything on its `cause` chain — drizzle wraps pg's
|
|
53
|
+
* DatabaseError) is the last-owner trigger rejection.
|
|
54
|
+
*/
|
|
55
|
+
export function isLastOwnerDbError(cause) {
|
|
56
|
+
for (let err = cause; err instanceof Error; err = err.cause) {
|
|
57
|
+
if (err.code === LAST_OWNER_SQLSTATE)
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Advisory-lock namespace for serializing owner-removing operations
|
|
64
|
+
* (two-int form: classid 7432003, objid = hashtext(workspace id)). Distinct
|
|
65
|
+
* from the migration lock (7432001) and the trigger's own xact lock
|
|
66
|
+
* (7432002) — the session lock is held ACROSS the cascade while the trigger
|
|
67
|
+
* lock is taken INSIDE it, so sharing a key would self-deadlock.
|
|
68
|
+
*/
|
|
69
|
+
const OWNER_GUARD_LOCK_KEY = 7_432_003;
|
|
70
|
+
/**
|
|
71
|
+
* The self-service path parks the lock between Better Auth's before/after
|
|
72
|
+
* hooks; if the cascade dies in between, afterDelete never runs. The
|
|
73
|
+
* watchdog then cuts the dedicated connection (a session lock dies with its
|
|
74
|
+
* session), so a leaked lock can stall owner removals for at most this long.
|
|
75
|
+
*/
|
|
76
|
+
const LOCK_WATCHDOG_MS = 60_000;
|
|
77
|
+
/** True when the workspace keeps ≥1 ACTIVE owner besides excludeUserId. */
|
|
78
|
+
export async function hasOtherActiveOwner(db, workspaceId, excludeUserId) {
|
|
79
|
+
const [row] = await db
|
|
80
|
+
.select({ id: workspaceMembers.id })
|
|
81
|
+
.from(workspaceMembers)
|
|
82
|
+
.where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.role, 'owner'), eq(workspaceMembers.isActive, true), ne(workspaceMembers.userId, excludeUserId)))
|
|
83
|
+
.limit(1);
|
|
84
|
+
return Boolean(row);
|
|
85
|
+
}
|
|
86
|
+
export class AccountDeletionService {
|
|
87
|
+
db;
|
|
88
|
+
audit;
|
|
89
|
+
logger;
|
|
90
|
+
connectionString;
|
|
91
|
+
erasureLog;
|
|
92
|
+
/**
|
|
93
|
+
* before/after stash: beforeUserDelete runs with the user row still
|
|
94
|
+
* present (memberships + email are readable); afterUserDelete runs after
|
|
95
|
+
* the FK cascade, when neither is — so the system-actor audit rows pop
|
|
96
|
+
* their context from here. In-process by design: both hooks run in the
|
|
97
|
+
* same request on the same replica.
|
|
98
|
+
*/
|
|
99
|
+
stash = new Map();
|
|
100
|
+
/** Locks parked across Better Auth's cascade (beforeUserDelete → afterUserDelete). */
|
|
101
|
+
heldLocks = new Map();
|
|
102
|
+
constructor(db, audit, logger,
|
|
103
|
+
/** Dedicated advisory-lock connections (mirrors packages/chassis-db migrate.ts). */
|
|
104
|
+
connectionString,
|
|
105
|
+
/** The append-only erasure tombstone (OPS-3): every completed erasure lands a line. */
|
|
106
|
+
erasureLog) {
|
|
107
|
+
this.db = db;
|
|
108
|
+
this.audit = audit;
|
|
109
|
+
this.logger = logger;
|
|
110
|
+
this.connectionString = connectionString;
|
|
111
|
+
this.erasureLog = erasureLog;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Throws LastOwnerError when the user is the last ACTIVE owner of ANY of
|
|
115
|
+
* their non-projected workspaces (ADR 014: N owned workspaces = N
|
|
116
|
+
* obligations; projected ones are exempt, D11). Unlocked fast-path check —
|
|
117
|
+
* the race-free enforcement is withLastOwnerGuard + the 0009/0019 trigger.
|
|
118
|
+
*/
|
|
119
|
+
async assertDeletable(userId) {
|
|
120
|
+
for (const workspaceId of await this.ownedGuardedWorkspaceIds(userId)) {
|
|
121
|
+
if (!(await hasOtherActiveOwner(this.db, workspaceId, userId))) {
|
|
122
|
+
throw new LastOwnerError();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Serialize an owner-removing operation and enforce the last-owner rule
|
|
128
|
+
* race-free: the per-workspace advisory lock makes the guard re-check see
|
|
129
|
+
* every previously committed removal (the loser of a race rejects with
|
|
130
|
+
* LastOwnerError → 400), and the migration-0009 trigger — surfaced here as
|
|
131
|
+
* LastOwnerError too — backstops anything that slips past. The lock is
|
|
132
|
+
* released on EVERY path (finally). Projected workspaces skip the guard
|
|
133
|
+
* entirely (D11): ownership is asserted hub-side and the trigger stands
|
|
134
|
+
* aside there too (migration 0019).
|
|
135
|
+
*/
|
|
136
|
+
async withLastOwnerGuard(workspaceId, excludeUserId, op) {
|
|
137
|
+
if (await this.isProjectedWorkspace(workspaceId)) {
|
|
138
|
+
return op();
|
|
139
|
+
}
|
|
140
|
+
const lock = await this.acquireOwnerLock(workspaceId);
|
|
141
|
+
try {
|
|
142
|
+
if (!(await hasOtherActiveOwner(this.db, workspaceId, excludeUserId))) {
|
|
143
|
+
throw new LastOwnerError();
|
|
144
|
+
}
|
|
145
|
+
return await op();
|
|
146
|
+
}
|
|
147
|
+
catch (cause) {
|
|
148
|
+
if (isLastOwnerDbError(cause))
|
|
149
|
+
throw new LastOwnerError();
|
|
150
|
+
throw cause;
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
await this.releaseOwnerLock(lock);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Guard + stash. Runs while the user row still exists. For EVERY
|
|
158
|
+
* non-projected workspace where the user is an ACTIVE OWNER the guard
|
|
159
|
+
* re-check runs under that workspace's lock — locks acquired in
|
|
160
|
+
* deterministic order (sorted workspace id) so concurrent deletes never
|
|
161
|
+
* deadlock — and the locks are parked across Better Auth's cascade
|
|
162
|
+
* (released by afterUserDelete, or by the watchdog if the cascade dies in
|
|
163
|
+
* between). Of two concurrent last-owner self-deletes, the loser blocks
|
|
164
|
+
* here until the winner's cascade commits, re-checks, and rejects with a
|
|
165
|
+
* clean LastOwnerError.
|
|
166
|
+
*/
|
|
167
|
+
async beforeUserDelete(userId) {
|
|
168
|
+
const memberships = await this.membershipsOf(userId);
|
|
169
|
+
if (memberships.length === 0)
|
|
170
|
+
return; // no workspace to guard or audit against
|
|
171
|
+
const locks = await this.acquireOwnerLocks(userId);
|
|
172
|
+
if (locks.length > 0)
|
|
173
|
+
this.parkLocks(userId, locks);
|
|
174
|
+
const [u] = await this.db
|
|
175
|
+
.select({ email: userTable.email })
|
|
176
|
+
.from(userTable)
|
|
177
|
+
.where(eq(userTable.id, userId))
|
|
178
|
+
.limit(1);
|
|
179
|
+
this.stash.set(userId, {
|
|
180
|
+
workspaceIds: memberships.map((m) => m.workspaceId),
|
|
181
|
+
email: u?.email ?? ''
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Run an erasure under EVERY last-owner guard the user is subject to, with
|
|
186
|
+
* nothing touched when any guard refuses (PRDCT-1809). The boot-time
|
|
187
|
+
* tombstone replay uses this: Better Auth's cascade deletes the account
|
|
188
|
+
* rows BEFORE the user row, so a delete the 0009 trigger refuses mid-way
|
|
189
|
+
* leaves a half-erased owner (no credential, PII intact, membership
|
|
190
|
+
* intact). The locks are acquired in sorted order (as beforeUserDelete)
|
|
191
|
+
* and released on every path; a refusal surfaces as LastOwnerError before
|
|
192
|
+
* `op` runs, and a trigger refusal inside `op` is mapped to the same.
|
|
193
|
+
*/
|
|
194
|
+
async withAllLastOwnerGuards(userId, op) {
|
|
195
|
+
const locks = await this.acquireOwnerLocks(userId);
|
|
196
|
+
try {
|
|
197
|
+
return await op();
|
|
198
|
+
}
|
|
199
|
+
catch (cause) {
|
|
200
|
+
if (isLastOwnerDbError(cause))
|
|
201
|
+
throw new LastOwnerError();
|
|
202
|
+
throw cause;
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
for (const lock of locks)
|
|
206
|
+
await this.releaseOwnerLock(lock);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Land the erasure tombstone (OPS-3) for a deletion that did NOT run
|
|
211
|
+
* through Better Auth's deleteUser hooks — the admin DELETE /members/{id}
|
|
212
|
+
* cascade calls the internal adapter directly, so afterUserDelete never
|
|
213
|
+
* fires there. Every GDPR surface must end here or in afterUserDelete.
|
|
214
|
+
*/
|
|
215
|
+
async recordErasure(user) {
|
|
216
|
+
await this.erasureLog?.append(user);
|
|
217
|
+
}
|
|
218
|
+
/** Pop the stash and record the system-actor completion rows (FK-safe: the user is gone). */
|
|
219
|
+
async afterUserDelete(user) {
|
|
220
|
+
const locks = this.heldLocks.get(user.id);
|
|
221
|
+
if (locks) {
|
|
222
|
+
this.heldLocks.delete(user.id);
|
|
223
|
+
for (const lock of locks)
|
|
224
|
+
await this.releaseOwnerLock(lock);
|
|
225
|
+
}
|
|
226
|
+
// The tombstone is written for EVERY completed erasure, stashed context
|
|
227
|
+
// or not: the audit rows below are what a restore rolls back; this line
|
|
228
|
+
// is what makes the erasure hold across one (OPS-3).
|
|
229
|
+
await this.erasureLog?.append(user);
|
|
230
|
+
const stashed = this.stash.get(user.id);
|
|
231
|
+
this.stash.delete(user.id);
|
|
232
|
+
if (!stashed) {
|
|
233
|
+
this.logger.warn({ userId: user.id }, 'account delete completed without a stashed context');
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
// One row per workspace the user belonged to: every workspace's audit
|
|
237
|
+
// trail records that its member's account was erased (ADR 014).
|
|
238
|
+
for (const workspaceId of stashed.workspaceIds) {
|
|
239
|
+
await this.audit.write({
|
|
240
|
+
workspaceId,
|
|
241
|
+
principal: null, // → actorVia 'system'
|
|
242
|
+
action: 'user.account_delete',
|
|
243
|
+
resourceType: 'user',
|
|
244
|
+
resourceId: user.id,
|
|
245
|
+
metadata: { deletedUserId: user.id, email: stashed.email || user.email }
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Acquire the per-workspace lock and run the guard re-check for EVERY
|
|
251
|
+
* non-projected workspace where the user is an active owner, in sorted
|
|
252
|
+
* order (deterministic → no deadlock between concurrent deletes). On a
|
|
253
|
+
* refusal every lock taken so far is released and LastOwnerError is
|
|
254
|
+
* thrown; on success the caller owns the locks.
|
|
255
|
+
*/
|
|
256
|
+
async acquireOwnerLocks(userId) {
|
|
257
|
+
const locks = [];
|
|
258
|
+
try {
|
|
259
|
+
for (const workspaceId of await this.ownedGuardedWorkspaceIds(userId)) {
|
|
260
|
+
locks.push(await this.acquireOwnerLock(workspaceId));
|
|
261
|
+
if (!(await hasOtherActiveOwner(this.db, workspaceId, userId))) {
|
|
262
|
+
throw new LastOwnerError();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return locks;
|
|
266
|
+
}
|
|
267
|
+
catch (cause) {
|
|
268
|
+
for (const lock of locks)
|
|
269
|
+
await this.releaseOwnerLock(lock);
|
|
270
|
+
throw cause;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Session-scoped pg_advisory_lock on a dedicated client — never the pool:
|
|
275
|
+
* a session lock parked on a pooled connection would poison the pool.
|
|
276
|
+
*/
|
|
277
|
+
async acquireOwnerLock(workspaceId) {
|
|
278
|
+
const client = new pg.Client({ connectionString: this.connectionString });
|
|
279
|
+
await client.connect();
|
|
280
|
+
const lock = { client, workspaceId, released: false };
|
|
281
|
+
try {
|
|
282
|
+
await client.query('SELECT pg_advisory_lock($1, hashtext($2))', [OWNER_GUARD_LOCK_KEY, workspaceId]);
|
|
283
|
+
}
|
|
284
|
+
catch (cause) {
|
|
285
|
+
await this.releaseOwnerLock(lock);
|
|
286
|
+
throw cause;
|
|
287
|
+
}
|
|
288
|
+
return lock;
|
|
289
|
+
}
|
|
290
|
+
/** Idempotent; closing the client guarantees the session lock dies with it. */
|
|
291
|
+
async releaseOwnerLock(lock) {
|
|
292
|
+
if (lock.released)
|
|
293
|
+
return;
|
|
294
|
+
lock.released = true;
|
|
295
|
+
if (lock.watchdog)
|
|
296
|
+
clearTimeout(lock.watchdog);
|
|
297
|
+
try {
|
|
298
|
+
await lock.client.query('SELECT pg_advisory_unlock($1, hashtext($2))', [
|
|
299
|
+
OWNER_GUARD_LOCK_KEY,
|
|
300
|
+
lock.workspaceId
|
|
301
|
+
]);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
// client.end() below still drops the session-scoped lock
|
|
305
|
+
}
|
|
306
|
+
await lock.client.end().catch(() => { });
|
|
307
|
+
}
|
|
308
|
+
/** Park the locks across the cascade, each watchdogged against a hook-gap leak. */
|
|
309
|
+
parkLocks(userId, locks) {
|
|
310
|
+
for (const lock of locks) {
|
|
311
|
+
lock.watchdog = setTimeout(() => {
|
|
312
|
+
const held = this.heldLocks.get(userId)?.filter((l) => l !== lock);
|
|
313
|
+
if (held !== undefined) {
|
|
314
|
+
if (held.length === 0)
|
|
315
|
+
this.heldLocks.delete(userId);
|
|
316
|
+
else
|
|
317
|
+
this.heldLocks.set(userId, held);
|
|
318
|
+
}
|
|
319
|
+
this.logger.warn({ userId, workspaceId: lock.workspaceId }, 'owner-delete lock watchdog fired — a delete died between the hooks; releasing the lock');
|
|
320
|
+
void this.releaseOwnerLock(lock);
|
|
321
|
+
}, LOCK_WATCHDOG_MS);
|
|
322
|
+
lock.watchdog.unref();
|
|
323
|
+
}
|
|
324
|
+
this.heldLocks.set(userId, locks);
|
|
325
|
+
}
|
|
326
|
+
/** Every membership row the user holds, active or not. */
|
|
327
|
+
async membershipsOf(userId) {
|
|
328
|
+
return this.db
|
|
329
|
+
.select({
|
|
330
|
+
workspaceId: workspaceMembers.workspaceId,
|
|
331
|
+
role: workspaceMembers.role,
|
|
332
|
+
isActive: workspaceMembers.isActive
|
|
333
|
+
})
|
|
334
|
+
.from(workspaceMembers)
|
|
335
|
+
.where(eq(workspaceMembers.userId, userId));
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Workspaces where the user is an ACTIVE OWNER and the last-owner guard
|
|
339
|
+
* applies — i.e. NON-PROJECTED ones (centralAccountId IS NULL, D11).
|
|
340
|
+
* Sorted for deterministic lock ordering.
|
|
341
|
+
*/
|
|
342
|
+
async ownedGuardedWorkspaceIds(userId) {
|
|
343
|
+
const rows = await this.db
|
|
344
|
+
.select({ workspaceId: workspaceMembers.workspaceId })
|
|
345
|
+
.from(workspaceMembers)
|
|
346
|
+
.innerJoin(workspaces, eq(workspaceMembers.workspaceId, workspaces.id))
|
|
347
|
+
.where(and(eq(workspaceMembers.userId, userId), eq(workspaceMembers.role, 'owner'), eq(workspaceMembers.isActive, true), isNull(workspaces.centralAccountId)));
|
|
348
|
+
return rows.map((r) => r.workspaceId).sort();
|
|
349
|
+
}
|
|
350
|
+
/** True when the workspace is a hub projection (ownership asserted hub-side, D11). */
|
|
351
|
+
async isProjectedWorkspace(workspaceId) {
|
|
352
|
+
const [row] = await this.db
|
|
353
|
+
.select({ centralAccountId: workspaces.centralAccountId })
|
|
354
|
+
.from(workspaces)
|
|
355
|
+
.where(eq(workspaces.id, workspaceId))
|
|
356
|
+
.limit(1);
|
|
357
|
+
return Boolean(row?.centralAccountId);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=deletion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deletion.js","sourceRoot":"","sources":["../../src/accounts/deletion.ts"],"names":[],"mappings":"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"}
|