@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,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App surface generation — JSON-serializable attack surface from route and middleware specs.
|
|
3
|
+
*
|
|
4
|
+
* Pure schema helpers (`is_null_schema`, `schema_to_surface`, `middleware_applies`,
|
|
5
|
+
* `merge_error_schemas`) live in `schema_helpers.ts`.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { schema_to_surface, middleware_applies, merge_error_schemas, is_null_schema, is_strict_object_schema, } from './schema_helpers.js';
|
|
11
|
+
// --- Surface generation ---
|
|
12
|
+
/**
|
|
13
|
+
* Collect error schemas from all middleware that applies to a route path.
|
|
14
|
+
*
|
|
15
|
+
* @param middleware - the middleware specs
|
|
16
|
+
* @param route_path - the route path to match against
|
|
17
|
+
* @returns merged middleware error schemas, or `null` if none
|
|
18
|
+
*/
|
|
19
|
+
export const collect_middleware_errors = (middleware, route_path) => {
|
|
20
|
+
const errors = {};
|
|
21
|
+
for (const mw of middleware) {
|
|
22
|
+
if (mw.errors && middleware_applies(mw.path, route_path)) {
|
|
23
|
+
Object.assign(errors, mw.errors);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return Object.keys(errors).length > 0 ? errors : null;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Convert env schema to surface entries using `.meta()` metadata.
|
|
30
|
+
*
|
|
31
|
+
* @param schema - Zod object schema with `.meta()` on fields
|
|
32
|
+
* @returns array of env surface entries
|
|
33
|
+
*/
|
|
34
|
+
export const env_schema_to_surface = (schema) => {
|
|
35
|
+
const entries = [];
|
|
36
|
+
for (const [name, field_schema] of Object.entries(schema.shape)) {
|
|
37
|
+
const field = field_schema;
|
|
38
|
+
const meta = field.meta();
|
|
39
|
+
const undef_result = field.safeParse(undefined);
|
|
40
|
+
entries.push({
|
|
41
|
+
name,
|
|
42
|
+
description: meta?.description ?? '',
|
|
43
|
+
sensitivity: meta?.sensitivity ?? null,
|
|
44
|
+
has_default: undef_result.success && undef_result.data !== undefined,
|
|
45
|
+
optional: undef_result.success,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return entries;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Convert SSE event specs to surface entries.
|
|
52
|
+
*
|
|
53
|
+
* @param event_specs - event specs to convert
|
|
54
|
+
* @returns array of event surface entries
|
|
55
|
+
*/
|
|
56
|
+
export const events_to_surface = (event_specs) => {
|
|
57
|
+
return event_specs.map((spec) => ({
|
|
58
|
+
method: spec.method,
|
|
59
|
+
description: spec.description,
|
|
60
|
+
channel: spec.channel ?? null,
|
|
61
|
+
params_schema: schema_to_surface(spec.params),
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Generate a JSON-serializable attack surface from middleware, route specs,
|
|
66
|
+
* and optional env/event metadata.
|
|
67
|
+
*
|
|
68
|
+
* @param options - the surface generation options
|
|
69
|
+
* @returns the attack surface
|
|
70
|
+
*/
|
|
71
|
+
export const generate_app_surface = (options) => {
|
|
72
|
+
const { route_specs, middleware_specs, env_schema, event_specs } = options;
|
|
73
|
+
const diagnostics = [];
|
|
74
|
+
// Spec-level diagnostics: check for non-strict input schemas
|
|
75
|
+
for (const r of route_specs) {
|
|
76
|
+
if (!is_null_schema(r.input) && !is_strict_object_schema(r.input)) {
|
|
77
|
+
diagnostics.push({
|
|
78
|
+
level: 'warning',
|
|
79
|
+
category: 'schema',
|
|
80
|
+
message: 'Input schema is not z.strictObject() — unknown keys will be silently stripped',
|
|
81
|
+
source: `${r.method} ${r.path} input`,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
diagnostics,
|
|
87
|
+
middleware: middleware_specs.map((m) => {
|
|
88
|
+
let mw_error_schemas = null;
|
|
89
|
+
if (m.errors) {
|
|
90
|
+
const schemas = {};
|
|
91
|
+
for (const [status, schema] of Object.entries(m.errors)) {
|
|
92
|
+
const json_schema = schema_to_surface(schema);
|
|
93
|
+
if (json_schema !== null) {
|
|
94
|
+
schemas[status] = json_schema;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (Object.keys(schemas).length > 0) {
|
|
98
|
+
mw_error_schemas = schemas;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { name: m.name, path: m.path, error_schemas: mw_error_schemas };
|
|
102
|
+
}),
|
|
103
|
+
routes: route_specs.map((r) => {
|
|
104
|
+
const applicable_middleware = middleware_specs
|
|
105
|
+
.filter((m) => middleware_applies(m.path, r.path))
|
|
106
|
+
.map((m) => m.name);
|
|
107
|
+
// Merge auto-derived + middleware + explicit error schemas
|
|
108
|
+
const mw_errors = collect_middleware_errors(middleware_specs, r.path);
|
|
109
|
+
const merged_errors = merge_error_schemas(r, mw_errors);
|
|
110
|
+
let error_schemas = null;
|
|
111
|
+
if (merged_errors) {
|
|
112
|
+
const schemas = {};
|
|
113
|
+
for (const [status, schema] of Object.entries(merged_errors)) {
|
|
114
|
+
const json_schema = schema_to_surface(schema);
|
|
115
|
+
if (json_schema !== null) {
|
|
116
|
+
schemas[status] = json_schema;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (Object.keys(schemas).length > 0) {
|
|
120
|
+
error_schemas = schemas;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
method: r.method,
|
|
125
|
+
path: r.path,
|
|
126
|
+
auth: r.auth,
|
|
127
|
+
applicable_middleware,
|
|
128
|
+
description: r.description,
|
|
129
|
+
is_mutation: r.method !== 'GET',
|
|
130
|
+
transaction: r.transaction ?? r.method !== 'GET',
|
|
131
|
+
rate_limit_key: r.rate_limit ?? null,
|
|
132
|
+
params_schema: r.params ? schema_to_surface(r.params) : null,
|
|
133
|
+
query_schema: r.query ? schema_to_surface(r.query) : null,
|
|
134
|
+
input_schema: schema_to_surface(r.input),
|
|
135
|
+
output_schema: schema_to_surface(r.output),
|
|
136
|
+
error_schemas,
|
|
137
|
+
};
|
|
138
|
+
}),
|
|
139
|
+
env: env_schema ? env_schema_to_surface(env_schema) : [],
|
|
140
|
+
events: event_specs?.length ? events_to_surface(event_specs) : [],
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Create an `AppSurfaceSpec` — the surface bundled with its source specs.
|
|
145
|
+
*
|
|
146
|
+
* @param options - the surface generation options
|
|
147
|
+
* @returns the surface spec with surface and raw specs
|
|
148
|
+
*/
|
|
149
|
+
export const create_app_surface_spec = (options) => {
|
|
150
|
+
const surface = generate_app_surface(options);
|
|
151
|
+
return {
|
|
152
|
+
surface,
|
|
153
|
+
route_specs: options.route_specs,
|
|
154
|
+
middleware_specs: options.middleware_specs,
|
|
155
|
+
};
|
|
156
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure query functions over `AppSurface` data.
|
|
3
|
+
*
|
|
4
|
+
* Usable in tests, the adversarial auth runner, and future surface explorer UI.
|
|
5
|
+
* Replaces duplicated inline `.filter()` patterns.
|
|
6
|
+
*
|
|
7
|
+
* TODO @surface-explorer Used by test utilities (test_auth_surface, adversarial_input,
|
|
8
|
+
* surface_invariants) and SurfaceExplorer.svelte (surface_auth_summary, format_route_key).
|
|
9
|
+
* Several query functions (filter_authenticated_routes, filter_keeper_routes,
|
|
10
|
+
* routes_by_auth_type, filter_routes_by_prefix) are pre-built for richer surface
|
|
11
|
+
* explorer features and consumer test suites — leverage more as the surface UI matures.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import type { AppSurface, AppSurfaceRoute } from './surface.js';
|
|
16
|
+
/** Filter routes that require any form of authentication. */
|
|
17
|
+
export declare const filter_protected_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
18
|
+
/** Filter routes that are publicly accessible (no auth). */
|
|
19
|
+
export declare const filter_public_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
20
|
+
/** Filter all role-guarded routes (any role). */
|
|
21
|
+
export declare const filter_role_routes: (surface: AppSurface) => Array<AppSurfaceRoute & {
|
|
22
|
+
auth: {
|
|
23
|
+
type: "role";
|
|
24
|
+
role: string;
|
|
25
|
+
};
|
|
26
|
+
}>;
|
|
27
|
+
/** Filter routes that require basic authentication (no specific role). */
|
|
28
|
+
export declare const filter_authenticated_routes: (surface: AppSurface) => Array<AppSurfaceRoute & {
|
|
29
|
+
auth: {
|
|
30
|
+
type: "authenticated";
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
33
|
+
/** Filter routes that require keeper credentials. */
|
|
34
|
+
export declare const filter_keeper_routes: (surface: AppSurface) => Array<AppSurfaceRoute & {
|
|
35
|
+
auth: {
|
|
36
|
+
type: "keeper";
|
|
37
|
+
};
|
|
38
|
+
}>;
|
|
39
|
+
/** Filter routes that require a specific named role. */
|
|
40
|
+
export declare const filter_routes_for_role: (surface: AppSurface, role: string) => Array<AppSurfaceRoute & {
|
|
41
|
+
auth: {
|
|
42
|
+
type: "role";
|
|
43
|
+
role: string;
|
|
44
|
+
};
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Group routes by auth type.
|
|
48
|
+
*
|
|
49
|
+
* @returns a map from auth type string to route arrays, with role routes keyed as `'role:name'`
|
|
50
|
+
*/
|
|
51
|
+
export declare const routes_by_auth_type: (surface: AppSurface) => Map<string, Array<AppSurfaceRoute>>;
|
|
52
|
+
/** Filter routes whose path starts with `prefix`. */
|
|
53
|
+
export declare const filter_routes_by_prefix: (surface: AppSurface, prefix: string) => Array<AppSurfaceRoute>;
|
|
54
|
+
/** Filter routes that have a non-null input schema. */
|
|
55
|
+
export declare const filter_routes_with_input: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
56
|
+
/** Filter routes that have a non-null params schema. */
|
|
57
|
+
export declare const filter_routes_with_params: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
58
|
+
/** Filter routes that have a non-null query schema. */
|
|
59
|
+
export declare const filter_routes_with_query: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
60
|
+
/** Filter routes that are mutations (POST, PUT, DELETE, PATCH). */
|
|
61
|
+
export declare const filter_mutation_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
62
|
+
/** Filter routes that declare rate limiting. */
|
|
63
|
+
export declare const filter_rate_limited_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
|
|
64
|
+
/** Format a route as `'METHOD /path'` (e.g. `'GET /health'`). */
|
|
65
|
+
export declare const format_route_key: (route: AppSurfaceRoute) => string;
|
|
66
|
+
/**
|
|
67
|
+
* Summarize route auth distribution across the surface.
|
|
68
|
+
*
|
|
69
|
+
* @returns counts by auth type, with role counts broken out by role name
|
|
70
|
+
*/
|
|
71
|
+
export declare const surface_auth_summary: (surface: AppSurface) => {
|
|
72
|
+
none: number;
|
|
73
|
+
authenticated: number;
|
|
74
|
+
role: Map<string, number>;
|
|
75
|
+
keeper: number;
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=surface_query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface_query.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface_query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,cAAc,CAAC;AAE9D,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEtD,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEtD,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,GAC9B,SAAS,UAAU,KACjB,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAG7D,CAAC;AAEH,0EAA0E;AAC1E,eAAO,MAAM,2BAA2B,GACvC,SAAS,UAAU,KACjB,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,eAAe,CAAA;KAAC,CAAA;CAAC,CAGxD,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,GAChC,SAAS,UAAU,KACjB,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAC,CAAA;CAAC,CAGjD,CAAC;AAEH,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,GAClC,SAAS,UAAU,EACnB,MAAM,MAAM,KACV,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAI7D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,UAAU,KAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,CAY3F,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,GACnC,SAAS,UAAU,EACnB,QAAQ,MAAM,KACZ,KAAK,CAAC,eAAe,CAA4D,CAAC;AAErF,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAExD,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CACtC,CAAC;AAE7C,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEzD,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,KAAG,MAAyC,CAAC;AAEpG;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,UAAU,KACjB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAwBjF,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure query functions over `AppSurface` data.
|
|
3
|
+
*
|
|
4
|
+
* Usable in tests, the adversarial auth runner, and future surface explorer UI.
|
|
5
|
+
* Replaces duplicated inline `.filter()` patterns.
|
|
6
|
+
*
|
|
7
|
+
* TODO @surface-explorer Used by test utilities (test_auth_surface, adversarial_input,
|
|
8
|
+
* surface_invariants) and SurfaceExplorer.svelte (surface_auth_summary, format_route_key).
|
|
9
|
+
* Several query functions (filter_authenticated_routes, filter_keeper_routes,
|
|
10
|
+
* routes_by_auth_type, filter_routes_by_prefix) are pre-built for richer surface
|
|
11
|
+
* explorer features and consumer test suites — leverage more as the surface UI matures.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
/** Filter routes that require any form of authentication. */
|
|
16
|
+
export const filter_protected_routes = (surface) => surface.routes.filter((r) => r.auth.type !== 'none');
|
|
17
|
+
/** Filter routes that are publicly accessible (no auth). */
|
|
18
|
+
export const filter_public_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'none');
|
|
19
|
+
/** Filter all role-guarded routes (any role). */
|
|
20
|
+
export const filter_role_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'role');
|
|
21
|
+
/** Filter routes that require basic authentication (no specific role). */
|
|
22
|
+
export const filter_authenticated_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'authenticated');
|
|
23
|
+
/** Filter routes that require keeper credentials. */
|
|
24
|
+
export const filter_keeper_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'keeper');
|
|
25
|
+
/** Filter routes that require a specific named role. */
|
|
26
|
+
export const filter_routes_for_role = (surface, role) => surface.routes.filter((r) => r.auth.type === 'role' && r.auth.role === role);
|
|
27
|
+
/**
|
|
28
|
+
* Group routes by auth type.
|
|
29
|
+
*
|
|
30
|
+
* @returns a map from auth type string to route arrays, with role routes keyed as `'role:name'`
|
|
31
|
+
*/
|
|
32
|
+
export const routes_by_auth_type = (surface) => {
|
|
33
|
+
const groups = new Map();
|
|
34
|
+
for (const r of surface.routes) {
|
|
35
|
+
const key = r.auth.type === 'role' ? `role:${r.auth.role}` : r.auth.type;
|
|
36
|
+
let group = groups.get(key);
|
|
37
|
+
if (!group) {
|
|
38
|
+
group = [];
|
|
39
|
+
groups.set(key, group);
|
|
40
|
+
}
|
|
41
|
+
group.push(r);
|
|
42
|
+
}
|
|
43
|
+
return groups;
|
|
44
|
+
};
|
|
45
|
+
/** Filter routes whose path starts with `prefix`. */
|
|
46
|
+
export const filter_routes_by_prefix = (surface, prefix) => surface.routes.filter((r) => r.path.startsWith(prefix));
|
|
47
|
+
/** Filter routes that have a non-null input schema. */
|
|
48
|
+
export const filter_routes_with_input = (surface) => surface.routes.filter((r) => r.input_schema !== null);
|
|
49
|
+
/** Filter routes that have a non-null params schema. */
|
|
50
|
+
export const filter_routes_with_params = (surface) => surface.routes.filter((r) => r.params_schema !== null);
|
|
51
|
+
/** Filter routes that have a non-null query schema. */
|
|
52
|
+
export const filter_routes_with_query = (surface) => surface.routes.filter((r) => r.query_schema !== null);
|
|
53
|
+
/** Filter routes that are mutations (POST, PUT, DELETE, PATCH). */
|
|
54
|
+
export const filter_mutation_routes = (surface) => surface.routes.filter((r) => r.is_mutation);
|
|
55
|
+
/** Filter routes that declare rate limiting. */
|
|
56
|
+
export const filter_rate_limited_routes = (surface) => surface.routes.filter((r) => r.rate_limit_key !== null);
|
|
57
|
+
/** Format a route as `'METHOD /path'` (e.g. `'GET /health'`). */
|
|
58
|
+
export const format_route_key = (route) => `${route.method} ${route.path}`;
|
|
59
|
+
/**
|
|
60
|
+
* Summarize route auth distribution across the surface.
|
|
61
|
+
*
|
|
62
|
+
* @returns counts by auth type, with role counts broken out by role name
|
|
63
|
+
*/
|
|
64
|
+
export const surface_auth_summary = (surface) => {
|
|
65
|
+
let none = 0;
|
|
66
|
+
let authenticated = 0;
|
|
67
|
+
const role = new Map();
|
|
68
|
+
let keeper = 0;
|
|
69
|
+
for (const r of surface.routes) {
|
|
70
|
+
switch (r.auth.type) {
|
|
71
|
+
case 'none':
|
|
72
|
+
none++;
|
|
73
|
+
break;
|
|
74
|
+
case 'authenticated':
|
|
75
|
+
authenticated++;
|
|
76
|
+
break;
|
|
77
|
+
case 'role':
|
|
78
|
+
role.set(r.auth.role, (role.get(r.auth.role) ?? 0) + 1);
|
|
79
|
+
break;
|
|
80
|
+
case 'keeper':
|
|
81
|
+
keeper++;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { none, authenticated, role, keeper };
|
|
86
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory sliding window rate limiter.
|
|
3
|
+
*
|
|
4
|
+
* Tracks failed attempts per key (typically IP address) using a sliding
|
|
5
|
+
* time window. No external dependencies — state resets on server restart.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from 'hono';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for a rate limiter instance.
|
|
12
|
+
*/
|
|
13
|
+
export interface RateLimiterOptions {
|
|
14
|
+
/** Maximum allowed attempts within the window. */
|
|
15
|
+
max_attempts: number;
|
|
16
|
+
/** Sliding window duration in milliseconds. */
|
|
17
|
+
window_ms: number;
|
|
18
|
+
/** Interval for pruning stale entries (0 disables the timer). */
|
|
19
|
+
cleanup_interval_ms: number;
|
|
20
|
+
}
|
|
21
|
+
/** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
|
|
22
|
+
export declare const DEFAULT_LOGIN_IP_RATE_LIMIT: RateLimiterOptions;
|
|
23
|
+
/** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
|
|
24
|
+
export declare const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT: RateLimiterOptions;
|
|
25
|
+
/**
|
|
26
|
+
* Result of a rate limit check or record operation.
|
|
27
|
+
*/
|
|
28
|
+
export interface RateLimitResult {
|
|
29
|
+
/** Whether the request is allowed. */
|
|
30
|
+
allowed: boolean;
|
|
31
|
+
/** Remaining attempts before blocking. */
|
|
32
|
+
remaining: number;
|
|
33
|
+
/** Seconds until the oldest active attempt expires (0 if allowed). */
|
|
34
|
+
retry_after: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* In-memory sliding window rate limiter.
|
|
38
|
+
*
|
|
39
|
+
* Stores an array of timestamps per key. On `check`/`record`, timestamps
|
|
40
|
+
* outside the window are pruned. `retry_after` reports seconds until the
|
|
41
|
+
* oldest active timestamp expires.
|
|
42
|
+
*
|
|
43
|
+
* Parameters that accept `RateLimiter | null` (e.g. `ip_rate_limiter`,
|
|
44
|
+
* `login_account_rate_limiter`) silently disable rate limiting when `null`
|
|
45
|
+
* is passed — no checks are performed and all requests are allowed through.
|
|
46
|
+
*/
|
|
47
|
+
export declare class RateLimiter {
|
|
48
|
+
#private;
|
|
49
|
+
readonly options: RateLimiterOptions;
|
|
50
|
+
constructor(options: RateLimiterOptions);
|
|
51
|
+
/** Number of tracked keys. */
|
|
52
|
+
get size(): number;
|
|
53
|
+
/**
|
|
54
|
+
* Check whether `key` is allowed without recording an attempt.
|
|
55
|
+
*
|
|
56
|
+
* @param key - rate limit key (e.g. IP address)
|
|
57
|
+
* @param now - current timestamp in ms (defaults to `Date.now()`)
|
|
58
|
+
*/
|
|
59
|
+
check(key: string, now?: number): RateLimitResult;
|
|
60
|
+
/**
|
|
61
|
+
* Record a failed attempt for `key` and return the updated result.
|
|
62
|
+
*
|
|
63
|
+
* @param key - rate limit key (e.g. IP address)
|
|
64
|
+
* @param now - current timestamp in ms (defaults to `Date.now()`)
|
|
65
|
+
*/
|
|
66
|
+
record(key: string, now?: number): RateLimitResult;
|
|
67
|
+
/**
|
|
68
|
+
* Clear all attempts for `key` (e.g. after successful login).
|
|
69
|
+
*/
|
|
70
|
+
reset(key: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Remove entries whose timestamps are all outside the window.
|
|
73
|
+
*
|
|
74
|
+
* @param now - current timestamp in ms (defaults to `Date.now()`)
|
|
75
|
+
*/
|
|
76
|
+
cleanup(now?: number): void;
|
|
77
|
+
/** Stop the cleanup timer. Safe to call multiple times. */
|
|
78
|
+
dispose(): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a `RateLimiter` with sensible defaults for per-IP login protection.
|
|
82
|
+
*
|
|
83
|
+
* @param options - override individual options; unset fields use `DEFAULT_LOGIN_IP_RATE_LIMIT`
|
|
84
|
+
*/
|
|
85
|
+
export declare const create_rate_limiter: (options?: Partial<RateLimiterOptions>) => RateLimiter;
|
|
86
|
+
/**
|
|
87
|
+
* Build a 429 rate-limit-exceeded JSON response with `Retry-After` header.
|
|
88
|
+
*
|
|
89
|
+
* @param c - Hono context
|
|
90
|
+
* @param retry_after - seconds until the client should retry
|
|
91
|
+
* @returns a 429 Response
|
|
92
|
+
*/
|
|
93
|
+
export declare const rate_limit_exceeded_response: (c: Context, retry_after: number) => Response;
|
|
94
|
+
//# sourceMappingURL=rate_limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate_limiter.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/rate_limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAIlC;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,iFAAiF;AACjF,eAAO,MAAM,2BAA2B,EAAE,kBAIzC,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,gCAAgC,EAAE,kBAI9C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,WAAW;;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;gBAOzB,OAAO,EAAE,kBAAkB;IAWvC,8BAA8B;IAC9B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA2B7D;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA0B9D;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB;;;;OAIG;IACH,OAAO,CAAC,GAAG,GAAE,MAAmB,GAAG,IAAI;IAYvC,2DAA2D;IAC3D,OAAO,IAAI,IAAI;CAMf;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,OAAO,CAAC,kBAAkB,CAAC,KAAG,WAE3E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GAAI,GAAG,OAAO,EAAE,aAAa,MAAM,KAAG,QAI7E,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory sliding window rate limiter.
|
|
3
|
+
*
|
|
4
|
+
* Tracks failed attempts per key (typically IP address) using a sliding
|
|
5
|
+
* time window. No external dependencies — state resets on server restart.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { ERROR_RATE_LIMIT_EXCEEDED } from './http/error_schemas.js';
|
|
10
|
+
/** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
|
|
11
|
+
export const DEFAULT_LOGIN_IP_RATE_LIMIT = {
|
|
12
|
+
max_attempts: 5,
|
|
13
|
+
window_ms: 15 * 60_000,
|
|
14
|
+
cleanup_interval_ms: 5 * 60_000,
|
|
15
|
+
};
|
|
16
|
+
/** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
|
|
17
|
+
export const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT = {
|
|
18
|
+
max_attempts: 10,
|
|
19
|
+
window_ms: 30 * 60_000,
|
|
20
|
+
cleanup_interval_ms: 5 * 60_000,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* In-memory sliding window rate limiter.
|
|
24
|
+
*
|
|
25
|
+
* Stores an array of timestamps per key. On `check`/`record`, timestamps
|
|
26
|
+
* outside the window are pruned. `retry_after` reports seconds until the
|
|
27
|
+
* oldest active timestamp expires.
|
|
28
|
+
*
|
|
29
|
+
* Parameters that accept `RateLimiter | null` (e.g. `ip_rate_limiter`,
|
|
30
|
+
* `login_account_rate_limiter`) silently disable rate limiting when `null`
|
|
31
|
+
* is passed — no checks are performed and all requests are allowed through.
|
|
32
|
+
*/
|
|
33
|
+
export class RateLimiter {
|
|
34
|
+
options;
|
|
35
|
+
/** Key → array of attempt timestamps. */
|
|
36
|
+
#attempts = new Map();
|
|
37
|
+
#cleanup_timer = null;
|
|
38
|
+
constructor(options) {
|
|
39
|
+
this.options = options;
|
|
40
|
+
if (options.cleanup_interval_ms > 0) {
|
|
41
|
+
this.#cleanup_timer = setInterval(() => this.cleanup(), options.cleanup_interval_ms);
|
|
42
|
+
// Allow the process to exit even if the timer is still active.
|
|
43
|
+
if (typeof this.#cleanup_timer === 'object' && 'unref' in this.#cleanup_timer) {
|
|
44
|
+
this.#cleanup_timer.unref();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Number of tracked keys. */
|
|
49
|
+
get size() {
|
|
50
|
+
return this.#attempts.size;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check whether `key` is allowed without recording an attempt.
|
|
54
|
+
*
|
|
55
|
+
* @param key - rate limit key (e.g. IP address)
|
|
56
|
+
* @param now - current timestamp in ms (defaults to `Date.now()`)
|
|
57
|
+
*/
|
|
58
|
+
check(key, now = Date.now()) {
|
|
59
|
+
const { max_attempts, window_ms } = this.options;
|
|
60
|
+
const cutoff = now - window_ms;
|
|
61
|
+
const timestamps = this.#attempts.get(key);
|
|
62
|
+
if (!timestamps) {
|
|
63
|
+
return { allowed: true, remaining: max_attempts, retry_after: 0 };
|
|
64
|
+
}
|
|
65
|
+
const active = timestamps.filter((t) => t > cutoff);
|
|
66
|
+
if (active.length !== timestamps.length) {
|
|
67
|
+
if (active.length === 0) {
|
|
68
|
+
this.#attempts.delete(key);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.#attempts.set(key, active);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (active.length < max_attempts) {
|
|
75
|
+
return { allowed: true, remaining: max_attempts - active.length, retry_after: 0 };
|
|
76
|
+
}
|
|
77
|
+
const oldest = active[0];
|
|
78
|
+
const retry_after = Math.ceil((oldest + window_ms - now) / 1000);
|
|
79
|
+
return { allowed: false, remaining: 0, retry_after };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Record a failed attempt for `key` and return the updated result.
|
|
83
|
+
*
|
|
84
|
+
* @param key - rate limit key (e.g. IP address)
|
|
85
|
+
* @param now - current timestamp in ms (defaults to `Date.now()`)
|
|
86
|
+
*/
|
|
87
|
+
record(key, now = Date.now()) {
|
|
88
|
+
const { max_attempts, window_ms } = this.options;
|
|
89
|
+
const cutoff = now - window_ms;
|
|
90
|
+
let timestamps = this.#attempts.get(key);
|
|
91
|
+
if (timestamps) {
|
|
92
|
+
// Prune expired entries in place.
|
|
93
|
+
const active = timestamps.filter((t) => t > cutoff);
|
|
94
|
+
active.push(now);
|
|
95
|
+
this.#attempts.set(key, active);
|
|
96
|
+
timestamps = active;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
timestamps = [now];
|
|
100
|
+
this.#attempts.set(key, timestamps);
|
|
101
|
+
}
|
|
102
|
+
const count = timestamps.length;
|
|
103
|
+
if (count <= max_attempts) {
|
|
104
|
+
return { allowed: true, remaining: max_attempts - count, retry_after: 0 };
|
|
105
|
+
}
|
|
106
|
+
const oldest = timestamps[0];
|
|
107
|
+
const retry_after = Math.ceil((oldest + window_ms - now) / 1000);
|
|
108
|
+
return { allowed: false, remaining: 0, retry_after };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Clear all attempts for `key` (e.g. after successful login).
|
|
112
|
+
*/
|
|
113
|
+
reset(key) {
|
|
114
|
+
this.#attempts.delete(key);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Remove entries whose timestamps are all outside the window.
|
|
118
|
+
*
|
|
119
|
+
* @param now - current timestamp in ms (defaults to `Date.now()`)
|
|
120
|
+
*/
|
|
121
|
+
cleanup(now = Date.now()) {
|
|
122
|
+
const cutoff = now - this.options.window_ms;
|
|
123
|
+
for (const [key, timestamps] of this.#attempts) {
|
|
124
|
+
const active = timestamps.filter((t) => t > cutoff);
|
|
125
|
+
if (active.length === 0) {
|
|
126
|
+
this.#attempts.delete(key);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.#attempts.set(key, active);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Stop the cleanup timer. Safe to call multiple times. */
|
|
134
|
+
dispose() {
|
|
135
|
+
if (this.#cleanup_timer !== null) {
|
|
136
|
+
clearInterval(this.#cleanup_timer);
|
|
137
|
+
this.#cleanup_timer = null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Create a `RateLimiter` with sensible defaults for per-IP login protection.
|
|
143
|
+
*
|
|
144
|
+
* @param options - override individual options; unset fields use `DEFAULT_LOGIN_IP_RATE_LIMIT`
|
|
145
|
+
*/
|
|
146
|
+
export const create_rate_limiter = (options) => {
|
|
147
|
+
return new RateLimiter({ ...DEFAULT_LOGIN_IP_RATE_LIMIT, ...options });
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Build a 429 rate-limit-exceeded JSON response with `Retry-After` header.
|
|
151
|
+
*
|
|
152
|
+
* @param c - Hono context
|
|
153
|
+
* @param retry_after - seconds until the client should retry
|
|
154
|
+
* @returns a 429 Response
|
|
155
|
+
*/
|
|
156
|
+
export const rate_limit_exceeded_response = (c, retry_after) => c.json({ error: ERROR_RATE_LIMIT_EXCEEDED, retry_after }, { status: 429, headers: { 'Retry-After': String(Math.ceil(retry_after)) } });
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE (Server-Sent Events) streaming utilities for Hono.
|
|
3
|
+
*
|
|
4
|
+
* Provides generic helpers for creating SSE response streams
|
|
5
|
+
* and a notification type aligned with JSON-RPC 2.0.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from 'hono';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
12
|
+
/**
|
|
13
|
+
* Generic SSE stream controller interface.
|
|
14
|
+
*
|
|
15
|
+
* Transport-agnostic — works with any serializable type.
|
|
16
|
+
*/
|
|
17
|
+
export interface SseStream<T = unknown> {
|
|
18
|
+
/** Send data to the client as a JSON SSE event. */
|
|
19
|
+
send: (data: T) => void;
|
|
20
|
+
/** Send a comment (for keep-alive pings). */
|
|
21
|
+
comment: (text: string) => void;
|
|
22
|
+
/** Close the stream. */
|
|
23
|
+
close: () => void;
|
|
24
|
+
/** Register a listener called when the stream closes (client disconnect or explicit close). */
|
|
25
|
+
on_close: (fn: () => void) => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Notification shape aligned with JSON-RPC 2.0.
|
|
29
|
+
*
|
|
30
|
+
* Uses `{method, params}` to match the JSON-RPC notification format.
|
|
31
|
+
*/
|
|
32
|
+
export interface SseNotification {
|
|
33
|
+
/** Notification method name (e.g. 'run_created', 'host_updated'). */
|
|
34
|
+
method: string;
|
|
35
|
+
/** Method-specific payload. */
|
|
36
|
+
params: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create an SSE response for a Hono context.
|
|
40
|
+
*
|
|
41
|
+
* Wraps Hono's `streamSSE` to provide a `{response, stream}` API
|
|
42
|
+
* compatible with `SubscriberRegistry` push-based broadcasting.
|
|
43
|
+
* The callback suspends via a promise that resolves on client disconnect
|
|
44
|
+
* or explicit `close()`, keeping the stream alive for external sends.
|
|
45
|
+
*
|
|
46
|
+
* Uses `hono_stream.write()` directly (not `writeSSE`) to avoid
|
|
47
|
+
* Hono's HTML callback resolution — keeps the same `data: JSON\n\n` format.
|
|
48
|
+
*
|
|
49
|
+
* @param c - Hono context
|
|
50
|
+
* @returns object with response and stream controller
|
|
51
|
+
*/
|
|
52
|
+
export declare const create_sse_response: <T = unknown>(c: Context, log: Logger) => {
|
|
53
|
+
response: Response;
|
|
54
|
+
stream: SseStream<T>;
|
|
55
|
+
};
|
|
56
|
+
/** SSE comment sent on connect to flush headers through proxies. Exported for test assertions. */
|
|
57
|
+
export declare const SSE_CONNECTED_COMMENT = ": connected\n\n";
|
|
58
|
+
/** Spec for an SSE event — declares params schema, description, and channel. */
|
|
59
|
+
export interface SseEventSpec {
|
|
60
|
+
method: string;
|
|
61
|
+
params: z.ZodType;
|
|
62
|
+
description: string;
|
|
63
|
+
channel?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a broadcaster that validates events in DEV mode.
|
|
67
|
+
*
|
|
68
|
+
* In DEV: warns on unknown methods and invalid params.
|
|
69
|
+
* In production: passes through with zero overhead.
|
|
70
|
+
*
|
|
71
|
+
* @param broadcaster - duck-typed broadcaster (e.g. `SubscriberRegistry`)
|
|
72
|
+
* @param event_specs - event specs to validate against
|
|
73
|
+
* @returns validated broadcaster wrapper (passthrough in production)
|
|
74
|
+
*/
|
|
75
|
+
export declare const create_validated_broadcaster: <T extends SseNotification>(broadcaster: {
|
|
76
|
+
broadcast: (channel: string, data: T) => void;
|
|
77
|
+
}, event_specs: Array<SseEventSpec>, log: Logger) => {
|
|
78
|
+
broadcast: (channel: string, data: T) => void;
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=sse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/realtime/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAElC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACrC,mDAAmD;IACnD,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,6CAA6C;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,wBAAwB;IACxB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,+FAA+F;IAC/F,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,GAAG,OAAO,EAC9C,GAAG,OAAO,EACV,KAAK,MAAM,KACT;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CAiD3C,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS,eAAe,EACrE,aAAa;IAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;CAAC,EAC5D,aAAa,KAAK,CAAC,YAAY,CAAC,EAChC,KAAK,MAAM,KACT;IAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;CAmBhD,CAAC"}
|