@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,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic session management for cookie-based auth.
|
|
3
|
+
*
|
|
4
|
+
* Parameterized on identity type via `SessionOptions<TIdentity>`.
|
|
5
|
+
* Handles signing, expiration, and key rotation. Apps provide
|
|
6
|
+
* encode/decode for their specific identity format.
|
|
7
|
+
*
|
|
8
|
+
* Cookie value format: `${encode(identity)}:${expires_at}` (signed with HMAC-SHA256).
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { Keyring } from './keyring.js';
|
|
13
|
+
/** Cookie max age in seconds (30 days — aligned with AUTH_SESSION_LIFETIME_MS). */
|
|
14
|
+
export declare const SESSION_AGE_MAX: number;
|
|
15
|
+
/**
|
|
16
|
+
* Cookie options for session cookies.
|
|
17
|
+
*/
|
|
18
|
+
export interface SessionCookieOptions {
|
|
19
|
+
path: string;
|
|
20
|
+
httpOnly: boolean;
|
|
21
|
+
secure: boolean;
|
|
22
|
+
sameSite: 'strict' | 'lax' | 'none';
|
|
23
|
+
maxAge: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default cookie options for session cookies.
|
|
27
|
+
*
|
|
28
|
+
* Uses strict security settings:
|
|
29
|
+
* - `secure: true` - Works on localhost in Chrome/Firefox (treated as secure context)
|
|
30
|
+
* - `sameSite: 'strict'` - Prevents CSRF
|
|
31
|
+
* - `httpOnly: true` - Prevents XSS access to cookie
|
|
32
|
+
*/
|
|
33
|
+
export declare const SESSION_COOKIE_OPTIONS: SessionCookieOptions;
|
|
34
|
+
/**
|
|
35
|
+
* Configuration for a session cookie format.
|
|
36
|
+
*
|
|
37
|
+
* Apps provide encode/decode to control the identity portion
|
|
38
|
+
* of the cookie payload.
|
|
39
|
+
*
|
|
40
|
+
* The `TIdentity` type parameter determines the trust model:
|
|
41
|
+
* - `string` (e.g. a session_id) — the cookie references a server-side session record,
|
|
42
|
+
* enabling per-session revocation and metadata. Use when you need admin controls
|
|
43
|
+
* like "revoke all sessions" or per-session audit trails.
|
|
44
|
+
* - `number` (e.g. an account_id) — the cookie directly encodes the user identity,
|
|
45
|
+
* requiring no server-side session state. Simpler, but individual sessions
|
|
46
|
+
* can only be invalidated by rotating the signing key (which invalidates all sessions).
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* // tx: 3-part format (admin:session_id)
|
|
51
|
+
* const tx_config: SessionOptions<string> = {
|
|
52
|
+
* cookie_name: 'tx_session',
|
|
53
|
+
* context_key: 'auth_session_id',
|
|
54
|
+
* encode_identity: (session_id) => `admin:${session_id}`,
|
|
55
|
+
* decode_identity: (payload) => {
|
|
56
|
+
* const parts = payload.split(':');
|
|
57
|
+
* if (parts.length !== 2 || parts[0] !== 'admin') return null;
|
|
58
|
+
* return parts[1] || null;
|
|
59
|
+
* },
|
|
60
|
+
* };
|
|
61
|
+
*
|
|
62
|
+
* // visiones: 1-part format (account_id)
|
|
63
|
+
* const visiones_config: SessionOptions<number> = {
|
|
64
|
+
* cookie_name: 'session_id',
|
|
65
|
+
* context_key: 'auth_session_id',
|
|
66
|
+
* encode_identity: (id) => String(id),
|
|
67
|
+
* decode_identity: (payload) => {
|
|
68
|
+
* const n = parseInt(payload, 10);
|
|
69
|
+
* return Number.isFinite(n) && n > 0 ? n : null;
|
|
70
|
+
* },
|
|
71
|
+
* };
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export interface SessionOptions<TIdentity> {
|
|
75
|
+
cookie_name: string;
|
|
76
|
+
/** Hono context variable name for the identity. */
|
|
77
|
+
context_key: string;
|
|
78
|
+
max_age?: number;
|
|
79
|
+
cookie_options?: Partial<SessionCookieOptions>;
|
|
80
|
+
/** Encode identity into the cookie payload (before the `:expires_at` suffix). */
|
|
81
|
+
encode_identity: (identity: TIdentity) => string;
|
|
82
|
+
/** Decode identity from cookie payload. Return null if invalid. */
|
|
83
|
+
decode_identity: (payload: string) => TIdentity | null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Result of parsing a signed session cookie.
|
|
87
|
+
*/
|
|
88
|
+
export interface ParsedSession<TIdentity> {
|
|
89
|
+
/** The decoded identity. */
|
|
90
|
+
identity: TIdentity;
|
|
91
|
+
/** True if verified with a non-primary key (needs re-signing). */
|
|
92
|
+
should_refresh_signature: boolean;
|
|
93
|
+
/** Index of the key that verified the signature. */
|
|
94
|
+
key_index: number;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parse a signed session cookie value.
|
|
98
|
+
*
|
|
99
|
+
* The signed value format is `${encode(identity)}:${expires_at}`.
|
|
100
|
+
* Tries all keys in order to support key rotation.
|
|
101
|
+
*
|
|
102
|
+
* @param signed_value - the raw cookie value (signed)
|
|
103
|
+
* @param keyring - key ring for verification
|
|
104
|
+
* @param options - session configuration with decode logic
|
|
105
|
+
* @param now_seconds - current time in seconds (for testing)
|
|
106
|
+
* @returns `ParsedSession` if valid, null if invalid/expired, undefined if empty/missing
|
|
107
|
+
*/
|
|
108
|
+
export declare const parse_session: <TIdentity>(signed_value: string | undefined, keyring: Keyring, options: SessionOptions<TIdentity>, now_seconds?: number) => Promise<ParsedSession<TIdentity> | null | undefined>;
|
|
109
|
+
/**
|
|
110
|
+
* Create a signed session cookie value.
|
|
111
|
+
*
|
|
112
|
+
* Format: `${encode(identity)}:${expires_at}` signed with HMAC-SHA256.
|
|
113
|
+
* Embeds expiration in the signed value itself for defense-in-depth.
|
|
114
|
+
*
|
|
115
|
+
* @param keyring - key ring for signing
|
|
116
|
+
* @param identity - the identity to encode
|
|
117
|
+
* @param options - session configuration with encode logic
|
|
118
|
+
* @param now_seconds - current time in seconds (for testing)
|
|
119
|
+
* @returns signed cookie value string
|
|
120
|
+
*/
|
|
121
|
+
export declare const create_session_cookie_value: <TIdentity>(keyring: Keyring, identity: TIdentity, options: SessionOptions<TIdentity>, now_seconds?: number) => Promise<string>;
|
|
122
|
+
/**
|
|
123
|
+
* Result of processing a session cookie.
|
|
124
|
+
*/
|
|
125
|
+
export interface ProcessSessionResult<TIdentity> {
|
|
126
|
+
/** Whether the session is valid. */
|
|
127
|
+
valid: boolean;
|
|
128
|
+
/** Action the adapter should take. */
|
|
129
|
+
action: 'none' | 'clear' | 'refresh';
|
|
130
|
+
/** New signed value when action is 'refresh'. */
|
|
131
|
+
new_signed_value?: string;
|
|
132
|
+
/** The decoded identity if the cookie was valid. */
|
|
133
|
+
identity?: TIdentity;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Create a session config for raw session token identity.
|
|
137
|
+
*
|
|
138
|
+
* The standard pattern: cookie stores the raw session token,
|
|
139
|
+
* server hashes it (blake3) to look up the `auth_session` row.
|
|
140
|
+
* Only the `cookie_name` varies per app.
|
|
141
|
+
*
|
|
142
|
+
* @param cookie_name - cookie name (e.g. `'tx_session'`, `'visiones_session'`)
|
|
143
|
+
* @returns a `SessionOptions<string>` ready for use with session middleware
|
|
144
|
+
*/
|
|
145
|
+
export declare const create_session_config: (cookie_name: string) => SessionOptions<string>;
|
|
146
|
+
/** Canonical session config for fuz_app auth. */
|
|
147
|
+
export declare const fuz_session_config: SessionOptions<string>;
|
|
148
|
+
/**
|
|
149
|
+
* Process a session cookie and determine what action to take.
|
|
150
|
+
*
|
|
151
|
+
* @param signed_value - the raw cookie value (may be undefined)
|
|
152
|
+
* @param keyring - key ring for verification and signing
|
|
153
|
+
* @param options - session configuration
|
|
154
|
+
* @param now_seconds - current time in seconds (for testing)
|
|
155
|
+
* @returns result with validity and action to take
|
|
156
|
+
*/
|
|
157
|
+
export declare const process_session_cookie: <TIdentity>(signed_value: string | undefined, keyring: Keyring, options: SessionOptions<TIdentity>, now_seconds?: number) => Promise<ProcessSessionResult<TIdentity>>;
|
|
158
|
+
//# sourceMappingURL=session_cookie.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_cookie.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/session_cookie.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAE1C,mFAAmF;AACnF,eAAO,MAAM,eAAe,QAAoB,CAAC;AAKjD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,oBAMpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,WAAW,cAAc,CAAC,SAAS;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC/C,iFAAiF;IACjF,eAAe,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,MAAM,CAAC;IACjD,mEAAmE;IACnE,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,GAAG,IAAI,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,SAAS;IACvC,4BAA4B;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,kEAAkE;IAClE,wBAAwB,EAAE,OAAO,CAAC;IAClC,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GAAU,SAAS,EAC5C,cAAc,MAAM,GAAG,SAAS,EAChC,SAAS,OAAO,EAChB,SAAS,cAAc,CAAC,SAAS,CAAC,EAClC,cAAc,MAAM,KAClB,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,CA4BrD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,GAAU,SAAS,EAC1D,SAAS,OAAO,EAChB,UAAU,SAAS,EACnB,SAAS,cAAc,CAAC,SAAS,CAAC,EAClC,cAAc,MAAM,KAClB,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,SAAS;IAC9C,oCAAoC;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,sCAAsC;IACtC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,MAAM,KAAG,cAAc,CAAC,MAAM,CAK/E,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,MAAM,CAAwC,CAAC;AAE/F;;;;;;;;GAQG;AAEH,eAAO,MAAM,sBAAsB,GAAU,SAAS,EACrD,cAAc,MAAM,GAAG,SAAS,EAChC,SAAS,OAAO,EAChB,SAAS,cAAc,CAAC,SAAS,CAAC,EAClC,cAAc,MAAM,KAClB,OAAO,CAAC,oBAAoB,CAAC,SAAS,CAAC,CA4BzC,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic session management for cookie-based auth.
|
|
3
|
+
*
|
|
4
|
+
* Parameterized on identity type via `SessionOptions<TIdentity>`.
|
|
5
|
+
* Handles signing, expiration, and key rotation. Apps provide
|
|
6
|
+
* encode/decode for their specific identity format.
|
|
7
|
+
*
|
|
8
|
+
* Cookie value format: `${encode(identity)}:${expires_at}` (signed with HMAC-SHA256).
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/** Cookie max age in seconds (30 days — aligned with AUTH_SESSION_LIFETIME_MS). */
|
|
13
|
+
export const SESSION_AGE_MAX = 60 * 60 * 24 * 30;
|
|
14
|
+
/** Separator between identity payload and expires_at in signed value. */
|
|
15
|
+
const VALUE_SEPARATOR = ':';
|
|
16
|
+
/**
|
|
17
|
+
* Default cookie options for session cookies.
|
|
18
|
+
*
|
|
19
|
+
* Uses strict security settings:
|
|
20
|
+
* - `secure: true` - Works on localhost in Chrome/Firefox (treated as secure context)
|
|
21
|
+
* - `sameSite: 'strict'` - Prevents CSRF
|
|
22
|
+
* - `httpOnly: true` - Prevents XSS access to cookie
|
|
23
|
+
*/
|
|
24
|
+
export const SESSION_COOKIE_OPTIONS = {
|
|
25
|
+
path: '/',
|
|
26
|
+
httpOnly: true,
|
|
27
|
+
secure: true,
|
|
28
|
+
sameSite: 'strict',
|
|
29
|
+
maxAge: SESSION_AGE_MAX,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Parse a signed session cookie value.
|
|
33
|
+
*
|
|
34
|
+
* The signed value format is `${encode(identity)}:${expires_at}`.
|
|
35
|
+
* Tries all keys in order to support key rotation.
|
|
36
|
+
*
|
|
37
|
+
* @param signed_value - the raw cookie value (signed)
|
|
38
|
+
* @param keyring - key ring for verification
|
|
39
|
+
* @param options - session configuration with decode logic
|
|
40
|
+
* @param now_seconds - current time in seconds (for testing)
|
|
41
|
+
* @returns `ParsedSession` if valid, null if invalid/expired, undefined if empty/missing
|
|
42
|
+
*/
|
|
43
|
+
export const parse_session = async (signed_value, keyring, options, now_seconds) => {
|
|
44
|
+
if (!signed_value)
|
|
45
|
+
return undefined;
|
|
46
|
+
const result = await keyring.verify(signed_value);
|
|
47
|
+
if (!result)
|
|
48
|
+
return null;
|
|
49
|
+
// Split on the last VALUE_SEPARATOR to get identity_payload and expires_at
|
|
50
|
+
const last_sep = result.value.lastIndexOf(VALUE_SEPARATOR);
|
|
51
|
+
if (last_sep === -1)
|
|
52
|
+
return null;
|
|
53
|
+
const identity_payload = result.value.slice(0, last_sep);
|
|
54
|
+
const expires_at_str = result.value.slice(last_sep + 1);
|
|
55
|
+
const identity = options.decode_identity(identity_payload);
|
|
56
|
+
if (identity === null)
|
|
57
|
+
return null;
|
|
58
|
+
const expires_at = parseInt(expires_at_str, 10);
|
|
59
|
+
if (!Number.isFinite(expires_at))
|
|
60
|
+
return null;
|
|
61
|
+
// Check expiration
|
|
62
|
+
const now = now_seconds ?? Math.floor(Date.now() / 1000);
|
|
63
|
+
if (expires_at <= now)
|
|
64
|
+
return null;
|
|
65
|
+
return {
|
|
66
|
+
identity,
|
|
67
|
+
should_refresh_signature: result.key_index > 0,
|
|
68
|
+
key_index: result.key_index,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Create a signed session cookie value.
|
|
73
|
+
*
|
|
74
|
+
* Format: `${encode(identity)}:${expires_at}` signed with HMAC-SHA256.
|
|
75
|
+
* Embeds expiration in the signed value itself for defense-in-depth.
|
|
76
|
+
*
|
|
77
|
+
* @param keyring - key ring for signing
|
|
78
|
+
* @param identity - the identity to encode
|
|
79
|
+
* @param options - session configuration with encode logic
|
|
80
|
+
* @param now_seconds - current time in seconds (for testing)
|
|
81
|
+
* @returns signed cookie value string
|
|
82
|
+
*/
|
|
83
|
+
export const create_session_cookie_value = async (keyring, identity, options, now_seconds) => {
|
|
84
|
+
const max_age = options.max_age ?? SESSION_AGE_MAX;
|
|
85
|
+
const now = now_seconds ?? Math.floor(Date.now() / 1000);
|
|
86
|
+
const expires_at = now + max_age;
|
|
87
|
+
const value = `${options.encode_identity(identity)}${VALUE_SEPARATOR}${expires_at}`;
|
|
88
|
+
return keyring.sign(value);
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Create a session config for raw session token identity.
|
|
92
|
+
*
|
|
93
|
+
* The standard pattern: cookie stores the raw session token,
|
|
94
|
+
* server hashes it (blake3) to look up the `auth_session` row.
|
|
95
|
+
* Only the `cookie_name` varies per app.
|
|
96
|
+
*
|
|
97
|
+
* @param cookie_name - cookie name (e.g. `'tx_session'`, `'visiones_session'`)
|
|
98
|
+
* @returns a `SessionOptions<string>` ready for use with session middleware
|
|
99
|
+
*/
|
|
100
|
+
export const create_session_config = (cookie_name) => ({
|
|
101
|
+
cookie_name,
|
|
102
|
+
context_key: 'auth_session_id',
|
|
103
|
+
encode_identity: (session_id) => session_id,
|
|
104
|
+
decode_identity: (payload) => payload || null,
|
|
105
|
+
});
|
|
106
|
+
/** Canonical session config for fuz_app auth. */
|
|
107
|
+
export const fuz_session_config = create_session_config('fuz_session');
|
|
108
|
+
/**
|
|
109
|
+
* Process a session cookie and determine what action to take.
|
|
110
|
+
*
|
|
111
|
+
* @param signed_value - the raw cookie value (may be undefined)
|
|
112
|
+
* @param keyring - key ring for verification and signing
|
|
113
|
+
* @param options - session configuration
|
|
114
|
+
* @param now_seconds - current time in seconds (for testing)
|
|
115
|
+
* @returns result with validity and action to take
|
|
116
|
+
*/
|
|
117
|
+
export const process_session_cookie = async (signed_value, keyring, options, now_seconds) => {
|
|
118
|
+
const now = now_seconds ?? Math.floor(Date.now() / 1000);
|
|
119
|
+
const parsed = await parse_session(signed_value, keyring, options, now);
|
|
120
|
+
if (parsed === undefined) {
|
|
121
|
+
// No cookie present
|
|
122
|
+
return { valid: false, action: 'none' };
|
|
123
|
+
}
|
|
124
|
+
if (parsed === null) {
|
|
125
|
+
// Invalid cookie - should be cleared
|
|
126
|
+
return { valid: false, action: 'clear' };
|
|
127
|
+
}
|
|
128
|
+
// Valid session
|
|
129
|
+
if (parsed.should_refresh_signature) {
|
|
130
|
+
// Re-sign with current key (extends expiration)
|
|
131
|
+
const new_signed_value = await create_session_cookie_value(keyring, parsed.identity, options, now);
|
|
132
|
+
return { valid: true, action: 'refresh', new_signed_value, identity: parsed.identity };
|
|
133
|
+
}
|
|
134
|
+
return { valid: true, action: 'none', identity: parsed.identity };
|
|
135
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session lifecycle — creation and cookie management shared across login and bootstrap flows.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from 'hono';
|
|
7
|
+
import type { Keyring } from './keyring.js';
|
|
8
|
+
import { type SessionOptions } from './session_cookie.js';
|
|
9
|
+
import type { QueryDeps } from '../db/query_deps.js';
|
|
10
|
+
/**
|
|
11
|
+
* Options for `create_session_and_set_cookie`.
|
|
12
|
+
*/
|
|
13
|
+
export interface CreateSessionAndSetCookieOptions {
|
|
14
|
+
/** Keyring for cookie signing. */
|
|
15
|
+
keyring: Keyring;
|
|
16
|
+
/** Query deps (needs db for session creation). */
|
|
17
|
+
deps: QueryDeps;
|
|
18
|
+
/** Hono context for setting the cookie. */
|
|
19
|
+
c: Context;
|
|
20
|
+
/** The account to create a session for. */
|
|
21
|
+
account_id: string;
|
|
22
|
+
/** Session cookie configuration. */
|
|
23
|
+
session_options: SessionOptions<string>;
|
|
24
|
+
/** Per-account session cap (`null` to skip enforcement). */
|
|
25
|
+
max_sessions?: number | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create an auth session and set the session cookie on the response.
|
|
29
|
+
*
|
|
30
|
+
* Shared by login and bootstrap — generates a token, hashes it, persists
|
|
31
|
+
* the session row, optionally enforces a per-account session limit, and
|
|
32
|
+
* sets the signed cookie.
|
|
33
|
+
*/
|
|
34
|
+
export declare const create_session_and_set_cookie: (options: CreateSessionAndSetCookieOptions) => Promise<void>;
|
|
35
|
+
//# sourceMappingURL=session_lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_lifecycle.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/session_lifecycle.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAElC,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,EAA8B,KAAK,cAAc,EAAC,MAAM,qBAAqB,CAAC;AASrF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAChD,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,IAAI,EAAE,SAAS,CAAC;IAChB,2CAA2C;IAC3C,CAAC,EAAE,OAAO,CAAC;IACX,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACzC,SAAS,gCAAgC,KACvC,OAAO,CAAC,IAAI,CAad,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session lifecycle — creation and cookie management shared across login and bootstrap flows.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { create_session_cookie_value } from './session_cookie.js';
|
|
7
|
+
import { set_session_cookie } from './session_middleware.js';
|
|
8
|
+
import { generate_session_token, hash_session_token, AUTH_SESSION_LIFETIME_MS, query_create_session, query_session_enforce_limit, } from './session_queries.js';
|
|
9
|
+
/**
|
|
10
|
+
* Create an auth session and set the session cookie on the response.
|
|
11
|
+
*
|
|
12
|
+
* Shared by login and bootstrap — generates a token, hashes it, persists
|
|
13
|
+
* the session row, optionally enforces a per-account session limit, and
|
|
14
|
+
* sets the signed cookie.
|
|
15
|
+
*/
|
|
16
|
+
export const create_session_and_set_cookie = async (options) => {
|
|
17
|
+
const { keyring, deps, c, account_id, session_options, max_sessions } = options;
|
|
18
|
+
const session_token = generate_session_token();
|
|
19
|
+
const token_hash = hash_session_token(session_token);
|
|
20
|
+
const expires_at = new Date(Date.now() + AUTH_SESSION_LIFETIME_MS);
|
|
21
|
+
await query_create_session(deps, token_hash, account_id, expires_at);
|
|
22
|
+
if (max_sessions != null) {
|
|
23
|
+
await query_session_enforce_limit(deps, account_id, max_sessions);
|
|
24
|
+
}
|
|
25
|
+
const cookie_value = await create_session_cookie_value(keyring, session_token, session_options);
|
|
26
|
+
set_session_cookie(c, cookie_value, session_options);
|
|
27
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hono session middleware using generic session management.
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper that gets/sets cookies and delegates to session processing.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import type { Context, MiddlewareHandler } from 'hono';
|
|
9
|
+
import type { Keyring } from './keyring.js';
|
|
10
|
+
import { type SessionOptions } from './session_cookie.js';
|
|
11
|
+
/**
|
|
12
|
+
* Read the session cookie value from a request.
|
|
13
|
+
*/
|
|
14
|
+
export declare const get_session_cookie: <T>(c: Context, options: SessionOptions<T>) => string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Set the session cookie on a response.
|
|
17
|
+
*/
|
|
18
|
+
export declare const set_session_cookie: <T>(c: Context, value: string, options: SessionOptions<T>) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Clear the session cookie on a response.
|
|
21
|
+
*/
|
|
22
|
+
export declare const clear_session_cookie: <T>(c: Context, options: SessionOptions<T>) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Create session middleware that parses cookies and sets identity on context.
|
|
25
|
+
*
|
|
26
|
+
* Always sets the identity on context (null when invalid/missing) for type-safe reads.
|
|
27
|
+
* Uses `options.context_key` as the Hono context variable name.
|
|
28
|
+
*
|
|
29
|
+
* @param keyring - key ring for cookie verification
|
|
30
|
+
* @param options - session configuration
|
|
31
|
+
*/
|
|
32
|
+
export declare const create_session_middleware: <TIdentity>(keyring: Keyring, options: SessionOptions<TIdentity>) => MiddlewareHandler;
|
|
33
|
+
//# sourceMappingURL=session_middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_middleware.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/session_middleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAC;AAGrD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,EACN,KAAK,cAAc,EAInB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,EACnC,GAAG,OAAO,EACV,SAAS,cAAc,CAAC,CAAC,CAAC,KACxB,MAAM,GAAG,SAEX,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,EACnC,GAAG,OAAO,EACV,OAAO,MAAM,EACb,SAAS,cAAc,CAAC,CAAC,CAAC,KACxB,IASF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,cAAc,CAAC,CAAC,CAAC,KAAG,IAMhF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,EAClD,SAAS,OAAO,EAChB,SAAS,cAAc,CAAC,SAAS,CAAC,KAChC,iBAgBF,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hono session middleware using generic session management.
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper that gets/sets cookies and delegates to session processing.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { getCookie, setCookie, deleteCookie } from 'hono/cookie';
|
|
9
|
+
import { SESSION_COOKIE_OPTIONS, process_session_cookie, } from './session_cookie.js';
|
|
10
|
+
/**
|
|
11
|
+
* Read the session cookie value from a request.
|
|
12
|
+
*/
|
|
13
|
+
export const get_session_cookie = (c, options) => {
|
|
14
|
+
return getCookie(c, options.cookie_name);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Set the session cookie on a response.
|
|
18
|
+
*/
|
|
19
|
+
export const set_session_cookie = (c, value, options) => {
|
|
20
|
+
const cookie_options = {
|
|
21
|
+
...SESSION_COOKIE_OPTIONS,
|
|
22
|
+
...options.cookie_options,
|
|
23
|
+
};
|
|
24
|
+
if (options.max_age !== undefined) {
|
|
25
|
+
cookie_options.maxAge = options.max_age;
|
|
26
|
+
}
|
|
27
|
+
setCookie(c, options.cookie_name, value, cookie_options);
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Clear the session cookie on a response.
|
|
31
|
+
*/
|
|
32
|
+
export const clear_session_cookie = (c, options) => {
|
|
33
|
+
const cookie_options = {
|
|
34
|
+
...SESSION_COOKIE_OPTIONS,
|
|
35
|
+
...options.cookie_options,
|
|
36
|
+
};
|
|
37
|
+
deleteCookie(c, options.cookie_name, cookie_options);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Create session middleware that parses cookies and sets identity on context.
|
|
41
|
+
*
|
|
42
|
+
* Always sets the identity on context (null when invalid/missing) for type-safe reads.
|
|
43
|
+
* Uses `options.context_key` as the Hono context variable name.
|
|
44
|
+
*
|
|
45
|
+
* @param keyring - key ring for cookie verification
|
|
46
|
+
* @param options - session configuration
|
|
47
|
+
*/
|
|
48
|
+
export const create_session_middleware = (keyring, options) => {
|
|
49
|
+
return async (c, next) => {
|
|
50
|
+
const signed_value = get_session_cookie(c, options);
|
|
51
|
+
const result = await process_session_cookie(signed_value, keyring, options);
|
|
52
|
+
// Always set identity (null when invalid/missing) for type-safe reads
|
|
53
|
+
c.set(options.context_key, result.identity ?? null);
|
|
54
|
+
if (result.action === 'clear') {
|
|
55
|
+
clear_session_cookie(c, options);
|
|
56
|
+
}
|
|
57
|
+
else if (result.action === 'refresh' && result.new_signed_value) {
|
|
58
|
+
set_session_cookie(c, result.new_signed_value, options);
|
|
59
|
+
}
|
|
60
|
+
await next();
|
|
61
|
+
};
|
|
62
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth session database queries.
|
|
3
|
+
*
|
|
4
|
+
* Server-side sessions keyed by blake3 hash of the session token.
|
|
5
|
+
* The cookie contains the raw token; the database stores only the hash.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
10
|
+
import type { QueryDeps } from '../db/query_deps.js';
|
|
11
|
+
import type { AuthSession } from './account_schema.js';
|
|
12
|
+
/** Session lifetime in milliseconds (30 days). */
|
|
13
|
+
export declare const AUTH_SESSION_LIFETIME_MS: number;
|
|
14
|
+
/** Extend session when it has less than this remaining (1 day in ms). */
|
|
15
|
+
export declare const AUTH_SESSION_EXTEND_THRESHOLD_MS: number;
|
|
16
|
+
/**
|
|
17
|
+
* Hash a session token to its storage key using blake3.
|
|
18
|
+
*
|
|
19
|
+
* @param token - the raw session token
|
|
20
|
+
* @returns hex-encoded blake3 hash
|
|
21
|
+
*/
|
|
22
|
+
export declare const hash_session_token: (token: string) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Generate a cryptographically random session token.
|
|
25
|
+
*
|
|
26
|
+
* @returns a 32-byte base64url-encoded token
|
|
27
|
+
*/
|
|
28
|
+
export declare const generate_session_token: () => string;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new auth session.
|
|
31
|
+
*
|
|
32
|
+
* @param deps - query dependencies
|
|
33
|
+
* @param token_hash - blake3 hash of the session token (use `hash_session_token`)
|
|
34
|
+
* @param account_id - the account this session belongs to
|
|
35
|
+
* @param expires_at - when the session expires
|
|
36
|
+
*/
|
|
37
|
+
export declare const query_create_session: (deps: QueryDeps, token_hash: string, account_id: string, expires_at: Date) => Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Get a session if it exists, is not expired, and has not been revoked.
|
|
40
|
+
*
|
|
41
|
+
* @param deps - query dependencies
|
|
42
|
+
* @param token_hash - blake3 hash of the session token
|
|
43
|
+
*/
|
|
44
|
+
export declare const query_session_get_valid: (deps: QueryDeps, token_hash: string) => Promise<AuthSession | undefined>;
|
|
45
|
+
/**
|
|
46
|
+
* Update `last_seen_at` and optionally extend expiry for a session.
|
|
47
|
+
*
|
|
48
|
+
* Extends if less than `AUTH_SESSION_EXTEND_THRESHOLD_MS` remaining.
|
|
49
|
+
*
|
|
50
|
+
* @param deps - query dependencies
|
|
51
|
+
* @param token_hash - blake3 hash of the session token
|
|
52
|
+
*/
|
|
53
|
+
export declare const query_session_touch: (deps: QueryDeps, token_hash: string) => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Revoke (delete) a session by its token hash.
|
|
56
|
+
*
|
|
57
|
+
* No account_id constraint — caller must ensure the hash comes from a
|
|
58
|
+
* trusted source (e.g. the authenticated session cookie). For user-facing
|
|
59
|
+
* revocation of a specific session by ID, prefer `query_session_revoke_for_account`
|
|
60
|
+
* which includes an IDOR guard.
|
|
61
|
+
*/
|
|
62
|
+
export declare const query_session_revoke_by_hash: (deps: QueryDeps, token_hash: string) => Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Revoke a session only if it belongs to the specified account.
|
|
65
|
+
*
|
|
66
|
+
* Prevents cross-account session revocation.
|
|
67
|
+
*
|
|
68
|
+
* @param deps - query dependencies
|
|
69
|
+
* @param token_hash - blake3 hash of the session token
|
|
70
|
+
* @param account_id - the account that must own the session
|
|
71
|
+
* @returns `true` if a session was revoked, `false` if not found or wrong account
|
|
72
|
+
*/
|
|
73
|
+
export declare const query_session_revoke_for_account: (deps: QueryDeps, token_hash: string, account_id: string) => Promise<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Revoke all sessions for an account.
|
|
76
|
+
*
|
|
77
|
+
* @returns the number of sessions revoked
|
|
78
|
+
*/
|
|
79
|
+
export declare const query_session_revoke_all_for_account: (deps: QueryDeps, account_id: string) => Promise<number>;
|
|
80
|
+
/**
|
|
81
|
+
* List sessions for an account, newest first.
|
|
82
|
+
*/
|
|
83
|
+
export declare const query_session_list_for_account: (deps: QueryDeps, account_id: string, limit?: number) => Promise<Array<AuthSession>>;
|
|
84
|
+
/**
|
|
85
|
+
* Enforce a per-account session limit by evicting the oldest sessions.
|
|
86
|
+
*
|
|
87
|
+
* Keeps the newest `max_sessions` sessions and deletes the rest.
|
|
88
|
+
*
|
|
89
|
+
* Race safety: this function must run inside a transaction alongside the
|
|
90
|
+
* INSERT that created the new session. All callers satisfy this requirement:
|
|
91
|
+
* - `POST /login` and `POST /tokens/create` use the default `transaction: true`
|
|
92
|
+
* (framework-managed transaction wrapping in `apply_route_specs`)
|
|
93
|
+
* - `POST /bootstrap` and `POST /signup` manage their own transactions
|
|
94
|
+
* and pass the transaction-scoped `deps` to `create_session_and_set_cookie`
|
|
95
|
+
*
|
|
96
|
+
* The transaction ensures the INSERT + enforce_limit pair is atomic —
|
|
97
|
+
* concurrent session creation cannot interleave between the two statements.
|
|
98
|
+
*
|
|
99
|
+
* @param deps - query dependencies (must be transaction-scoped)
|
|
100
|
+
* @param account_id - the account to enforce the limit for
|
|
101
|
+
* @param max_sessions - maximum number of sessions to keep
|
|
102
|
+
* @returns the number of sessions evicted
|
|
103
|
+
*/
|
|
104
|
+
export declare const query_session_enforce_limit: (deps: QueryDeps, account_id: string, max_sessions: number) => Promise<number>;
|
|
105
|
+
/**
|
|
106
|
+
* List all active sessions across all accounts with usernames.
|
|
107
|
+
*
|
|
108
|
+
* @param deps - query dependencies
|
|
109
|
+
* @param limit - maximum entries to return
|
|
110
|
+
* @returns active sessions joined with account usernames, newest activity first
|
|
111
|
+
*/
|
|
112
|
+
export declare const query_session_list_all_active: (deps: QueryDeps, limit?: number) => Promise<Array<AuthSession & {
|
|
113
|
+
username: string;
|
|
114
|
+
}>>;
|
|
115
|
+
/**
|
|
116
|
+
* Delete expired sessions.
|
|
117
|
+
*
|
|
118
|
+
* @returns the number of sessions cleaned up
|
|
119
|
+
*/
|
|
120
|
+
export declare const query_session_cleanup_expired: (deps: QueryDeps) => Promise<number>;
|
|
121
|
+
/**
|
|
122
|
+
* Touch a session without blocking the caller.
|
|
123
|
+
*
|
|
124
|
+
* Errors are logged to console — session touching never breaks request flows.
|
|
125
|
+
* Pass `pending_effects` (from `c.var.pending_effects`) to register
|
|
126
|
+
* the promise for test flushing.
|
|
127
|
+
*
|
|
128
|
+
* @param deps - query dependencies
|
|
129
|
+
* @param token_hash - blake3 hash of the session token
|
|
130
|
+
* @param pending_effects - optional array to register the effect for later awaiting
|
|
131
|
+
* @param log - the logger instance
|
|
132
|
+
* @returns the settled promise (callers may ignore it — fire-and-forget semantics preserved)
|
|
133
|
+
*/
|
|
134
|
+
export declare const session_touch_fire_and_forget: (deps: QueryDeps, token_hash: string, pending_effects: Array<Promise<void>> | undefined, log: Logger) => Promise<void>;
|
|
135
|
+
//# sourceMappingURL=session_queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/session_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAErD,kDAAkD;AAClD,eAAO,MAAM,wBAAwB,QAA2B,CAAC;AAEjE,yEAAyE;AACzE,eAAO,MAAM,gCAAgC,QAAsB,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,KAAG,MAElD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAO,MAEzC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,YAAY,IAAI,KACd,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,WAAW,GAAG,SAAS,CAKjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAU,MAAM,SAAS,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,IAAI,CAY3F,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,IAAI,CAEd,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,YAAY,MAAM,KAChB,OAAO,CAAC,OAAO,CAMjB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,GAChD,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAAU,KACR,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAK5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,2BAA2B,GACvC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAAc,MAAM,KAClB,OAAO,CAAC,MAAM,CAYhB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACzC,MAAM,SAAS,EACf,cAAW,KACT,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAAC,CASjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,GAAU,MAAM,SAAS,KAAG,OAAO,CAAC,MAAM,CAKnF,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,GACzC,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,iBAAiB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,EACjD,KAAK,MAAM,KACT,OAAO,CAAC,IAAI,CAMd,CAAC"}
|