@fuzdev/fuz_app 0.1.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 +21 -0
- package/README.md +49 -0
- package/dist/actions/action_bridge.d.ts +65 -0
- package/dist/actions/action_bridge.d.ts.map +1 -0
- package/dist/actions/action_bridge.js +76 -0
- package/dist/actions/action_codegen.d.ts +97 -0
- package/dist/actions/action_codegen.d.ts.map +1 -0
- package/dist/actions/action_codegen.js +280 -0
- package/dist/actions/action_registry.d.ts +35 -0
- package/dist/actions/action_registry.d.ts.map +1 -0
- package/dist/actions/action_registry.js +83 -0
- package/dist/actions/action_spec.d.ts +169 -0
- package/dist/actions/action_spec.d.ts.map +1 -0
- package/dist/actions/action_spec.js +76 -0
- package/dist/auth/account_queries.d.ts +96 -0
- package/dist/auth/account_queries.d.ts.map +1 -0
- package/dist/auth/account_queries.js +172 -0
- package/dist/auth/account_routes.d.ts +86 -0
- package/dist/auth/account_routes.d.ts.map +1 -0
- package/dist/auth/account_routes.js +406 -0
- package/dist/auth/account_schema.d.ts +192 -0
- package/dist/auth/account_schema.d.ts.map +1 -0
- package/dist/auth/account_schema.js +105 -0
- package/dist/auth/admin_routes.d.ts +29 -0
- package/dist/auth/admin_routes.d.ts.map +1 -0
- package/dist/auth/admin_routes.js +193 -0
- package/dist/auth/api_token.d.ts +33 -0
- package/dist/auth/api_token.d.ts.map +1 -0
- package/dist/auth/api_token.js +36 -0
- package/dist/auth/api_token_queries.d.ts +80 -0
- package/dist/auth/api_token_queries.d.ts.map +1 -0
- package/dist/auth/api_token_queries.js +116 -0
- package/dist/auth/app_settings_queries.d.ts +33 -0
- package/dist/auth/app_settings_queries.d.ts.map +1 -0
- package/dist/auth/app_settings_queries.js +51 -0
- package/dist/auth/app_settings_routes.d.ts +27 -0
- package/dist/auth/app_settings_routes.d.ts.map +1 -0
- package/dist/auth/app_settings_routes.js +66 -0
- package/dist/auth/app_settings_schema.d.ts +35 -0
- package/dist/auth/app_settings_schema.d.ts.map +1 -0
- package/dist/auth/app_settings_schema.js +22 -0
- package/dist/auth/audit_log_queries.d.ts +90 -0
- package/dist/auth/audit_log_queries.d.ts.map +1 -0
- package/dist/auth/audit_log_queries.js +205 -0
- package/dist/auth/audit_log_routes.d.ts +33 -0
- package/dist/auth/audit_log_routes.d.ts.map +1 -0
- package/dist/auth/audit_log_routes.js +106 -0
- package/dist/auth/audit_log_schema.d.ts +259 -0
- package/dist/auth/audit_log_schema.d.ts.map +1 -0
- package/dist/auth/audit_log_schema.js +123 -0
- package/dist/auth/bearer_auth.d.ts +32 -0
- package/dist/auth/bearer_auth.d.ts.map +1 -0
- package/dist/auth/bearer_auth.js +90 -0
- package/dist/auth/bootstrap_account.d.ts +82 -0
- package/dist/auth/bootstrap_account.d.ts.map +1 -0
- package/dist/auth/bootstrap_account.js +97 -0
- package/dist/auth/bootstrap_routes.d.ts +74 -0
- package/dist/auth/bootstrap_routes.d.ts.map +1 -0
- package/dist/auth/bootstrap_routes.js +154 -0
- package/dist/auth/daemon_token.d.ts +49 -0
- package/dist/auth/daemon_token.d.ts.map +1 -0
- package/dist/auth/daemon_token.js +49 -0
- package/dist/auth/daemon_token_middleware.d.ts +93 -0
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -0
- package/dist/auth/daemon_token_middleware.js +167 -0
- package/dist/auth/ddl.d.ts +27 -0
- package/dist/auth/ddl.d.ts.map +1 -0
- package/dist/auth/ddl.js +111 -0
- package/dist/auth/deps.d.ts +52 -0
- package/dist/auth/deps.d.ts.map +1 -0
- package/dist/auth/deps.js +10 -0
- package/dist/auth/invite_queries.d.ts +68 -0
- package/dist/auth/invite_queries.d.ts.map +1 -0
- package/dist/auth/invite_queries.js +105 -0
- package/dist/auth/invite_routes.d.ts +18 -0
- package/dist/auth/invite_routes.d.ts.map +1 -0
- package/dist/auth/invite_routes.js +129 -0
- package/dist/auth/invite_schema.d.ts +51 -0
- package/dist/auth/invite_schema.d.ts.map +1 -0
- package/dist/auth/invite_schema.js +25 -0
- package/dist/auth/keyring.d.ts +87 -0
- package/dist/auth/keyring.d.ts.map +1 -0
- package/dist/auth/keyring.js +142 -0
- package/dist/auth/middleware.d.ts +40 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +64 -0
- package/dist/auth/migrations.d.ts +42 -0
- package/dist/auth/migrations.d.ts.map +1 -0
- package/dist/auth/migrations.js +79 -0
- package/dist/auth/password.d.ts +39 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +25 -0
- package/dist/auth/password_argon2.d.ts +43 -0
- package/dist/auth/password_argon2.d.ts.map +1 -0
- package/dist/auth/password_argon2.js +76 -0
- package/dist/auth/permit_queries.d.ts +72 -0
- package/dist/auth/permit_queries.d.ts.map +1 -0
- package/dist/auth/permit_queries.js +116 -0
- package/dist/auth/request_context.d.ts +114 -0
- package/dist/auth/request_context.d.ts.map +1 -0
- package/dist/auth/request_context.js +176 -0
- package/dist/auth/require_keeper.d.ts +20 -0
- package/dist/auth/require_keeper.d.ts.map +1 -0
- package/dist/auth/require_keeper.js +35 -0
- package/dist/auth/role_schema.d.ts +69 -0
- package/dist/auth/role_schema.d.ts.map +1 -0
- package/dist/auth/role_schema.js +70 -0
- package/dist/auth/route_guards.d.ts +21 -0
- package/dist/auth/route_guards.d.ts.map +1 -0
- package/dist/auth/route_guards.js +32 -0
- package/dist/auth/session_cookie.d.ts +158 -0
- package/dist/auth/session_cookie.d.ts.map +1 -0
- package/dist/auth/session_cookie.js +135 -0
- package/dist/auth/session_lifecycle.d.ts +35 -0
- package/dist/auth/session_lifecycle.d.ts.map +1 -0
- package/dist/auth/session_lifecycle.js +27 -0
- package/dist/auth/session_middleware.d.ts +33 -0
- package/dist/auth/session_middleware.d.ts.map +1 -0
- package/dist/auth/session_middleware.js +62 -0
- package/dist/auth/session_queries.d.ts +135 -0
- package/dist/auth/session_queries.d.ts.map +1 -0
- package/dist/auth/session_queries.js +186 -0
- package/dist/auth/signup_routes.d.ts +32 -0
- package/dist/auth/signup_routes.d.ts.map +1 -0
- package/dist/auth/signup_routes.js +150 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +76 -0
- package/dist/cli/config.d.ts +48 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +77 -0
- package/dist/cli/daemon.d.ts +82 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +149 -0
- package/dist/cli/help.d.ts +85 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +138 -0
- package/dist/cli/logger.d.ts +46 -0
- package/dist/cli/logger.d.ts.map +1 -0
- package/dist/cli/logger.js +48 -0
- package/dist/cli/util.d.ts +36 -0
- package/dist/cli/util.d.ts.map +1 -0
- package/dist/cli/util.js +50 -0
- package/dist/crypto.d.ts +13 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +19 -0
- package/dist/db/assert_row.d.ts +18 -0
- package/dist/db/assert_row.d.ts.map +1 -0
- package/dist/db/assert_row.js +24 -0
- package/dist/db/create_db.d.ts +38 -0
- package/dist/db/create_db.d.ts.map +1 -0
- package/dist/db/create_db.js +57 -0
- package/dist/db/db.d.ts +97 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +76 -0
- package/dist/db/db_pg.d.ts +21 -0
- package/dist/db/db_pg.d.ts.map +1 -0
- package/dist/db/db_pg.js +45 -0
- package/dist/db/db_pglite.d.ts +21 -0
- package/dist/db/db_pglite.d.ts.map +1 -0
- package/dist/db/db_pglite.js +28 -0
- package/dist/db/migrate.d.ts +67 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +118 -0
- package/dist/db/pg_error.d.ts +16 -0
- package/dist/db/pg_error.d.ts.map +1 -0
- package/dist/db/pg_error.js +15 -0
- package/dist/db/query_deps.d.ts +14 -0
- package/dist/db/query_deps.d.ts.map +1 -0
- package/dist/db/query_deps.js +9 -0
- package/dist/db/sql_identifier.d.ts +27 -0
- package/dist/db/sql_identifier.d.ts.map +1 -0
- package/dist/db/sql_identifier.js +31 -0
- package/dist/db/status.d.ts +62 -0
- package/dist/db/status.d.ts.map +1 -0
- package/dist/db/status.js +116 -0
- package/dist/dev/setup.d.ts +159 -0
- package/dist/dev/setup.d.ts.map +1 -0
- package/dist/dev/setup.js +265 -0
- package/dist/env/dotenv.d.ts +25 -0
- package/dist/env/dotenv.d.ts.map +1 -0
- package/dist/env/dotenv.js +52 -0
- package/dist/env/load.d.ts +52 -0
- package/dist/env/load.d.ts.map +1 -0
- package/dist/env/load.js +79 -0
- package/dist/env/mask.d.ts +19 -0
- package/dist/env/mask.d.ts.map +1 -0
- package/dist/env/mask.js +26 -0
- package/dist/env/resolve.d.ts +126 -0
- package/dist/env/resolve.d.ts.map +1 -0
- package/dist/env/resolve.js +200 -0
- package/dist/hono_context.d.ts +48 -0
- package/dist/hono_context.d.ts.map +1 -0
- package/dist/hono_context.js +22 -0
- package/dist/http/common_routes.d.ts +52 -0
- package/dist/http/common_routes.d.ts.map +1 -0
- package/dist/http/common_routes.js +65 -0
- package/dist/http/db_routes.d.ts +57 -0
- package/dist/http/db_routes.d.ts.map +1 -0
- package/dist/http/db_routes.js +176 -0
- package/dist/http/error_schemas.d.ts +169 -0
- package/dist/http/error_schemas.d.ts.map +1 -0
- package/dist/http/error_schemas.js +178 -0
- package/dist/http/middleware_spec.d.ts +19 -0
- package/dist/http/middleware_spec.d.ts.map +1 -0
- package/dist/http/middleware_spec.js +9 -0
- package/dist/http/origin.d.ts +57 -0
- package/dist/http/origin.d.ts.map +1 -0
- package/dist/http/origin.js +207 -0
- package/dist/http/proxy.d.ts +112 -0
- package/dist/http/proxy.d.ts.map +1 -0
- package/dist/http/proxy.js +240 -0
- package/dist/http/route_spec.d.ts +197 -0
- package/dist/http/route_spec.d.ts.map +1 -0
- package/dist/http/route_spec.js +243 -0
- package/dist/http/schema_helpers.d.ts +64 -0
- package/dist/http/schema_helpers.d.ts.map +1 -0
- package/dist/http/schema_helpers.js +90 -0
- package/dist/http/surface.d.ts +132 -0
- package/dist/http/surface.d.ts.map +1 -0
- package/dist/http/surface.js +156 -0
- package/dist/http/surface_query.d.ts +77 -0
- package/dist/http/surface_query.d.ts.map +1 -0
- package/dist/http/surface_query.js +86 -0
- package/dist/rate_limiter.d.ts +94 -0
- package/dist/rate_limiter.d.ts.map +1 -0
- package/dist/rate_limiter.js +156 -0
- package/dist/realtime/sse.d.ts +80 -0
- package/dist/realtime/sse.d.ts.map +1 -0
- package/dist/realtime/sse.js +109 -0
- package/dist/realtime/sse_auth_guard.d.ts +93 -0
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -0
- package/dist/realtime/sse_auth_guard.js +111 -0
- package/dist/realtime/subscriber_registry.d.ts +85 -0
- package/dist/realtime/subscriber_registry.d.ts.map +1 -0
- package/dist/realtime/subscriber_registry.js +108 -0
- package/dist/runtime/deno.d.ts +21 -0
- package/dist/runtime/deno.d.ts.map +1 -0
- package/dist/runtime/deno.js +83 -0
- package/dist/runtime/deps.d.ts +113 -0
- package/dist/runtime/deps.d.ts.map +1 -0
- package/dist/runtime/deps.js +10 -0
- package/dist/runtime/fs.d.ts +15 -0
- package/dist/runtime/fs.d.ts.map +1 -0
- package/dist/runtime/fs.js +17 -0
- package/dist/runtime/mock.d.ts +81 -0
- package/dist/runtime/mock.d.ts.map +1 -0
- package/dist/runtime/mock.js +195 -0
- package/dist/runtime/node.d.ts +17 -0
- package/dist/runtime/node.d.ts.map +1 -0
- package/dist/runtime/node.js +117 -0
- package/dist/schema_meta.d.ts +16 -0
- package/dist/schema_meta.d.ts.map +1 -0
- package/dist/schema_meta.js +9 -0
- package/dist/sensitivity.d.ts +15 -0
- package/dist/sensitivity.d.ts.map +1 -0
- package/dist/sensitivity.js +9 -0
- package/dist/server/app_backend.d.ts +74 -0
- package/dist/server/app_backend.d.ts.map +1 -0
- package/dist/server/app_backend.js +39 -0
- package/dist/server/app_server.d.ts +201 -0
- package/dist/server/app_server.d.ts.map +1 -0
- package/dist/server/app_server.js +266 -0
- package/dist/server/env.d.ts +68 -0
- package/dist/server/env.d.ts.map +1 -0
- package/dist/server/env.js +95 -0
- package/dist/server/startup.d.ts +22 -0
- package/dist/server/startup.d.ts.map +1 -0
- package/dist/server/startup.js +48 -0
- package/dist/server/static.d.ts +39 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +38 -0
- package/dist/server/validate_nginx.d.ts +34 -0
- package/dist/server/validate_nginx.d.ts.map +1 -0
- package/dist/server/validate_nginx.js +118 -0
- package/dist/testing/CLAUDE.md +3 -0
- package/dist/testing/admin_integration.d.ts +45 -0
- package/dist/testing/admin_integration.d.ts.map +1 -0
- package/dist/testing/admin_integration.js +840 -0
- package/dist/testing/adversarial_404.d.ts +15 -0
- package/dist/testing/adversarial_404.d.ts.map +1 -0
- package/dist/testing/adversarial_404.js +118 -0
- package/dist/testing/adversarial_headers.d.ts +36 -0
- package/dist/testing/adversarial_headers.d.ts.map +1 -0
- package/dist/testing/adversarial_headers.js +128 -0
- package/dist/testing/adversarial_input.d.ts +56 -0
- package/dist/testing/adversarial_input.d.ts.map +1 -0
- package/dist/testing/adversarial_input.js +494 -0
- package/dist/testing/app_server.d.ts +169 -0
- package/dist/testing/app_server.d.ts.map +1 -0
- package/dist/testing/app_server.js +240 -0
- package/dist/testing/assert_dev_env.d.ts +10 -0
- package/dist/testing/assert_dev_env.d.ts.map +1 -0
- package/dist/testing/assert_dev_env.js +13 -0
- package/dist/testing/assertions.d.ts +61 -0
- package/dist/testing/assertions.d.ts.map +1 -0
- package/dist/testing/assertions.js +96 -0
- package/dist/testing/attack_surface.d.ts +63 -0
- package/dist/testing/attack_surface.d.ts.map +1 -0
- package/dist/testing/attack_surface.js +224 -0
- package/dist/testing/audit_completeness.d.ts +29 -0
- package/dist/testing/audit_completeness.d.ts.map +1 -0
- package/dist/testing/audit_completeness.js +410 -0
- package/dist/testing/auth_apps.d.ts +55 -0
- package/dist/testing/auth_apps.d.ts.map +1 -0
- package/dist/testing/auth_apps.js +122 -0
- package/dist/testing/data_exposure.d.ts +62 -0
- package/dist/testing/data_exposure.d.ts.map +1 -0
- package/dist/testing/data_exposure.js +297 -0
- package/dist/testing/db.d.ts +111 -0
- package/dist/testing/db.d.ts.map +1 -0
- package/dist/testing/db.js +258 -0
- package/dist/testing/entities.d.ts +21 -0
- package/dist/testing/entities.d.ts.map +1 -0
- package/dist/testing/entities.js +42 -0
- package/dist/testing/error_coverage.d.ts +78 -0
- package/dist/testing/error_coverage.d.ts.map +1 -0
- package/dist/testing/error_coverage.js +135 -0
- package/dist/testing/integration.d.ts +37 -0
- package/dist/testing/integration.d.ts.map +1 -0
- package/dist/testing/integration.js +1139 -0
- package/dist/testing/integration_helpers.d.ts +107 -0
- package/dist/testing/integration_helpers.d.ts.map +1 -0
- package/dist/testing/integration_helpers.js +246 -0
- package/dist/testing/middleware.d.ts +125 -0
- package/dist/testing/middleware.d.ts.map +1 -0
- package/dist/testing/middleware.js +210 -0
- package/dist/testing/rate_limiting.d.ts +43 -0
- package/dist/testing/rate_limiting.d.ts.map +1 -0
- package/dist/testing/rate_limiting.js +216 -0
- package/dist/testing/round_trip.d.ts +37 -0
- package/dist/testing/round_trip.d.ts.map +1 -0
- package/dist/testing/round_trip.js +128 -0
- package/dist/testing/schema_generators.d.ts +33 -0
- package/dist/testing/schema_generators.d.ts.map +1 -0
- package/dist/testing/schema_generators.js +137 -0
- package/dist/testing/standard.d.ts +49 -0
- package/dist/testing/standard.d.ts.map +1 -0
- package/dist/testing/standard.js +16 -0
- package/dist/testing/stubs.d.ts +96 -0
- package/dist/testing/stubs.d.ts.map +1 -0
- package/dist/testing/stubs.js +192 -0
- package/dist/testing/surface_invariants.d.ts +189 -0
- package/dist/testing/surface_invariants.d.ts.map +1 -0
- package/dist/testing/surface_invariants.js +450 -0
- package/dist/ui/AccountSessions.svelte +75 -0
- package/dist/ui/AccountSessions.svelte.d.ts +19 -0
- package/dist/ui/AccountSessions.svelte.d.ts.map +1 -0
- package/dist/ui/AdminAccounts.svelte +107 -0
- package/dist/ui/AdminAccounts.svelte.d.ts +19 -0
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -0
- package/dist/ui/AdminAuditLog.svelte +144 -0
- package/dist/ui/AdminAuditLog.svelte.d.ts +4 -0
- package/dist/ui/AdminAuditLog.svelte.d.ts.map +1 -0
- package/dist/ui/AdminInvites.svelte +142 -0
- package/dist/ui/AdminInvites.svelte.d.ts +4 -0
- package/dist/ui/AdminInvites.svelte.d.ts.map +1 -0
- package/dist/ui/AdminOverview.svelte +337 -0
- package/dist/ui/AdminOverview.svelte.d.ts +4 -0
- package/dist/ui/AdminOverview.svelte.d.ts.map +1 -0
- package/dist/ui/AdminPermitHistory.svelte +61 -0
- package/dist/ui/AdminPermitHistory.svelte.d.ts +19 -0
- package/dist/ui/AdminPermitHistory.svelte.d.ts.map +1 -0
- package/dist/ui/AdminSessions.svelte +85 -0
- package/dist/ui/AdminSessions.svelte.d.ts +19 -0
- package/dist/ui/AdminSessions.svelte.d.ts.map +1 -0
- package/dist/ui/AdminSettings.svelte +32 -0
- package/dist/ui/AdminSettings.svelte.d.ts +19 -0
- package/dist/ui/AdminSettings.svelte.d.ts.map +1 -0
- package/dist/ui/AdminSurface.svelte +42 -0
- package/dist/ui/AdminSurface.svelte.d.ts +4 -0
- package/dist/ui/AdminSurface.svelte.d.ts.map +1 -0
- package/dist/ui/AppShell.svelte +93 -0
- package/dist/ui/AppShell.svelte.d.ts +20 -0
- package/dist/ui/AppShell.svelte.d.ts.map +1 -0
- package/dist/ui/BootstrapForm.svelte +105 -0
- package/dist/ui/BootstrapForm.svelte.d.ts +4 -0
- package/dist/ui/BootstrapForm.svelte.d.ts.map +1 -0
- package/dist/ui/ColumnLayout.svelte +46 -0
- package/dist/ui/ColumnLayout.svelte.d.ts +11 -0
- package/dist/ui/ColumnLayout.svelte.d.ts.map +1 -0
- package/dist/ui/ConfirmButton.svelte +125 -0
- package/dist/ui/ConfirmButton.svelte.d.ts +54 -0
- package/dist/ui/ConfirmButton.svelte.d.ts.map +1 -0
- package/dist/ui/Datatable.svelte +185 -0
- package/dist/ui/Datatable.svelte.d.ts +35 -0
- package/dist/ui/Datatable.svelte.d.ts.map +1 -0
- package/dist/ui/LoginForm.svelte +82 -0
- package/dist/ui/LoginForm.svelte.d.ts +8 -0
- package/dist/ui/LoginForm.svelte.d.ts.map +1 -0
- package/dist/ui/LogoutButton.svelte +36 -0
- package/dist/ui/LogoutButton.svelte.d.ts +10 -0
- package/dist/ui/LogoutButton.svelte.d.ts.map +1 -0
- package/dist/ui/MenuLink.svelte +35 -0
- package/dist/ui/MenuLink.svelte.d.ts +12 -0
- package/dist/ui/MenuLink.svelte.d.ts.map +1 -0
- package/dist/ui/OpenSignupToggle.svelte +36 -0
- package/dist/ui/OpenSignupToggle.svelte.d.ts +19 -0
- package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -0
- package/dist/ui/PopoverButton.svelte +136 -0
- package/dist/ui/PopoverButton.svelte.d.ts +63 -0
- package/dist/ui/PopoverButton.svelte.d.ts.map +1 -0
- package/dist/ui/SignupForm.svelte +117 -0
- package/dist/ui/SignupForm.svelte.d.ts +7 -0
- package/dist/ui/SignupForm.svelte.d.ts.map +1 -0
- package/dist/ui/SurfaceExplorer.svelte +287 -0
- package/dist/ui/SurfaceExplorer.svelte.d.ts +8 -0
- package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -0
- package/dist/ui/account_sessions_state.svelte.d.ts +15 -0
- package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -0
- package/dist/ui/account_sessions_state.svelte.js +45 -0
- package/dist/ui/admin_accounts_state.svelte.d.ts +19 -0
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -0
- package/dist/ui/admin_accounts_state.svelte.js +65 -0
- package/dist/ui/admin_invites_state.svelte.d.ts +19 -0
- package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -0
- package/dist/ui/admin_invites_state.svelte.js +71 -0
- package/dist/ui/admin_sessions_state.svelte.d.ts +18 -0
- package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -0
- package/dist/ui/admin_sessions_state.svelte.js +62 -0
- package/dist/ui/app_settings_state.svelte.d.ts +14 -0
- package/dist/ui/app_settings_state.svelte.d.ts.map +1 -0
- package/dist/ui/app_settings_state.svelte.js +44 -0
- package/dist/ui/audit_log_state.svelte.d.ts +40 -0
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -0
- package/dist/ui/audit_log_state.svelte.js +153 -0
- package/dist/ui/auth_state.svelte.d.ts +85 -0
- package/dist/ui/auth_state.svelte.d.ts.map +1 -0
- package/dist/ui/auth_state.svelte.js +238 -0
- package/dist/ui/datatable.d.ts +25 -0
- package/dist/ui/datatable.d.ts.map +1 -0
- package/dist/ui/datatable.js +9 -0
- package/dist/ui/enter_advance.d.ts +13 -0
- package/dist/ui/enter_advance.d.ts.map +1 -0
- package/dist/ui/enter_advance.js +30 -0
- package/dist/ui/loadable.svelte.d.ts +55 -0
- package/dist/ui/loadable.svelte.d.ts.map +1 -0
- package/dist/ui/loadable.svelte.js +75 -0
- package/dist/ui/popover.svelte.d.ts +137 -0
- package/dist/ui/popover.svelte.d.ts.map +1 -0
- package/dist/ui/popover.svelte.js +288 -0
- package/dist/ui/position_helpers.d.ts +27 -0
- package/dist/ui/position_helpers.d.ts.map +1 -0
- package/dist/ui/position_helpers.js +81 -0
- package/dist/ui/sidebar_state.svelte.d.ts +30 -0
- package/dist/ui/sidebar_state.svelte.d.ts.map +1 -0
- package/dist/ui/sidebar_state.svelte.js +39 -0
- package/dist/ui/table_state.svelte.d.ts +63 -0
- package/dist/ui/table_state.svelte.d.ts.map +1 -0
- package/dist/ui/table_state.svelte.js +117 -0
- package/dist/ui/ui_fetch.d.ts +29 -0
- package/dist/ui/ui_fetch.d.ts.map +1 -0
- package/dist/ui/ui_fetch.js +37 -0
- package/dist/ui/ui_format.d.ts +63 -0
- package/dist/ui/ui_format.d.ts.map +1 -0
- package/dist/ui/ui_format.js +196 -0
- package/package.json +121 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { Logger } from '@fuzdev/fuz_util/log.js';
|
|
4
|
+
import { ROLE_KEEPER } from '../auth/role_schema.js';
|
|
5
|
+
import { create_validated_keyring } from '../auth/keyring.js';
|
|
6
|
+
import { generate_api_token } from '../auth/api_token.js';
|
|
7
|
+
import { query_create_account_with_actor } from '../auth/account_queries.js';
|
|
8
|
+
import { query_grant_permit } from '../auth/permit_queries.js';
|
|
9
|
+
import { generate_session_token, hash_session_token, AUTH_SESSION_LIFETIME_MS, query_create_session, } from '../auth/session_queries.js';
|
|
10
|
+
import { query_create_api_token } from '../auth/api_token_queries.js';
|
|
11
|
+
import { create_session_cookie_value } from '../auth/session_cookie.js';
|
|
12
|
+
import { run_migrations } from '../db/migrate.js';
|
|
13
|
+
import { AUTH_MIGRATION_NS } from '../auth/migrations.js';
|
|
14
|
+
import { create_app_server, } from '../server/app_server.js';
|
|
15
|
+
import { create_pglite_factory } from './db.js';
|
|
16
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
17
|
+
/**
|
|
18
|
+
* Fast password stub for tests that don't exercise login/password flows.
|
|
19
|
+
*
|
|
20
|
+
* Hashes are deterministic (`stub_hash_<password>`) and verify correctly,
|
|
21
|
+
* so auth bootstrap and session creation work without Argon2 overhead.
|
|
22
|
+
*/
|
|
23
|
+
export const stub_password_deps = {
|
|
24
|
+
hash_password: async (p) => `stub_hash_${p}`,
|
|
25
|
+
verify_password: async (p, h) => h === `stub_hash_${p}`,
|
|
26
|
+
verify_dummy: async () => false,
|
|
27
|
+
};
|
|
28
|
+
/** 64-hex-char test cookie secret — deterministic, never used in production. */
|
|
29
|
+
export const TEST_COOKIE_SECRET = 'a'.repeat(64);
|
|
30
|
+
// Module-level PGlite factory for create_test_app_server when no db is provided.
|
|
31
|
+
// Shares the WASM instance cache from test_db.ts, avoiding redundant cold starts
|
|
32
|
+
// within the same vitest worker thread. Schema is reset on each create() call.
|
|
33
|
+
const fallback_pglite_factory = create_pglite_factory(async (db) => {
|
|
34
|
+
await run_migrations(db, [AUTH_MIGRATION_NS]);
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Bootstrap a test account with credentials.
|
|
38
|
+
*
|
|
39
|
+
* Creates an account with actor, grants roles, creates an API token,
|
|
40
|
+
* creates a session, and signs a session cookie. Shared by
|
|
41
|
+
* `create_test_app_server` and `TestApp.create_account`.
|
|
42
|
+
*/
|
|
43
|
+
export const bootstrap_test_account = async (options) => {
|
|
44
|
+
const { db, keyring, session_options, password, username = 'keeper', password_value = 'test-password-123', roles = [], } = options;
|
|
45
|
+
const deps = { db };
|
|
46
|
+
const password_hash = await password.hash_password(password_value);
|
|
47
|
+
const { account, actor } = await query_create_account_with_actor(deps, {
|
|
48
|
+
username,
|
|
49
|
+
password_hash,
|
|
50
|
+
});
|
|
51
|
+
// Grant roles
|
|
52
|
+
for (const role of roles) {
|
|
53
|
+
await query_grant_permit(deps, { actor_id: actor.id, role, granted_by: null }); // eslint-disable-line no-await-in-loop
|
|
54
|
+
}
|
|
55
|
+
// Create API token
|
|
56
|
+
const { token: api_token, id: token_id, token_hash } = generate_api_token();
|
|
57
|
+
await query_create_api_token(deps, token_id, account.id, 'test-cli', token_hash);
|
|
58
|
+
// Create session + cookie
|
|
59
|
+
const session_token = generate_session_token();
|
|
60
|
+
const session_hash = hash_session_token(session_token);
|
|
61
|
+
const expires_at = new Date(Date.now() + AUTH_SESSION_LIFETIME_MS);
|
|
62
|
+
await query_create_session(deps, session_hash, account.id, expires_at);
|
|
63
|
+
const session_cookie = await create_session_cookie_value(keyring, session_token, session_options);
|
|
64
|
+
return {
|
|
65
|
+
account: { id: account.id, username: account.username },
|
|
66
|
+
actor: { id: actor.id },
|
|
67
|
+
api_token,
|
|
68
|
+
session_cookie,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Create an app server with a bootstrapped account for testing.
|
|
73
|
+
*
|
|
74
|
+
* Sets up:
|
|
75
|
+
* - Auth tables (via cached PGlite factory, or reuses existing `db`)
|
|
76
|
+
* - A keeper account with hashed password
|
|
77
|
+
* - Role permits for each role in `options.roles`
|
|
78
|
+
* - An API token for Bearer auth
|
|
79
|
+
* - A session with a signed cookie value
|
|
80
|
+
*
|
|
81
|
+
* Uses `stub_password_deps` by default — deterministic hashing that works
|
|
82
|
+
* correctly for login/logout tests without Argon2 overhead.
|
|
83
|
+
*
|
|
84
|
+
* @param options - session options and optional overrides
|
|
85
|
+
* @returns a `TestAppServer` ready for HTTP testing
|
|
86
|
+
*/
|
|
87
|
+
/** Silent logger for tests — suppresses all output. */
|
|
88
|
+
const test_log = new Logger('test', { level: 'off' });
|
|
89
|
+
export const create_test_app_server = async (options) => {
|
|
90
|
+
const { session_options, db: existing_db, db_type = 'pglite-memory', password = stub_password_deps, username = 'keeper', password_value = 'test-password-123', roles = [ROLE_KEEPER], } = options;
|
|
91
|
+
// Keyring from test secret
|
|
92
|
+
const keyring_result = create_validated_keyring(TEST_COOKIE_SECRET);
|
|
93
|
+
if (!keyring_result.ok) {
|
|
94
|
+
throw new Error(`Test keyring failed: ${keyring_result.errors.join(', ')}`);
|
|
95
|
+
}
|
|
96
|
+
const fs_stubs = {
|
|
97
|
+
stat: async () => null,
|
|
98
|
+
read_file: async () => '',
|
|
99
|
+
delete_file: async (_path) => { }, // eslint-disable-line @typescript-eslint/no-empty-function
|
|
100
|
+
};
|
|
101
|
+
let backend;
|
|
102
|
+
if (existing_db) {
|
|
103
|
+
// Reset singleton config rows that may retain state from a previous test.
|
|
104
|
+
// Harmless for fresh pglite (these are already at defaults).
|
|
105
|
+
await existing_db.query('UPDATE bootstrap_lock SET bootstrapped = false WHERE bootstrapped = true');
|
|
106
|
+
await existing_db.query('UPDATE app_settings SET open_signup = false, updated_at = NULL, updated_by = NULL WHERE open_signup = true OR updated_at IS NOT NULL');
|
|
107
|
+
// Use the caller's database — tables already created by the factory's init_schema.
|
|
108
|
+
// Caller owns the DB lifecycle — close is a no-op.
|
|
109
|
+
backend = {
|
|
110
|
+
db_type,
|
|
111
|
+
db_name: 'test',
|
|
112
|
+
migration_results: [], // migrations ran in the factory's init_schema, results not captured
|
|
113
|
+
close: async () => { }, // eslint-disable-line @typescript-eslint/no-empty-function
|
|
114
|
+
deps: {
|
|
115
|
+
keyring: keyring_result.keyring,
|
|
116
|
+
password,
|
|
117
|
+
db: existing_db,
|
|
118
|
+
log: test_log,
|
|
119
|
+
on_audit_event: () => { }, // eslint-disable-line @typescript-eslint/no-empty-function
|
|
120
|
+
...fs_stubs,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// In-memory PGlite via cached factory — reuses the WASM instance from test_db.ts
|
|
126
|
+
// instead of creating a new PGlite each time. Schema is reset and migrations re-run
|
|
127
|
+
// on each call, but the expensive WASM cold start only happens once per worker thread.
|
|
128
|
+
const db = await fallback_pglite_factory.create();
|
|
129
|
+
backend = {
|
|
130
|
+
db_type: 'pglite-memory',
|
|
131
|
+
db_name: '(memory)',
|
|
132
|
+
migration_results: [],
|
|
133
|
+
close: async () => { }, // eslint-disable-line @typescript-eslint/no-empty-function
|
|
134
|
+
deps: {
|
|
135
|
+
keyring: keyring_result.keyring,
|
|
136
|
+
password,
|
|
137
|
+
db,
|
|
138
|
+
log: test_log,
|
|
139
|
+
on_audit_event: () => { }, // eslint-disable-line @typescript-eslint/no-empty-function
|
|
140
|
+
...fs_stubs,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const bootstrapped = await bootstrap_test_account({
|
|
145
|
+
db: backend.deps.db,
|
|
146
|
+
keyring: keyring_result.keyring,
|
|
147
|
+
session_options,
|
|
148
|
+
password,
|
|
149
|
+
username,
|
|
150
|
+
password_value,
|
|
151
|
+
roles,
|
|
152
|
+
});
|
|
153
|
+
return {
|
|
154
|
+
...backend,
|
|
155
|
+
...bootstrapped,
|
|
156
|
+
keyring: keyring_result.keyring,
|
|
157
|
+
cleanup: () => backend.close(),
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Create a fully assembled test app with a Hono server, middleware, and routes.
|
|
162
|
+
*
|
|
163
|
+
* Combines `create_test_app_server` + `create_app_server` into a single call.
|
|
164
|
+
* Disables rate limiters and logging by default (test-friendly).
|
|
165
|
+
*
|
|
166
|
+
* A fresh Hono app is created each call — middleware closures bind to the
|
|
167
|
+
* server's deps (db, keyring), so reuse across servers is unsafe.
|
|
168
|
+
* The expensive resource (PGlite WASM) is cached separately in `test_db.ts`.
|
|
169
|
+
*
|
|
170
|
+
* @param options - test app configuration
|
|
171
|
+
* @returns a `TestApp` ready for HTTP testing
|
|
172
|
+
*/
|
|
173
|
+
export const create_test_app = async (options) => {
|
|
174
|
+
const test_server = await create_test_app_server(options);
|
|
175
|
+
const result = await create_app_server({
|
|
176
|
+
backend: test_server,
|
|
177
|
+
session_options: options.session_options,
|
|
178
|
+
allowed_origins: [/^http:\/\/localhost/],
|
|
179
|
+
proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
|
|
180
|
+
env_schema: z.object({}),
|
|
181
|
+
ip_rate_limiter: null,
|
|
182
|
+
login_account_rate_limiter: null,
|
|
183
|
+
signup_account_rate_limiter: null,
|
|
184
|
+
bearer_ip_rate_limiter: null,
|
|
185
|
+
await_pending_effects: true,
|
|
186
|
+
...options.app_options,
|
|
187
|
+
create_route_specs: options.create_route_specs,
|
|
188
|
+
});
|
|
189
|
+
const { app, surface_spec } = result;
|
|
190
|
+
const { cookie_name } = options.session_options;
|
|
191
|
+
const { password = stub_password_deps } = options;
|
|
192
|
+
const create_session_headers = (extra) => ({
|
|
193
|
+
host: 'localhost',
|
|
194
|
+
origin: 'http://localhost:5173',
|
|
195
|
+
cookie: `${cookie_name}=${test_server.session_cookie}`,
|
|
196
|
+
...extra,
|
|
197
|
+
});
|
|
198
|
+
const create_bearer_headers = (extra) => ({
|
|
199
|
+
host: 'localhost',
|
|
200
|
+
authorization: `Bearer ${test_server.api_token}`,
|
|
201
|
+
...extra,
|
|
202
|
+
});
|
|
203
|
+
let account_counter = 0;
|
|
204
|
+
const create_account = async (account_options) => {
|
|
205
|
+
account_counter++;
|
|
206
|
+
const bootstrapped = await bootstrap_test_account({
|
|
207
|
+
db: test_server.deps.db,
|
|
208
|
+
keyring: test_server.keyring,
|
|
209
|
+
session_options: options.session_options,
|
|
210
|
+
password,
|
|
211
|
+
username: account_options?.username ?? `test_user_${account_counter}`,
|
|
212
|
+
password_value: account_options?.password_value ?? 'test-password-123',
|
|
213
|
+
roles: account_options?.roles ?? [],
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
...bootstrapped,
|
|
217
|
+
create_session_headers: (extra) => ({
|
|
218
|
+
host: 'localhost',
|
|
219
|
+
origin: 'http://localhost:5173',
|
|
220
|
+
cookie: `${cookie_name}=${bootstrapped.session_cookie}`,
|
|
221
|
+
...extra,
|
|
222
|
+
}),
|
|
223
|
+
create_bearer_headers: (extra) => ({
|
|
224
|
+
host: 'localhost',
|
|
225
|
+
authorization: `Bearer ${bootstrapped.api_token}`,
|
|
226
|
+
...extra,
|
|
227
|
+
}),
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
return {
|
|
231
|
+
app,
|
|
232
|
+
backend: test_server,
|
|
233
|
+
surface: surface_spec.surface,
|
|
234
|
+
route_specs: surface_spec.route_specs,
|
|
235
|
+
create_session_headers,
|
|
236
|
+
create_bearer_headers,
|
|
237
|
+
create_account,
|
|
238
|
+
cleanup: () => test_server.cleanup(),
|
|
239
|
+
};
|
|
240
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asserts that testing utilities are only imported in development environments.
|
|
3
|
+
*
|
|
4
|
+
* Each testing module imports this as a side effect to prevent accidental
|
|
5
|
+
* inclusion in production bundles. Uses `esm-env` which is set correctly
|
|
6
|
+
* by SvelteKit and Vite build tools — `DEV` is `true` during development
|
|
7
|
+
* and testing, `false` in production builds.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=assert_dev_env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assert_dev_env.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/assert_dev_env.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asserts that testing utilities are only imported in development environments.
|
|
3
|
+
*
|
|
4
|
+
* Each testing module imports this as a side effect to prevent accidental
|
|
5
|
+
* inclusion in production bundles. Uses `esm-env` which is set correctly
|
|
6
|
+
* by SvelteKit and Vite build tools — `DEV` is `true` during development
|
|
7
|
+
* and testing, `false` in production builds.
|
|
8
|
+
*/
|
|
9
|
+
import { DEV } from 'esm-env';
|
|
10
|
+
if (!DEV) {
|
|
11
|
+
throw new Error('fuz_app testing utilities must not be imported in production. ' +
|
|
12
|
+
'These modules are intended for use in test files only.');
|
|
13
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { AppSurface, AppSurfaceRoute } from '../http/surface.js';
|
|
4
|
+
import type { RouteErrorSchemas } from '../http/error_schemas.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve an absolute path relative to the caller's module.
|
|
7
|
+
*
|
|
8
|
+
* @param filename - the filename to resolve
|
|
9
|
+
* @param import_meta_url - the caller's `import.meta.url`
|
|
10
|
+
* @returns absolute path
|
|
11
|
+
*/
|
|
12
|
+
export declare const resolve_fixture_path: (filename: string, import_meta_url: string) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Compare live surface against a committed snapshot JSON file.
|
|
15
|
+
*
|
|
16
|
+
* @param surface - the live surface to check
|
|
17
|
+
* @param snapshot_path - absolute path to the committed JSON snapshot
|
|
18
|
+
*/
|
|
19
|
+
export declare const assert_surface_matches_snapshot: (surface: AppSurface, snapshot_path: string) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Verify surface generation is deterministic (build twice, compare).
|
|
22
|
+
*
|
|
23
|
+
* @param build_surface - function that builds the surface
|
|
24
|
+
*/
|
|
25
|
+
export declare const assert_surface_deterministic: (build_surface: () => AppSurface) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Bidirectional check: no unexpected public routes, no missing expected ones.
|
|
28
|
+
*
|
|
29
|
+
* @param surface - the app surface to check
|
|
30
|
+
* @param expected_public - format: `['GET /health', 'POST /api/account/login']`
|
|
31
|
+
*/
|
|
32
|
+
export declare const assert_only_expected_public_routes: (surface: AppSurface, expected_public: Array<string>) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Verify every route under a path prefix has the exact expected middleware stack.
|
|
35
|
+
*
|
|
36
|
+
* @param surface - the app surface to check
|
|
37
|
+
* @param path_prefix - prefix to filter routes (e.g. `'/api/'`)
|
|
38
|
+
* @param expected_middleware - the exact middleware names in order
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* Look up the merged error schema for a route+status from a pre-built schema lookup.
|
|
42
|
+
*
|
|
43
|
+
* @param lookup - map from `"METHOD /path"` to merged error schemas
|
|
44
|
+
* @param route - the surface route to look up
|
|
45
|
+
* @param status - HTTP status code
|
|
46
|
+
*/
|
|
47
|
+
export declare const get_route_error_schema: (lookup: Map<string, RouteErrorSchemas>, route: AppSurfaceRoute, status: number) => z.ZodType | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Assert that an error schema exists for a route+status and validate the body against it.
|
|
50
|
+
*
|
|
51
|
+
* Protected routes should always have auto-derived error schemas (401 for authenticated,
|
|
52
|
+
* 403 for role-restricted). A missing schema indicates a gap in error schema derivation.
|
|
53
|
+
*
|
|
54
|
+
* @param lookup - map from `"METHOD /path"` to merged error schemas
|
|
55
|
+
* @param route - the surface route to validate against
|
|
56
|
+
* @param status - expected HTTP status code
|
|
57
|
+
* @param body - the parsed response body to validate
|
|
58
|
+
*/
|
|
59
|
+
export declare const assert_error_schema_valid: (lookup: Map<string, RouteErrorSchemas>, route: AppSurfaceRoute, status: number, body: unknown) => void;
|
|
60
|
+
export declare const assert_full_middleware_stack: (surface: AppSurface, path_prefix: string, expected_middleware: Array<string>) => void;
|
|
61
|
+
//# sourceMappingURL=assertions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/assertions.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAe7B,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAE3B,OAAO,KAAK,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,UAAU,MAAM,EAAE,iBAAiB,MAAM,KAAG,MACtB,CAAC;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,GAC3C,SAAS,UAAU,EACnB,eAAe,MAAM,KACnB,IAOF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,GAAI,eAAe,MAAM,UAAU,KAAG,IAE9E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,GAC9C,SAAS,UAAU,EACnB,iBAAiB,KAAK,CAAC,MAAM,CAAC,KAC5B,IAWF,CAAC;AAEF;;;;;;GAMG;AACH;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,GAClC,QAAQ,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACtC,OAAO,eAAe,EACtB,QAAQ,MAAM,KACZ,CAAC,CAAC,OAAO,GAAG,SAGd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,GACrC,QAAQ,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACtC,OAAO,eAAe,EACtB,QAAQ,MAAM,EACd,MAAM,OAAO,KACX,IAIF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACxC,SAAS,UAAU,EACnB,aAAa,MAAM,EACnB,qBAAqB,KAAK,CAAC,MAAM,CAAC,KAChC,IAUF,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Assertion helpers for auth attack surface testing.
|
|
4
|
+
*
|
|
5
|
+
* Plain functions called inside explicit `test()` blocks to verify
|
|
6
|
+
* surface snapshots, public routes, and middleware stacks.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { resolve, dirname } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { assert } from 'vitest';
|
|
14
|
+
/**
|
|
15
|
+
* Resolve an absolute path relative to the caller's module.
|
|
16
|
+
*
|
|
17
|
+
* @param filename - the filename to resolve
|
|
18
|
+
* @param import_meta_url - the caller's `import.meta.url`
|
|
19
|
+
* @returns absolute path
|
|
20
|
+
*/
|
|
21
|
+
export const resolve_fixture_path = (filename, import_meta_url) => resolve(dirname(fileURLToPath(import_meta_url)), filename);
|
|
22
|
+
/**
|
|
23
|
+
* Compare live surface against a committed snapshot JSON file.
|
|
24
|
+
*
|
|
25
|
+
* @param surface - the live surface to check
|
|
26
|
+
* @param snapshot_path - absolute path to the committed JSON snapshot
|
|
27
|
+
*/
|
|
28
|
+
export const assert_surface_matches_snapshot = (surface, snapshot_path) => {
|
|
29
|
+
const committed = JSON.parse(readFileSync(snapshot_path, 'utf-8'));
|
|
30
|
+
assert.deepStrictEqual(surface, committed, 'Attack surface changed! Run `gro gen` to update the snapshot, then review the diff.');
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Verify surface generation is deterministic (build twice, compare).
|
|
34
|
+
*
|
|
35
|
+
* @param build_surface - function that builds the surface
|
|
36
|
+
*/
|
|
37
|
+
export const assert_surface_deterministic = (build_surface) => {
|
|
38
|
+
assert.deepStrictEqual(build_surface(), build_surface());
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Bidirectional check: no unexpected public routes, no missing expected ones.
|
|
42
|
+
*
|
|
43
|
+
* @param surface - the app surface to check
|
|
44
|
+
* @param expected_public - format: `['GET /health', 'POST /api/account/login']`
|
|
45
|
+
*/
|
|
46
|
+
export const assert_only_expected_public_routes = (surface, expected_public) => {
|
|
47
|
+
const expected = new Set(expected_public);
|
|
48
|
+
const actual_public = surface.routes
|
|
49
|
+
.filter((r) => r.auth.type === 'none')
|
|
50
|
+
.map((r) => `${r.method} ${r.path}`);
|
|
51
|
+
const unexpected = actual_public.filter((r) => !expected.has(r));
|
|
52
|
+
const missing = expected_public.filter((r) => !actual_public.includes(r));
|
|
53
|
+
assert.strictEqual(unexpected.length, 0, `Unexpected public routes: ${unexpected.join(', ')}`);
|
|
54
|
+
assert.strictEqual(missing.length, 0, `Expected public routes missing: ${missing.join(', ')}`);
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Verify every route under a path prefix has the exact expected middleware stack.
|
|
58
|
+
*
|
|
59
|
+
* @param surface - the app surface to check
|
|
60
|
+
* @param path_prefix - prefix to filter routes (e.g. `'/api/'`)
|
|
61
|
+
* @param expected_middleware - the exact middleware names in order
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* Look up the merged error schema for a route+status from a pre-built schema lookup.
|
|
65
|
+
*
|
|
66
|
+
* @param lookup - map from `"METHOD /path"` to merged error schemas
|
|
67
|
+
* @param route - the surface route to look up
|
|
68
|
+
* @param status - HTTP status code
|
|
69
|
+
*/
|
|
70
|
+
export const get_route_error_schema = (lookup, route, status) => {
|
|
71
|
+
const key = `${route.method} ${route.path}`;
|
|
72
|
+
return lookup.get(key)?.[status];
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Assert that an error schema exists for a route+status and validate the body against it.
|
|
76
|
+
*
|
|
77
|
+
* Protected routes should always have auto-derived error schemas (401 for authenticated,
|
|
78
|
+
* 403 for role-restricted). A missing schema indicates a gap in error schema derivation.
|
|
79
|
+
*
|
|
80
|
+
* @param lookup - map from `"METHOD /path"` to merged error schemas
|
|
81
|
+
* @param route - the surface route to validate against
|
|
82
|
+
* @param status - expected HTTP status code
|
|
83
|
+
* @param body - the parsed response body to validate
|
|
84
|
+
*/
|
|
85
|
+
export const assert_error_schema_valid = (lookup, route, status, body) => {
|
|
86
|
+
const schema = get_route_error_schema(lookup, route, status);
|
|
87
|
+
assert.ok(schema, `missing error schema for ${status} on ${route.method} ${route.path}`);
|
|
88
|
+
schema.parse(body);
|
|
89
|
+
};
|
|
90
|
+
export const assert_full_middleware_stack = (surface, path_prefix, expected_middleware) => {
|
|
91
|
+
const routes = surface.routes.filter((r) => r.path.startsWith(path_prefix));
|
|
92
|
+
assert.ok(routes.length > 0, `No routes found under ${path_prefix}`);
|
|
93
|
+
for (const route of routes) {
|
|
94
|
+
assert.deepStrictEqual(route.applicable_middleware, expected_middleware, `${route.method} ${route.path} has wrong middleware stack`);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import { type SurfaceSecurityPolicyOptions, type ErrorSchemaTightnessOptions } from './surface_invariants.js';
|
|
3
|
+
import { type AppSurfaceSpec } from '../http/surface.js';
|
|
4
|
+
/** Options for adversarial test runners (auth enforcement and input validation). */
|
|
5
|
+
export interface AdversarialTestOptions {
|
|
6
|
+
/** Build the app surface bundle (surface + route specs + middleware specs). */
|
|
7
|
+
build: () => AppSurfaceSpec;
|
|
8
|
+
/** All roles in the app (e.g. `['admin', 'keeper']`). */
|
|
9
|
+
roles: Array<string>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate adversarial HTTP auth enforcement test suites.
|
|
13
|
+
*
|
|
14
|
+
* Describe blocks:
|
|
15
|
+
* - unauthenticated → 401 — every protected route
|
|
16
|
+
* - wrong role → 403 — every role route, tested with all non-matching roles
|
|
17
|
+
* - authenticated without role → 403 — every role route, no-role context
|
|
18
|
+
* - correct auth passes guard — every protected route, assert not 401/403
|
|
19
|
+
*
|
|
20
|
+
* @param options - the test configuration
|
|
21
|
+
*/
|
|
22
|
+
export declare const describe_adversarial_auth: (options: AdversarialTestOptions) => void;
|
|
23
|
+
/** Options for the standard attack surface test suite. */
|
|
24
|
+
export interface StandardAttackSurfaceOptions {
|
|
25
|
+
/** Build the app surface bundle (surface + route specs + middleware specs). */
|
|
26
|
+
build: () => AppSurfaceSpec;
|
|
27
|
+
/** Absolute path to the committed snapshot JSON file. */
|
|
28
|
+
snapshot_path: string;
|
|
29
|
+
/** Expected public routes, e.g. `['GET /health', 'POST /api/account/login']`. */
|
|
30
|
+
expected_public_routes: Array<string>;
|
|
31
|
+
/** Expected middleware names for API routes, e.g. `['origin', 'session', 'request_context', 'bearer_auth']`. */
|
|
32
|
+
expected_api_middleware: Array<string>;
|
|
33
|
+
/** All roles in the app (e.g. `['admin', 'keeper']`). */
|
|
34
|
+
roles: Array<string>;
|
|
35
|
+
/** Path prefix for middleware stack assertion. Default `'/api/'`. */
|
|
36
|
+
api_path_prefix?: string;
|
|
37
|
+
/** Security policy configuration. Omit for sensible defaults. */
|
|
38
|
+
security_policy?: SurfaceSecurityPolicyOptions;
|
|
39
|
+
/** Error schema tightness assertion. Omit for informational-only behavior. */
|
|
40
|
+
error_schema_tightness?: ErrorSchemaTightnessOptions;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run the standard attack surface test suite.
|
|
44
|
+
*
|
|
45
|
+
* Generates 10 test groups:
|
|
46
|
+
* 1. Snapshot — live surface matches committed JSON
|
|
47
|
+
* 2. Determinism — building twice yields identical results
|
|
48
|
+
* 3. Public routes — bidirectional check (no unexpected, no missing)
|
|
49
|
+
* 4. Middleware stack — every API route has the full middleware chain
|
|
50
|
+
* 5. Surface invariants — structural assertions (error schemas, descriptions, duplicates, consistency)
|
|
51
|
+
* 6. Security policy — rate limiting on sensitive routes, no unexpected public mutations, method conventions
|
|
52
|
+
* 7. Error schema tightness audit — informational log of generic vs specific error schemas
|
|
53
|
+
* 8. Adversarial auth — unauthenticated/wrong-role/correct-auth enforcement
|
|
54
|
+
* 9. Adversarial input — input body and params validation
|
|
55
|
+
* 10. Adversarial 404 — stub 404 handlers, validate response bodies against declared schemas
|
|
56
|
+
*
|
|
57
|
+
* Consumer test files call this with project-specific options, then add
|
|
58
|
+
* any project-specific assertions in additional `describe` blocks.
|
|
59
|
+
*
|
|
60
|
+
* @param options - the test configuration
|
|
61
|
+
*/
|
|
62
|
+
export declare const describe_standard_attack_surface_tests: (options: StandardAttackSurfaceOptions) => void;
|
|
63
|
+
//# sourceMappingURL=attack_surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attack_surface.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/attack_surface.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAoB7B,OAAO,EAKN,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,MAAM,yBAAyB,CAAC;AAoBjC,OAAO,EAA4B,KAAK,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAsClF,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACtC,+EAA+E;IAC/E,KAAK,EAAE,MAAM,cAAc,CAAC;IAC5B,yDAAyD;IACzD,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,sBAAsB,KAAG,IAkH3E,CAAC;AAIF,0DAA0D;AAC1D,MAAM,WAAW,4BAA4B;IAC5C,+EAA+E;IAC/E,KAAK,EAAE,MAAM,cAAc,CAAC;IAC5B,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,sBAAsB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,gHAAgH;IAChH,uBAAuB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC,yDAAyD;IACzD,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,eAAe,CAAC,EAAE,4BAA4B,CAAC;IAC/C,8EAA8E;IAC9E,sBAAsB,CAAC,EAAE,2BAA2B,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,sCAAsC,GAClD,SAAS,4BAA4B,KACnC,IAoEF,CAAC"}
|