@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,66 @@
|
|
|
1
|
+
import type { Logger } from '../logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* The append-only ERASURE TOMBSTONE (OPS-3, PRDCT-1357).
|
|
4
|
+
*
|
|
5
|
+
* A GDPR erasure that lives only in the database is undone by the next
|
|
6
|
+
* restore from an older dump: the subject's row comes back, their password
|
|
7
|
+
* works again, and the audit row saying they were erased is rolled back
|
|
8
|
+
* with everything else. The tombstone lives OUTSIDE the dump — one JSON
|
|
9
|
+
* line per erased user in `$DATA_DIR/erasures.jsonl` — so it survives the
|
|
10
|
+
* database swap; restore.sh carries the live volume's file forward into
|
|
11
|
+
* the restored tree, and boot REPLAYS it: any tombstoned user present in
|
|
12
|
+
* the database is deleted again, with an audit row recording the replay.
|
|
13
|
+
*
|
|
14
|
+
* The line carries the user id (the replay key) and a KEYED fingerprint of
|
|
15
|
+
* the lowercased email (a second correlation handle for operators, never
|
|
16
|
+
* the address itself — the file is the one artifact that must outlive the
|
|
17
|
+
* erasure it records). Keyed (PRDCT-1811): the file rides in the
|
|
18
|
+
* UNENCRYPTED data tarball of every backup, and a plain hash of a
|
|
19
|
+
* low-entropy value is a dictionary lookup away from the address — an
|
|
20
|
+
* off-site backup would list who asked to be forgotten. HMAC-SHA256 under
|
|
21
|
+
* the instance's auth secret (which travels only in the passphrase-
|
|
22
|
+
* encrypted config archive) keeps the operator's correlation and denies it
|
|
23
|
+
* to anyone holding the tarball alone. Rotating the auth secret changes
|
|
24
|
+
* the fingerprints written from then on; old lines keep their old key.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ERASURE_LOG_FILE = "erasures.jsonl";
|
|
27
|
+
/** What a replay did: the ids re-erased, and the tombstones it could NOT apply. */
|
|
28
|
+
export interface ErasureReplay {
|
|
29
|
+
replayed: string[];
|
|
30
|
+
refused: Array<{
|
|
31
|
+
userId: string;
|
|
32
|
+
erasedAt: string;
|
|
33
|
+
cause: unknown;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export interface ErasureTombstone {
|
|
37
|
+
userId: string;
|
|
38
|
+
emailHash: string;
|
|
39
|
+
at: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function emailHash(email: string, key: string): string;
|
|
42
|
+
export declare class ErasureLog {
|
|
43
|
+
private readonly logger;
|
|
44
|
+
/** The fingerprint key: the resolved auth secret (never stored beside the file). */
|
|
45
|
+
private readonly fingerprintKey;
|
|
46
|
+
private readonly path;
|
|
47
|
+
constructor(dataDir: string, logger: Logger,
|
|
48
|
+
/** The fingerprint key: the resolved auth secret (never stored beside the file). */
|
|
49
|
+
fingerprintKey: string);
|
|
50
|
+
/** Append one tombstone. Best-effort on I/O failure: loud, never blocking the erasure itself. */
|
|
51
|
+
append(user: {
|
|
52
|
+
id: string;
|
|
53
|
+
email: string;
|
|
54
|
+
}): Promise<void>;
|
|
55
|
+
/** Every tombstone on disk (malformed lines skipped, loudly). Empty when the file is absent. */
|
|
56
|
+
read(): Promise<ErasureTombstone[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Replay: for every tombstoned user still (or again) present, delete them
|
|
59
|
+
* through `deleteUser` (Better Auth's cascade, the same path every GDPR
|
|
60
|
+
* surface uses) and count it. A tombstone whose delete FAILS is reported
|
|
61
|
+
* as refused, never swallowed (PRDCT-1809): the caller decides what a
|
|
62
|
+
* present-but-unerasable subject means for the boot (it refuses to serve).
|
|
63
|
+
*/
|
|
64
|
+
replay(exists: (userId: string) => Promise<boolean>, deleteUser: (userId: string) => Promise<void>): Promise<ErasureReplay>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=erasure-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"erasure-log.d.ts","sourceRoot":"","sources":["../../src/accounts/erasure-log.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,qBAAa,UAAU;IAKnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,cAAc;IANjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAG5B,OAAO,EAAE,MAAM,EACE,MAAM,EAAE,MAAM;IAC/B,oFAAoF;IACnE,cAAc,EAAE,MAAM;IAKzC,iGAAiG;IAC3F,MAAM,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBhE,gGAAgG;IAC1F,IAAI,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA0BzC;;;;;;OAMG;IACG,MAAM,CACV,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAC5C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAC5C,OAAO,CAAC,aAAa,CAAC;CAyB1B"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createHmac } from 'node:crypto';
|
|
2
|
+
import { appendFile, mkdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* The append-only ERASURE TOMBSTONE (OPS-3, PRDCT-1357).
|
|
6
|
+
*
|
|
7
|
+
* A GDPR erasure that lives only in the database is undone by the next
|
|
8
|
+
* restore from an older dump: the subject's row comes back, their password
|
|
9
|
+
* works again, and the audit row saying they were erased is rolled back
|
|
10
|
+
* with everything else. The tombstone lives OUTSIDE the dump — one JSON
|
|
11
|
+
* line per erased user in `$DATA_DIR/erasures.jsonl` — so it survives the
|
|
12
|
+
* database swap; restore.sh carries the live volume's file forward into
|
|
13
|
+
* the restored tree, and boot REPLAYS it: any tombstoned user present in
|
|
14
|
+
* the database is deleted again, with an audit row recording the replay.
|
|
15
|
+
*
|
|
16
|
+
* The line carries the user id (the replay key) and a KEYED fingerprint of
|
|
17
|
+
* the lowercased email (a second correlation handle for operators, never
|
|
18
|
+
* the address itself — the file is the one artifact that must outlive the
|
|
19
|
+
* erasure it records). Keyed (PRDCT-1811): the file rides in the
|
|
20
|
+
* UNENCRYPTED data tarball of every backup, and a plain hash of a
|
|
21
|
+
* low-entropy value is a dictionary lookup away from the address — an
|
|
22
|
+
* off-site backup would list who asked to be forgotten. HMAC-SHA256 under
|
|
23
|
+
* the instance's auth secret (which travels only in the passphrase-
|
|
24
|
+
* encrypted config archive) keeps the operator's correlation and denies it
|
|
25
|
+
* to anyone holding the tarball alone. Rotating the auth secret changes
|
|
26
|
+
* the fingerprints written from then on; old lines keep their old key.
|
|
27
|
+
*/
|
|
28
|
+
export const ERASURE_LOG_FILE = 'erasures.jsonl';
|
|
29
|
+
export function emailHash(email, key) {
|
|
30
|
+
return createHmac('sha256', key).update(email.trim().toLowerCase()).digest('hex');
|
|
31
|
+
}
|
|
32
|
+
export class ErasureLog {
|
|
33
|
+
logger;
|
|
34
|
+
fingerprintKey;
|
|
35
|
+
path;
|
|
36
|
+
constructor(dataDir, logger,
|
|
37
|
+
/** The fingerprint key: the resolved auth secret (never stored beside the file). */
|
|
38
|
+
fingerprintKey) {
|
|
39
|
+
this.logger = logger;
|
|
40
|
+
this.fingerprintKey = fingerprintKey;
|
|
41
|
+
this.path = join(dataDir, ERASURE_LOG_FILE);
|
|
42
|
+
}
|
|
43
|
+
/** Append one tombstone. Best-effort on I/O failure: loud, never blocking the erasure itself. */
|
|
44
|
+
async append(user) {
|
|
45
|
+
const line = {
|
|
46
|
+
userId: user.id,
|
|
47
|
+
emailHash: emailHash(user.email, this.fingerprintKey),
|
|
48
|
+
at: new Date().toISOString()
|
|
49
|
+
};
|
|
50
|
+
try {
|
|
51
|
+
await mkdir(join(this.path, '..'), { recursive: true });
|
|
52
|
+
await appendFile(this.path, JSON.stringify(line) + '\n', { mode: 0o600 });
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
this.logger.error({ err, path: this.path }, 'erasure tombstone: could not append — a restore may resurrect this user');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Every tombstone on disk (malformed lines skipped, loudly). Empty when the file is absent. */
|
|
59
|
+
async read() {
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = await readFile(this.path, 'utf8');
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const line of raw.split('\n')) {
|
|
69
|
+
if (!line.trim())
|
|
70
|
+
continue;
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(line);
|
|
73
|
+
if (typeof parsed.userId === 'string' && parsed.userId) {
|
|
74
|
+
out.push({
|
|
75
|
+
userId: parsed.userId,
|
|
76
|
+
emailHash: String(parsed.emailHash ?? ''),
|
|
77
|
+
at: String(parsed.at ?? '')
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
this.logger.warn({ path: this.path }, 'erasure tombstone: skipping a malformed line');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Replay: for every tombstoned user still (or again) present, delete them
|
|
89
|
+
* through `deleteUser` (Better Auth's cascade, the same path every GDPR
|
|
90
|
+
* surface uses) and count it. A tombstone whose delete FAILS is reported
|
|
91
|
+
* as refused, never swallowed (PRDCT-1809): the caller decides what a
|
|
92
|
+
* present-but-unerasable subject means for the boot (it refuses to serve).
|
|
93
|
+
*/
|
|
94
|
+
async replay(exists, deleteUser) {
|
|
95
|
+
const replayed = [];
|
|
96
|
+
const refused = [];
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
for (const tomb of await this.read()) {
|
|
99
|
+
if (seen.has(tomb.userId))
|
|
100
|
+
continue;
|
|
101
|
+
seen.add(tomb.userId);
|
|
102
|
+
if (!(await exists(tomb.userId)))
|
|
103
|
+
continue;
|
|
104
|
+
try {
|
|
105
|
+
await deleteUser(tomb.userId);
|
|
106
|
+
replayed.push(tomb.userId);
|
|
107
|
+
this.logger.warn({ userId: tomb.userId, erasedAt: tomb.at }, 'erasure tombstone replayed: a previously erased user was present again (restore from an older backup?) and has been re-erased');
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
refused.push({ userId: tomb.userId, erasedAt: tomb.at, cause: err });
|
|
111
|
+
this.logger.error({ err, userId: tomb.userId }, 'erasure tombstone: replay delete refused — the user is STILL PRESENT');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { replayed, refused };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=erasure-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"erasure-log.js","sourceRoot":"","sources":["../../src/accounts/erasure-log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAcjD,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,GAAW;IAClD,OAAO,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,OAAO,UAAU;IAKF;IAEA;IANF,IAAI,CAAS;IAE9B,YACE,OAAe,EACE,MAAc;IAC/B,oFAAoF;IACnE,cAAsB;QAFtB,WAAM,GAAN,MAAM,CAAQ;QAEd,mBAAc,GAAd,cAAc,CAAQ;QAEvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,MAAM,CAAC,IAAmC;QAC9C,MAAM,IAAI,GAAqB;YAC7B,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;YACrD,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC7B,CAAC;QACF,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EACxB,yEAAyE,CAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,gGAAgG;IAChG,KAAK,CAAC,IAAI;QACR,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAAuB,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,SAAS;YAC3B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA8B,CAAC;gBAC7D,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBACvD,GAAG,CAAC,IAAI,CAAC;wBACP,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;wBACzC,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;qBAC5B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,8CAA8C,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CACV,MAA4C,EAC5C,UAA6C;QAE7C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,OAAO,GAA6B,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACrC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,SAAS;YACpC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtB,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAAE,SAAS;YAC3C,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,EAC1C,+HAA+H,CAChI,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;gBACrE,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAC5B,sEAAsE,CACvE,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AccountDeletionService, LastOwnerError, isLastOwnerDbError } from './deletion.js';
|
|
2
|
+
export { ErasureLog, emailHash } from './erasure-log.js';
|
|
3
|
+
export { mintRefusal } from './mint-refusal.js';
|
|
4
|
+
export { isDuplicateAccountError } from './signup-duplicate.js';
|
|
5
|
+
export { parseSuperadminEmails } from './superadmin.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accounts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AccountDeletionService, LastOwnerError, isLastOwnerDbError } from './deletion.js';
|
|
2
|
+
export { ErasureLog, emailHash } from './erasure-log.js';
|
|
3
|
+
export { mintRefusal } from './mint-refusal.js';
|
|
4
|
+
export { isDuplicateAccountError } from './signup-duplicate.js';
|
|
5
|
+
export { parseSuperadminEmails } from './superadmin.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accounts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Db } from '@antasphere/chassis-db';
|
|
2
|
+
/**
|
|
3
|
+
* Shared refusal for the SIGN-IN-EQUIVALENT mint routes (PRDCT-1354,
|
|
4
|
+
* findings AUTH-1/AUTH-2/AUTH-8). `/members/{id}/reset-link`,
|
|
5
|
+
* `/members/{id}/change-email-link` and the demo pass mint
|
|
6
|
+
* (`POST /demo/passes`) all hand the caller a bearer credential
|
|
7
|
+
* for ANOTHER user's GLOBAL account: consuming any one of them signs the
|
|
8
|
+
* target in (LESSONS.md M6: "Consuming a change-email JWT while logged
|
|
9
|
+
* out CREATES a session for the target user"). A `user` row is
|
|
10
|
+
* instance-global, so the blast radius of a mint is every workspace that
|
|
11
|
+
* user belongs to — not just the minter's.
|
|
12
|
+
*
|
|
13
|
+
* Two target classes therefore make a mint a CROSS-TENANT takeover and
|
|
14
|
+
* are refused outright:
|
|
15
|
+
*
|
|
16
|
+
* 1. `origin='guest'` — the guest row exists for principal resolution
|
|
17
|
+
* only (D2). It was created by the per-resource claim path for an
|
|
18
|
+
* EXTERNAL party whose account is not this tenant's to administer;
|
|
19
|
+
* the host tenant never owned that credential. Admins have no
|
|
20
|
+
* recovery duty toward a guest, so there is nothing to trade away.
|
|
21
|
+
* 2. a target holding a membership in ANY OTHER workspace — the minted
|
|
22
|
+
* credential would carry into that workspace too. "Admin of the
|
|
23
|
+
* workspace" is not "owner of the person"; a user who works with two
|
|
24
|
+
* tenants must never be recoverable by either one unilaterally.
|
|
25
|
+
* Recovery for such a user is self-serve (`/request-password-reset`)
|
|
26
|
+
* or the operator's break-glass surface.
|
|
27
|
+
*
|
|
28
|
+
* The role gate is OWNER, not admin (AUTH-8): the old guards only fired
|
|
29
|
+
* when `target.role === 'owner'`, so any admin could mint against any
|
|
30
|
+
* other admin and escalate laterally. Minting someone else's credential
|
|
31
|
+
* is an owner-level act on every route that calls this.
|
|
32
|
+
*
|
|
33
|
+
* Fail-CLOSED shape: a new route that mints a credential for another user
|
|
34
|
+
* must call this helper. Returning `null` means "no refusal found".
|
|
35
|
+
* `guestTargetMessage` is the tool's `guest_target` sentence
|
|
36
|
+
* (`copy.guestTarget`).
|
|
37
|
+
*/
|
|
38
|
+
export declare function mintRefusal(db: Db, guestTargetMessage: string, principal: {
|
|
39
|
+
workspaceId: string;
|
|
40
|
+
}, target: {
|
|
41
|
+
userId: string;
|
|
42
|
+
origin: string;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
} | null>;
|
|
47
|
+
//# sourceMappingURL=mint-refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint-refusal.d.ts","sourceRoot":"","sources":["../../src/accounts/mint-refusal.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,EAAE,EACN,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,EAClC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAsBnD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { and, eq, ne } from 'drizzle-orm';
|
|
2
|
+
import { workspaceMembers } from '@antasphere/chassis-db';
|
|
3
|
+
/**
|
|
4
|
+
* Shared refusal for the SIGN-IN-EQUIVALENT mint routes (PRDCT-1354,
|
|
5
|
+
* findings AUTH-1/AUTH-2/AUTH-8). `/members/{id}/reset-link`,
|
|
6
|
+
* `/members/{id}/change-email-link` and the demo pass mint
|
|
7
|
+
* (`POST /demo/passes`) all hand the caller a bearer credential
|
|
8
|
+
* for ANOTHER user's GLOBAL account: consuming any one of them signs the
|
|
9
|
+
* target in (LESSONS.md M6: "Consuming a change-email JWT while logged
|
|
10
|
+
* out CREATES a session for the target user"). A `user` row is
|
|
11
|
+
* instance-global, so the blast radius of a mint is every workspace that
|
|
12
|
+
* user belongs to — not just the minter's.
|
|
13
|
+
*
|
|
14
|
+
* Two target classes therefore make a mint a CROSS-TENANT takeover and
|
|
15
|
+
* are refused outright:
|
|
16
|
+
*
|
|
17
|
+
* 1. `origin='guest'` — the guest row exists for principal resolution
|
|
18
|
+
* only (D2). It was created by the per-resource claim path for an
|
|
19
|
+
* EXTERNAL party whose account is not this tenant's to administer;
|
|
20
|
+
* the host tenant never owned that credential. Admins have no
|
|
21
|
+
* recovery duty toward a guest, so there is nothing to trade away.
|
|
22
|
+
* 2. a target holding a membership in ANY OTHER workspace — the minted
|
|
23
|
+
* credential would carry into that workspace too. "Admin of the
|
|
24
|
+
* workspace" is not "owner of the person"; a user who works with two
|
|
25
|
+
* tenants must never be recoverable by either one unilaterally.
|
|
26
|
+
* Recovery for such a user is self-serve (`/request-password-reset`)
|
|
27
|
+
* or the operator's break-glass surface.
|
|
28
|
+
*
|
|
29
|
+
* The role gate is OWNER, not admin (AUTH-8): the old guards only fired
|
|
30
|
+
* when `target.role === 'owner'`, so any admin could mint against any
|
|
31
|
+
* other admin and escalate laterally. Minting someone else's credential
|
|
32
|
+
* is an owner-level act on every route that calls this.
|
|
33
|
+
*
|
|
34
|
+
* Fail-CLOSED shape: a new route that mints a credential for another user
|
|
35
|
+
* must call this helper. Returning `null` means "no refusal found".
|
|
36
|
+
* `guestTargetMessage` is the tool's `guest_target` sentence
|
|
37
|
+
* (`copy.guestTarget`).
|
|
38
|
+
*/
|
|
39
|
+
export async function mintRefusal(db, guestTargetMessage, principal, target) {
|
|
40
|
+
if (target.origin === 'guest') {
|
|
41
|
+
return {
|
|
42
|
+
code: 'guest_target',
|
|
43
|
+
message: guestTargetMessage
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const [foreign] = await db
|
|
47
|
+
.select({ id: workspaceMembers.id })
|
|
48
|
+
.from(workspaceMembers)
|
|
49
|
+
.where(and(eq(workspaceMembers.userId, target.userId), ne(workspaceMembers.workspaceId, principal.workspaceId)))
|
|
50
|
+
.limit(1);
|
|
51
|
+
if (foreign) {
|
|
52
|
+
return {
|
|
53
|
+
code: 'cross_workspace_target',
|
|
54
|
+
message: 'This member also belongs to another workspace — an admin-minted link would carry into it, so it is refused'
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=mint-refusal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint-refusal.js","sourceRoot":"","sources":["../../src/accounts/mint-refusal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAW,MAAM,wBAAwB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,EAAM,EACN,kBAA0B,EAC1B,SAAkC,EAClC,MAA0C;IAE1C,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,kBAAkB;SAC5B,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,EAAE,EAAE,EAAE,gBAAgB,CAAC,EAAE,EAAE,CAAC;SACnC,IAAI,CAAC,gBAAgB,CAAC;SACtB,KAAK,CACJ,GAAG,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CACzG;SACA,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO;YACL,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EACL,4GAA4G;SAC/G,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when a failed `signUpEmail` means "this email already has an account":
|
|
3
|
+
* either Better Auth's own pre-check (APIError USER_ALREADY_EXISTS / 422) or,
|
|
4
|
+
* in the tight concurrent-signup race where two callers pass an account lookup
|
|
5
|
+
* together, the losing INSERT's Postgres unique_violation (23505) on the user
|
|
6
|
+
* email — found anywhere down the wrapped error's `cause` chain.
|
|
7
|
+
*
|
|
8
|
+
* Shared by every public account-minting endpoint (invitation accept,
|
|
9
|
+
* collaborator claim): the existence-revealing 409 is answered ONLY here, after
|
|
10
|
+
* the caller has committed real credentials, so a credential-less probe can
|
|
11
|
+
* never read it (PRDCT-1437).
|
|
12
|
+
*/
|
|
13
|
+
export declare function isDuplicateAccountError(e: unknown): boolean;
|
|
14
|
+
//# sourceMappingURL=signup-duplicate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signup-duplicate.d.ts","sourceRoot":"","sources":["../../src/accounts/signup-duplicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAQ3D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when a failed `signUpEmail` means "this email already has an account":
|
|
3
|
+
* either Better Auth's own pre-check (APIError USER_ALREADY_EXISTS / 422) or,
|
|
4
|
+
* in the tight concurrent-signup race where two callers pass an account lookup
|
|
5
|
+
* together, the losing INSERT's Postgres unique_violation (23505) on the user
|
|
6
|
+
* email — found anywhere down the wrapped error's `cause` chain.
|
|
7
|
+
*
|
|
8
|
+
* Shared by every public account-minting endpoint (invitation accept,
|
|
9
|
+
* collaborator claim): the existence-revealing 409 is answered ONLY here, after
|
|
10
|
+
* the caller has committed real credentials, so a credential-less probe can
|
|
11
|
+
* never read it (PRDCT-1437).
|
|
12
|
+
*/
|
|
13
|
+
export function isDuplicateAccountError(e) {
|
|
14
|
+
for (let cur = e, depth = 0; cur instanceof Error && depth < 10; cur = cur.cause, depth++) {
|
|
15
|
+
const anyErr = cur;
|
|
16
|
+
if (anyErr.code === '23505')
|
|
17
|
+
return true;
|
|
18
|
+
if (anyErr.body?.code === 'USER_ALREADY_EXISTS')
|
|
19
|
+
return true;
|
|
20
|
+
if (anyErr.status === 'UNPROCESSABLE_ENTITY' || anyErr.status === 422)
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=signup-duplicate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signup-duplicate.js","sourceRoot":"","sources":["../../src/accounts/signup-duplicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAU;IAChD,KAAK,IAAI,GAAG,GAAY,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,YAAY,KAAK,IAAI,KAAK,GAAG,EAAE,EAAE,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;QACnG,MAAM,MAAM,GAAG,GAAsE,CAAC;QACtF,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACzC,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,qBAAqB;YAAE,OAAO,IAAI,CAAC;QAC7D,IAAI,MAAM,CAAC,MAAM,KAAK,sBAAsB,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;IACrF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Break-glass superadmin recognition (ADR 010).
|
|
3
|
+
*
|
|
4
|
+
* The capability is env-derived and off by default: `SUPERADMIN_EMAILS` is a
|
|
5
|
+
* comma-separated allowlist, and a caller is superadmin ONLY when all three
|
|
6
|
+
* hold at once:
|
|
7
|
+
*
|
|
8
|
+
* 1. the request carries a Better Auth SESSION (never a machine credential —
|
|
9
|
+
* the break-glass routes are unlisted in the fail-closed scope allowlist,
|
|
10
|
+
* and the handlers resolve the session directly);
|
|
11
|
+
* 2. the session user's email is on the allowlist;
|
|
12
|
+
* 3. that email is VERIFIED (`user.email_verified`) — an unverified match
|
|
13
|
+
* must never qualify, or squatting an allowlisted address would be enough.
|
|
14
|
+
*
|
|
15
|
+
* There is deliberately NO persistent DB super-role: unset/empty env means no
|
|
16
|
+
* superadmin exists and the capability is fully dormant.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Parse `SUPERADMIN_EMAILS` into a lowercased set (Better Auth stores emails
|
|
20
|
+
* lowercased, so membership checks compare in that form).
|
|
21
|
+
*
|
|
22
|
+
* Throws on malformed entries so the env schema fails LOUDLY at boot — a typo
|
|
23
|
+
* must never silently disarm break-glass. `undefined` (unset/blank through
|
|
24
|
+
* `blankToUndefined`) yields the empty set: dormant.
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseSuperadminEmails(raw: string | undefined): Set<string>;
|
|
27
|
+
//# sourceMappingURL=superadmin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"superadmin.d.ts","sourceRoot":"","sources":["../../src/accounts/superadmin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB1E"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Break-glass superadmin recognition (ADR 010).
|
|
3
|
+
*
|
|
4
|
+
* The capability is env-derived and off by default: `SUPERADMIN_EMAILS` is a
|
|
5
|
+
* comma-separated allowlist, and a caller is superadmin ONLY when all three
|
|
6
|
+
* hold at once:
|
|
7
|
+
*
|
|
8
|
+
* 1. the request carries a Better Auth SESSION (never a machine credential —
|
|
9
|
+
* the break-glass routes are unlisted in the fail-closed scope allowlist,
|
|
10
|
+
* and the handlers resolve the session directly);
|
|
11
|
+
* 2. the session user's email is on the allowlist;
|
|
12
|
+
* 3. that email is VERIFIED (`user.email_verified`) — an unverified match
|
|
13
|
+
* must never qualify, or squatting an allowlisted address would be enough.
|
|
14
|
+
*
|
|
15
|
+
* There is deliberately NO persistent DB super-role: unset/empty env means no
|
|
16
|
+
* superadmin exists and the capability is fully dormant.
|
|
17
|
+
*/
|
|
18
|
+
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
19
|
+
/**
|
|
20
|
+
* Parse `SUPERADMIN_EMAILS` into a lowercased set (Better Auth stores emails
|
|
21
|
+
* lowercased, so membership checks compare in that form).
|
|
22
|
+
*
|
|
23
|
+
* Throws on malformed entries so the env schema fails LOUDLY at boot — a typo
|
|
24
|
+
* must never silently disarm break-glass. `undefined` (unset/blank through
|
|
25
|
+
* `blankToUndefined`) yields the empty set: dormant.
|
|
26
|
+
*/
|
|
27
|
+
export function parseSuperadminEmails(raw) {
|
|
28
|
+
const allowlist = new Set();
|
|
29
|
+
if (raw === undefined || raw.trim() === '')
|
|
30
|
+
return allowlist;
|
|
31
|
+
const entries = raw
|
|
32
|
+
.split(',')
|
|
33
|
+
.map((entry) => entry.trim())
|
|
34
|
+
.filter((entry) => entry.length > 0);
|
|
35
|
+
if (entries.length === 0) {
|
|
36
|
+
throw new Error('SUPERADMIN_EMAILS must list at least one email address');
|
|
37
|
+
}
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
if (!EMAIL_RE.test(entry)) {
|
|
40
|
+
throw new Error(`SUPERADMIN_EMAILS entry "${entry}" is not a valid email address`);
|
|
41
|
+
}
|
|
42
|
+
allowlist.add(entry.toLowerCase());
|
|
43
|
+
}
|
|
44
|
+
return allowlist;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=superadmin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"superadmin.js","sourceRoot":"","sources":["../../src/accounts/superadmin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAuB;IAC3D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC7D,MAAM,OAAO,GAAG,GAAG;SAChB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,gCAAgC,CAAC,CAAC;QACrF,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OpenAPIHono } from '@hono/zod-openapi';
|
|
2
|
+
import type { ScopeRoutes } from './scope-routes.js';
|
|
3
|
+
import { type Db } from '@antasphere/chassis-db';
|
|
4
|
+
import type { ApiKeyService } from '../apikeys/service.js';
|
|
5
|
+
/**
|
|
6
|
+
* API keys are USER credentials (user-scoped credential model): the listing
|
|
7
|
+
* and the revoke are keyed on the CREATOR, not on any workspace — a key acts
|
|
8
|
+
* as its holder wherever their memberships reach, so "my keys" is the only
|
|
9
|
+
* honest scope. Mint stays sessions-only and accepts an optional workspace
|
|
10
|
+
* PIN (least privilege); revocation is creator-only (a workspace admin has
|
|
11
|
+
* no standing over another user's credential).
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerApiKeyRoutes(api: OpenAPIHono, db: Db, service: ApiKeyService, routes: Pick<ScopeRoutes, 'apiKeysListRoute' | 'apiKeyCreateRoute' | 'apiKeyRevokeRoute'>): void;
|
|
14
|
+
//# sourceMappingURL=apikeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apikeys.d.ts","sourceRoot":"","sources":["../../src/api/apikeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAA0C,KAAK,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAEzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAmB3D;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,kBAAkB,GAAG,mBAAmB,GAAG,mBAAmB,CAAC,GACxF,IAAI,CA6GN"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { and, desc, eq } from 'drizzle-orm';
|
|
2
|
+
import { apiKeys, workspaceMembers } from '@antasphere/chassis-db';
|
|
3
|
+
import { sql } from 'drizzle-orm';
|
|
4
|
+
import { cursorRowId, keysetBefore, pageOf } from '../pagination.js';
|
|
5
|
+
import { requireAuth } from '../middleware/auth-context.js';
|
|
6
|
+
const err = (code, message) => ({ error: { code, message } });
|
|
7
|
+
const toWire = (k) => ({
|
|
8
|
+
id: k.id,
|
|
9
|
+
name: k.name,
|
|
10
|
+
keyId: k.keyId,
|
|
11
|
+
scopes: k.scopes,
|
|
12
|
+
workspaceId: k.workspaceId,
|
|
13
|
+
createdBy: k.createdBy,
|
|
14
|
+
createdAt: k.createdAt.toISOString(),
|
|
15
|
+
lastUsedAt: k.lastUsedAt?.toISOString() ?? null,
|
|
16
|
+
revokedAt: k.revokedAt?.toISOString() ?? null,
|
|
17
|
+
expiresAt: k.expiresAt?.toISOString() ?? null
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* API keys are USER credentials (user-scoped credential model): the listing
|
|
21
|
+
* and the revoke are keyed on the CREATOR, not on any workspace — a key acts
|
|
22
|
+
* as its holder wherever their memberships reach, so "my keys" is the only
|
|
23
|
+
* honest scope. Mint stays sessions-only and accepts an optional workspace
|
|
24
|
+
* PIN (least privilege); revocation is creator-only (a workspace admin has
|
|
25
|
+
* no standing over another user's credential).
|
|
26
|
+
*/
|
|
27
|
+
export function registerApiKeyRoutes(api, db, service, routes) {
|
|
28
|
+
const { apiKeysListRoute, apiKeyCreateRoute, apiKeyRevokeRoute } = routes;
|
|
29
|
+
api.use('/api-keys', requireAuth());
|
|
30
|
+
api.use('/api-keys/*', requireAuth());
|
|
31
|
+
api.openapi(apiKeysListRoute, async (c) => {
|
|
32
|
+
const principal = c.get('principal');
|
|
33
|
+
const { cursor, limit } = c.req.valid('query');
|
|
34
|
+
const cursorId = cursorRowId(cursor);
|
|
35
|
+
const rows = await db
|
|
36
|
+
.select()
|
|
37
|
+
.from(apiKeys)
|
|
38
|
+
.where(and(eq(apiKeys.createdBy, principal.userId), ...(cursorId
|
|
39
|
+
? [
|
|
40
|
+
keysetBefore({
|
|
41
|
+
table: apiKeys,
|
|
42
|
+
id: apiKeys.id,
|
|
43
|
+
createdAt: apiKeys.createdAt,
|
|
44
|
+
// The keyset scope column (see pagination.ts): the listing
|
|
45
|
+
// is creator-scoped, so a foreign user's cursor can never
|
|
46
|
+
// position inside this user's ordering.
|
|
47
|
+
workspaceId: apiKeys.createdBy,
|
|
48
|
+
cursorId,
|
|
49
|
+
workspace: principal.userId
|
|
50
|
+
})
|
|
51
|
+
]
|
|
52
|
+
: [])))
|
|
53
|
+
.orderBy(desc(apiKeys.createdAt), desc(apiKeys.id))
|
|
54
|
+
.limit(limit + 1);
|
|
55
|
+
const { page, nextCursor } = pageOf(rows, limit);
|
|
56
|
+
return c.json({ apiKeys: page.map(toWire), nextCursor }, 200);
|
|
57
|
+
});
|
|
58
|
+
api.openapi(apiKeyCreateRoute, async (c) => {
|
|
59
|
+
const principal = c.get('principal');
|
|
60
|
+
// Locked rule: a key never mints a key. Sessions only.
|
|
61
|
+
if (principal.via !== 'session') {
|
|
62
|
+
return c.json(err('sessions_only', 'API keys can only be created from a browser session'), 403);
|
|
63
|
+
}
|
|
64
|
+
const body = c.req.valid('json');
|
|
65
|
+
// Optional PIN: an ACTIVE membership of the pinned workspace is required
|
|
66
|
+
// — one uniform 403 whether the workspace does not exist or the caller
|
|
67
|
+
// is not a member (no oracle about other workspaces).
|
|
68
|
+
if (body.workspaceId) {
|
|
69
|
+
const [member] = await db
|
|
70
|
+
.select({ id: workspaceMembers.id })
|
|
71
|
+
.from(workspaceMembers)
|
|
72
|
+
.where(and(eq(workspaceMembers.userId, principal.userId), eq(workspaceMembers.workspaceId, body.workspaceId), eq(workspaceMembers.isActive, true)))
|
|
73
|
+
.limit(1);
|
|
74
|
+
if (!member) {
|
|
75
|
+
return c.json(err('no_membership', 'This workspace is not available to this account'), 403);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// The client sends a TTL in days; the server owns the absolute expiry.
|
|
79
|
+
const expiresAt = body.expiresInDays ? new Date(Date.now() + body.expiresInDays * 86_400_000) : null;
|
|
80
|
+
const minted = await service.mint({
|
|
81
|
+
workspaceId: body.workspaceId ?? null,
|
|
82
|
+
createdBy: principal.userId,
|
|
83
|
+
name: body.name,
|
|
84
|
+
scopes: body.scopes,
|
|
85
|
+
expiresAt
|
|
86
|
+
});
|
|
87
|
+
const [row] = await db.select().from(apiKeys).where(eq(apiKeys.id, minted.id)).limit(1);
|
|
88
|
+
c.set('audit', {
|
|
89
|
+
action: 'apikey.create',
|
|
90
|
+
resourceType: 'api_key',
|
|
91
|
+
resourceId: minted.id,
|
|
92
|
+
metadata: {
|
|
93
|
+
name: body.name,
|
|
94
|
+
scopes: body.scopes,
|
|
95
|
+
workspaceId: body.workspaceId ?? null,
|
|
96
|
+
expiresAt: expiresAt?.toISOString() ?? null
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return c.json({ apiKey: toWire(row), key: minted.key }, 201);
|
|
100
|
+
});
|
|
101
|
+
api.openapi(apiKeyRevokeRoute, async (c) => {
|
|
102
|
+
const principal = c.get('principal');
|
|
103
|
+
const { id } = c.req.valid('param');
|
|
104
|
+
// Creator-only: a key is its creator's credential. A foreign key answers
|
|
105
|
+
// the same 404 as a nonexistent one (existence is not probeable).
|
|
106
|
+
const [key] = await db
|
|
107
|
+
.select()
|
|
108
|
+
.from(apiKeys)
|
|
109
|
+
.where(and(eq(apiKeys.id, id), eq(apiKeys.createdBy, principal.userId)))
|
|
110
|
+
.limit(1);
|
|
111
|
+
if (!key)
|
|
112
|
+
return c.json(err('not_found', 'API key not found'), 404);
|
|
113
|
+
if (!key.revokedAt) {
|
|
114
|
+
await db
|
|
115
|
+
.update(apiKeys)
|
|
116
|
+
.set({ revokedAt: sql `now()` })
|
|
117
|
+
.where(eq(apiKeys.id, key.id));
|
|
118
|
+
}
|
|
119
|
+
const [updated] = await db.select().from(apiKeys).where(eq(apiKeys.id, key.id)).limit(1);
|
|
120
|
+
c.set('audit', { action: 'apikey.revoke', resourceType: 'api_key', resourceId: key.id });
|
|
121
|
+
return c.json(toWire(updated), 200);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=apikeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apikeys.js","sourceRoot":"","sources":["../../src/api/apikeys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/api/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAA+B,KAAK,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAI9E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CA2ElE"}
|