@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,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "7",
|
|
3
|
+
"dialect": "postgresql",
|
|
4
|
+
"entries": [
|
|
5
|
+
{
|
|
6
|
+
"idx": 0,
|
|
7
|
+
"version": "7",
|
|
8
|
+
"when": 1791388822563,
|
|
9
|
+
"tag": "0000_chassis_baseline",
|
|
10
|
+
"breakpoints": true
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"idx": 1,
|
|
14
|
+
"version": "7",
|
|
15
|
+
"when": 1791388823563,
|
|
16
|
+
"tag": "0001_last_owner_guard",
|
|
17
|
+
"breakpoints": true
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineConfig } from 'drizzle-kit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The chassis's own migration history, for its own test host: the chassis
|
|
5
|
+
* tables alone, generated from the chassis schema into `test/host/drizzle`
|
|
6
|
+
* (`pnpm db:generate` in this package). A tool's history starts from these
|
|
7
|
+
* tables and adds its own; this one exists so the chassis suite boots without
|
|
8
|
+
* a tool beside it.
|
|
9
|
+
*/
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
dialect: 'postgresql',
|
|
12
|
+
// drizzle-kit resolves paths from the package root, where pnpm runs it.
|
|
13
|
+
schema: '../chassis-db/src/schema.ts',
|
|
14
|
+
out: './test/host/drizzle',
|
|
15
|
+
verbose: true,
|
|
16
|
+
strict: true
|
|
17
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ToolIdentity } from '@antasphere/chassis-contract';
|
|
2
|
+
import type { ChassisRoutesCopy } from '@antasphere/chassis-contract/routes';
|
|
3
|
+
import type { ToolCopy } from '@antasphere/chassis-server';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The identity of the test tools of this package (`minimal-tool.ts`, and the
|
|
7
|
+
* slot-less tool of `empty-tool.test.ts`): a tool called Things. Every value
|
|
8
|
+
* is its own, the key prefix included: the suite reads the prefix from its
|
|
9
|
+
* host (`host.identity.apiKeyPrefix`), so no file of this package spells a
|
|
10
|
+
* real tool's.
|
|
11
|
+
*/
|
|
12
|
+
export const THINGS_IDENTITY = {
|
|
13
|
+
slug: 'things',
|
|
14
|
+
displayName: 'Things',
|
|
15
|
+
apiKeyPrefix: 'thg',
|
|
16
|
+
scopes: { read: 'things:read', write: 'things:write', dataExport: 'things:export' },
|
|
17
|
+
cliKeyScopesLabel: 'things:read+write',
|
|
18
|
+
cloud: { url: 'https://things.antasphere.test' },
|
|
19
|
+
cli: { bin: 'things', envPrefix: 'THINGS', legacyConfigDir: 'things' },
|
|
20
|
+
mcp: { serverName: 'things', toolPrefix: 'things_' },
|
|
21
|
+
otelServiceName: 'things',
|
|
22
|
+
imageName: 'example.test/things'
|
|
23
|
+
} as const satisfies ToolIdentity;
|
|
24
|
+
|
|
25
|
+
/** The same tool's wording of the chassis refusals that name a domain (the `copy` slot). */
|
|
26
|
+
export const THINGS_COPY: ToolCopy = {
|
|
27
|
+
guestForbidden: 'Guest access is limited to the things you were invited to',
|
|
28
|
+
guestTarget:
|
|
29
|
+
'This member is an external guest of one thing: their account is not this workspace’s to recover',
|
|
30
|
+
fileInUse: 'This file is referenced by a thing',
|
|
31
|
+
mail: {
|
|
32
|
+
tagline: 'A place for things. A test tool.',
|
|
33
|
+
invitePitch: 'Join to see the things the team keeps there, and to add your own.',
|
|
34
|
+
invitePreheader: 'their things, and a place for yours.'
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** And its wording of the OpenAPI document (`defineChassisRoutes`' third argument). */
|
|
39
|
+
export const THINGS_ROUTES_COPY: ChassisRoutesCopy = {
|
|
40
|
+
fileInUseOpenApi: 'file_in_use: referenced by a thing'
|
|
41
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { createPlatform } from '@antasphere/chassis-server';
|
|
4
|
+
import type { ChassisTestHost } from '@antasphere/chassis-server/testing';
|
|
5
|
+
import { THINGS_IDENTITY } from './identity.js';
|
|
6
|
+
import {
|
|
7
|
+
MIGRATIONS_FIXTURE,
|
|
8
|
+
minimalTool,
|
|
9
|
+
THINGS_ROUTE,
|
|
10
|
+
THINGS_SCOPES,
|
|
11
|
+
type MinimalBootOverrides,
|
|
12
|
+
type MinimalBootResult
|
|
13
|
+
} from './minimal-tool.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The chassis package's host of the suite (`test/integration`): the chassis
|
|
17
|
+
* composition bound to the minimal test tool. `@chassis-test/host` resolves
|
|
18
|
+
* here under this package's vitest config; the tool's app aliases the same
|
|
19
|
+
* specifier to its own host, over its real composition.
|
|
20
|
+
*/
|
|
21
|
+
export type HostBootResult = MinimalBootResult;
|
|
22
|
+
export type HostBootOverrides = MinimalBootOverrides;
|
|
23
|
+
|
|
24
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
const platform = createPlatform(minimalTool);
|
|
26
|
+
|
|
27
|
+
export const host: ChassisTestHost<HostBootResult, HostBootOverrides> = {
|
|
28
|
+
boot: (source, overrides) => platform.boot(source, overrides),
|
|
29
|
+
migrationsDir: MIGRATIONS_FIXTURE,
|
|
30
|
+
drLib: join(here, 'dr-lib.sh'),
|
|
31
|
+
identity: THINGS_IDENTITY,
|
|
32
|
+
hubClientId: 'tool-things-cloud',
|
|
33
|
+
scopes: THINGS_SCOPES,
|
|
34
|
+
probeRoute: THINGS_ROUTE
|
|
35
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { createDb, schema } from '@antasphere/chassis-db';
|
|
4
|
+
import {
|
|
5
|
+
auditedSizeBytes,
|
|
6
|
+
declareRouteEntitlements,
|
|
7
|
+
declaredContentLength,
|
|
8
|
+
defineChassisContract
|
|
9
|
+
} from '@antasphere/chassis-contract';
|
|
10
|
+
import { defineChassisRoutes, fileUploadRoute } from '@antasphere/chassis-contract/routes';
|
|
11
|
+
import type { BootOverrides, BootResult, ToolDefinition } from '@antasphere/chassis-server';
|
|
12
|
+
import { createScopeAllowlist, requireAuth } from '@antasphere/chassis-server/middleware';
|
|
13
|
+
import { THINGS_COPY, THINGS_IDENTITY, THINGS_ROUTES_COPY } from './identity.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The MINIMAL test tool: the smallest tool that fills the required slots of
|
|
17
|
+
* `createPlatform` and gives the chassis suite something of a tool's to aim
|
|
18
|
+
* at. Its own three scope names, one tiny probe route per scope, the required
|
|
19
|
+
* blob policy, no domain, no env extension, no jobs, no buckets, no public
|
|
20
|
+
* app, no MCP tools.
|
|
21
|
+
*
|
|
22
|
+
* The migrations are a FIXTURE read by path, not an import (same stance as
|
|
23
|
+
* `empty-tool.test.ts`): the chassis's own history, `test/host/drizzle`,
|
|
24
|
+
* generated from the chassis schema by `pnpm db:generate` in this package
|
|
25
|
+
* (the chassis tables and nothing else). A tool's history starts from the
|
|
26
|
+
* same tables and adds its own; the tool's host of this suite boots on it.
|
|
27
|
+
*/
|
|
28
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
export const MIGRATIONS_FIXTURE = join(here, 'drizzle');
|
|
30
|
+
|
|
31
|
+
export const THINGS_SCOPES = THINGS_IDENTITY.scopes;
|
|
32
|
+
type ThingsScope = (typeof THINGS_SCOPES)[keyof typeof THINGS_SCOPES];
|
|
33
|
+
|
|
34
|
+
/** The probe routes, one per scope: authenticated, workspace-scoped, and empty. */
|
|
35
|
+
export const THINGS_ROUTE = '/api/v1/things';
|
|
36
|
+
const THINGS_EXPORT_ROUTE = '/api/v1/things/export';
|
|
37
|
+
|
|
38
|
+
const contract = defineChassisContract({
|
|
39
|
+
scopes: [THINGS_SCOPES.read, THINGS_SCOPES.write, THINGS_SCOPES.dataExport]
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
43
|
+
type NoEnv = {};
|
|
44
|
+
type NoDomain = Record<string, never>;
|
|
45
|
+
|
|
46
|
+
export type MinimalBootOverrides = BootOverrides;
|
|
47
|
+
export type MinimalBootResult = BootResult<NoEnv, NoDomain>;
|
|
48
|
+
|
|
49
|
+
export const minimalTool: ToolDefinition<NoEnv, NoDomain> = {
|
|
50
|
+
identity: THINGS_IDENTITY,
|
|
51
|
+
runtime: {
|
|
52
|
+
version: '0.0.0-test',
|
|
53
|
+
findMigrationsDir: () => MIGRATIONS_FIXTURE,
|
|
54
|
+
publicDir: join(here, 'no-dashboard-build')
|
|
55
|
+
},
|
|
56
|
+
db: (url) => createDb(url, schema),
|
|
57
|
+
scopes: {
|
|
58
|
+
oauth: [
|
|
59
|
+
'openid',
|
|
60
|
+
'profile',
|
|
61
|
+
'email',
|
|
62
|
+
'offline_access',
|
|
63
|
+
THINGS_SCOPES.read,
|
|
64
|
+
THINGS_SCOPES.write,
|
|
65
|
+
THINGS_SCOPES.dataExport
|
|
66
|
+
],
|
|
67
|
+
cliKey: [THINGS_SCOPES.read, THINGS_SCOPES.write],
|
|
68
|
+
requiredScopeFor: createScopeAllowlist<ThingsScope>({
|
|
69
|
+
...THINGS_SCOPES,
|
|
70
|
+
rules: [
|
|
71
|
+
(path, _method, isRead) => {
|
|
72
|
+
if (path === THINGS_ROUTE) return isRead ? THINGS_SCOPES.read : THINGS_SCOPES.write;
|
|
73
|
+
if (path === THINGS_EXPORT_ROUTE && isRead) return THINGS_SCOPES.dataExport;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}),
|
|
78
|
+
contractRoutes: defineChassisRoutes(contract, THINGS_IDENTITY, THINGS_ROUTES_COPY)
|
|
79
|
+
},
|
|
80
|
+
services: () => ({}),
|
|
81
|
+
api: {
|
|
82
|
+
// TEST FIXTURE ONLY: `undefined` is the whole-workspace view, for every member. The suite's
|
|
83
|
+
// files tests never assert member-to-member privacy (that proof is the tool's, SL-B1), so
|
|
84
|
+
// nothing here reads as a policy to copy: a real tool MUST return a per-principal scope.
|
|
85
|
+
filePolicy: () => ({ blobInUse: async () => false, blobReadScope: () => undefined }),
|
|
86
|
+
routes: (api) => {
|
|
87
|
+
api.use('/things', requireAuth());
|
|
88
|
+
api.use('/things/*', requireAuth());
|
|
89
|
+
api.get('/things', (c) => c.json({ things: [], nextCursor: null }, 200));
|
|
90
|
+
api.post('/things', (c) => c.json({ thing: { id: 'thing' } }, 201));
|
|
91
|
+
api.get('/things/export', (c) => c.json({ things: [] }, 200));
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
// The billing rail (slot 22): the generic files upload is the one metered
|
|
95
|
+
// route of the minimal tool — a price on the chassis' own route is the
|
|
96
|
+
// tool's declaration, never the chassis'. The limit's oss value is the
|
|
97
|
+
// operator's cap and so is the paid tier's (what discovery advertises is
|
|
98
|
+
// what the instance serves, PRDCT-2653); the free value is a fifth of it,
|
|
99
|
+
// so a suite can upload above the free value and below the cap as a pro
|
|
100
|
+
// account. Self-hosted instances read the oss value alone.
|
|
101
|
+
entitlements: (env) => {
|
|
102
|
+
const capBytes = env.MAX_FILE_SIZE_MB * 1024 * 1024;
|
|
103
|
+
return {
|
|
104
|
+
actions: [{ key: 'files.upload', creditsPerUnit: 5, unit: 'bytes', label: 'Upload a file' }],
|
|
105
|
+
limits: { 'files.maxBytes': { oss: capBytes, free: Math.floor(capBytes / 5), pro: capBytes } },
|
|
106
|
+
features: { 'things.premium': { free: false, pro: true } },
|
|
107
|
+
routes: declareRouteEntitlements([
|
|
108
|
+
{
|
|
109
|
+
route: fileUploadRoute,
|
|
110
|
+
meter: { key: 'files.upload', unit: 'bytes', quantity: auditedSizeBytes },
|
|
111
|
+
limit: { key: 'files.maxBytes', value: declaredContentLength }
|
|
112
|
+
}
|
|
113
|
+
])
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
mcp: {
|
|
117
|
+
registerTools: () => {},
|
|
118
|
+
instructions: (info) => `MCP endpoint of the "${info.instanceName}" instance.`,
|
|
119
|
+
errorHints: {},
|
|
120
|
+
scopes: { read: THINGS_SCOPES.read, write: THINGS_SCOPES.write }
|
|
121
|
+
},
|
|
122
|
+
copy: THINGS_COPY
|
|
123
|
+
};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
+
import type { StartedPostgreSqlContainer } from '@testcontainers/postgresql';
|
|
3
|
+
import {
|
|
4
|
+
createDatabase,
|
|
5
|
+
createTestApp,
|
|
6
|
+
extractCookie,
|
|
7
|
+
readJson,
|
|
8
|
+
startPostgres,
|
|
9
|
+
type TestApp
|
|
10
|
+
} from './helpers.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* PRDCT-1437 — the account-existence oracle, closed on both remaining doors.
|
|
14
|
+
*
|
|
15
|
+
* Door 1: minting a change-email link succeeds for ANY new address; consuming
|
|
16
|
+
* it used to answer a raw 500 when the address already had an account
|
|
17
|
+
* anywhere on the instance (the update died at the `user.email` UNIQUE
|
|
18
|
+
* constraint) versus a 302 when it did not — a mint-then-consume oracle for
|
|
19
|
+
* any owner, free on a "yes". The consume now answers the SAME observables on
|
|
20
|
+
* both branches: 302 to the callback, a session cookie for the target, no
|
|
21
|
+
* error param — the email just does not change on a collision.
|
|
22
|
+
*
|
|
23
|
+
* Door 2: the public invitation/collaborator lookups no longer carry
|
|
24
|
+
* `accountExists` (asserted in their own suites); this file pins door 1.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const OWNER = { email: 'owner@oracle.test', name: 'Oracle Owner', password: 'oracle-owner-pass-1' };
|
|
28
|
+
const MEMBER = { email: 'member@oracle.test', name: 'Oracle Member', password: 'oracle-member-pass-1' };
|
|
29
|
+
/** An account that exists on the instance but NOT in this workspace. */
|
|
30
|
+
const ELSEWHERE_EMAIL = 'elsewhere@oracle.test';
|
|
31
|
+
|
|
32
|
+
let container: StartedPostgreSqlContainer;
|
|
33
|
+
let app: TestApp;
|
|
34
|
+
let ownerCookie: string;
|
|
35
|
+
let memberId: string;
|
|
36
|
+
|
|
37
|
+
let ipCounter = 0;
|
|
38
|
+
const nextIp = () => `10.67.${Math.floor(ipCounter / 250)}.${(ipCounter++ % 250) + 1}`;
|
|
39
|
+
|
|
40
|
+
const json = (body: unknown, headers: Record<string, string> = {}) => ({
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: { 'content-type': 'application/json', 'x-forwarded-for': nextIp(), ...headers },
|
|
43
|
+
body: JSON.stringify(body)
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
async function memberEmail(): Promise<string> {
|
|
47
|
+
const { rows } = await app.db.pool.query<{ email: string }>(
|
|
48
|
+
`SELECT u.email FROM "user" u JOIN workspace_members m ON m.user_id = u.id WHERE m.id = $1`,
|
|
49
|
+
[memberId]
|
|
50
|
+
);
|
|
51
|
+
return rows[0]!.email;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Mint a change-email link for the member; must succeed (200). */
|
|
55
|
+
async function mint(newEmail: string): Promise<string> {
|
|
56
|
+
const res = await app.app.request(
|
|
57
|
+
`/api/v1/members/${memberId}/change-email-link`,
|
|
58
|
+
json({ newEmail }, { cookie: ownerCookie })
|
|
59
|
+
);
|
|
60
|
+
expect(res.status).toBe(200);
|
|
61
|
+
return (await readJson(res)).verifyUrl as string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface Observables {
|
|
65
|
+
status: number;
|
|
66
|
+
location: string | null;
|
|
67
|
+
hasSessionCookie: boolean;
|
|
68
|
+
hasErrorParam: boolean;
|
|
69
|
+
body: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Consume a link logged out; returns the FULL observable set a prober reads. */
|
|
73
|
+
async function consume(verifyUrl: string): Promise<Observables> {
|
|
74
|
+
const res = await app.app.request(verifyUrl, { headers: { 'x-forwarded-for': nextIp() } });
|
|
75
|
+
const location = res.headers.get('location');
|
|
76
|
+
const setCookie = res.headers.get('set-cookie') ?? '';
|
|
77
|
+
const body = res.status === 200 ? await res.text() : '';
|
|
78
|
+
return {
|
|
79
|
+
status: res.status,
|
|
80
|
+
location,
|
|
81
|
+
hasSessionCookie: /better-auth\.session_token=[^;]/.test(setCookie),
|
|
82
|
+
hasErrorParam: (location ?? '').includes('error='),
|
|
83
|
+
body
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Rewrite (or drop) the callbackURL query param on a minted verify URL. */
|
|
88
|
+
function withCallback(verifyUrl: string, callbackURL: string | null): string {
|
|
89
|
+
const u = new URL(verifyUrl, 'http://localhost:3000');
|
|
90
|
+
if (callbackURL === null) u.searchParams.delete('callbackURL');
|
|
91
|
+
else u.searchParams.set('callbackURL', callbackURL);
|
|
92
|
+
return u.pathname + u.search;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Every observable must agree between the taken and the free consume. */
|
|
96
|
+
function expectIdentical(taken: Observables, free: Observables): void {
|
|
97
|
+
expect(taken.status).toBe(free.status);
|
|
98
|
+
expect(taken.location).toBe(free.location);
|
|
99
|
+
expect(taken.hasSessionCookie).toBe(free.hasSessionCookie);
|
|
100
|
+
expect(taken.hasErrorParam).toBe(false);
|
|
101
|
+
expect(free.hasErrorParam).toBe(false);
|
|
102
|
+
expect(taken.body).toBe(free.body);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
beforeAll(async () => {
|
|
106
|
+
container = await startPostgres();
|
|
107
|
+
app = await createTestApp(await createDatabase(container, 'oracle_uniform'));
|
|
108
|
+
await app.app.request(
|
|
109
|
+
'/api/v1/setup',
|
|
110
|
+
json({ setupToken: 'integration-test-setup-token', instanceName: 'Oracle', owner: OWNER })
|
|
111
|
+
);
|
|
112
|
+
ownerCookie = extractCookie(
|
|
113
|
+
await app.app.request(
|
|
114
|
+
'/api/v1/auth/sign-in/email',
|
|
115
|
+
json({ email: OWNER.email, password: OWNER.password })
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// The member whose email the owner "changes" while probing.
|
|
120
|
+
const inv = await readJson(
|
|
121
|
+
await app.app.request(
|
|
122
|
+
'/api/v1/invitations',
|
|
123
|
+
json({ email: MEMBER.email, role: 'member' }, { cookie: ownerCookie })
|
|
124
|
+
)
|
|
125
|
+
);
|
|
126
|
+
const token = (inv.acceptUrl as string).split('/invite/')[1]!;
|
|
127
|
+
expect(
|
|
128
|
+
(
|
|
129
|
+
await app.app.request(
|
|
130
|
+
'/api/v1/invitations/accept',
|
|
131
|
+
json({ token, name: MEMBER.name, password: MEMBER.password })
|
|
132
|
+
)
|
|
133
|
+
).status
|
|
134
|
+
).toBe(200);
|
|
135
|
+
const members = await readJson(
|
|
136
|
+
await app.app.request('/api/v1/members', { headers: { cookie: ownerCookie } })
|
|
137
|
+
);
|
|
138
|
+
memberId = members.members.find((m: { email: string }) => m.email === MEMBER.email).id;
|
|
139
|
+
|
|
140
|
+
// The probed address: an account that exists on the instance but holds no
|
|
141
|
+
// membership in this workspace (another tenant's user, say) — so the mint's
|
|
142
|
+
// workspace-scoped advisory pre-check does NOT catch it and the collision
|
|
143
|
+
// would only surface at consumption, exactly the oracle's shape.
|
|
144
|
+
await app.db.pool.query(
|
|
145
|
+
`INSERT INTO "user" (id, name, email, email_verified, created_at, updated_at)
|
|
146
|
+
VALUES ('oracle-elsewhere-user', 'Elsewhere', $1, true, now(), now())`,
|
|
147
|
+
[ELSEWHERE_EMAIL]
|
|
148
|
+
);
|
|
149
|
+
}, 120_000);
|
|
150
|
+
|
|
151
|
+
afterAll(async () => {
|
|
152
|
+
await app?.stop();
|
|
153
|
+
await container?.stop();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Consume, once for a FRESH unused address (the change goes through) and once
|
|
158
|
+
* for ELSEWHERE_EMAIL (a collision), under the SAME callbackURL shape, and
|
|
159
|
+
* assert every observable agrees. A counter hands each call a distinct fresh
|
|
160
|
+
* address, since every successful free consume renames the member.
|
|
161
|
+
*/
|
|
162
|
+
let freshCounter = 0;
|
|
163
|
+
async function bothWaysUnder(callbackURL: string | null): Promise<{ taken: Observables; free: Observables }> {
|
|
164
|
+
const fresh = `fresh${freshCounter++}@oracle.test`;
|
|
165
|
+
const free = await consume(withCallback(await mint(fresh), callbackURL));
|
|
166
|
+
const taken = await consume(withCallback(await mint(ELSEWHERE_EMAIL), callbackURL));
|
|
167
|
+
return { taken, free };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
describe('the change-email consume answers uniformly (door 1)', () => {
|
|
171
|
+
it('the minted shape (relative callbackURL): taken ≡ free, and only free renames the member', async () => {
|
|
172
|
+
const before = await memberEmail();
|
|
173
|
+
const { taken, free } = await bothWaysUnder('/account');
|
|
174
|
+
expectIdentical(taken, free);
|
|
175
|
+
expect(free.status).toBeGreaterThanOrEqual(300);
|
|
176
|
+
expect(free.status).toBeLessThan(400);
|
|
177
|
+
// The free consume renamed the member; the collision left both accounts.
|
|
178
|
+
expect(await memberEmail()).not.toBe(before);
|
|
179
|
+
const { rows } = await app.db.pool.query(`SELECT 1 FROM "user" WHERE email = $1`, [ELSEWHERE_EMAIL]);
|
|
180
|
+
expect(rows.length).toBe(1);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('Repro A — no callbackURL (the JSON path): taken ≡ free, both user:null (no user record leaks)', async () => {
|
|
184
|
+
const { taken, free } = await bothWaysUnder(null);
|
|
185
|
+
expectIdentical(taken, free);
|
|
186
|
+
expect(free.status).toBe(200);
|
|
187
|
+
// The free JSON must be normalized to user:null — a leaked user record is
|
|
188
|
+
// the whole oracle this repro exposed.
|
|
189
|
+
expect(JSON.parse(free.body)).toEqual({ status: true, user: null });
|
|
190
|
+
expect(JSON.parse(taken.body)).toEqual({ status: true, user: null });
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('Repro B — absolute SAME-ORIGIN callbackURL: taken ≡ free (both redirect, no oracle)', async () => {
|
|
194
|
+
const { taken, free } = await bothWaysUnder('http://localhost:3000/account');
|
|
195
|
+
expectIdentical(taken, free);
|
|
196
|
+
expect(free.status).toBeGreaterThanOrEqual(300);
|
|
197
|
+
expect(free.status).toBeLessThan(400);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// CAVEAT: this harness runs with NODE_ENV=test, which makes Better Auth
|
|
201
|
+
// skip ITS OWN callbackURL origin check — so these two assertions exercise
|
|
202
|
+
// safeRedirectLocation (our defence-in-depth layer) alone, not production's
|
|
203
|
+
// stacked guards. Do not read them as proof the upstream guard works.
|
|
204
|
+
it('an untrusted absolute callbackURL is refused IDENTICALLY on both branches (no open redirect)', async () => {
|
|
205
|
+
const { taken, free } = await bothWaysUnder('http://evil.example/x');
|
|
206
|
+
expect(taken.status).toBe(free.status);
|
|
207
|
+
expect(taken.location).toBe(free.location);
|
|
208
|
+
for (const o of [taken, free]) {
|
|
209
|
+
expect(o.location ?? '').not.toContain('evil.example');
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('a tab-smuggled protocol-relative callbackURL never redirects off-origin, and both branches agree', async () => {
|
|
214
|
+
const { taken, free } = await bothWaysUnder('/\t/evil.example');
|
|
215
|
+
expect(taken.status).toBe(free.status);
|
|
216
|
+
expect(taken.location).toBe(free.location);
|
|
217
|
+
for (const o of [taken, free]) {
|
|
218
|
+
// The one thing that must never happen: a Location resolving off-origin.
|
|
219
|
+
const loc = o.location;
|
|
220
|
+
if (loc) {
|
|
221
|
+
const resolved = new URL(loc, 'http://localhost:3000');
|
|
222
|
+
expect(resolved.origin).toBe('http://localhost:3000');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('never answers 5xx on the consume path, and the collision-branch session authenticates the target', async () => {
|
|
228
|
+
const res = await app.app.request(withCallback(await mint(ELSEWHERE_EMAIL), '/account'), {
|
|
229
|
+
headers: { 'x-forwarded-for': nextIp() }
|
|
230
|
+
});
|
|
231
|
+
expect(res.status).toBeLessThan(500);
|
|
232
|
+
// The link is sign-in-equivalent by design (LESSONS M6) — on the collision
|
|
233
|
+
// branch too, and for the TARGET member, never the probed account.
|
|
234
|
+
const cookie = extractCookie(res);
|
|
235
|
+
const me = await readJson(await app.app.request('/api/v1/me', { headers: { cookie } }));
|
|
236
|
+
expect(me.user.email).toBe(await memberEmail());
|
|
237
|
+
expect(me.user.email).not.toBe(ELSEWHERE_EMAIL);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('an invalid token keeps its ordinary error redirect (uniformity never hides real failures)', async () => {
|
|
241
|
+
const res = await app.app.request('/api/v1/auth/verify-email?token=not-a-jwt&callbackURL=%2Faccount', {
|
|
242
|
+
headers: { 'x-forwarded-for': nextIp() }
|
|
243
|
+
});
|
|
244
|
+
expect(res.status).toBeGreaterThanOrEqual(300);
|
|
245
|
+
expect(res.status).toBeLessThan(400);
|
|
246
|
+
expect(res.headers.get('location')).toContain('error=');
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
/** Mint an invitation and return its accept token. */
|
|
251
|
+
async function inviteToken(email: string): Promise<string> {
|
|
252
|
+
const inv = await readJson(
|
|
253
|
+
await app.app.request('/api/v1/invitations', json({ email, role: 'member' }, { cookie: ownerCookie }))
|
|
254
|
+
);
|
|
255
|
+
return (inv.acceptUrl as string).split('/invite/')[1]!;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
describe('the invitation accept answers uniformly to a credential-less probe (door 2)', () => {
|
|
259
|
+
it('existing and fresh emails answer credentials_required alike; existence surfaces only on a committed create', async () => {
|
|
260
|
+
// ELSEWHERE_EMAIL has an account on the instance; the fresh one does not.
|
|
261
|
+
const takenToken = await inviteToken(ELSEWHERE_EMAIL);
|
|
262
|
+
const freshToken = await inviteToken('door2-fresh@oracle.test');
|
|
263
|
+
|
|
264
|
+
const probe = (token: string, body: Record<string, unknown> = {}) =>
|
|
265
|
+
app.app.request('/api/v1/invitations/accept', json({ token, ...body }));
|
|
266
|
+
|
|
267
|
+
// Credential-less: the account-existence bit is not readable for free —
|
|
268
|
+
// same status, same code on both. (The old oracle answered 409
|
|
269
|
+
// account_exists for the existing email, 400 for the fresh one.)
|
|
270
|
+
const taken = await probe(takenToken);
|
|
271
|
+
const fresh = await probe(freshToken);
|
|
272
|
+
expect(taken.status).toBe(fresh.status);
|
|
273
|
+
expect(taken.status).toBe(400);
|
|
274
|
+
expect((await readJson(taken)).error.code).toBe('credentials_required');
|
|
275
|
+
expect((await readJson(fresh)).error.code).toBe('credentials_required');
|
|
276
|
+
|
|
277
|
+
// Existence surfaces ONLY after real credentials are committed — the
|
|
278
|
+
// inherent signup collision, not a free pre-credential probe. The invite
|
|
279
|
+
// stays alive (nothing created on the collision branch).
|
|
280
|
+
const withCreds = await probe(takenToken, { name: 'Probe', password: 'a-probe-password-123' });
|
|
281
|
+
expect(withCreds.status).toBe(409);
|
|
282
|
+
expect((await readJson(withCreds)).error.code).toBe('account_exists');
|
|
283
|
+
});
|
|
284
|
+
});
|