diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..838c0c61fa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false + +[*.svelte] +quote_type = single + +# Go files +[*.go] +indent_style = tab +indent_size = 4 + +# Go mod and sum files +[go.{mod,sum}] +indent_style = tab +indent_size = 4 diff --git a/.env.with-auth b/.env.with-auth new file mode 100644 index 0000000000..cd349b6871 --- /dev/null +++ b/.env.with-auth @@ -0,0 +1,4 @@ +VITE_TEMPORAL_PORT="7233" +VITE_API="http://localhost:8081" +VITE_MODE="development" +VITE_TEMPORAL_UI_BUILD_TARGET="local" diff --git a/.tool-versions b/.tool-versions index e1010718d4..1c79f89c25 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1,2 @@ pnpm 8.15.7 +golang 1.21.0 diff --git a/TESTING_TOKEN_REFRESH.md b/TESTING_TOKEN_REFRESH.md new file mode 100644 index 0000000000..93744ca3ad --- /dev/null +++ b/TESTING_TOKEN_REFRESH.md @@ -0,0 +1,87 @@ +# Testing Token Refresh Flow + +The UI now implements automatic OAuth2 token refresh to prevent session interruptions when access tokens expire. + +## Quick Test + +1. **Start the dev server with auth**: + + ```bash + pnpm dev:with-auth + ``` + +2. **Login**: + + - Navigate to http://localhost:3000 + - Login with any username (e.g., `testuser`) + - You should see the UI load successfully + +3. **Verify refresh token cookie**: + + - Open browser DevTools → Application tab → Cookies + - Check for `refresh` cookie (HttpOnly, 30 day expiry) + - Check for `user0` cookie (1 minute expiry, contains access token) + +4. **Wait for token expiration**: + + - Tokens expire after 60 seconds + - Open DevTools → Network tab + - Wait 60+ seconds + +5. **Trigger a request**: + + - Navigate to a different page or trigger any API call + - Watch the Network tab + +6. **Observe automatic refresh**: + - First request → `401 Unauthorized` (expired token) + - `/auth/refresh` → `200 OK` (exchanging refresh token) + - Original request retries → `200 OK` (with new token) + - UI continues working seamlessly + +## What to Look For + +### Success Case (Refresh Works) + +- First API call after expiration: `401 Unauthorized` +- `/auth/refresh` call: `200 OK` +- Original request automatically retries: `200 OK` +- New cookies are set with fresh tokens +- UI continues without interruption or login redirect + +### Failure Case (Refresh Token Expired) + +- First API call: `401 Unauthorized` +- `/auth/refresh` call: `401 Unauthorized` +- Browser redirects to login page (`/auth/sso`) + +## Configuration + +### Token Expiration Times + +- **Access token**: 60 seconds (`utilities/oidc-server/support/configuration.ts:7`) +- **ID token**: 60 seconds (`utilities/oidc-server/support/configuration.ts:8`) +- **Refresh token**: 1 day (`utilities/oidc-server/support/configuration.ts:9`) +- **User cookie**: 1 minute (`server/server/auth/auth.go:80`) +- **Refresh cookie**: 30 days (`server/server/auth/auth.go:94`) + +### Required OIDC Configuration + +- **Grant types**: `authorization_code`, `refresh_token` (`utilities/oidc-server/support/configuration.ts:19`) +- **Scopes**: `openid`, `profile`, `email`, `offline_access` (`server/config/with-auth.yaml:33-37`) +- **issueRefreshToken**: Must return `true` (`utilities/oidc-server/support/configuration.ts:12-14`) + +The `offline_access` scope and `issueRefreshToken` callback are critical for refresh tokens to be issued. + +## How It Works + +1. User logs in via OAuth2 authorization code flow +2. OIDC server issues access token, ID token, and refresh token +3. UI server stores refresh token in HttpOnly cookie (secure, not accessible to JavaScript) +4. Frontend stores access/ID tokens in short-lived cookies +5. When tokens expire (after 60s), API requests return 401 +6. Frontend automatically calls `/auth/refresh` with refresh token cookie +7. Server exchanges refresh token for new access/ID tokens +8. New tokens are stored in cookies +9. Original request retries with new tokens +10. User session continues seamlessly diff --git a/package.json b/package.json index 214f6df038..8cc644c31b 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,13 @@ "dev:local-temporal": ". ./.env.local-temporal && vite dev --mode local-temporal", "dev:temporal-cli": "vite dev --mode temporal-server", "dev:docker": ". ./.env && VITE_API=http://localhost:8080 vite dev --mode docker", + "dev:with-auth": "vite dev --mode with-auth", "build:local": "vite build", "build:docker": "VITE_API=http://localhost:8080 vite build", "build:server": "VITE_API= BUILD_PATH=server/ui/assets/local vite build", "temporal-server": "esno scripts/start-temporal-server.ts --codecEndpoint http://127.0.0.1:8888", "codec-server": "esno ./scripts/start-codec-server.ts --port 8888", + "oidc-server": "esno ./scripts/start-oidc-server.ts --port 8889", "serve:playwright:e2e": "vite build && vite preview --mode test.e2e", "serve:playwright:integration": "vite build && vite preview --mode test.integration --port 3333", "test": "TZ=UTC vitest", @@ -167,6 +169,9 @@ "chalk": "^4.1.2", "cors": "^2.8.5", "cssnano": "^5.1.14", + "desm": "^1.3.1", + "ejs": "^3.1.10", + "esbuild": "^0.25.0", "eslint": "^8.47.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", @@ -178,11 +183,17 @@ "express": "^4.18.2", "fast-glob": "^3.3.1", "google-protobuf": "^3.21.2", + "helmet": "^8.1.0", "husky": "^8.0.3", "jsdom": "^20.0.3", "lint-staged": "^13.1.0", + "lodash": "^4.17.21", "mkdirp": "^2.1.3", + "mock-socket": "^9.1.5", + "nanoid": "^5.1.5", "node-fetch": "^3.3.0", + "npm-run-all": "^4.1.5", + "oidc-provider": "^9.0.1", "postcss": "^8.4.31", "postcss-cli": "^9.1.0", "postcss-html": "^1.5.0", diff --git a/plugins/vite-plugin-oidc-server.ts b/plugins/vite-plugin-oidc-server.ts new file mode 100644 index 0000000000..7a452f7d60 --- /dev/null +++ b/plugins/vite-plugin-oidc-server.ts @@ -0,0 +1,76 @@ +import type { Plugin } from 'vite'; +import type { ViteDevServer } from 'vite'; +import waitForPort from 'wait-port'; +import { chalk } from 'zx'; + +import { + Account, + getConfig, + OIDCServer, + providerConfiguration, + routes, +} from '../utilities/oidc-server'; + +const { blue } = chalk; + +let oidcServer: OIDCServer; + +function log(...message: string[]): void { + const [first, ...rest] = message; + console.log(blue(first), ...rest); +} + +/** + * Determine whether to skip starting the OIDC server. + */ +const shouldSkip = (server: ViteDevServer): boolean => { + if (process.env.VERCEL) return true; + if (process.env.VITEST) return true; + if (process.env.CI) return true; + // only run in oidc-server mode + if (server.config.mode !== 'with-auth') return true; + return false; +}; + +/** + * Vite plugin to manage the lifecycle of the OIDC server during dev. + */ +export function oidcServerPlugin(): Plugin { + const { PORT, ISSUER, VIEWS_PATH } = getConfig(); + + return { + name: 'vite-plugin-oidc-server', + enforce: 'post', + apply: 'serve', + async configureServer(server) { + if (shouldSkip(server)) return; + + log(`Starting OIDC Server on port ${PORT}…`); + + oidcServer = new OIDCServer({ + issuer: ISSUER, + port: PORT, + viewsPath: VIEWS_PATH, + providerConfiguration, + accountModel: Account, + routes, + }); + // start and wait for readiness + await oidcServer.start(); + await waitForPort({ port: PORT, output: 'silent' }); + + log(`OIDC Server is running on port ${PORT}.`); + }, + async closeBundle() { + if (oidcServer) { + oidcServer.stop(); + log('🔪 killed OIDC Server'); + } + }, + }; +} + +// ensure shutdown on process exit +process.on('beforeExit', () => { + if (oidcServer) oidcServer.stop(); +}); diff --git a/plugins/vite-plugin-temporal-server.ts b/plugins/vite-plugin-temporal-server.ts index 7a8b374025..2cc17d2992 100644 --- a/plugins/vite-plugin-temporal-server.ts +++ b/plugins/vite-plugin-temporal-server.ts @@ -7,7 +7,7 @@ import { type TemporalServer, } from '../utilities/temporal-server'; -const { cyan, magenta } = chalk; +const { magenta } = chalk; let temporal: TemporalServer; @@ -16,7 +16,9 @@ const shouldSkip = (server: ViteDevServer): boolean => { if (process.env.VITEST) return true; if (temporal) return true; if (process.platform === 'win32') return true; - if (!['temporal-server', 'ui-server'].includes(server.config.mode)) + if ( + !['temporal-server', 'ui-server', 'with-auth'].includes(server.config.mode) + ) return true; return false; @@ -38,7 +40,10 @@ const persistentDB = (server: ViteDevServer): string | undefined => { return filename; }; -const getPortFromApiEndpoint = (endpoint: string, fallback = 8233): number => { +export const getPortFromApiEndpoint = ( + endpoint: string, + fallback = 8233, +): number => { return validatePort( endpoint.slice(endpoint.lastIndexOf(':') + 1, endpoint.length), fallback, @@ -79,7 +84,6 @@ export function temporalServer(): Plugin { const uiPort = getPortFromApiEndpoint(server.config.env.VITE_API); console.log(magenta(`Starting Temporal Server on Port ${port}…`)); - console.log(cyan(`Starting Temporal UI Server on Port ${uiPort}…`)); temporal = await createTemporalServer({ port, @@ -90,7 +94,6 @@ export function temporalServer(): Plugin { await temporal.ready(); console.log(magenta(`Temporal Server is running on Port ${port}.`)); - console.log(cyan(`Temporal UI Server is running on Port ${uiPort}.`)); }, async closeBundle() { await temporal?.shutdown(); diff --git a/plugins/vite-plugin-ui-server.ts b/plugins/vite-plugin-ui-server.ts index 4568df7fcd..6b49f49755 100644 --- a/plugins/vite-plugin-ui-server.ts +++ b/plugins/vite-plugin-ui-server.ts @@ -1,7 +1,15 @@ import type { Plugin } from 'vite'; import type { ViteDevServer } from 'vite'; +import { chalk } from 'zx'; -import { createUIServer, type UIServer } from '../utilities/ui-server'; +import { getPortFromApiEndpoint } from './vite-plugin-temporal-server'; +import { + createUIServer, + type UIServer, + type ValidEnv, +} from '../utilities/ui-server'; + +const { cyan } = chalk; let uiServer: UIServer; @@ -9,12 +17,18 @@ const shouldSkip = (server: ViteDevServer): boolean => { if (process.env.VERCEL) return true; if (process.env.VITEST) return true; if (process.env.CI) return true; - if (['ui-server', 'local-temporal'].includes(server.config.mode)) + if (['ui-server', 'local-temporal', 'with-auth'].includes(server.config.mode)) return false; return true; }; +function serverEnv(server: ViteDevServer): ValidEnv { + if (server.config.mode === 'with-auth') return 'with-auth'; + if (server.config.mode === 'e2e') return 'e2e'; + return 'development'; +} + export function uiServerPlugin(): Plugin { return { name: 'vite-plugin-ui-server', @@ -22,8 +36,14 @@ export function uiServerPlugin(): Plugin { apply: 'serve', async configureServer(server) { if (shouldSkip(server)) return; - uiServer = await createUIServer(); + + const uiPort = getPortFromApiEndpoint(server.config.env.VITE_API); + console.log(cyan(`Starting Temporal UI Server on Port ${uiPort}…`)); + + uiServer = await createUIServer(serverEnv(server)); await uiServer.ready(); + + console.log(cyan(`Temporal UI Server is running on Port ${uiPort}.`)); }, async closeBundle() { await uiServer?.shutdown(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 164521fc33..2fbc2fbf67 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,10 +11,10 @@ overrides: dependencies: '@codemirror/autocomplete': specifier: ^6.18.7 - version: 6.18.7 + version: 6.19.0 '@codemirror/commands': specifier: ^6.8.1 - version: 6.8.1 + version: 6.9.0 '@codemirror/lang-go': specifier: ^6.0.1 version: 6.0.1 @@ -26,7 +26,7 @@ dependencies: version: 6.0.2 '@codemirror/lang-markdown': specifier: ^6.3.4 - version: 6.3.4 + version: 6.4.0 '@codemirror/lang-php': specifier: ^6.0.2 version: 6.0.2 @@ -38,13 +38,13 @@ dependencies: version: 6.5.1 '@codemirror/legacy-modes': specifier: ^6.5.1 - version: 6.5.1 + version: 6.5.2 '@codemirror/state': specifier: ^6.5.2 version: 6.5.2 '@codemirror/view': specifier: ^6.38.2 - version: 6.38.2 + version: 6.38.6 '@fontsource-variable/inter': specifier: ^5.0.8 version: 5.0.8 @@ -110,7 +110,7 @@ dependencies: version: 10.0.3 sveltekit-superforms: specifier: ^2.26.1 - version: 2.27.1(@sveltejs/kit@2.36.1)(esbuild@0.25.10)(svelte@5.25.5)(typescript@5.2.2) + version: 2.28.0(@sveltejs/kit@2.47.2)(esbuild@0.25.0)(svelte@5.25.5)(typescript@5.2.2) tailwind-merge: specifier: ^1.14.0 version: 1.14.0 @@ -122,12 +122,12 @@ dependencies: version: 1.0.3 zod: specifier: ^3.25.64 - version: 3.25.67 + version: 3.25.76 devDependencies: '@axe-core/playwright': specifier: ^4.10.1 - version: 4.10.1(playwright-core@1.56.0) + version: 4.10.1(playwright-core@1.51.1) '@babel/core': specifier: ^7.20.12 version: 7.20.12 @@ -151,10 +151,10 @@ devDependencies: version: 8.6.4(storybook@8.6.11) '@storybook/addon-docs': specifier: ^8.6.11 - version: 8.6.11(@types/react@19.2.0)(storybook@8.6.11) + version: 8.6.11(@types/react@19.1.1)(storybook@8.6.11) '@storybook/addon-essentials': specifier: ^8.6.11 - version: 8.6.11(@types/react@19.2.0)(storybook@8.6.11) + version: 8.6.11(@types/react@19.1.1)(storybook@8.6.11) '@storybook/addon-interactions': specifier: ^8.6.11 version: 8.6.11(storybook@8.6.11) @@ -163,7 +163,7 @@ devDependencies: version: 8.6.11(react@18.2.0)(storybook@8.6.11) '@storybook/addon-svelte-csf': specifier: ^5.0.0-next.23 - version: 5.0.0-next.27(@storybook/svelte@8.6.11)(@sveltejs/vite-plugin-svelte@5.0.3)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.7) + version: 5.0.0-next.27(@storybook/svelte@8.6.11)(@sveltejs/vite-plugin-svelte@5.0.3)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.6) '@storybook/addon-themes': specifier: ^8.6.11 version: 8.6.11(storybook@8.6.11) @@ -178,7 +178,7 @@ devDependencies: version: 8.6.11(storybook@8.6.11)(svelte@5.25.5) '@storybook/sveltekit': specifier: ^8.6.11 - version: 8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.7) + version: 8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.6) '@storybook/test': specifier: ^8.6.11 version: 8.6.11(storybook@8.6.11) @@ -187,16 +187,16 @@ devDependencies: version: 0.22.0(@types/node@18.15.3)(storybook@8.6.11) '@sveltejs/adapter-static': specifier: ^3.0.8 - version: 3.0.8(@sveltejs/kit@2.36.1) + version: 3.0.8(@sveltejs/kit@2.47.2) '@sveltejs/adapter-vercel': specifier: ^4.0.0 - version: 4.0.0(@sveltejs/kit@2.36.1) + version: 4.0.0(@sveltejs/kit@2.47.2) '@sveltejs/kit': specifier: ^2.20.6 - version: 2.36.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7) + version: 2.47.2(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6) '@sveltejs/vite-plugin-svelte': specifier: ^5.0.3 - version: 5.0.3(svelte@5.25.5)(vite@6.2.7) + version: 5.0.3(svelte@5.25.5)(vite@6.2.6) '@temporalio/activity': specifier: 1.12.1 version: 1.12.1 @@ -211,16 +211,16 @@ devDependencies: version: 1.13.0 '@temporalio/testing': specifier: 1.12.1 - version: 1.12.1(esbuild@0.25.10) + version: 1.12.1(esbuild@0.25.0) '@temporalio/worker': specifier: 1.12.1 - version: 1.12.1(esbuild@0.25.10) + version: 1.12.1(esbuild@0.25.0) '@temporalio/workflow': specifier: 1.12.1 version: 1.12.1 '@types/base-64': specifier: ^1.0.0 - version: 1.0.2 + version: 1.0.0 '@types/cors': specifier: ^2.8.13 version: 2.8.13 @@ -262,7 +262,7 @@ devDependencies: version: 10.4.13(postcss@8.4.31) axe-playwright: specifier: ^2.0.3 - version: 2.0.3(playwright@1.56.0) + version: 2.0.3(playwright@1.51.1) c8: specifier: ^7.12.0 version: 7.12.0 @@ -275,6 +275,15 @@ devDependencies: cssnano: specifier: ^5.1.14 version: 5.1.14(postcss@8.4.31) + desm: + specifier: ^1.3.1 + version: 1.3.1 + ejs: + specifier: ^3.1.10 + version: 3.1.10 + esbuild: + specifier: ^0.25.0 + version: 0.25.0 eslint: specifier: ^8.47.0 version: 8.47.0 @@ -295,7 +304,7 @@ devDependencies: version: 2.46.1(eslint@8.47.0)(svelte@5.25.5) eslint-plugin-vitest: specifier: ^0.2.8 - version: 0.2.8(eslint@8.47.0)(typescript@5.2.2)(vite@6.2.7)(vitest@3.1.1) + version: 0.2.8(eslint@8.47.0)(typescript@5.2.2)(vite@6.2.6)(vitest@3.1.1) esno: specifier: ^0.16.3 version: 0.16.3 @@ -308,6 +317,9 @@ devDependencies: google-protobuf: specifier: ^3.21.2 version: 3.21.2 + helmet: + specifier: ^8.1.0 + version: 8.1.0 husky: specifier: ^8.0.3 version: 8.0.3 @@ -317,12 +329,27 @@ devDependencies: lint-staged: specifier: ^13.1.0 version: 13.1.0 + lodash: + specifier: ^4.17.21 + version: 4.17.21 mkdirp: specifier: ^2.1.3 version: 2.1.3 + mock-socket: + specifier: ^9.1.5 + version: 9.1.5 + nanoid: + specifier: ^5.1.5 + version: 5.1.5 node-fetch: specifier: ^3.3.0 version: 3.3.0 + npm-run-all: + specifier: ^4.1.5 + version: 4.1.5 + oidc-provider: + specifier: ^9.0.1 + version: 9.0.1 postcss: specifier: ^8.4.31 version: 8.4.31 @@ -427,7 +454,7 @@ devDependencies: version: 5.0.0 vite: specifier: ^6.2.4 - version: 6.2.7(@types/node@18.15.3) + version: 6.2.6(@types/node@18.15.3) vitest: specifier: ^3.1.1 version: 3.1.1(@types/node@18.15.3)(@vitest/ui@3.1.1)(jsdom@20.0.3) @@ -439,7 +466,7 @@ devDependencies: version: 1.0.4 webpack: specifier: ^5.76.0 - version: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.10) + version: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.0) yargs: specifier: ^17.7.2 version: 17.7.2 @@ -478,27 +505,35 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - /@ark/schema@0.49.0: - resolution: {integrity: sha512-GphZBLpW72iS0v4YkeUtV3YIno35Gimd7+ezbPO9GwEi9kzdUrPVjvf6aXSBAfHikaFc/9pqZOpv3pOXnC71tw==} + /@ark/regex@0.0.0: + resolution: {integrity: sha512-p4vsWnd/LRGOdGQglbwOguIVhPmCAf5UzquvnDoxqhhPWTP84wWgi1INea8MgJ4SnI2gp37f13oA4Waz9vwNYg==} requiresBuild: true dependencies: - '@ark/util': 0.49.0 + '@ark/util': 0.50.0 dev: false optional: true - /@ark/util@0.49.0: - resolution: {integrity: sha512-/BtnX7oCjNkxi2vi6y1399b+9xd1jnCrDYhZ61f0a+3X8x8DxlK52VgEEzyuC2UQMPACIfYrmHkhD3lGt2GaMA==} + /@ark/schema@0.50.0: + resolution: {integrity: sha512-hfmP82GltBZDadIOeR3argKNlYYyB2wyzHp0eeAqAOFBQguglMV/S7Ip2q007bRtKxIMLDqFY6tfPie1dtssaQ==} requiresBuild: true + dependencies: + '@ark/util': 0.50.0 dev: false optional: true - /@axe-core/playwright@4.10.1(playwright-core@1.56.0): + /@ark/util@0.50.0: + resolution: {integrity: sha512-tIkgIMVRpkfXRQIEf0G2CJryZVtHVrqcWHMDa5QKo0OEEBu0tHkRSIMm4Ln8cd8Bn9TPZtvc/kE2Gma8RESPSg==} + requiresBuild: true + dev: false + optional: true + + /@axe-core/playwright@4.10.1(playwright-core@1.51.1): resolution: {integrity: sha512-EV5t39VV68kuAfMKqb/RL+YjYKhfuGim9rgIaQ6Vntb2HgaCaau0h98Y3WEUqW1+PbdzxDtDNjFAipbtZuBmEA==} peerDependencies: playwright-core: '>= 1.0.0' dependencies: axe-core: 4.10.2 - playwright-core: 1.56.0 + playwright-core: 1.51.1 dev: true /@babel/code-frame@7.18.6: @@ -1279,32 +1314,32 @@ packages: - react dev: true - /@codemirror/autocomplete@6.18.7: - resolution: {integrity: sha512-8EzdeIoWPJDsMBwz3zdzwXnUpCzMiCyz5/A3FIPpriaclFCGDkAzK13sMcnsu5rowqiyeQN2Vs2TsOcoDPZirQ==} + /@codemirror/autocomplete@6.19.0: + resolution: {integrity: sha512-61Hfv3cF07XvUxNeC3E7jhG8XNi1Yom1G0lRC936oLnlF+jrbrv8rc/J98XlYzcsAoTVupfsf5fLej1aI8kyIg==} dependencies: '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 dev: false - /@codemirror/commands@6.8.1: - resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==} + /@codemirror/commands@6.9.0: + resolution: {integrity: sha512-454TVgjhO6cMufsyyGN70rGIfJxJEjcqjBG2x2Y03Y/+Fm99d3O/Kv1QDYWuG6hvxsgmjXmBuATikIIYvERX+w==} dependencies: '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 dev: false /@codemirror/lang-angular@0.1.4: resolution: {integrity: sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==} dependencies: - '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-html': 6.4.11 '@codemirror/lang-javascript': 6.2.4 '@codemirror/language': 6.11.3 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 + '@lezer/highlight': 1.1.3 '@lezer/lr': 1.4.2 dev: false @@ -1318,7 +1353,7 @@ packages: /@codemirror/lang-css@6.3.1: resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 @@ -1328,25 +1363,25 @@ packages: /@codemirror/lang-go@6.0.1: resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 '@lezer/go': 1.0.1 dev: false - /@codemirror/lang-html@6.4.9: - resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==} + /@codemirror/lang-html@6.4.11: + resolution: {integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/lang-css': 6.3.1 '@codemirror/lang-javascript': 6.2.4 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/css': 1.3.0 - '@lezer/html': 1.3.10 + '@lezer/html': 1.3.12 dev: false /@codemirror/lang-java@6.0.2: @@ -1359,13 +1394,13 @@ packages: /@codemirror/lang-javascript@6.2.4: resolution: {integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 - '@codemirror/lint': 6.8.5 + '@codemirror/lint': 6.9.0 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 - '@lezer/javascript': 1.5.1 + '@lezer/javascript': 1.5.4 dev: false /@codemirror/lang-json@6.0.2: @@ -1381,49 +1416,49 @@ packages: '@codemirror/lang-css': 6.3.1 '@codemirror/language': 6.11.3 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@codemirror/lang-liquid@6.3.0: resolution: {integrity: sha512-fY1YsUExcieXRTsCiwX/bQ9+PbCTA/Fumv7C7mTUZHoFkibfESnaXwpr2aKH6zZVwysEunsHHkaIpM/pl3xETQ==} dependencies: - '@codemirror/autocomplete': 6.18.7 - '@codemirror/lang-html': 6.4.9 + '@codemirror/autocomplete': 6.19.0 + '@codemirror/lang-html': 6.4.11 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 + '@lezer/highlight': 1.1.3 '@lezer/lr': 1.4.2 dev: false - /@codemirror/lang-markdown@6.3.4: - resolution: {integrity: sha512-fBm0BO03azXnTAsxhONDYHi/qWSI+uSEIpzKM7h/bkIc9fHnFp9y7KTMXKON0teNT97pFhc1a9DQTtWBYEZ7ug==} + /@codemirror/lang-markdown@6.4.0: + resolution: {integrity: sha512-ZeArR54seh4laFbUTVy0ZmQgO+C/cxxlW4jEoQMhL3HALScBpZBeZcLzrQmJsTEx4is9GzOe0bFAke2B1KZqeA==} dependencies: - '@codemirror/autocomplete': 6.18.7 - '@codemirror/lang-html': 6.4.9 + '@codemirror/autocomplete': 6.19.0 + '@codemirror/lang-html': 6.4.11 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 - '@lezer/markdown': 1.4.3 + '@lezer/markdown': 1.5.1 dev: false /@codemirror/lang-php@6.0.2: resolution: {integrity: sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==} dependencies: - '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-html': 6.4.11 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 - '@lezer/php': 1.0.4 + '@lezer/php': 1.0.5 dev: false /@codemirror/lang-python@6.2.1: resolution: {integrity: sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 @@ -1450,22 +1485,22 @@ packages: /@codemirror/lang-sql@6.10.0: resolution: {integrity: sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@codemirror/lang-vue@0.1.3: resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} dependencies: - '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-html': 6.4.11 '@codemirror/lang-javascript': 6.2.4 '@codemirror/language': 6.11.3 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 + '@lezer/highlight': 1.1.3 '@lezer/lr': 1.4.2 dev: false @@ -1474,17 +1509,17 @@ packages: dependencies: '@codemirror/language': 6.11.3 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@codemirror/lang-xml@6.1.0: resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 '@lezer/xml': 1.0.6 dev: false @@ -1492,12 +1527,12 @@ packages: /@codemirror/lang-yaml@6.1.2: resolution: {integrity: sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==} dependencies: - '@codemirror/autocomplete': 6.18.7 + '@codemirror/autocomplete': 6.19.0 '@codemirror/language': 6.11.3 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.2.2 + '@lezer/lr': 1.3.0 '@lezer/yaml': 1.0.3 dev: false @@ -1508,13 +1543,13 @@ packages: '@codemirror/lang-cpp': 6.0.3 '@codemirror/lang-css': 6.3.1 '@codemirror/lang-go': 6.0.1 - '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-html': 6.4.11 '@codemirror/lang-java': 6.0.2 '@codemirror/lang-javascript': 6.2.4 '@codemirror/lang-json': 6.0.2 '@codemirror/lang-less': 6.0.2 '@codemirror/lang-liquid': 6.3.0 - '@codemirror/lang-markdown': 6.3.4 + '@codemirror/lang-markdown': 6.4.0 '@codemirror/lang-php': 6.0.2 '@codemirror/lang-python': 6.2.1 '@codemirror/lang-rust': 6.0.2 @@ -1525,31 +1560,31 @@ packages: '@codemirror/lang-xml': 6.1.0 '@codemirror/lang-yaml': 6.1.2 '@codemirror/language': 6.11.3 - '@codemirror/legacy-modes': 6.5.1 + '@codemirror/legacy-modes': 6.5.2 dev: false /@codemirror/language@6.11.3: resolution: {integrity: sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==} dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 style-mod: 4.1.2 dev: false - /@codemirror/legacy-modes@6.5.1: - resolution: {integrity: sha512-DJYQQ00N1/KdESpZV7jg9hafof/iBNp9h7TYo1SLMk86TWl9uDsVdho2dzd81K+v4retmK6mdC7WpuOQDytQqw==} + /@codemirror/legacy-modes@6.5.2: + resolution: {integrity: sha512-/jJbwSTazlQEDOQw2FJ8LEEKVS72pU0lx6oM54kGpL8t/NJ2Jda3CZ4pcltiKTdqYSRk3ug1B3pil1gsjA6+8Q==} dependencies: '@codemirror/language': 6.11.3 dev: false - /@codemirror/lint@6.8.5: - resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==} + /@codemirror/lint@6.9.0: + resolution: {integrity: sha512-wZxW+9XDytH3SKvS8cQzMyQCaaazH8XL1EMHleHe00wVzsv7NBQKVW2yzEHrRhmM7ZOhVdItPbvlRBvMp9ej7A==} dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 + '@codemirror/view': 6.38.6 crelt: 1.0.6 dev: false @@ -1559,8 +1594,8 @@ packages: '@marijn/find-cluster-break': 1.0.2 dev: false - /@codemirror/view@6.38.2: - resolution: {integrity: sha512-bTWAJxL6EOFLPzTx+O5P5xAO3gTqpatQ2b/ARQ8itfU/v2LlpS3pH2fkL0A3E/Fx8Y2St2KES7ZEV0sHTsSW/A==} + /@codemirror/view@6.38.6: + resolution: {integrity: sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==} dependencies: '@codemirror/state': 6.5.2 crelt: 1.0.6 @@ -1640,14 +1675,6 @@ packages: requiresBuild: true optional: true - /@esbuild/aix-ppc64@0.25.10: - resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - optional: true - /@esbuild/android-arm64@0.17.19: resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -1674,14 +1701,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm64@0.25.10: - resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm@0.17.19: resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} engines: {node: '>=12'} @@ -1708,14 +1727,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm@0.25.10: - resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-x64@0.17.19: resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} engines: {node: '>=12'} @@ -1742,14 +1753,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-x64@0.25.10: - resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.17.19: resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} engines: {node: '>=12'} @@ -1776,14 +1779,6 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-arm64@0.25.10: - resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-x64@0.17.19: resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} engines: {node: '>=12'} @@ -1810,14 +1805,6 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-x64@0.25.10: - resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - /@esbuild/freebsd-arm64@0.17.19: resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} engines: {node: '>=12'} @@ -1844,14 +1831,6 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-arm64@0.25.10: - resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-x64@0.17.19: resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} engines: {node: '>=12'} @@ -1878,14 +1857,6 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-x64@0.25.10: - resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/linux-arm64@0.17.19: resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} engines: {node: '>=12'} @@ -1912,14 +1883,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm64@0.25.10: - resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm@0.17.19: resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} engines: {node: '>=12'} @@ -1946,14 +1909,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm@0.25.10: - resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ia32@0.17.19: resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} engines: {node: '>=12'} @@ -1980,14 +1935,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ia32@0.25.10: - resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64@0.17.19: resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} engines: {node: '>=12'} @@ -2014,14 +1961,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-loong64@0.25.10: - resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-mips64el@0.17.19: resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} engines: {node: '>=12'} @@ -2048,14 +1987,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.25.10: - resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ppc64@0.17.19: resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} engines: {node: '>=12'} @@ -2082,14 +2013,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.25.10: - resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-riscv64@0.17.19: resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} @@ -2116,14 +2039,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-riscv64@0.25.10: - resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-s390x@0.17.19: resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} @@ -2150,14 +2065,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-s390x@0.25.10: - resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-x64@0.17.19: resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} @@ -2184,14 +2091,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-x64@0.25.10: - resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/netbsd-arm64@0.25.0: resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} engines: {node: '>=18'} @@ -2200,14 +2099,6 @@ packages: requiresBuild: true optional: true - /@esbuild/netbsd-arm64@0.25.10: - resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - requiresBuild: true - optional: true - /@esbuild/netbsd-x64@0.17.19: resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} @@ -2234,14 +2125,6 @@ packages: requiresBuild: true optional: true - /@esbuild/netbsd-x64@0.25.10: - resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - /@esbuild/openbsd-arm64@0.25.0: resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} engines: {node: '>=18'} @@ -2250,14 +2133,6 @@ packages: requiresBuild: true optional: true - /@esbuild/openbsd-arm64@0.25.10: - resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - requiresBuild: true - optional: true - /@esbuild/openbsd-x64@0.17.19: resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} engines: {node: '>=12'} @@ -2284,22 +2159,6 @@ packages: requiresBuild: true optional: true - /@esbuild/openbsd-x64@0.25.10: - resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - - /@esbuild/openharmony-arm64@0.25.10: - resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - requiresBuild: true - optional: true - /@esbuild/sunos-x64@0.17.19: resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} engines: {node: '>=12'} @@ -2326,14 +2185,6 @@ packages: requiresBuild: true optional: true - /@esbuild/sunos-x64@0.25.10: - resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - /@esbuild/win32-arm64@0.17.19: resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} @@ -2360,14 +2211,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-arm64@0.25.10: - resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-ia32@0.17.19: resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} @@ -2394,14 +2237,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-ia32@0.25.10: - resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-x64@0.17.19: resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} @@ -2428,14 +2263,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-x64@0.25.10: - resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.47.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2473,7 +2300,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.4.0 espree: 9.6.1 globals: 13.21.0 ignore: 5.2.4 @@ -2496,6 +2323,16 @@ packages: dev: false optional: true + /@finom/zod-to-json-schema@3.24.11(zod@4.1.12): + resolution: {integrity: sha512-fL656yBPiWebtfGItvtXLWrFNGlF1NcDFS0WdMQXMs9LluVg0CfT5E2oXYp0pidl0vVG53XkW55ysijNkU5/hA==} + requiresBuild: true + peerDependencies: + zod: ^4.0.14 + dependencies: + zod: 4.1.12 + dev: false + optional: true + /@fontsource-variable/inter@5.0.8: resolution: {integrity: sha512-WkYfFNccmEIeL2fNg0mYeLWqOoB7xD8MFxFRc4IwbSP2o8ZaBt36v5aW4by4MyrgGRMNk7uNi5LbvYKq6clPjw==} dev: false @@ -2504,7 +2341,7 @@ packages: resolution: {integrity: sha512-kEnRN/Vs7TgWkY+Y5U36b2NZOYITWEY1T6LYkjFopCA2eaUWY4DDO7UOov55VE/PHDZH8KZZIOoEmBiM4Nv7Kw==} dev: false - /@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.10)(typescript@5.2.2): + /@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.0)(typescript@5.2.2): resolution: {integrity: sha512-4Et4AN6wmqeA0PfU5Clkv/IS27wiefsWf6TemAZrb75uzkClYEFavim7SboeKwbll9Nbsn2Iv0LT/HS5H7orZg==} hasBin: true requiresBuild: true @@ -2512,7 +2349,7 @@ packages: valibot: 0.42.1(typescript@5.2.2) optionalDependencies: '@types/json-schema': 7.0.15 - esbuild-runner: 2.2.2(esbuild@0.25.10) + esbuild-runner: 2.2.2(esbuild@0.25.0) transitivePeerDependencies: - esbuild - typescript @@ -2527,11 +2364,11 @@ packages: '@js-sdsl/ordered-map': 4.4.2 dev: true - /@grpc/grpc-js@1.13.4: - resolution: {integrity: sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==} + /@grpc/grpc-js@1.14.0: + resolution: {integrity: sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg==} engines: {node: '>=12.10.0'} dependencies: - '@grpc/proto-loader': 0.7.13 + '@grpc/proto-loader': 0.8.0 '@js-sdsl/ordered-map': 4.4.2 dev: true @@ -2546,6 +2383,17 @@ packages: yargs: 17.7.2 dev: true + /@grpc/proto-loader@0.8.0: + resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.5.4 + yargs: 17.7.2 + dev: true + /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -2559,7 +2407,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 + debug: 4.4.0 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -2879,6 +2727,22 @@ packages: resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} dev: true + /@koa/cors@5.0.0: + resolution: {integrity: sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==} + engines: {node: '>= 14.0.0'} + dependencies: + vary: 1.1.2 + dev: true + + /@koa/router@13.1.0: + resolution: {integrity: sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw==} + engines: {node: '>= 18'} + dependencies: + http-errors: 2.0.0 + koa-compose: 4.1.0 + path-to-regexp: 6.3.0 + dev: true + /@lezer/common@1.0.2: resolution: {integrity: sha512-SVgiGtMnMnW3ActR8SXgsDhw7a0w0ChHSYAyAUxxrOiJ1OqYWEKk/xJd84tTSPo1mo6DXLObAJALNnd0Hrv7Ng==} dev: false @@ -2887,28 +2751,32 @@ packages: resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} dev: false + /@lezer/common@1.3.0: + resolution: {integrity: sha512-L9X8uHCYU310o99L3/MpJKYxPzXPOS7S0NmBaM7UO/x2Kb2WbmMLSkfvdr1KxRIFYOpbY0Jhn7CfLSUDzL8arQ==} + dev: false + /@lezer/cpp@1.1.3: resolution: {integrity: sha512-ykYvuFQKGsRi6IcE+/hCSGUhb/I4WPjd3ELhEblm2wS2cOznDFzO+ubK2c+ioysOnlZ3EduV+MVQFCPzAIoY3w==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/css@1.3.0: resolution: {integrity: sha512-pBL7hup88KbI7hXnZV3PQsn43DHy6TWyzuyk2AO9UyoXcDltvIdqWKE1dLL/45JVZ+YZkHe1WVHqO6wugZZWcw==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/go@1.0.1: resolution: {integrity: sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/highlight@1.1.3: @@ -2917,41 +2785,47 @@ packages: '@lezer/common': 1.0.2 dev: false - /@lezer/highlight@1.2.1: - resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} + /@lezer/highlight@1.2.2: + resolution: {integrity: sha512-z8TQwaBXXQIvG6i2g3e9cgMwUUXu9Ib7jo2qRRggdhwKpM56Dw3PM3wmexn+EGaaOZ7az0K7sjc3/gcGW7sz7A==} dependencies: - '@lezer/common': 1.2.3 + '@lezer/common': 1.3.0 dev: false - /@lezer/html@1.3.10: - resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==} + /@lezer/html@1.3.12: + resolution: {integrity: sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/java@1.1.3: resolution: {integrity: sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false - /@lezer/javascript@1.5.1: - resolution: {integrity: sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==} + /@lezer/javascript@1.5.4: + resolution: {integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/json@1.0.0: resolution: {integrity: sha512-zbAuUY09RBzCoCA3lJ1+ypKw5WSNvLqGMtasdW6HvVOqZoCpPr8eWrsGnOVWGKGn8Rh21FnrKRVlJXrGAVUqRw==} dependencies: - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 + dev: false + + /@lezer/lr@1.3.0: + resolution: {integrity: sha512-rpvS+WPS/PlbJCiW+bzXPbIFIRXmzRiTEDzMvrvgpED05w5ZQO59AzH3BJen2AnHuJIlP3DcJRjsKLTrkknUNA==} + dependencies: + '@lezer/common': 1.2.3 dev: false /@lezer/lr@1.4.2: @@ -2960,58 +2834,58 @@ packages: '@lezer/common': 1.2.3 dev: false - /@lezer/markdown@1.4.3: - resolution: {integrity: sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==} + /@lezer/markdown@1.5.1: + resolution: {integrity: sha512-F3ZFnIfNAOy/jPSk6Q0e3bs7e9grfK/n5zerkKoc5COH6Guy3Zb0vrJwXzdck79K16goBhYBRAvhf+ksqe0cMg==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 + '@lezer/highlight': 1.1.3 dev: false - /@lezer/php@1.0.4: - resolution: {integrity: sha512-D2dJ0t8Z28/G1guztRczMFvPDUqzeMLSQbdWQmaiHV7urc8NlEOnjYk9UrZ531OcLiRxD4Ihcbv7AsDpNKDRaQ==} + /@lezer/php@1.0.5: + resolution: {integrity: sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/python@1.1.18: resolution: {integrity: sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/rust@1.0.2: resolution: {integrity: sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/sass@1.1.0: resolution: {integrity: sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/xml@1.0.6: resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 + '@lezer/highlight': 1.1.3 + '@lezer/lr': 1.3.0 dev: false /@lezer/yaml@1.0.3: resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==} dependencies: '@lezer/common': 1.2.3 - '@lezer/highlight': 1.2.1 + '@lezer/highlight': 1.2.2 '@lezer/lr': 1.4.2 dev: false @@ -3037,14 +2911,14 @@ packages: resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} dev: false - /@mdx-js/react@3.0.1(@types/react@19.2.0)(react@18.2.0): + /@mdx-js/react@3.0.1(@types/react@19.1.1)(react@18.2.0): resolution: {integrity: sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==} peerDependencies: '@types/react': '>=16' react: '>=16' dependencies: '@types/mdx': 2.0.9 - '@types/react': 19.2.0 + '@types/react': 19.1.1 react: 18.2.0 dev: true @@ -3087,9 +2961,8 @@ packages: /@polka/url@1.0.0-next.24: resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} - /@poppinss/macroable@1.0.4: - resolution: {integrity: sha512-ct43jurbe7lsUX5eIrj4ijO3j/6zIPp7CDnFWXDs7UPAbw1Pu1iH3oAmFdP4jcskKJBURH5M9oTtyeiUXyHX8Q==} - engines: {node: '>=18.16.0'} + /@poppinss/macroable@1.1.0: + resolution: {integrity: sha512-y/YKzZDuG8XrpXpM7Z1RdQpiIc0MAKyva24Ux1PB4aI7RiSI/79K8JVDcdyubriTm7vJ1LhFs8CrZpmPnx/8Pw==} requiresBuild: true dev: false optional: true @@ -3145,141 +3018,141 @@ packages: picomatch: 2.3.1 dev: true - /@rollup/rollup-android-arm-eabi@4.40.1: - resolution: {integrity: sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==} + /@rollup/rollup-android-arm-eabi@4.39.0: + resolution: {integrity: sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==} cpu: [arm] os: [android] requiresBuild: true optional: true - /@rollup/rollup-android-arm64@4.40.1: - resolution: {integrity: sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==} + /@rollup/rollup-android-arm64@4.39.0: + resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==} cpu: [arm64] os: [android] requiresBuild: true optional: true - /@rollup/rollup-darwin-arm64@4.40.1: - resolution: {integrity: sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==} + /@rollup/rollup-darwin-arm64@4.39.0: + resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /@rollup/rollup-darwin-x64@4.40.1: - resolution: {integrity: sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==} + /@rollup/rollup-darwin-x64@4.39.0: + resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /@rollup/rollup-freebsd-arm64@4.40.1: - resolution: {integrity: sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==} + /@rollup/rollup-freebsd-arm64@4.39.0: + resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==} cpu: [arm64] os: [freebsd] requiresBuild: true optional: true - /@rollup/rollup-freebsd-x64@4.40.1: - resolution: {integrity: sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==} + /@rollup/rollup-freebsd-x64@4.39.0: + resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==} cpu: [x64] os: [freebsd] requiresBuild: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.40.1: - resolution: {integrity: sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==} + /@rollup/rollup-linux-arm-gnueabihf@4.39.0: + resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==} cpu: [arm] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-arm-musleabihf@4.40.1: - resolution: {integrity: sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==} + /@rollup/rollup-linux-arm-musleabihf@4.39.0: + resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==} cpu: [arm] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.40.1: - resolution: {integrity: sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==} + /@rollup/rollup-linux-arm64-gnu@4.39.0: + resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-arm64-musl@4.40.1: - resolution: {integrity: sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==} + /@rollup/rollup-linux-arm64-musl@4.39.0: + resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-loongarch64-gnu@4.40.1: - resolution: {integrity: sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==} + /@rollup/rollup-linux-loongarch64-gnu@4.39.0: + resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==} cpu: [loong64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-powerpc64le-gnu@4.40.1: - resolution: {integrity: sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==} + /@rollup/rollup-linux-powerpc64le-gnu@4.39.0: + resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==} cpu: [ppc64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-riscv64-gnu@4.40.1: - resolution: {integrity: sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==} + /@rollup/rollup-linux-riscv64-gnu@4.39.0: + resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==} cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-riscv64-musl@4.40.1: - resolution: {integrity: sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==} + /@rollup/rollup-linux-riscv64-musl@4.39.0: + resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==} cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-s390x-gnu@4.40.1: - resolution: {integrity: sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==} + /@rollup/rollup-linux-s390x-gnu@4.39.0: + resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==} cpu: [s390x] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-x64-gnu@4.40.1: - resolution: {integrity: sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==} + /@rollup/rollup-linux-x64-gnu@4.39.0: + resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-x64-musl@4.40.1: - resolution: {integrity: sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==} + /@rollup/rollup-linux-x64-musl@4.39.0: + resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.40.1: - resolution: {integrity: sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==} + /@rollup/rollup-win32-arm64-msvc@4.39.0: + resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.40.1: - resolution: {integrity: sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==} + /@rollup/rollup-win32-ia32-msvc@4.39.0: + resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /@rollup/rollup-win32-x64-msvc@4.40.1: - resolution: {integrity: sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==} + /@rollup/rollup-win32-x64-msvc@4.39.0: + resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==} cpu: [x64] os: [win32] requiresBuild: true @@ -3300,12 +3173,6 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true - /@sinclair/typebox@0.34.41: - resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} - requiresBuild: true - dev: false - optional: true - /@sinonjs/commons@3.0.1: resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} dependencies: @@ -3320,7 +3187,6 @@ packages: /@standard-schema/spec@1.0.0: resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} - requiresBuild: true /@storybook/addon-a11y@8.6.11(storybook@8.6.11): resolution: {integrity: sha512-VijoBrsoHkZDkBNT9Fkpt569S4p5rVRBCUrcyZiGOLAt/DZtuAWQEBO4eENHPldvEXtjHckZRzz4oaUwJGcXGQ==} @@ -3382,12 +3248,12 @@ packages: ts-dedent: 2.2.0 dev: true - /@storybook/addon-docs@8.6.11(@types/react@19.2.0)(storybook@8.6.11): + /@storybook/addon-docs@8.6.11(@types/react@19.1.1)(storybook@8.6.11): resolution: {integrity: sha512-gTSF1m3HJkeU7GKPYhe8grO48FbpulvIWZ213PtnWedgVkTNieok3oBmmigv17ua/QXH0u5EbaoMSxaAyrsAzg==} peerDependencies: storybook: ^8.6.11 dependencies: - '@mdx-js/react': 3.0.1(@types/react@19.2.0)(react@18.2.0) + '@mdx-js/react': 3.0.1(@types/react@19.1.1)(react@18.2.0) '@storybook/blocks': 8.6.11(react-dom@18.2.0)(react@18.2.0)(storybook@8.6.11) '@storybook/csf-plugin': 8.6.11(storybook@8.6.11) '@storybook/react-dom-shim': 8.6.11(react-dom@18.2.0)(react@18.2.0)(storybook@8.6.11) @@ -3399,7 +3265,7 @@ packages: - '@types/react' dev: true - /@storybook/addon-essentials@8.6.11(@types/react@19.2.0)(storybook@8.6.11): + /@storybook/addon-essentials@8.6.11(@types/react@19.1.1)(storybook@8.6.11): resolution: {integrity: sha512-QII5yTM0cGRryfTSJSK5Hf2CEiAX3atqccHZbPipkqO7dE9YDBvRfVwG0cQpHdv10tP066MDWgVDF5E3pDKecw==} peerDependencies: storybook: ^8.6.11 @@ -3407,7 +3273,7 @@ packages: '@storybook/addon-actions': 8.6.11(storybook@8.6.11) '@storybook/addon-backgrounds': 8.6.11(storybook@8.6.11) '@storybook/addon-controls': 8.6.11(storybook@8.6.11) - '@storybook/addon-docs': 8.6.11(@types/react@19.2.0)(storybook@8.6.11) + '@storybook/addon-docs': 8.6.11(@types/react@19.1.1)(storybook@8.6.11) '@storybook/addon-highlight': 8.6.11(storybook@8.6.11) '@storybook/addon-measure': 8.6.11(storybook@8.6.11) '@storybook/addon-outline': 8.6.11(storybook@8.6.11) @@ -3476,7 +3342,7 @@ packages: ts-dedent: 2.2.0 dev: true - /@storybook/addon-svelte-csf@5.0.0-next.27(@storybook/svelte@8.6.11)(@sveltejs/vite-plugin-svelte@5.0.3)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.7): + /@storybook/addon-svelte-csf@5.0.0-next.27(@storybook/svelte@8.6.11)(@sveltejs/vite-plugin-svelte@5.0.3)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.6): resolution: {integrity: sha512-iWEg084pWy2m9Z7jLDg+zXS8cjA2eRBrLe127KV9P1RYtyYzh45ALN72wVNoHmWzLNQl2CAh0ggTCKjMHHEjRg==} peerDependencies: '@storybook/svelte': ^0.0.0-0 || ^8.2.0 || ^9.0.0-0 @@ -3487,7 +3353,7 @@ packages: dependencies: '@storybook/csf': 0.1.13 '@storybook/svelte': 8.6.11(storybook@8.6.11)(svelte@5.25.5) - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.6) dedent: 1.5.3 es-toolkit: 1.32.0 esrap: 1.4.5 @@ -3495,7 +3361,7 @@ packages: storybook: 8.6.11(prettier@3.5.3) svelte: 5.25.5 svelte-ast-print: 0.4.2(svelte@5.25.5) - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) zimmerframe: 1.1.2 transitivePeerDependencies: - babel-plugin-macros @@ -3546,7 +3412,7 @@ packages: ts-dedent: 2.2.0 dev: true - /@storybook/builder-vite@8.6.11(storybook@8.6.11)(vite@6.2.7): + /@storybook/builder-vite@8.6.11(storybook@8.6.11)(vite@6.2.6): resolution: {integrity: sha512-d8SsHr6iM49kTyrg6PTYn9aHxOBiWUZvPhOOtfODHl2SH9PPRenfwX3a3B+OsD04GPVGvLz5fp4Apg9lrDVSzw==} peerDependencies: storybook: ^8.6.11 @@ -3556,7 +3422,7 @@ packages: browser-assert: 1.2.1 storybook: 8.6.11(prettier@3.5.3) ts-dedent: 2.2.0 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) dev: true /@storybook/components@8.6.11(storybook@8.6.11): @@ -3674,7 +3540,7 @@ packages: storybook: 8.6.11(prettier@3.5.3) dev: true - /@storybook/svelte-vite@8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.7): + /@storybook/svelte-vite@8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.6): resolution: {integrity: sha512-umLoL/B7+P4Yb9ENe4kP8cpRWVg3WnfaVkMrnNzKG/Di7pQePeRY+KNP/RBVA/+8QpF3kwU00KNHKmpUYDzP/Q==} engines: {node: '>=18.0.0'} peerDependencies: @@ -3683,9 +3549,9 @@ packages: svelte: ^4.0.0 || ^5.0.0 vite: ^4.0.0 || ^5.0.0 || ^6.0.0 dependencies: - '@storybook/builder-vite': 8.6.11(storybook@8.6.11)(vite@6.2.7) + '@storybook/builder-vite': 8.6.11(storybook@8.6.11)(vite@6.2.6) '@storybook/svelte': 8.6.11(storybook@8.6.11)(svelte@5.25.5) - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.6) magic-string: 0.30.17 storybook: 8.6.11(prettier@3.5.3) svelte: 5.25.5 @@ -3694,7 +3560,7 @@ packages: sveltedoc-parser: 4.2.1 ts-dedent: 2.2.0 typescript: 5.2.2 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) transitivePeerDependencies: - '@babel/core' - coffeescript @@ -3730,7 +3596,7 @@ packages: - supports-color dev: true - /@storybook/sveltekit@8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.7): + /@storybook/sveltekit@8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.6): resolution: {integrity: sha512-PzC+dJZXm9150rrtgRC2LHDwrD/ZVR/8+QQwsEBZYjzwU8uX3VTFqQmymVWlvSF7xHyF3rq5iPvOoQTmX4BMSA==} engines: {node: '>=18.0.0'} peerDependencies: @@ -3739,12 +3605,12 @@ packages: vite: ^4.0.0 || ^5.0.0 || ^6.0.0 dependencies: '@storybook/addon-actions': 8.6.11(storybook@8.6.11) - '@storybook/builder-vite': 8.6.11(storybook@8.6.11)(vite@6.2.7) + '@storybook/builder-vite': 8.6.11(storybook@8.6.11)(vite@6.2.6) '@storybook/svelte': 8.6.11(storybook@8.6.11)(svelte@5.25.5) - '@storybook/svelte-vite': 8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.7) + '@storybook/svelte-vite': 8.6.11(@babel/core@7.20.12)(@sveltejs/vite-plugin-svelte@5.0.3)(postcss-load-config@3.1.4)(postcss@8.4.31)(storybook@8.6.11)(svelte@5.25.5)(vite@6.2.6) storybook: 8.6.11(prettier@3.5.3) svelte: 5.25.5 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) transitivePeerDependencies: - '@babel/core' - '@sveltejs/vite-plugin-svelte' @@ -3833,20 +3699,20 @@ packages: dependencies: acorn: 8.15.0 - /@sveltejs/adapter-static@3.0.8(@sveltejs/kit@2.36.1): + /@sveltejs/adapter-static@3.0.8(@sveltejs/kit@2.47.2): resolution: {integrity: sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==} peerDependencies: '@sveltejs/kit': ^2.0.0 dependencies: - '@sveltejs/kit': 2.36.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/kit': 2.47.2(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6) dev: true - /@sveltejs/adapter-vercel@4.0.0(@sveltejs/kit@2.36.1): + /@sveltejs/adapter-vercel@4.0.0(@sveltejs/kit@2.47.2): resolution: {integrity: sha512-Qt8BY/Z7B0EXSeu+7mLhHoMdxeU7/AzIDRwH2TWgxT+eowiYxm9ZdtsLxVrXHHwborWlK2nbwfBsZr3FDXVxkQ==} peerDependencies: '@sveltejs/kit': ^2.0.0 dependencies: - '@sveltejs/kit': 2.36.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/kit': 2.47.2(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6) '@vercel/nft': 0.24.4 esbuild: 0.19.12 transitivePeerDependencies: @@ -3854,8 +3720,8 @@ packages: - supports-color dev: true - /@sveltejs/kit@2.36.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7): - resolution: {integrity: sha512-dldNCtSIpaGxQMEfHaUxSPH/k3uU28pTZwtKzfkn8fqpOjWufKlMBeIL7FJ/s93dOrhEq41zaQYkXh+XTgEgVw==} + /@sveltejs/kit@2.47.2(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6): + resolution: {integrity: sha512-mbUomaJTiADTrq6GT4ZvQ7v1rs0S+wXGMzrjFwjARAKMEF8FpOUmz2uEJ4M9WMJMQOXCMHpKFzJfdjo9O7M22A==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -3869,7 +3735,7 @@ packages: dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.6) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 @@ -3882,7 +3748,7 @@ packages: set-cookie-parser: 2.6.0 sirv: 3.0.1 svelte: 5.25.5 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) /@sveltejs/package@2.3.10(svelte@5.25.5)(typescript@5.2.2): resolution: {integrity: sha512-A4fQacgjJ7C/7oSmxR61/TdB14u6ecyMZ8V9JCR5Lol0bLj/PdJPU4uFodFBsKzO3iFiJMpNTgZZ+zYsYZNpUg==} @@ -3901,7 +3767,7 @@ packages: - typescript dev: false - /@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7): + /@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6): resolution: {integrity: sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: @@ -3909,28 +3775,28 @@ packages: svelte: ^5.0.0 vite: ^6.0.0 dependencies: - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.25.5)(vite@6.2.6) debug: 4.4.0 svelte: 5.25.5 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) transitivePeerDependencies: - supports-color - /@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.5)(vite@6.2.7): + /@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.5)(vite@6.2.6): resolution: {integrity: sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: svelte: ^5.0.0 vite: ^6.0.0 dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6) debug: 4.4.0 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.17 svelte: 5.25.5 - vite: 6.2.7(@types/node@18.15.3) - vitefu: 1.0.6(vite@6.2.7) + vite: 6.2.6(@types/node@18.15.3) + vitefu: 1.0.6(vite@6.2.6) transitivePeerDependencies: - supports-color @@ -4083,7 +3949,7 @@ packages: resolution: {integrity: sha512-m89isGb6I4BBeCbhkvXbpjeRZZUa3E2R06J/I+t2JWgv0Tg+PoNPusvU9UBd6LN7f7AetsQvAZKU6eQHyWxSEA==} engines: {node: '>= 18.0.0'} dependencies: - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@temporalio/common': 1.12.1 '@temporalio/proto': 1.12.1 abort-controller: 3.0.0 @@ -4106,7 +3972,7 @@ packages: engines: {node: '>= 18.0.0'} requiresBuild: true dependencies: - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@temporalio/common': 1.12.1 arg: 5.0.2 cargo-cp-artifact: 0.1.8 @@ -4129,7 +3995,7 @@ packages: protobufjs: 7.2.5 dev: true - /@temporalio/testing@1.12.1(esbuild@0.25.10): + /@temporalio/testing@1.12.1(esbuild@0.25.0): resolution: {integrity: sha512-vg6NfqoF5xHw/L3eswBqCA3cxqHEePEj2kPxNkxMrEaNAqjHx/1HNkmazRFjC3kN/L1hHRj/ERLcF8zGIOeiwA==} engines: {node: '>= 18.0.0'} dependencies: @@ -4138,7 +4004,7 @@ packages: '@temporalio/common': 1.12.1 '@temporalio/core-bridge': 1.12.1 '@temporalio/proto': 1.12.1 - '@temporalio/worker': 1.12.1(esbuild@0.25.10) + '@temporalio/worker': 1.12.1(esbuild@0.25.0) '@temporalio/workflow': 1.12.1 abort-controller: 3.0.0 transitivePeerDependencies: @@ -4148,11 +4014,11 @@ packages: - webpack-cli dev: true - /@temporalio/worker@1.12.1(esbuild@0.25.10): + /@temporalio/worker@1.12.1(esbuild@0.25.0): resolution: {integrity: sha512-jI3UxPAVbuM2MJO0c27iNV59KNHgAlx6yoJOpcE+jdGAmoN52MHdSt3qedrWtWINgZDbZg9dPC8KoDbXr9kP6g==} engines: {node: '>= 18.0.0'} dependencies: - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@swc/core': 1.10.7 '@temporalio/activity': 1.12.1 '@temporalio/client': 1.12.1 @@ -4170,7 +4036,7 @@ packages: supports-color: 8.1.1 swc-loader: 0.2.3(@swc/core@1.10.7)(webpack@5.94.0) unionfs: 4.5.1 - webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.10) + webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.0) transitivePeerDependencies: - '@swc/helpers' - esbuild @@ -4265,8 +4131,8 @@ packages: '@babel/types': 7.26.9 dev: true - /@types/base-64@1.0.2: - resolution: {integrity: sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw==} + /@types/base-64@1.0.0: + resolution: {integrity: sha512-AvCJx/HrfYHmOQRFdVvgKMplXfzTUizmh0tz9GFTpDePWgCY4uoKll84zKlaRoeiYiCr7c9ZnqSTzkl0BUVD6g==} dev: true /@types/body-parser@1.19.2: @@ -4449,8 +4315,8 @@ packages: resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} dev: true - /@types/react@19.2.0: - resolution: {integrity: sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA==} + /@types/react@19.1.1: + resolution: {integrity: sha512-ePapxDL7qrgqSF67s0h9m412d9DbXyC1n59O2st+9rjuuamWsZuD2w55rqY12CbzsZ7uVXb5Nw0gEp9Z8MMutQ==} dependencies: csstype: 3.1.3 dev: true @@ -4506,8 +4372,8 @@ packages: resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} dev: true - /@types/validator@13.15.2: - resolution: {integrity: sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==} + /@types/validator@13.15.3: + resolution: {integrity: sha512-7bcUmDyS6PN3EuD9SlGGOxM77F8WLVsrwkxyWxKnxzmXoequ6c7741QBrANq6htVRGOITJ7z72mTP6Z4XyuG+Q==} requiresBuild: true dev: false optional: true @@ -4645,7 +4511,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 6.6.0(typescript@5.2.2) '@typescript-eslint/utils': 6.6.0(eslint@8.47.0)(typescript@5.2.2) - debug: 4.3.4 + debug: 4.4.0 eslint: 8.47.0 ts-api-utils: 1.0.2(typescript@5.2.2) typescript: 5.2.2 @@ -4721,7 +4587,7 @@ packages: dependencies: '@typescript-eslint/types': 6.6.0 '@typescript-eslint/visitor-keys': 6.6.0 - debug: 4.3.4 + debug: 4.4.0 globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 @@ -4850,13 +4716,13 @@ packages: engines: {node: '>=18.16.0'} requiresBuild: true dependencies: - '@poppinss/macroable': 1.0.4 - '@types/validator': 13.15.2 + '@poppinss/macroable': 1.1.0 + '@types/validator': 13.15.3 '@vinejs/compiler': 3.0.0 camelcase: 8.0.0 - dayjs: 1.11.13 + dayjs: 1.11.18 dlv: 1.1.3 - normalize-url: 8.0.2 + normalize-url: 8.1.0 validator: 13.15.15 dev: false optional: true @@ -4879,7 +4745,7 @@ packages: tinyrainbow: 2.0.0 dev: true - /@vitest/mocker@3.1.1(vite@6.2.7): + /@vitest/mocker@3.1.1(vite@6.2.6): resolution: {integrity: sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==} peerDependencies: msw: ^2.4.9 @@ -4893,7 +4759,7 @@ packages: '@vitest/spy': 3.1.1 estree-walker: 3.0.3 magic-string: 0.30.17 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) dev: true /@vitest/pretty-format@2.0.5: @@ -5317,12 +5183,13 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} - /arktype@2.1.22: - resolution: {integrity: sha512-xdzl6WcAhrdahvRRnXaNwsipCgHuNoLobRqhiP8RjnfL9Gp947abGlo68GAIyLtxbD+MLzNyH2YR4kEqioMmYQ==} + /arktype@2.1.23: + resolution: {integrity: sha512-tyxNWX6xJVMb2EPJJ3OjgQS1G/vIeQRrZuY4DeBNQmh8n7geS+czgbauQWB6Pr+RXiOO8ChEey44XdmxsqGmfQ==} requiresBuild: true dependencies: - '@ark/schema': 0.49.0 - '@ark/util': 0.49.0 + '@ark/regex': 0.0.0 + '@ark/schema': 0.50.0 + '@ark/util': 0.50.0 dev: false optional: true @@ -5427,6 +5294,10 @@ packages: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} dev: true + /async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + dev: true + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true @@ -5467,7 +5338,7 @@ packages: mustache: 4.2.0 dev: true - /axe-playwright@2.0.3(playwright@1.56.0): + /axe-playwright@2.0.3(playwright@1.51.1): resolution: {integrity: sha512-s7iI2okyHHsD3XZK4RMJtTy2UASkNWLQtnzLuaHiK3AWkERf+cqZJqkxb7O4b56fnbib9YnZVRByTl92ME3o6g==} peerDependencies: playwright: '>1.0.0' @@ -5477,7 +5348,7 @@ packages: axe-html-reporter: 2.2.11(axe-core@4.10.2) junit-report-builder: 5.1.1 picocolors: 1.1.0 - playwright: 1.56.0 + playwright: 1.51.1 dev: true /axios@1.8.2: @@ -5586,12 +5457,17 @@ packages: resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} dev: true - /bare-events@2.7.0: - resolution: {integrity: sha512-b3N5eTW1g7vXkw+0CXh/HazGTcO5KYuu/RCNaJbDMPI6LHDi+7qe8EmxKUVe1sUbY2KZOVZFyj62x0OEz9qyAA==} + /bare-events@2.8.0: + resolution: {integrity: sha512-AOhh6Bg5QmFIXdViHbMc2tLDsBIRxdkIaIddPslJF9Z5De3APBScuqGP2uThXnIpqFrgoxMNC6km7uXNIMLHXA==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true dev: true - /bare-fs@4.4.5: - resolution: {integrity: sha512-TCtu93KGLu6/aiGWzMr12TmSRS6nKdfhAnzTQRbXoSWxkbb9eRd53jQ51jG7g1gYjjtto3hbBrrhzg6djcgiKg==} + /bare-fs@4.4.11: + resolution: {integrity: sha512-Bejmm9zRMvMTRoHS+2adgmXw1ANZnCNx+B5dgZpGwlP1E3x6Yuxea8RToddHUbWtVV0iUMWqsgZr8+jcgUI2SA==} engines: {bare: '>=1.16.0'} requiresBuild: true peerDependencies: @@ -5600,12 +5476,13 @@ packages: bare-buffer: optional: true dependencies: - bare-events: 2.7.0 + bare-events: 2.8.0 bare-path: 3.0.0 - bare-stream: 2.7.0(bare-events@2.7.0) - bare-url: 2.2.2 + bare-stream: 2.7.0(bare-events@2.8.0) + bare-url: 2.3.1 fast-fifo: 1.3.2 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a dev: true optional: true @@ -5625,7 +5502,7 @@ packages: dev: true optional: true - /bare-stream@2.7.0(bare-events@2.7.0): + /bare-stream@2.7.0(bare-events@2.8.0): resolution: {integrity: sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==} requiresBuild: true peerDependencies: @@ -5637,15 +5514,16 @@ packages: bare-events: optional: true dependencies: - bare-events: 2.7.0 + bare-events: 2.8.0 streamx: 2.23.0 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a dev: true optional: true - /bare-url@2.2.2: - resolution: {integrity: sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA==} + /bare-url@2.3.1: + resolution: {integrity: sha512-v2yl0TnaZTdEnelkKtXZGnotiV6qATBlnNuUMrHl6v9Lmmrh9mw9RYyImPU7/4RahumSwQS1k2oKXcRfXcbjJw==} requiresBuild: true dependencies: bare-path: 3.0.0 @@ -5790,6 +5668,14 @@ packages: engines: {node: '>=8'} dev: true + /cache-content-type@1.0.1: + resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} + engines: {node: '>= 6.0.0'} + dependencies: + mime-types: 2.1.35 + ylru: 1.4.0 + dev: true + /caching-transform@4.0.0: resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==} engines: {node: '>=8'} @@ -5991,8 +5877,8 @@ packages: resolution: {integrity: sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==} requiresBuild: true dependencies: - '@types/validator': 13.15.2 - libphonenumber-js: 1.12.9 + '@types/validator': 13.15.3 + libphonenumber-js: 1.12.24 validator: 13.15.15 dev: false optional: true @@ -6186,6 +6072,14 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + /cookies@0.9.1: + resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + keygrip: 1.1.0 + dev: true + /cors@2.8.5: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} @@ -6227,6 +6121,17 @@ packages: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} dev: false + /cross-spawn@6.0.5: + resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + engines: {node: '>=4.8'} + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.1 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -6420,8 +6325,8 @@ packages: engines: {node: '>=0.11'} dev: false - /dayjs@1.11.13: - resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + /dayjs@1.11.18: + resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} requiresBuild: true dev: false optional: true @@ -6515,6 +6420,10 @@ packages: engines: {node: '>=6'} dev: true + /deep-equal@1.0.1: + resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -6569,6 +6478,11 @@ packages: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} dev: true + /depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: true + /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -6583,6 +6497,10 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + /desm@1.3.1: + resolution: {integrity: sha512-vgTAOosB1aHrmzjGnzFCbjvXbk8QAOC/36JxJhcBkeAuUy8QwRFxAWBHemiDpUB3cbrBruFUdzpUS21aocvaWg==} + dev: true + /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -6764,8 +6682,8 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: true - /effect@3.18.3: - resolution: {integrity: sha512-CmsQdMJdcBk+HigAtiNYb0Fp2xHtZmHjuCgYXDF74IGCCk+4EvQwQG4oHwG4XLFSqQ9eTIOIJ/+4FOYP05aBHg==} + /effect@3.18.4: + resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==} requiresBuild: true dependencies: '@standard-schema/spec': 1.0.0 @@ -6773,6 +6691,14 @@ packages: dev: false optional: true + /ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.9.2 + dev: true + /electron-to-chromium@1.4.745: resolution: {integrity: sha512-tRbzkaRI5gbUn5DEvF0dV4TQbMZ5CLkWeTAXmpC9IrYT+GE+x76i9p+o3RJ5l9XmdQlI1pPhVtE9uNcJJ0G0EA==} dev: true @@ -6805,8 +6731,8 @@ packages: engines: {node: '>= 0.8'} dev: true - /end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: once: 1.4.0 dev: true @@ -6992,14 +6918,14 @@ packages: - supports-color dev: true - /esbuild-runner@2.2.2(esbuild@0.25.10): + /esbuild-runner@2.2.2(esbuild@0.25.0): resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} hasBin: true requiresBuild: true peerDependencies: esbuild: '*' dependencies: - esbuild: 0.25.10 + esbuild: 0.25.0 source-map-support: 0.5.21 tslib: 2.4.0 dev: false @@ -7098,39 +7024,6 @@ packages: '@esbuild/win32-ia32': 0.25.0 '@esbuild/win32-x64': 0.25.0 - /esbuild@0.25.10: - resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} - engines: {node: '>=18'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.10 - '@esbuild/android-arm': 0.25.10 - '@esbuild/android-arm64': 0.25.10 - '@esbuild/android-x64': 0.25.10 - '@esbuild/darwin-arm64': 0.25.10 - '@esbuild/darwin-x64': 0.25.10 - '@esbuild/freebsd-arm64': 0.25.10 - '@esbuild/freebsd-x64': 0.25.10 - '@esbuild/linux-arm': 0.25.10 - '@esbuild/linux-arm64': 0.25.10 - '@esbuild/linux-ia32': 0.25.10 - '@esbuild/linux-loong64': 0.25.10 - '@esbuild/linux-mips64el': 0.25.10 - '@esbuild/linux-ppc64': 0.25.10 - '@esbuild/linux-riscv64': 0.25.10 - '@esbuild/linux-s390x': 0.25.10 - '@esbuild/linux-x64': 0.25.10 - '@esbuild/netbsd-arm64': 0.25.10 - '@esbuild/netbsd-x64': 0.25.10 - '@esbuild/openbsd-arm64': 0.25.10 - '@esbuild/openbsd-x64': 0.25.10 - '@esbuild/openharmony-arm64': 0.25.10 - '@esbuild/sunos-x64': 0.25.10 - '@esbuild/win32-arm64': 0.25.10 - '@esbuild/win32-ia32': 0.25.10 - '@esbuild/win32-x64': 0.25.10 - /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -7321,7 +7214,7 @@ packages: - ts-node dev: true - /eslint-plugin-vitest@0.2.8(eslint@8.47.0)(typescript@5.2.2)(vite@6.2.7)(vitest@3.1.1): + /eslint-plugin-vitest@0.2.8(eslint@8.47.0)(typescript@5.2.2)(vite@6.2.6)(vitest@3.1.1): resolution: {integrity: sha512-q8s4tStyKtn3gXf+8nf1ZYTHhoCXKdnozZzp6u8b4ni5v68Y4vxhNh4Z8njUfNjEY8HoPBB77MazHMR23IPb+g==} engines: {node: 14.x || >= 16} peerDependencies: @@ -7334,7 +7227,7 @@ packages: dependencies: '@typescript-eslint/utils': 6.4.1(eslint@8.47.0)(typescript@5.2.2) eslint: 8.47.0 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) vitest: 3.1.1(@types/node@18.15.3)(@vitest/ui@3.1.1)(jsdom@20.0.3) transitivePeerDependencies: - supports-color @@ -7560,6 +7453,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /eta@3.5.0: + resolution: {integrity: sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==} + engines: {node: '>=6.0.0'} + dev: true + /etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -7585,7 +7483,9 @@ packages: /events-universal@1.0.1: resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} dependencies: - bare-events: 2.7.0 + bare-events: 2.8.0 + transitivePeerDependencies: + - bare-abort-controller dev: true /events@3.3.0: @@ -7784,6 +7684,12 @@ packages: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} dev: true + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: true + /filesize@10.1.2: resolution: {integrity: sha512-Dx770ai81ohflojxhU+oG+Z2QGvKdYxgEr9OSA8UVrqhwNHjfH9A8f5NKfg83fEH8ZFA5N5llJo5T3PIoZ4CRA==} engines: {node: '>= 10.4.0'} @@ -8106,7 +8012,7 @@ packages: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 - minimatch: 9.0.3 + minimatch: 9.0.5 minipass: 7.0.2 path-scurry: 1.10.1 dev: true @@ -8532,6 +8438,11 @@ packages: engines: {node: '>=10.0.0'} dev: true + /helmet@8.1.0: + resolution: {integrity: sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==} + engines: {node: '>=18.0.0'} + dev: true + /highlight.js@11.11.1: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} @@ -8544,6 +8455,10 @@ packages: parse-passwd: 1.0.0 dev: true + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + /hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} @@ -8608,6 +8523,25 @@ packages: entities: 4.4.0 dev: true + /http-assert@1.5.0: + resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} + engines: {node: '>= 0.8'} + dependencies: + deep-equal: 1.0.1 + http-errors: 1.8.1 + dev: true + + /http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + dev: true + /http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -9133,6 +9067,17 @@ packages: '@pkgjs/parseargs': 0.11.0 dev: true + /jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + /jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -9652,6 +9597,10 @@ packages: dev: false optional: true + /jose@6.0.10: + resolution: {integrity: sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw==} + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -9727,12 +9676,22 @@ packages: hasBin: true dev: true + /jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + dev: true + /json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} dependencies: bignumber.js: 9.1.1 dev: false + /json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + dev: true + /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true @@ -9805,6 +9764,13 @@ packages: resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} dev: false + /keygrip@1.1.0: + resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} + engines: {node: '>= 0.6'} + dependencies: + tsscmp: 1.0.6 + dev: true + /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -9827,6 +9793,49 @@ packages: resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==} dev: true + /koa-compose@4.1.0: + resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} + dev: true + + /koa-convert@2.0.0: + resolution: {integrity: sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==} + engines: {node: '>= 10'} + dependencies: + co: 4.6.0 + koa-compose: 4.1.0 + dev: true + + /koa@2.16.1: + resolution: {integrity: sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==} + engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} + dependencies: + accepts: 1.3.8 + cache-content-type: 1.0.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookies: 0.9.1 + debug: 4.4.0 + delegates: 1.0.0 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + fresh: 0.5.2 + http-assert: 1.5.0 + http-errors: 1.8.1 + is-generator-function: 1.0.10 + koa-compose: 4.1.0 + koa-convert: 2.0.0 + on-finished: 2.4.1 + only: 0.0.2 + parseurl: 1.3.3 + statuses: 1.5.0 + type-is: 1.6.18 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + /leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -9848,8 +9857,8 @@ packages: type-check: 0.4.0 dev: true - /libphonenumber-js@1.12.9: - resolution: {integrity: sha512-VWwAdNeJgN7jFOD+wN4qx83DTPMVPPAUyx9/TUkBXKLiNkuWWk6anV0439tgdtwaJDrEdqkvdN22iA6J4bUCZg==} + /libphonenumber-js@1.12.24: + resolution: {integrity: sha512-l5IlyL9AONj4voSd7q9xkuQOL4u8Ty44puTic7J88CmdXkxfGsRfoVLXHCxppwehgpb/Chdb80FFehHqjN3ItQ==} requiresBuild: true dev: false optional: true @@ -9915,6 +9924,16 @@ packages: wrap-ansi: 7.0.0 dev: true + /load-json-file@4.0.0: + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} + engines: {node: '>=4'} + dependencies: + graceful-fs: 4.2.11 + parse-json: 4.0.0 + pify: 3.0.0 + strip-bom: 3.0.0 + dev: true + /loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} @@ -10273,6 +10292,11 @@ packages: map-or-similar: 1.5.0 dev: true + /memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + dev: true + /meow@10.1.5: resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -10773,6 +10797,13 @@ packages: brace-expansion: 1.1.11 dev: true + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimatch@8.0.4: resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} engines: {node: '>=16 || 14 >=14.17'} @@ -10780,8 +10811,8 @@ packages: brace-expansion: 2.0.1 dev: true - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + /minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 @@ -10853,6 +10884,11 @@ packages: hasBin: true dev: true + /mock-socket@9.1.5: + resolution: {integrity: sha512-3DeNIcsQixWHHKk6NdoBhWI4t1VMj5/HzfnI1rE/pLl5qKx7+gd4DNA07ehTaZ6MoUU053si6Hd+YtiM/tQZfg==} + engines: {node: '>= 8'} + dev: true + /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -10895,9 +10931,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + /nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} hasBin: true dev: true @@ -10914,6 +10950,10 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: true + /nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + dev: true + /no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: @@ -10983,6 +11023,15 @@ packages: abbrev: 1.1.1 dev: true + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.1 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + /normalize-package-data@3.0.3: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} @@ -11008,13 +11057,29 @@ packages: engines: {node: '>=10'} dev: true - /normalize-url@8.0.2: - resolution: {integrity: sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==} + /normalize-url@8.1.0: + resolution: {integrity: sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==} engines: {node: '>=14.16'} requiresBuild: true dev: false optional: true + /npm-run-all@4.1.5: + resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} + engines: {node: '>= 4'} + hasBin: true + dependencies: + ansi-styles: 3.2.1 + chalk: 2.4.2 + cross-spawn: 6.0.5 + memorystream: 0.3.1 + minimatch: 3.1.2 + pidtree: 0.3.1 + read-pkg: 3.0.0 + shell-quote: 1.7.4 + string.prototype.padend: 3.1.4 + dev: true + /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -11145,6 +11210,29 @@ packages: es-abstract: 1.21.1 dev: true + /oidc-provider@9.0.1: + resolution: {integrity: sha512-pTWYdAlx1XemIrWtmjeSxHD8IC/BNtUGhOE9HYEn4R/OvQeAsaDLMJE33RSdd6nWwkW3btVZ9FXD+Tza5sezkw==} + dependencies: + '@koa/cors': 5.0.0 + '@koa/router': 13.1.0 + debug: 4.4.0 + eta: 3.5.0 + jose: 6.0.10 + jsesc: 3.1.0 + koa: 2.16.1 + nanoid: 5.1.5 + oidc-token-hash: 5.1.0 + quick-lru: 7.0.1 + raw-body: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /oidc-token-hash@5.1.0: + resolution: {integrity: sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==} + engines: {node: ^10.13.0 || >=12.0.0} + dev: true + /on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -11172,6 +11260,10 @@ packages: mimic-fn: 4.0.0 dev: true + /only@0.0.2: + resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} + dev: true + /open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -11274,6 +11366,14 @@ packages: callsites: 3.1.0 dev: true + /parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + dev: true + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -11319,6 +11419,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: true + /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -11345,6 +11450,17 @@ packages: resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} dev: true + /path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + dev: true + + /path-type@3.0.0: + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} + dependencies: + pify: 3.0.0 + dev: true + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -11386,6 +11502,12 @@ packages: engines: {node: '>=12'} dev: true + /pidtree@0.3.1: + resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + /pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} @@ -11397,6 +11519,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + dev: true + /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -11421,8 +11548,8 @@ packages: hasBin: true dev: true - /playwright-core@1.56.0: - resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==} + /playwright-core@1.51.1: + resolution: {integrity: sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==} engines: {node: '>=18'} hasBin: true dev: true @@ -11447,12 +11574,12 @@ packages: fsevents: 2.3.2 dev: true - /playwright@1.56.0: - resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==} + /playwright@1.51.1: + resolution: {integrity: sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==} engines: {node: '>=18'} hasBin: true dependencies: - playwright-core: 1.56.0 + playwright-core: 1.51.1 optionalDependencies: fsevents: 2.3.2 dev: true @@ -11941,7 +12068,7 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 picocolors: 1.0.0 source-map-js: 1.0.2 dev: true @@ -12128,6 +12255,25 @@ packages: long: 5.2.3 dev: true + /protobufjs@7.5.4: + resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + engines: {node: '>=12.0.0'} + requiresBuild: true + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 18.15.3 + long: 5.2.3 + dev: true + /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -12152,10 +12298,10 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true - /pump@3.0.3: - resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} dependencies: - end-of-stream: 1.4.5 + end-of-stream: 1.4.4 once: 1.4.0 dev: true @@ -12194,6 +12340,11 @@ packages: engines: {node: '>=10'} dev: true + /quick-lru@7.0.1: + resolution: {integrity: sha512-kLjThirJMkWKutUKbZ8ViqFc09tDQhlbQo2MNuVeLWbRauqYP96Sm6nzlQ24F0HFjUNZ4i9+AgldJ9H6DZXi7g==} + engines: {node: '>=18'} + dev: true + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -12215,6 +12366,16 @@ packages: unpipe: 1.0.0 dev: true + /raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + dev: true + /react-confetti@6.1.0(react@18.2.0): resolution: {integrity: sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==} engines: {node: '>=10.18'} @@ -12265,6 +12426,15 @@ packages: type-fest: 1.4.0 dev: true + /read-pkg@3.0.0: + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} + engines: {node: '>=4'} + dependencies: + load-json-file: 4.0.0 + normalize-package-data: 2.5.0 + path-type: 3.0.0 + dev: true + /read-pkg@6.0.0: resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} engines: {node: '>=12'} @@ -12328,7 +12498,6 @@ packages: /regenerator-runtime@0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} - requiresBuild: true /regexp.prototype.flags@1.4.3: resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} @@ -12559,33 +12728,33 @@ packages: glob: 9.3.5 dev: true - /rollup@4.40.1: - resolution: {integrity: sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==} + /rollup@4.39.0: + resolution: {integrity: sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.7 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.1 - '@rollup/rollup-android-arm64': 4.40.1 - '@rollup/rollup-darwin-arm64': 4.40.1 - '@rollup/rollup-darwin-x64': 4.40.1 - '@rollup/rollup-freebsd-arm64': 4.40.1 - '@rollup/rollup-freebsd-x64': 4.40.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.1 - '@rollup/rollup-linux-arm-musleabihf': 4.40.1 - '@rollup/rollup-linux-arm64-gnu': 4.40.1 - '@rollup/rollup-linux-arm64-musl': 4.40.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.1 - '@rollup/rollup-linux-riscv64-gnu': 4.40.1 - '@rollup/rollup-linux-riscv64-musl': 4.40.1 - '@rollup/rollup-linux-s390x-gnu': 4.40.1 - '@rollup/rollup-linux-x64-gnu': 4.40.1 - '@rollup/rollup-linux-x64-musl': 4.40.1 - '@rollup/rollup-win32-arm64-msvc': 4.40.1 - '@rollup/rollup-win32-ia32-msvc': 4.40.1 - '@rollup/rollup-win32-x64-msvc': 4.40.1 + '@rollup/rollup-android-arm-eabi': 4.39.0 + '@rollup/rollup-android-arm64': 4.39.0 + '@rollup/rollup-darwin-arm64': 4.39.0 + '@rollup/rollup-darwin-x64': 4.39.0 + '@rollup/rollup-freebsd-arm64': 4.39.0 + '@rollup/rollup-freebsd-x64': 4.39.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.39.0 + '@rollup/rollup-linux-arm-musleabihf': 4.39.0 + '@rollup/rollup-linux-arm64-gnu': 4.39.0 + '@rollup/rollup-linux-arm64-musl': 4.39.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.39.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.39.0 + '@rollup/rollup-linux-riscv64-gnu': 4.39.0 + '@rollup/rollup-linux-riscv64-musl': 4.39.0 + '@rollup/rollup-linux-s390x-gnu': 4.39.0 + '@rollup/rollup-linux-x64-gnu': 4.39.0 + '@rollup/rollup-linux-x64-musl': 4.39.0 + '@rollup/rollup-win32-arm64-msvc': 4.39.0 + '@rollup/rollup-win32-ia32-msvc': 4.39.0 + '@rollup/rollup-win32-x64-msvc': 4.39.0 fsevents: 2.3.3 /run-parallel@1.2.0: @@ -12663,6 +12832,11 @@ packages: ajv-keywords: 3.5.2(ajv@6.12.6) dev: true + /semver@5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + /semver@6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true @@ -12769,6 +12943,13 @@ packages: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: true + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -12776,11 +12957,20 @@ packages: shebang-regex: 3.0.0 dev: true + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} dev: true + /shell-quote@1.7.4: + resolution: {integrity: sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==} + dev: true + /side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} @@ -12884,7 +13074,7 @@ packages: dependencies: iconv-lite: 0.6.3 source-map-js: 1.2.1 - webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.10) + webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.0) dev: true /source-map-support@0.5.13: @@ -12983,6 +13173,11 @@ packages: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} dev: true + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: true + /statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -13022,6 +13217,7 @@ packages: fast-fifo: 1.3.2 text-decoder: 1.2.3 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a dev: true @@ -13064,6 +13260,15 @@ packages: strip-ansi: 7.0.1 dev: true + /string.prototype.padend@3.1.4: + resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + /string.prototype.trim@1.2.7: resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} engines: {node: '>= 0.4'} @@ -13516,33 +13721,33 @@ packages: - supports-color dev: true - /sveltekit-superforms@2.27.1(@sveltejs/kit@2.36.1)(esbuild@0.25.10)(svelte@5.25.5)(typescript@5.2.2): - resolution: {integrity: sha512-cvq2AevkZ0Zrk0w0gNM3kjcnJMtJ0jzu+2zqDoM9a+lZa+8bGpNl4YqxVkemiJNkGnFgNC8xr5xF5BlMzjookQ==} + /sveltekit-superforms@2.28.0(@sveltejs/kit@2.47.2)(esbuild@0.25.0)(svelte@5.25.5)(typescript@5.2.2): + resolution: {integrity: sha512-kHoROSmf5bzK9r261z2op5OPF5tRhxqQQOQc8dS6CatKAUDr3o94Fjjv7AwjD9i4FplyXI+OyTo6hGOXQ3qCKQ==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 dependencies: - '@sveltejs/kit': 2.36.1(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.7) + '@sveltejs/kit': 2.47.2(@sveltejs/vite-plugin-svelte@5.0.3)(svelte@5.25.5)(vite@6.2.6) devalue: 5.3.2 memoize-weak: 1.0.2 svelte: 5.25.5 ts-deepmerge: 7.0.3 optionalDependencies: '@exodus/schemasafe': 1.3.0 - '@gcornut/valibot-json-schema': 0.42.0(esbuild@0.25.10)(typescript@5.2.2) - '@sinclair/typebox': 0.34.41 + '@finom/zod-to-json-schema': 3.24.11(zod@4.1.12) + '@gcornut/valibot-json-schema': 0.42.0(esbuild@0.25.0)(typescript@5.2.2) '@typeschema/class-validator': 0.3.0(class-validator@0.14.2) '@vinejs/vine': 3.0.1 - arktype: 2.1.22 + arktype: 2.1.23 class-validator: 0.14.2 - effect: 3.18.3 + effect: 3.18.4 joi: 17.13.3 json-schema-to-ts: 3.1.1 superstruct: 2.0.2 + typebox: 1.0.41 valibot: 1.1.0(typescript@5.2.2) yup: 1.7.1 - zod: 3.25.67 - zod-to-json-schema: 3.24.6(zod@3.25.67) + zod: 4.1.12 transitivePeerDependencies: - '@types/json-schema' - esbuild @@ -13574,7 +13779,7 @@ packages: webpack: '>=2' dependencies: '@swc/core': 1.10.7 - webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.10) + webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.0) dev: true /symbol-tree@3.2.4: @@ -13635,12 +13840,13 @@ packages: /tar-fs@3.1.1: resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} dependencies: - pump: 3.0.3 + pump: 3.0.0 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 4.4.5 + bare-fs: 4.4.11 bare-path: 3.0.0 transitivePeerDependencies: + - bare-abort-controller - bare-buffer - react-native-b4a dev: true @@ -13652,6 +13858,7 @@ packages: fast-fifo: 1.3.2 streamx: 2.23.0 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a dev: true @@ -13667,7 +13874,7 @@ packages: yallist: 4.0.0 dev: true - /terser-webpack-plugin@5.3.10(@swc/core@1.10.7)(esbuild@0.25.10)(webpack@5.94.0): + /terser-webpack-plugin@5.3.10(@swc/core@1.10.7)(esbuild@0.25.0)(webpack@5.94.0): resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -13685,12 +13892,12 @@ packages: dependencies: '@jridgewell/trace-mapping': 0.3.25 '@swc/core': 1.10.7 - esbuild: 0.25.10 + esbuild: 0.25.0 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.28.1 - webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.10) + webpack: 5.94.0(@swc/core@1.10.7)(esbuild@0.25.0) dev: true /terser@5.28.1: @@ -13916,6 +14123,11 @@ packages: /tslib@2.5.0: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + /tsscmp@1.0.6: + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} + dev: true + /tsutils@3.21.0(typescript@5.2.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -13992,6 +14204,12 @@ packages: mime-types: 2.1.35 dev: true + /typebox@1.0.41: + resolution: {integrity: sha512-ArVs9pvOH3AKItL/DARnb7rG6fuv6dk7y7A42F5J+RmbZ1AE0b4gZ6o0HgLQXj5xidT761UfbJmhrSxR/+7gmA==} + requiresBuild: true + dev: false + optional: true + /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} @@ -14348,7 +14566,7 @@ packages: debug: 4.4.0 es-module-lexer: 1.6.0 pathe: 2.0.3 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) transitivePeerDependencies: - '@types/node' - jiti @@ -14364,8 +14582,8 @@ packages: - yaml dev: true - /vite@6.2.7(@types/node@18.15.3): - resolution: {integrity: sha512-qg3LkeuinTrZoJHHF94coSaTfIPyBYoywp+ys4qu20oSJFbKMYoIJo0FWJT9q6Vp49l6z9IsJRbHdcGtiKbGoQ==} + /vite@6.2.6(@types/node@18.15.3): + resolution: {integrity: sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -14407,11 +14625,11 @@ packages: '@types/node': 18.15.3 esbuild: 0.25.0 postcss: 8.5.3 - rollup: 4.40.1 + rollup: 4.39.0 optionalDependencies: fsevents: 2.3.3 - /vitefu@1.0.6(vite@6.2.7): + /vitefu@1.0.6(vite@6.2.6): resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 @@ -14419,7 +14637,7 @@ packages: vite: optional: true dependencies: - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) /vitest-localstorage-mock@0.1.2(vitest@3.1.1): resolution: {integrity: sha512-1oee6iDWhhquzVogssbpwQi6a2F3L+nCKF2+qqyCs5tH0sOYRyTqnsfj2dtmEQiL4xtJkHLn42hEjHGESlsJHw==} @@ -14459,7 +14677,7 @@ packages: dependencies: '@types/node': 18.15.3 '@vitest/expect': 3.1.1 - '@vitest/mocker': 3.1.1(vite@6.2.7) + '@vitest/mocker': 3.1.1(vite@6.2.6) '@vitest/pretty-format': 3.1.1 '@vitest/runner': 3.1.1 '@vitest/snapshot': 3.1.1 @@ -14477,7 +14695,7 @@ packages: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.2.7(@types/node@18.15.3) + vite: 6.2.6(@types/node@18.15.3) vite-node: 3.1.1(@types/node@18.15.3) why-is-node-running: 2.3.0 transitivePeerDependencies: @@ -14584,7 +14802,7 @@ packages: resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} dev: true - /webpack@5.94.0(@swc/core@1.10.7)(esbuild@0.25.10): + /webpack@5.94.0(@swc/core@1.10.7)(esbuild@0.25.0): resolution: {integrity: sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==} engines: {node: '>=10.13.0'} hasBin: true @@ -14614,7 +14832,7 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.10.7)(esbuild@0.25.10)(webpack@5.94.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.10.7)(esbuild@0.25.0)(webpack@5.94.0) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -14898,6 +15116,11 @@ packages: yargs-parser: 21.1.1 dev: true + /ylru@1.4.0: + resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==} + engines: {node: '>= 4.0.0'} + dev: true + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -14917,19 +15140,15 @@ packages: /zimmerframe@1.1.2: resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - /zod-to-json-schema@3.24.6(zod@3.25.67): - resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==} - requiresBuild: true - peerDependencies: - zod: ^3.24.1 - dependencies: - zod: 3.25.67 + /zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} dev: false - optional: true - /zod@3.25.67: - resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + /zod@4.1.12: + resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + requiresBuild: true dev: false + optional: true /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} diff --git a/scripts/start-oidc-server.ts b/scripts/start-oidc-server.ts new file mode 100644 index 0000000000..fa66889e63 --- /dev/null +++ b/scripts/start-oidc-server.ts @@ -0,0 +1,28 @@ +import { + Account, + getConfig, + OIDCServer, + providerConfiguration, + routes, +} from '../utilities/oidc-server'; + +const { PORT, ISSUER, VIEWS_PATH } = getConfig(); + +const server = new OIDCServer({ + issuer: ISSUER, + port: PORT, + viewsPath: VIEWS_PATH, + providerConfiguration, + accountModel: Account, + routes, +}); + +server.start().catch(async (error) => { + console.error(error); + server.stop(); + process.exit(1); +}); + +process.on('beforeExit', () => { + if (server) server.stop(); +}); diff --git a/server/config/with-auth.yaml b/server/config/with-auth.yaml new file mode 100644 index 0000000000..a35c01f7eb --- /dev/null +++ b/server/config/with-auth.yaml @@ -0,0 +1,58 @@ +publicPath: +port: 8081 +enableUi: true +bannerText: +cors: + cookieInsecure: false + allowOrigins: + - http://localhost:3000 # used at development by https://github.com/temporalio/ui +refreshInterval: 1m +defaultNamespace: default +showTemporalSystemNamespace: false +feedbackUrl: +notifyOnNewVersion: true +disableWriteActions: false +workflowTerminateDisabled: false +workflowCancelDisabled: false +workflowSignalDisabled: false +workflowUpdateDisabled: false +workflowResetDisabled: false +batchActionsDisabled: false +startWorkflowDisabled: false +hideWorkflowQueryErrors: false +refreshWorkflowCountsDisabled: false +auth: + enabled: true + providers: + - label: Dummy OIDC + type: oidc # for futureproofing; only oidc is supported today + providerUrl: http://localhost:8889 + issuerUrl: "" # needed if the Issuer Url and the Provider Url are different + clientId: temporal-ui + clientSecret: temporal-secret + scopes: + - openid + - profile + - email + - offline_access + callbackUrl: http://localhost:8081/auth/sso/callback + options: # added as URL query params when redirecting to auth provider + audience: myorg-dev + organization: org_xxxxxxxxxxxx + invitation: +tls: + caFile: + certFile: + keyFile: + caData: + certData: + keyData: + enableHostVerification: false + serverName: +codec: + endpoint: + passAccessToken: false + includeCredentials: false +forwardHeaders: # can be used to pass additional HTTP headers from HTTP requests to Temporal gRPC backend + - X-Forwarded-For + diff --git a/server/go.mod b/server/go.mod index be9f002afb..a78b78ae5e 100644 --- a/server/go.mod +++ b/server/go.mod @@ -5,6 +5,7 @@ go 1.23.0 require ( github.com/Masterminds/sprig/v3 v3.3.0 github.com/coreos/go-oidc/v3 v3.11.0 + github.com/golang-jwt/jwt/v5 v5.3.0 github.com/gomarkdown/markdown v0.0.0-20240729212818-a2a9c4f76ef5 github.com/gorilla/securecookie v1.1.1 github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 diff --git a/server/go.sum b/server/go.sum index 875a544786..19ef8bbaa8 100644 --- a/server/go.sum +++ b/server/go.sum @@ -18,6 +18,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/gomarkdown/markdown v0.0.0-20240729212818-a2a9c4f76ef5 h1:8QWUW69MXlNdZXnDnD9vEQ1BL8/mm1FTiSesKKHYivk= github.com/gomarkdown/markdown v0.0.0-20240729212818-a2a9c4f76ef5/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= diff --git a/server/server/auth/auth.go b/server/server/auth/auth.go index e4eba31493..6cb15c6079 100644 --- a/server/server/auth/auth.go +++ b/server/server/auth/auth.go @@ -28,11 +28,15 @@ import ( "encoding/base64" "encoding/json" "errors" + "fmt" + "log" "net/http" "strconv" + "strings" "time" "unicode/utf8" + "github.com/golang-jwt/jwt/v5" "github.com/labstack/echo/v4" "github.com/temporalio/ui-server/v2/server/config" ) @@ -82,6 +86,61 @@ func SetUser(c echo.Context, user *User) error { c.SetCookie(cookie) } + if rt := user.OAuth2Token.RefreshToken; rt != "" { + log.Printf("[Auth] Setting refresh token cookie (length: %d)", len(rt)) + refreshCookie := &http.Cookie{ + Name: "refresh", + Value: rt, + MaxAge: int((30 * 24 * time.Hour).Seconds()), + Secure: c.Request().TLS != nil, + HttpOnly: true, + Path: "/", + SameSite: http.SameSiteStrictMode, + } + c.SetCookie(refreshCookie) + } else { + log.Println("[Auth] No refresh token received from OAuth provider") + } + + return nil +} + +func validateJWTExpiration(tokenString string) error { + tokenString = strings.TrimPrefix(tokenString, "Bearer ") + + if tokenString == "" { + log.Println("[JWT Validation] Token is empty, skipping validation") + return nil + } + + parser := jwt.NewParser(jwt.WithoutClaimsValidation()) + token, _, err := parser.ParseUnverified(tokenString, jwt.MapClaims{}) + if err != nil { + log.Printf("[JWT Validation] Failed to parse JWT: %v, skipping validation", err) + return nil + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + log.Println("[JWT Validation] Failed to extract claims, skipping validation") + return nil + } + + exp, ok := claims["exp"].(float64) + if !ok { + log.Println("[JWT Validation] No exp claim found, skipping validation") + return nil + } + + expirationTime := time.Unix(int64(exp), 0) + now := time.Now() + + if now.After(expirationTime) { + log.Printf("[JWT Validation] Token expired at %v (current time: %v)", expirationTime, now) + return errors.New("token expired") + } + + log.Printf("[JWT Validation] Token valid, expires at %v (time remaining: %v)", expirationTime, expirationTime.Sub(now)) return nil } @@ -104,9 +163,23 @@ func ValidateAuthHeaderExists(c echo.Context, cfgProvider *config.ConfigProvider return echo.NewHTTPError(http.StatusUnauthorized, "unauthorized") } + // The Authorization-Extras header contains the ID token (JWT) that we should validate + // The Authorization header contains the access token (opaque string) + idToken := c.Request().Header.Get(AuthorizationExtrasHeader) + if idToken != "" { + log.Println("[Auth] Validating ID token from Authorization-Extras header") + if err := validateJWTExpiration(idToken); err != nil { + return echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("invalid ID token: %v", err)) + } + } else { + log.Println("[Auth] No Authorization-Extras header, validating Authorization header") + if err := validateJWTExpiration(token); err != nil { + return echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("invalid token: %v", err)) + } + } + // Handle token swapping for OIDC providers that require ID token as Bearer if len(cfg.Auth.Providers) > 0 && cfg.Auth.Providers[0].UseIDTokenAsBearer { - idToken := c.Request().Header.Get(AuthorizationExtrasHeader) if idToken != "" { // Replace the Authorization header with ID token c.Request().Header.Set(echo.HeaderAuthorization, "Bearer "+idToken) diff --git a/server/server/auth/auth_test.go b/server/server/auth/auth_test.go index 5e45e3482b..f83c08039a 100644 --- a/server/server/auth/auth_test.go +++ b/server/server/auth/auth_test.go @@ -113,13 +113,13 @@ func TestSetUser(t *testing.T) { func TestValidateAuthHeaderExists(t *testing.T) { tests := []struct { - name string - authEnabled bool - useIDTokenAsBearer bool - authHeader string - authExtrasHeader string - expectedAuthHeader string - expectedError bool + name string + authEnabled bool + useIDTokenAsBearer bool + authHeader string + authExtrasHeader string + expectedAuthHeader string + expectedError bool }{ { name: "auth disabled - no validation", diff --git a/server/server/cors/cors.go b/server/server/cors/cors.go index bb9df7abb3..2b570559bc 100644 --- a/server/server/cors/cors.go +++ b/server/server/cors/cors.go @@ -64,7 +64,7 @@ func CORSMiddleware(config CORSConfig) echo.MiddlewareFunc { // handleStaticCORS handles standard CORS with predefined allowed origins func handleStaticCORS(c echo.Context, next echo.HandlerFunc, allowOrigins []string, config CORSConfig) error { origin := c.Request().Header.Get("Origin") - + // Check if origin is in allowed list allowed := false for _, allowedOrigin := range allowOrigins { @@ -89,7 +89,7 @@ func handleStaticCORS(c echo.Context, next echo.HandlerFunc, allowOrigins []stri // handleDynamicCORS handles unsafe allow all origins by using the request origin func handleDynamicCORS(c echo.Context, next echo.HandlerFunc, config CORSConfig) error { origin := c.Request().Header.Get("Origin") - + // Only set CORS headers if origin is present if origin != "" { setCORSHeaders(c, origin, config) @@ -106,14 +106,14 @@ func handleDynamicCORS(c echo.Context, next echo.HandlerFunc, config CORSConfig) // setCORSHeaders sets the appropriate CORS headers func setCORSHeaders(c echo.Context, origin string, config CORSConfig) { c.Response().Header().Set("Access-Control-Allow-Origin", origin) - + if config.AllowCredentials { c.Response().Header().Set("Access-Control-Allow-Credentials", "true") } - + if len(config.AllowHeaders) > 0 { c.Response().Header().Set("Access-Control-Allow-Headers", strings.Join(config.AllowHeaders, ", ")) } - + c.Response().Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") -} \ No newline at end of file +} diff --git a/server/server/cors/cors_test.go b/server/server/cors/cors_test.go index ac77e9a609..917927df65 100644 --- a/server/server/cors/cors_test.go +++ b/server/server/cors/cors_test.go @@ -159,4 +159,4 @@ func TestCORSMiddleware_PreflightRequest(t *testing.T) { assert.NoError(t, err) assert.Equal(t, http.StatusNoContent, rec.Code) assert.Equal(t, "https://example.com", rec.Header().Get("Access-Control-Allow-Origin")) -} \ No newline at end of file +} diff --git a/server/server/route/auth.go b/server/server/route/auth.go index 21cab99728..897458940d 100644 --- a/server/server/route/auth.go +++ b/server/server/route/auth.go @@ -29,7 +29,6 @@ import ( "fmt" "log" "net/http" - "net/url" "time" "github.com/coreos/go-oidc/v3/oidc" @@ -79,6 +78,7 @@ func SetAuthRoutes(e *echo.Echo, cfgProvider *config.ConfigProviderWithRefresh) api.GET("/sso", authenticate(&oauthCfg, providerCfg.Options)) api.GET("/sso/callback", authenticateCb(ctx, &oauthCfg, provider)) api.GET("/sso_callback", authenticateCb(ctx, &oauthCfg, provider)) // compatibility with UI v1 + api.GET("/refresh", refreshTokens(ctx, &oauthCfg, provider)) } func authenticate(config *oauth2.Config, options map[string]interface{}) func(echo.Context) error { @@ -149,6 +149,51 @@ func authenticateCb(ctx context.Context, oauthCfg *oauth2.Config, provider *oidc } } +// refreshTokens exchanges a refresh token (stored in an HttpOnly cookie) for a new access token +// and optionally a new ID token. It resets the cookies using auth.SetUser and returns 200. +func refreshTokens(ctx context.Context, oauthCfg *oauth2.Config, provider *oidc.Provider) func(echo.Context) error { + return func(c echo.Context) error { + // Read refresh cookie + refreshCookie, err := c.Request().Cookie("refresh") + if err != nil || refreshCookie.Value == "" { + return echo.NewHTTPError(http.StatusUnauthorized, "missing refresh token") + } + + // Use the refresh token to obtain a new token set + ts := oauthCfg.TokenSource(ctx, &oauth2.Token{RefreshToken: refreshCookie.Value}) + newTok, err := ts.Token() + if err != nil { + return echo.NewHTTPError(http.StatusUnauthorized, "unable to refresh token: "+err.Error()) + } + + var user auth.User + user.OAuth2Token = newTok + + // Try to capture a new ID token if provided and verify it + if raw, ok := newTok.Extra("id_token").(string); ok && raw != "" { + oidcConfig := &oidc.Config{ClientID: oauthCfg.ClientID} + verifier := provider.Verifier(oidcConfig) + idTok, verr := verifier.Verify(ctx, raw) + if verr == nil { + var claims auth.Claims + // If claims fail, we still proceed with tokens + _ = idTok.Claims(&claims) + user.IDToken = &auth.IDToken{RawToken: raw, Claims: &claims} + } else { + // If verification fails, do not include ID token + user.IDToken = nil + } + } + + if err := auth.SetUser(c, &user); err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "unable to set refreshed user: "+err.Error()) + } + + // Respond OK. UI can read the short-lived 'user*' cookie to pick up tokens. + return c.NoContent(http.StatusOK) + } +} + func setCallbackCookie(c echo.Context, name, value string) { // Explicitly expire pre v2.8.0 state and nonce cookies. // As they had different path, they were not being cleared and in some cases result in "state did not match" error. @@ -189,15 +234,15 @@ func randNonce(c echo.Context) (string, error) { } returnURL := c.QueryParam("returnUrl") - u, err := url.Parse(returnURL) - if err != nil { - return "", fmt.Errorf("invalid returnUrl: %w", err) - } + // u, err := url.Parse(returnURL) + // if err != nil { + // return "", fmt.Errorf("invalid returnUrl: %w", err) + // } // Reject redirects to other hosts, our use case only needs to handle local redirects. - if u.Host != "" && u.Host != c.Request().Host { - return "", fmt.Errorf("invalid returnUrl: does not match expected host %s", c.Request().Host) - } + // if u.Host != "" && u.Host != c.Request().Host { + // return "", fmt.Errorf("invalid returnUrl: does not match expected host %s", c.Request().Host) + // } n := &Nonce{ Nonce: v, diff --git a/server/server/route/ui.go b/server/server/route/ui.go index c26fe19950..f1be81979c 100644 --- a/server/server/route/ui.go +++ b/server/server/route/ui.go @@ -353,7 +353,6 @@ body[data-theme='dark-primary'] { color: #8098f9; } `, - } // Set headers diff --git a/server/server/rpc/tls_cert_loader_test.go b/server/server/rpc/tls_cert_loader_test.go index 472d8daa72..0712a86357 100644 --- a/server/server/rpc/tls_cert_loader_test.go +++ b/server/server/rpc/tls_cert_loader_test.go @@ -90,4 +90,3 @@ func generateCertKeyPair(t *testing.T, commonName string) (certPEM, keyPEM []byt keyPEM = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) return certPEM, keyPEM } - diff --git a/src/lib/utilities/auth-refresh.ts b/src/lib/utilities/auth-refresh.ts new file mode 100644 index 0000000000..37034a27d7 --- /dev/null +++ b/src/lib/utilities/auth-refresh.ts @@ -0,0 +1,52 @@ +import { BROWSER } from 'esm-env'; + +import { setAuthUser } from '$lib/stores/auth-user'; +import { + cleanAuthUserCookie, + getAuthUserCookie, +} from '$lib/utilities/auth-user-cookie'; +import { getApiOrigin } from '$lib/utilities/get-api-origin'; + +let refreshPromise: Promise | null = null; + +export const refreshTokens = async (): Promise => { + if (!BROWSER) return false; + + if (refreshPromise) { + return refreshPromise; + } + + refreshPromise = (async () => { + try { + const res = await fetch(`${getApiOrigin()}/auth/refresh`, { + method: 'GET', + credentials: 'include', + }); + + if (!res.ok) { + console.warn( + `[Auth] Token refresh failed with status ${res.status}: ${res.statusText}`, + ); + return false; + } + + const user = getAuthUserCookie(true); + if (user?.accessToken) { + setAuthUser(user); + cleanAuthUserCookie(true); + console.info('[Auth] Token refresh successful'); + return true; + } + + console.warn('[Auth] Token refresh returned no access token'); + return false; + } catch (error) { + console.error('[Auth] Token refresh network error:', error); + return false; + } finally { + refreshPromise = null; + } + })(); + + return refreshPromise; +}; diff --git a/src/lib/utilities/handle-error.ts b/src/lib/utilities/handle-error.ts index f108d7ad13..0d07f08ac9 100644 --- a/src/lib/utilities/handle-error.ts +++ b/src/lib/utilities/handle-error.ts @@ -7,7 +7,7 @@ import type { NetworkError } from '$lib/types/global'; import { has } from './has'; import { isNetworkError } from './is-network-error'; import type { APIErrorResponse, TemporalAPIError } from './request-from-api'; -import { routeForLoginPage } from './route-for'; +import { routeForSsoRedirect } from './route-for'; interface NetworkErrorWithReport extends NetworkError { report?: boolean; @@ -34,11 +34,11 @@ export const handleError = ( } if (isUnauthorized(error) && isBrowser) { - window.location.assign(routeForLoginPage(error?.message)); + window.location.assign(routeForSsoRedirect()); } if (isForbidden(error) && isBrowser) { - window.location.assign(routeForLoginPage(error?.message)); + window.location.assign(routeForSsoRedirect()); } if (isNetworkError(error)) { @@ -57,15 +57,13 @@ export const handleUnauthorizedOrForbiddenError = ( error: APIErrorResponse, isBrowser = BROWSER, ): void => { - const msg = `${error?.status} ${error?.body?.message}`; - if (isUnauthorized(error) && isBrowser) { - window.location.assign(routeForLoginPage(msg)); + window.location.assign(routeForSsoRedirect()); return; } if (isForbidden(error) && isBrowser) { - window.location.assign(routeForLoginPage(msg)); + window.location.assign(routeForSsoRedirect()); return; } }; diff --git a/src/lib/utilities/request-from-api.ts b/src/lib/utilities/request-from-api.ts index 6831453858..f882d86ce4 100644 --- a/src/lib/utilities/request-from-api.ts +++ b/src/lib/utilities/request-from-api.ts @@ -3,6 +3,7 @@ import { BROWSER } from 'esm-env'; import { getAuthUser } from '$lib/stores/auth-user'; import type { NetworkError } from '$lib/types/global'; +import { refreshTokens } from './auth-refresh'; import { handleError as handleRequestError } from './handle-error'; import { isFunction } from './is-function'; import { toURL } from './to-url'; @@ -93,15 +94,36 @@ export const requestFromAPI = async ( const queryIsTooLong = [...query.values()].some( (value) => value.length > MAX_QUERY_LENGTH, ); - const response = queryIsTooLong - ? new Response(JSON.stringify({ message: 'Query string is too long' }), { - status: 414, - statusText: 'URI Too Long', - }) - : await request(url, options); - const body = await response.json(); - const { status, statusText } = response; + const makeRequest = async () => + queryIsTooLong + ? new Response( + JSON.stringify({ message: 'Query string is too long' }), + { + status: 414, + statusText: 'URI Too Long', + }, + ) + : await request(url, options); + + let response = await makeRequest(); + let { status, statusText } = response; + + if (isBrowser && status === 401) { + const refreshed = await refreshTokens(); + if (refreshed) { + options = withSecurityOptions(init.options, isBrowser); + if (!endpoint.endsWith('api/v1/settings')) { + options = await withAuth(options, isBrowser); + } + response = await makeRequest(); + status = response.status; + statusText = response.statusText; + } + // If refresh failed, let the error flow to handleError() which will redirect to login + } + + const body = await response.json(); if (!response.ok) { if (onError && isFunction(onError)) { diff --git a/src/lib/utilities/route-for.ts b/src/lib/utilities/route-for.ts index 195b834359..8b9fe3d9d4 100644 --- a/src/lib/utilities/route-for.ts +++ b/src/lib/utilities/route-for.ts @@ -5,6 +5,7 @@ import { base } from '$app/paths'; import type { EventView } from '$lib/types/events'; import type { Settings } from '$lib/types/global'; import { encodeURIForSvelte } from '$lib/utilities/encode-uri'; +import { getApiOrigin } from '$lib/utilities/get-api-origin'; import { toURL } from '$lib/utilities/to-url'; type RouteParameters = { @@ -317,6 +318,14 @@ export const routeForLoginPage = (error = '', isBrowser = BROWSER): string => { return `${base}/login`; }; +export const routeForSsoRedirect = (isBrowser = BROWSER): string => { + const url = new URL(`${getApiOrigin()}/auth/sso`); + if (isBrowser) { + url.searchParams.set('returnUrl', window.location.href); + } + return url.toString(); +}; + export const routeForEventHistoryImport = ( namespace?: string, view?: EventView, diff --git a/utilities/oidc-server/README.md b/utilities/oidc-server/README.md new file mode 100644 index 0000000000..16314b9220 --- /dev/null +++ b/utilities/oidc-server/README.md @@ -0,0 +1,35 @@ +# OIDC Server + +This is a standalone Express-based OpenID Connect (OIDC) server built with `oidc-provider`. + +## Configuration + +- Default port: `8889` (override with `PORT` environment variable) +- Issuer URL: `http://localhost:` (override with `ISSUER` environment variable) + +## Running the Server + +Install dependencies (from project root if using monorepo): +```bash +npm install +``` + +Start the server: +```bash +PORT=8889 node index.js +``` + +Once running, visit `http://localhost:8889/.well-known/openid-configuration` to inspect the provider configuration. +Once running, visit `http://localhost:8889/.well-known/openid-configuration` to inspect the provider configuration. + +## Views and Routes + +Custom EJS views are located in the `views/` directory. Express routes for OIDC interactions are defined in `routes/express.js`. + +## Testing + +Verify the server boots and shuts down cleanly by running: +```bash +cd utilities/oidc-server +ts-node test-server.ts +``` diff --git a/utilities/oidc-server/config.ts b/utilities/oidc-server/config.ts new file mode 100644 index 0000000000..f3bba0df8b --- /dev/null +++ b/utilities/oidc-server/config.ts @@ -0,0 +1,31 @@ +import path from 'node:path'; + +import { dirname } from 'desm'; + +const __dirname = dirname(import.meta.url); + +/** + * Configuration for the OIDC server + */ +export function getConfig() { + /** + * Port on which the OIDC server listens (default: 8889) + */ + const PORT: number = Number(process.env.OIDC_PORT) || 8889; + + /** + * Issuer URL for OIDC provider (default: http://localhost:) + */ + const ISSUER: string = process.env.OIDC_ISSUER || `http://localhost:${PORT}`; + + /** + * Path to EJS views directory + */ + const VIEWS_PATH: string = path.join(__dirname, 'views'); + + return { + PORT, + ISSUER, + VIEWS_PATH, + }; +} diff --git a/utilities/oidc-server/index.ts b/utilities/oidc-server/index.ts new file mode 100644 index 0000000000..31baaac131 --- /dev/null +++ b/utilities/oidc-server/index.ts @@ -0,0 +1,7 @@ +import { getConfig } from './config'; +import routes from './routes/express'; +import OIDCServer from './server'; +import Account from './support/account'; +import providerConfiguration from './support/configuration'; + +export { OIDCServer, getConfig, routes, providerConfiguration, Account }; diff --git a/utilities/oidc-server/routes/express.ts b/utilities/oidc-server/routes/express.ts new file mode 100644 index 0000000000..b027b526f1 --- /dev/null +++ b/utilities/oidc-server/routes/express.ts @@ -0,0 +1,210 @@ +import { strict as assert } from 'node:assert'; +import * as querystring from 'node:querystring'; +import { inspect } from 'node:util'; + +import { + type Application, + type NextFunction, + type Request, + type Response, + urlencoded, +} from 'express'; +import isEmpty from 'lodash/isEmpty.js'; +import type Provider from 'oidc-provider'; +import { errors } from 'oidc-provider'; + +import Account from '../support/account'; + +const body = urlencoded({ extended: false }); +const keys = new Set(); +const debug = (obj: Record): string => + querystring.stringify( + Object.entries(obj).reduce( + (acc, [key, value]) => { + keys.add(key); + if (isEmpty(value)) return acc; + acc[key] = inspect(value, { depth: null }); + return acc; + }, + {} as Record, + ), + '
', + ': ', + { + encodeURIComponent(value: string) { + return keys.has(value) ? `${value}` : value; + }, + }, + ); +const { SessionNotFound } = errors; + +/** + * Registers interaction routes into the Express app. + */ +export default function registerRoutes( + app: Application, + provider: Provider, +): void { + app.use((req: Request, res: Response, next: NextFunction) => { + const orig = res.render.bind(res); + res.render = ((view: string, locals?: Record) => { + app.render(view, locals || {}, (err, html) => { + if (err) throw err; + orig('_layout', { + ...locals, + body: html, + }); + }); + }) as typeof res.render; + next(); + }); + + function setNoCache(req: Request, res: Response, next: NextFunction): void { + res.set('cache-control', 'no-store'); + next(); + } + + app.get( + '/interaction/:uid', + setNoCache, + async (req: Request, res: Response, next: NextFunction) => { + try { + const { uid, prompt, params, session } = + await provider.interactionDetails(req, res); + const client = await provider.Client.find(params.client_id as string); + switch (prompt.name) { + case 'login': + return res.render('login', { + client, + uid, + details: prompt.details, + params, + title: 'Sign-in', + session: session + ? debug(session as Record) + : undefined, + dbg: { + params: debug(params as Record), + prompt: debug(prompt as Record), + }, + }); + case 'consent': + return res.render('interaction', { + client, + uid, + details: prompt.details, + params, + title: 'Authorize', + session: session + ? debug(session as Record) + : undefined, + dbg: { + params: debug(params as Record), + prompt: debug(prompt as Record), + }, + }); + default: + return; + } + } catch (err) { + next(err as Error); + } + }, + ); + + app.post( + '/interaction/:uid/login', + setNoCache, + body, + async (req: Request, res: Response, next: NextFunction) => { + try { + const { + prompt: { name }, + } = await provider.interactionDetails(req, res); + assert.equal(name, 'login'); + const { login } = req.body as { login: string }; + const account = await Account.findByLogin(login); + const result = { login: { accountId: account.accountId } }; + await provider.interactionFinished(req, res, result, { + mergeWithLastSubmission: false, + }); + } catch (err) { + next(err as Error); + } + }, + ); + + app.post( + '/interaction/:uid/confirm', + setNoCache, + body, + async (req: Request, res: Response, next: NextFunction) => { + try { + const interactionDetails = await provider.interactionDetails(req, res); + const { + prompt: { name, details }, + params, + session: { accountId }, + } = interactionDetails; + assert.equal(name, 'consent'); + let { grantId } = interactionDetails; + let grant; + if (grantId) { + grant = await provider.Grant.find(grantId as string); + } else { + grant = new provider.Grant({ + accountId: accountId as string, + clientId: params.client_id as string, + }); + } + if (details.missingOIDCScope) { + grant.addOIDCScope((details.missingOIDCScope as string[]).join(' ')); + } + if (details.missingOIDCClaims) { + grant.addOIDCClaims(details.missingOIDCClaims as string[]); + } + if (details.missingResourceScopes) { + for (const [indicator, scopes] of Object.entries( + details.missingResourceScopes as Record, + )) { + grant.addResourceScope(indicator, scopes.join(' ')); + } + } + grantId = await grant.save(); + const consent: Record = {}; + if (!interactionDetails.grantId) consent.grantId = grantId; + const result = { consent }; + await provider.interactionFinished(req, res, result, { + mergeWithLastSubmission: true, + }); + } catch (err) { + next(err as Error); + } + }, + ); + + app.get( + '/interaction/:uid/abort', + setNoCache, + async (req: Request, res: Response, next: NextFunction) => { + try { + const result = { + error: 'access_denied', + error_description: 'End-User aborted interaction', + }; + await provider.interactionFinished(req, res, result, { + mergeWithLastSubmission: false, + }); + } catch (err) { + next(err as Error); + } + }, + ); + + app.use((err: unknown, req: Request, res: Response, next: NextFunction) => { + if (err instanceof SessionNotFound) { + // handle interaction expired / session not found error + } + next(err); + }); +} diff --git a/utilities/oidc-server/server.test.ts b/utilities/oidc-server/server.test.ts new file mode 100644 index 0000000000..583aba24a0 --- /dev/null +++ b/utilities/oidc-server/server.test.ts @@ -0,0 +1,25 @@ +// @vitest-environment node +import { describe, expect, it } from 'vitest'; + +import OIDCServer from './server'; +import Account from './support/account'; +import providerConfiguration from './support/configuration'; + +describe('OIDCServer', () => { + it('starts and stops without errors', async () => { + const server = new OIDCServer({ + issuer: 'http://localhost', + port: 0, + viewsPath: './views', + providerConfiguration, + accountModel: Account, + routes: () => {}, + }); + // starting on port 0 should pick an available port + await expect(server.start()).resolves.toBeUndefined(); + // Express app should be initialized + expect(server.app).toBeDefined(); + // stop should not throw + expect(() => server.stop()).not.toThrow(); + }); +}); diff --git a/utilities/oidc-server/server.ts b/utilities/oidc-server/server.ts new file mode 100644 index 0000000000..1602545bd1 --- /dev/null +++ b/utilities/oidc-server/server.ts @@ -0,0 +1,133 @@ +import type { Server as HttpServer } from 'http'; + +import express, { type Application } from 'express'; +import helmet, { contentSecurityPolicy } from 'helmet'; +import Provider from 'oidc-provider'; + +/** + * Options for configuring the OIDCServer. + */ +export interface OIDCServerOptions { + issuer: string; + port: number; + viewsPath: string; + providerConfiguration: Record & { + findAccount?: ( + ctx: unknown, + id: string, + token?: unknown, + ) => Promise; + }; + accountModel: { + findAccount: ( + ctx: unknown, + id: string, + token?: unknown, + ) => Promise; + }; + routes: (app: Application, provider: Provider) => void; +} + +/** + * OIDCServer encapsulates an Express application and an oidc-provider instance. + */ +export default class OIDCServer { + public app: Application; + public provider!: Provider; + public server?: HttpServer; + + private issuer: string; + private port: number; + private viewsPath: string; + private providerConfiguration: Record & { + findAccount?: ( + ctx: unknown, + id: string, + token?: unknown, + ) => Promise; + }; + private accountModel: { + findAccount: ( + ctx: unknown, + id: string, + token?: unknown, + ) => Promise; + }; + private routes: (app: Application, provider: Provider) => void; + + constructor(options: OIDCServerOptions) { + this.issuer = options.issuer; + this.port = options.port; + this.viewsPath = options.viewsPath; + this.providerConfiguration = options.providerConfiguration; + this.accountModel = options.accountModel; + this.routes = options.routes; + this.app = express(); + } + + private configureSecurity(): void { + const directives = contentSecurityPolicy.getDefaultDirectives(); + // remove default form-action to allow form submissions + delete directives['form-action']; + // allow Tailwind CDN and inline scripts for dynamic CSS + directives['script-src'] = [ + ...((directives['script-src'] as string[]) || []), + 'https://cdn.tailwindcss.com', + "'unsafe-inline'", + ]; + this.app.use( + helmet({ + contentSecurityPolicy: { + useDefaults: false, + directives, + }, + }), + ); + } + + private configureViews(): void { + this.app.set('views', this.viewsPath); + this.app.set('view engine', 'ejs'); + } + + private configureProvider(): void { + // inject account model for findAccount + this.providerConfiguration.findAccount = this.accountModel.findAccount; + this.provider = new Provider(this.issuer, this.providerConfiguration); + } + + private configureRoutes(): void { + // custom interaction routes + this.routes(this.app, this.provider); + // oidc-provider callback for all other endpoints + this.app.use(this.provider.callback()); + } + + /** + * Starts the Express server and the oidc-provider instance. + */ + public async start(): Promise { + try { + this.configureSecurity(); + this.configureViews(); + this.configureProvider(); + this.configureRoutes(); + + this.server = this.app.listen(this.port); + } catch (err) { + if (this.server?.listening) this.server.close(); + console.error('Error starting OIDC Server:', err); + process.exit(1); + } + } + + /** + * Stops the server if it is running. + */ + public stop(): void { + if (this.server?.listening) { + console.log('Stopping OIDC Server...'); + this.server.close(); + } + } +} diff --git a/utilities/oidc-server/support/account.ts b/utilities/oidc-server/support/account.ts new file mode 100644 index 0000000000..b1f9f39491 --- /dev/null +++ b/utilities/oidc-server/support/account.ts @@ -0,0 +1,98 @@ +import { nanoid } from 'nanoid'; + +/** + * Account model for oidc-provider interactions. + */ +export default class Account { + public accountId: string; + private profile?: Record; + + constructor(id?: string, profile?: Record) { + this.accountId = id ?? nanoid(); + this.profile = profile; + Account.store.set(this.accountId, this); + } + + /** + * Returns claims for the ID token or userinfo endpoint. + */ + public async claims(): Promise> { + if (this.profile) { + return { + sub: this.accountId, + email: this.profile.email, + email_verified: this.profile.email_verified, + family_name: this.profile.family_name, + given_name: this.profile.given_name, + locale: this.profile.locale, + name: this.profile.name, + }; + } + return { + sub: this.accountId, + address: { + country: '000', + formatted: '000', + locality: '000', + postal_code: '000', + region: '000', + street_address: '000', + }, + birthdate: '1987-10-16', + email: 'johndoe@example.com', + email_verified: false, + family_name: 'Doe', + gender: 'male', + given_name: 'John', + locale: 'en-US', + middle_name: 'Middle', + name: 'John Doe', + nickname: 'Johny', + phone_number: '+49 000 000000', + phone_number_verified: false, + picture: 'http://lorempixel.com/400/200/', + preferred_username: 'johnny', + profile: 'https://johnswebsite.com', + updated_at: 1454704946, + website: 'http://example.com', + zoneinfo: 'Europe/Berlin', + }; + } + + private static store = new Map(); + private static logins = new Map(); + + /** + * Finds or creates an account for federated logins. + */ + public static async findByFederated( + provider: string, + claims: { sub: string } & Record, + ): Promise { + const id = `${provider}.${claims.sub}`; + if (!Account.logins.has(id)) { + Account.logins.set(id, new Account(id, claims)); + } + return Account.logins.get(id)!; + } + + /** + * Finds or creates an account by login identifier. + */ + public static async findByLogin(login: string): Promise { + if (!Account.logins.has(login)) { + Account.logins.set(login, new Account(login)); + } + return Account.logins.get(login)!; + } + + /** + * Finds an account by its accountId. + */ + public static async findAccount(ctx: unknown, id: string): Promise { + if (!Account.store.has(id)) { + new Account(id); + } + return Account.store.get(id)!; + } +} diff --git a/utilities/oidc-server/support/configuration.ts b/utilities/oidc-server/support/configuration.ts new file mode 100644 index 0000000000..4a9988445c --- /dev/null +++ b/utilities/oidc-server/support/configuration.ts @@ -0,0 +1,80 @@ +// ⚠️ FOR LOCAL DEVELOPMENT AND TESTING ONLY - Contains hardcoded secrets +const configuration: Record = { + conformIdTokenClaims: false, + ttl: { + AccessToken: 60, // 1 minute for testing + IdToken: 60, // 1 minute for testing + RefreshToken: 60 * 60 * 24, // 1 day + }, + scopes: ['openid', 'profile', 'email', 'offline_access'], + issueRefreshToken: async () => { + return true; + }, + clients: [ + { + client_id: 'temporal-ui', + client_secret: 'temporal-secret', + grant_types: ['authorization_code', 'refresh_token'], + redirect_uris: ['http://localhost:8081/auth/sso/callback'], + response_types: ['code'], + token_endpoint_auth_method: 'client_secret_basic', + }, + ], + interactions: { + url(_ctx: unknown, interaction: { uid: string }): string { + return `/interaction/${interaction.uid}`; + }, + }, + claims: { + address: ['address'], + email: ['email', 'email_verified'], + phone: ['phone_number', 'phone_number_verified'], + profile: [ + 'birthdate', + 'family_name', + 'gender', + 'given_name', + 'locale', + 'middle_name', + 'name', + 'nickname', + 'picture', + 'preferred_username', + 'profile', + 'updated_at', + 'website', + 'zoneinfo', + ], + }, + features: { + devInteractions: { enabled: false }, + deviceFlow: { enabled: true }, + revocation: { enabled: true }, + }, + jwks: { + keys: [ + { + d: 'VEZOsY07JTFzGTqv6cC2Y32vsfChind2I_TTuvV225_-0zrSej3XLRg8iE_u0-3GSgiGi4WImmTwmEgLo4Qp3uEcxCYbt4NMJC7fwT2i3dfRZjtZ4yJwFl0SIj8TgfQ8ptwZbFZUlcHGXZIr4nL8GXyQT0CK8wy4COfmymHrrUoyfZA154ql_OsoiupSUCRcKVvZj2JHL2KILsq_sh_l7g2dqAN8D7jYfJ58MkqlknBMa2-zi5I0-1JUOwztVNml_zGrp27UbEU60RqV3GHjoqwI6m01U7K0a8Q_SQAKYGqgepbAYOA-P4_TLl5KC4-WWBZu_rVfwgSENwWNEhw8oQ', + dp: 'E1Y-SN4bQqX7kP-bNgZ_gEv-pixJ5F_EGocHKfS56jtzRqQdTurrk4jIVpI-ZITA88lWAHxjD-OaoJUh9Jupd_lwD5Si80PyVxOMI2xaGQiF0lbKJfD38Sh8frRpgelZVaK_gm834B6SLfxKdNsP04DsJqGKktODF_fZeaGFPH0', + dq: 'F90JPxevQYOlAgEH0TUt1-3_hyxY6cfPRU2HQBaahyWrtCWpaOzenKZnvGFZdg-BuLVKjCchq3G_70OLE-XDP_ol0UTJmDTT-WyuJQdEMpt_WFF9yJGoeIu8yohfeLatU-67ukjghJ0s9CBzNE_LrGEV6Cup3FXywpSYZAV3iqc', + e: 'AQAB', + kty: 'RSA', + n: 'xwQ72P9z9OYshiQ-ntDYaPnnfwG6u9JAdLMZ5o0dmjlcyrvwQRdoFIKPnO65Q8mh6F_LDSxjxa2Yzo_wdjhbPZLjfUJXgCzm54cClXzT5twzo7lzoAfaJlkTsoZc2HFWqmcri0BuzmTFLZx2Q7wYBm0pXHmQKF0V-C1O6NWfd4mfBhbM-I1tHYSpAMgarSm22WDMDx-WWI7TEzy2QhaBVaENW9BKaKkJklocAZCxk18WhR0fckIGiWiSM5FcU1PY2jfGsTmX505Ub7P5Dz75Ygqrutd5tFrcqyPAtPTFDk8X1InxkkUwpP3nFU5o50DGhwQolGYKPGtQ-ZtmbOfcWQ', + p: '5wC6nY6Ev5FqcLPCqn9fC6R9KUuBej6NaAVOKW7GXiOJAq2WrileGKfMc9kIny20zW3uWkRLm-O-3Yzze1zFpxmqvsvCxZ5ERVZ6leiNXSu3tez71ZZwp0O9gys4knjrI-9w46l_vFuRtjL6XEeFfHEZFaNJpz-lcnb3w0okrbM', + q: '3I1qeEDslZFB8iNfpKAdWtz_Wzm6-jayT_V6aIvhvMj5mnU-Xpj75zLPQSGa9wunMlOoZW9w1wDO1FVuDhwzeOJaTm-Ds0MezeC4U6nVGyyDHb4CUA3ml2tzt4yLrqGYMT7XbADSvuWYADHw79OFjEi4T3s3tJymhaBvy1ulv8M', + qi: 'wSbXte9PcPtr788e713KHQ4waE26CzoXx-JNOgN0iqJMN6C4_XJEX-cSvCZDf4rh7xpXN6SGLVd5ibIyDJi7bbi5EQ5AXjazPbLBjRthcGXsIuZ3AtQyR0CEWNSdM7EyM5TRdyZQ9kftfz9nI03guW3iKKASETqX2vh0Z8XRjyU', + use: 'sig', + }, + { + crv: 'P-256', + d: 'K9xfPv773dZR22TVUB80xouzdF7qCg5cWjPjkHyv7Ws', + kty: 'EC', + use: 'sig', + x: 'FWZ9rSkLt6Dx9E3pxLybhdM6xgR5obGsj5_pqmnz5J4', + y: '_n8G69C-A2Xl4xUW2lF0i8ZGZnk_KPYrhv4GbTGu5G4', + }, + ], + }, +}; + +export default configuration; diff --git a/utilities/oidc-server/test-server.ts b/utilities/oidc-server/test-server.ts new file mode 100644 index 0000000000..daba22f5a4 --- /dev/null +++ b/utilities/oidc-server/test-server.ts @@ -0,0 +1,30 @@ +#!/usr/bin/env ts-node +import { getConfig } from './config'; +import routes from './routes/express'; +import OIDCServer from './server'; +import Account from './support/account'; +import providerConfiguration from './support/configuration'; + +(async () => { + const { PORT, ISSUER, VIEWS_PATH } = getConfig(); + + const server = new OIDCServer({ + issuer: ISSUER, + port: PORT, + viewsPath: VIEWS_PATH, + providerConfiguration, + accountModel: Account, + routes, + }); + + try { + await server.start(); + console.log('✅ Server started successfully'); + } catch (err) { + console.error('❌ Error starting server:', err); + process.exit(1); + } finally { + server.stop(); + console.log('✅ Server stopped successfully'); + } +})(); diff --git a/utilities/oidc-server/views/_layout.ejs b/utilities/oidc-server/views/_layout.ejs new file mode 100644 index 0000000000..8e3127f0d7 --- /dev/null +++ b/utilities/oidc-server/views/_layout.ejs @@ -0,0 +1,245 @@ + + + + + + + <%= title %> + + + + + + + + + +
+

<%= title %>

+ <%- body %> + +
+
+
+ (Click to expand) DEBUG information +
+ uid: <%= uid %> +
+ + <% if (session) { %> +
+ SESSION
+ =========
+ <%- session %> +
+ <% } %> + +
+ PARAMS
+ ========
+ <%- dbg.params %> +
+ +
+ PROMPT
+ ========
+ <%- dbg.prompt %> +
+
+
+ + diff --git a/utilities/oidc-server/views/interaction.ejs b/utilities/oidc-server/views/interaction.ejs new file mode 100644 index 0000000000..9493b416f7 --- /dev/null +++ b/utilities/oidc-server/views/interaction.ejs @@ -0,0 +1,67 @@ +<% if (client.logoUri) { %> +
+ Client logo +
+<% } %> + +
    +<% if ([details.missingOIDCScope, details.missingOIDCClaims, details.missingResourceScopes, details.rar].filter(Boolean).length === 0) { %> +
  • the client is asking you to confirm previously given authorization
  • +<% } %> + +<% missingOIDCScope = new Set(details.missingOIDCScope); missingOIDCScope.delete('openid'); missingOIDCScope.delete('offline_access') %> +<% if (missingOIDCScope.size) { %> +
  • scopes:
  • +
      + <% missingOIDCScope.forEach((scope) => { %> +
    • <%= scope %>
    • + <% }) %> +
    +<% } %> + +<% missingOIDCClaims = new Set(details.missingOIDCClaims); ['sub', 'sid', 'auth_time', 'acr', 'amr', 'iss'].forEach(Set.prototype.delete.bind(missingOIDCClaims)) %> +<% if (missingOIDCClaims.size) { %> +
  • claims:
  • +
      + <% missingOIDCClaims.forEach((claim) => { %> +
    • <%= claim %>
    • + <% }) %> +
    +<% } %> + +<% missingResourceScopes = details.missingResourceScopes %> +<% if (missingResourceScopes) { %> + <% for (const [indicator, scopes] of Object.entries(details.missingResourceScopes)) { %> +
  • <%= indicator %>:
  • +
      + <% scopes.forEach((scope) => { %> +
    • <%= scope %>
    • + <% }) %> +
    + <% } %> +<% } %> + +<% rar = details.rar %> +<% if (rar) { %> +
  • authorization_details:
  • +
      + <% for (const { type, ...detail } of details.rar) { %> +
    • <%= JSON.stringify({ type, ...detail }, null, 4) %>
    • + <% } %> +
    +<% } %> + +<% if (params.scope && params.scope.includes('offline_access')) { %> +
  • + the client is asking to have offline access to this authorization + <% if ((!details.missingOIDCScope) || !details.missingOIDCScope.includes('offline_access')) { %> + (which you've previously granted) + <% } %> +
  • +<% } %> + +
+ +
+ +
diff --git a/utilities/oidc-server/views/login.ejs b/utilities/oidc-server/views/login.ejs new file mode 100644 index 0000000000..906a5284a2 --- /dev/null +++ b/utilities/oidc-server/views/login.ejs @@ -0,0 +1,23 @@ +<% if (locals.google) { %> +
+ + +
+ +<% } %> +
+ autofocus="on"<% } else { %> value="<%= params.login_hint %>" <% } %>> + autofocus="on"<% } %>> + + +
diff --git a/utilities/ui-server.ts b/utilities/ui-server.ts index 57dc7cef7c..48b63f865f 100644 --- a/utilities/ui-server.ts +++ b/utilities/ui-server.ts @@ -8,21 +8,21 @@ export type UIServer = { ready: () => ReturnType; }; +export type ValidEnv = 'development' | 'e2e' | 'with-auth'; + let uiServer: UIServer; export const getUIServer = (): UIServer => { return uiServer; }; -type Environemt = 'development' | 'e2e'; - -const portForEnv = (env: Environemt) => { - if (env === 'development') return 8081; +const portForEnv = (env: ValidEnv) => { if (env === 'e2e') return 8080; + return 8081; }; export const createUIServer = async ( - env: 'development' | 'e2e' = 'development', + env: ValidEnv = 'development', options?: { verbose?: boolean }, ) => { $.cwd = join(process.cwd(), 'server'); diff --git a/vite.config.ts b/vite.config.ts index 794ad44a93..88a70cee6f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,11 +3,17 @@ import path from 'path'; import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; +import { oidcServerPlugin } from './plugins/vite-plugin-oidc-server'; import { temporalServer } from './plugins/vite-plugin-temporal-server'; import { uiServerPlugin } from './plugins/vite-plugin-ui-server'; export default defineConfig({ - plugins: [sveltekit(), temporalServer(), uiServerPlugin()], + plugins: [ + sveltekit(), + oidcServerPlugin(), + temporalServer(), + uiServerPlugin(), + ], optimizeDeps: { include: ['date-fns', 'date-fns-tz'], }, diff --git a/vitest.config.ts b/vitest.config.ts index 6924eeeda4..a0abcedf15 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -16,6 +16,7 @@ export default defineConfig({ }, }, test: { + include: ['**/*.test.ts', '**/*.spec.ts'], globals: true, coverage: { reporter: ['text', 'json', 'html'],