@bajustone/fortress 1.0.0-rc.1
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/CHANGELOG.md +1011 -0
- package/LICENSE +21 -0
- package/README.md +760 -0
- package/SECURITY.md +197 -0
- package/bin/fortress.ts +667 -0
- package/dist/auth-service-BcyQ2PuZ.d.cts +307 -0
- package/dist/auth-service-BkzZkWfH.d.ts +307 -0
- package/dist/config-B2366s_G.d.ts +665 -0
- package/dist/config-GtlVt6ZD.d.cts +665 -0
- package/dist/convert-routes-BLCQT57f.d.ts +72 -0
- package/dist/convert-routes-BdMvP2_X.d.cts +72 -0
- package/dist/crypto.cjs +61 -0
- package/dist/crypto.d.cts +36 -0
- package/dist/crypto.d.ts +36 -0
- package/dist/crypto.js +35 -0
- package/dist/drift-BT1wtMDJ.d.cts +22 -0
- package/dist/drift-k9LiYpRP.d.ts +22 -0
- package/dist/drizzle/pg.cjs +481 -0
- package/dist/drizzle/pg.d.cts +15 -0
- package/dist/drizzle/pg.d.ts +15 -0
- package/dist/drizzle/pg.js +454 -0
- package/dist/drizzle.cjs +1442 -0
- package/dist/drizzle.d.cts +85 -0
- package/dist/drizzle.d.ts +85 -0
- package/dist/drizzle.js +1411 -0
- package/dist/express.cjs +1357 -0
- package/dist/express.d.cts +333 -0
- package/dist/express.d.ts +333 -0
- package/dist/express.js +1314 -0
- package/dist/fetcher.cjs +77 -0
- package/dist/fetcher.d.cts +7 -0
- package/dist/fetcher.d.ts +7 -0
- package/dist/fetcher.js +41 -0
- package/dist/fortress-BmSvFfqK.d.cts +1089 -0
- package/dist/fortress-uA-_cheR.d.ts +1089 -0
- package/dist/hono.cjs +1530 -0
- package/dist/hono.d.cts +514 -0
- package/dist/hono.d.ts +514 -0
- package/dist/hono.js +1483 -0
- package/dist/index-CxEkfCA0.d.cts +77 -0
- package/dist/index-CxEkfCA0.d.ts +77 -0
- package/dist/index-D054pcb-.d.cts +146 -0
- package/dist/index-jAMbbUAY.d.ts +146 -0
- package/dist/index.cjs +9046 -0
- package/dist/index.d.cts +717 -0
- package/dist/index.d.ts +717 -0
- package/dist/index.js +8935 -0
- package/dist/jwt.cjs +255 -0
- package/dist/jwt.d.cts +90 -0
- package/dist/jwt.d.ts +90 -0
- package/dist/jwt.js +227 -0
- package/dist/otel.cjs +108 -0
- package/dist/otel.d.cts +62 -0
- package/dist/otel.d.ts +62 -0
- package/dist/otel.js +73 -0
- package/dist/plugins/account-lockout.cjs +322 -0
- package/dist/plugins/account-lockout.d.cts +42 -0
- package/dist/plugins/account-lockout.d.ts +42 -0
- package/dist/plugins/account-lockout.js +295 -0
- package/dist/plugins/admin.cjs +2378 -0
- package/dist/plugins/admin.d.cts +72 -0
- package/dist/plugins/admin.d.ts +72 -0
- package/dist/plugins/admin.js +2351 -0
- package/dist/plugins/api-key.cjs +792 -0
- package/dist/plugins/api-key.d.cts +121 -0
- package/dist/plugins/api-key.d.ts +121 -0
- package/dist/plugins/api-key.js +765 -0
- package/dist/plugins/audit-log.cjs +493 -0
- package/dist/plugins/audit-log.d.cts +86 -0
- package/dist/plugins/audit-log.d.ts +86 -0
- package/dist/plugins/audit-log.js +468 -0
- package/dist/plugins/data-isolation.cjs +211 -0
- package/dist/plugins/data-isolation.d.cts +49 -0
- package/dist/plugins/data-isolation.d.ts +49 -0
- package/dist/plugins/data-isolation.js +186 -0
- package/dist/plugins/email-verification.cjs +273 -0
- package/dist/plugins/email-verification.d.cts +44 -0
- package/dist/plugins/email-verification.d.ts +44 -0
- package/dist/plugins/email-verification.js +246 -0
- package/dist/plugins/magic-link.cjs +231 -0
- package/dist/plugins/magic-link.d.cts +39 -0
- package/dist/plugins/magic-link.d.ts +39 -0
- package/dist/plugins/magic-link.js +204 -0
- package/dist/plugins/oauth.cjs +1696 -0
- package/dist/plugins/oauth.d.cts +406 -0
- package/dist/plugins/oauth.d.ts +406 -0
- package/dist/plugins/oauth.js +1669 -0
- package/dist/plugins/openapi.cjs +1185 -0
- package/dist/plugins/openapi.d.cts +6 -0
- package/dist/plugins/openapi.d.ts +6 -0
- package/dist/plugins/openapi.js +1158 -0
- package/dist/plugins/rate-limit/express.cjs +55 -0
- package/dist/plugins/rate-limit/express.d.cts +64 -0
- package/dist/plugins/rate-limit/express.d.ts +64 -0
- package/dist/plugins/rate-limit/express.js +30 -0
- package/dist/plugins/rate-limit/hono.cjs +51 -0
- package/dist/plugins/rate-limit/hono.d.cts +59 -0
- package/dist/plugins/rate-limit/hono.d.ts +59 -0
- package/dist/plugins/rate-limit/hono.js +26 -0
- package/dist/plugins/rate-limit/sveltekit.cjs +49 -0
- package/dist/plugins/rate-limit/sveltekit.d.cts +59 -0
- package/dist/plugins/rate-limit/sveltekit.d.ts +59 -0
- package/dist/plugins/rate-limit/sveltekit.js +24 -0
- package/dist/plugins/rate-limit.cjs +354 -0
- package/dist/plugins/rate-limit.d.cts +140 -0
- package/dist/plugins/rate-limit.d.ts +140 -0
- package/dist/plugins/rate-limit.js +325 -0
- package/dist/plugins/social-login.cjs +905 -0
- package/dist/plugins/social-login.d.cts +114 -0
- package/dist/plugins/social-login.d.ts +114 -0
- package/dist/plugins/social-login.js +880 -0
- package/dist/plugins/tenancy.cjs +780 -0
- package/dist/plugins/tenancy.d.cts +108 -0
- package/dist/plugins/tenancy.d.ts +108 -0
- package/dist/plugins/tenancy.js +753 -0
- package/dist/plugins/two-factor.cjs +555 -0
- package/dist/plugins/two-factor.d.cts +67 -0
- package/dist/plugins/two-factor.d.ts +67 -0
- package/dist/plugins/two-factor.js +526 -0
- package/dist/plugins/webauthn.cjs +786 -0
- package/dist/plugins/webauthn.d.cts +72 -0
- package/dist/plugins/webauthn.d.ts +72 -0
- package/dist/plugins/webauthn.js +766 -0
- package/dist/plugins/webhook.cjs +819 -0
- package/dist/plugins/webhook.d.cts +254 -0
- package/dist/plugins/webhook.d.ts +254 -0
- package/dist/plugins/webhook.js +789 -0
- package/dist/protect-D1v_0upK.d.cts +123 -0
- package/dist/protect-DsxV_-dJ.d.ts +123 -0
- package/dist/sveltekit.cjs +1258 -0
- package/dist/sveltekit.d.cts +420 -0
- package/dist/sveltekit.d.ts +420 -0
- package/dist/sveltekit.js +1207 -0
- package/dist/testing.cjs +4294 -0
- package/dist/testing.d.cts +197 -0
- package/dist/testing.d.ts +197 -0
- package/dist/testing.js +4264 -0
- package/dist/types-et0R8tsC.d.cts +217 -0
- package/dist/types-et0R8tsC.d.ts +217 -0
- package/docs/adapter-typed-helpers.md +192 -0
- package/docs/admin-recipes.md +227 -0
- package/docs/architecture.md +434 -0
- package/docs/ci/github-actions.yml +59 -0
- package/docs/ci.md +109 -0
- package/docs/compatibility.md +115 -0
- package/docs/deployment.md +305 -0
- package/docs/hardening.md +118 -0
- package/docs/host-owned-routes.md +154 -0
- package/docs/migrations/0001-schema-version.md +54 -0
- package/docs/migrations/0002-initial-schema.md +84 -0
- package/docs/migrations/upgrade-guide.md +160 -0
- package/docs/observability.md +394 -0
- package/docs/plugins/account-lockout.md +131 -0
- package/docs/plugins/admin.md +402 -0
- package/docs/plugins/api-key.md +327 -0
- package/docs/plugins/audit-log.md +261 -0
- package/docs/plugins/data-isolation.md +186 -0
- package/docs/plugins/email-verification.md +121 -0
- package/docs/plugins/magic-link.md +123 -0
- package/docs/plugins/oauth.md +544 -0
- package/docs/plugins/openapi.md +250 -0
- package/docs/plugins/rate-limit.md +223 -0
- package/docs/plugins/social-login.md +337 -0
- package/docs/plugins/tenancy.md +122 -0
- package/docs/plugins/two-factor.md +191 -0
- package/docs/plugins/webauthn.md +188 -0
- package/docs/plugins/webhook.md +242 -0
- package/docs/policy-as-code.md +156 -0
- package/docs/route-manifest.md +46 -0
- package/docs/security.md +261 -0
- package/docs/threat-model.md +161 -0
- package/examples/README.md +119 -0
- package/examples/express-app/index.ts +747 -0
- package/examples/hono-app/docker-compose.yml +14 -0
- package/examples/hono-app/index.ts +1009 -0
- package/examples/policy/fortress.policy.json +47 -0
- package/examples/sveltekit-app/README.md +125 -0
- package/examples/sveltekit-app/src/app.d.ts +16 -0
- package/examples/sveltekit-app/src/hooks.server.ts +23 -0
- package/examples/sveltekit-app/src/lib/server/fortress.ts +81 -0
- package/examples/sveltekit-app/src/routes/api/echo/[id]/+server.ts +32 -0
- package/examples/sveltekit-app/src/routes/api/fortress/[...path]/+server.ts +15 -0
- package/examples/sveltekit-app/src/routes/dashboard/+page.server.ts +20 -0
- package/examples/sveltekit-app/src/routes/login/+page.server.ts +48 -0
- package/examples/sveltekit-app/src/routes/oauth/consent/+page.server.ts +69 -0
- package/examples/sveltekit-app/src/routes/oauth/consent/+page.svelte +83 -0
- package/migrations/pg/0001_schema_version.down.sql +2 -0
- package/migrations/pg/0001_schema_version.sql +8 -0
- package/migrations/pg/0002_initial_schema.down.sql +36 -0
- package/migrations/pg/0002_initial_schema.sql +376 -0
- package/migrations/pg/0003_auth_continuation.down.sql +6 -0
- package/migrations/pg/0003_auth_continuation.sql +30 -0
- package/migrations/pg/0004_tenant_default_unique.down.sql +1 -0
- package/migrations/pg/0004_tenant_default_unique.sql +14 -0
- package/migrations/pg/0005_hot_indexes_timestamptz.down.sql +71 -0
- package/migrations/pg/0005_hot_indexes_timestamptz.sql +71 -0
- package/migrations/pg/0006_canonical_email.down.sql +3 -0
- package/migrations/pg/0006_canonical_email.sql +8 -0
- package/migrations/pg/0007_audit_chain_anchor.down.sql +1 -0
- package/migrations/pg/0007_audit_chain_anchor.sql +8 -0
- package/migrations/pg/0008_two_factor_hardening.down.sql +8 -0
- package/migrations/pg/0008_two_factor_hardening.sql +8 -0
- package/migrations/pg/0009_encrypt_totp_secrets.down.sql +2 -0
- package/migrations/pg/0009_encrypt_totp_secrets.sql +5 -0
- package/migrations/pg/0010_bigint_append_only_ids.down.sql +2 -0
- package/migrations/pg/0010_bigint_append_only_ids.sql +23 -0
- package/migrations/sqlite/0001_schema_version.down.sql +2 -0
- package/migrations/sqlite/0001_schema_version.sql +8 -0
- package/migrations/sqlite/0002_initial_schema.down.sql +36 -0
- package/migrations/sqlite/0002_initial_schema.sql +376 -0
- package/migrations/sqlite/0003_auth_continuation.down.sql +27 -0
- package/migrations/sqlite/0003_auth_continuation.sql +45 -0
- package/migrations/sqlite/0004_tenant_default_unique.down.sql +1 -0
- package/migrations/sqlite/0004_tenant_default_unique.sql +13 -0
- package/migrations/sqlite/0005_hot_indexes_timestamptz.down.sql +10 -0
- package/migrations/sqlite/0005_hot_indexes_timestamptz.sql +10 -0
- package/migrations/sqlite/0006_canonical_email.down.sql +3 -0
- package/migrations/sqlite/0006_canonical_email.sql +8 -0
- package/migrations/sqlite/0007_audit_chain_anchor.down.sql +1 -0
- package/migrations/sqlite/0007_audit_chain_anchor.sql +8 -0
- package/migrations/sqlite/0008_two_factor_hardening.down.sql +14 -0
- package/migrations/sqlite/0008_two_factor_hardening.sql +7 -0
- package/migrations/sqlite/0009_encrypt_totp_secrets.down.sql +2 -0
- package/migrations/sqlite/0009_encrypt_totp_secrets.sql +5 -0
- package/migrations/sqlite/0010_bigint_append_only_ids.down.sql +1 -0
- package/migrations/sqlite/0010_bigint_append_only_ids.sql +2 -0
- package/package.json +398 -0
- package/src/adapters/database/index.ts +63 -0
- package/src/adapters/database/types.ts +22 -0
- package/src/changelog-script.test.ts +21 -0
- package/src/cli.test.ts +79 -0
- package/src/core/auth/auth-admin.test.ts +247 -0
- package/src/core/auth/auth-endpoints.ts +558 -0
- package/src/core/auth/auth-observer.test.ts +191 -0
- package/src/core/auth/auth-service.ts +1464 -0
- package/src/core/auth/email.test.ts +17 -0
- package/src/core/auth/email.ts +11 -0
- package/src/core/auth/hooks.test.ts +251 -0
- package/src/core/auth/impersonation.test.ts +179 -0
- package/src/core/auth/jwt.test.ts +184 -0
- package/src/core/auth/jwt.ts +239 -0
- package/src/core/auth/login-timing.test.ts +77 -0
- package/src/core/auth/password-policy.test.ts +253 -0
- package/src/core/auth/password-policy.ts +220 -0
- package/src/core/auth/password.test.ts +42 -0
- package/src/core/auth/password.ts +62 -0
- package/src/core/auth/post-auth-gate.test.ts +258 -0
- package/src/core/auth/post-auth-gate.ts +228 -0
- package/src/core/auth/refresh-token.test.ts +86 -0
- package/src/core/auth/refresh-token.ts +105 -0
- package/src/core/auth/timing-safe.ts +23 -0
- package/src/core/config.ts +212 -0
- package/src/core/endpoint.ts +149 -0
- package/src/core/errors.ts +199 -0
- package/src/core/fetcher-interop.test.ts +106 -0
- package/src/core/fortress.test.ts +354 -0
- package/src/core/fortress.ts +550 -0
- package/src/core/http/call.test.ts +148 -0
- package/src/core/http/call.ts +149 -0
- package/src/core/http/cookie-serialize.test.ts +198 -0
- package/src/core/http/cookie-serialize.ts +107 -0
- package/src/core/http/csrf.test.ts +140 -0
- package/src/core/http/csrf.ts +173 -0
- package/src/core/http/dispatch.ts +652 -0
- package/src/core/http/error-response.test.ts +69 -0
- package/src/core/http/error-response.ts +93 -0
- package/src/core/http/fortress-rbac.test.ts +43 -0
- package/src/core/http/fortress-rbac.ts +127 -0
- package/src/core/http/handle-request.test.ts +441 -0
- package/src/core/http/handle-request.ts +354 -0
- package/src/core/http/match.test.ts +122 -0
- package/src/core/http/match.ts +126 -0
- package/src/core/http/outbound.test.ts +34 -0
- package/src/core/http/outbound.ts +105 -0
- package/src/core/http/plugin-middleware.ts +67 -0
- package/src/core/http/principal.test.ts +345 -0
- package/src/core/http/principal.ts +86 -0
- package/src/core/http/protect.test.ts +220 -0
- package/src/core/http/protect.ts +394 -0
- package/src/core/http/token-extraction.test.ts +59 -0
- package/src/core/http/token-extraction.ts +53 -0
- package/src/core/iam/explain.test.ts +177 -0
- package/src/core/iam/explain.ts +302 -0
- package/src/core/iam/iam-endpoints.ts +779 -0
- package/src/core/iam/iam-service.test.ts +829 -0
- package/src/core/iam/iam-service.ts +1137 -0
- package/src/core/iam/permission-cache.test.ts +115 -0
- package/src/core/iam/permission-cache.ts +71 -0
- package/src/core/iam/permission-check-observer.test.ts +90 -0
- package/src/core/iam/permission-evaluator.test.ts +291 -0
- package/src/core/iam/permission-evaluator.ts +198 -0
- package/src/core/iam/permission-sync.test.ts +166 -0
- package/src/core/iam/permission-sync.ts +192 -0
- package/src/core/iam/resource-sync.test.ts +70 -0
- package/src/core/iam/resource-sync.ts +182 -0
- package/src/core/iam/service-account-http.test.ts +529 -0
- package/src/core/iam/service-account.test.ts +282 -0
- package/src/core/internal-adapter.test.ts +389 -0
- package/src/core/internal-adapter.ts +435 -0
- package/src/core/json-schema.ts +50 -0
- package/src/core/manifest/__snapshots__/route-manifest.test.ts.snap +192 -0
- package/src/core/manifest/drift.ts +103 -0
- package/src/core/manifest/route-manifest.test.ts +142 -0
- package/src/core/manifest/route-manifest.ts +154 -0
- package/src/core/migrate.test.ts +72 -0
- package/src/core/migrations/engine.test.ts +308 -0
- package/src/core/migrations/engine.ts +548 -0
- package/src/core/migrations/migrations.ts +1771 -0
- package/src/core/migrations/pg-migration.integration-test.ts +353 -0
- package/src/core/migrations/upgrade-fixture.test.ts +378 -0
- package/src/core/observability/db-instrumentation.ts +205 -0
- package/src/core/observability/listener-list.test.ts +124 -0
- package/src/core/observability/listener-list.ts +73 -0
- package/src/core/observability/logger.test.ts +43 -0
- package/src/core/observability/logger.ts +49 -0
- package/src/core/observability/spans.test.ts +193 -0
- package/src/core/observability/types.ts +80 -0
- package/src/core/openapi-drift.test.ts +41 -0
- package/src/core/openapi.ts +47 -0
- package/src/core/plugin-methods-map.ts +75 -0
- package/src/core/plugin-runner.test.ts +233 -0
- package/src/core/plugin-runner.ts +276 -0
- package/src/core/plugin.ts +210 -0
- package/src/core/policy/apply.ts +272 -0
- package/src/core/policy/diff.ts +288 -0
- package/src/core/policy/loader.test.ts +63 -0
- package/src/core/policy/loader.ts +214 -0
- package/src/core/policy/policy.test.ts +232 -0
- package/src/core/policy/types.ts +105 -0
- package/src/core/schema-builder.test.ts +660 -0
- package/src/core/schema-builder.ts +881 -0
- package/src/core/standard-schema.ts +56 -0
- package/src/core/types.ts +258 -0
- package/src/core/validation.test.ts +195 -0
- package/src/core/validation.ts +192 -0
- package/src/drizzle/adapter.test.ts +425 -0
- package/src/drizzle/adapter.ts +474 -0
- package/src/drizzle/index.ts +31 -0
- package/src/drizzle/pg/adapter.integration-test.ts +456 -0
- package/src/drizzle/pg/index.ts +13 -0
- package/src/drizzle/pg/pg.integration-test.ts +1539 -0
- package/src/drizzle/pg/schema.ts +539 -0
- package/src/drizzle/pg-error-map.test.ts +218 -0
- package/src/drizzle/pg-error-map.ts +151 -0
- package/src/drizzle/schema.ts +544 -0
- package/src/drizzle/sqlite-serialization.test.ts +106 -0
- package/src/express/express-api-key-user-routes.test.ts +241 -0
- package/src/express/express.test.ts +442 -0
- package/src/express/handle.ts +191 -0
- package/src/express/index.ts +62 -0
- package/src/express/middleware.ts +551 -0
- package/src/express/protect.ts +154 -0
- package/src/express/validated.test.ts +86 -0
- package/src/express/validated.ts +99 -0
- package/src/fetcher/index.ts +81 -0
- package/src/hono/convert-routes.test.ts +220 -0
- package/src/hono/convert-routes.ts +196 -0
- package/src/hono/converters.test.ts +50 -0
- package/src/hono/converters.ts +43 -0
- package/src/hono/handle.ts +79 -0
- package/src/hono/helpers.ts +2 -0
- package/src/hono/hono-api-key-user-routes.test.ts +225 -0
- package/src/hono/hono-handlers.test.ts +861 -0
- package/src/hono/hono.test.ts +454 -0
- package/src/hono/index.ts +101 -0
- package/src/hono/middleware/auth.ts +236 -0
- package/src/hono/middleware/auth.types.test.ts +94 -0
- package/src/hono/middleware/csrf.test.ts +127 -0
- package/src/hono/middleware/csrf.ts +68 -0
- package/src/hono/middleware/error-handler.ts +12 -0
- package/src/hono/middleware/plugin-middleware.ts +35 -0
- package/src/hono/middleware/rbac.ts +131 -0
- package/src/hono/middleware/security-headers.test.ts +88 -0
- package/src/hono/middleware/security-headers.ts +68 -0
- package/src/hono/openapi.ts +237 -0
- package/src/hono/protect.ts +87 -0
- package/src/hono/validated.test.ts +123 -0
- package/src/hono/validated.ts +62 -0
- package/src/index.ts +309 -0
- package/src/integration.test.ts +718 -0
- package/src/internal/changelog.ts +56 -0
- package/src/otel/index.ts +158 -0
- package/src/otel/otel-types.test.ts +35 -0
- package/src/otel/otel.test.ts +235 -0
- package/src/plugins/account-lockout/account-lockout.test.ts +367 -0
- package/src/plugins/account-lockout/index.ts +267 -0
- package/src/plugins/admin/admin-api-key.test.ts +438 -0
- package/src/plugins/admin/index.ts +1612 -0
- package/src/plugins/api-key/api-key.test.ts +684 -0
- package/src/plugins/api-key/core.ts +336 -0
- package/src/plugins/api-key/index.ts +315 -0
- package/src/plugins/audit-log/audit-log.test.ts +749 -0
- package/src/plugins/audit-log/index.ts +680 -0
- package/src/plugins/data-isolation/data-isolation.test.ts +197 -0
- package/src/plugins/data-isolation/index.ts +157 -0
- package/src/plugins/email-verification/email-verification.test.ts +199 -0
- package/src/plugins/email-verification/index.ts +190 -0
- package/src/plugins/magic-link/index.ts +129 -0
- package/src/plugins/magic-link/magic-link.test.ts +156 -0
- package/src/plugins/oauth/id-token.ts +86 -0
- package/src/plugins/oauth/index.ts +2145 -0
- package/src/plugins/oauth/jwks.test.ts +32 -0
- package/src/plugins/oauth/jwks.ts +182 -0
- package/src/plugins/oauth/oauth.test.ts +2220 -0
- package/src/plugins/oauth/pkce.ts +58 -0
- package/src/plugins/openapi/index.ts +298 -0
- package/src/plugins/openapi/openapi.test.ts +425 -0
- package/src/plugins/openapi/spec-builder.ts +287 -0
- package/src/plugins/rate-limit/express.test.ts +89 -0
- package/src/plugins/rate-limit/express.ts +86 -0
- package/src/plugins/rate-limit/hono.test.ts +60 -0
- package/src/plugins/rate-limit/hono.ts +74 -0
- package/src/plugins/rate-limit/index.ts +383 -0
- package/src/plugins/rate-limit/memory-store.ts +61 -0
- package/src/plugins/rate-limit/rate-limit.test.ts +756 -0
- package/src/plugins/rate-limit/sveltekit.test.ts +58 -0
- package/src/plugins/rate-limit/sveltekit.ts +66 -0
- package/src/plugins/social-login/index.ts +715 -0
- package/src/plugins/social-login/providers/apple.ts +34 -0
- package/src/plugins/social-login/providers/discord.ts +26 -0
- package/src/plugins/social-login/providers/github.ts +54 -0
- package/src/plugins/social-login/providers/google.ts +23 -0
- package/src/plugins/social-login/providers/index.ts +22 -0
- package/src/plugins/social-login/providers/microsoft.ts +35 -0
- package/src/plugins/social-login/providers/oidc.ts +37 -0
- package/src/plugins/social-login/providers/providers.test.ts +211 -0
- package/src/plugins/social-login/social-login.test.ts +675 -0
- package/src/plugins/social-login/types.ts +80 -0
- package/src/plugins/tenancy/index.ts +544 -0
- package/src/plugins/tenancy/tenancy.test.ts +323 -0
- package/src/plugins/two-factor/index.ts +569 -0
- package/src/plugins/two-factor/two-factor.test.ts +235 -0
- package/src/plugins/webauthn/index.ts +554 -0
- package/src/plugins/webauthn/webauthn.test.ts +472 -0
- package/src/plugins/webhook/builtin-events.ts +29 -0
- package/src/plugins/webhook/delivery.test.ts +51 -0
- package/src/plugins/webhook/delivery.ts +154 -0
- package/src/plugins/webhook/hooks.ts +89 -0
- package/src/plugins/webhook/index.ts +445 -0
- package/src/plugins/webhook/queue/database.ts +67 -0
- package/src/plugins/webhook/queue/in-memory.test.ts +48 -0
- package/src/plugins/webhook/queue/in-memory.ts +71 -0
- package/src/plugins/webhook/queue/types.ts +51 -0
- package/src/plugins/webhook/registry.test.ts +48 -0
- package/src/plugins/webhook/registry.ts +64 -0
- package/src/plugins/webhook/signing.ts +45 -0
- package/src/plugins/webhook/ssrf.ts +198 -0
- package/src/plugins/webhook/types.ts +138 -0
- package/src/plugins/webhook/webhook.test.ts +324 -0
- package/src/sveltekit/actions.ts +233 -0
- package/src/sveltekit/catch-all.ts +43 -0
- package/src/sveltekit/cookies.ts +136 -0
- package/src/sveltekit/handle.ts +356 -0
- package/src/sveltekit/helpers.ts +69 -0
- package/src/sveltekit/index.ts +74 -0
- package/src/sveltekit/protect.ts +80 -0
- package/src/sveltekit/sveltekit-types.test.ts +31 -0
- package/src/sveltekit/sveltekit.test.ts +799 -0
- package/src/sveltekit/types.ts +134 -0
- package/src/sveltekit/validated.test.ts +117 -0
- package/src/sveltekit/validated.ts +78 -0
- package/src/testing/adapter-conformance.test.ts +408 -0
- package/src/testing/checks.test.ts +124 -0
- package/src/testing/checks.ts +304 -0
- package/src/testing/index.ts +107 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- Widen identifiers on unbounded/churn-heavy append tables before int4 exhaustion.
|
|
2
|
+
ALTER SEQUENCE fortress_refresh_token_id_seq AS BIGINT;
|
|
3
|
+
ALTER TABLE fortress_refresh_token ALTER COLUMN id TYPE BIGINT;
|
|
4
|
+
ALTER SEQUENCE fortress_auth_continuation_id_seq AS BIGINT;
|
|
5
|
+
ALTER TABLE fortress_auth_continuation ALTER COLUMN id TYPE BIGINT;
|
|
6
|
+
ALTER SEQUENCE fortress_email_verification_token_id_seq AS BIGINT;
|
|
7
|
+
ALTER TABLE fortress_email_verification_token ALTER COLUMN id TYPE BIGINT;
|
|
8
|
+
ALTER SEQUENCE fortress_magic_link_token_id_seq AS BIGINT;
|
|
9
|
+
ALTER TABLE fortress_magic_link_token ALTER COLUMN id TYPE BIGINT;
|
|
10
|
+
ALTER SEQUENCE fortress_oauth_authorization_code_id_seq AS BIGINT;
|
|
11
|
+
ALTER TABLE fortress_oauth_authorization_code ALTER COLUMN id TYPE BIGINT;
|
|
12
|
+
ALTER SEQUENCE fortress_oauth_access_token_id_seq AS BIGINT;
|
|
13
|
+
ALTER TABLE fortress_oauth_access_token ALTER COLUMN id TYPE BIGINT;
|
|
14
|
+
ALTER SEQUENCE fortress_oauth_refresh_token_id_seq AS BIGINT;
|
|
15
|
+
ALTER TABLE fortress_oauth_refresh_token ALTER COLUMN id TYPE BIGINT;
|
|
16
|
+
ALTER SEQUENCE fortress_oauth_pending_flow_id_seq AS BIGINT;
|
|
17
|
+
ALTER TABLE fortress_oauth_pending_flow ALTER COLUMN id TYPE BIGINT;
|
|
18
|
+
ALTER SEQUENCE fortress_audit_log_id_seq AS BIGINT;
|
|
19
|
+
ALTER TABLE fortress_audit_log ALTER COLUMN id TYPE BIGINT;
|
|
20
|
+
ALTER SEQUENCE fortress_webhook_delivery_id_seq AS BIGINT;
|
|
21
|
+
ALTER TABLE fortress_webhook_delivery ALTER COLUMN id TYPE BIGINT;
|
|
22
|
+
ALTER SEQUENCE fortress_webauthn_challenge_id_seq AS BIGINT;
|
|
23
|
+
ALTER TABLE fortress_webauthn_challenge ALTER COLUMN id TYPE BIGINT;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Fortress migration 0001: schema version tracking table (SQLite)
|
|
2
|
+
-- The version row is written by the migration runner after apply; this
|
|
3
|
+
-- migration only creates the checkpoint table.
|
|
4
|
+
CREATE TABLE IF NOT EXISTS fortress_schema_version (
|
|
5
|
+
id INTEGER PRIMARY KEY DEFAULT 1 CHECK (id = 1),
|
|
6
|
+
version INTEGER NOT NULL,
|
|
7
|
+
applied_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
8
|
+
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- Fortress migration 0002: initial Fortress schema (SQLite) — rollback
|
|
2
|
+
|
|
3
|
+
DROP TABLE IF EXISTS fortress_webauthn_challenge;
|
|
4
|
+
DROP TABLE IF EXISTS fortress_webauthn_credential;
|
|
5
|
+
DROP TABLE IF EXISTS fortress_webhook_delivery;
|
|
6
|
+
DROP TABLE IF EXISTS fortress_webhook_endpoint;
|
|
7
|
+
DROP TABLE IF EXISTS fortress_audit_log;
|
|
8
|
+
DROP TABLE IF EXISTS fortress_account_lockout;
|
|
9
|
+
DROP TABLE IF EXISTS fortress_user_scope_assignment;
|
|
10
|
+
DROP TABLE IF EXISTS fortress_oauth_signing_key;
|
|
11
|
+
DROP TABLE IF EXISTS fortress_oauth_pending_flow;
|
|
12
|
+
DROP TABLE IF EXISTS fortress_oauth_refresh_token;
|
|
13
|
+
DROP TABLE IF EXISTS fortress_oauth_access_token;
|
|
14
|
+
DROP TABLE IF EXISTS fortress_oauth_authorization_code;
|
|
15
|
+
DROP TABLE IF EXISTS fortress_oauth_client;
|
|
16
|
+
DROP TABLE IF EXISTS fortress_tenant_user;
|
|
17
|
+
DROP TABLE IF EXISTS fortress_tenant;
|
|
18
|
+
DROP TABLE IF EXISTS fortress_social_account;
|
|
19
|
+
DROP TABLE IF EXISTS fortress_trusted_device;
|
|
20
|
+
DROP TABLE IF EXISTS fortress_backup_code;
|
|
21
|
+
DROP TABLE IF EXISTS fortress_two_factor_secret;
|
|
22
|
+
DROP TABLE IF EXISTS fortress_api_key;
|
|
23
|
+
DROP TABLE IF EXISTS fortress_magic_link_token;
|
|
24
|
+
DROP TABLE IF EXISTS fortress_email_verification_token;
|
|
25
|
+
DROP TABLE IF EXISTS fortress_direct_permission_binding;
|
|
26
|
+
DROP TABLE IF EXISTS fortress_role_binding;
|
|
27
|
+
DROP TABLE IF EXISTS fortress_role_permission;
|
|
28
|
+
DROP TABLE IF EXISTS fortress_role;
|
|
29
|
+
DROP TABLE IF EXISTS fortress_permission;
|
|
30
|
+
DROP TABLE IF EXISTS fortress_resource;
|
|
31
|
+
DROP TABLE IF EXISTS fortress_service_account;
|
|
32
|
+
DROP TABLE IF EXISTS fortress_group_user;
|
|
33
|
+
DROP TABLE IF EXISTS fortress_group;
|
|
34
|
+
DROP TABLE IF EXISTS fortress_refresh_token;
|
|
35
|
+
DROP TABLE IF EXISTS fortress_login_identifier;
|
|
36
|
+
DROP TABLE IF EXISTS fortress_user;
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
-- Fortress migration 0002: initial Fortress schema (SQLite)
|
|
2
|
+
|
|
3
|
+
CREATE TABLE IF NOT EXISTS fortress_user (
|
|
4
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5
|
+
email TEXT NOT NULL UNIQUE,
|
|
6
|
+
name TEXT NOT NULL,
|
|
7
|
+
password_hash TEXT,
|
|
8
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
9
|
+
email_verified INTEGER NOT NULL DEFAULT 0,
|
|
10
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
11
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
CREATE TABLE IF NOT EXISTS fortress_login_identifier (
|
|
15
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
17
|
+
type TEXT NOT NULL,
|
|
18
|
+
value TEXT NOT NULL UNIQUE
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS fortress_refresh_token (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
24
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
25
|
+
token_family TEXT NOT NULL,
|
|
26
|
+
is_revoked INTEGER NOT NULL DEFAULT 0,
|
|
27
|
+
expires_at INTEGER NOT NULL,
|
|
28
|
+
ip_address TEXT,
|
|
29
|
+
user_agent TEXT,
|
|
30
|
+
device_name TEXT,
|
|
31
|
+
last_active_at INTEGER,
|
|
32
|
+
fingerprint_hash TEXT,
|
|
33
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
CREATE TABLE IF NOT EXISTS fortress_group (
|
|
37
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38
|
+
name TEXT NOT NULL UNIQUE,
|
|
39
|
+
description TEXT
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
CREATE TABLE IF NOT EXISTS fortress_group_user (
|
|
43
|
+
group_id INTEGER NOT NULL REFERENCES fortress_group(id) ON DELETE CASCADE,
|
|
44
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
45
|
+
PRIMARY KEY (group_id, user_id)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
CREATE TABLE IF NOT EXISTS fortress_service_account (
|
|
49
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
50
|
+
name TEXT NOT NULL UNIQUE,
|
|
51
|
+
display_name TEXT,
|
|
52
|
+
description TEXT,
|
|
53
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
54
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
55
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
CREATE TABLE IF NOT EXISTS fortress_resource (
|
|
59
|
+
name TEXT PRIMARY KEY,
|
|
60
|
+
description TEXT
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
CREATE TABLE IF NOT EXISTS fortress_permission (
|
|
64
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
65
|
+
resource TEXT NOT NULL REFERENCES fortress_resource(name) ON DELETE CASCADE,
|
|
66
|
+
action TEXT NOT NULL,
|
|
67
|
+
effect TEXT NOT NULL DEFAULT 'ALLOW',
|
|
68
|
+
conditions TEXT,
|
|
69
|
+
description TEXT
|
|
70
|
+
);
|
|
71
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_permission_no_conditions
|
|
72
|
+
ON fortress_permission (resource, action, effect)
|
|
73
|
+
WHERE conditions IS NULL;
|
|
74
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_permission_with_conditions
|
|
75
|
+
ON fortress_permission (resource, action, effect, conditions)
|
|
76
|
+
WHERE conditions IS NOT NULL;
|
|
77
|
+
|
|
78
|
+
CREATE TABLE IF NOT EXISTS fortress_role (
|
|
79
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
80
|
+
name TEXT NOT NULL UNIQUE,
|
|
81
|
+
description TEXT,
|
|
82
|
+
is_system INTEGER NOT NULL DEFAULT 0
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
CREATE TABLE IF NOT EXISTS fortress_role_permission (
|
|
86
|
+
role_id INTEGER NOT NULL REFERENCES fortress_role(id) ON DELETE CASCADE,
|
|
87
|
+
permission_id INTEGER NOT NULL REFERENCES fortress_permission(id) ON DELETE CASCADE,
|
|
88
|
+
PRIMARY KEY (role_id, permission_id)
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
CREATE TABLE IF NOT EXISTS fortress_role_binding (
|
|
92
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
93
|
+
role_id INTEGER NOT NULL REFERENCES fortress_role(id) ON DELETE CASCADE,
|
|
94
|
+
subject_type TEXT NOT NULL,
|
|
95
|
+
subject_id INTEGER NOT NULL,
|
|
96
|
+
tenant_id TEXT,
|
|
97
|
+
UNIQUE (role_id, subject_type, subject_id, tenant_id)
|
|
98
|
+
);
|
|
99
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_role_binding_global
|
|
100
|
+
ON fortress_role_binding (role_id, subject_type, subject_id)
|
|
101
|
+
WHERE tenant_id IS NULL;
|
|
102
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_role_binding_tenant
|
|
103
|
+
ON fortress_role_binding (role_id, subject_type, subject_id, tenant_id)
|
|
104
|
+
WHERE tenant_id IS NOT NULL;
|
|
105
|
+
|
|
106
|
+
CREATE TABLE IF NOT EXISTS fortress_direct_permission_binding (
|
|
107
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
108
|
+
permission_id INTEGER NOT NULL REFERENCES fortress_permission(id) ON DELETE CASCADE,
|
|
109
|
+
subject_type TEXT NOT NULL,
|
|
110
|
+
subject_id INTEGER NOT NULL,
|
|
111
|
+
tenant_id TEXT,
|
|
112
|
+
UNIQUE (permission_id, subject_type, subject_id, tenant_id)
|
|
113
|
+
);
|
|
114
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_direct_permission_binding_global
|
|
115
|
+
ON fortress_direct_permission_binding (permission_id, subject_type, subject_id)
|
|
116
|
+
WHERE tenant_id IS NULL;
|
|
117
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_direct_permission_binding_tenant
|
|
118
|
+
ON fortress_direct_permission_binding (permission_id, subject_type, subject_id, tenant_id)
|
|
119
|
+
WHERE tenant_id IS NOT NULL;
|
|
120
|
+
|
|
121
|
+
CREATE TABLE IF NOT EXISTS fortress_email_verification_token (
|
|
122
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
123
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
124
|
+
token TEXT NOT NULL,
|
|
125
|
+
email TEXT NOT NULL,
|
|
126
|
+
expires_at INTEGER NOT NULL,
|
|
127
|
+
used_at INTEGER,
|
|
128
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
CREATE TABLE IF NOT EXISTS fortress_magic_link_token (
|
|
132
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
133
|
+
email TEXT NOT NULL,
|
|
134
|
+
token TEXT NOT NULL,
|
|
135
|
+
expires_at INTEGER NOT NULL,
|
|
136
|
+
used_at INTEGER,
|
|
137
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
CREATE TABLE IF NOT EXISTS fortress_api_key (
|
|
141
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
142
|
+
subject_type TEXT NOT NULL,
|
|
143
|
+
subject_id INTEGER NOT NULL,
|
|
144
|
+
name TEXT NOT NULL,
|
|
145
|
+
key_hash TEXT NOT NULL UNIQUE,
|
|
146
|
+
key_prefix TEXT NOT NULL,
|
|
147
|
+
scopes TEXT,
|
|
148
|
+
expires_at INTEGER,
|
|
149
|
+
last_used_at INTEGER,
|
|
150
|
+
is_revoked INTEGER NOT NULL DEFAULT 0,
|
|
151
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
152
|
+
);
|
|
153
|
+
CREATE INDEX IF NOT EXISTS api_key_subject_idx ON fortress_api_key (subject_type, subject_id);
|
|
154
|
+
|
|
155
|
+
CREATE TABLE IF NOT EXISTS fortress_two_factor_secret (
|
|
156
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
157
|
+
user_id INTEGER NOT NULL UNIQUE REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
158
|
+
secret TEXT NOT NULL,
|
|
159
|
+
is_enabled INTEGER NOT NULL DEFAULT 0,
|
|
160
|
+
last_used_counter INTEGER,
|
|
161
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
CREATE TABLE IF NOT EXISTS fortress_backup_code (
|
|
165
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
166
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
167
|
+
code_hash TEXT NOT NULL,
|
|
168
|
+
is_used INTEGER NOT NULL DEFAULT 0,
|
|
169
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
CREATE TABLE IF NOT EXISTS fortress_trusted_device (
|
|
173
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
174
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
175
|
+
device_hash TEXT NOT NULL,
|
|
176
|
+
expires_at INTEGER NOT NULL,
|
|
177
|
+
last_used_at INTEGER NOT NULL,
|
|
178
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
CREATE TABLE IF NOT EXISTS fortress_social_account (
|
|
182
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
183
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
184
|
+
provider TEXT NOT NULL,
|
|
185
|
+
provider_account_id TEXT NOT NULL,
|
|
186
|
+
email TEXT,
|
|
187
|
+
access_token TEXT,
|
|
188
|
+
refresh_token TEXT,
|
|
189
|
+
token_expires_at INTEGER,
|
|
190
|
+
profile TEXT,
|
|
191
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
192
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
193
|
+
UNIQUE (user_id, provider),
|
|
194
|
+
UNIQUE (provider, provider_account_id)
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
CREATE TABLE IF NOT EXISTS fortress_tenant (
|
|
198
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
199
|
+
name TEXT NOT NULL,
|
|
200
|
+
tax_id TEXT NOT NULL UNIQUE,
|
|
201
|
+
description TEXT,
|
|
202
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
203
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
CREATE TABLE IF NOT EXISTS fortress_tenant_user (
|
|
207
|
+
tenant_id INTEGER NOT NULL REFERENCES fortress_tenant(id) ON DELETE CASCADE,
|
|
208
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
209
|
+
is_default INTEGER NOT NULL DEFAULT 0,
|
|
210
|
+
PRIMARY KEY (tenant_id, user_id)
|
|
211
|
+
);
|
|
212
|
+
CREATE UNIQUE INDEX IF NOT EXISTS fortress_tenant_user_one_default_idx
|
|
213
|
+
ON fortress_tenant_user (user_id) WHERE is_default = 1;
|
|
214
|
+
|
|
215
|
+
CREATE TABLE IF NOT EXISTS fortress_oauth_client (
|
|
216
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
217
|
+
client_id TEXT NOT NULL UNIQUE,
|
|
218
|
+
client_secret_hash TEXT NOT NULL,
|
|
219
|
+
name TEXT NOT NULL,
|
|
220
|
+
redirect_uris TEXT NOT NULL,
|
|
221
|
+
grant_types TEXT NOT NULL,
|
|
222
|
+
allowed_scopes TEXT,
|
|
223
|
+
token_endpoint_auth_method TEXT,
|
|
224
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
CREATE TABLE IF NOT EXISTS fortress_oauth_authorization_code (
|
|
228
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
229
|
+
code TEXT NOT NULL UNIQUE,
|
|
230
|
+
client_id TEXT NOT NULL,
|
|
231
|
+
user_id INTEGER NOT NULL,
|
|
232
|
+
redirect_uri TEXT NOT NULL,
|
|
233
|
+
scope TEXT,
|
|
234
|
+
code_challenge TEXT,
|
|
235
|
+
code_challenge_method TEXT,
|
|
236
|
+
nonce TEXT,
|
|
237
|
+
auth_time INTEGER,
|
|
238
|
+
expires_at INTEGER NOT NULL,
|
|
239
|
+
used_at INTEGER,
|
|
240
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
CREATE TABLE IF NOT EXISTS fortress_oauth_access_token (
|
|
244
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
245
|
+
token TEXT NOT NULL UNIQUE,
|
|
246
|
+
client_id TEXT NOT NULL,
|
|
247
|
+
user_id INTEGER,
|
|
248
|
+
scope TEXT,
|
|
249
|
+
expires_at INTEGER NOT NULL,
|
|
250
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
CREATE TABLE IF NOT EXISTS fortress_oauth_refresh_token (
|
|
254
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
255
|
+
token TEXT NOT NULL UNIQUE,
|
|
256
|
+
family_id TEXT NOT NULL,
|
|
257
|
+
client_id TEXT NOT NULL,
|
|
258
|
+
user_id INTEGER NOT NULL,
|
|
259
|
+
scope TEXT,
|
|
260
|
+
issued_at INTEGER NOT NULL,
|
|
261
|
+
expires_at INTEGER NOT NULL,
|
|
262
|
+
used_at INTEGER,
|
|
263
|
+
parent_id INTEGER,
|
|
264
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
CREATE TABLE IF NOT EXISTS fortress_oauth_pending_flow (
|
|
268
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
269
|
+
flow_id TEXT NOT NULL UNIQUE,
|
|
270
|
+
client_id TEXT NOT NULL,
|
|
271
|
+
redirect_uri TEXT NOT NULL,
|
|
272
|
+
scope TEXT,
|
|
273
|
+
state TEXT NOT NULL,
|
|
274
|
+
code_challenge TEXT,
|
|
275
|
+
code_challenge_method TEXT,
|
|
276
|
+
nonce TEXT,
|
|
277
|
+
user_id INTEGER,
|
|
278
|
+
used_at INTEGER,
|
|
279
|
+
expires_at INTEGER NOT NULL,
|
|
280
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
CREATE TABLE IF NOT EXISTS fortress_oauth_signing_key (
|
|
284
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
285
|
+
kid TEXT NOT NULL UNIQUE,
|
|
286
|
+
alg TEXT NOT NULL,
|
|
287
|
+
public_jwk TEXT NOT NULL,
|
|
288
|
+
private_jwk TEXT NOT NULL,
|
|
289
|
+
rotated_at INTEGER,
|
|
290
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
CREATE TABLE IF NOT EXISTS fortress_user_scope_assignment (
|
|
294
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
295
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
296
|
+
scope_name TEXT NOT NULL,
|
|
297
|
+
scope_value TEXT NOT NULL,
|
|
298
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
CREATE TABLE IF NOT EXISTS fortress_account_lockout (
|
|
302
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
303
|
+
identifier TEXT NOT NULL UNIQUE,
|
|
304
|
+
failed_attempts INTEGER NOT NULL DEFAULT 0,
|
|
305
|
+
last_failed_at INTEGER,
|
|
306
|
+
locked_until INTEGER,
|
|
307
|
+
lockout_count INTEGER NOT NULL DEFAULT 0,
|
|
308
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
CREATE TABLE IF NOT EXISTS fortress_audit_log (
|
|
312
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
313
|
+
timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
314
|
+
event_type TEXT NOT NULL,
|
|
315
|
+
actor_id INTEGER,
|
|
316
|
+
actor_type TEXT NOT NULL DEFAULT 'USER',
|
|
317
|
+
target_id INTEGER,
|
|
318
|
+
target_type TEXT,
|
|
319
|
+
ip_address TEXT,
|
|
320
|
+
user_agent TEXT,
|
|
321
|
+
outcome TEXT NOT NULL DEFAULT 'SUCCESS',
|
|
322
|
+
metadata TEXT,
|
|
323
|
+
previous_hash TEXT,
|
|
324
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
CREATE TABLE IF NOT EXISTS fortress_webhook_endpoint (
|
|
328
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
329
|
+
url TEXT NOT NULL,
|
|
330
|
+
events TEXT NOT NULL,
|
|
331
|
+
secret TEXT NOT NULL,
|
|
332
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
333
|
+
deactivated_reason TEXT,
|
|
334
|
+
consecutive_failures INTEGER NOT NULL DEFAULT 0,
|
|
335
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
CREATE TABLE IF NOT EXISTS fortress_webhook_delivery (
|
|
339
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
340
|
+
endpoint_id INTEGER NOT NULL REFERENCES fortress_webhook_endpoint(id) ON DELETE CASCADE,
|
|
341
|
+
event_type TEXT NOT NULL,
|
|
342
|
+
payload TEXT NOT NULL,
|
|
343
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
344
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
345
|
+
idempotency_key TEXT,
|
|
346
|
+
last_attempt_at INTEGER,
|
|
347
|
+
next_retry_at INTEGER,
|
|
348
|
+
response_status INTEGER,
|
|
349
|
+
response_body TEXT,
|
|
350
|
+
error_kind TEXT,
|
|
351
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uniq_webhook_delivery_idempotency
|
|
355
|
+
ON fortress_webhook_delivery (endpoint_id, idempotency_key)
|
|
356
|
+
WHERE idempotency_key IS NOT NULL;
|
|
357
|
+
|
|
358
|
+
CREATE TABLE IF NOT EXISTS fortress_webauthn_credential (
|
|
359
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
360
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
361
|
+
credential_id TEXT NOT NULL UNIQUE,
|
|
362
|
+
public_key TEXT NOT NULL,
|
|
363
|
+
counter INTEGER NOT NULL DEFAULT 0,
|
|
364
|
+
device_type TEXT NOT NULL,
|
|
365
|
+
backed_up INTEGER NOT NULL DEFAULT 0,
|
|
366
|
+
transports TEXT,
|
|
367
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
CREATE TABLE IF NOT EXISTS fortress_webauthn_challenge (
|
|
371
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
372
|
+
challenge TEXT NOT NULL UNIQUE,
|
|
373
|
+
user_id INTEGER,
|
|
374
|
+
expires_at INTEGER NOT NULL,
|
|
375
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
376
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- Fortress migration 0003 rollback: auth continuation + refresh-session metadata (SQLite)
|
|
2
|
+
|
|
3
|
+
DROP TABLE IF EXISTS fortress_auth_continuation;
|
|
4
|
+
CREATE TABLE fortress_refresh_token_v2 (
|
|
5
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
7
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
8
|
+
token_family TEXT NOT NULL,
|
|
9
|
+
is_revoked INTEGER NOT NULL DEFAULT 0,
|
|
10
|
+
expires_at INTEGER NOT NULL,
|
|
11
|
+
ip_address TEXT,
|
|
12
|
+
user_agent TEXT,
|
|
13
|
+
device_name TEXT,
|
|
14
|
+
last_active_at INTEGER,
|
|
15
|
+
fingerprint_hash TEXT,
|
|
16
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
17
|
+
);
|
|
18
|
+
INSERT INTO fortress_refresh_token_v2 (
|
|
19
|
+
id, user_id, token_hash, token_family, is_revoked, expires_at,
|
|
20
|
+
ip_address, user_agent, device_name, last_active_at, fingerprint_hash, created_at
|
|
21
|
+
)
|
|
22
|
+
SELECT
|
|
23
|
+
id, user_id, token_hash, token_family, is_revoked, expires_at,
|
|
24
|
+
ip_address, user_agent, device_name, last_active_at, fingerprint_hash, created_at
|
|
25
|
+
FROM fortress_refresh_token;
|
|
26
|
+
DROP TABLE fortress_refresh_token;
|
|
27
|
+
ALTER TABLE fortress_refresh_token_v2 RENAME TO fortress_refresh_token;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- Fortress migration 0003: auth continuation + refresh-session metadata (SQLite)
|
|
2
|
+
|
|
3
|
+
CREATE TABLE fortress_refresh_token_v3 (
|
|
4
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
6
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
7
|
+
token_family TEXT NOT NULL,
|
|
8
|
+
family_created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
9
|
+
successor_token_hash TEXT,
|
|
10
|
+
rotated_at INTEGER,
|
|
11
|
+
is_revoked INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
expires_at INTEGER NOT NULL,
|
|
13
|
+
ip_address TEXT,
|
|
14
|
+
user_agent TEXT,
|
|
15
|
+
device_name TEXT,
|
|
16
|
+
last_active_at INTEGER,
|
|
17
|
+
fingerprint_hash TEXT,
|
|
18
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
19
|
+
);
|
|
20
|
+
INSERT INTO fortress_refresh_token_v3 (
|
|
21
|
+
id, user_id, token_hash, token_family, family_created_at,
|
|
22
|
+
successor_token_hash, rotated_at, is_revoked, expires_at, ip_address,
|
|
23
|
+
user_agent, device_name, last_active_at, fingerprint_hash, created_at
|
|
24
|
+
)
|
|
25
|
+
SELECT
|
|
26
|
+
token.id, token.user_id, token.token_hash, token.token_family,
|
|
27
|
+
(SELECT MIN(family.created_at)
|
|
28
|
+
FROM fortress_refresh_token AS family
|
|
29
|
+
WHERE family.token_family = token.token_family),
|
|
30
|
+
NULL, NULL, token.is_revoked, token.expires_at, token.ip_address,
|
|
31
|
+
token.user_agent, token.device_name, token.last_active_at,
|
|
32
|
+
token.fingerprint_hash, token.created_at
|
|
33
|
+
FROM fortress_refresh_token AS token;
|
|
34
|
+
DROP TABLE fortress_refresh_token;
|
|
35
|
+
ALTER TABLE fortress_refresh_token_v3 RENAME TO fortress_refresh_token;
|
|
36
|
+
|
|
37
|
+
CREATE TABLE fortress_auth_continuation (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
40
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
41
|
+
reason TEXT NOT NULL,
|
|
42
|
+
expires_at INTEGER NOT NULL,
|
|
43
|
+
consumed_at INTEGER,
|
|
44
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
45
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DROP INDEX IF EXISTS fortress_tenant_user_one_default_idx;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
UPDATE fortress_tenant_user
|
|
2
|
+
SET is_default = 0
|
|
3
|
+
WHERE is_default = 1
|
|
4
|
+
AND rowid NOT IN (
|
|
5
|
+
SELECT MIN(rowid)
|
|
6
|
+
FROM fortress_tenant_user
|
|
7
|
+
WHERE is_default = 1
|
|
8
|
+
GROUP BY user_id
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
CREATE UNIQUE INDEX IF NOT EXISTS fortress_tenant_user_one_default_idx
|
|
12
|
+
ON fortress_tenant_user (user_id)
|
|
13
|
+
WHERE is_default = 1;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
DROP INDEX IF EXISTS audit_log_timestamp_idx;
|
|
2
|
+
DROP INDEX IF EXISTS webhook_delivery_retry_idx;
|
|
3
|
+
DROP INDEX IF EXISTS trusted_device_user_idx;
|
|
4
|
+
DROP INDEX IF EXISTS backup_code_user_idx;
|
|
5
|
+
DROP INDEX IF EXISTS direct_permission_binding_subject_idx;
|
|
6
|
+
DROP INDEX IF EXISTS role_binding_subject_idx;
|
|
7
|
+
DROP INDEX IF EXISTS magic_link_token_token_idx;
|
|
8
|
+
DROP INDEX IF EXISTS email_verification_token_token_idx;
|
|
9
|
+
DROP INDEX IF EXISTS refresh_token_user_idx;
|
|
10
|
+
DROP INDEX IF EXISTS refresh_token_family_idx;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
CREATE INDEX refresh_token_family_idx ON fortress_refresh_token (token_family);
|
|
2
|
+
CREATE INDEX refresh_token_user_idx ON fortress_refresh_token (user_id);
|
|
3
|
+
CREATE INDEX email_verification_token_token_idx ON fortress_email_verification_token (token);
|
|
4
|
+
CREATE INDEX magic_link_token_token_idx ON fortress_magic_link_token (token);
|
|
5
|
+
CREATE INDEX role_binding_subject_idx ON fortress_role_binding (subject_type, subject_id);
|
|
6
|
+
CREATE INDEX direct_permission_binding_subject_idx ON fortress_direct_permission_binding (subject_type, subject_id);
|
|
7
|
+
CREATE INDEX backup_code_user_idx ON fortress_backup_code (user_id);
|
|
8
|
+
CREATE INDEX trusted_device_user_idx ON fortress_trusted_device (user_id);
|
|
9
|
+
CREATE INDEX webhook_delivery_retry_idx ON fortress_webhook_delivery (status, next_retry_at);
|
|
10
|
+
CREATE INDEX audit_log_timestamp_idx ON fortress_audit_log (timestamp);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- This sentinel is created only by the Fortress migration engine after its
|
|
2
|
+
-- Unicode-aware data step. Applying this SQL directly fails closed.
|
|
3
|
+
INSERT INTO fortress_email_migration_ready (id) VALUES (1);
|
|
4
|
+
CREATE UNIQUE INDEX user_email_ci_unique ON fortress_user (email COLLATE NOCASE);
|
|
5
|
+
CREATE UNIQUE INDEX login_identifier_email_ci_unique
|
|
6
|
+
ON fortress_login_identifier (value COLLATE NOCASE)
|
|
7
|
+
WHERE type = 'email';
|
|
8
|
+
DROP TABLE fortress_email_migration_ready;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DROP TABLE IF EXISTS fortress_audit_chain_state;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
CREATE TABLE fortress_audit_chain_state (
|
|
2
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
3
|
+
last_hash TEXT,
|
|
4
|
+
entry_count INTEGER NOT NULL CHECK (entry_count >= 0),
|
|
5
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
6
|
+
CHECK ((entry_count = 0 AND last_hash IS NULL) OR (entry_count > 0 AND last_hash IS NOT NULL))
|
|
7
|
+
);
|
|
8
|
+
INSERT INTO fortress_audit_chain_state (id, last_hash, entry_count) VALUES (1, NULL, 0);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- SQLite cannot drop columns portably; recreate the continuation table without hardening fields.
|
|
2
|
+
CREATE TABLE fortress_auth_continuation_old AS SELECT id, user_id, token_hash, reason, expires_at, consumed_at, created_at FROM fortress_auth_continuation;
|
|
3
|
+
DROP TABLE fortress_auth_continuation;
|
|
4
|
+
CREATE TABLE fortress_auth_continuation (
|
|
5
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
user_id INTEGER NOT NULL REFERENCES fortress_user(id) ON DELETE CASCADE,
|
|
7
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
8
|
+
reason TEXT NOT NULL,
|
|
9
|
+
expires_at INTEGER NOT NULL,
|
|
10
|
+
consumed_at INTEGER,
|
|
11
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
12
|
+
);
|
|
13
|
+
INSERT INTO fortress_auth_continuation SELECT * FROM fortress_auth_continuation_old;
|
|
14
|
+
DROP TABLE fortress_auth_continuation_old;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- Fortress migration 0008: bounded MFA continuation attempts.
|
|
2
|
+
ALTER TABLE fortress_auth_continuation ADD COLUMN failed_attempts INTEGER NOT NULL DEFAULT 0;
|
|
3
|
+
ALTER TABLE fortress_auth_continuation ADD COLUMN last_failed_at INTEGER;
|
|
4
|
+
ALTER TABLE fortress_auth_continuation ADD COLUMN invalidated_at INTEGER;
|
|
5
|
+
ALTER TABLE fortress_auth_continuation ADD COLUMN max_attempts INTEGER NOT NULL DEFAULT 5;
|
|
6
|
+
ALTER TABLE fortress_auth_continuation ADD COLUMN cooldown_seconds INTEGER NOT NULL DEFAULT 1;
|
|
7
|
+
CREATE INDEX auth_continuation_failure_idx ON fortress_auth_continuation (user_id, reason, last_failed_at);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- Existing TOTP seeds were stored in plaintext. SQL migrations cannot encrypt
|
|
2
|
+
-- them with the application-held key, so fail securely by requiring re-enrolment.
|
|
3
|
+
DELETE FROM fortress_backup_code;
|
|
4
|
+
DELETE FROM fortress_trusted_device;
|
|
5
|
+
DELETE FROM fortress_two_factor_secret;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT 1;
|