From 9fd8744ec4e356dedb7a3b13c26c36ead8afd4a6 Mon Sep 17 00:00:00 2001 From: brainx <12695242+brainx@users.noreply.github.com> Date: Sun, 2 Aug 2026 20:56:13 +0200 Subject: [PATCH 1/3] feat: replace Streamlit with polished local web app --- .github/CONTRIBUTING.md | 2 +- .github/workflows/ci.yml | 76 +- .github/workflows/release.yml | 18 +- .gitignore | 5 - .streamlit/config.toml | 7 - CHANGELOG.md | 11 + README.md | 55 +- api_app.py | 44 +- crypto_core.py | 13 +- docs/API.md | 17 + docs/RELEASE_CHECKLIST.md | 4 +- docs/SCREENSHOTS.md | 24 +- docs/SECURITY.md | 2 +- docs/THREAT_MODEL.md | 2 +- .../custom-web-encrypt-workflow.png | Bin 136505 -> 94974 bytes .../screenshots/custom-web-mobile-inspect.png | Bin 70493 -> 49048 bytes docs/screenshots/decrypt-file-workflow.jpg | Bin 63202 -> 0 bytes docs/screenshots/encrypt-file-workflow.jpg | Bin 62132 -> 0 bytes .../generate-keys-backend-warning.jpg | Bin 69833 -> 0 bytes docs/screenshots/key-utilities-workflow.jpg | Bin 54640 -> 0 bytes package-lock.json | 1397 +++++++++++++++-- package.json | 16 +- pqc_app.py | 492 ------ pyproject.toml | 3 +- requirements-dev-lock.txt | 672 +------- requirements-lock.txt | 876 +---------- requirements.txt | 3 - scripts/api_client.test.mjs | 72 +- scripts/ui_native_smoke.mjs | 111 ++ scripts/ui_smoke.mjs | 375 ++++- start.sh | 6 - tests/test_api_app.py | 25 + tests/test_crypto_core.py | 11 + tests/test_startup.py | 43 + tsconfig.json | 2 +- ui_helpers.py | 2 +- vite.config.ts | 8 + web/src/App.tsx | 632 -------- web/src/{api.ts => api/client.ts} | 71 +- web/src/api/contracts.ts | 68 + web/src/api/errors.ts | 18 + web/src/api/index.ts | 13 + web/src/app/App.test.tsx | 130 ++ web/src/app/App.tsx | 84 + web/src/app/AppShell.test.tsx | 59 + web/src/app/AppShell.tsx | 99 ++ web/src/app/navigation.ts | 8 + web/src/components/ActionButton.tsx | 14 + web/src/components/CapabilityStatus.tsx | 60 + web/src/components/FilePicker.tsx | 69 + web/src/components/Notice.tsx | 18 + web/src/components/PasswordField.tsx | 35 + web/src/components/TechnicalDetails.tsx | 14 + web/src/components/WorkflowLayout.tsx | 39 + web/src/components/components.test.tsx | 83 + .../features/decrypt/DecryptWorkflow.test.tsx | 306 ++++ web/src/features/decrypt/DecryptWorkflow.tsx | 298 ++++ .../features/encrypt/EncryptWorkflow.test.tsx | 238 +++ web/src/features/encrypt/EncryptWorkflow.tsx | 268 ++++ .../generate/GenerateKeysWorkflow.test.tsx | 257 +++ .../generate/GenerateKeysWorkflow.tsx | 223 +++ .../features/generate/passwordPolicy.test.ts | 35 + web/src/features/generate/passwordPolicy.ts | 44 + .../inspect/InspectKeyWorkflow.test.tsx | 33 + .../features/inspect/InspectKeyWorkflow.tsx | 68 + web/src/hooks/useKeyInspection.test.tsx | 131 ++ web/src/hooks/useKeyInspection.ts | 80 + web/src/lib/download.ts | 19 + web/src/lib/filenames.test.ts | 20 + web/src/lib/filenames.ts | 19 + web/src/lib/format.test.ts | 10 + web/src/lib/format.ts | 13 + web/src/lib/workflow.test.ts | 16 + web/src/lib/workflow.ts | 6 + web/src/main.tsx | 6 +- web/src/styles.css | 564 ------- web/src/styles/components.css | 609 +++++++ web/src/styles/global.css | 29 + web/src/styles/tokens.css | 50 + web/src/test/fixtures.ts | 26 + web/src/test/setup.ts | 7 + 81 files changed, 5786 insertions(+), 3497 deletions(-) delete mode 100644 .streamlit/config.toml delete mode 100644 docs/screenshots/decrypt-file-workflow.jpg delete mode 100644 docs/screenshots/encrypt-file-workflow.jpg delete mode 100644 docs/screenshots/generate-keys-backend-warning.jpg delete mode 100644 docs/screenshots/key-utilities-workflow.jpg delete mode 100644 pqc_app.py create mode 100644 scripts/ui_native_smoke.mjs create mode 100644 tests/test_startup.py delete mode 100644 web/src/App.tsx rename web/src/{api.ts => api/client.ts} (77%) create mode 100644 web/src/api/contracts.ts create mode 100644 web/src/api/errors.ts create mode 100644 web/src/api/index.ts create mode 100644 web/src/app/App.test.tsx create mode 100644 web/src/app/App.tsx create mode 100644 web/src/app/AppShell.test.tsx create mode 100644 web/src/app/AppShell.tsx create mode 100644 web/src/app/navigation.ts create mode 100644 web/src/components/ActionButton.tsx create mode 100644 web/src/components/CapabilityStatus.tsx create mode 100644 web/src/components/FilePicker.tsx create mode 100644 web/src/components/Notice.tsx create mode 100644 web/src/components/PasswordField.tsx create mode 100644 web/src/components/TechnicalDetails.tsx create mode 100644 web/src/components/WorkflowLayout.tsx create mode 100644 web/src/components/components.test.tsx create mode 100644 web/src/features/decrypt/DecryptWorkflow.test.tsx create mode 100644 web/src/features/decrypt/DecryptWorkflow.tsx create mode 100644 web/src/features/encrypt/EncryptWorkflow.test.tsx create mode 100644 web/src/features/encrypt/EncryptWorkflow.tsx create mode 100644 web/src/features/generate/GenerateKeysWorkflow.test.tsx create mode 100644 web/src/features/generate/GenerateKeysWorkflow.tsx create mode 100644 web/src/features/generate/passwordPolicy.test.ts create mode 100644 web/src/features/generate/passwordPolicy.ts create mode 100644 web/src/features/inspect/InspectKeyWorkflow.test.tsx create mode 100644 web/src/features/inspect/InspectKeyWorkflow.tsx create mode 100644 web/src/hooks/useKeyInspection.test.tsx create mode 100644 web/src/hooks/useKeyInspection.ts create mode 100644 web/src/lib/download.ts create mode 100644 web/src/lib/filenames.test.ts create mode 100644 web/src/lib/filenames.ts create mode 100644 web/src/lib/format.test.ts create mode 100644 web/src/lib/format.ts create mode 100644 web/src/lib/workflow.test.ts create mode 100644 web/src/lib/workflow.ts delete mode 100644 web/src/styles.css create mode 100644 web/src/styles/components.css create mode 100644 web/src/styles/global.css create mode 100644 web/src/styles/tokens.css create mode 100644 web/src/test/fixtures.ts create mode 100644 web/src/test/setup.ts diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 67bcc0a..9896c7a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -84,7 +84,7 @@ By participating in this project, you agree to abide by our Code of Conduct. - Run mypy to check static typing: ```bash .venv/bin/python -m mypy \ - crypto_config.py crypto_core.py pqc_agent_tools.py pqc_app.py \ + api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py ui_helpers.py \ tests/test_agent_tools.py tests/test_crypto_core.py ``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5eb54a4..83539df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,13 +32,13 @@ jobs: run: python -m pip install -r requirements-dev.txt - name: Check formatting - run: python -m black --check api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py setup.py tests/test_agent_tools.py tests/test_api_app.py tests/test_crypto_core.py tests/test_ui_helpers.py + run: python -m black --check api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py ui_helpers.py setup.py tests/test_agent_tools.py tests/test_api_app.py tests/test_crypto_core.py tests/test_ui_helpers.py - name: Lint - run: python -m flake8 api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py setup.py tests/test_agent_tools.py tests/test_api_app.py tests/test_crypto_core.py tests/test_ui_helpers.py + run: python -m flake8 api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py ui_helpers.py setup.py tests/test_agent_tools.py tests/test_api_app.py tests/test_crypto_core.py tests/test_ui_helpers.py - name: Type check - run: python -m mypy api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py tests/test_agent_tools.py tests/test_api_app.py tests/test_crypto_core.py tests/test_ui_helpers.py + run: python -m mypy api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py ui_helpers.py tests/test_agent_tools.py tests/test_api_app.py tests/test_crypto_core.py tests/test_ui_helpers.py - name: Unit tests without native liboqs run: > @@ -93,15 +93,21 @@ jobs: /tmp/qe-wheel-test/bin/quantum-encryptor-agent health --json /tmp/qe-wheel-test/bin/python -I - <<'PY' from pathlib import Path + from importlib.metadata import requires + from importlib.util import find_spec import sys import api_app import pqc_agent_tools + import ui_helpers prefix = Path(sys.prefix).resolve() - for module in (api_app, pqc_agent_tools): + for module in (api_app, pqc_agent_tools, ui_helpers): module_path = Path(module.__file__).resolve() assert module_path.is_relative_to(prefix), (module.__name__, module_path, prefix) + assert find_spec("pqc_app") is None + package_requirements = requires("quantum-encryptor") or () + assert all(not requirement.lower().startswith("streamlit") for requirement in package_requirements) PY - name: Smoke installed web UI @@ -155,7 +161,7 @@ jobs: run: npm audit --package-lock-only --audit-level=high - name: Run Python security lint - run: python -m bandit -q -r api_app.py crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py + run: python -m bandit -q -r api_app.py crypto_core.py pqc_agent_tools.py ui_helpers.py web: name: Custom web UI @@ -262,9 +268,9 @@ jobs: run: | git init .ci/liboqs git -C .ci/liboqs remote add origin https://github.com/open-quantum-safe/liboqs.git - # liboqs 0.15.0 - git -C .ci/liboqs fetch --depth=1 origin 97f6b86b1b6d109cfd43cf276ae39c2e776aed80 - git -C .ci/liboqs checkout --detach 97f6b86b1b6d109cfd43cf276ae39c2e776aed80 + # liboqs 0.16.0 + git -C .ci/liboqs fetch --depth=1 origin 5a1a854b0dc9f2141bdc771c555ee60c37950183 + git -C .ci/liboqs checkout --detach 5a1a854b0dc9f2141bdc771c555ee60c37950183 cmake -S .ci/liboqs -B .ci/liboqs/build \ -GNinja \ -DBUILD_SHARED_LIBS=ON \ @@ -273,7 +279,22 @@ jobs: cmake --install .ci/liboqs/build - name: Install Python dependencies - run: python -m pip install -r requirements-dev.txt + run: python -m pip install --require-hashes -r requirements-dev-lock.txt + + - name: Set up Node + uses: actions/setup-node@v7 + with: + node-version: "22" + cache: npm + + - name: Install frontend dependencies + run: npm ci + + - name: Build frontend + run: npm run build + + - name: Install Playwright Chromium + run: npx playwright install --with-deps chromium - name: Verify native backend is active run: | @@ -314,3 +335,40 @@ jobs: --private-key agent-private.pem \ --output agent-output.txt cmp agent-input.txt agent-output.txt + + - name: Native browser encryption round trip + run: | + SKIP_WEB_BUILD=1 PYTHON=python ./start.sh & + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT + python - <<'PY' + import json + import time + from urllib.request import urlopen + + required = ("generate", "encrypt", "decrypt") + deadline = time.monotonic() + 30 + + while (remaining := deadline - time.monotonic()) > 0: + try: + with urlopen("http://127.0.0.1:4000/api/health", timeout=min(1, remaining)) as response: + health = json.load(response) + except Exception: + health = None + + ready = bool( + health + and health.get("ok") + and health.get("backendReady") + and all(health.get("capabilities", {}).get(name, {}).get("available") for name in required) + ) + if ready: + raise SystemExit(0) + + remaining = deadline - time.monotonic() + if remaining > 0: + time.sleep(min(0.25, remaining)) + + raise SystemExit("Native local app did not become ready within 30 seconds.") + PY + npm run ui-native diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 815f3c2..3bc944b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,7 +44,7 @@ jobs: run: python -m pip_audit -r requirements-dev-lock.txt - name: Run Python security lint - run: python -m bandit -q -r crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py api_app.py + run: python -m bandit -q -r crypto_core.py pqc_agent_tools.py ui_helpers.py api_app.py - name: Install frontend dependencies run: npm ci @@ -82,15 +82,21 @@ jobs: /tmp/qe-release-test/bin/quantum-encryptor-agent health --json /tmp/qe-release-test/bin/python -I - <<'PY' from pathlib import Path + from importlib.metadata import requires + from importlib.util import find_spec import sys import api_app import pqc_agent_tools + import ui_helpers prefix = Path(sys.prefix).resolve() - for module in (api_app, pqc_agent_tools): + for module in (api_app, pqc_agent_tools, ui_helpers): module_path = Path(module.__file__).resolve() assert module_path.is_relative_to(prefix), (module.__name__, module_path, prefix) + assert find_spec("pqc_app") is None + package_requirements = requires("quantum-encryptor") or () + assert all(not requirement.lower().startswith("streamlit") for requirement in package_requirements) PY - name: Smoke installed web UI @@ -177,9 +183,9 @@ jobs: run: | git init .ci/liboqs git -C .ci/liboqs remote add origin https://github.com/open-quantum-safe/liboqs.git - # liboqs 0.15.0 - git -C .ci/liboqs fetch --depth=1 origin 97f6b86b1b6d109cfd43cf276ae39c2e776aed80 - git -C .ci/liboqs checkout --detach 97f6b86b1b6d109cfd43cf276ae39c2e776aed80 + # liboqs 0.16.0 + git -C .ci/liboqs fetch --depth=1 origin 5a1a854b0dc9f2141bdc771c555ee60c37950183 + git -C .ci/liboqs checkout --detach 5a1a854b0dc9f2141bdc771c555ee60c37950183 cmake -S .ci/liboqs -B .ci/liboqs/build \ -GNinja \ -DBUILD_SHARED_LIBS=ON \ @@ -188,7 +194,7 @@ jobs: cmake --install .ci/liboqs/build - name: Install Python dependencies - run: python -m pip install -r requirements-dev.txt + run: python -m pip install --require-hashes -r requirements-dev-lock.txt - name: Verify migration backends are active run: | diff --git a/.gitignore b/.gitignore index 8cb241b..aba43b7 100644 --- a/.gitignore +++ b/.gitignore @@ -108,11 +108,6 @@ ENV/ env.bak/ venv.bak/ -# Streamlit local state and secrets. Keep committed UI theme config. -.streamlit/* -!.streamlit/ -!.streamlit/config.toml - # Spyder project settings .spyderproject .spyproject diff --git a/.streamlit/config.toml b/.streamlit/config.toml deleted file mode 100644 index d76f1b1..0000000 --- a/.streamlit/config.toml +++ /dev/null @@ -1,7 +0,0 @@ -[theme] -base = "dark" -primaryColor = "#2DD4BF" -backgroundColor = "#000000" -secondaryBackgroundColor = "#111827" -textColor = "#FFFFFF" -font = "sans serif" diff --git a/CHANGELOG.md b/CHANGELOG.md index 349bea6..efd4998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ This project follows a practical semantic-versioning style. - ML-KEM-768 + X25519 composite key generation and format-v4 encrypted containers. - SHA3-256 hybrid key combiner binding both key shares, X25519 context, suite identifier, and application domain. +- Polished monochrome local web workflows with progressive technical details, + responsive navigation, component tests, accessibility checks, and a native + browser encryption round trip. + +### Changed + +- Retired the Streamlit application, temporary startup fallback, packaging + surface, and superseded reference screenshots. `./start.sh` now serves the + React/Vite interface through the loopback-only Python API as the sole GUI. +- Preserved decrypt-only compatibility for authenticated earlier containers and + private-key formats, including the bounded ML-KEM/Kyber migration path. ### Security diff --git a/README.md b/README.md index 127b1a6..947f795 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,14 @@ A post-quantum cryptography tool for file encryption. New files combine ML-KEM-7 Quantum Encryptor custom web app showing the encrypt file workflow and backend readiness warning

- Dark local web interface for ML-KEM-768 + X25519 key generation, file encryption, decryption, and PEM key inspection. + Monochrome local web interface for ML-KEM-768 + X25519 key generation, file encryption, decryption, and PEM key inspection.

## Features @@ -25,12 +25,12 @@ A post-quantum cryptography tool for file encryption. New files combine ML-KEM-7 - **Post-Quantum/Traditional Security**: Combines ML-KEM-768 with X25519 so confidentiality does not depend on one key-establishment algorithm - **Authenticated File Encryption**: Derives AES-256-GCM keys from both ML-KEM and X25519 shared secrets - **Password-Protected Keys**: Private keys are always encrypted with scrypt-derived AES-256-GCM keys -- **User-Friendly Interface**: Custom local web UI with a Python ASGI API +- **User-Friendly Interface**: Custom local web UI with progressive technical details and a Python ASGI API - **PEM Key Format**: Keys stored in PEM-like format with quantum algorithm extensions ## Screenshots -The backend readiness warning shown here is expected when native `liboqs` is not installed in the local environment. Click any image to open the full screenshot page. +The current browser smoke captures show the responsive Encrypt and Inspect key workflows. Click either image to open the full screenshot page.

@@ -111,21 +111,22 @@ See [docs/SCREENSHOTS.md](docs/SCREENSHOTS.md) for the dedicated screenshot page PYTHON=.venv/bin/python ./test.sh ``` - To run the legacy Streamlit UI during transition: - ```bash - LEGACY_STREAMLIT=1 ./start.sh - ``` - Frontend development can run Vite separately on `127.0.0.1:4001`: ```bash npm run dev ``` -2. Open the web interface in your browser. You can: - - Generate a new post-quantum key pair - - Encrypt files using a recipient's public key - - Decrypt files using your private key - - Access key utilities +2. Open the web interface in your browser. Choose the intent that matches your task: + - **Encrypt**: protect a file for the holder of a recipient public key. + - **Decrypt**: recover a file with the matching encrypted private key and password. + - **Generate keys**: create a new public key and password-protected private key. + - **Inspect key**: check supported key metadata without exposing key material. + + Each workflow starts with plain-language guidance. Expand **Technical details** only when you need suite, format, or key-policy information. + +### Local-only interface privacy + +The custom interface processes selected files through the local Python service at `127.0.0.1`. It does not use browser persistence, telemetry, remote fonts, or remote application assets. The UI does not display plaintext previews, passwords, private-key content, or the local API token. ## Verification @@ -138,8 +139,9 @@ Run the Python test suite: Run the custom frontend checks: ```bash -npm run build +npm run test:unit npm run check +npm run build ``` With the app already running on `127.0.0.1:4000`, run the browser smoke test: @@ -150,16 +152,24 @@ npm run ui-smoke The UI smoke test writes ignored screenshots under `tmp/ui-smoke/`. +When a native `liboqs` installation is available to the running app, also run the real browser encryption round trip: + +```bash +npm run ui-native +``` + +Do not treat the browser smoke test as proof that the native cryptographic backend is installed; it verifies the built interface against the local API contract. `npm run ui-native` verifies key generation, encryption, and decryption through the available native backend. + ### Key Generation -1. Select "Generate Keys" from the sidebar +1. Select "Generate keys" from the workflow navigation 2. Enter and confirm a strong private-key password 3. Generate the keys and download both public and private key files 4. Share your public key with others who want to send you encrypted files ### File Encryption -1. Select "Encrypt File" from the sidebar +1. Select "Encrypt" from the workflow navigation 2. Upload the file you want to encrypt 3. Upload the recipient's public key (.pem file) 4. Specify the output filename @@ -167,15 +177,15 @@ The UI smoke test writes ignored screenshots under `tmp/ui-smoke/`. ### File Decryption -1. Select "Decrypt File" from the sidebar +1. Select "Decrypt" from the workflow navigation 2. Upload the encrypted file (.pqc file) 3. Upload your private key (.pem file) 4. Enter your private-key password 5. Download the decrypted file -## Agent Usage +## Automation Usage -Local automation agents can use the deterministic JSON CLI instead of driving the Streamlit UI. Run commands from the repository workspace and pass only workspace-relative paths. Absolute paths, `..` traversal, symlink escapes, and accidental output overwrites are rejected. +Automation tools can use the deterministic JSON CLI instead of driving the browser interface. Run commands from the repository workspace and pass only workspace-relative paths. Absolute paths, `..` traversal, symlink escapes, and accidental output overwrites are rejected. ```bash mkdir -p keys data @@ -229,7 +239,7 @@ The CLI prints JSON only and never includes plaintext, private keys, passwords, - State-changing local web API requests require a per-process API token and reject non-local browser origins when an `Origin` header is present - The local agent CLI accepts only workspace-relative paths, returns machine-readable JSON without secret material, and writes private keys plus decrypted outputs with owner-only permissions on POSIX systems; non-overwrite output creation uses exclusive file creation - Native `liboqs` is loaded lazily and missing backend support disables key generation/encryption instead of crashing the app -- CI runs Python formatting, linting, type checks, unit tests, custom web UI build/type checks, API client tests, browser UI smoke, isolated installed-wheel checks, Python/npm dependency audits, locked runtime install, and a native `liboqs` integration test job pinned to the matching 0.15.0 release commit; repository CodeQL default setup provides static analysis +- CI runs Python formatting, linting, type checks, unit tests, custom web UI build/type checks, API client tests, browser UI smoke, isolated installed-wheel checks, Python/npm dependency audits, locked runtime install, and a native `liboqs` integration test job pinned to the matching 0.16.0 release commit; repository CodeQL default setup provides static analysis - See [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md) for repository trust boundaries, assets, abuse cases, and invariants - **Disclaimer**: This software has not undergone an independent security audit and should be reviewed before production use @@ -238,8 +248,7 @@ The CLI prints JSON only and never includes plaintext, private keys, passwords, - `crypto_config.py` - Configuration parameters for cryptographic operations - `crypto_core.py` - Core cryptographic functions (key generation, encryption, decryption) - `api_app.py` - Local ASGI API and static web UI server -- `pqc_agent_tools.py` - Local JSON CLI for agentic workflows -- `pqc_app.py` - Legacy Streamlit web application interface +- `pqc_agent_tools.py` - Local JSON CLI for automation workflows - `web/` - React frontend source for the custom UI - `package.json` / `vite.config.ts` - Frontend build configuration - `ui_helpers.py` - UI-safe filename helpers diff --git a/api_app.py b/api_app.py index 8d9826c..465d1d4 100644 --- a/api_app.py +++ b/api_app.py @@ -299,23 +299,53 @@ async def _read_upload_text(upload: UploadFile, max_bytes: int, label: str) -> s raise ApiError(400, "invalid_text", f"{label} must be a UTF-8 text file.") from exc +def _capability(available: bool, reason: str = "") -> dict[str, bool | str]: + return {"available": available, "reason": "" if available else reason} + + def _health_payload() -> dict[str, Any]: try: active_kem_component = core.resolve_kem_algorithm(cfg.KEM_ALG) - backend_ready = True - backend_message = "Post-quantum backend ready." + current_backend_ready = True except Exception as exc: active_kem_component = cfg.KEM_ALG - backend_ready = False - backend_message = ( + current_backend_ready = False + logger.warning("Post-quantum backend readiness check failed: %s", exc) + + try: + decrypt_ready = bool(core.available_decryption_kem_algorithms()) + except Exception as exc: + decrypt_ready = False + logger.warning("Decryption backend readiness check failed: %s", exc) + + capabilities = { + "inspect": _capability(True), + "generate": _capability( + current_backend_ready, + "ML-KEM-768 is unavailable for new key generation.", + ), + "encrypt": _capability( + current_backend_ready, + "ML-KEM-768 is unavailable for new encryption.", + ), + "decrypt": _capability( + decrypt_ready, + "No supported post-quantum decryption backend is available.", + ), + } + backend_message = ( + "Post-quantum backend ready." + if current_backend_ready + else ( "The ML-KEM backend is not ready, so new keys and ciphertexts cannot be created. " - "Compatible legacy archives may still be decryptable." + "Compatible encrypted archives may still be decryptable." ) - logger.warning("Post-quantum backend readiness check failed: %s", exc) + ) return { - "backendReady": backend_ready, + "backendReady": current_backend_ready, "backendMessage": backend_message, + "capabilities": capabilities, "formatVersion": cfg.FORMAT_VERSION, "kem": cfg.HYBRID_KEM_ALG, "kemComponent": active_kem_component, diff --git a/crypto_core.py b/crypto_core.py index 737dcb9..9c5aff1 100644 --- a/crypto_core.py +++ b/crypto_core.py @@ -220,6 +220,16 @@ def resolve_kem_algorithm(kem_alg: Optional[str] = None) -> str: ) +def available_decryption_kem_algorithms() -> Tuple[str, ...]: + """Return enabled, application-supported KEM identities in preference order.""" + enabled = set(_enabled_kem_mechanisms()) + return tuple( + candidate + for candidate in (cfg.KEM_ALG, *cfg.LEGACY_KEM_ALGS) + if candidate in enabled + ) + + def resolve_decryption_kem_algorithms(suite: str) -> Tuple[str, ...]: """Resolve exact KEM identities allowed to decrypt a key/container suite.""" if suite == cfg.HYBRID_KEM_ALG: @@ -229,8 +239,7 @@ def resolve_decryption_kem_algorithms(suite: str) -> Tuple[str, ...]: if suite != cfg.LEGACY_HYBRID_KEM_ALG: raise UnsupportedAlgorithmError(f"Unsupported key or container suite: {suite!r}") - enabled = set(_enabled_kem_mechanisms()) - candidates = tuple(candidate for candidate in (cfg.KEM_ALG, *cfg.LEGACY_KEM_ALGS) if candidate in enabled) + candidates = available_decryption_kem_algorithms() if candidates: return candidates raise CryptoDependencyError( diff --git a/docs/API.md b/docs/API.md index b6c27f9..0ea8946 100644 --- a/docs/API.md +++ b/docs/API.md @@ -39,6 +39,23 @@ The custom web UI is served by `api_app.py` on `127.0.0.1` by default. `GET /api When a browser sends an `Origin` header on a state-changing API request, the server only accepts local origins beginning with `http://127.0.0.1:` or `http://localhost:`. Requests without the local API token are rejected before route handlers parse uploaded files or form data. +### Health capability contract + +`GET /api/health` includes additive, operation-specific readiness information. New clients should use these capabilities to decide whether to enable each workflow: + +``` +{ + "capabilities": { + "inspect": { "available": true, "reason": "" }, + "generate": { "available": true, "reason": "" }, + "encrypt": { "available": true, "reason": "" }, + "decrypt": { "available": true, "reason": "" } + } +} +``` + +`backendReady` and `backendMessage` remain in the response for compatibility, while new clients use operation-specific capabilities. A capability `reason` is a safe user-facing summary of an unavailable operation; it is not a raw backend exception. The health response is marked `Cache-Control: no-store` and `Pragma: no-cache` because it includes the per-process local API token. + ### Agent JSON Contract Successful command output: diff --git a/docs/RELEASE_CHECKLIST.md b/docs/RELEASE_CHECKLIST.md index 9c96c51..f5283a1 100644 --- a/docs/RELEASE_CHECKLIST.md +++ b/docs/RELEASE_CHECKLIST.md @@ -26,8 +26,8 @@ Use this checklist before publishing a new release. python -m pip install -r requirements-dev.txt npm ci python -m black --check . -python -m flake8 api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py setup.py tests -python -m mypy api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py pqc_app.py ui_helpers.py tests +python -m flake8 api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py ui_helpers.py setup.py tests +python -m mypy api_app.py crypto_config.py crypto_core.py pqc_agent_tools.py ui_helpers.py tests ./test.sh --cov=crypto_core --cov=pqc_agent_tools --cov=ui_helpers --cov=api_app --cov-report=term-missing --cov-fail-under=80 npm run build npm run check diff --git a/docs/SCREENSHOTS.md b/docs/SCREENSHOTS.md index 29f7949..7acda34 100644 --- a/docs/SCREENSHOTS.md +++ b/docs/SCREENSHOTS.md @@ -1,31 +1,11 @@ # Application Screenshots -These screenshots show the custom local web UI. They were captured from the local app with native `liboqs` unavailable, so the backend readiness warning and disabled key generation or file processing controls are expected. +These screenshots show the current monochrome custom local web UI. The interface uses progressive disclosure: plain-language task guidance appears first, while suite, format, and key-policy information stays inside **Technical details** until it is needed. The desktop Encrypt capture shows format version 4 and the `ML-KEM-768+X25519-v2` hybrid suite; the mobile Inspect key capture shows responsive workflow navigation and public-key metadata only. ## Custom Web Encrypt Workflow -![Custom web encrypt workflow with backend readiness warning](screenshots/custom-web-encrypt-workflow.png) +![Custom web encrypt workflow with local engine ready and technical details expanded](screenshots/custom-web-encrypt-workflow.png) ## Custom Web Mobile Inspect ![Custom web mobile key inspection workflow](screenshots/custom-web-mobile-inspect.png) - -## Legacy Streamlit Reference - -The default `./start.sh` path serves the custom local web UI. These older screenshots remain as a reference for the legacy Streamlit interface available through `LEGACY_STREAMLIT=1 ./start.sh`. - -### Generate Keys - -![Legacy generate keys workflow with backend readiness warning](screenshots/generate-keys-backend-warning.jpg) - -### Encrypt File - -![Legacy encrypt file workflow](screenshots/encrypt-file-workflow.jpg) - -### Decrypt File - -![Legacy decrypt file workflow](screenshots/decrypt-file-workflow.jpg) - -### Key Utilities - -![Legacy key utilities workflow](screenshots/key-utilities-workflow.jpg) diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 08941fd..2c5a62b 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -76,7 +76,7 @@ The application is designed to protect against the following threats: - Legacy hybrid public keys are rejected for encryption and must be regenerated under the current suite. - The UI and core encryption path enforce a 100 MiB plaintext in-memory file limit; decryption accepts only the bounded encrypted-container size needed for header, KEM ciphertext, nonce, and tag overhead. - The local web API requires a per-process `X-Quantum-Encryptor-Token` for state-changing `/api/*` requests and rejects non-local browser origins when an `Origin` header is present. -- Download filenames are reduced to local filenames before being passed to Streamlit. +- Download filenames are reduced to local filenames before the API returns them to the browser. - Private-key password protection requires at least 16 characters, at least 5 unique characters, and rejects known weak values in the core, UI, and agent CLI. - Unencrypted private keys are rejected in the core, UI, and agent CLI. - The core module defines its own logger but leaves root logging configuration to application entry points. diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md index e0825b8..c70c3ab 100644 --- a/docs/THREAT_MODEL.md +++ b/docs/THREAT_MODEL.md @@ -15,7 +15,7 @@ Quantum Encryptor protects local files with post-quantum key encapsulation and a ## Trust Boundaries -- Streamlit uploads are untrusted user-controlled files. +- Browser uploads to the local web API are untrusted user-controlled files. - Agent CLI arguments and environment variables are untrusted automation inputs. - Public/private PEM files and `.pqc` files are attacker-controlled until parsed and authenticated. - Native `liboqs` and Python `cryptography` are trusted dependencies but may be unavailable or misconfigured. diff --git a/docs/screenshots/custom-web-encrypt-workflow.png b/docs/screenshots/custom-web-encrypt-workflow.png index 2b36c3dbda0eba28f0cd358a9197d3a49f41bd05..9a423ed3b85b59c02abca9078d0208584352d930 100644 GIT binary patch literal 94974 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

de{_(Jz0(zUwhqWs%5G!OMqM+TJ+XmiBf<1%>NG zYZQ!(mr~SmWnmsf(+UksM0Eg_9KskI@w|gR5b&R^zw5JO8T}kKkmF-QjPF0PzN^n? zc60(i?nC~rtM)CryH9CM!R!S6=PE238$Z!?xpy#Vm7MwB-TU2LIuKA-efZEAc?PHq zKiQ1mp3>K^x6NBn{$mm$_(ixRm*+4!=vV-NIg-VT`0-OjUJy-hDgW`C@Vl}|@WgKY z5e?_%la`Vd^;60U zgE5IiyB!6#XHgL`Vopyz`5lSI%zMf=Q-5Vc{oW9H<}zlzNCa|eWjTbYvjw}{yqR3} z0;=G)wCsHFMyyxtyxvjfxr?w|&Ib7rN-P*ma|B5Q2at;U5@_tt z4tz$st|@~@3R_HX$*t88Vn)=50PC=DYTqLaC~ZqsZnNAz;Uec*1vG9vmq&=R&^2L(Gpn#NAsa9db-crct3#WqJv@nE&X45+iAyV-TN+iqasF<&tG z5)24F|J0ugBntJK6;Em<%xVW<(PcZ{LR`}-1&)g{ftkk#GQBQG_ z99N2Y!N;`E-Mt&bp42LuF=QLXg5mPDTK!z9RWy(D9jn-LI7^RCcIQ%%3%f1;WRq}y zw|oi)Qpf8BQr??B^YeQ-n;JhP2bBX)bYuW)%O{dFe*%8`XC==WiMJi}Jo_w?UVR8X zwVx2ywzaW{TNXrT1TF6@Yh0g_JfN3ihd37v2Nk2K9y*?TDrZ0aTMOW6fNW2~eJUPf z=T0H2|8U?q24e-+-WnpU(O{ zrZKPcD3^4+_|j-9~lg{RveU}$CS?ws7*@>Lr_m+24aq;p8$LS}n+PdIq| z-a17OU}$Z*OeTdxf}BZYarBMWEjei^)yI$SJ*_Voy9F(QlTNK-FfOXAZ-(&Ifdb4uvK?0GM*vY-s7 zF`uEdr6`8$=G!eVfO;9okQnMGFN7Tl1!P{I(yVMdK@Y;ov-gAsfaScSQ$e5v_*Fm8oC){|E7q7eA7@eBFsg>00~KZZMXoEZt7sE5 ziaI}WKWG=hEIB*4GEm^Wp8V?JLu5Z&BnOq#ga~4}OC|ejRYAkOAaDCS81>WAqGqC0 zBk&8wo@QWC;K<)j={OsQ1DU;f*KxTLUUHP*3krn&N$nlxU^y7?$Q5;;I-+H4d5w{Y zk}J}uIN-1r`;jARIgdp|L?G7J^F1qd_QtELHCqeFg2`W%D6 zjS5bw5?koduu+qs>__BbZKGE%W4(+@C3MOde(BNMbr~Z!9zSE#Tb_A@5(I(r-Zg`6 z|32on{@&7vggfgv!V5{9$5=58VIOl(e^-}1+NH>ag=~8{#OonXgEoJn{bezH=Q$RX z7H_TI>4M8}2}(c&5o-CF+?4b4vpF}1?uolQ3J9G}x}2rG9{AGgJ<1R$7eP_u%I}iE z{o7_^0%YUsWYa?r9zKYle_?#zxhHpT2%Bd&=4Mr;8xr4dT8+ECZcdH!=>_Y9;K{xW z2Q-&c?VFe8u;2@AG^<&Um4Qqrt-5{qL~yKYvs9e4)SKPbb4|7+&8qR%#?xG!ueL+T`;c8E7v+se7Oi=fyg~bRMTC9 zQ1K!-AMeDRGUoFfG#VucFX6w?!}zEQW7ccIGgsdoxZTGQbyCc}1hGNel*zl86B}y| z#Z?cH$w3s`CMYN%5OKz8<4MwIS`Q(!o-38c!iefSUTHV#^B=B6&}I_&Ba}~NXcN<9 zdWJ5@U+U|+2jGUP>gBPHTuPA9%vGea>|i7@7oJ zWsm(j4lywqo15DW|8$~1LBnHsO`lP9Bq7HThBU)+qdkO+n)*2LSWL(+6^DPgl|EVF zaBCoKbp1$|gr3d=kto<@5nFw3Xy9*HH8l5>cb?POAp$F?H_&N=KoR&jnldQ_^ z0=I)j4l5QTRqlm4`PrR{Un>gx;FLw21@(~yy-x0OHO0bnMzi`zkE%wfBS>kw<1ImH%IIAK2&EIk*UVOfZtIW#yP0{PJ9?Ms5-aNHqfMF-2iUT%yiIyf6j2#434negM z;j^n2*hfcp*lsk`I!B}1`8L|Fvg zz`!n~7|M6aK?^_`VzW@C6+-nUR!qI9|D1v z$p=lZESbG~_nJEck%kLYp}R!{h<` znVgLx;& zRC0cg;9r;77%An1Q#r>w*_i=rX7urNzt7`C=v(UF2t+7J0||vZ2#>Jj=7}skoD~E}|oD0YCp?k*0->4Wry_HQN{PWJge&1T6|3;}*>sdOU ziO?N8_we2O#t%=6z4L#du{k@It`WjCxF%877Yljot_eTMpCN|Dp@SueyV zaH%bcgO~&uZ{ObJEMto%;2s$*4OjZqy}95;hNJ?k?3w1+BYceP@8V({3O*8)J5VMh z#dLhoxyq?|NmkdzC1R#C<0ceF4Glq4=K>XE6CvBAkUvfwk!n=4;JoWO?rmwJVHR;M^)Th1vtAuDQ8ox>S z<#0t^+PXf3+fxa)RGVMDShJ^av#m+Dd(11fN}V4H7FT+oOw%r-RZ3Hxr_TFm`=i^E zdu#6VnY6FHy}!k;VynM>GRmJ#>G7O7^N1B#4x9!Q&R=GC!;~ElrKTqC)Vf^4WnH7W ziKeSawg94{GSRrl#*T(?Gc7JGy!nuND+`XhTsj7q^|9#1a`>yv6T&BJw_?mw#uj6Iuro&Kl0|Hl`F1W4(Ci+OohY`!fY;1CUPP2$iR_Y8n znl~$-+@s?*(8YM(gEQn1$&dcR)m-37~_;-prM<<_QMd`?aq z>cj%_nSnAoK65w`70@3e?hZjL6Zqc`^hLAon*N=<4YoEm3GzQjM!q}|mMXSCH23+S zCql%V_YP&Bx(b?LTbC#k=>eHeFh>|npI;HEd$sBJ&n?_xF=AHk6RIN@*GD5HCyu^4J|wydb&qgIKdqtp7gJr;Z(P%I2b0YO#gp4xPOQs3K}yN4f-t^kJO`tUu_g4P;@ew~v8Hok4wk7KgC9SGxy6&@ zU~PAHWsrwiH|i5GY;;iN;}&25&5^DRB8@zRDN2pJfhwpCu&XOb-C+gAY-EkzMGcSC?#! zrDbk^oVs$QUnA6Fu>2#syKl*mbyCz2tt3rE`T3ui%u`ZOD1YOdg3kep%-UT>;zLp5 z`x3vwCm+3(@?JO|!iAXfNbm03@lMNW6k7cJohs*rW5s3WUI!S0SQYsRs|B#^z5aq)tvw+5_W(Ah+~CHH8Ooqv*Cm z|AI#0WoXI@uK1rdr+q6eNm_F4wiVy-boU}>YMAoSWLKna<&uoOeMxaRk-XNp;~xeE zGHwmVDloNaPga>N-|_J&wP|;@&ixC-{c5m;#~wP@RsGnNg@+FxA|4WbXie`oG44eh zk6tyv4#zZD>nTL^cC~u~ZEbg}@CCSb-`JhZec^)6ELbVO)%OM5j6y;hJRn58W|jM- z;HZW9sb%yL2ZS3V)?dg<&Z4oo16vZzDRFtHr*~<3^}{=oSdf+%y(ikd)7o#} zx}Ny+B4vR+eDbHoe=xTXKun}e5ju!lWX{BUWB1KwHSTpiVDZz^%hgT+13 zLt;7pHGHI=J}oJ@s8{v+GLJbdtHn#aUZRJ%$jDDl#qa4jV87N{^vFvRw&ho%ualp9 z8yTa!zLZKq`*WbIsBYoOf%PbHQ7#?M(>=MH;+0cti=n*D% z(}Vg}S1pDo+FpTsp93Jk%WAb05=U0-4({iz8(r@DVH5z@ofWhZ`W(VBl;7eb# z+@Y)n*?m7v zrk3XX-{;vGuqU%Cb2Ms{l$4Z-kugvUi-D)V$3;?Ix`uf!B^_(V1(@c#Vb6@e_ueB~ zC0CBfy}9C~GUj2K)zTE5@My2uA>+OzrCJa-QBiqal-1G-Zzg{`24`&;s16!LJ`vC6 z1d@0cUp+z=c?{L^jX;MC4zZh9H~M>b_{v~Jm|F>~369>Dle4h+5dT%wZu}|#%hNO` zPa-0nd&O)G0v^W+Dk_CF#8PWD@6u8&>|02lnd*PhO#Z@z6`N|8E9uH^>s0$iEX|7E zf&3^SKvDkEsVgQJrNj+J7c;hmzkT!OTX@hdb(Z(h(ddZ9LT*g{72}8Oi_oD}y8p2D zA3rNr=MC=}CT6-gHDXvp451+#r3Mw~`H%nO#_j%=gOfA8_?eB|&LYCH#5b${5HrQ% zLc64uhC>Qk#|Fp8wTGM^2_Kye$oBJl(&@xp(ri6`3+TPoDA>jHeYglbcjckDu`$`Y42Hk+Pk>K!s$7QRt{?18Oi%@I&WN8w_1_ddUP^f1(Keyrm*d8e z9vMe*J)Dx*(sKNksP6cOK8FNI<_xneA7cAcO7pu$|Lxi(^Y%$Y2|mRj_uT)p*N}y& z-rz&dT%tOUWTo);Z^T2&OZl6j_zwxYfS6MD{pSlLq@{UBMn1e23o3N{t&=gatIOs) zOtaLp&VtXImzM|oxgR}w@u^6Ja~|Asp(t8($ALpu!xRvVKBPp z0{@Y5i0=kH^xyPkTa3%EK0Cm}#|`)){^R%Wcd;%?@WFK4ALQ8f@INnseZ9_H;nM#Y z-(UL#h-6SARQ+QSU9Li0qO?_f0+|FosSmBw=-5bp5uY`N0GN_R1aH@@ygCyKh%Ht$ zb#M=mVk*U*h3C3f8)><@k4W()^cDt6fSuwKAvCJVPn_7!`To;k;7$>JGNt%H&J5Zt zewkcgyWWqP32=2bwz`4`TyzM$uw5jYh8WNExmAg9NqM6ExYMTO^tJi>_wSPxBBclO zA%rQn``@>jNKjYO6lRie94Iu6Pl(IUx8Ht9fBURkPlC=)`1s_dnWl$pLRW<~_Qbi# zc!Nt?e_dU+p$`YqLfQ(rIY2A==%@mDA|0G`5kChI$Yt}=Bq7iQ^kB>AcVRykXWG!W zq=Hf1mi#(wdwPiD!h2QB!c1VPI zWMEKUJmigO+5<0+^`x3GVW!q)eXLpe1s++sJXmsra|U8lHe-|{)aVtSV*^FY-@3aq zv0y{CxY%xXi_Xbz2VF&uhmP}ij$P0HKE&`BTYiy=Sl}W1{rl!kdRS#>6;za!`UO#^PnL1sT zMXUG?%{uDBAU4fJw^=J^`qsYAO#Py159i~@wlYViyXF^vbQpC-h437vq_i8WTLqDx zmBjsu0rd{j?8ld{?-1J=e*d-nq&?!d{%XCpV^*`gc7|1sYeV@C7m#ApwU_fUGpF0K zLZAG>b$cyax3ZX_shoV<-QE2?m%fzG$#pB=Gv1k1U%u!yv+6Rw$afR%ZJf|_wVECJ#;UB|MDp7D`$uND8cc&-=8!Ey08#)Qca*q^EjRG)b1Ql zv#PeX(F#frHFfm}VY?wbL}q4b>9;~&$70z>BqfJl|29N~OB<`6d1eC_xVZclKK6eU zk-pj0b3s?jPi%+~m~1!eQFEYH!%AKa< zj_O|ZUGBPnwV4aRR!~u0q-!nyxxDV%aqZ2p+yaZ)arFFIlE{8%Y_D<5>F%) zla*sZ>A=XE@BpK&i$={Kz~Lq%dH-7Hwfwz54J}CA_XvGF72RBrlaW#CFyBsZLMvpi z_p{JT;a=x^t=ay*WaU&E3Ys&Tszy5f#dI;t9G)@hg7+uHCa1RNhB>{cc`dA1GR+4r z+pS1aWjU!QeTPNy^KD}37hELe%*&({&|tt}e0!JLAQt)9)n zTcg2@9!_ThVa!vcJ5I|R;4t*`bo0^R)>CJ`Hx{)>{xv*HcPCldtNi`niz&Nu8Y46Z zN`)Ekz2S8-`}^+?G9t?w@niLGTT|pWTPL$Th*v!46Bb!KIQ}jyvZF}Fu6keT`V7-v zIlWBz&ugk{+i1RLZ*Je=IxEh{V%)FpYpeiulTwX&v54dW4MO6F591p02l)ahpzce$H3dcxbv{o`4;;Y>kZ4`7p#z zD6tf`s}Z|<_imyBV~j>_O1#jIbW&*XORW~)J~?M#V6Z&%wEA7-RnpdU?aJfG033)^lk^yJ;IS?X-tlwJ#_Zf|YC(yzpXnc^qsYL1*!%6u}N zRS;58*aWx!8W~WNe;?1b(#>a9_qG4{Q&s*Z-VaXhFLx`iW`+H|!WagU1KD zS&`S>4*utG5qgRiG&MC|ie?%>q^^e54s{!%eY`Zl$)K0_Xgfn6-8y|WJeDba){C{! ze>cmzBFoU2Bb;Gm4=z*jCN2MLxlQY5$EH=RQP?u|lJnK^yPfY#N>=V@!u{kQ??BBU z;f&l|TH&duevH!0+q(pIInWANJsFbWr_T`MZfBq<|P zv#mVSTVNu0K#6O1X)RCd8O*{z3;UKRZQV#G*wedi?`M_@X^tK3YH1O!-FGKbajy%M zw#@sF>rqf$0cVM7PVe!n{xUj_Fg;1~{SxgMx|ugcP1c9zacCC$RTldBboOlPEAE@z z!*teQ$rV}YU6?1z;rRIYWY3or)k4*0rd`JtDatqiEmcg_h#dXFm%u8zj>ty%VP1?? zVf30mmPJ>1gf|;?*qU3i4nzr9hz-=87LW}Sc(9=dtA;+&>)!TUR)02YMr_t^lr_jG z5L{v${0Hf4UmiZAM|XlJLj9a_ac6{n-yK@Q(z)$y=h8z`V?`kai{K`h^)3WQs<&l` zl8`(lef;Xm)%k$Z`_WsfX(B=Tthj@mykvZ0;?!l2ORAYM zp{c1q`-(ygk0o4HYfV>?&_ti0+*DL-GkD~PKlTGP$4Gw01REUhgyEYv!p{h=y1SoZ zoR4u=@O4X2PPKYUHkx@q+h)@5@LxBsS#1`&>FFu15=H~cFu*)dO1l2)m5r?@_|iy0 zI0`}A^!1^;{_sFVfrI*w8Rp$ou#A+k4iR zpk?pia7{uYnHMbnk=+4(%J`CdiC>Z*6FHv2y?ag^?a7@bETs)jPHwe_-iEOK2qmR< zvNCyyjEsyB_O|x_Fzd?H9jQ75aT0OkL&gisma|^y+4;=7PJ3dxMt78hf4Fc2t9&y% zss+Rt?8cpXP1D~$N_{bb=|W}XV+k5hekl(6o|i9P2s@A5@jP~u^ni1JOD+AvObMVF zNBev_e)~Ia)~anVn2dcId3BFQsa0E^Bd=}wbEaH}`3C||I<&&_&9@_CzI;(mecRL3 zRex~n!nVZP^Wb|wyeY5m_dOcx0#hxAlZ2#=gw*`PLYd>DQ*|Nphxrtj5*a2XpPRjJ z@4aC^@<7#2Ty5 zF*5?gK3DG)+UR$ro$UE>0LwH-^9I_r3ar?rxgBVXJp5|oY&SMI%sW36nD!_euVZT{ zr)uUCD6D5lxK(5tZ!|V4EB4q;n{~%vyPPIP-z4pT^Sb5%iTiRQwo~_quajfxj??0F z5bxl5`$JoAd?RNRXw9z$g$};Nh8*=b>KK7zM;k|>t*-0Zq{`-pL{!I(RP?I?(mTi) z&CSgr#N7SukEY+F zSb1{v#Yoc-);rdQn=uz!?>KXYb|n9$O$D9Mb4A*m3Z@$;2!Hc`HSX_G3a`@Dzu;g# zYN>nDAu-}qpB!QNI~~BcXnU?7xR8*iN(FITc*Q@WRwrA9ws5n3%^nA0UMRv{_W#eQp=^F!3~9+$>cQc z$ju1}nM7g~7OJ_?JT#;=HbvQSl-$qe`jRLYm+{&wpEiM8x5TxMU-(jAuLQr?a}qvb zcd`twE**vcv+0U@JAffvO^r+&eL1-ge~^eh{QR$v_s!jW+&NuHH%)sPj=zhx z?d=bGI{}q=N_WBQP1LQo)7RVkfMG*;nPp$u&Cnn?;QKuvFMs%16*2~2W8Z^kZpz#w z=1LUeJS#KXBCk9>Z)4H=o!mnfVuJs~@-7;^g{r1uf$-5^uR?{4-o;R>=iZlzZ%wD0&_Bo2hGb9fubsL9Rnl``Wv(pa6PNoo1%s{(Ls$?il$>Z_~0BtEJ8LA>&az z3T4*IGY3UCqHe)g0wy+vHj@f4#_TX(;Z)1!5fG^OU}_3f1t&E9DvRzz>B^Z^2(PBNf-*LQu#%_|ZkKW_PO{0-7FIvh{)sja-@0)!* zxNp?l@v9LDyzb+8L3$Ye-EiuJev#=;dprM1N$KL-abmZn!Bf21mHLw}LLk*b_31$j4Sp^f215Po$d730iTJ9kN{ zChL2~9XPNAK=*Ziq)CUjKa-dLYW%GT?B}@GnoxR;NvhOkt*gVhMz^Y-eO`a>pMN$t z?mbX&u5qe1kW`=!-l$STy{kkQdXg z(&9k5jJ!mEYcX_w_vQ`5=&#}H4vvMvoZ3rZf7nIa&CVR=b1oYkhqYprUaA`Jo&yuC zeOn-`>ZiX82w3P}@QHO1xAT4x!*uxhlc#-feX>I)d9^GWIC%9~$yPV37ghVf2c4`! z<-2#I*!*m+KDgQ(1XkO!Xw^G5)n?P0k-bMtSl@}b+^VKiX zXu-9;d1&Gd(nasC07`CQv(Za^TE^BC0d9%d<=^@5ceJ$se))QAOIjQ?7F3vEqA)f1 z)(0x+6TE$Yh1yb@**iFnC>Q9xIGmA@VO)3`Rm6Nv44;(@-xo|1T5Yc0AIOjnuXS`# zQ&p8xuo%B}Z&HD=gf$>oLeAp3S#)^W>_*#~KF}aTcmMwV%=;B} zb<<%+=EdjlKKB##+ofMX!6=^RKW1Pc&>sBe?8S>5XTD!{b}mlonO)Ull*(uM?@y!%DYFmf*|Y5ygpZGJz?Od_<(_@_C-kyXW8yRg4+c%|r_8(gx0Yo)Gi8mUZm#l{ z{Mgdsf{Mo@P&$aka=qc?IfhN&+=TtIIaTt%zE`}Yu*}ZNQX(*&IrFJH@i`I{j43Wv z7T9O7Ihox1=zOF|QV+PyLdmO@|N{Y+SsLeBZ^ z!+E}rV5k@Nn;h$~omE1t4jd=-^_Aj4+5(CiuyM|y(@LI6oR8V)&CHtj@0vBc{(}`5 zR#=cuSYdc`C*Q&nwWG+70rC=+QfC25O2f_01hYbJu2u^sb3YrPInp9g#HaLp6*JEh zq>lHexWUv!^izBAfP>@0lS_)%6cr5`%kDCo+seN!i!Gkqe z_W1-2$@?9$LRAU&lNCCo2WUZ2F>25D&B*u_lqzULZlE>S9OZCCdY@;)#KZ$rb$wOo zKRnO*SJH{PHusgtcu}?K-o4AAT@ciB7K7GH=(UF{y`U_R^N6bQU}Iz3;Lz_+)cZ2` zQ7LJKO*>->f+S;o6_wzdTS^*r996TK5d3uSCpCP0w`Sw}t2Jh|u8i)Ad z_hGun?ptrK%<8gcp$#JxK|MtqKy1ucNV82_q_mR7J%h%S%b;^qVp+ct#x)aL8^95( z=dEU?20=^tZ`=Wp?!EFO2f0{&eT30*oBug55&7__`d zrH*lE(8Lw(dvQr2ameAX|I~OP?9V*<*T;HhTURmC%sro%pjqTmDE~qc^&6y842xR1 zlPBCx?BLlg*YM_UWjj}tk-uBoP5*y{q$%gt)k2 z`tXP%6wSBX)cx6}fBpoR%5XxSP+3#c+}X(>BGPXGGq)F1-aN*4$^hKVk8Pg%_%J&9 zs$BZ@v3B`azC9XI{Q8x_vi@z$V}{^GFEA*!z?J`ppztDBs8}t*jJ?d14dwkkSUDPNbG>Prp8Y5P2B(fgFO7b@Y7qsGeVtMzw6$R$J5=yM{5R#dT z|Mf4#r-T@y$vA-hlUs1!eyikv>)%)ajv0x4AyzN}{YxjIBG#Bx-;$K9Sy@@}W`pPa z(&?~ah3q|X!u)>6>C=3g?>teklF0g6|GGX36q0Sy$zdg_=9u z+^!lAgTM@NzX&;0IKOKq(%qooke)5udl5U;5(7uv9Rmiwo0RlxjN%zn! z9kXaW{zznSDh)Cs_qI4NyO%0@kDO3rb+K4C69 z=fkX>b|3ov8b=43OU^uJ&noZ8_K;2@5z}R8;&+_3m$UegXSaGroMxuKgb!YYcFSCu z6Se831waD7?2Qi5^OHRL`)~82s~?|5RQoVP_Px(d)p^-0;g5U%zF}cue^5yE_xHQH zx)O^560vpSjU&G95f^?CU*Cj?4wrbnclgiUB{JFYavy{9&hJ+}{op_U@>b$MEy2I& zWdHq*zU=`l(jv<2c6EKpv^&=*&@K#JaH3+h`l>9iQSS$btg~I?c<{(+=8FAqA7XT? zj0&#Yckiv2>rvm5b0}n|y^hb^*>Q@LJ|{B431qjm!gs%pAa>g zl1{2ofF|lx#8!Kr9!dG_`TA+jl+@HVE36H?H&Mb_`tB$#ZKP1#c;N#){6kA8i>#9W zHa8!Lk)+4=1gz;`@sYe#h+PzS%3NPck&@!lSX(uuJH|f6V=&E{ z>F6yOC&ZnkoH{)@RO-JiZ^1so;c6NQiD%1O%eh#}6Q``K$_!Wxxm8oR&nEQHq3k})WoGOH8+W;` zCrz2+n=FJ+92zS>ejSM?KETez`&Iwvfdi|iZECA7MH&L>%Iu+Tb6Z86J~Zh3H`(r zR_`5nhqJBCeg6C%_NrvCr9vUSo}iS}IyLDLb%>m*HCZL^!PZW1vZFOb@ASKWR=Y27 z4>-;%0ehO{7V&=m{J2np+ibru+JDkLyNmMqeP~uc!JIjWP1WrFeJ(wVZRoCK-mDla zD%zO+EL)noCdp^e816LmC_;wHwHe9C(2cwC#s%>B13R4S-UO$Y5!Ceb0>FTLElP|U zCw%4Q#~ZZ+9@$h}ePk|mP_8f<;*DU}F=@^N^9u_%WMp71-kDy;ar;N@MzA*3%#7Cc zOUWJS>y7VtC0upscnMEoIF@ec%KD@9lK!X6(Xz#ft#>&&N;q6}ZfoL6)h`Lwo87k5 zd8R$*Mj@TU^5@p}_9Z;zSn1ISV_t^t#!%OkUfz=j>sG@@S(RbTOlC!HDU zVKl;PvE4bwptm9`>ooMva&NsgobVB^QAkxupRuZvl$2awqSMHo&J)rq_m6L2U^r_t z*(<-+4CeYvjwb%FpRGHULfhHNcY2%k6*2pqslVldF-C`ZRjIz4U0r>>VdI)}ZTrbJ z1JU(`oenzVb*mgsx2-fd%Y^Q3JW;`u&7H?#E-`=h$l21M%ARlv-C#zgWN6V4CzD`;-lI|IdoE?2v z+`LOiMTIgX>+Wh2M%mJ^2k`P|@&V7~j@gdN{0w?VHNVdR9ok{KE0X>P{oXphE3>%3 zA)=*~tq?197}3dnW0*^Y4@a z$;jS_57e!t8ssH0GZKx${#(efkN(ERXPv17$^r-ifYE4yN z$AHVg=(Zah_zs7ctA#!c+u>Y0be&dNW^fN>*>2wK7$g{L>G&w5cy zoa!?AGjKI9KfD71Wl4s}g)UDL9qc@-D_w_PxJc62$(Nk%>uq7_|tO^~AS_1Uc3l zw?BLMDAp1R1^7Dw$!0lPT}GN5ap;&Sfj3EYhNTnf`raegE5CfX6?Rec(W~D6Fkz=< z>5Hc)We^Ip;=J@dCA?`=Xtn#z2Uhn{qOtigHkNeYc5}87z2uQN+3hOPQ*vkZTl$J@ z<(E%Kg!)^=*rm@9UMR?p_}XnJr3g!w$vfpb37rnH;U+9zq8Z(rKbuXUWHl>F;dnDyir1RLAUI>Kme z;*LsUTe0u@Oy53#a)BZW7246du7SosUWb=0yvCw?U%O4rdeFkd#=?(o$+}4C*|TRw z42Pz~Y3|Mx?-o#=Pt`IVYAn;B@IxQ}n!T@8E^t$+_h~h)FDxtQ4IyO<4F$PUh4aT2UYHN}> zbJln7`juKr?nu)rhzp_AX*Dcr48CH~gW#;_9br?L#{*HCp@_gqs@ z$ZU1^^)zzIh_j$X5D5m&95TGWS(*QBU*Ivy1XLuIjIr0<`ZQ+DwI7TfJLW<6B0xyH znXRs_u77=?CvzM_-5YK@q&qlHj;6XT=H%(Oa21$ue}vibgUR00>n|>XIDc5{Nk2J8 zRubD=E+_+hU5*eQOr&f1o}UTr(zcoE^d?rDBXq?2{?&qfM@rWz%^6t5(Foap+4gY5 zu*pqpCE2l7VKTkDt4oq{Va;~iadC=*Q%gp8Z&Z}sQ;aD&HFLS7O_Y+AOD*Z=*$#qM z%F3EtUVdsbiXjYxzC_3m6Uc_SNc{uVSmjXl-!dOkQ`38Jgq77m086j~4<_#n3yT zl7Vvt#o1e4)9KO4UxOcaZo8Kwmyal~hMJGBt|^-jq}jqk2CG;Ddy42s!-^jGP_5ow ze_+aR?|kt?>0{M}H3X}~j;j2E0xFLB;h!zsTx-G<1(w3rh9lz2=6dP{R*a0+JYFVJ zA~G)PyriVhmgC$KMB}gDQB|+@j4mB}$#KEA_$pV}baLgFuQl^uZ>pQLB{ij)nh5k4 zr{D6+Ylf619A+2p&cn$&N$xd5AH#6(__wn31x>6AVGpab8*q?5Iq_@0QDkGF$Xq(? z2$O8J?055$RpT6EC92kRK?j1p_JDC$s2|;sI*&Qak6WQ@g$s&p@>dpbg$sdpood!- zyR={dps+Dm+gUNsELG?M8~=!bL8zwSsQv1T`1ofVj+~NTFj0z$DBCVS9fCH89Tt_| zCwl@H3GcWZ9_hGD4iIY=slZ}JHX;IC=JvN)PhW{s`a-gH7}sU0V0tQ%`ybTzs*G9& zu&O9u+FpBx0nSh}uSvVKoBGuKF2ZwX26|y#;K9Jw8$}1ywX%ErPg-IdkZNn(&021^ z80x+vyPqBDc0qg0CuTI8XIJ|Pmk>)bUz%B{mJ|<&SaOd9p_S7k^E(zM6j;D*Ubgu5 z%NaZr)I1*|7*6653zRs)_aFv3ml@%84NZ;Kj>^80>^f2GCj$JAj2fi!wWp|f`tkiA zgOT(OJc|{Ap? za;>gFzt;6fe~ITMjjCAb;L$~ST8ZJW_~x4#$tI%rF6iCj>}OGk?|Q#zH!#C|2%>qY}}SqFd_wrOYOtpc%#U+W8DP!E0Qd3D@}${ z9L?MZ3Cr{;nniI@MVe_stpez`)*Z+4;8&HImj}ek^BVQbnf>0{l$`!{s@0kr8XKTZ zF_>XgqY*^CSNaK$&c?kQ8gRKKO1=)x6yrYm=mm@hS&0n|0YM!fk0;sv)Uo+8Ea8_{ z57NakQSWbmpQN1g68(_<{K?4)XpIws*+;%sC*B~Uq?O%rHf3K8PwdbeY8*)2F!gf0 z+A@8!+U*s*oXKZzB{7LE!ZuESV4J4;A;=z6oNw(P;IhcLnI{!f=~n8W ztiMn9R~4D+$c0iP@0%4nJ(D*Qu zRcWLo?X0|Oe<|CGMtaf1KAvz9CK1{v!^TG7b-pAwN5QH*y|pQ!?R^q3U#(vwE?Z!l`B`k z#HA23AtGziKrH(D`eyrzAVVV}%Ns{VDi1F%ke^dmQ&Ud4bAg%pM%XT%C&bY!H>&D) zVPT^ZM~N!OIZjC_DL+nXSi%!3uKos@NU|@NaE-!9?l)*9Q)*R3c@QM$-QNxX-TAg> z)$h=;V;F{!2pz?rD0O9ae?Tlf_F(G~YE%&Xh+|gSr_R4_V5=bK>3@T7_|p3gfDVOo zt*+@1v9^EEx>GwOV0J+Kaukqyf{(}Qe*O2`RrxUC0uVpKZ3b;oFgd91CgD#zfJhGH zT@k+{{LJdwY3(Z%V)R6w2l4ga@gw4Y`9HXCbH_0NEzqlu%IkN$N>o0CGsb~M=MD=w zSl{U{`X8jdHq(>0{Vnn{OrdN19oK*IVNENOkAAK4u3ftT4U?2-5e1TDDO;Nn=sxp@ z-d%pYhk=2?=12SdS8}(}7dNgo=bDB>)ARcEU&J$LZ(#9)jD*4hj{69Z0(LXb3JQKQ zxESeoGGrVSYJ*beekCfWs@22$@SmT@B@)}gRB%0A%LR%8#*bg1kJ0l6TI_p9JZA9w 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�eW{Pv;>x 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 literal 136505 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 e^QU$ScG8dV;CneQ@(C*y#$QS)NAs** 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 z zyGs!og7(DpuTP5S$GQ|%N<)c3A{0H%`wss%a@uE0_5Fak*P+^Tzzh2S=ApP1oxdWm z4Z`WbD>KunQhUH+xUaK+)JL7aK_J$7zzF=?jNUtc1sWY?1Ljk}2vsf1`ob((Dm}p0 z7zLs-nt(OD&e8Fjpn}RCBPF;dbA)%F#Q??QTEmNIK&ij#zUAP}_F#%tRxr$!oAdb<8 zY@H8m?RSbxT^-HoW)Go&PdAsQ#0bVxfgL zU$Y38IxUg4ruq{7y$-P{UnM4*EX_}rhowkvUD(fU(oo!;e!{gZBV+sk-JTJ|5*G&G zo-vWjV==`E_PDo5L3(B6!H_BIu$XTQrxgV8PFWAu8U;n_v?j>N$daA!g#C!?i{Fu7 zUVP7~Rf`tuX0Tn{Urcp&gsiqhhE^69<4=XMUlv4#)u~1DT|ZzRf|TIxhbuv&eV@tH z3Tl`3MVX9^z%I0Pd?@{9{#5ODkv$J{mklu?s@mgJ=Xo6??|l{~2Aqr;do(O|CI+I# z8H*p~l^!Y%M|b`{+53$c!g&+9oOP~67f0K&(h5IOEiLNJzBb^eLEs9S4fq=+CF{&( z)zt~>L=}gZfySZ{w++vo|HddjoLB6s$)ArIZt-^a!}JKKlL~~UPOaiD{~L<$LRleV z`|Hbd)E;|x#o5sBb@x|WHMGmTq@fVcr6T1$>?D+gUfp?hrHb0ir0e@Z31WXdyc?pf zemq)R<*un%c$jvn5Ay8>9$uJooQtjF>~zyY;6>*`1?E)?Ka3|_pjrAUBWS(^b1wpY ze|60HwJ!$!>q>EOZ75vUdBoXdHX@W7hp7`!?LZ>*VtK!zlAfMQp|cC8($y8|0lu;$ zwMMQ7R3)a`qp=0DVz;0M{qN?Ye*WajV^pV7;68T?Sk-Uonl|5J>CEy*B@sGV501@M zZ*ib3?p%&wKh;{@Ts~dj;JmY;eb!^LrP464y|X)6um1;OwAWK))trm*E~d2fceC}= z*hkUVh&^c40xhg> ze|;g_c>oq-yFL@i;t;((huo9Trk2RSE(leGyk3OAhZ@c<;p^b4HEO~u(xRsNl4W0h zb|R~AU9F%KayrK%3Y2}j((QD#Xn(%!r>0VUdA#slEb%unTg2nOdsCmNJj|BTXVCj% z+Us)c;%2-SjOM1W6jo-Z$Wv4EtF0v@o<%#Y5BZh=%dx!Ja}mSSOMe%J2TjKn<_Y6X z1?%MU6i;i-GBA4*c=CNR=H~uP18|g9=XpFtYxFHLjYW-oC1}c+P402Q6((M;PtoT7 zJO}W6yH@QMigfEeFD3=1T=dgSEGY&q+(+0<$XAeB75B#AQS`x7B_`+G=D=rq`u3}m zs)H8S_$PsTP#A&}?wfG4dyP^oHenuNAAOg*V~hd$gGg1dOxXDsQsJL z@7k_^R`uv88c=Wcw?R=kzVlRbGn)i5Cg?4y$*)7pIPGoxVTUA#S$ z2kFzYovxtc-=w^39@^7zNvsiTbuI2_tMD20B<;yPho>MO0FDll9{u-)1thP*YQwS| zHD&2Go)VMIMCJS!g6W4N4Sl04QILAkN{i;1J>%vsC9H}cExG}1FHNRPpp-oM?&^=h z2)?=+K?(;RvO@n#es*3)c6MHVCMoA>>G2+|GFl9pQZ(~Nm^>$w0UJFl?e+V6#oLRu`|XN-q~Ul}Iu z^95FnuqDFXJ8JpA3tu*azJ+e)Y_4lVg(tJU<7sI=yt0?-b^B5Ly2-c)lU1H~qZb8A zMf|w`Y@S3|T-Z4}qInl2@V=!Rk0o~CI$Zt(fu7%-7WQz&n&R7jCSXS(p2WYh9uww` zWjI**Nv&@aD}t)L#OBPLz=dCZ7geDf!03Xim|v^9)!+1%1`*7AzI`B7yeR5@{@B&P zCdrqvPDps#+k@&D7^~rE`3w7!HR*155#j`X<#G0Z$CMAVnP4FxaA{gsfnT1hoF|t8 zo)vIVvC&3V+}gO)B2Zoqv`Y9XEvpU=(DS51tgcQ)&0DOK=<5~mi_YH8$cPZLiTb*_ zIxkh{L(mi(_1~ zIWxs`gDMt$=b+b0u1c<4^6uo2q+EhnG6cFCvZ_2a`BW)&YrLi}ADHxcJW^EOXf^vS z=(M&wfVDMMJApmwRl^zbQ+5J)OYLY~t%B3}YeEM_47!%D?4D5{KW5{&4_60DU0*%XFNFWLvYV`fin)UlS zd+l5ttcGi)qY7!}mUc)!@tXU49kmAOrPkQysP+U0Q|Vj8o==xg%=(zu7pE6h9Dxcf z;SSK zJsCR(MCX9R z+AEjJeVhsNsS?lvAR#s-6+*wym)+R+i+Xx@Z;w=ngQNFdVsdgpr3`SHerruz=DA!` zq*Lj5FoHDQ(Rz|*L(sFFzKMxpoA?|$3lC)Xc;m72$1Wof05Gpo>HtaM)>ty92y_KW zP_JIKS`mrVB)a%~L!uXR^L{9*-yCY87l1Z4Jlq2s-0<-1kMvOA_|T|3tqTy$!`-2r z?U7N@a|%KVThv-iczF0SyQZAiTx-0?5g-%c<^dOfF}-`_)LP2w>KVp8k5is79sDbd{+ViI@qLo?;-ce zA(hlL7*2fF2p%RTEc4*dP(>?~DBU_N{Cn}q$*9e6es$!Qe|-;)fM@m$i99}qkUGB4 z1Z*A6LVy1(KCRgKR^+8=j=Q{&v8Q_Tj{Kvu%*dX z=FQ@tA8n1T7tv+^7guK;7FFAYd!!o#X(>@qTIm)kl~O@KI;1-X7?_c6P)X?!>5|T& zk?!u!nW1xF&h~xZ@0{y8f6t}N?EUPupS7O*{@tgA3>ZKH1_|>uHth*DcRNNMp;=T# zVipwR={zlZSA#<>L$dTR@7H6ruw_Es0L(U_A7VU_aR1h#2JhDVn$Mtqs!(BE7VG-u zOMDt}XsQHy{lXBCqR6iYpRL?d?F;8V&LgE2Ccx|(`%q(qEG6d(wzU|?7y7!4*4M98 zymZy*R$7kQ9dXS+Tn$Tmb9s^W!|1l!scQ;K1G1X7nJD)IpECn74Ji9Yvgq)JTBoHL zIj^=K4wlv-vC; zG&nHu9bOiiZFKbVRIkywr#N*Xf&&y1j4dVRu+d{QNRfE8Tp25v!tmmru-oQ zU`XjF*kWP7d`b*$lciifmsMz{6=}!gBb?-NOwEc zDz1@fvJIpFt|}p6Xqe@%&aSSjtB#(C$ZZNLLqIQ*Fn<_r%ZF13fm+pHC>C)krsDl6TgfWwB+^NZX}*aPHFlzqCZBH z%da1$Jx;aIV7U7?73oJ{Q$Aa(rx`iSvd{27O>EO4c zoT0?E_WDOGdynjHT{hZ)TJelJwAo85Y43bMV|@(>T)G;#J|CCRR%@RE5=gEvX*b+2 zw9k@?^##f1YAkj$dM+IOc-jqzf1Ksk^`VTQ_>R7(OT?Z8 zBpx6TThj|NzST1I;nG)|`&ua9&q((ChjYRgJ!QspqTg%z(#VC6fP{dX8trVb+#`15 zk_zn!l@SQ>0lEer3dllkcNNF>rw>Wn{ zdGLs$%EEO~Tv3zE;BJ@?xDs=K8_++j&X1=ktn*y4iHTlh) z5K=#WA`^ib5(c5*6#xWtJ8N3C26sNH*R{wk` z5s`>P!Pfr%#>P%wbKNr+H{_NYeEuaZF-ZXY?x_EQTxOhTB!${;W?|wP<*kpe@jiLb zIegL{O=|wS0GWi1gY#10`fPW!Tvo~|1!#ulk^ZL@R(B8aVJ1}h)N1MJJIf5OY)dx* zO$bL61CC?c=u9)3yeZI3G(BcABbA@tuw5E43)RVg_-K_qivHE+NKG$gPt(Pg;3{o6 zp1fquYpM=iv$Cz8my!AIZ%<`j-Q{vkwOJbGh;!`S)!J)&TTBH6K7J>^YOZ-ImB8bR zhVSaTIGTE8AzrDat_{(+;jH9->+_plp6W_Q35Jmg+LsMSL-5sQq zDZu;&OV-y<{IEh^&Q>Wz6c-l*q6&gz&sOvZ?b%PG>Kn;KfY7_~BnRGgjN($S8}FD#>L4!#5vBw{3s*b`SsH7Bf^ zVcG}x_gm(v1iC!UaISTMv2Of|E9MT|n_Uq*E+#iU`w)8>UBSATa5 zUUzHeXq{~3?r>Z*jb+w7^?YNjQMr+*a%v&HAy&i%FlfA*L+hfaQ=I3_zQdX z6zXv%`rB#VPvCA?tC^xd{ia8O$*csk48WxK2c_ggYx6h)3yh%Wr8OykvKLNh%E+a| zmnzMxIYa`2?^9=~1)B?;tkUmaDKBs;-=V~wY?+QLlEnGO7^XXJAICGa9?X`kpOYvL zGtCniNC|M=%th(pUc+|!8 zDDB32bITYwxiIKE*pVH@xFae1j4dei5#xck--pI>p4rLe}56d`LRJ61}fVf9;6s~Y$($}xa$zyfa z<6lSkK_a#5x^Q~0hbvI42LO`@FabIY1Bf0G!X01Wxaz)puL^!~HDNj8kEwr@=Erm& zMEtHJ#0fs9y87l76BEKw1-#lHvkbI`!lAV*Uh9)+SxwZ?{z4u0^GW^gul{Kx4*C-?CkK{IYDKEHzktTv!8Cl&5Nd%Bfce52Yx@|Vhx}v$c zxoxI@;SiUQzXHMg7j56}z&ZDS9~cp7FGV*HAzy`p0o|fS?}x!!HuiIAZd_fFDx0f4 zl6_&jZ?7IF7&O>44{a&>qX)^P@hpvBRs)WyCcNy5@*-}D>t32{WcSOU@{(~&-q-W( z(pp}2K*y9~yql8@t%hLXrb|(JU9EKiZMws3llA$6(f&jUTNBZk{QNni8j}pJhkS`H z5aAd`un_RZak1|H`$~%(#VC;7JSVppWGog?n4s+!zQ)DTQqb#`$p-9em-)lqj9ZKY zfyT>-#eQm@2Q7Q04i4rudpQ@&8MVf;Jwpa+X_8*2Bdk~{SU0ULzJTT>`MRAbu<-}> z5EK$=EGQ#67n+C`uN;fl@dX@*o43E|V}4$Y3B!Jq8`=gFxhg*V$$2vT{o^5CH;_$A zjXG!3=VN|ux6;is9|Vfk7`N&eoQyZrPLfPbizU(?YFo{Mu;D4G!&Bba)YQ35b5PxHTs9}_$ZcI{qeFmv z3J;I{RC*&j{`A>f<+pS0%#WswO1uR|A(mU(j?l{|9iS0PyqZ?WK2Rl8g3-&Q4Y|PR z>fm%;SZsgq{@|_$2cT!5p6JNaIXcG%XnuC37hX)=cAzh!e2!@|NcaVa+{WJ@nNtCo)!Pd>fxOBju$ z*@_f>J^6X!unq9vQ~n``Qro!!md z&fqmyMs{_N3UzkL%mng%HKnkcwp)ZwrO?2Kl)FNisc&#^{XNggHsp)La_EN%7h`bix z2K3o}jF?zGiLTp}0qw+Me&h4|lN~_+M9?G&zN7G+%+x9grC&8Ue6H$c^RQ`PtxPl& z8wZ!-XSiue1#m2!1)&{LOi5ukn0oQ<)v2vY+Tn2TpGq@D;=7}im>{*p45P!$N@%_e9qodE|d!T69?7ic5gX;2OO*O#YNSKUSA^;Eh*wXcz zJnl{!Z|MMEj7-;IqbHq6zQ3uL4?02l z8y@5icyTVR|MsWh*6%(ZHj8ZW-kZu@x7QWAI6j@Jzrk2_pzK@Zl;O|RotV_H*Q+Hj zYM^wFaUyu;@NP1#pW^_2r6(R=1cJ{)Y1iaJjro+A0%vY!S_VfhD{|sR{9By&Nmr5U z?nkE(XQ&bQ%*(UhqSvRKGWL6!VWVuB>A>?WzuFQ$oki8wEtH4 zr2ea9{=93X0@qHhF=!}bA;t5;B?osQ>f;4sn-|vZ;PM@Z6?!XdJ83GX?x@Jgr$rC` z#F;M301x?$MoxkWA=phUDi(P!>zGUlD=1qseCPI0U2HE=6V5u zlGX^iX+D}R33+%+9r*i@V}^XZJtHqMv9j_c;L=m!31H;%i;az~jZsJ4-c+Hlt8Is6 zq;Qsw&x$d% zVaR(f1~I!o`(@2>2?^4km!hUmnwlh`$!G5CxFi&@u^F^4uFof39UMx56quvSUX7vz zG!~JHkIkNebZ=int1N@4=~{9w)XTGOy0~o-$|OD5)j#cX`~*Z-y8N}Gv9{QHw&_iT zg+3`fAn+%Ub{DZvm~nGa2_+&XPLecn>%d*;c)YrIXX`kK9Zzv*n0&|k^hf#np|-w0 z3TO%pn+6t1aNJe^_bT&)9Ws;jjEpj!)rDo6NXF;bkDT%eAE~Ff)C8 z*~2E+6C3~MtK8yY0>emN=(KB_L}y)VI@o12Uh zTvR-N$iLS*1Z5DhdzS{y--1hw$|*i0%lT6VMX@a`(M=iD*f8D#nSvl6A77uQX5)CG z#8MRqBzYxd{c38TudVEZ8Jxu8D`#+gw_z}={54gkr70k2NH}Gd@Yh{YRa7%B@@Rf=>h)WSPMpPy6*3_#B~8sZ|1~n$d@YBG_Jb z|FBxj%PvVQLPa}dZz7F)r#`)<#TJankNDFUborjG_&qW%uyO8$Kl`dW6LD)bgWNZg zI=WLeeR!sKUhiT``8*|v2*M!jndzkQNc8?fjqh|)*h1oU3NTyV%-v?iK0Yo}EA9+q zYh(~w$^Mp_x&UP66_92B4J7sfZB>|Y#5|n2cZcxBO^cRPX2K+yC#meUl1x81g+7EER?@FXeB=MLJzcX4yJ8rYj7!4m1xQ z?C9Z&pZv+fLZj@dR~@~iwtBa5Wby~e9W$g|TeiP^V{P*TJVg!htqr*Jk(#=wfc+$~ z^KShmRTaE$)J9-qq^_H4;=d}0YE;YJ>Lvr#U>3zD1_KM56dM;;fTja32_x>@A3(Sc zO&0==TBDXvp9zMNcWzIa*59`z;{8*_*RZLi@Qv3c6vZ$9O8;}KWLEcn59 zvhX~0V4zs#y8^eop&{f))Ua6QR|t^$9l^OAo5~s@5Az=z z@L!j->sTL9O;8xz0vM9NGL+H`oq)bG+Q+`Y2?CV4=~lR4K?Qmg6qchj>~q1mdZqHm z4EK!qF+fLxttkL#Zh53sM*q+a)lf#&deEGesokfFFUi*jG zP~u{Pn~R4BHH}{LLB_yF(rIU7Kh5nE&%Nm)Fk-^w@N;gbAN9@!9{ZBt&JjHpT%Ug(bASk z!KY98gO5`*xqWX=A4Jj^dC4UaT~7$``JCSA1$v7Xrll=@x%0)w!qhGwPM3n7wvytf z%W?%&zw!@AxD#N0u#OcHohn_!m#yeNbN?$dP!sZC*O)T`GPf?h%O@}OqF0ee4Ak_$ z?N&4HvfR^mrtwZK+pV3CfP6TKDo59~5yX~#W9T5(`LERzUOBTEa>wK8{pGX9cF zWcHsf5s+$pl)I<+^)2ZI6+3E@8z4hH-}Hiwo$;GIB_B?(N?~TZRCuCCs~U><^C1Cd zy1S5-W}GTY^^CT+_u2T8Cy)&Jl#0f7G7H??U4qkSS)7aM zmRV!X;R_Lwi=i|te#Bx#iAJ7Q0PdN$2a>b+xAQpl(-`I$yM^+sj50@W?`|L!2Z%3T z{N=8E8Boh>*fLf!-I^>^6ae4f7r4kncCx$g&snekD(QSMSG(%(D*8nRf{x!gm?*eK z;Y0v>su(h0XF{`;#UG6!xZ6FS$tV5luYk1N0*V7^Z}Xb=s&n5&Hk zZg=(Yl~!X$my;{E`6#3{&reQ*y8HtI@X;#CY&~lDL~i?I1br5&46+2HWlqamEm$D| zk_=wK;A`7hMH1G5=&)4_d80;;ocAZ^ha!kxOAZx?!*;1}r~HsXo&4oxlXC>=yWy49 z_004b>8o%S{9_%H+zRdOL`=Xjuh`f(uk}yd06zQ1?Xl}BkiBiTzt^nW^+iwC#C3i{ ziM&4Du2_{bp{c2mQ4Bnz0k3Qs%Wa^X37@8W@ryF z4)^zi+}-bOXFuuB$ws#8X71b_pIjiD&UDWX`45pZ&3P8`QR6-5e!jbX@o^7S4gWSK z2aE@L)pmw3$Rd?8ji;A)a7a)>LPGGg198ctUo2I4?FR<)!jB)b3p@5nX`lDzp|$DK z$s$=^cm4e}n zS{nT&OfK0^*K04_dWJ@^UI$J7jj{*QRi{grFVAl>R-OdTvXBNGoh*2*=pPP$&)7nd z7Kzv|;Abx{EG%$jTrofGb~~wJh_Cg#(LN4^6A%)A+0o87vLgGte5UBZSIi{vGTbbP z?7zz9zUwfdf1q!GTJNtVW9yiS@&sZ&SEkSWtIEg*=M_Ou`6v)Oqd|fE5W(+#96osq zxi?9PTo!b}+pj%v-RxvHWz`k5UEAC8-q;~n?;@9xG18`?G02)69j(xk?~J$YvuvHp zXL2yJW&2DzK2iKBhXwYf1+H~r!G9;`1>8Igo%X12bymk=Lca3~=v z-cI%7Z!mQ=G0YZ2UA-*xYq_m9F9o*Oz#&_QtO=y z9%Q~1sVELTkoTE+`vQQly?CpauwOI@-u*sO)7^&uM8tn2Ip98IpY`*3vb>AS+ZS&} z&;ITi6k#t<7r}*RJHefsY|oz&+=a$Fc{no)yQCUbf60y5%FA^cPKPg4Tb?A?v*Hf* z_Zw82zE>0%xn&UV+o@2;2@3R2i@OBCT|wMsRYbH98qd918b-#nJCwaJ+~;mn*&EpCM3i?W|y9+bNFbI)q7vaU-Jp@irNeNSIS*fZcp_W zQWViz2uMx$Fxq9RN`BoQCw5KP5eg_i^w(5nK`;tHT(lAdp%RY;n-uoXC2AZ(8(eKC zX7YlgAJ%%dAy<$Sxt1@DN4`VvzSOz3YiKlH9KalF-KK3jkS_d@0MyV*Cu%0is_nj^ z6y_^aR_E)PRji(vhYzR&*2=tOI$&8QlQ-wgV-?CVx8R!l*j|AZV>A6$X2z@y!oBB* z$21USY``&KU&Ui(Y56$8OrOH8=pV-c1^{oC|9JBxyF@DLyIr-uQ9aLlgaB(W%SS48 zN2I_vjv*RHPwNT5s0HFAl- z9pXdnPiMEc`^hN*BZ6YR>Lixexov+>f$#!()PMX)*Fm@gKrCf$Wu%R{;CoEKZHG$(zs6Bedwb!$gebYRp6KJp4<+06 zfTJX}p&|dlnVE?~Js6~e-4~De==3yP(mk>id#Sp*5^L4Fqaohws$MQ6rWw3F^$V&k zE>T~#KSDyiv((6JXF7iUk!CoZ zaI7_eJzt7cR#XoT_EMwjXH!=XHhzBUIc(HjL-uTLZVTB@(H~e0>ID?09{eCf(>RRG3hLHXEB(QQ1dTQC2=JNcmhYby$STS~)r`KJCD zBG&hZ&a6}Hal0=247Qi%pWY$hymh>3g>C+{O7JpLIXq%JS+YERO8XX{ zF>9cAkbsbs3e}di3aBbib%U3w#Av+wCMT=kj3)pl_3hy_c3eM%_xhYUo|2ND9wl$d z`L4`kXNV;=BEK)m`{$M)dk4oBo^#D5y^NymT6k}^yB zGC$!w0A`e%IDz2wF;TcFQfm!|=Bz0((eb9noSvSRE|(L?r%T-stEj%APTvQgja}iA zq`Z7gfE2c$dh2Q7I8I%nR}24%G%z3}I$1~bxb4r12%j68_<4UFn3)l6tZO%lN_L+E zA%K=%`@;v7$nL2rb~ZLCK9O335Z-t3D-R`oRNN*?nj34Y?G~5D`%_q6o3{gxs-nW^ zoAM%ogoL7m zedT!+;ctB-S!Ujdf8Wpv;LanW{BNFU_UF+fx`P^Pj@zFfQ*@5id0m0=rotP2qmx2P zO43pq!HV9=?MR@$GS?p_J<4t_Zr|~m*8Ot0zq1pUk*G}mb8MYizh|IAcG(qlthm%PkJ=NLBFkFD*rMMs zyj2Y)#CLrCHRPqSXU;^R72v;^%xdp8-1HEt5d7=!+04<<{Rc})!S7$p6-Nv}((4^X zxr{>p^tqS}g_^Ae&s^^GXSvUjcV-7pSu@bM`~Ahs=a*M#*BgZ9K4YZ)yQ96iU;bYm z)QLJ*mdDX4Cs1D8{$xv;d#=|4#z+!aBd6?rtNy3&bvx~hf8eBj%8&G~Y0*C>@jrCs z|EbV!F$gYGWq5xgZ1TUd`XAEpUJf8G;xGPr`oe9AujKak=9u3gopb2!=iDcsb2)^p z1paW8|4PY&l{B--ssL2M(ZT*@j!cVyngD?@{%eJ=oNsVqnt#Jz5L3NB*^d5?4Qc}L zO)hC41NUj6fF!4GSiqnU6*$`2y2UzCAlCR|lzkJ^ZDoI((igMv#uHbx-h0M`*zS=+ z(A8D_58$p%4{M#0kln|wct9m{Zd1b*Q~J^3(|@+Ulm8f>`BpH^1U|Xl*3L(xd`5Id z4?hWd%tAgm=m?+5x^V)!cQ2KSp&2gD;a^INQ`NwP7~o9X6>6sZHKP(%{tvgQvi`9m zOqg=Ug{E$Mg2|@cAU*J6Uj>V_isuODP@)dPG6P`Tg=!cYe!m~LNE5%PbKTxT!1at5^D@A_ZL$L69DFhtr@iaidck?BB(*Ws#)1iO7 zAAAtlD<(GEPksBuu2!L_1~41AIJ=uGD^pT115H9rX89Kf1_QFH&l8tna zyoUfQ6WaxzXby}}gqWSNSpk?N7UZvoERM)FsyW%aZtOF|nvMimLQjv}luldZVv7f$ zf=%B;33~{yfIOV?p}F@Pz+(2*#iXQS zIu%a1opgava9pY@1rN7GB?}g5l-&U#5nYw)3Pjby7l`X>F4^hZW#uxtDxiyxkBfVn zUQq~7>vot82iv@Kn}GAA+_}5DX9#YJk*V{M@s$mnx+xTWfnWjPxVp~e7ztn0Q-k?7 zEHJN;sJf#$I^6)6rdW-)Q1&N?i;Dit%T-vcw_f_@g{=(61J@xkuS;_RloTT| zLwB(B&4a|e+9xO%cVLWvTF1e9-OS7o`$qw$Y0nAHt7vY%UFjO_z-t{E>eX#_=?!)- zI(9vA)1!L$P>U^F%lZ8glwpd~#&)i0^Gll?9x0PynF(7P^a8>7HI!8sG1n}@UG9h^ zrHqlAJnVoT-V1}2doiDtMn$!FCvYdl()vQy>h3q3@#*o4uwJ8L*AGT$?1!%#nr{s`ys%ZWZ7&FH{<&lQ=@kGw&*@2dSqlz zBOP3zLBmUTxwolYthN3mFtk4c{H$eva}&O?fgK!^k&%}tVwC3%7L;Ccw6s*N^I69< z`7sfW@l-Wah-2gxHs<-fLA`(C3Rfj)4voF)$Hq; zcHrigmNeumc{(lNY0`2P*wUgk8UxZ*nl>+mdAmA#{y)<#-~-G)lYFpKi7mwzVJP#r zC`lKKo_|OVQ;~VzUSV3j~Vg@n9?zZ9a1=-iyST-3MUp1?6#$}=B89HaAU#-ocAa%AHamNW_@Tj}B18JI19q|U-gCCfS}wT1 z(*t9W((si$UjH;cnd=H4U9mo3ib-d}QY2%%JslW^;WcW<@cM$?83jzgzJm_mGYgJP zKOWtdNtzv+6JpEs*$Se&4N>*E>{l)XL)Xb&in0S2J5lUz1oIIh5K1E`i;joC*;UaOL70 zyiTY~G9fc>dw3UjZ#kdw_<9{l@k?4t`g)IGBwUtU+SN^>v%4HIXAUhjyzXHbPeCAOH1A3RLxtJ;@o=U}1IT1NIfyiRVKOASx=@K}DV+lR3}LasR|)$9 z0wh$jwd9g&Y75P6+k;oh^V8RJr>|Ye$D1?XC?`Eh1|XjktDHSQM{rWfHSn zIdcs$ev>aF_&Dhf<jW&rFAw$tHXKv~r$ zCi+rxcxPBQTU{M7hOola|6s{P?}4=N-z1z$)Y+Du?~f86P|eLs{O{g#^KuGW9z3yN znaTtUTL)&8`F#uI_D&tn}Sp)3O_12pX)EJzY{`P^67IvefpX97kHbrBlr~0k{aaKngwu| zq#E7*6MNL5dA+4)0qGO4xkQ>%D>-Yu`8(~l9|jG+6`Hf29n7E(nwpof`S6z z4Iv~X>Z~=^OJ_nDt3Q-@B*iv9G*oJv=P@iPM2Z3nmjMVfZvgS9J;KxE z&ha*B?vRCbx4T3_{d8aGqK6L?t8g)_0cc{zvaQ!+@#-zDuCAQtZN`89$S4EZ=z7aS z{B%0t5}?%*4vt9d8-Nzo8V&tQ&P08@n8@6YNL}~fAoH+aNki$ymQ% z%SM{Si75C#-gQBKJ8GKE6oGS!lXp>7Q5EVLlDN>q{+~Y|-`@6=sqqe#mO20mye93+ z0cP0U&ro3;iQ^6DeAU$uZ^+FRUc((*$VEp+ZH%L=p`n9esj1h~UGERyze8@Xz|KFa zixT%7w5x!D8O*0Ai*S~vOy71fd$*P2AH`hzDD(CJpd}Dtk7gdNGm-KHbfo>Y@jh68i+jkl-HQ)L4$wEbOnDE(xf8XdE*$S>cRwnC}BG&0zw>uR|Dexirf zG@;<+;ti=BKH;74BCevsqTXfC0pKa3^qLnxqfemqWy(G(C~Im_)7}#Z&Jr{3kx&#ub)DrWN;y?Jq z3r&@!GP{U1{C0p(ae8y&^1|n~XnWh@A4GuYf>crNPP@Bo&C@2~W?N&xw8*5qNw&$v_VHXT*f<2L>^pa&t#Uhu>QV&Ix=liYJcb$>Q8? zm0o%Q=-sE36yIedJY3!3v(-6=2zb8L^J}VpbPXb~6|gJix<^<5hqdJr(7Vco`Ej!$ zvW#Ak(oDDq*-u|qRr)DBtg4-MOoX+%<*>oQbYA0{#G|Ib9HmRT^~?)@m~TqLA%#CG z=)^LD%42`(?q(JyhoN6-an>ERC)e>3vfSW{G@IEk{y<@C+=h|l>~>aF4fH*Cb&4vX(b<08L*YM_O^Q};Ti?FfE825u({qIir_m_K=!K$W9Gs**B zvR)X4auea+#$-Z!!`(A{__2O!mZRqzh~)e62;O9|${tcw&3>pk4XDj??rkP`!>0n~ z;1>LhC>{>eSEsZGgTYx4gR1#Sr=35}Pi5H{Pvwz3^B(Hyf{K-KO=(pe*A8~?j9;!R zp0y%zE6O5>L}MPt*bVfIE!g2#-!4|74_oh=Uw#RCdU5)LsH>|BX${)$vPK5lc!WIp zF#q#BV0$iV-dKJDpQa@$%JXCDlC3jzeT^9#=Te)D?Di^T_*b*o$-tFzM+k9fc+0d| ztCi>Ud{6&i*I9STJo(X5L>Lhn(UloOWMvt2_$Ozsj580mR-y9K2D!7hwwn?EL;qb8 z>8Qdps4FIRLEud5CLMx4syPuFl^WT(=Ks+2Ip?*6-BzfE&Q~I|rzeiZFPXnv&QJ); zHP68CGwuO_6T9Jub^4#2Erg`{=>Y%@KtEDfRlYbn_m5%PFnW5yBr0h#;Kc8Nkov>d zaYpz~G*9K>c%HU)RxH2E) zA<5I-yEtz1k8zTo^lO*koz+>^s?Ce=mKhY`a^rqS0*kyeA^&_H2|1Xt5xd*d06KE9GM!633k$8~rA6Z_>a=UWwPw$&IkM#+OMq`sXFp{2VJ9gF>q;Np4)nVptVH{GH6$PgqRL?AerwV8 z?!M4mjGr$GTSP{TM+)n+$|1VhDtF{QHP0r(0yTNz`jXGx&5c(0C-hXxq5HQJ-U~pn z9olBtV8e)?LT*-Nx767&Zs0?-$H&8i)A%#4QrS~)$IKTu#;Dw?3qYK4sAt?j&XGRV zeKiF41VMZb!Q7wf9nKeIh=_>htF2e}*VDcxE#wY6l|pJX-3{8Lp}TM2+R(42KQOpl zo=RImA2(*WdxTKI1i6~Cg)utB5810#mV+Yj-F zdL*x42dNM7=Wfn+N&8MD1YnWT4S4-%acCC#Nym%4VS`qPj>$QCwvnurz3+}}MO`Zv zA!VJF8`muI`(i1SMHz?ci0Wd0NzX_mKl9NeFxf1N+_|B7ZB-m%Y_Vz<$yYBN$U6u0 zFmV;Zxv0@GU6g>Dv|~J)nB-^XIK?nnN!mh_p0kbu#sbuB&})ydN!$`R9<6ixX#e_vZW1*nUs2 zH!0K1b{ZT6NmU%9{bD?-eIr&-5s3$; zYOU2+SCzsScn~8HCtif@wZS!HM#d7uw#=m0UWs9WaWRV$Gm2yuXh&7$zZN?F))T`d zGiXz7PP9$RG!o+fGj3uFezP+ux8{WYw8(YL`mNDZz*el@yTIyHCC3!Q-+W|0HC5j& z`H=-rP>Q;Pcp1eUVfwwZc%0cS0slyHwo>m%sV}rjEmEd5B7FOIhO{>*lpVrFtS~={ zgY1!_5AzzV7BL4}dF`OKlv^|nHL5$9OPo*~Fe5F3V@}G{sUU^SA7xkH*E^H>1Q@6!pFS{o}r--67Uu z2Se4aq4$>)FAqm!LsS!)m*3AX-|U@1$2**tkO9>5Ol2v?Z_HhY(f%W&&sCIOP_mpR zg_cBB;E_vM*r9n=gY+-Ka6rb-uMQ) z;UhUGJ{CQOS3GHo<33eWu-E^2&uinGlHrKgyxcuvme0B1gm7tA))>?x)VkdAYtJ{w z7@pOx-wlcp)I4)@qjOk57EhMTDHA0R@O^@&j!i!qpg4XZ7?R|k$Re$7xx*%80R!Sv?TnWi-dYWksLy%AL|?=<9 z@AxMi-|k`9q^jjj+Dz!GzBiF2g-M^Q4O~7g$mY@ezyCKivxjx$^sp)iWdto(-ay{> z84VMs1Zzi{*HzvUzGN6IFR7c~ycsrqI@!Mw<-9FY(Y_rK9Diqkr+$UTmXapAPlY7@!&!v@?a%-;EqTfQ$OTYI%H)F|!`CVU6S z!0&%LV8@Da{2=3njAB}pU>5g5RfD80gf_C&;IPXL#<@bKTcrxT^zs^N&dxH9?_Bzy zUA9l-XmK$xKskKaQ3`x!3Vr$@B+H&?wat@db+AuTLNB7Q^hcJB7YO;1*NFJJX=kV{ z?@<4n%4{RfX!vRiO>6p)cmH0k?a!_Hr9SZ`?{Lb>P8o!=7%kg6`>0(yp|4u*_N(om z`jtM(iHYcQyo}qUX+kYkUogma?&r5k{UIB*oZxRIx`Jj+B+TN6VFi?qmKH;vTTeWe zCnl!+rG7|j$4^&kJ_9b)H*v9Ti(GyTjC@T)t?&>K|5@5EXJaN`KIW~Hd}Zyqi=l1v zTrFG3KX+n&D3GMA${ML=VAT@_6PaV3~*TW!FWqWIz+zxTVB>KX9d2Z^co5Tzp$ zZxFX1zkK+V^dsIrb$JnfgZ6#JQ>5SxK;LV%Yk>)!z?VK}DSR$>&^@`y<45a1hG+93 z_b>_{i*U^@j>GzV?XJAKL!8Anql;Mnd5DA^$u4R!JQ7oo-d%H(lPbtxoF8|_$LS0r z#Di_aGhTcvioHvZNRvRu9CpJkr7w&S);%621-^Sny+_(=W8}}JO4DQ(N|cox_MquM zn7~K0PXs9Wn3rKZ01#keOt|EV>(;_;VUtp@K%w#%V2tWjYk4b>A>CB;z5{o_t%iT_ zWel?A`YGG$8eA_C$lK816e3L*v0nI^B6D>8Lt3gaadG0UAy;BQ;P6eSW=>1-PMf+r zYAn+@-sh9{G~L4{{QQEh*=8?iy`R^njc<7@n-o4P-@7}`K9-UTQo4dOX#Y_)o4a=h z0b&)iy{vlUjIMjs7aYp0Y^~8Fc14M(Zu^fe2V&mW*IdKTJzJ?RSb_5CU@&!@aBB8^_D5>jw{> zc9}ZoD3YARXN>Ff9bu?^Kw<_kNGlEbr!v4bCDHjb2^mIT6OG6}$)HvcQPN9>r3eR? zSdL$6Kj-4#jsw?8E#;Jd5Vntu7nI?dot!k^IFvOPss29AbOU0Tta7QRY{t>;Kd`j) zIUTa?^U2jJ+B7Tzh`ijKoQ?U;IU(aNpDAXOzR6kN><+R&VNkc<8!K4+CIuZ&Rld8d z2VlWf9|0k$AiA6t%Mg4e6K`j)VkbE`RSBjE?}?$4)!5wy@+RmcSHi*M?{TD*&Am7Z z^vlLy0FS_nW;LF8v7=ou9dmAxZD;6xHfo67-&L2O%iUsP93akYW_EN%CsuYd$Yk zPwVE44_^!EiT-(Hf;iZBgeGlMEgYWCp2XX^7EA|Y1SL;>Rq;k5=7P_a)zGw6%P8Ktxzd*EHUiUCVg{e`e3K-4%G1525 z=iT{7F;Zgtxd*BGeIVpq{r8ev2ZWCW{Y~z@!{<4{A5xPOn80l5ZCKGtF>K$&fZFEIbA1X8uU_~~BJ@%OHNZN5v_PZthp%g~c}f_25s ztxYs?z8=|p^&)CkcZmJl>qqVTADrOVBsS_9%_DX0+WmBOl)(jSQf{Y@anj~%&AVmP zAJMA_51+hCBo(1>a6URW02j=ty?v82H`(=Rv{z8(2fD{-qI9;rUbTpt${x5b=ZMj$ ze#eEXw7Cu?bs^iaB*nr{R6a*%4|(&MO?*Ht(n~Tvw_#p3F$e>C;ZUFT_-(7NGcMYi zzpGPf5!{>~o;^5z7R$6X#9>rxLKJ{!)Vs~er5h$6ZX}6`kx#uR93_)5l=JU{_I~(p zg<|6yXadUPedFqLwNFr?>UQ@}YQKHnD146{S4$PYSyzYcyLGD{0u&doY0cZh$-TUE z-_6Q02>M5C;3Bv)Ras9=aQZ3szLp) zPF!JgT-v4MQ)6apX2T=6$fXnHd|C6$No4fm4Q^D@*Z4Gz_>#r5VQCvBGUm=G3h2o? zA2E~9=IOJK4)-ux#n1P^QOZx7&({Qs{$EAW!?1M&Elp;GP;Cz7OfyhF)Qr3N9zKxz zTr6R;2X$4p3~}S6yR@JFwVCQDeRh6a+&2ZFGV~o}-Z5l2aXq1`RieO* zklsY3=Ms8hV3bEUUoRa`nZ5+d>NgsLFSRVYRu|PBz2KzlQ}utCI_rR@-uC~` z08~m;KtMo6M37KYT0la&J4B=#q+==|(o&-t4WqkZNJ@?xIhxTuVC486KA-1#e&7Gu z89V2`?{i)6>$+ZV;9Zw;Rf5@fXJXGuSZBoQ=I@V3w2DjQo%JI);;*_EOPVj&+mzsn za)>lIx2V5j}5r?(Gq3AmDw<9&AA&_Dr_vLpTOH!n{ zZ0HW3ub3TNHJ^xj2qw8#4Roq`@F{G59B~{$ZVy@c~v|O;G_X} zIuf{*K0mYsgm0zcwCA%?*+H!T#^X1Dc$@;SREncMmhDJ+ZC$0BC})_jL?&6ye`DNk zz~EQvVS5G9?Legn6Shd1t%r|ywl>lo_TS*>UaALbW&)`%3!ziF>e3$1?QhDHnY(P7 zh6Z8R`NU1T>kGeOs*x#F4|&Atr~la@iu&qBUe)thMfEH)>!Wwi9;Th09KO?Z#FE@A zp5|r)!X*?p%ko!ha=(q=f0yr3DlrAfsTa(4I}UkF!iYe(yH0aP6hlk83hf&G za}GkDH{S*)s&}ijw^O(Z$ga~FNc*t^7>s`xw8LOR+A1&ni`k4~Ul@b@fGkN0+%2;1 zq8hzFm9S%o+nN1N1oH3r>9cE4VCrVI9;N+->^dd*OZdi~6v*9fhbTp;(LRrSS8F%Y zzRC1>G*3?}B5>5&@Is6VSw*GR@;Zp!e@>fbFuh6P(!lZ(u8E@BHeUZI+@%UPFU4EK7#<7>hLrjV+8UsRves zT==sB!+!`L%Plc*CyyQwCIH;buqolzDEhY{ZC#%ug z$kC6T&iwx@B_2o(|MyE-cL5=KzSUndOA_(R-Kz7j zCvI;t7fL7S>A#48U$AhN;|LL=b8qq&wkQotlegg|%}(1J$Q~^%tM1FQBk*zEDl3-Jugu5?&w%bBukb0%kz_HB^n;94*xx~*I zd<{x#w|Mmw^LzBTHc@5UfYVoEbPAX8lsrD^JH4YOQ?1@wL`Vm@%hBRbl`!1-nf2_f zA!@k1yc~XZ5b`>%WKhVYGc1MMQdLD|C@Uyp_+nuJa1_Mw^mDBbNr&7Ep}4I2+uvU_ z+R2LBEOD_OXESVUpX^BJwct*))+%W_-)X26ptpw_fv>`%5JJLSY;0kWI`0mr1o`80 zd${dnIrgf$Mzg0a}*bL`UhNytn93CDlX51 z7-keiulaZcAp*Dpl%cJ!^iNhhiD_z2F>geakULQ5pll7j;=F;J6KNi2;0|=~xtT znX3d9IgIinAo0c=@nu&_!_*ZMxD)io2aP45@pcz|bzk>~d91Y}=!AnQ?COR?hA8Je zR&6(NP4^jGVVsUd<1rvS$`654kgLjc*q|= z#PtT39mwHD1r@}^b*G42tVtA~W!o>nvQPX-MY9_BqoXZH+MkyJkPtpA-EgT)p7@v- zVU@Z?miwLjF1l%XX~jSTm|X5BQ!7+0=wVkb(u|w(9ZKnc)4*le zZp*}0`lWZ*6TU)g=9?{5@D`zTbWwnskeb|nRCc^Q?cB|4I}Mqkqoj<>`$=5qeRbn9 zM2mrUfZ;)iT#>r1ckbAQ*RzPmB_LJ5bFfudMk?C4TmrAHl?Wu!^v*u}>wj0+^Y~(+ zVRs;zzs=O*S$B80w`MNVLRBpUJha^LF zIbDV3M!5`r`<}#W%hGUh{U8QHnNriPXt`Xsvbv-5+*98fi^IZnuNjW91tMpMz%&gF zuN}%i*6@eeSL}i4`LdeX#na{fFf?v;@+vFF8}z#AGPFpy&grxq4VgCK&+UN3O_GKh z!09kk1tsMNUoGa+omU5>0Xjp~Y+BkUQc}|VRbo$JWc|X?Mn_jy9Ca?Wu-PHt6PEtF zS3;t#&zcXRW<{xk-3<^r2#+>De%eSjU!YZTys32&OM`b9`HF|9NPzGYt)N@#oBbhl zFJyZX6T$xx4E4mW_X^j$Zg!fxaDPTsS&zf7WzDr{OFJWMN+KI~>i$U~5VpD)%CJJG z)9~%-WP#eH<03ikd~fvDGZs(gI2JrRK%a=5PSqKj5c&@B=FD8{xGQ5{TbWNS zbxU3rf+ievUZ1bwj4&2(%^H#SDw(*TiH?=c(i3t;^nZH_e`pV6qOsEijIWa7}R z0hs3IX7YY{WT86C!Xg;E%fZ6J`O*uU!&@%)1(pC!5>6ttV8zaVzlGH|NUFBIytt@6 zX$>F*jQI2~+7FqI@Y@cu<(NtCk?bEFu*ftXEfDOwtxY)Y%|8P`(bnUIDlD-zTotWt z46WjAFI1UrX>R4QN3KUy{~a4o|4y5oW9slH!U#N7Dz==@Lz64wu{w4O$kn?|qUqD0 za&XLzcX_>xHNYTB^hDybLB`)I1Y4 zKD2Bv0Ho4da}jrJly1@3bT4Lx&#-4;0B5_P3N|uI1V|)Zjg@YO;2=F+V8D>C#NYw4 zJVgE_`sL7y#`V&i^FH#}K?B(?)OT-XB1lQwuEJE_qUkWdKHX(QL@2TM>&}F0Z+&(X zLD=0pd$}KRH#$nfPEt)JWH}Qw`CiI|Qd>>zbLd9riCP7_%cPp^>ux zzA{;F%XEvTRBf(TV@L`envG&8R_k*2&&tV)#{kw}fVEnBdOE};Y2}oS(=Dv4T(y@k zePaqS2iMbDnin%O%eh{mV-D9Vl$O`~v9LT1RA4i~T-H|abXup}RzyTZEr-G=#%pbG zp)zXZ@ZjL!g=$bpMX%s)lb#igz}Gj1aEF75yRo_&9F2zO$J?^Dh^ozT%d`fU0?k9? zD4f{ChY#EGdU#MCZinf1J)?^yO%@;8-+3Ecf;rlM(Y~(cUkC%u4g8gnmG}O7@QB_B zDv+Mu3t@+SSVu1*Cho>loL-588k5pvxorZd zuR*TZW{v1Y@**s{GfubFE9c-~ZGYs?k)G?;+xYtC&alk9AD+HrL@XSz!eFbR4!9i` zOFC@P$8Ico<}4fq9(0EQ`?IV$UBPwxv}Q|F(x_hEWax;x#>??op5=6{%7wb}Zjen% zQj#>!bZ8fo%jR%ofiIKrej%V521cZ2xvw0;(9K;Tam9nxO}OH+4QFR(S{|EH^k}fA zajG$TDy%Yii7AYsiPVMDuvc0xbMlpTsfCB~hY%;Nv&~k*3d8#t=xF;d;7pR7pB_c_J6g)-}v#J6#%ze;V7<8t6%?22&@$^x6iL zm;>6W>I~POOj0#H^{lCitNZ`1!7zySIQ8xaQ`S2^{ZuCMCatjb6|%=mI(KtmhZwo?RBsjZ z%;iVf0s!b4#cC>=rPZ>iQx}2DTzVR>_@64o9XW(5jb?d$rvU-lJ6PDL{*?wx8$gp85tHr!w4X`$gQ z1aH7{nUoTwW+u_H9Cy9kwm7$ipC)^%0Q*qax^s$h^7NY11M6Ltz0nGeE<+(HvGIZJ z-P8OTFI|KXp$9%*{h*zunVZk* zf-c~mv7BMgRsv5=q=_@dKAo8v|9!edYmKFU*Vn?kHHvkrs&ujadKf^#rl;IL_9lM_ zNH_C{@A3LFx!_vy5~;yl;h*zA`Th8z78Nb%!fSZ+{>mUveziZAF1t*>{G*M{R#n0H z;-cLXA&1hmwD(`?J1Q;L^hT@X#(AtY$BSrQ#!@2~>l_&doC;XLM#(_U@$eL3 zucJzRL9SHEycE&h0a?H$IbCw|PLaW#1GjH(I}_=Ak3Ek#Nh%?UAL#Rc$f-M7aeJH> z@xd;aM;48^GVBB`L{sOpeA^hvjGW#j8jN zE5y}Bh4vLr>r9T${!&T{Oe!cqTi5k)!QX$x4EiN8F$rqfo!KcCvE!=4Mb51h++2%# zjHa2n^I$m~g-m<)Ygbd_XOxc;gKsa9|0H*CbFNB` zPLMiyy`i8A|F0I{d7gX~tKY9T1RpB!Kd)!_d7UP>FI>zn(+kxwk z6MuG1`*WqGWX#HCxygC>#gCip_JfLgRPQx7XCt!HPB-VM=s zhPdSL`K8dsZ75iNCD8!Q|3jGz}CkiYC4+n$!&j$RB)=SdusyTvwk`EOpgE&dztjgR}H zClvWw?#i{erUt77?^~i1y?B=!74XH}{EFM$&OzpHWf$El=L+R;rkEeThK>PqgnYaV zy{2!~$qENBY>PEo1wt~*?fN6&4Yva970UP>j}s&%6kw|P9-qd=NEck! zM+bUGP6)dJJI&%A7H#sA^Rt+wT*qX!(r2NXY0aj$v&sA`-UC@sYbs0rquD-ev@5Y zNmG4&g>gpiL4pJ8f4$C&+=B0gyikQfOC0yO-oD*0;+rei5C4+}x0c%}UhOT$hK(C4 zDSXT(AF^O!g9LB$&AE>_3HB3m$2WgxX}B!>fi+Fwn0(!rQ2UtP7w5ZTo5oSv=RwM$ z)O%Xz0hqAT`s`0h0&_^sIU}vu?de?g;bWGoN!!N!x!&H9hy#jEgBn*hu5h!tK}+uJ z6>P6?y`M5Nkyq_>wA7hQrOa zuRUdr2nLB(E>Fk6M(*3_#f+M?_v=>mjI3;RDg}XO*!4fLYn8+-v585KeAb=f4BHk< zl9yct6*5enOyHHo7+<}1g)^6hs5m1p#Ko8hZgKija2#NjCQk#rr)P(|?mOaNYnmDQ z^*EQxq~WKF61q=`w~}fgW{=3x`2-9*Zi*h_cG5F5~0KOGm!N z@`{QR4q~7xP*rk77+MN6r-_Aw2*Wiq>)h8r!#3imln7Ka&+s;bkTl4)+0_pj%`&l|`nZ#_e>{w>6%ZDByj#T)1kK+cVPNADeHK-);!TKFs%B zXPiS^##)Kr^Y&@HyzpkD&@R_tWZ(ySC%rD#Df9eENbaQ#$5bEJ1jxZy)nV#01fjA( z8BaIz^+L7Hbce08PQkeCV!qK-d@l6dUiH90luT=grN=Hb8!$ztN7huz7ay|+xZY%g zymqu?ARytJ{phtSdX7yf&X1-3`1$jaY*TRaowTYE!3;=sLiKlzLd3iyYM_vkLiWnF zvXX2mM}r%aCry_rETz|A*YP75*A&0L8d z`yQD5ej>W=7%X~q(sb458O*|7^3AhPF`N#CEd2P;j2fSaD5OWeZee-(5ICfthYnTuQ(lT_a^Y3F7;^9B4T=|~E;s`OO;Z!HI-+hd^qRQ0sFUTaz6 zx7&AoP&iVUq@r#Yj`K!YEZv3Tj}ZU1K-v7AzX2{WdTTSvuytcFt$F_*qF=9ClymZA zq_BVbYx<2EAgHxQX7GDG9U7cFQ_$;8`QUYe3Rv@EfA(@ks_rxDe}zy=xdWJ(A# zpOp>xQ?JR|&mhtnvJN(CqBPVq4z^c)Szs}ZjTb$9??lq6&G!fK9hO=&UmfipU0#W- z_+k=;NDPqJE(f0|B(>2BV@7_AK z-)C3KG!*15>6HoYM#wjMT(&aNH@2YziD@5sp^5tCBTlSWrHMFjcXf2V`bD~}+-Q|FC`Tys7n?$LVm_8fLm z>MXQEd7_lc3$pv`Bj%*r(~2Dx>+B!$1)lv0xr$d}=sd>>yD#pg{@U|A9J3f5=;{Jm zjLlRp1_+=RRr8e8dWvsmuM$QDQ`7W;DB*3d7wkXqMd*F~)iC*b~ML`+XOlDA;AAl3ZZ1B5U9({8c@s2s_i*36#2d(rsTtz<=-DI9ZnIKR^cP@c|^<3PjWB2_*FmgBRsz8=%)BZ$Fp zz%Px%_qBScx$|~S>q9u0Sj!VS53MN(ary_!5jV)2LZq2Q&)QDzKusqRhNh~!V_$1IZhXnd5iR(@O%D9 z@U3ucZR<2LoY})t*gZf-Ybo$?s}>;DwR_NtfL<{>4ivFE6YW~OFe^m>)9IxG_0c-g z&#U`qSQ1RwY55B#M*(mqsHkwRww>d#_yi}}o*wplnG(@FQL#ICcC@LowYiB|ax+Tg zgPBJZ1Em0CN6Kta(Rio23kR5mj1~MNv<;OO6PGyO$GA-gU6iiAmpm8;87N7`4L0wj4)~-wW$Tv5(z9A zG{o<^XkP_0J^ps{@%ucWF5g#ukC0HSWcrQWp$v6?ziilR7S+0j1{GX;_lWwW=3&0+ zYfYeTNcg$zWHEsuAV3m@sKlL)57RjAAF@ynrC=_BqUPC6EMe2M+jdUyVf%vcBOt)r zKi*#4bc#rM$LJiT@)lL=*k&361~9ROG!*&co145Aih3RSe$#X;6>fG0&_u{sy(yur zqQ}MhNzz^5{{Cz_Gu(;Ju;ho7{o4m!>(MapLR@N?OCG{V^#1SK;~a*ByJ`uuS=41= z!n{6XQ%6bM)M4^3GdJR-l(AdqHHi01c$Fxn-b5vm<(pP{gS32(y1u^OLqZ5+8@Lb8 zb^@Wr(|ddh+oMJHpH(@Lo$8mvy*0ZRtKA6*qh_b0kP@H{pl&uY{|0aF>V%LHe6>`v z>wA)5I9u+)mG2uXi;iJR%^@@C?SHMaJ~Q1y1fjwl-zLCQJ?dqHPSb%LUI9lj@rw28 zPCcEr|9`pw41S?}7~-q+8-K*$OUx>=9_TT#38&EYDFVis(qSp{ ztMs)eh*O;!uDn;YqWf<}uRw`enlQ~G?U)2(RJAKD-NtZLpbRVT+L0E!5vr`~Z)NR& zwE){pG+e+3ySK-n=C|punw$zL|GX~lXZd7yt1fOmUiHMcAh4#r}00xDc z@jTptCdd4SB#Lvzn*;E$ORvlP&_i`s(S&iCq{IXdueK>uywg*kGg8a3j4BVhBB^ss zgwaoF?#CjY7ovhSAE2TpsiPUD(}tJ$w)zdvMc9Ad*!xt{Jid`XT^`#DV2UoCxS~gU zSc~eFYnk5P__iIi&J`G4@!>g^kOB(}zgTKwynD%*S$XuK0-_NAv^nZIhS6Q z?f*26kyTf#rB_xWW=uXKF2HdPZYj zcy4U0@NNg`z%LK{bZv#Kbv3lr^H^nSb?!S~TD5g5$Tc1BGePAV$>}H4%CuRh;BHJ| zJ*v-&hAgUaO~+;z#MFs&0^agXdoqbYYH!>&g;xI^K__T=naJ4vF$my?Y#u5{1i<@| zc}Pfa77q*Iz0bvlu8ywjNVofJ{!~|Vn}Fw>Y*C6-P?OJvkZ_ZeQ)q60mnV=PpT|(6 z@vj>X4VO4rf@C3@m)gY+(fs_Txm|BTpjoG3dw0AKc|^~{bS+)rFCI*;K4b<)T*!*@ z->a$5FOau`{C_q#46$I=ADgv)U3HHAqdXJ;{f)}D+w#0fFSw;5H^QjdLZCqZh1EnY zKk;wQC7pg4)w<=wT*cjq?DG?8`tc2JEp}-=_O6Z&MxN{w-L;sQ7j^n7$MJcTWRnGR zX~39&*UYQtDIL}*nJiVu?zynR`Xg#?tKm$otDJt_RDPGn(O&Xu z1^3KXkE|hT*|NP~I*03tHQ<8Pwo^^cauyadkfQ0_7mPVsDC&1#xqYN|$1-txh;K z0mm(6Z+)ULE@>&A*(wv~vF%W2bH%UQvvDs|1f8Sk4&9WVX?-y@#ZSC9UIZ?I;zpg- z=%EQlzugW_7Rm{2220B#N{muU>mwtH`%U@7>n@IFJyg_Iy6}6 zQ27wd@e&vsk-XZ*ZYc6P)hVA=UbPL~_#tag98 zrt>cS2GyOgOx|KWkJrz_Z&JgzC(S>3>)R;0LeNBbIm5cv^}ULb>soP0D;~Gzhr|ov zkGcNzP6sAM|1?*?yi$S+%oas7v(gegO-`A6O^_qDHE(qq~tktoR`1Okl(UGV-jg3%9>XYWn(1g&ZZ~Xp8IV z(>Jy1H}r!;77ebOE*L3(M(iAorX!=9hVrT7 z(MERlwm?WnMuAoa)xbp{_2-i2I0R1%_q%ir!UHS`XkJW;me7S`>`3lrGyY@HRtJE% z2ZlzFp;V(3zPRrIhLGRwc)2La(avtCI48+~5!DFvwoxJTm@nlB0!Qx>7s>IwL7$U6 z>6~%f7!IgVNUYvFKFZu*fD}!U8%gS?hUNU3ATxOhNqOO>2_WI{@yDrzY>0#v8p#p) z@-JOfDPd0K1@^sQCR$$HBx3jL>i>LlxLE@(^2mm6p|o3uWt%UXQ|;c&R{_oNEWDk z{Nj`%)sdDngw3ILAzMoK+Vy>279Xtb>5xDVKRx_>Sod4N_!dFLWA3kyOf5zaTbgGM zg{=X&(xHHXw|?Ic1Hr~vfvCrnTHm2y3wKopx)7^Ip}e1%QtuZKPrI3q{rVBLJoXQZAmsC;=5KQl z2pi^d8AXfu_~?3s6*T|n^()T*qp@nwES>x}Obn2!Zccfk_B*;WEvL={&z(T>WoNQ6 z_J&W<#==el6lzW9witc`Lj=$TV_4Luwx!m%zZI%e%vbQ=k@;VYmm>lcJfivvEi9Xu z9kJQa8z2J8N3)6MyI;rp3E{MbvQ`;%MxIY=}DZUl;F05 zXAl;D1BBuOHk`f<<@Lm;YrZSf_{ zWc6R(0y!ujuX`n|Q-4yCTx!AoB^(F`o5 zW3%@39{UF)A;*K5z(7Hb-owL%vdotvoW*io;lNKkDJ?cCUpi&J{FONUKdo>x_=(XyUAHwze0)17Ek_&4 zF}Z*72z8tAeO@8%#f$bKpfR4nf9A~4?#}6eK~?Zl{<02F)71b?H(v?boN+F+?xel4 zJBEt?^V)Vyt##bM)>QRd4ld@Ep2;DGKxZ!S(P7jD^5>VVj;yNd)Tp(p-lUhL8m zXp^XHkB6@M_9|?T=Z+usny&@qhU0+u28$<$c{u%@yCfN(HkN}bH^|xop9q(pqhM{> zW|YP<^c4bQ0QF-cQRJ`ejL_q~Fqxt3$&%tq+amV+4ynUyMBcD^*4 zFSnUUcNy|aC#A%?I$tK5);^}OVkx$x(85-;m{-)yJ?h18590D(4v8_nhd zaj9C|h~IBl&tF5K^dH(Wo}IW~?agQj*NZN%?}+gjJ1Bq34c~_SCM3FZa=3)GSfPZ1 zj}vlp8yXtWXmmq;ee>yAF977?MWFH}2@_Yxie7l$H3c4Xc&e+#9Ar`W{Fvb6RAsPC zLNHN{l_D@;Y_bt3+NWt+*Rl;+aQC#f;uAlIm1gn0%*|qX6wDl+*QSW=DG0($&anrH0P-K8$o2K%c&^YtoVHiOhi$0VAIW%)$jwi%``r#(D@5l?b+ zea??>JvQ%hW4 z*~4C+UT&JA#Oe*?_^dA`h4j@(q2)te%Q`Mndf{f3it0+Ke0NLjlgPj>r`_j;zR^tP zBIc>vLwA=fexgu~-vlBNLg&x76G{criPCt>%Z)fEwv#{T-vZ8Jw1JBzk^%%OG^uGG z&&Vit)u(llXp6T@K1Sfd9TLnG61QfXB7S6KWVB~3r!*YLY~54Q&MV6kbUJ)orM}{L z3X2YPd5QD~q_Y)H(f;!)Kt@xb=J8x!czbxbnBB`AoAl_RGXocwHG0DZj)2M$W*q^1 z;}It>V6z(jkz*)W*#`Qt(d?TVFm(bFY9+Ir2XRt_tF^nLF=72pl?-MV_53l zd`1>nb^)c9oTul{xVY7Po=x9)Oh`pVMQ*ONxcKMkv7(-o1QsPyQmhnlX8by8JzWC7 zNT=d^(ieV~29I7>;ED9PZcV5heqBG%SovsdoX$Nai+riY=VUVQM9ZAgs>C2-9a%9Q zR(k@A5M_*%xwyQ%ckf>E7e($M3KE)7mg9~Y+rDw*MubAb^3D##8kEdwl*2SJt8vFa~@P)*r%)K+!1`+DBm!K6-Ig)3wq!m?7ZROBWKxb!fE zRgq8$eaoL4F-PFckAb(4HpzDLNzdl_mGB2KAXUnHGE;AR?U~SHu!X>Ymwv=g&~W=( z4*>r5f4`_^sKV%y_KD(>`M}>*VOihTG>deVU1XC!@Gv0}>X&9;P;{4jnE?R-l~%=y zIosWReV;Fg9&@sAaKMe*@PTyX?Zqfpg{4=|fK;@q>WIF+zC|_$tml5#SGO(bdVLBV z^J^S9?(_8v1~yZlEEd>T>Dn%J62s22TX8TQ1lKp+?t0&D-*Hd~AY(oT?alvRb_#PD zI*d!Znta6o)oAe~QzoGe1WL1d#Gb0YM9%D7wBvQ@x2gA^sCot9L@sL?dN=g_32j(xF;TNphNJ9 zx4>t8lRHfWLo$}KR#uZ8x+F;>PaW(G4Pi$3BzN}spwK=jU@nzZP!?XLFGAh~SU9LL zDO^|%@BxS#-#=tA@=AzO6feuXu&}Vjw39v4uo$OPpZ|>4v19bcc!Z3CLPg=}4Xfz1 zy)idWCPgIhz<24@=Z>Knj`z5~DJMvg%XU)iv}fcm$DU65iY)-~4k&+MW<-?X2!Ck^ zd+@oy`kUOCS*`oJ6Vkl+!cdLA@m%xV)%MjyvooL8B}BFQ3{7Eu8Y3uJA46T}dzYAF zWGS_mBPlC#RyDRx$7YKdU%6p{`V**>I7Bc+)8yh$G9VBFLfAmRED%9EaEuzSnC5a? zclqvi@w6a+ZEyQUh!Pe&^jupj17pyn=-r+2fW~)UlcdS*j~SkD>PpwQ~6C zye<|DJ*s3sMh0pr+qvEYUZTM&M+Gc>e6C3vJAe?*CDH>cD462(TJjahi}BYBI{b7q zGA<5$^0&-u!1X}=NRfvikJx`q5GkL{65UYmj=zjH%Nw0kH<%wQ-)ng=GS1bxYw^YK z#sVI{rEcuEl5W_i(>=Krh8%!?X=KwOwPLN_Ha^|?mDy_3V5Yi*S-?f(|Fh`#`^2A7wB#Hg;fX7sSztJ6MF3!eW|{W_iQV#Dw9X{?_2HN_A>G0zk;aqI8W z-07#u8TrMBP)esosl|~ns``RhY`p~r;A2<)A*$w5t6<)pY zZ_HdRBe({{K-r8h1bieCWShU}qYXWPd(&0#3p>#h7o67s$(i0uQS1fz%jb^BBtQE1 zlR^joerXrvjfgBnt$MiGJXNGgJ)~V9O8tLzn8+%q z|8KWFp<~biz_6)i1iseJ5?`XqWXVW?$^2SH`J%|Ks}SjOsp@ERt!}fN?PoGS{rZ)N z@W^X_k*@vIP|{N=@7;fHn|DJ8@cEFp(HkAqE|DKL+Cd`+G3p+_8G(!rF83#CMKp>c%w}r!|k{^XBKR z8|}bvWLY}zPow>3Ofz)jX*J8g7q)w=l#@*! zk)Y0{Nr|Q;C-*!HuzNcitJmeebM@L1M*jC;(Md!(>YlsJ@ z)~F`1hg4rYAQ-bwNJ_{W$*GlHpS)wpe!s8*bJ&j(V1998`vTxp zq$p-;6mV0!NXgoKEXF@$oUV}UT19UI-4|bb`x0YAhE>&GSxnaZG>{koWe#FbAG4Kh z13{dk+(+J(>B`-yB2vBz-Aq|o`H3=925eH>2sCwjIqMzxxc&R()u7sxEti?d?u%$B zzt7g*_oj~5_k&WsSMXpT0DGQtvySJo+*YVUrK|L8-o8dE&<}NAdteD`ApQkTReKl) z7g&(-rS>tftFAmkwmV&uh2rgPNULk{wOPsJOjSK)UVPqp_JC?!kK=i{IrN75r4>(S z&)7Huj5=ZFWLmO4Ln}Jj`8FA@E-p?z&ENk`W>TBojlP#SS|~}gV|jU|!hOs1(LG8G zH3I_;%cFr9BG|)xllxx)O;ic(k?UfIzy-L;D#UWVOVk3y(b#qMKd*&B}x&R*6p3 zoB8aCaGtyG#$?=~zzk{^{s|42|U#==smA1T9{^8&BI%_hCt5~E3!ruiUNbl@BCl>Yt)3+9nZgb$FcGKy@A z`X@_45ZMOohIB+~6M+*IOkLd8*!TvvvUJd$>8*JPR|4#@@7ZJ=%q+(VJNR9ArP0v7 z)`N>(NT^%~Gp4=+6u4)dBvpu$elbR&P{|jK`ksJ^N<>J(>sxs~gC+nai=wDhmu{yK zx3fY059MmYBdNmRMxlx|#T7r4PLATT)6~hS9A-P3#gFCY%qOb~s#)yk=pLx2^}!M0 z=@#t(F#tqP&}-wdMjcSK%U+m^S$@&`v0smxgYXF+x@}FVo)`4k&j{eC{4C*52N5?;zpue(3wN%w?&~QX2Vs+u)t#lh7 zZ_}kdWXSEOGZ5;#?xMsQi~Bx~t*7rmPLp8(sbj>^f&#fYlaPhf4nM%ZUl+Ir&6|+|Js|7zhqMecUhcaW}-& z*NXL;Vx)Z7j3m6!Y3r-uQ`MUNpPXuz73TfJ0XS~w z4Fsf8Qp%Kl0L1_XXD183T2ooOs)k+0^ z!|Yqk@!W#~6>@{dC)9Fp_kt1%l4|60e)lA|KR5@I+yWG-{*6znkAVb?_ z!5cTsQCDNwOnCvK>f%DIe2n3b<2Z=9;Bmq2<{tkfNy`_Q%gX{W=ZGqIS6osuLkkqH zxlwdOGVo4R=}Cf`l^F{)rpck=0>Y{~(5LiA5ul=!bm2*OsF(htB);=;@kx8s5_hcS zs!LL@FDH&~Hqh0{$~2Ln+3Wi=kSE!)?yicMi{(ZZ#}|iqcpImvsV4W6e%{CRHUF&W zS9y8y!3K|wps>eRGHZ~}t}2i!MLK;c+KTVpM0+-ihE;jKPW-(#gs}T^Vf|A11VHK+ zUQ1f|X7FA&AHFC+mqG)sIyJeL4Au!YO|3GunMD(X7UP@v;zot2q&5h|RfTLUgJWRU zUZ5r4rHDX_w7zQR5b$i_5iiKuh3CNlZNMFpw!HC!%q^?l+My4rjGuB7V*kVfCViHo z08UnA+hbErU%rzFbmW)K%_|rhzm!rt3%*st#iCM2)JEr*4n0-hMRJI_{Ig>#;M?%ml+B)Cw0u97_Ld$ATder*!Zq{udmxOPF*v=aklO>GiC`6bo*+lm4LeUe4f zL>kkN8KqemL+o9w&x5ii*^K??hWAw3)EPJ;1*x`#Ft%8x!3RM>ts#!}L&f*RRO5E$ zs~kR0g{?b()k98RpP$PUJ?ZO5$@zqfA?s|`XaLytU}4jyuaD>6-uI6(;7UPnmBRh1 zaj-k+AxNQ>^`y*N!+HN(H^fJLCIP|E3CW}c7>A9^N!a<~JVAnZo}j>1xzxGH zJljmdw7N$K;d>`^-C##wwXSJ1W@@)!+~)Gi(GDlM=P@91`gF9RHR`f@HAqrN*yU|# z=r{9HTF?D$pqF?90wqeK!E+15uwbrz+QWMxm*YG%JU};-StM9%LIe46T$rafz0paN z)~VJaDpUgvI3~dWq6;;~YON4C31b#R`rz4PKfg}I<(h6c_+w1c1W&$cu$`w?6+Fvp zL?CTSL`TCQ>XP|Gw8D0jD2@kCK_FxD4<%-eev9AFNILZ{%4{kgV3oIE6ItKuAQvDO zHvlB-EwvEV`V`{|r~N9?;y9WU6*bO zUZ}u-POp${-Tg}M6Mkl!mokLneSsBMNTI@RV6r1RbxqBkG?+zB6}RTn#@9*uzn9Y) zi91D^d2Brkc@Go+WHCCIU#XwV88U0uzl3vzTPWb?W8>FQ?y{$f9DX7jWN574QO7pb zJL90r%QL3)EF?R^1oHclj5i>W*VY-Q7*NI}L$IeoWu|cp{(Tz%XVkN~ZCGQ(TdOg( zwQkAMT&=P)kGBW13^%Eh@VaoBTHLMjG3({LYy6G_uI>Yu5Ut5&z=g$hNwqhg214!0 z9d1AfsvjheU^hGuZTN(v-?Z}OBg9v3;J@O_W;*hk>oe}brTqJ1gWMgO=Pn~R%aw4_~R+d3$ zycWY{&-&2{S|!>0a=%wcoB`^yl;!$TiO_{o;2=d%dob$K*Ov_A4x7>FzCr>^0twRwfhSgzSqLbzoSfW5 zorRXS_XH@+Q@bzBGc)WEk;RiJ>bCrJ3)vrK!$VyGq{U{hR~SxJ7p)cQ!1IVG`Rp8= zKtbq}a%<(%oS{_3>l6*!ik@rdb5+SrRb{hZ-SGY9>WXI;jPJO3{;qsRtzQ(+2-wY| z&IVaN+mxTuO4ox=3woTwOZ+<(Uc#_M;i?Luwz;i^!>7b9#7ZADZeAfBLrlJi8}1l& zY5H^tI^1r^-L7IamfBPQHM51c4TTERCAmT|R$!-+B@e9oxR`jk8^}h%9NoXVo{Dn^ zYgw8rldwgHRBbQH%&~XTDl=Lxe3DtXk_IT@!i)<%%`*fRvflBD-!srnu8=S7Pxn{@ zIbvj$$F~dpm5VZblzYGK+{}OdWxnbm7@^X>f|^l<-oJ>g-^WDe4VjftlGP$#;YDiz zXK+?OsB^qOsl|KSoZ(tdkxA6)<~M?eoI}l1ah_kc&D{0eDug2|G7D_iUng}%n)>cE z#zs;Lxx_qXfWB-e3kKRoZxz%>b!!}N|K3LdMZ{;S!#S$)pDbd!^4r@xLuHkk-C@lWH5r-ssjc~vUE#sW@UyAWYe8}RHqE)Fe; z25l*Fj$+F&9lJz{T!-JYg>vNG0fR*I-Rv2Z-^Dro;~jS=YoM*xAi3TG%2Fw(5%{vr(i@HVUTXAZCDf7GRIAKPNy#izaDU89^CAzC z0wd#HXo(fbg=_zqn(JbgCgXGIXBAK{mw}5iTqpNoB_JY@ImgP1U9kRve)v7!)qCrZ zG%wrDSa@g&pq+n)B%E#P%d`%(>bLPNdCD*};F^gR4yx^jtL0WYsF-Gz>^4fT%6As= zrOD=U)8g~`$44YkkZ2B#j~DAo;;_4IZ|L9_Xj*B%DKnJUV9r%WJs{f%O2tFo=iy0> z5HwO$Y+jRsvoKdWNGGcKxj%dXR-lUS?3_@7TTlkCKqHG`IN187{x(owihR^kSLXuv zqW|H3wZx;%{)$f)QJo2iaf?6a9!Y$;+hvfa8@KztpVw86VPV85q#bsmza_}*%Vc^5 z^>!p-nN{`KhdILWgDton+L&$BR;gcEg@Q#a!F1vKXe)>ClJjt?CVVIfxWTFt=Js^t zh9(me1@2k#RWilbbAOu2%97wnobFerwmNh!LCan}3B(1+X0h7@=q}X!BuJ`I`#pG) z76Ig>Vw2eSovayn^pK99CFo~h301$B<%rqcjy9Tu(c$4p>C{qayS@5lEnVi$OIg=i zbQn89@jH+tB~4>sL?LW$a?uFeEyhN+D&7>V&q?q98DTx1MmHwTX*#0P^Mrw9HFTka zyocw?$LZScY_Z^BoXM&OIKDL++Bl&Uc1~vtHYr%JJMs|-(nl*Q&I^2kTrYdN*%l*0 zyg}4tYmX<2u%(YAf;DfZhD4`wSwwGR1n7^h_~fI^N=a$O?Qe;Thj*x-j;T(MtdGY&~H{pl~-LyN>GX#eIRy9@usB2r&baYGtNURsX6s(MKl z)?__g5EsvDKbFdSN3J1hbKcZR6F`1dHNLL$aM&c#Dc}1siMG{Pt$mp>@x*X^j|szT zhbbP&1T?4}Ji|Pm*y30U0##hdZ2-)mO@1T`5TZc2rw4$pGq?Z{N~_mLfKo z{q`?!H4VGThEVDrn71UDygO&K=vQDNsGt5g7W zp<+qS_Y@*GXHD`(&Rv!e$Mr{VIgfeNIy-?>`%OUijPI|7L&e&99ax8oSk7`CeQ%gp zId4N~A;j13%Ge$g*b@~D>Xbp)Sq&fON?dggG^Ot7SYo2l@DrIwZ@ZFawxmRXx_f)hTobCWbtQ5@2MBlBqKcjTObjE|@pJpD$jPVQsnjUZ(an)*&lD0evltLZL!X z*`Dd#Kf}kG4E;vyuBdMI|2VzOd(3@*9%Mahjh@FS< zcz>)!&|ZxaM+5umPhz156XT!2O#$B(| zdtF@v4^no|x2D>QQ86)5@BPlu>!fD=wlp)PN~GKJWEK7XVQjS3h|9`gs|e%D8$GnA zRKphBL|BliJ4w{;#ff-}h{3;voCzTnSAR^`;$Whpz4*yS)jz2I0-pxUqKEz1*iWv= zH7UmqG!MU-zWqf80Hh5K)0DU6lt9!tPLeoCvQxAo=Ib23EWbr>fJaS8!QYyKnsweE zLqb?EvEvJnyBWHEOTzM#ZBb2Nd~9PqCabvlp(U!D$JonN4qmo&$9D`-v!bV?%2v$= zh~?+#8Efsy5^JO3J=pBV-?3ld`d2;weJcmJi$HtfEEJyM=3P_!Re!e0k$qa{#wkDQ z)Z9vgvjF6yY`Uliaq^4tMFz^!5qssQwy>AY!#wB+wid^yf2MyNpY4u4+Wvq*IM-8R_lOQ)s& zRBP8X!K@)F>xobT;&98sYQCCZ8_k=95LS(?Tc;;egRsrCreMVZMy_H4;jc2L#=hX~ zhz=cY@%9oc|0^UIOX*2Fnz$nE%SYMOHWLUc6C~H)a)m!;^>$~!f5&n5d(ajrr>LHj zo1W3RhPUDf_oFdbO24r-OvC62MGdoA zB*^O_j}nBB6iJ;1549)6D_*ULOO0BCnp*QXH_LNe)8$W zca>}p6HR@*m?DxT-~GwW^3`o=?dIKv$%jCPVD5twjNfUzleyW;8<&qC(1cwj;EI-o z<^27x#+yNsE&ui}jt}k7_M66J4oN+~!Y+WnS;%$5)n{?QmVRr_xC!aD|NM?5S?Ak- zQZdwJOt2OA}Y+wg)ck+!hDSPdO5KeMkCVA1N@v!6%Kr?8UKF{dtCa0shv z2Y`yxINsIC{1_-R+d*SD^(df!$YWl^t#=3T#%U?y{0Ezx!RSXcd$O3_PS|*2&?0Sh z|937yr+NB;XMhdYdq9UTF~9daSmb*qr27d{I^3r$uTXxX(m5`okUadEi1F;x;Qr~g z8uAJ$K0r@54ay2f%h`MT0hYK)q-|sU`>afM(eI+`-3MaAd*)fKX)-N+X+ZDtPHUoY z_0AffoOfzz-N_&eTHR~2IgoesodQd_jkZKXxt@0uFcFLtWhIJ0RODq)N zjcu0Wod$EuMo1Pj35u-A&>7q`vipb05r5S-V|b?D#O>q+>Gql{8$SY61&%H*9UUET z*9RxMq%m=yHB&QaXjVPS^FDKZpJD7doNpHB+8d31P8kO3092F_wa#)T?2_fylh~A+y*(w-?^<3D^k)M`=jAbB!>4sO!bN3^ttKi}@`s3N zg>3grf=*~eik!a~U$FJLS4=`A1oJWNKO7^3simSax7>BsORDlbG4;pC=SE1tlr5F1 zJ@s)(vLfRHX~XOXzRp*-?|T9~=jhP_S*}6<`A>_ZL%N4OqqN?N>q{J>t*%!>nh#v8 zlj-=G1f71oy%ZgJAuPcaV8#+HPJRcvZT*;5*Zs7;O2t7&dT+>T?BSy>=uu0{xaD{j zu|f(-xz4B>JHAP9mGj~QtHxYF(kl9>0Z{ohE(JKP4$$Coj;X&vGL^HZyYCK0R=FZQ zcAv-jnu>8^PWtwml;l1;GoGuI7KkB5`py%t_2>9vdy5{L z(52|Ed$lwUGy8Aoy=%o{pAS3C9~FA{tI2u;f^|S4a`QT6k#+M!O={J;l9!X7C)aQ) zCJ6(^LhpmSdk66ngFuM+*?fsH>1NbJNBOlsq#@5Wk{=f&qlFm|)k<6JDFovgwucBP`E*W0I;7PrnuyIiL>@g++6( zkvv@StrhL>;~^o5TzvDUb_We8(6Z#z^V0QQN8gD8a<9cv1l7(6sApG_tLuWCwjbwS z^s6L`A8Z_~F2&StkA#2;nG)s-CgFTeAEuKGAx#;t&X| zz!kjx@qeWI9P&Ea`cP_kug;a5qQt$A+LF(CsU7qAjHTTm#NO9(R|f8{S6^C9KYa{% zX$JWX0`yW+i|zAzRmW>3C4`&(O|!x=vf?6U(jmrSpu~$lTRbU|D=Pc>W?ERh%SR6) zTLz1KQz>z;9VC=l;fcbD#V|9w!-}T7WDTbiVDN$^={?9*GZDe7dUU`)usTufgBl4V zC8Qp3SDiIgov85!YnaAI4#&&tDPOTMTj{-~;i zgt6+$6K#I$&bN6mVbAs6QDK+0keaJK3M19dg?sGZiuJr505QZG(wW(=BQH}|<6hW; z@~;i5wfM;V+C7PrT2U%~OIz2qNjJB4unH>MPwBB_in=a*U-{gxrtpxZV z^$T4$M;OqCzI91%w*iAIqSRTgu5&NAC3xnVwbe-VctZ8nq+bKY`GDdW3^|o;xi_mZ zlbv$`p70*`AeOS$(3_y#+t!^ecWynF1CWzrnkxhp!-Cp$wI)!{!1j~UK?FMHy!b5u zqs|Zw8_1SYG4DwT;s1EFC*gVv*I&{I-o$Cq>vQo^ZxzMq2}HhIdf_{+JcwHPU;t;1 zlT7EpIsM)jFEm#Pur-{v0s>GkaN2%c0UPY;C*Mb4yTg8Y`QO6Xr{6yvU1#QSjeCf_PAPT%RZPid6`U6Q0H8@u5|>Xe<~#BZ$X?(V z^@~*dQTTEqJ@Cj3;oPSev4waNyf~}LdqYX#ANZ#x@ATIn5LX?X&fYA1$WAsBF3wrM+`5Rtvte5OZQ#wEeu4yo zl5y;(o9BTsa@uVF%LAYK0c;aUK*}28XUVfi56t!u;0)ZVQAD6JOBU&(xMi9Mu@|~2 z-386&Mj}E?9_U&J$ifs*Z*=nwAjEgLyhIHS-$|p%uIRpx%upr64jNm`6aJes9r2pZ z=v|e|E!@mkr}upGuSpAEvt@N=m$ok1mym~%F;UE_6;I~!&aMgRIj=E0edB$6*dn<< zGmsZTvAjS1qc08sMhPR`(eoKRklP(SPhzTEK|v*GnJYl~OF8x-9LU1l?*GY4!if9l z^$sZ%q;VtFfF|018Y#F18g$JZG_QcDSg2m!X&>7D1)O=J(=$T;FS@v_VlOwQd<_)j zBQ;W0;ddFScXyIsjlll7tVJ)U>omDEi69J@q+V^ zd!FU&1wK_Mqd0dR<0^fmAqo0EJj_t-?YDj{qirr&IkF;9gEggk?1|zNMr8H#O|`Ly znk8mRH)110u>%1DOEL}aQXeEU->wn0rI5q;+-j=9J9R&XhsPBvZ zkceJhe*I^3<`@K?uXwTz;CltvXBZzw)Y5R*7I`MCFnok0O|~XOCnNbV>kF{hF>n zB99C5ir`{UyJFDG!IYCLBq=V~qg)Gyr(MowA7uG5KuVmp`+xnPS2938@$Uy(>Oex| z+Z8mql_EOk9^vh*4W=6mt4GbPuJRktegkaRP`jxFZ&0pl(I26zP*d$4B)P&HEmh&;rQHo|h9snn3+4|tE;VMHi!_{dowU} z{^=7sP-vPPdfr%JK0<|-y65ax?*eqqg9hZ$V2P{y?Rv8|-|*u8{Wq)}e{cbgTasJp9nk68y~RynS+TfGO`fdHtP(o`h7ql@mGCagAWhln;9>dqf%e5O1Y^n|4 zB_)bQVJDui)o>of+j}q)dgCqwTzM?j0&0)j~Ggo~5$BY?n*kdo`O zT>eY(9=*p#wlh^qHXz=S6C|4+ceF8jEu#x)z+5l_+{YD904Sa}OSN?Z-5P}$Vmj%q z%2zpQE)bF~mIRNoFAvY24YGzbQ9QXP4*iu_0jH3VB(lKo5WZ2_Jxm1U) z$NWt2^$Cw}6b^^WDoRh|qZ1|AK(YN45KU5~ogllaE5IUba=hl_^}CMNRQYYz!$H%M zw!-;YdpHoXd|s?KV?I+a&WH(?o`;W{{)T<(4O`=n3I{>Zmfts z8Q$R_nuv?p+$N_Dy(#uqjn^t*{q@eD>pr-dukzk@o0QF=akm$mva>WkUOflGiJxC5gv1M2 zIqojBeWzOIt*4@)kse(G6i;TG&T+G7wE3Playr_B{*EY5WVL*Ze=jL=Xf3;aTY}eYB(lfN&CRa3xoLv4M?Bd^DNLHjbD1=6pCK%T&cpGi zBT$uFHPh8SSMF>Md@R5qw@HA{l%cPY+xw~Psmz<5Ydm_qHZ8p~jAqPT%PVtxUF5Wm zKlzqJ^5+i^my*s=*I^7=3;X&oUi z-;n&~F$ym0;D@*2b^~Dua%vI#vF2gqqpCq(v+<1Ffz^>sn=Dn<=bRW_fQ=0T@8fkA zc0t2|rebn-eoKns%x8WxVP)xQa3J9r8{4gw@q07B_GGbmC&^piekOou5k-`)|7r1i zvz+>~D);dWGu0fopNR!6{RE=|#W7r8+XdrT2Ml_}djH!MNOK zuNb|Gs2biLT&c>k=jV9YkTR#|d3c%Vq@}3^@Wh=tS1+{6DhReZicOT`KPI%R))^kZ zuFDL|B$qZ~jQP-J2t1VvJQw$0so|myV*4pj=9S@G0@XTbj52I*JbaEgL0PID7swHo zXsk}5(P~eV6S!x@d0FM9nAif1cY*pAW+82;#tre&s`w~v?cucckOu+H=DJ4H)7{4A zvIixp+nsb7Fy{-y!H_OyPktQOlAvcKy?(uS;CWA7t?|)hNp!)tE1FlW7DtHU8Aa`e z0N23ci1NGe4K~ul_U%5yB!KeTQ2meC8bh2F;<$u?goc-k|>Ccn9D_ zLCai83&jJG$mp*C7}Lv@gCfNmT)>VFgCOvW01?g^VurvT>r)Ikd)mBKeGfxVQ3HOG zwsGOiTf*245Lo3vSWXo;F6BHi$3Xopk*)DCwOFNAPHgYt)h|)Lc&Dg(OTSaRLPA%u zQWxH94#iZdiM(&p4}#t$mor>VJl=brB@~ABe0>cvUjf6i<&}f70Zh9l4PRZw2~=v~ zX4<*KqH9xovqOqh^rh&qM)SMWzd0Xp0BH!O$$Z%Xbvf83@sBI{ANuOQYpMBD9#R7# zF_a3O%3~w@!nC_Sx)jM5emZI9N~f!mXMGf;Gsa%%2d8<4GRXDlh~RA4^FS9Zv)Q-Y zsc~Fy1^ryQG2_C^o$veWbpmg0Hr8%DeL@Xpm&kkCeJc7C^*G_RuxE&mq@+v^V>LKT z4~R}ziXXRt!v`u_{ynvL`fR`hyCPr7b^e!_cj!dxB%?j#pm9N zm1E5yoDSOQc!+K%6@o>dyBMno|8Sq_&+DzWe$5coR!T|s2k~`!kyB3_Ap5-6FZ#cG z_wvx55A(Gz{SOav)6)YWkpF%c7c_U-U{g+t4d^h0b<1RO{pgTQW2(~A0<)ubtxI-e zmMg+y1D{m{@cDCeqCbABX9x^)zt74_$HesVOPrDXoj9SR8|o(IULIw7)wYB7WSBw- z!*!KBAdf9#xBR2v!%XAi;EBmlG)oM-?dW@KW{XYlYnOp{+=ma9=EHy-?zEXxYlT8W z81%E`Wy1$ogzRDgHHY1eAgF#~t{b9EyT}OPjGlevb@DXBy5?>2dm*b4=U-dDn3OCd~qvtikpZ(lDEnDCnOA&S(jMo$Pytl=Q2h8Y1gvhi-BAAEgL8|5RfvS^YL;Fq8u{o90Z6Gt|9_3gqun2|Ck}uMH#l z1O(zk027o(-K+J+nb55gzXKQS3JS?|vfLN07aV>rhy+w|%+>;{~r&%#3IAF8N& z9fWar-sg3~rjP+@`At z42eewuFcJLG0>+{V%K9xW|-t^?bS|AU5O87PlhObK{eWc8EF$be>UV^aQu%VL&nNk zAF=Mt11l3CC~m0CJd89LjqZw%682$;%)YOLv?!6+74*2rcKq;Za-E>wsvLGiK3K4X zLJnL#j;bskDYo;uZvkUN4lvW+XA^U8&4|Ktws{;ZD3_k&b}V~W)hkh|?)Ymi7c+BT zf~WPMBfH>s@A}rjP-}>^uitr`me8B+b4VHI4b;p*`QG0Cna7+-1|Z$#W~jqO}?^AI`6hYpL;rB$P*Xuj&5f z8$)@c^-^-`z5T!3KmS<}Z~++pfSB51((9WRt*3G9>;-?Ih#=2K)?(75mzJz@z#pZQ z-QFShdE|Rr+t0$baL$>hzdE#AL{R--bQBY2$5aY64wFnWeD;2N0PfdRIKhc#1NKEE zs{u&5=g$okKtjth`1zgBQjnLQO3cW}ct)iwkb}`kb7K;AUP*WU&C{O+9Bg9MI)Uk# z=eTLgKjCY2Tn_uBluCe9Puy$u{NJ5oE$;U*B2L!o@#9-Ny!DQ>=v{v;>>WPo=?o1* z_9jalfmDywqXwXzWJ0EbKoP~cSfdJeKqs!Qu9jI&^^obPpFMq}e);)N!e+?PN3c&n z%QSKo;Jmb=cG(+GfF%fuGv+ow@|jGWH=lGnk}?Yp^wpWUv1k2S8X zXJhV-V%>~vK48kR^4{U#@Y(WjEpo7D0ri4E5gQvtgcrVak00FoWI>6Kwtl2zet|ui z4k-tB2D(|1vguFSvW^17IE2p@jf)??jtjhg-hmCN&%mXMGo;K_hpP;ugoDh-o6<;E z=RdCQ+50l%W30o%<17CfczP0B1ISP{wx1X&y~vxL!@hTjv9s{sR$}!3TPxA^h%iDi zl|;_)w3Kwv93Sh14mbm_tSavF)kJUb127g*xPsVDGZ(HEXkh+|DTLOCG|sM4L*K*N zPw%t-+%GoY((LmJ&t3(Ro4>e1v%e~h=!6>p1|HCW5$Qz4DFbJ|!iD}*O8mbic*E|6 z^;`oF&UMPq)C*=6D(2}bzd>YGX2v$3AGlwmC^y+_ijo5SXLMJwL%H=?WK?$LEv+ty z|2Y&0DS<1dPI(ZWEik^f{s%$y|8}(f|E~iZPrwT~IiVPlVFSH%0W;fhASwL~d7=-V Rn_)WciIk#b-oqEK{}-vfmMQ=M diff --git a/docs/screenshots/custom-web-mobile-inspect.png b/docs/screenshots/custom-web-mobile-inspect.png index 3405895fce6657a83c0c06e04a29dab528de7dd0..a27f59d14520902712077ab86d23e7f293e41aa0 100644 GIT binary patch literal 49048 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%0AG}T4@PqFFMD3gj>PDHBAY~=)UH>em|#4q_VML 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 )5#5#y@9)hcdKO+J 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 PCpbD9hU%|W9nk*+IHr`J literal 70493 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 diff --git a/docs/screenshots/decrypt-file-workflow.jpg b/docs/screenshots/decrypt-file-workflow.jpg deleted file mode 100644 index 322e96c2a083bc4de0dcde22b7d85faba708e57e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63202 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 ~yeg5qJ4y;9A zro}d@`2vx{c{VeH3IUeA;*ozY_mWFk_xe6_l(*eTT0e@E9dR5B5LriKfcO!y(nSoZfba64>?m!9{}&pQT70@zTVK7i2rW(Lk?GN z%t247VQA~rOs~Pyb3YAkHugEE76dDGD2Fe4Twkq&q7rmy`Bkr`DG!HZ-cGZx(+jzS zzj;99QdtF;8~WMbtM$q1tGhuUDl3%W8Gjo#CG3y9%;x6r+CS|&(EcC86IlattWePmJLRk{0jLr(` z`(;+KSOs)pMUs&;8MFsDMGJ5J`s25be!G!=tIUgH@0_UZMt+8-(g+I=y%289t47b0 zF}*J|?kn}mckG1owD8F?lW((WxnXUWiFVc!xXg*Vn;q=b^yx|gJen~F)*fH?#8+LO*`Am7r^a!TPR60qg1gwW1cOyZC*a%owUpit` zF!6b33bTvwATK{ZH0FcUwR=S-R6Yzh0;KlwBc3SAeT=kFHLweOJQdBT3&+oFcGW+X*mvUhHR~VEJk;L)XisB5+ zm*!?;KVu!_>F)?3G4N&ak1BlgPYfOX#S!r5Qe*q^peqmL@d}_Z`t$P=LXsOg3-*)K zv_fD16bt4rtiPWM#uoxnvJcsN z6qi{uG+SO}CM*BjG%yu$6yk9)7QN;gFPY_%jBtBSyIcWyifzdgUL-aFL6xE^n87h8URd-dJw z&R;m0i4w!7NuPn+-x%m%OOEw}xsXwjC%IkQ1Dc{YW&{_%_Q6*RiJG}DzQo4G7aIG* zKl$_yP$OHNKiVFM@_6UhyWSO0i3Oz$GrdLW9xB3ufnrJ5WuJmp2cB8?=$&s|vuY`O zzjiFq?mN6hQOUhz--6}3#lu)oi4`R@N?>Nq)f1Ni2mfx2`PaPw-0*AM+iWs7OE=FH1199{8(J6%g7_koe23M z7vHBNK8TO$8%VcLVtjd$|9E|N`}68$a_4moK@~|M`7MfS0~B9>P*uGu5;v9iw$LU( zs(Akku=362M=WIKQWj%FZBz0GwUCrXSc3&}ObYWedRz=(9O|N>+Spj3m`0LId~45m zCF|19_}>rCJ9!Rk?*TmL&MbIE)WGD&h9nj%wfMXetPkyZkXoJA&cC9{;us2x>$>=9 z#jMgIQgeZu_*$5Id}DrWVB&dv=+@1RuAK*+dGW;gZ60d{pDA7nep%lB`DPcVA*zeUUf877#af5`*&!ETvgzT@(r;_1 zmq}Y^iqJ9$G5v2t{UXmjW_E6!J>mUo4jRn1U;}G-O%t(>(dUQO%E8@Bea~j|1CO03 zGtXyRm6W#kE0cIh`SRYR4n#+lysQtJlZul^&-)l!aRa*vl;IKMXXEM+2&RkI>T{d( z*AF|v3Mo?Ej6;X79-_H*TOnuxT?8@JEM8_9GGbeZ@*MFZ9ie@vg6Y)x#??bd#|Gc# zb)?JkNZ>O@pJ66j3KAS(OM<(dygukPY3KvZYv`aQ0-bw4(9KdIdAR@GJiVeCf^OUQhlmSCEVO=iz2IhO3p01mp+A#O?;`V_Sd zl`D_3D;+>imM&&LR~n)-=Ru&*eGGm7?=f%poTOsqtX`}4w%XW~RkRX9lm)d|`mnJz)&6F)dKY=Vj?Lq5 z)x*(hUBNN+SZ5;Mu(<#uEra4&-v$G9C-A`t=iEJj09#N#ar8*Sb^!5#mxAYHLxVUG zPZ80TrpeZ}w7uD%W@P>QtL`n;fyriS%O37XDbIuQ@% zo;8jL9Z#_~!FK#J4lQXHr1rE`ym(4*)x(GU0}`4^341!5HhVQY5EvurV~7ZfMNh;G zOdoWtITO=6X1ZcKbFX8gHmB4;@-*?H$m4B98@P%8Wgl^0(tN}jJ)PHOYM4fwX3rQ` z$8R4e_f-2Xz3-gTbL^Xzz1l;c26q8{wYLqyHf=n0c^1hM>ke`E!AyuxUBak6cyeG% z=wEQ;GK=-nn%zYr91`3z8w*)Nf2kfOSoc;qv;A?8P92K(HGYq;To@as@zO(-JffR-PwE)+{tCWrD~ZzPKQa)wZo%r{X|X~O+8gLv6OyQ6*Krz^ zFG^FSZ~m;4V3ON?I<#X&9rE(%_H^;t@<^nvCT{GMeJ>ZW??>oURw-W=zI7oir@UTO zV{|d+`@Zi9v~g&s{`%(a09@av9-pth^F_7>H>Z??gVn48+Zs|aEE)sj0St5M8R+_r z(z37&*`+A#qrAZvw}@wTVUNQ@JH(H@SY21D6`aJBO(h{7Dqqn_!Aw z(Dnc%^Nm%vt$^`|E1T7cm45L=n8rKL*PHLsL&tf#jXj^lW?lz$zCzK=@Il?ZuZs~U zyGzwvuN&5Q1a#=bXK(zZt=`xJ1Y@lC0Hsg&02}8oN|bHnt__`@n?FYo;DJeJ4JWJq z_CCwF8>=FUbi#zb9-Ulv+$9IK?g0pUfYDqXyNP{c!>KoW0K2?>v+(oA;reGsliDP; zioNF8RU2TRi+U+r_gsUpRi50-%y?1O=Yd`?R5Q{*TkIm;LBu*SX){?f8a3#r_U22S zMr`+Di^kwFzx%f$V7l-20LS(KUpg)>Tb98({cZV&&lsCR^bLiiAI)_lO`=yD_?u}% z1ZN=18nL{);a1XD$m&GiYK&d`WHD&AfWnv zp>C{smjQh6A{>t1xAq)$7*YB7)AWppZ?djA;$d*rn)+4{phtuwViYi0g?WD08jd(QohgE)7x1{4P zjh(!m_HNg_wK|eS3OPtnMv%+7lZk~%}lyvepsQ7yTZw5?hjDRxeTIn{&e!P zGJjX`Vfl<1H9#cr8jeIOv%(6UF|=9>yj)$QL0J&DOXw zJd|U(r;#zV&`-SYl01x3JP?5%pU&uU9t*#Z?$06*H~VNZKatjKV4qSJaQdVO~qi746kbrl56NkbMbu${aNbHFOx*=0NaY_(rHS#lJUK4V=ZE0$b`l2 zC2m-MnN>?vR8+=nR(I9uj(X?^C(vdFhiWki+U}F-rGAH8&5r3b&pmb)jGa?iv#FiX zjeZap-N1L7z_EJjE|0@&HpY9dpXm?H`x;_AvtVhCgkijiNlAEbon@tDRo8v%u0wi- z0tbSa=FGfaNhX$`LHIAO+#!F1hfmlVI=J09KJ}yB5(RiCW$nCsB!El)%V)9ozJ-M2JM+wa5sed(W z{u*h|v_{y$(GkK18M9yy#6=(-Y?qmaGK(y0a@II6>`$zDZ z=XQyeE(N`~DNk}{iC$1*JyhzNZ~THOkPz1!RfWOvMIKIjIG;>&p32>HY~sSq&0$VX za;~s1eD`=3s!m#m&KG&`pgzl{Zq+aHLMpTL(*VNQ!MhAx%?<*7e~a64jOzZf)RUwdaQKh_s=#gSJRxJ zc$0y_z<80+8z5R$qUZfv0i{*}5{4ZP^RJNiL2gVU)yYBF=Wb__5zV7WConm0AD)aK zw*HA4j2K+n10(`-cT}sHnARPs8@mbE4`Z?7q0hIB_EmDI)4tlx42DS=3;SWfZf^ej zmYFGK=P{Rn4piUT#xEeXr2C-Z?1bZFEGVt>b5g0mD{T6kFM{DA0~10wH>EeruQ*&Q zd47AkzYJ#zr*dx)lnY%R*Y|?Hl*iaRDDQ?S&Ha{#W9zb+c$ws30)1Kc&BwdndY$C* zyaOiaNV_dkZ<(RDMPK9ws4?c}*Q=X=V>1iw+D$o_vA>!0vcgcE6htG72^4A%P&;u| ziUyX?CqLY3a=@}~X}Hr9%0+L_oF@=iEaFF!Q&0LG-F;{`q~ktpI)zG(?c|y;-GFq$ zeZ9nOx0d0L1K4s+2Y89B8}0iwhfn>pgf419}Lqd1#D)N^7AA$TnCh zP9{T{VW%y&P={z*#H1KMu5A>r5;ixg#aKgJlw>g>BMn{I$(s|fZ5nP!Wb@6#QA<8a zG*tbhcyK78&0yD8*qM)52uwbato8w@E4&;Rt?ew15k;#od@SV*Y<0_ZBpL4WkjCIe zoQMCssybIh1Zu#%%Bqv7KBHEcn`~f*Rv}`Yjx_4By>TA8^8>ZQ)>%rLT@43a!8r*tPG(7b(r7W zq8*65!4TBohW#v&FlG!KNX4nFj8TjfE{t)SsW zQd(*QgAiTZVmR}nK4oC1H}BV##OGVIp-=++x=a~(QrRHEHD;j*AiXFCL=?aOwNcO(e8L$ zo_!(b;*O!`l@+0w^=7A9h8mSz^x4?22=PJY&8uL9g+*%7gU=cH)E7R!VQ5aMbL!Cf z@L!9W#Ur&-*1ZcG4Rj?5aigsiS8uNpJAE7@9?7Ejzr~GoJ0Iz-t`8b$HRGG7GTQI+ zl@Ry>b+yc>%;(kn(#pLT7hWfSxckCJBc_B#M@Sh*=lGfRNY-mzH%O_D?p|H6%fpio z^q|}rA6U3p4@%P(@Zx``X0na_T}I6%5g2H z9W(e6zl*s7Y)Gx~MbzIF($5bj(kr#Cy<)f%%LVhL?dEpVX$!Q~Si*#%^ZYRH?56cS z`QDwoT24c@)b_aAc-dBNUrEHIjr27w`f%LMZpLE#Sz1_{Rb41uCVBz4bIvZjxraRN zarY_9{7`&bv(Mu%p}FVeM;Y<-zx9{J)1-pSSc)^FexQVSBElOub+t7tneFtf zl>-E7-#8pD&FBp^Ynxf{utbe#VGJxCEqIAn9P6WL}FQ_+3 zwG1ImHgoKq6AdSQ@Q;?@3mX@6!msZZ26b&SU+==K?k*F?F1+l*ODUJQm+_G56y21& zK_?_F>?Y_HN|}tXL~=-~R`POMTSP7v)%D6)3fwI|%tz&jTBOIYNI9T6am_FI>DXw6ed z7xYS3l&Ti37~>b~I;C-AmcvEdh_N}f@mTj!srhoURj=<$`#IOhZ%yLsbwwsWv6j&mX2c<;&A<*Qm=Ua$vh~2Vz+|wt$(ffapPjf#_8h$*;8$~3kCaL7csoOz$*|!Q z9Z6;~7wTwt9#}#U5Elo8h+g7VIN$k9?|RQihM)fAhP9)<@+)-R8pJ>8j) zO(c^yj(5+|)`?q4j7pu!dCTOB;tBSzy>oI(cpYsB zOZfC#vy`?)Wcj&rgdrS`S${AX8gM75Bkg*!wG&qPT(p`k-(@G!JLr3}b))I8ZXGI4 zG+Gxu?RC6HFXwj1<&IO>%yBFbJ%N^%_CT0frM;Wc*SK3f^EyMHMi7Y9qWDnmQE9ZC z=r}u_=B5dwrT944U{`PS*hx1#6`kx$#Sa2)P{TQd^7$<>#UG@W6?ql|;vHVXwewUW zZN~d^fkLG~)^j3JOwOA~)aJ5E1NjVu5e2GV^{kN`ZuqCUa6pxPW}VsVlqoRuLTVi} zZ0oi0)3zSz!Y<|V)@z-|8S2UjH)~DhquG~fGSGm?5TNduMEUR+-!$JRYqT|~IU7@R zr0ZLD2j6~X58x-I9j)JIU-3IO$EYsVSO$7+o;ISM?RNUX(dDeK<;HeSnCW5~{hC!( z0`q~CGNZQ22z&`^3&)aV9w8(d5Ie3q&8Xh3y^A3gO6v%@*FGhogzW^)%*rHyv~H~X z<-wiNQFW_0eMI9pI#h`DJPUC4kN>hi$* z?_>^z`^VIPma-YVbsqzhxn}a=o>S5Cy-{NQ`-tRv9!^z6Pve=PR9SPo6qhmuVyDieOOwL|e)+H5{^uvh ze)rENUej;CcBRN+GQZHnN$R@%V@32t5EBu|r*HZ*16d@ilzGje3!Ak!gp?Gi3SJZB zj#Xa=>E{SYg2QF%mq)t$CMmKsXiSM8*a7|Hn1}6si+d@>^P1KahxPlVk)q#*q-@C`Le!GoU3p0roJ-8qwQEOeEj!%t?@)$e2)|2gyUMN6U=n0a} zKQr@R^M4Ef|GZ$St=Q5((8jquIVEPzncD*xElhrnLwdTbeDINwl4&b|Ak|!dTN=&i z-_+i!NZtvEn>-?-5r`gO^hv-3eFL9ulWgqxjersKzuvm}9DgB4q zKM1Ly%o*u@7pb16M@O{vEgzPbXLac{*D)~m-IOUfcSc5hp&1*Gq{)<%L!{Rfcv=#a z^fEcYZv+&G?P?PL`Q-w71Rrrk`h9X1ud7$!39`-E_p)7%<bIM82{Y_nF0#CnThDCIpz*kFYhYS+|R%mue4yWKcw0eNXIjeP# z!%w)8EEC9HXk6VFw5eUREo=K=CiO`XjVWk+pGc!)td*49jm_DY2b$8ELS+2$u!n+( zI%+Xb_#2O>!^9a2AzI*AL<{;-77)4lTWFrQsFSHbN;KD5^ zrrgevo)XV*x7d1+LNxXXlVt3x2x@TKM+%=8P?O~6LlFu0XxLzp(PPl2U@AR`&>JcP z{nAb4H^$aYgc{aJ%O5vktE?+26|6Y>Di?D^&c(9TOb{YC>bt8ow5h{4&jbFi;`ILe z=sbXuyB}WPzFz12>-7B8-i%b2Q24<=(5<%|tQcklR1~RAD`-f(^h$+<3;)K+iObxW zgzo>k&Hv+xexIrBmJX=TT7&9_H~JAzD8Q0LptQyPAbaP`iEDsEgSuv^UUzB4OwW$n z4DTW~p&-^NBY$GvVk985UvU^9Qm)N@8J05c_MP3BAw}%Jkf{h8HFX&Men0K==c##T z=N(Vq#pdogV*i2RfA96=SnM|)M+wO_LnH{S(Iy0{mj2^E`1wcX!mH&b*foDx-H*GZ zhB~7xOK0>1JN;&5XijkKgew4=1}RTNlBSr zKduzCf9qyWu&yNQNyS>^A!c~XfCH$y)z~5>$#@Q8-^G649Ivrrog%#7b68tDytCy` zD6AQ(o1Gs2sWyxxPT0rB$_ych4e7_je`D?prW{4k;UNArKTNBub}z82z@`x~BVi;O zA!d+3xc>(LaAbkP_pd~3GRRMuRe6}|M00`MN4y0m1_XW17lNVbh=}Nd)ci00jog7H zq&d`B9pZ5KFS7#gsL%F{kS?%f*PZ{M_qR&_n*L4RGN<`zC1o}5IA9+Mr0+)(Uhr&? zvrnf#3q+>`BDrULcwEk#pXrx2r&i^m-||{=^8%~Sp@*KhT^yw}3?DuL3+Df&QiV-3 z&7(Pv`g84ne3!lMwja_&s7hBX$Rl~+RDlf49fsBTwWw-EU%lXReI389WL>U=;NjI* zuV6M`oyjXqv+F_8t&lLs3MEe1l@5VdR`1q2%|cB77kBR&)#SSN`#P7?GDV#e0a1!h zX-a5P0s?{sLJts<5C{R3CImtY%>X(rAOsTx3B72LkV1l#0HHZmdKE}Q3n_hr zTI(HSpLgs%_B-|&d!G;I(@pY}z{8!pT-X2qyQu00b~Ym`1`nOoNGGZc2o>hwU%7L; zUh#)I47D(zxjM+$u>Qv0pbA0_4%#4--lk79pyc|qHEg+DKmUU)QU-FmG+;xs0r||f zcS!FNmA~6Dp7l;iG-Nar8CI25y@=5dc=&J(`v@`!8=K!PlTSDJT>|&^6nRT&`&u7g zVMAutT-$HqQ`TCu{m}SeiPo%FLQ)><9eE;J@>tTUR?GUywQhfNTGj~>H1*{=8tK?X zv-{Ojy3k^T8v&sb;kFHo6pv6r_Dy}NMy-QOPi}=X8x$&-&#{y}9{g4Lo2#Rq!L_l_ zjwC6=qbxK>i%P$RQg{B7hnpW<^rVfCU2|KYpUF(abKk?e&=^>9vFTUDxkoUSTm}ga z-=G&rz~OKNpn+Zp^RAA%dm_Gkm=*|gEEV@w#N_$$Sw39L!wb1a4q(DNz(u#jf&M$` zi;86#vA12I#guy2`$gDtR#rN7k%E!W2#fMc)k|+(3H^%9YZpAxBFT>v5%PH?8^A34 z&}Z+vF&J%)$it%(*~fIKDSzVce|?%9y6j(Dnw$98jlnHDQ2w9$*1uo<2a4y}zsWqu zzRvrNTs?5B=HCYc#t)Yz-)kJ_bD$OilzeME&lfsWyy|a$ zu1AKl)-lLvBQIW;d2?sJX||5jNJ7^uE8@~Ow{PB(h=s-r{EuodUAl-j>pi-VhU7bp ze8!4y9?P6*K+OU;!nsB4W%S+8MJ=QfyH^qa{^@;3{@|qDWyCW57NYW}2uU)S;1GmvQCY{(2fJ;^cWh5lUj2 z;|ELXC5_019ZXdlgA&)*H61OjI*M$HRIVe5V)KSfB&eUm`RIG@38TnuzpeRp1v5*I zFiyd6-&yYhCuFr4;vzh@?L*Lw8);gGw(}hZqcQf)H=M1HFQ*gA^kt>Yk^t<>v~iv- z{jfi?M#Zb#zBXb|upH8lnxCW7S=a$%{fSgtmtvt^6D!J?RdF9g7vlg*5-nhffIglM z1nFB^_E!7Vu(PX<7?f|8Ijo>%njqAy!WleKmw7b}f%%v2u<%VOYiq5~?0^y)6{CU?@9+Is z^OLWr#g1j7^j4c`H2Hox6^mT=hl9)mimPEa0@p>LCCjPV*Nl;o0Kf`@QNP5#IioUgjdWLESs4Xo?V6C^rwJ&V^J%)e1SW*sIFvy}Y`iX;|I zRMkR__6599%M5_NWZ>n5ED+4?gI>XJ8r5jx9}7uK)%)<&O(<1Rfl`0Q_5?YRJ9X*m zMn^N}AF_@bpKwMr*RbL5@N9K0$f&zJSlUILi0l3}h#)E|rcxnm2p8wshcqtA=w)8) z-?L&77u~7>cqCm}G4Y}!kUqoqp3lpvon_?Bzq>A!%5}cdT(DSn95te-OjTknI%5sV z80~pfGT}D3gV6b0y=RHex_o$(Cv|q~{NXm85}gn2GzI3XSQ8`@w2n`#=c|x{@q{4( zoqSs~`h+{#ceDBgo2Qf;p58yo-o52{HkfEoRfgXNp2N4Qb9~V!6#+POooCLQ^3aFbD+C&0*X7a%;6y0YyX(-=!41VK&l?fQ=EtWes>@a8mL}+#| z5MXYtfURQGF9T^`huJ|=;b8NGVQI@kHK@4_``N2tV(2!<%R1O*-wFyG#8HTLdc=o_%^VCXL_JSNy8r+mV zu60O2AHSam>Uv1lM`(DC<}$Ex%PT+h+s9hI-cpf}MSL(ANjIfLCWcCcQcK42 z#>80nGp=jYD`E)bH}f=pb{qh(wAKj^sczx-5B6pRr5g#ww=~i_0J+%I#z$yeeb0a& zIXPdQ*p2)}ZBG z8Aj#|`6^3nYOi_6t0GUWd9)%*Nw6`;=ST{^dd)L+mM^rp0Tfj$t7fcyV>|FHT0+_N zRP|{b<=R07b0y88_t}>=$Ht#rZ+}JA*GW4y81-%7U1`9VH)x>LY+y?d0VQ|Qkv!GO ztPkhHg8N&6l(%lLNBVo^8Gh3#Xum$_iHxlTqFd6+*Sxfa!`^=U^pSgdE{rR2RMm_H zTy!+~7013`o<^f!%X!gAZqL<~hF}(`<2GFFN^8;PcxkO4b?p0jE`}bkTs^k@n~d8P z;Y>e_q7y)9U~odsHzznMQ#Hns_Q>8mtgs)cn?keNv!uRcf6gcC(E(qjSaA4U9t8S< zWBd62A6Jq>_+gHtVQHu9K>1@0e$1^l{mblL6sIE##kuE-puj_=&p#~achzGKzZ@%C zVmORcaoy7>B`HTIm*CEJXV; zY}MUz+5huYr35_n{>=?k8Q6ZL=2m#c@gmY0zK^QmrKB<$D!n0;_VfX#lAlK(*pxBj z?xl=4CczvKH_T;SVSq{)0V^NcE-k8^QEui*!H({?)xJ--syP@r7IdGEA@yt2#V z)8rqLARZv|vQjLnE=2;4+a123_U$%T)Qx>2d?bAkSNujlnf0Oux>}4aY*j;YVei<& zC3UH(%``+p6C6TkAqRxvDGl4Cmf4Y<3xPwE{zA}zhj(y7;=H@n^!2$tsm}D2z_`AV zUq(E})H=Ekjj(E0AA9#WyH=+XVV&g-1UtiH3HZ##k>Kc@0Gev zFU+AID55K2U>KMQ$FapK)|4*elOD_yb=;POgKt@~{yJvGnBQqX>Kc{$6sIpC zs!K5(_-*iLLOSw(Quf1vus2-pz^FPmayT8gAO5Z&3#@=&9!<%z0Yt=9lf}{2*Xr#OZ!p ze6cHRG2^*Q)GIiq?vDP-^qZqXX#`MAD7_yhej&KL8+8@W?nr%$2&UHz=a{=&9?wB7 zWS`9(>tr)Q7u5KVkryxtBBUtki z*cH2bvFZZ*MpuPK)s3wglkgY#;WoUamH{$KK=izTHtaTqt&WYnxC0wGm*Y4R6=Z1_ zS!Ys=PG7fAfvbiZ;Iq$G8~X68HE?ow^ue8JHesr4+r zvzpn<0ZqRhRb3Sz-GEo45HWOKs)XK*rZe(6bB)AIQ`^M9bkF}DC4VEPZ_6-m#=63% z0qZKW@f@mk?6e%iY2HO{^*JEtb=Pf4*`oM@iN>e+QSvBVC1?@LWwTH3^b6+hYFf%# zy-P;u)9F0;9n)UiY}s+G&L%WoP49+xt&=KZ#05JQE5f>L)LT4Wm&@`MMwT|+ zZ_1qx+uNEwq)T{^w&9|~v|gZ=x6YUw`*hJR=JE7^VwCZ`@1ML?Uh4Fa$_%DU>8siX z_B6(D%UUH*4&WI|md9zlDYZ-PuRY!Oep!zi#FiqWlcq>&_+#cbn+VT( zN)Q|rZ?QTkJF8=se&MWnv*E)V!IZjTRRkTtc${Gd9sGM+D?5_TNC*1&wee8ibb3-U zZsycix<62j{??O090P#@vJ0Q>Ok$;a&ydc2|BmQJZwXyud7tj+xrvW1@sPA_sga^; z2Yz4QFon?F9Q2fPjyG0)a`Yss#&p5LbqD*>C7j2P2Ky9+_u91Vjby-7W$5^*DYO;; zHpjdWl^MDLUoo9?@?Z9|+Ee?b$S(*o=3BYd%11P{>MDDUC-B)4qNt%lQ?#Kh1o84~ z(p8An{tWZQfaAWJkwpJX&-{7wgQE~<5!WJhb@nSq~6Y)su^;=2?M;YFgSmtO@LaPR77uOt18>+>g4U`fm2@Dm+hPZx1FLii4yR&D%L zk`hAUH+i^T1Kefsn85p5;xCZqoRYyafq|97sVixxT#8v1uPgzDVV0-ouldD=0>zFc zAZsPddU3+T@tG66@w-CYg?>==xxa?}|j^!YyamH4FEalv(rBET*4Yqss zSJd@7E!p!@%@#io%r(GBY01%UEYfOLg<*DG{gi;aG*Z)x+EfD`W~A=kfS&+UcoJ}M zk4rB5!{0P})^q(N9Q{YP1RTU%EBG+D4^DzNL$&yQsCnnk`c+)$ zNGgYAQy9~92LyLplFM|Bc#xP@YfGMCi&tBBZ&5~riwW|c%6$FIW{VO21RcMPgOYDw zcJgym0vFF=%9Jt(BsL=kg9=%6vRjOGU8r{#7P13}gWKqMPJ4*Q=jDY_Yt`_oMd0Uf zj%7qVdD3?Nyd7Lg&nRIKNF#xVT10UV^dK*FyzztdKpe5qzSG*DJK#k7{37Pkt`s+v z-HWI`S|gm*jfQNd)faZ$i%NI~RaNW34R*KLefFqJ=_zs;(=xceC=;iDnFxZ}Y-~){ zRKNTT7Kw_ymp_jwcMZ~WwXasjuv0ANhFY7pRiD03f&Tvf{;7>n^6bSi!=@S7=#}IM z?%D{0mElBnw!_fk+U-=%YRR?m*$~K?F2LPk5Lz7`dZc<+bs*IG{q)%da%J!4O zQ7L|5&PC;0pm*AUX^{EkncnqFm1}RnAHz>RO&<)YeM{L?G>U%S;sB%(DTw}rHdJV_cs<8*03zuA~H$QL7x8Mm;uOVUW(DGpKzT>hBU)3Y@DM)r5&=Z1;w zhutABt4DlkCETwA_Ml30~Ki z?Gs%jz1ur(Zsl)9xaLteT!5)|Rm)H$TK>uM6r{9ukGeH`W>Z)7vGa2l<2A_;cS@kH zmBlrS8=`k{^UJXC%+dTjhVXJ_-Ee(5JdSsJdRia3E<03dzo zVc&?3fWet8v>VYhC@)^`w`$pYrm?;8QvSATE2R#OZmuStl$Q@#Qoy7fV618Mc$;8m zqO4595Q6ylp>?jNlQu8kFItwqU13vY=D=Pza)@X&7Jj40BhIE%bT{D3s=in9!sFLz z{_5hooki*|GxFSTIE&?pfmo2)LggbWkHm@(gzOtx-ei0 z)1+#5VO9>X)FRcGwphy8DTror#ugQet2L`d>{3o;UqZF{`GxY#ZgL}Y;(~01PP4m3 zI~CY6=K%h0K$SG3q{1ND8~iSBHJyZ7?jSfeaKK|wqom}Uw~Rv$nz=K=50`Uc+)Mjc zCDA=z-*yH9FNSJlvIGq@fsa8>+=zPiKE1LzyAE>SqNHk2kOM?0`W2a(4Le>1iViz+ z#6syx*nwhKwHOZgZi7Ib1SXIq*r#A^LwykHEC)qRpfjG97J*w^)KyKObhfFK8NRJ@ z+aLmBiHkq7!!s2T(-W@gFgA1*cm$a)hZDX2^-4^kiNw|&z}BxJPVDP zrjzA!o^GNv?lK1ws@pb=^WXIEFoEyd%@3W>YL!|JgJ?SC^ua?}Xu9E<<@twuv&|~G z%azT3Z0CTm^u?sWE=o0&^E8!K)08Zj1xyOF#}HA;b59Qo(``{CA zxft?8a=P*~4Z-okx+|R-%FYzZpHN#H7fS2Z2XI!!P(ip_$2{~_HSY$xmMu3dpG(-I*(s4}s+HLn>*Qwdzu%^B!-QC}EV!7#+@6EB+U3$}g?U=_ZSvM92IBH!9SdPJbbNY43Q+i0MJ>-V zHq~-dWuE#f>w_*l&u=g-6(IMc6I~rDHyZ($_@j|8I7%*?Uo1@ohq*LVU2!8xXb(g& zvAIn1@=GK2Z9F}1y*pQ6s~})S4FRr5+`N<8?D56BrMOkT*z0#fn)a7nKLu&GOjr=J zj(%q#n~e}%5XRAZYMlbCqw`YA{k!ZNNOnU^*nRUQbCy6Qg_ed2JBS|EnMv!HxN14D zMNi_nkze$)L-?@XPK-jHJmSkpV#DQWv=aP&w180(6;iaZJZQNvc7sl-(@k&voa0ed z;=6mdH(FB&hYB~_T(Q}3drash=tUEN!``pwTLdfIlhp{pu+syPa`d7HG-vs!>rIB0gK10f&x?Z@c=|X;7cQXU*1XO!u?vfMr#=)<%XuK*F zpHKHiRelZ4>I_{bXt7d)X>*Y_>hNInIKXXzHE1Aof|+)Vs+1fr!b|E(AwjJ1+?KV1skFz}wV6imrLO%k(EX-= z;kQ);dZexYBibU}?5*7lpzgkzhM_VCjwGNrw8s?RH|Q5dy`&VSWa#^@q<73;pycDw zPfTi;UVS8uCzE^dJF# zRv*QvW5>$=E*TQB*4dL?`l51(dbW7@Dl9CGyBYv!Pk}5)!xvZ`fXxoTv@lyhJ==o+ zG?UMbu#%pHLJWA3j8rKdA|)lcFpfAhe+Mynzo4$0a7`pSlo~H|>6@lEUeoPrmxim! zvtWJ-v8fE@Ss$pN=7*Q*RePL$?HIgBXUvXQ7wJk<1VQ&GiYg=$!zE&6 zyS zyj4e%CxiTRBC^?uNpLGg(lIPyJBd=bo{n_c?0yfk=tRlfr)}!)qcD}PX7mRIOSEW zQ8%?Cz3hvoO!DaC-rO44vW;@={m)nRjKZm41C9c6ZA3!yicGv5|%rdJeOeGf9B=wqGOMj)dA7M0Mhqwb#`=z=3F z4Yq9o=;{z!-0B6L(`Af4(x6nffpl!N%G|4J?hUurMm^JQV2=&38?~E|*MNT!WPBR! zrxH~h&g5kiAHnQhHpXmHVFUdPc`sCp$}rp0gFb20IXZ#^kzag}QTuE}FH2PHXf#Ni zp9&?HCPI5{?-`hO4?Zi|oGry{%}e`c+rdKUyS=z0Bf(;i)VMSy z#hF%Tqvt#eJ?Ux{TFTPWGp1^M_A>-lpvD|&H*u&QZ>GrVl) z>2n2Tt#{m(jjxi@ypa5w6<~M))Dc<9e^EBjY`b7RdJAJRG_&m!`PA&iw0DE0t z0!d9a*KgZg3YEM4#~^X?1fTN8-Y&d+h-L4Vp0z1X`lI7Ddt=GWY=&%+G?bVIhq;G_ zT`g$tWP=wW2ozHnxe&dfv+nr8`go#keLPzZ3n?`RLeUzZTj5Ldf9*EG)_=$bf8M;7 z=b|PHuQH#M&I0So?P{3@-sf#geHz*}!UR=YlZ7E}alM?_hvQQ*l2+lVzb(-9jAP1z z>3q%{VY?-XciI21|1rJ!FNM#li6z7xA)zLtkxfQmyaH?(X}$N`Pg2&6BflTXdiq7b z^Ucm3>HAq4pSG>-6nj>oazONLye=r8>rWab8K-~iN&f<`+XGIbdPkSWy2kc@Pz()m zBEer{gg$`jtuO04WqUq>C>2*r$PI*=nwLgA`64DJ$VLVBW&np-<(b4v?!*ywq{CP7oyNBR6Bbr5tTWYC!)XXxVspB2%c;{ z344+*^!dzcZkeR~0pinx?V3XCoHv1a0PcYdKLK{>Vi2G`S zILjQPM!h1Pdm3VVUCmH}O{pD1<*By~J^MXHxpV}_${xD`u`UVH;pwD(dDrfcol@dY zA&8y1v;4|YC0e)jLD`dQqf|5t{d-hB#RY(9U+#kX-D$22c4;Y$lL=BYG!BH@{V6(|lG@o~HgxYKt>np5p`g}64g7+Jk?`Q!H~+&y9@;d8k{7+)RV|VmIZGXSFIqci1ori|UWv$} zxqy#6?d*=0qMh6DnX=jZDomhvY|4cn%CEK?M=v9sQl%CUOQeLUP`ODXT3@tHN2f&m zv?rgZJ8C%ZNvUkw$wAnU6t`*+%c8M!rydw#o-^QIQt}WlWwhKOc+%DVH%P&KD^>g2B(9_ns9d+ZVlRjG5dk#554?b%NnC3yNx3|wj@cUNOhWVHvn~5mkHC7% zv^x{&38n6#D$i$RWukgcg-rH$m1h39qa9s6YgjR8oSP9TB9z%>mmM z{UuNYvlRg+lul=q(;3`WHGaov!PA{Mo##81zteI&?qrDF7aJ60nefxwv5a^;60JN< zta|C^M610@ib z^2Gi$B`GAE2byzapWZPFd3ygrw6ia>kUhEryj*x`aW`L0X^ZupII@z!vC$|JGiv_p z`v1I-{1@W2|M^A#*WUFyaIh$KA*V?3X7#!^_07^|?^n~Sy=h+!Bv;UKWQq)L3AS-g zFcLV9;%r7zjHCXkm0~Iy)UA8B6)bJEeueAm{Q|f|Q%Ba47p)dL&QvbjJcj~D?{-^W zfcr$JL~E}Ci%fg6_Hz>w664v1qDDtjB&XGh4+ny{QY~*_meMPg+t$|zPBeFGSv%z} zth3IE2R)wWcAybwa{=nB`cP&X?!GO03=}fZ?j0V_%HtxOW6*@O(9k}qk*Y#S&rq{x zj*4?Wo~Zv_0s?`+gS_T702oVOmoP`Ff zh1`lj*+J+>;7kR67<@>+G+l_esv-~qz~dWTA#zGmN%50AS-OOW#pbZJccb@<@#&4x z-Cz?MJ(Cxs+1{Q=#3C3Hs6mW-1o$v)TYm*%)bUUF&NM7XG{e$Y8auzLi(eeeCJx5@ z$WYVnH!y=TJl7?J@($6=nNuaiM2GVfcE~7?QT1~@aE+g_a$!HHZCDZi+Mh= zEO)PMrYXcg(NVr?w{3{mZJQt3=b+6+Oygu-c|FL)eFZEIG&dl)0q{lGFopfZPB>7@wLu_+m^*0$8v7l-|)|o*| z@sMS>Z5N~B$5Hpz)<6f9-t_v=TJl;n7cSn{sR+~5Z_lH5P0moGe;!y`y#MpSo3|Sm ze;&yEXzcR5pMot~ws$Rg?P#Yuw<|Gh_U5-f_=(+}owcm8eQJR z&&n=JR0#Cg2)$F2^(mJUoQ%mhsd8X$`S(wq-!JuTB`qv`6#o*Z4bVRa{@5wVYFRChU#j4(?Y_zN-HpvX;IyI#vtyh*^8m30VKX7sAhJ<=2!YJ^o+W`&Qc>F0r;2X5)Zr1#@wu6?*1a>Qxq%9Ak4 z^L8x-aet^orA@)Hjg;@_lG04k%Yp`p=#YMmI0Fq!w6T$(a*rKY>j9)Ay=V1vMw-7$ zM$6!-`MI0Rs|T$fdGDCaCz(C_9E&Nmb6_eqUbztMF=K3_l8J9X(Hk1SBLDlJ{D11F ze4Sil5)2N0>I-l|x*%;eb#0 z*TF^>KbMe6p83EIjnHD8Mv?f(T5J0OvXT&T89Dj^vn!c?jpBCv&i*Zf zk>&_07rq$`vDkyZPqiT{iPA{R!0#O~qYDNfzfhwi%hNZwiGt$@d6cH6V}5SZQ&ch{g(^E05?el>7A=;^c~5M_bigZ}p||N4|q!xyDkmdK1~kYU0e|NRS!*O+_T! z&X%XsQ$N|0-w@omc&lvQYB5#~6-bGjmkB5)EKG$K=L{IZgYy=jsqbjN1#5#|%Jb{3 z9NX%NJr~v<7O; zODEv|&popS)ZsQ0h9vuu81Gk9ZsYOwH?}Ri9!P*eqm3mgOl@e|<~}_?a@$re9#6+1 z@tMk$)ch=|ijFp(^C|t{v5q`x(p=WEy+OsJ`m_B~qYriQ`vfuC%BEe4ca6EqZUP@J z6phfA6X-3N9$pJJPAzCq{nzs8;-%C6;Kl}GtyU__QP(FRu{-*1?j~$JQLcqvN0QK@ zdVK>%XMGBCnh}=fs2r1!kUUmUnfv*ZUTK{92_{Zz(}y_#vo!Z*J?N`d;;fo=HFpS+ zHH2<#aMpL8mh%+YJj@c%~8}5yR8{w&g(~wXhx<(FzQo?P#o3M1fSX6VN zDF=fouy*-0)2|KK8P$G&3{f}RKYo+6Cb1++rsx%S6#l+H>=NN=a^)+QNoQ4@C z+CT$-P-^my$Od>YE@%*C{LsKFUYA>pU$LNHK**!;&EHN2!RHbh{ZpVuxvwIZ2kpBV zG199U9Sm#c?mOR_F~YfWd{W3~o(wGbiu(2ZV+_6;8fA9(^iWf{x3J7mazrrCQ3+ME zBuq0PKHvlP(}|x}k6>WpBk%Gu42z%!?GUlzRMfqTuYBt~(SVKB`H^Xm-0J2Z{ZRqK z)AVRh!djIsXG|2eXI@5I4<+9hyS3ix;@2(V8bswuDF@keTRVvjelJr>LII`9s2|jt zuPKI-D#Yf4Ry#M>7`84Ov2R?1ze}X!NCck;L~P;kMMoPr#k`$WZl8|Iu0{4ZzE|IHKrwb%XYzr5&w zxuo=w(RuUMv%ZZ)9JX`ddKN6uBLMrgv?mXvzSIYLsCG4nO(Bl?dHR2*CN70~%M8kq zGr|xwUq^2;%Spe>X=?h7bj}Xt!J&_`Lx2ykz%x+ z3@H@oA_GRT5Dl?MeJ_K)CEaPVS!)VtB`5;r_AF>F|a%zr{m}l$Uc%WFq}Et*aw~t;-gLjuY)ddN$dc;e%%xivaKJ zDxtvdVl>HZmOhPQ%(n*|n2!~mFo&Dp!GA0%$%n@T46&bC5yEIc>SQv7b_u}!gA$V( zGLwTNe%ZK>6h91q#%4H2wH&K}t}b&Tm=#JMn{sbXgD>ekI~cwel$_yqeq_|A#=dC0 zs}=CBCrBL`!-7jK0aQZib#Oxj`*=n|i)yZ*ynOJjqwE!pwP7qe1s zwpywP2%cxM5P%I+(^ZFu*5I+C*Jz>GBL9p}{zHlZbuvrBX;!ms%3Kbhu9Y}`1i5o= zX!CUb>jlfr6KbF;o@!a+QHFe&?KrytKg6NKR54Hl*60_9n!9iFLk@pz&J}4!=YJD=S(S1P6DrK|Tm_ZTNPAlu#oeJ9xwJq&1IzL{Q($l-%-T=&a%r1rc?vq%t=jGu1{!VMo zCI)+ZoEJD#=L3h5Cx08tv-LR;Yn$|8L0U4-p~9}&j#}B9EST_w_~2ib5F;F^0n&ZDv=JadP4Bd7?whrl`m> ze;y23fB#fG7xdf?KC%qdP0C~TK5vP+Ei;7(fSJ+dG_p%Tp!sBTs9}Gj_^P$ZC3bqg z_2XrqLGFMB|JC@m>C`)oVv*#V7jJj{d7`}D5M(=G+y*@)TAbkiWEFv0{`WkiX6PfiTUV{|FZyK19tJKi|O-L{+G~9G9kz2c# zS!8kL(XD)|yMHnn6%KYz&s76S1A);p*}#$V zyA2V=Zw6A^?2#b<(bH(Yi+A8{J zhE*Npl=yQFs{G!0!!=Qx_-uo-&c5CRK!4Rsc4CMV#90cU5PizFW%Amip5DKUtL`5! zF1QAE#}*S_%MUgAr-bxrKG&!UUU`U7DPF0@Aa3~48rwDSQ10J9Ts#O1t;UwnLId)| zWll%9ZB29Fn@!M5Jfd}+9UC1!4eJ>22lj1Kb4{Ti zTwRkFTr>A9{qYg#+DAKt8(Z=STd|f@;e1Igxrjj%a08&4UxCOecn`c6Ef+bJ&>yzV zcyjPO#v%|ILCoekBc_k$9Ov(+1tI`dF}qzE+tNI^W^TlvQYU{N@Q>#isRpCwSjtAK z;U{C|b7^AvSx#eVLI;r$t+6E6llzL9&co7cAPQi5(F8$Ztzn%#H!Ss<;mU5K((wtj zv}IEbod%FuG56cmMie}CK{`ICM!S^*j!Eehd1XQIa!s}PXnqeXIHK|>EDAKXT5;bD zgSfBODRD?8o4pN?bckBoC!w}9V;vdN`Mg!zX4fa-4K4-maVu)A3g9=WrGSBzL{X_m zgHlIJ08X}yI%NlMT+_Fgt#B5*D^b=d%eb4ywK6UG7q%UPLd*Y#P`o7ju``2?Ca$yurC`2B|Omy}6zGQ*NZ;^l?&YKt{4So3xqK#f}x+eL57xU^iP*7c)~Hv8$m&h$0(C@SM)RB7 zC8^70&a2^J;@eWzx%Sum(Q^V8-YtQHrps+l?iAncufOplw>rMw-lxVh>-xx^(nwB~ zZcB=yotxWuo$i;ig8TO-d!5G@D|x+y3~PlFO3jTBwu1JT>}^w403lS!n3S79Wi2nf z2>oQh9|ao?xS;|2F-bS5>PW{i_h|q!FlMde2hyVKW*!0;1`mQQFGFpkOx;)+vC&el zeyp@5$}9YttA#d|Uu+Tt#$L%~)a}BI-v%bruGer;hj{5omE3N6nZT#2xtH}sO7JsCKD;$d_sIPxDNy|ybx=%m@r|kFY2}$dPn8k$&5*NQ8g*~ z#F2(7jFJ4NH%9CdrMBCtzGi601LpYtDS#{=jbL+@;2<|PyeEGCt*o}`&TY29Hvr2o zydAg~XIbb7?1lC48CnUM3)4NiTe3J%~ry|xKG+42*rku(yzPp?(fpX zE>Bi;n;27NVN+}e-ei3;F(!K1AiFltcY-MHgkhQMcl*N)_4IdOUu$nmQjQlSsI#GK zwUZ}^y`dc6dDWBa@FFY4m&NxaT#QjPJs`^zzPyS86kngRR(f9J7S{MeSYGpYvGS-l zPs>(dDS}zX*)mZHNqTrkaZ}BpfzmA5yBhk@tH?Xt+W^K?2vsR6MsF$59-DD+8z8r4 z-Rej8UKaM_4kqf2#x4k3*Rt8`8DMk+W{9 zX<@)B7XolR5(-6K@;`+R^mh?4wvoW1(LZVjk`%d8`3P54#$GQsqXn{uES(tA=&e zx%4A!=iQizOb>EkkM@(mK!b2$@$c3b1KZgrReZA-;~zeOt#K(GtxcwiIU{~zzl zDPpWMse*1t|~OXG3AA>Y)gra;0^k+e;yDGNL18jI_9a5=E-W$%V9m~#AAMEwWb-I zwpluv6)in?U0)`BK=;^~Wk@Q1B&DRQIJ-#DiZS(qa8?%Q-y_a_lNI &mE2iKd+o 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 diff --git a/docs/screenshots/encrypt-file-workflow.jpg b/docs/screenshots/encrypt-file-workflow.jpg deleted file mode 100644 index b5255b8c4235992fa56d72e31abd6a8bee607435..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62132 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 diff --git a/docs/screenshots/generate-keys-backend-warning.jpg b/docs/screenshots/generate-keys-backend-warning.jpg deleted file mode 100644 index ee860c869dd633bd027567a0042ec9ac2d6b6f84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69833 zcmd?Qby%BGw=WoqJG2xH?h;zut#~Q!TG~L7;I4&2ks`rb+}$ZOKnT)OBv^2FclSbp z%XiK_cjkWQ%*;3Q$ISEGdGlmHdEULV_R72WUTfvIe(PcSVHrU3T1iz2fQAMDpgq0- z4|4!{02T%&7A6K37A6)pHWm&Z2_7CUE*=>XF#!n$86_nJ896yMEh{}W4Kt9OoPmdd znT?&3i<62T^b*AJl9hv#;~zrMu(7f6aPXet;XUJ^Ca323zkNOY0+8Z78O8*lqcH)V zkfNcJqCIp1X#b%mCfYyr{f`R^9Rm{^=Ls6_W49>@01X}e2|79sHU=gx1`awd8sN!e zKPlEzY(~CkWO6u6+Pd#PB_uxQ*U@urA7y?epGO{&R69Z;AfoWz&E4|{i${K)ppdZW zXV~u*N>(L(cCgpi&f}A@N8!|uv!ee`Qv=ZcAsp+mkB9WJ^U0GZkF%pcs`n4w(4LT@ z^F4jWh#{xV#DDxQZv@k|cIBj<>|qu_fc`j`6rB_x1K3hfFz5NKAgiE&@h>$-w~fcG z4}ioTp1`?liw8ijp>%Rq?RMmMvwu~>|EuHV7!(vod;aw)G2@zp@R$DZgdi7wh8_L= z=DuS$M;955+4(O$oPT|uf9+xavpn5JEK?3=pcYKqyo|9b-=E9knhm3N}3Ms!0{Nx`R+_3uwz>e9KmN?FDosFR~6=eo=*wVNHZ z9G;5h>nzi9gI&B9a^1U+$f#S%+b1N2KV}t-*MBoqSubqRR3ju9_To>M8Q zZRRnhYwG}AzL7p8c@vZp#GHWP^L$0+I_joLXyM|DJB+pO`$Ug*Wx?ExhWo`_V>0mr zU`q)2xci@C{I7HlFtbLe(`%G>?bS9A)ONdepJN?7LGA@E0Zy?qgzlQk*`M8wSmY!# zqC^_>jh1YR8)i5i&eF^6B|I?W(^NWg*tW!mT%FU^GJUNGtSUF7R-Y#)-g?zkj7@T@ zvHY0&HO=|1)I;CBuf0Kx+R7Dz>jbc~MMI|U3W+mJD@S(aXyvz9(1ZrviZ8oSu|dd{P9_&F#<-l0j6??sYx^h`fH@Obsmv?(;C{sEA5|2=mE zajs{f>eztD8rSU|R{(CtpGwMt0Jpf(U3G#VGDd-%ZBzC)C@`dXOjn+vK}UO_my4B` zk_vFq4%+C?Rt3D%Wi2q>`AEFz+#p`j(kLNR9S*HM*Vn8m^)Qc4iydTl;!6ZUEQP~j%8%YAV_oy1kHu3`ztJnQcSi&4$^Db2ApocgzP>3cTL*;hCZ zWsV#6&-}Jxg@SmG+1Y7*D=%b7J*rct#HqV^$1l#kq7{;7qce>>Knbg~g`&^;FC|an zhwp6?I{MP>V&DCiXv>5Jay}m%^3H=6!94j*cL}m)-^KijHnK7p2VJl}g*viPP_HaC4w7c2wkN!e=rm0waL3rBhJVJdrb3XYcB;AiQ z!#?*%Pq!qp_SRp+#{=5$E9m1kXwbUK&|nXxwdI~bJODmG_B~#X=@0koP3k${C8o11p+IGj)JJts8fC`h-_O5soD`1Q+w-h^n?*UhXdAS5|5hr;$2{&c!?RM=d_TSOp zPTN77YhExT4otPu)xb%2Vu*kr%nhlvveU20tLRt(Ev;?t%bxLs{&5se9;RF}nr-j` zT=M%C{h1qw8t;XzMTh`CCPWqJ*&+@=hMr}~h%uk9LdVLpIkO6y>`s&}Lm6Y(Eb$9M zz?FbT=@FmGMl~rZg|Br8b~Saj>qWV4lOvK!z352wIssD)nj#H{klZM6qS6v=;n`f~ z+DsU&VI(Oj2@}&3CWimq{CnV;EC)VZ`h9i(y6GHt5T~FRvie_*{r~(P?h_{7^-OWp+!Zzp` z9Xsa!0RvTN7{V1b)i84D#p;M>iIES0y7&{rh)KUzMqNWmg0!zAR>~anCgQ%;yNeYL z&R^%6}md(dMS9etf`GPAAau#Jhw49 zB(&qrD+hS8Q3QqH3%=E4Mg_mo6^{d(An~V4~ zO;^J_u7@Dn$}Eo8a6l+QWF$@vD7o*pUemjNc*0;P=F($CTp2tT9-{Bx6>?%dbB-!r zab9#;yn1up_>m^KkKjGidAHaRgmQEXzAQ+P7>Fa8-+IHfc7^wI-~1kL*4FydMpF0n zqKxMO!vjE&>@mh7B_Vxm3`+{i$}q-sQ7@gD!0)`IaX6U%x9{P1oEpLng>~hCgb|78ve``|s;F%u<%m%<6RLY#k*ut#3Kn%@S*mueHnaq!ZowPU-C6 zz4qxk6O1WLcYV`AuqxkDKM4GZ z^}I&wADWrzj_B)sZ_7^iH6p?NlhwDE8-X9(7?Q+=fq|$4vNxosH zDU5;HjG!><{_`QaL6drN9USeo{ga(mzue;+=u&*o`Wb}jnahoa%mGS(tXLPQ|eA4>Vax=ug1JEdLMLJeyy}gl>>}T1Fr&Qgfp% zVF7_?BViakQI;Jbm>q^iNH!J)lxTKY+*5UGn=sufD+_HA)b80j_^>+C>~0zp{}GQo zIO-(1?+PaNRY(I8E=MXFB8|6bTNok_9BC7QR{5(i&ui)a=OdX5(=AQan!dFUQY#XPnW#xjNw(cEp$+RS-9 zzF>cgFZk`dqEXLsLQ;e6H1(Ae2sFF8zYb<*Ptb<#RFSIDbf9$h78EPC>$rB79p4m< zbxx-}YpWP2TF55yrJbLOvY_Af%b4gM@7If|Y7E}36|C*-k?S7ap<5o3U&EU*D~ihTi^se04{ONE)m8hP})JTS|&B!vV|-*V{UP$BRQ(srOlsK*0H_* zc|z~|zyWHmsKAle)1mWp_=E55BhC>-?vR5QE-4#A#iPl#00+NDVV@{3mH;NHm zo@EW@Wm)Rx8V7ZqtGIT*q=5*MlK1VTr2oeY`+wUNycSLFAE2*xT*vXP9x3_~+vc?er2LzK~0A(50urpJd~NVfB6wFs1u2Gym^$PgMEf??y}f*ZvLxZ zaM0sWl*g_EySejLuLLS$d(a}4%-$k2fgzGJ1MI!uSnA^W?PRwasGjCF$A5ZXO*mmA z4qbTwkX62h*OYpiJ6sU&G55D|Etp4FwuCdCF~(u?)u`kv)`guMa;fcvu+9?cq`5 z`DWv@q$+nD!>DV-XBvwm%aKguQCB?_ChO>uA=TlNunyp585=(bXjl80#AdcXt26 z*t7+6qY@ny_>>6}Xy?viD?iPi64@0|25}T7ihIYy2s%)8X}9-_`L~`C&x< z-k+M2HN=;n#bB1TG&)_7-MGJ*WoCt4)C=gTg~p_&{~8X=sb@byb4$)aj8E4j-&Wx_ zOlWKLMGgk}R%6)A^kS?3(R2AYCvTHtyyK^`J@CR7KKgs1wyByi-vH)jhY`Fi2HZ-( z$ddT=kw&#M3p~FS5I?g$&0d|BW9sBGJ?n=px>X|!^j*V7_{1sA#Swc7F(1=N)fJ_A zA0|Ef9=KqTcFL9?E=~WIJN*|I8-nr?ihMe$NM(CPMSCLG0O2|h!t=+OI&S#8) zP`WdpECYBG)(MgZGM@&#Zr64Nha9j8|v7 zs*@qe*^0@up%U%=_D4F{2UU1>HFTc>@@t?-I=ZnL&AIw{pTckyYh8AbE~BYuQS(EZ zCQ!^WVLzrNWD5%_pQA&Lt_oQo?VN^yF4GZ^Tr2-_j`Fe|)`(;^7U#@G%cuNUN`7H# z&~$^1Dp4Ev+8G5lMBZ^zh|Rte4Y!$F5WoO&>b{({6>$?)cUxM)F>tDrZe&+xv9&CQ za?ji%k^TiBxY+B($~`SvDQc9rrwQ!W>{>YRe#d6_so(Nj>O9RhB=i&duLy85U~1|k z<(`^QHl%7yV`|KF#Wo*gL|k%x5Z+TdUz{VNQ z6&vq-D2Q5KsETYtffg728)6cPur;!|AugJ7!^gLBBf1TgGj63}^%T^hAzOW>iK9n# z^YPdk3KuN#Yxeh8CrsgAE_CheOB6=nksqRL)~359;r9TLr=*T9ibbINx;VBg4m@kJ z`REblwqG3%(w*G2S9$KI+b4#Xr>eGS>#HoA>VALfHgBC~%VHxXwtT8p!{dmq2#TV$ zb1tzm#Pc=QG}{D7*k<+Cco(6(Cbz0-hjwGInRv%fIUilq)Z0G;KhGJ=44QR&O76%P zg0}b{0K=cK+9z7x4d1-JmCAkq_^omBkK{;$C_F`BE9}1*Wqu@NB(1+rR;2Zx?W-k*3+oYgKr z0w>AP#KH{qIZu5_koE8EJXlg|F3~7^1o`24a#JqxRUeV8`OJD0U>QZAvJhbsjmVC)Ct6?!L4i7LGo|4w|(>2~Lzr7n>35cqzM|s4Qq_cGk z*H%#yMP|p+vAWxQwIQhdE7&|!R;h1@7g=E$5O)*@&K#XW>#48W7#a>?v|P!q8yAk` zO*WS@H+IhPwvlwCd0XFA0{n}^Jl|@2Pq_yItL#=uyeqFLvO_v;@l(#rwG+Dc%SSS2 zi&=*@1^EQ>60^Zhe%0PZvyqU{iIi53pR6xn?K}tg z8T$XxHO^~xd4Ix_fIV)y@Z5|@1}@)W_EA~Ve;mE%C}Ny%+G?_q+DrYdHup-d`!APp z;Xl>>fkeFX^A~6>ZMAaw2Q4J4Qr%zb^==HRYDKMZ*P+;d<6OK?weIAKk4(IFL5=;^ z`h>3S4!TMv7P!Aa$1X#WJ?0f%)iN{ipwj!$s2OcfxB}&FZm+_dU{NcAcy9?iY)T~G zP_@`ttfZl&`lPU{9L9KqI2F}Gex{(x7QE4aDMUFKV0B7$!ofHj8lK*-X;Rc=0lV;| zB~Z*eQyHl*>J+rW?u?h(W2eWw{(Q?_UGhd>Sz&shn!gw5hV?1&jgw1|CV}{vuD}zcD7yteBb)#%}$}UOM=yTW3z5i%R5}Fg0+S!lXW66 zICfUkJlcnSE1T3F96{@$FzVeYr?Q%wF%cY2&H|4guQy}(VySpVr2w1x??3vIArr5WNynT)kZT22CdO3ZPh0Jyh8=*6~DQGs@Pk*2NM%9qB zsuW@#!fccNOF7a#I&O`68}e+9F0E0Ov4cjHCet-r?h`he37oT2tq2{$DOhj$se`#O zz@;Vbif;L6J)d}ND)ML*$y!~X63P&%ElzC6n06WONlcazQk#vgzjo#9Zs+k4i+|(X2Atno2ok*F-lGx`2yHe3_kG+~oUR zvoo@GKZojg?^3hZpDRTR2@Ed zwR_KO-N?*-0P@|sA1w;GO5w3>u1sDvD%^Zdc2o>S(2XlxVUxQvV?bLe_)o5&9)^2F zWy2>kT<=O94Ly&XvWl9*^9r-zL()TItDz#l+gMzgq9e%DUuyuz7cIk6ChFsz9EHd?iH-N-N@QLnsp+Abz52EiPvQtfv(?TiKGARcs|L+8 zn>BYx5vx@PeK_G}2UWbHe*x_CKMb?!?DvEM+oCo~s!1lz zfSaSQm=^y;yTS!USk@RFt7&$WwsW}4B``GIcXo=)Jczvc-vQ z>gu-fvCl*9Xcn2hy@TaRJZk*^?Au9(%k#U*o&}2Hh^T-c_p}cVT?GpH7=p+-Hf#hBev zRHR>%=L0j%Vjv{Ij>J zUe{5FY=I6R0B(qJz)VHCb-526k$->O88=<%1rz6L;g7m}a08{~Q^`-6f+FlG%VZ*N zT4bjuBocLXOsYPNuyIl$!bM9iQ9{?#o@6+CQBsu-{`m$Ts??wSY23rjl0Sb=o6dYCHB;blw`r(nN={o} zcM8J&l_x!)3dM?VF&`Oe>%LC6Bq~TxATb)MIp;&)=^u;FwR2u?`rf7ISwGo}KXl70 z$68r(?-4t5Ne5SRf$ErGvD9*A9u}+E4k@|zc3{-ufqxgxWX6PJy@`*1=@CqO|LFNS z?9_n@kU-Atk_5Obj#>BDPx*$GR5(7*Sp&Z$yipn+yjADUs7F~c!|XOP$*tB#CvQkx zzR`jd9rg6aUDUL7xkH(w*eF^Lr2yz@-0yW=1im~MR4n*$`uJUK*~*} zecP>WHX_30r^eXWkl)zFc!J*GtgTvF_Nd_#lV4b>?AYkj4TMWyo}F;_;VaM6Jli?& znDP^~wfrd3AbtGX?62GW+Q9O%8}KA)cIwZ;SK+G#XY*)I$4?XCcBa`#2oN6$^=j%! zk+u~j{7bqj02-+Jm{R6IJQw^SQgw?2z;`rHq_Y01W0#H^0+O&#-|`=u822Da{=%M6 z0P!Xn$)tZOdsQ{p6~{?UC|APLuw#NB1~P?k?lP5^5ulT*uwvV?XKxCm6maL+o62|5 zJ?mivku}cQ@hn7my>R!nxht0WQ;)sn8Pe}ME@BHxHW7nBwiagEN&2(GQ|N;+Zj)_v zjvoN}J5jb=FD|+IDA~Wt(QMdu6f(pwDp#XjgO=98MH|#Z+6#Mm9&V-#WQ=i6_}2a{ zNB#;{^j8y_+zZ-Ep7)t!dZ!<_y=K!o%>Nn#g+rtmV=??$KKMx3)c>|^2PDOnAA(U^ z{ax6^rm%&>jR4Q|@Cj3)nJ`o!%{y=V(WOd!*MvA=&F~`m%!j(;8jacVvIRmtgY7xN z7r;5@j1<_d_tW|#;BKj?d*%7j(+tNWe!9siW1uD}!tn&&xxXCK2=3P8e<}H7escG6 z%6P|#0G!^t?6C6r3=KtuJd^v=TJAwqHu{y%z@D4dx-HpQf?Q2NY4qw9B(Y^PrBSbN}L>8y-vN>7i%R#`J8KJMo*q!P-uRWqIjqE|s)3@5nx7Wy(!2uFCCtTY|I45=mS(t43xc zRP=>&bY{5@j)KNLD$iJu<~3B1+Jxau?m)icBkJPST|z16?6%t4v^QEY@xNr*k9+B# z-_Wy&`$x@7d>QLlbeOVtWflo$iA;!rHd}NgBxI8Kg$*pezWf4v0MH8&W*4=eX=zXB zv@TnU*7?jO?2GmhN*H%ky;Tk@tQ)u63w8SDaKKnh>f}C6gx}Ymo+2pJru2cDd<>TlThO_^+UTmaOx2Uc9ZOuJ0~5>Cq|L!^70uojJ0Tu zHy}hi^}bI^4R8-)KAeeB;D2ff_G)ZrohLX*&2O@+ZPgcEvrZ32>65(~7)llq3>QK|(2WNUU0KfY z08xTj4eRrA-_7>1+TEZ#nu=1;CFkUF%G5v1rA7YpIPZLjVvbH+BqLZ?S86;CHu1ZX z5j0h-P(Kqqd-2i&s7Z2^QZj4+g(6x6uDToveu}Aj^JR^&QUAqL*!orT=P9-YT5!T} z*ZG@sEq$aR!AoH_u|xM+a7F^_!5|iv#*^BlFCMx(TzEbo${Wl%91~43TusWjj3r(k z56$&{VaAXkLYHPCNUW!3j}e|VW1md7d95|p?^axHJ&T`YpQWoQhpDz%LI`*@)wlfq zEc6SAis6Ee?1f*&8+%6?RYjkh_fUUpbq84MB;~rp$q-{a_My-8@>+<}%BO3v2@~Yd zvHoX?Nq{1)k>l9UpK3Ci{n+p5Kg?jzX0Q-1C5}PCPRjNA&8~RuI(v7A>G(P4;a9ef z<$i`p%A$yY*tmomqIo4|r^y3Kv8@q%1$BAHjE_?d&9Q67dPq!n%T`lP+gwQMKGWaq7 z^j|di^j`NAKTnPSJFSjuYjmtZij*8b@_&pK5LY_ACA>**`n+#9$3Vv;6@;8eKHyun&)RzetlY#dJ+67>O_jrE4^2!Ryl6fb{D{(+j53S~7rltNF$tvm7AHgT zgEnv>Nby2s=Z|FDlDFJ(L;1>_)Wq~5!6w_+l@7W%6_W=*U$oIxs-5j}s&o0f863&A zV4&3vKGfHbqE)WbYh-$H3pxGsIu`qDc6j4-P?P&+aoeMPn@}IzU<_0^>^&Fs5%dQb zt|5_BA`Ne~bABXll*!CQD=2#L{y3$108HF;{2QiRIPbp}I2AsNNJcry57 zj*ukTQe}1xR(|m^z##e5b#)>-+@o>(Xgozc!my1(alRmS84G*MYpd~qC{6o_!-ByC z9#_S2cq#6;&6(F&_YGAErarywW&VOz?b1yr8OXuCcQ3hTZs(Z1psTI!*f=oSo7>pE zefuE?TWrw17OLk}qF)93*6ndtOJH z%9uyf!;P;U<*$LSvMqPaA<@_uEjtAX#KmZM?XK-v|HhszqH?F^;tzg5eieM2X^-hD{La=!Cv_0QeOUA=jEXgsIu_=7uF~*kYx!EPxlhoA;$QHc<%4S|@sLcWl-Za(LiY)nZo8 zOYyp_e9xY?&A8arJv*?lX7oU=UtzxX0kFRlwDavxOf%8WhC~6^`Gz@$7wQ#Tdcv_F z0>>+Yocv6x+BIog4jFxZNwqwVP)!;}r9-mFw~L%#2rIeCJo))D`Fh!gzGS#z(x{%6 zXNm@BmC6zfUCfZ|mvu!$4M|#&CJn>@=p=Kl-OFu#rkq41gaXOP(^wPBec!t?Q-agc zEtF`RI>8w0R#18Fz&|GQW!vxgR>tX{W60e+Tc5lC?9up_N@h>W{R%gG z^3U6aj!4WYiBel>b^-cBOdGiB27ZyCH&JB+epcHbkTsdJRa{9pyOL_c;JP`76j1WX zs0ZTW63RCL@fRd=H}@#5g5n-eiE~=~t)1?{s9m?R!MM)dCFYrZonB2oES`@0!GXeP z<7@ZtLsSUWC->T6E2zyV*-@}J2X7|rXp*idd6z<;4chYc&kxIi2iz7*E%`qF0V7x9 zT%n%eiqegeK)#~>znA0*@ds_v-||FhyVW8Hx!4NRGv|4PUOZKMLtlR)L-``+e2_2R z7f1vyCkmaC^l7!dQ`5DDyBs#%vhj_L3xD4)cRpx0mD4E*@<$LSj zYDJFe8{ zBMV30kyZoyGn;n~TXbS35yqyXp;7`);-k^}s+t&A$f*rV1{zBPG?7xAPOQz((5}+xH$e0Yg6R z9>M1>$Gfnq4;6VCF>w=>Q6<}J0Tg_s5PyrI#sj{XH7`klnCskwBaRp60u?fcL3iqp zP&vz7n3N4BNK5v3hohu4#8Sp{(@+JwpINgN@{!Y5(N4;+<8}c$=hTKYHpjN6*=77v z8w#hhdaW6eTP4&EoF1eONNZ$UR@Gi@Y=z3 z*F)w}9ELMYFIx7mo5AUyhxnRx2eAB`cic_`0rg!!2SC_J=!-egXzw3wQ`Uh(LUrl~ zt*Dnz&+CKD$cnMc>w5(Y^2|FKK*tE?XYY?Y56F8)*_w#@##-oCw$`Z=?GfcW%H z1P^!Ty~p=glv8aYf)u2jqP<(ehRh5*K}@K(3ojbYIrVv&s%-*_>_llRu;>6MydQ{H zsCSx`z7^K*Ny(MwJ^)5v@agiu+kRPp(DT>C^t2j#xr-<_>5GX|iH7#LsxGaSGckcz zJEa#3uM04((S?2F+k%<-g!)LPSewP?Pv7`t!Nn&7M`z%TwFnZ;?_@y54cu~~idEEU zwHW>mr`4h0d^=i#Z(-;*@8Z!O?`3`Ms2!ftOY6ftu_=xgmalSh0b zd@D`eu9TvEM8c=eD~F}g(U*PwvB_)Bg$-0}rRn8aCxX6ETU%bhQ?r#GAFFH7$%eaI zcyy=`Y_$2Q;e?zf3DOYz3-M`81=m~7J8ag9mcf3QkgR**Vfzp}J!1Kw&|j54*leWx zkjv0j_>OGo^T;emM~1R$vn$ojknf4>ubmzM;DkkjqIcG3SCqTx?XyNfU9r!%rp&X- zozJ^~7Io$vq6rmmjh)NGUli`L9?(AvRio#Qrp*KsVOU;oIOMP&N{nqwFrQx*7gdzi z3oEOsNeKh5@u6nFM`d{i&Ews0C856R*ZoLy>~grb&-al)c0+A*9MbnWU~ob;@jF*n zU}(BPu$B`qMo``X>jS_g){dARKT~i~OH!_}&u9k1TJE8c?Zi{Y0`t$*ywJCx{-d-* z`y#i}ODzm>$7)U}@Gjw44)>kQElVGf3<-tAxP4!_G_!$ym6Rat8`c`gQ6MW8MeLtd z|LZA{{CDM-a?Gi6+NBK=3jB3&BQX_IciX0~Pakmxx{fuBfU+?y%WRj2ZT$_6v)rC9{d ztt~JR)IKk;&9FA=SNWDSp!6VNj=g9Y<|#1Gf>~8n8N<)<;}-Qn)%E-dU`RR;#~86e z*x&y#u30S3n%k=Q#k)bXSt=3q10vR+6FNg6;&bgsyCf2E|Fu8mTD5ZLyoBrk@o4Ur zAWUIry;|=(lT>z?5}I4K02*8CiGkcUzH+XO8m=@7W5)Ym4Sl%4)zDHz9mg!H$|{x_ zlz$XpXr*)@T{(a43n+kwL^>? zx7{F6M!%iMWAPL+IUUhBo>c-6W^-)6e8wR&A&2aV3_ZWxq1hM}a{WhEY`C=wqNMgE zW*KeAOzpP@wtcK>IY-XNx=E9Ltv54V>(yby2&E^uu`ymiHG~Z%a4>-Ap!l?8gilwI zrphnADTYwAB=lEMw;u0D{aF)nWyI9`)^WX0o65Q~uYLzsLl%{P<<7MDjO*P%KHosg z^JQo3Io~R3Ec_B1?Hlc0lX6X5+qct-V~+kR6u^-j8Yb?dvgd+&`n^;HFP;}WEIS*KGIga}xVnJ8Xoma)Z-3hh)VYK_kyn_9CeOG0Grk&&(Sao+)Nfnss>yx{^h-Q|H zaPfYPdb4c${Fz-QHjlJq_tEBP6Lw6d$b`W?`x1tiTC9Tz-j2N;dr?UM>RX*;3qba! zLzKB%xd7vK*_jG*ZKo|nt0+-Tj+gRaSweZJJiVT*7M^(#+iFoPzGD zB;85>w-b_j{iW;nL-p!p%J_(}RYBtn*K)#8kEi~dH)(ag9TIYskBox~sQJ*>qZnx| z6GIc1)w7ZVuiJI~Z?Q2-H>vL(zz&tZy$+ur19J{BS1*bLubLx-(^ipv(ZJ-6#00nM z=DYYm%f#|;2Oc%Uk2BafHO?C+SUo5&pHSAG?{t1%CkAy03{Cy`qjqQ3L{bGug8Pjf zf{?+JRqus^%Y60Ig%9pfbo|tXzjsuSxYmz>yIG37Rjc}rm+v2g56_Nz@Y{)mL$uiY z3VG!wub^*4E3w{t$ox^!aU_pB(FRu3=00Sf+6Hj=d z`D-0nx{C7nTaTuALjK=!m)nnc>j6t}lYg&(+%B~SbH6Xbq~c&)P;m4mq8wX(R^^e$ z`Vt#0ldyBG7|SngQoQ)ZLzG;5tKk=0h6aH8_gC!JjY zf;>E<4U9gIi&)yeQV;6e`MD$HF7nlo^87>d@M`}D3hJm$J)|zdV6gHte7CV?cFEZ* zBKh(pyCBXg8oSYkXh+2#T8MmT6t#C#{3{c)ZmdMyuRtq55@TQD`4!iAJE>0EGmJqGd z2|=Md_Lj%3zMk(1vioo9X3X6ONunxI`cD9;B`GzMqcEkONa;{$+z< zU&DUj@31o2n0@A7Qk9+jnu;^jj&e#;YzX|RBXcB9@H%(#<0C)u7E~N`lo+(GOV3hs z&h7L7Xc-S0=a%{9k9NrdK|_CT0ogG1&C9Q~Uf!#Q-HvtmICVmk+s zDExs57Zgv}`S;FEk}WHDk65uQhRJLlnVm+x2S9h+eKa{t=N@ElF9q&Yo4B8QuAt{x zCv;Mmm#YE*n+`ltHpqFJkMmz)Yb-dC2xG3%F_fV;kgQhPZrugK40hY1m&LQbSF1Pl zIJo`n+wIRglW|XlZ01s2zm?Y%n%y(yz{*c&oncu}d@y{@a2rm&pUI5(t=*|;KGdD#yot8tG@UwS7( zCyTMx5M|`rEKYwdG*IWSgmg~I5>iYC6lAKbFQ;W$U7Vio!VgXhgQ6cxP9T=NS{WA9 z^^5oFrHh)Dwykn&%A(TSINv7)(BS9KkFh{8huA?h-#b2Ka^pn{heS<${HZm^)YK*K zRP=SEOWTluAnO8)om^U}LHT8D3ASWMFmq{5lA~Zc=!7U@RLjslx>b=!y+KFE)ZT8p zytv#$3oo@}-eTKiM+JjqY;5qX<$2hchV6~HlxO946P8vr{h%AR>7A|goVus7$QalG zOZ^6lCU{6UzNBaD4PUi?s1bgq1^}Jq+lI$Pj_OW^&|}0gzjL6cWyV=A;3%M|uCLGX z#uuD9-=?*2%C`@k76z_iDpi`eD{0z3l0i+D3!@PGH&mRrueZF}YO647FCBdaMBzW5 z0_kLl;Bn0Av_SsXGqgZwf3VY5GAw>1o<9(sh1gFOqgI(_Ze)Vp5&Pk6RgK75sQ>%M7a1Vx?DH@cWgiUGTUA3zXtKfT z5;HYBL?N%5Nn|~OJjCQA(Lh*&F1giquhk&qhZ3)AT|-Nkxs-yNq7w2Rb-qqFDBFGN z;>*j6O@|i{D}=|yDf|BvM8=5>*{o|ThbeKD1myG8H^*t--%mLF4~!W!_e= z{L)cgWe=5)R!4=AVb5R_DkqsevP^`tlL^3zP@v5};zCi)Je`xy<6ld9^YT*;vi@%h z-CO&ey`vQBJ}##{HEnH{?_-AxGkk-rl|wwsBvO4{|5g+6uQk|~E(K6YsZmM3$DDX+ zjkP(gG+VGvQ`aawMG|&rMjAX^_7$F{j_}z{+vcbS9L%XqYjCc0FAsPgh+Dgs|8rr{H5!rsRz-5O-=IY-A zXMuRWxCMOk{C{SSA5+G2reFL2FTrvH?*5>n;3`^gqvFxTB!M`Nh> z%zV&K%6r?5ts7q6fR?(0l*yay68*(2bFFqVb!Qs_hIOSOWartY0bNK#`I6ytbIdp6 z_1ZwB;8Sv`h*6+en39sXNU|h3+!NDUa51ad-hOMu$o4~Zxzz_7WfCd^j32fxv-}aZDPy%)=-Ccc#Nf>$p_>oM^%1TVNRl&br0=7<|dD>I~PyCm2-K1 zZkQ4CJfE$74ykkb^M@@!Kx}ZB`lYxVU6@k!m1iY*&d|L&t4?zOo3+RDwYLXOi7G!+%ak`UTl=&P$oa+HDq)G( zRr{1ztA#Q(ptR!a6bp~Bx(6b=lz;swsjet?RI}SH`BKlbzeNxadp!_ZKYi1|0Hh~* ze(_W1EvP$Y*uqJ0VL%GD@J(%&kyy;f5*tM%*+Uy(pi>bso1f_Wt`gR($zvXV+0RU^ z?8pce2syNDDsZAJl-O&G^OWEX%I*HSMQ_$b@hI zCMoKgme!DnLrtsHO$$LKF1GH%q^M32n&>7102cXEkXm3=-=3slMl^^QgIajJ<&~Tm z^9R=u4VPM+bPNTB|H_9y-mATGUh#hbu*UyK?OSyqNCG@UY6<_}S;N*kkrv5XsEg(N zDwY>CO?vPh_Gd$ZVFTUds3?=j=zNE@0PCjM>DhbmZe|Q!1lP=euhsfLu}g-ItZLiq z6^@dFMX{?Q1C(mitGI-`+qi(!%ja@v&wX~dtc%ji#eH+saUs^%oNu5pcHn3g&-QqAMPX zE-^=g!P&CBj0KXxy)u|9|Fx2OCE+G%Ya!Vp{esm5Rt|RV*{d#(6dIOmhT`b?5mk&) zc}Zue(Y(>6B+0)svkgE0k2x%o6N@X~*x7C7)W)D*e0YSDL#f1l-G{!UPWn7FK7lXQN zUG4~mN!Yt8Iy4>ak2>>SdmesnOEtWne!|qaJDeQFdAY5Mi_Ii|IyHP=K)kIErTF@> z8Qh1aj5%l6a^X8t0ucBvu4RLs@bs=QidOKMZbU!JOJKwY_1sel`4;}Bi$F-UhKY)F zyuODc+}RKZRvbN6FGOwfYp=+95lSZ<+3zFeEZV8!*N(uWRwpRDT0s2gf@N{sIoP_!J{#kq@pZ@dG%V& zcPtqqTv{z6{$W&E9w=2Lg13{&UO78-qKEif^Q`r(nfcCq=Tp!Y5~_mNzpnDJR$3}txp*ti73~mA)b3vAaqQGd8>@Z) z(~}e0o8uI=aW_$0CDH7wHeXU=KqBVhoa>K6HX6H{=kvuCmSf2&^>96>b=cE**OJb@ zBpde|>_2I(Qj{9ZfiW#RxA2+D(knYxLYXOEgLRsgl2CSEO@uaYpv+@q zw+_^)xwz5-en*#59`sz*VCcsPTMq|&Y~TF2(rp(GDv(>&I}*mUTd}xc%DC#;D?FdO z)VSyMc4Yn|mGazroh}if?jpf`Mx4GwIl3wIzz5#*ew?X%OPZk^cS@BWQc(x}AxBe%rGmq4ZG z;bMVls}HE(QT`r;ld%u0{-B8tF2Izv-Vl-Y0!1Q{lUi%PXX^pp`?&R~KP~W*-sr5FJ(;Oi zd~ma;HW}aig%1k#WoNaP4KOS|ovLfKO$#(zh@eK|nmv*Ai}%D0OrLiu+U2?E(Z*;{ z7vz!q)gtZ4ry=g9{kAz?#L6c8YJL-L%*4cEqc8~G$(Na4^dUhJPNts${vD`wKz_rF zMarZ`(|AlBn%mY(KAdD{=QRq_H)rnY=Sk$I6w?MOwF8gKbk691f5al&^0cA$79fa_ zpc9)m&%VB^Cnt`_b=o!+K(RXXVw>P?SS)NT^DGdA9f9U&o`4FoT|!hGLfFrkT6?qG z0U_6Z-S$fU^*Dcp?uMM3TWCUcJwk!?W8bw(sl?1Am`awE;zizgwd}?mR>``otU;5E zctR3J$jzt=k*dPU)rS7wqC$@_))^c73

VW!zhK^3JR_(%kr_w{mmd%5uXlZ`gHQ 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%0DSi6gIc53K(70cBgBB_50p(rFr}y}4x6doc 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 Q`v3kh`+s}fQT;mgPt+r%YybcN diff --git a/docs/screenshots/key-utilities-workflow.jpg b/docs/screenshots/key-utilities-workflow.jpg deleted file mode 100644 index 6d66f843c50f2535e1f664fa44f9b2baefd94210..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54640 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 z 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 bYX8?Z_(DbaRiFPEroVcNzSiK#Z+-s*qa`jU diff --git a/package-lock.json b/package-lock.json index 412e548..f6b9712 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,17 +12,208 @@ "react-dom": "^19.2.7" }, "devDependencies": { + "@axe-core/playwright": "^4.12.1", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.3", + "jsdom": "26.1.0", "playwright": "^1.61.1", "typescript": "^7.0.2", - "vite": "^8.1.5" + "vite": "^8.1.5", + "vitest": "^4.1.10" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@adobe/css-tools": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@axe-core/playwright": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.12.1.tgz", + "integrity": "sha512-rMd7xriptqKpP+w5265i4Hdkv2X5kbu6uiBi/B2I7uf3hieRBM3qDCfaKPtxfiYb2mKXfF+yLODJwIx+Jv1GDw==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "axe-core": "~4.12.1" + }, + "peerDependencies": { + "playwright-core": ">= 1.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@emnapi/core": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", @@ -57,6 +248,13 @@ "tslib": "^2.4.0" } }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", @@ -179,9 +377,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -199,9 +394,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -219,9 +411,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -239,9 +428,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -259,9 +445,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -279,9 +462,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -368,6 +548,102 @@ "dev": true, "license": "MIT" }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", @@ -379,6 +655,38 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.17", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", @@ -765,96 +1073,524 @@ } } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" + "dependencies": { + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "picomatch": "^3 || ^4" + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "picomatch": { + "msw": { + "optional": true + }, + "vite": { "optional": true } } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", "dev": true, - "license": "MPL-2.0", + "license": "MIT", "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" + "url": "https://opencollective.com/vitest" } }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", "dev": true, - "license": "MPL-2.0", - "optional": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/axe-core": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.12.1.tgz", + "integrity": "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, "os": [ "android" ], @@ -958,9 +1694,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -982,9 +1715,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1006,9 +1736,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1030,9 +1757,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1088,6 +1812,50 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.16", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", @@ -1107,6 +1875,47 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nwsapi": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", + "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", + "dev": true, + "license": "MIT" + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1203,6 +2012,31 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/react": { "version": "19.2.7", "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", @@ -1224,6 +2058,27 @@ "react": "^19.2.7" } }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/rolldown": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", @@ -1258,12 +2113,46 @@ "@rolldown/binding-win32-x64-msvc": "1.1.5" } }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1274,6 +2163,57 @@ "node": ">=0.10.0" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", @@ -1291,6 +2231,62 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -1411,6 +2407,213 @@ "optional": true } } + }, + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" } } } diff --git a/package.json b/package.json index 53f6745..6af6ac9 100644 --- a/package.json +++ b/package.json @@ -9,20 +9,30 @@ "scripts": { "dev": "vite --host 127.0.0.1 --port 4001", "build": "tsc --noEmit && vite build", - "check": "tsc --noEmit && npm run test:api", + "check": "tsc --noEmit && npm run test:api && npm run test:unit", "test:api": "node --test scripts/api_client.test.mjs", - "ui-smoke": "node scripts/ui_smoke.mjs" + "test:unit": "vitest run", + "test:unit:watch": "vitest", + "ui-smoke": "node scripts/ui_smoke.mjs", + "ui-native": "node scripts/ui_native_smoke.mjs" }, "dependencies": { "react": "^19.2.7", "react-dom": "^19.2.7" }, "devDependencies": { + "@axe-core/playwright": "^4.12.1", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.3", + "jsdom": "26.1.0", "playwright": "^1.61.1", "typescript": "^7.0.2", - "vite": "^8.1.5" + "vite": "^8.1.5", + "vitest": "^4.1.10" } } diff --git a/pqc_app.py b/pqc_app.py deleted file mode 100644 index c80728f..0000000 --- a/pqc_app.py +++ /dev/null @@ -1,492 +0,0 @@ -# pqc_app.py -import streamlit as st -import logging -from pathlib import Path -import mimetypes # For guessing download mime type -import re - -# Import core logic and config -from crypto_config import cfg -import crypto_core as core -from ui_helpers import format_key_info_for_display, guess_decrypted_filename - -# --- Basic Logging Setup --- -# Configure logging level and format -# Streamlit can sometimes interfere with basicConfig, setting level explicitly helps. -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s - %(levelname)s - [%(module)s] - %(message)s", -) -logger = logging.getLogger(__name__) - -# --- Streamlit Page Configuration --- -st.set_page_config( - page_title="PQC Pro Encryptor", - layout="wide", - initial_sidebar_state="expanded", - menu_items={"About": f""" - **PQC Pro Encryptor v{cfg.FORMAT_VERSION}.0** - - Uses **{cfg.KEM_ALG}** (PQC KEM) + **AES-256-GCM** (DEM) with HKDF. - Private keys are always password protected (scrypt + AES-GCM). - - **Disclaimer:** Security relies on correct implementation, secure key management, - and the underlying cryptographic primitives. Requires auditing for production use. - **The developer provides no warranty.** Use at your own risk. - """}, -) - -# --- Helper Functions for GUI --- - - -def display_pem_download(pem_string: str, filename: str, key_label: str): - """Provides a download button for a PEM string.""" - try: - st.download_button( - label=f"Download {key_label} ({filename})", - data=pem_string.encode("ascii"), # PEM is ASCII - file_name=filename, - mime="application/x-pem-file", - ) - except Exception as e: - logger.exception(f"Error creating download button for {key_label}: {e}") - st.error(f"Could not prepare {key_label} for download.") - - -def format_size(byte_count: int) -> str: - """Format a byte count for user-facing validation messages.""" - mib = byte_count / (1024 * 1024) - return f"{mib:.1f} MiB" - - -def uploaded_file_too_large(uploaded_file, max_bytes: int | None = None) -> bool: - """Return whether a Streamlit upload exceeds the configured in-memory limit.""" - size = getattr(uploaded_file, "size", None) - limit = cfg.MAX_FILE_BYTES if max_bytes is None else max_bytes - return size is not None and size > limit - - -def uploaded_key_file_too_large(uploaded_file, max_bytes: int | None = None) -> bool: - """Return whether a Streamlit PEM/key upload exceeds the configured limit.""" - limit = cfg.MAX_PEM_BYTES if max_bytes is None else max_bytes - return uploaded_file_too_large(uploaded_file, limit) - - -def sanitize_download_filename(filename: str, fallback: str) -> str: - """Constrain user-controlled download names to a simple local filename.""" - candidate = Path(filename or "").name.strip() - candidate = re.sub(r"[\x00-\x1f\x7f]+", "", candidate) - return candidate or fallback - - -def validate_private_key_password_for_ui(password: str) -> tuple[bool, str | None]: - """Validate private-key password text with the core policy.""" - try: - core.validate_private_key_password(password) - return True, None - except (core.PasswordRequiredError, core.WeakPasswordError) as exc: - return False, str(exc) - - -# --- Main Application UI --- - -try: - active_kem_component = core.resolve_kem_algorithm(cfg.KEM_ALG) - kem_status_message = None -except Exception as exc: - active_kem_component = cfg.KEM_ALG - kem_status_message = ( - "The ML-KEM backend is not ready, so new keys and ciphertexts cannot be created. " - "Compatible legacy archives may still be decryptable." - ) - logger.warning("Unable to resolve configured KEM algorithm: %s", exc) - -st.title("🛡️ PQC Pro File Encryption / Decryption") -st.markdown(f""" -Utilizes **{cfg.HYBRID_KEM_ALG}** + **AES-256-GCM** hybrid encryption. -Supports password-protected private keys (PEM format). -""") - -st.sidebar.header("Operations") -operation = st.sidebar.radio( - "Choose action:", - ["Generate Keys", "Encrypt File", "Decrypt File", "Key Utilities"], - key="main_operation", -) - -st.sidebar.markdown("---") -st.sidebar.info( - f"Version: {cfg.FORMAT_VERSION}.0\nSuite: {cfg.HYBRID_KEM_ALG}\n" - f"ML-KEM backend: {active_kem_component}\nDEM: AES-256-GCM" -) -if kem_status_message: - st.sidebar.warning(kem_status_message) - -# State Management (using session state is generally better) -# Empty password field defaults are not credential values. -if "password_gen" not in st.session_state: - st.session_state.password_gen = "" # nosec B105 -if "password_gen_confirm" not in st.session_state: - st.session_state.password_gen_confirm = "" # nosec B105 -if "password_decrypt" not in st.session_state: - st.session_state.password_decrypt = "" # nosec B105 - -# === Key Generation === -if operation == "Generate Keys": - st.header("🔑 Generate PQC Key Pair") - st.markdown(f"Generates a **{cfg.HYBRID_KEM_ALG}** public/private key pair (PEM format).") - st.info(f"Using hybrid suite: **{cfg.HYBRID_KEM_ALG}**") - - st.subheader("Private Key Password") - password_valid = False - st.session_state.password_gen = st.text_input("Enter Password:", type="password", key="gen_pw1") - st.session_state.password_gen_confirm = st.text_input("Confirm Password:", type="password", key="gen_pw2") - if st.session_state.password_gen or st.session_state.password_gen_confirm: - if not st.session_state.password_gen: - st.warning("Password cannot be empty.") - elif st.session_state.password_gen != st.session_state.password_gen_confirm: - st.warning("Passwords do not match.") - else: - password_valid, password_error = validate_private_key_password_for_ui(st.session_state.password_gen) - if password_valid: - st.success("Passwords match.") - else: - st.warning(password_error) - else: - st.warning("A password is required. Unencrypted private keys are not supported.") - disable_gen_button = not password_valid - - st.markdown("---") - if st.button( - f"Generate {cfg.HYBRID_KEM_ALG} Key Pair", - key="gen_button", - disabled=disable_gen_button or bool(kem_status_message), - ): - final_password = st.session_state.password_gen if password_valid else None - - with st.status(f"Generating {cfg.HYBRID_KEM_ALG} keys...", expanded=True) as status: - st.write("Generating independent X25519 and ML-KEM key pairs...") - raw_pub_key, raw_priv_key = core.generate_hybrid_keys(active_kem_component) - - if raw_pub_key and raw_priv_key: - st.write("Raw keys generated.") - st.write("Formatting Public Key (PEM)...") - pub_pem = core.save_key_pem(raw_pub_key, cfg.HYBRID_KEM_ALG, "public") - - st.write("Formatting Private Key (PEM)...") - st.write("(Encrypting private key with password...)") - priv_pem = core.save_key_pem( - raw_priv_key, - cfg.HYBRID_KEM_ALG, - "private", - password=final_password, - ) - - # Cleanup raw keys immediately after PEM generation - del raw_pub_key - del raw_priv_key - - if pub_pem and priv_pem: - status.update(label="Key generation complete!", state="complete") - st.success("Key pair generated successfully!") - st.markdown("---") - st.subheader("Download Your Keys (PEM Format)") - st.warning( - "🚨 **CRITICAL:** Securely store the **Private Key** file. " - "Remember the password. Loss = permanent data loss." - ) - - pub_filename = "ml-kem-768_x25519_public.pem" - priv_filename = "ml-kem-768_x25519_private.pem" - - col1, col2 = st.columns(2) - with col1: - display_pem_download(pub_pem, pub_filename, "Public Key") - with col2: - display_pem_download(priv_pem, priv_filename, "Private Key") - - st.markdown("---") - st.info("Share the Public Key (`.pem`) file with others to allow them to encrypt files for you.") - - else: - err_msg = "Failed to format keys into PEM format." - logger.error(err_msg) - status.update(label=err_msg, state="error") - st.error(err_msg) - else: - err_msg = f"Failed to generate raw keys for {cfg.HYBRID_KEM_ALG}." - logger.error(err_msg) - status.update(label=err_msg, state="error") - st.error(err_msg + " Check logs for details. Is liboqs working?") - -# === Encryption === -elif operation == "Encrypt File": - st.header("⬆️ Encrypt a File") - st.markdown("Encrypt using the recipient's **Public Key** (PEM format).") - - uploaded_file = st.file_uploader("1. Choose File to Encrypt", type=None, key="enc_file_input") - public_key_pem_file = st.file_uploader( - "2. Upload Recipient's Public Key (.pem)", type=["pem"], key="enc_pubkey_input" - ) - - if uploaded_file and public_key_pem_file: - st.markdown("---") - input_too_large = uploaded_file_too_large(uploaded_file) - if input_too_large: - st.error( - f"Selected file is {format_size(uploaded_file.size)}. " - f"The maximum supported size is {format_size(cfg.MAX_FILE_BYTES)}." - ) - if uploaded_key_file_too_large(public_key_pem_file): - st.error( - f"Public key file is {format_size(public_key_pem_file.size)}. " - f"The maximum supported PEM size is {format_size(cfg.MAX_PEM_BYTES)}." - ) - st.stop() - pub_pem_content: str | None - try: - pub_pem_content = public_key_pem_file.getvalue().decode("utf-8") - except Exception as e: - logger.exception("Error reading public key file: %s", e) - st.error("Could not read the public key file.") - pub_pem_content = None # Halt further processing - - if pub_pem_content: - # Load public key (password ignored by load_key_pem for public keys) - pub_key_bytes, kem_alg_from_key, key_type = core.load_key_pem(pub_pem_content) - - if pub_key_bytes and kem_alg_from_key == cfg.HYBRID_KEM_ALG and key_type == "public": - st.success(f"Public Key loaded successfully (Algorithm: {kem_alg_from_key}).") - - original_filename = Path(uploaded_file.name) - suggested_output_filename = f"{original_filename.stem}_encrypted.pqc" - output_filename = st.text_input( - "3. Encrypted file name:", - value=suggested_output_filename, - key="enc_output_name", - ) - output_filename = sanitize_download_filename(output_filename, suggested_output_filename) - - if not output_filename: - st.warning("Please provide a name for the encrypted file.") - elif st.button("Encrypt File", key="enc_button", disabled=input_too_large): - input_data = uploaded_file.getvalue() - if len(input_data) == 0: - st.warning( - "Input file is empty. Encryption will proceed, resulting file will contain " - "header and metadata only." - ) - elif len(input_data) > cfg.MAX_FILE_BYTES: - st.error("Selected file exceeds the maximum supported size.") - st.stop() - - with st.status(f"Encrypting '{uploaded_file.name}'...", expanded=False) as status: - try: - status.write("Reading input file...") # Already done by getvalue() - status.write(f"Performing {cfg.HYBRID_KEM_ALG} + AES-GCM encryption...") - encrypted_blob = core.encrypt_file_pro(input_data, pub_key_bytes, kem_alg_from_key) - status.write("Cleaning up...") - del input_data - del pub_key_bytes - - if encrypted_blob: - status.update(label="Encryption successful!", state="complete") - st.success("File encrypted successfully!") - st.download_button( - label=f"Download Encrypted File ({output_filename})", - data=encrypted_blob, - file_name=output_filename, - mime="application/octet-stream", - key="enc_download_button", - ) - else: - err_msg = "Encryption process failed." - logger.error(err_msg + " (Core function returned None)") - status.update(label=err_msg, state="error") - st.error(err_msg + " Check logs.") - - except Exception as e: - logger.exception(f"Unhandled exception during encryption action: {e}") - status.update(label="Encryption Error", state="error") - st.error("An unexpected error occurred during encryption. Check server logs for details.") - - elif key_type == "private": - st.error("Error: The uploaded key file appears to be a Private Key, not a Public Key.") - else: - st.error( - "Failed to load or validate the Public Key from the provided PEM file. Is it correctly formatted?" - ) - - -# === Decryption === -elif operation == "Decrypt File": - st.header("⬇️ Decrypt a File") - st.markdown("Decrypt a `.pqc` file using **your** corresponding **Private Key** (PEM format).") - - encrypted_file = st.file_uploader("1. Choose Encrypted File (.pqc)", type=["pqc"], key="dec_file_input") - private_key_pem_file = st.file_uploader("2. Upload Your Private Key (.pem)", type=["pem"], key="dec_privkey_input") - - if encrypted_file and private_key_pem_file: - st.markdown("---") - encrypted_too_large = uploaded_file_too_large(encrypted_file, cfg.MAX_ENCRYPTED_FILE_BYTES) - if encrypted_too_large: - st.error( - f"Selected encrypted file is {format_size(encrypted_file.size)}. " - f"The maximum supported encrypted file size is {format_size(cfg.MAX_ENCRYPTED_FILE_BYTES)}." - ) - if uploaded_key_file_too_large(private_key_pem_file): - st.error( - f"Private key file is {format_size(private_key_pem_file.size)}. " - f"The maximum supported PEM size is {format_size(cfg.MAX_PEM_BYTES)}." - ) - st.stop() - # First, inspect the private key security metadata. - priv_pem_content: str | None - try: - priv_pem_content = private_key_pem_file.getvalue().decode("utf-8") - priv_info = core.inspect_key_pem_strict(priv_pem_content) - priv_type = str(priv_info.get("key_type", "")).title() - except Exception as e: - logger.exception("Error reading private key file: %s", e) - st.error("Could not read a supported encrypted private key file.") - priv_pem_content = None # Halt - - password_provided = False - if priv_pem_content: - if priv_type == "Private": - st.subheader("Password Required for Private Key") - st.session_state.password_decrypt = st.text_input( - "Enter Private Key Password:", type="password", key="dec_pw" - ) - if st.session_state.password_decrypt: - password_provided = True - else: - st.warning("This private key is encrypted. Please enter the password.") - elif priv_type == "Public": - st.error( - "Error: The uploaded key file appears to be a Public Key. A Private Key is required for decryption." - ) - priv_pem_content = None # Halt - elif not priv_type: - st.error("Could not determine key type or algorithm from the Private Key file. Is it a valid PEM?") - priv_pem_content = None # Halt - - if priv_pem_content and password_provided: - original_filename = Path(encrypted_file.name) - suggested_output_filename = guess_decrypted_filename(original_filename) - output_filename = st.text_input( - "3. Decrypted file name:", - value=suggested_output_filename, - key="dec_output_name", - ) - output_filename = sanitize_download_filename(output_filename, suggested_output_filename) - - disable_dec_button = not output_filename or not password_provided or encrypted_too_large - - if st.button("Decrypt File", key="dec_button", disabled=disable_dec_button): - encrypted_blob = encrypted_file.getvalue() - if len(encrypted_blob) == 0: - st.error("Encrypted file appears to be empty. Cannot decrypt.") - else: - if len(encrypted_blob) > cfg.MAX_ENCRYPTED_FILE_BYTES: - st.error("Selected encrypted file exceeds the maximum supported encrypted file size.") - st.stop() - - with st.status(f"Decrypting '{encrypted_file.name}'...", expanded=False) as status: - try: - status.write("Loading private key...") - priv_key_bytes, kem_alg_key, key_type = core.load_key_pem( - priv_pem_content, - password=st.session_state.password_decrypt, - ) - - if not priv_key_bytes or key_type != "private": - err_msg = "Failed to load private key." - err_msg += " Check if password is correct." - logger.error(err_msg + " (Core function returned None or wrong key type)") - status.update(label=err_msg, state="error") - st.error(err_msg) - else: - status.write(f"Private key loaded (Algorithm: {kem_alg_key}).") - status.write("Reading encrypted data...") # Already done by getvalue() - status.write("Performing decryption and authentication...") - - decrypted_data, _detected_alg = core.decrypt_file_pro( - encrypted_blob, - priv_key_bytes, - expected_kem_alg=kem_alg_key, - ) - - status.write("Cleaning up...") - del encrypted_blob - del priv_key_bytes # Very important! - - if decrypted_data is not None: - status.update(label="Decryption successful!", state="complete") - st.success("File decrypted successfully!") - - # Guess mime type for download - mime_type, _ = mimetypes.guess_type(output_filename) - mime_type = mime_type or "application/octet-stream" # Default - - st.download_button( - label=f"Download Decrypted File ({output_filename})", - data=decrypted_data, - file_name=output_filename, - mime=mime_type, - key="dec_download_button", - ) - # Clean up decrypted data after download button is prepared - del decrypted_data - else: - err_msg = "Decryption failed." - logger.error( - err_msg + " (Core function returned None - check for auth errors in logs)" - ) - status.update(label=err_msg, state="error") - st.error( - err_msg + " Possible reasons: incorrect private key, wrong password, " - "file corrupted/tampered with." - ) - - except Exception as e: - logger.exception(f"Unhandled exception during decryption action: {e}") - status.update(label="Decryption Error", state="error") - st.error("An unexpected error occurred during decryption. Check server logs for details.") - - -# === Key Utilities === -elif operation == "Key Utilities": - st.header("🛠️ Key Utilities") - st.markdown("Inspect a PEM key file.") - - key_util_file = st.file_uploader("Upload Key File (.pem)", type=["pem"], key="util_key_input") - - if key_util_file: - if uploaded_key_file_too_large(key_util_file): - st.error( - f"Key file is {format_size(key_util_file.size)}. " - f"The maximum supported PEM size is {format_size(cfg.MAX_PEM_BYTES)}." - ) - st.stop() - try: - pem_content = key_util_file.getvalue().decode("utf-8") - key_info = core.inspect_key_pem_strict(pem_content) - display_info = format_key_info_for_display(key_info) - - st.success("Key file parsed successfully.") - st.markdown("---") - for label, value in display_info.items(): - st.write(f"**{label}:** `{value}`") - st.markdown("---") - st.info( - "Note: This checks supported key metadata and security policy. " - "It does not prove the key matches a ciphertext." - ) - - except (core.InvalidKeyFormatError, core.UnencryptedPrivateKeyError, core.UnsupportedKDFError) as e: - logger.warning("Unsupported key file in utility inspector: %s", e) - st.error("Unsupported or insecure PEM key file.") - except Exception as e: - logger.exception(f"Error inspecting key file: {e}") - st.error("Could not read or parse the key file.") diff --git a/pyproject.toml b/pyproject.toml index e0a3aa4..ec2fda5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,6 @@ authors = [ dependencies = [ "liboqs-python>=0.14.1,<1.0", "cryptography>=42.0.0", - "streamlit>=1.32.0", "starlette>=1.3.1,<2", "uvicorn>=0.49.0,<1", "python-multipart>=0.0.32,<1" @@ -39,7 +38,7 @@ Issues = "https://github.com/brainx/Quantum-Encryptor/issues" quantum-encryptor-agent = "pqc_agent_tools:main" [tool.setuptools] -py-modules = ["api_app", "crypto_config", "crypto_core", "pqc_agent_tools", "pqc_app", "ui_helpers"] +py-modules = ["api_app", "crypto_config", "crypto_core", "pqc_agent_tools", "ui_helpers"] [tool.setuptools.data-files] "static/app" = ["static/app/index.html"] diff --git a/requirements-dev-lock.txt b/requirements-dev-lock.txt index a3c453b..890e129 100644 --- a/requirements-dev-lock.txt +++ b/requirements-dev-lock.txt @@ -8,16 +8,10 @@ alabaster==1.0.0 \ --hash=sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e \ --hash=sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b # via sphinx -altair==6.2.2 \ - --hash=sha256:94014f8ad8617c3cb163d1137359cd6db5ba134b9b46d93cfd8b609fd245a583 \ - --hash=sha256:a1ff9d9cfe81c75414641826312b9471780e19d39293ba0b012933f6b6cba0fe - # via streamlit anyio==4.14.2 \ --hash=sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494 \ --hash=sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f - # via - # starlette - # streamlit + # via starlette ast-serialize==0.6.0 \ --hash=sha256:0067b25fce104eaae5b88383de9ab803faeb671831e14ca698b771b356e2600f \ --hash=sha256:085de7f62dc9cc247eb01e965a362707d1d90b1d89a82c5bf78301a60a3c417b \ @@ -54,12 +48,6 @@ ast-serialize==0.6.0 \ --hash=sha256:e61580a69faf47e3689795367ed211f2a10fd741478cc0f36a0f128793360aad \ --hash=sha256:f2ff3baffc3a29c1f15bc9098aa0c09763410262d5e6cef42116f7356c184554 # via mypy -attrs==26.1.0 \ - --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ - --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 - # via - # jsonschema - # referencing babel==2.18.0 \ --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 @@ -97,10 +85,6 @@ black==26.5.1 \ --hash=sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294 \ --hash=sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae # via -r requirements-dev.txt -blinker==1.9.0 \ - --hash=sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf \ - --hash=sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc - # via streamlit boolean-py==5.0 \ --hash=sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95 \ --hash=sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9 @@ -117,10 +101,6 @@ cachecontrol[filecache]==0.14.4 \ # via # cachecontrol # pip-audit -cachetools==7.1.4 \ - --hash=sha256:323dc4127934744db5b54eb4924482d7edafbf9554e820d1531c2e08c0e4ef54 \ - --hash=sha256:437f55a4e0c1b01a4f3077cc470e6991d47430970e36fbcb77e2be0df4fc1cd6 - # via streamlit certifi==2026.6.17 \ --hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \ --hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db @@ -328,7 +308,6 @@ click==8.4.2 \ # via # black # pip-tools - # streamlit # uvicorn coverage[toml]==7.15.2 \ --hash=sha256:075560438765b7a2ef43bf7aa7758661b53d889df47f062a31bda6c1ade553a2 \ @@ -470,7 +449,9 @@ cryptography==49.0.0 \ --hash=sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4 \ --hash=sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493 \ --hash=sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b - # via -r requirements.txt + # via + # -r requirements.txt + # secretstorage cyclonedx-python-lib==11.11.0 \ --hash=sha256:3049fc83e06a059b5c5907a527625a8ed5073caab10607ed4c9e5503b590fd44 \ --hash=sha256:4b3194db72b613717f2912447e67ab618c75ff7dcac6c4af3c0e9e1ac617c102 @@ -495,14 +476,6 @@ flake8==7.3.0 \ --hash=sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e \ --hash=sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872 # via -r requirements-dev.txt -gitdb==4.0.12 \ - --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ - --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf - # via gitpython -gitpython==3.1.52 \ - --hash=sha256:79a36ee1f83523214a3f72d56cf1c4e490d577dc61af77e43dfe5862bd9da01a \ - --hash=sha256:de0a8ad86274c6e75ae8b37dd055ba68f19818c813108642263227b20775b48e - # via streamlit h11==0.16.0 \ --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 @@ -558,9 +531,7 @@ httptools==0.8.0 \ --hash=sha256:ef7c3c97f4311c7be57e2986629df89d49cb434dbff78eafcd48c2bff986b15a \ --hash=sha256:f256d6ce930c52ca1cb2a960b7da03548c454e7d28b06059ad41bfe789036ce0 \ --hash=sha256:fe2a4c95aeba2209434e7b31172da572846cae8ca0bf1e7013e61b99fbbf5e72 - # via - # -r requirements.txt - # streamlit + # via -r requirements.txt id==1.6.1 \ --hash=sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069 \ --hash=sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca @@ -579,10 +550,6 @@ iniconfig==2.3.0 \ --hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \ --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 # via pytest -itsdangerous==2.2.0 \ - --hash=sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef \ - --hash=sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173 - # via streamlit jaraco-classes==3.4.0 \ --hash=sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd \ --hash=sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790 @@ -604,24 +571,14 @@ jeepney==0.9.0 ; sys_platform == "linux" \ jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 - # via - # altair - # pydeck - # sphinx -jsonschema==4.26.0 \ - --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \ - --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce - # via altair -jsonschema-specifications==2025.9.1 \ - --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ - --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d - # via jsonschema + # via sphinx keyring==25.7.0 \ --hash=sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f \ --hash=sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b # via twine -liboqs-python==0.15.0 \ - --hash=sha256:969b27c65c99f973f8c991472151331814c9f02642115fe4d6391bcdc33433a4 +liboqs-python==0.16.0 \ + --hash=sha256:50bb11a9767b88f68099cedef8de09f798f31eaba1aa18b483988bfcd50df440 \ + --hash=sha256:ee01445ccfbeab8dced956a642ce1eb5ba69438caba7ec291eea14083627d5c0 # via -r requirements.txt librt==0.13.0 \ --hash=sha256:05d96b80b95d3a2721b619f8982b8558848b04875bb4772fd54842b59f61dd97 \ @@ -951,10 +908,6 @@ mypy-extensions==1.1.0 \ # via # black # mypy -narwhals==2.24.0 \ - --hash=sha256:42fdedf44e5b2ca7505630d45b4ac3058f38d8485cba9fe1652ca23152df7489 \ - --hash=sha256:b5c0f684ccd9d7475b564111e319a4964abcf2baf79d3cf6b1003d06ac9b828d - # via altair nh3==0.3.6 \ --hash=sha256:082675ff87b9385ec430ffe6d5847ba7456cc39b73720cd4add472f9f4cffd56 \ --hash=sha256:2411e8c3cee81a1ddd62c2a5d50585c28aa5566d373ad1db92536b95ddb24ef2 \ @@ -984,83 +937,6 @@ nh3==0.3.6 \ --hash=sha256:f3736c9dd3d1856f80cd031715b84ca75cda2bbb1ac802c3da26bfce590838d7 \ --hash=sha256:f5ed5fe84aee7f39db95c214a7421bf0499fbf500fec6d86a4e29bfc37971438 # via readme-renderer -numpy==2.4.6 \ - --hash=sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1 \ - --hash=sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4 \ - --hash=sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f \ - --hash=sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079 \ - --hash=sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096 \ - --hash=sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47 \ - --hash=sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66 \ - --hash=sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d \ - --hash=sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1 \ - --hash=sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e \ - --hash=sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147 \ - --hash=sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd \ - --hash=sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75 \ - --hash=sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063 \ - --hash=sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73 \ - --hash=sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab \ - --hash=sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4 \ - --hash=sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41 \ - --hash=sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402 \ - --hash=sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698 \ - --hash=sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7 \ - --hash=sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8 \ - --hash=sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b \ - --hash=sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8 \ - --hash=sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0 \ - --hash=sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662 \ - --hash=sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91 \ - --hash=sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0 \ - --hash=sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f \ - --hash=sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3 \ - --hash=sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f \ - --hash=sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67 \ - --hash=sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6 \ - --hash=sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997 \ - --hash=sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b \ - --hash=sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e \ - --hash=sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538 \ - --hash=sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627 \ - --hash=sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93 \ - --hash=sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02 \ - --hash=sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853 \ - --hash=sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c \ - --hash=sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43 \ - --hash=sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd \ - --hash=sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8 \ - --hash=sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089 \ - --hash=sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778 \ - --hash=sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1 \ - --hash=sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb \ - --hash=sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261 \ - --hash=sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb \ - --hash=sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a \ - --hash=sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8 \ - --hash=sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359 \ - --hash=sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5 \ - --hash=sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7 \ - --hash=sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751 \ - --hash=sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8 \ - --hash=sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605 \ - --hash=sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e \ - --hash=sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45 \ - --hash=sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2 \ - --hash=sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895 \ - --hash=sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe \ - --hash=sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb \ - --hash=sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a \ - --hash=sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577 \ - --hash=sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d \ - --hash=sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a \ - --hash=sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda \ - --hash=sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6 \ - --hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20 - # via - # pandas - # pydeck - # streamlit packageurl-python==0.17.6 \ --hash=sha256:1252ce3a102372ca6f86eb968e16f9014c4ba511c5c37d95a7f023e2ca6e5c25 \ --hash=sha256:31a85c2717bc41dd818f3c62908685ff9eebcb68588213745b14a6ee9e7df7c9 @@ -1069,161 +945,20 @@ packaging==26.2 \ --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661 # via - # altair # black # build # pip-audit # pip-requirements-parser # pytest # sphinx - # streamlit # twine # wheel -pandas==3.0.3 \ - --hash=sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c \ - --hash=sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2 \ - --hash=sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13 \ - --hash=sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04 \ - --hash=sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6 \ - --hash=sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824 \ - --hash=sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb \ - --hash=sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066 \ - --hash=sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e \ - --hash=sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76 \ - --hash=sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac \ - --hash=sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7 \ - --hash=sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5 \ - --hash=sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f \ - --hash=sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98 \ - --hash=sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d \ - --hash=sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1 \ - --hash=sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639 \ - --hash=sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2 \ - --hash=sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49 \ - --hash=sha256:5cc09a68b3120e0f54870dede8287a7bb1fa463907e4fcec1ea77cab6179bf7a \ - --hash=sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028 \ - --hash=sha256:6674ab18ad8c57802867264b00e15e7bb904700cdd9046e3b2fa1fce237439ea \ - --hash=sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa \ - --hash=sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc \ - --hash=sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9 \ - --hash=sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf \ - --hash=sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c \ - --hash=sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27 \ - --hash=sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a \ - --hash=sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a \ - --hash=sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977 \ - --hash=sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a \ - --hash=sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938 \ - --hash=sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44 \ - --hash=sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4 \ - --hash=sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1 \ - --hash=sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb \ - --hash=sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f \ - --hash=sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d \ - --hash=sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc \ - --hash=sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870 \ - --hash=sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8 \ - --hash=sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085 \ - --hash=sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd \ - --hash=sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360 \ - --hash=sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c \ - --hash=sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09 - # via streamlit pathspec==1.1.1 \ --hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \ --hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 # via # black # mypy -pillow==12.3.0 \ - --hash=sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756 \ - --hash=sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a \ - --hash=sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59 \ - --hash=sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45 \ - --hash=sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3 \ - --hash=sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df \ - --hash=sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139 \ - --hash=sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b \ - --hash=sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39 \ - --hash=sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e \ - --hash=sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8 \ - --hash=sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1 \ - --hash=sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8 \ - --hash=sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89 \ - --hash=sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5 \ - --hash=sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130 \ - --hash=sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd \ - --hash=sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d \ - --hash=sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b \ - --hash=sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed \ - --hash=sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace \ - --hash=sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb \ - --hash=sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931 \ - --hash=sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510 \ - --hash=sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6 \ - --hash=sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1 \ - --hash=sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce \ - --hash=sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385 \ - --hash=sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e \ - --hash=sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c \ - --hash=sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7 \ - --hash=sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace \ - --hash=sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c \ - --hash=sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f \ - --hash=sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64 \ - --hash=sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f \ - --hash=sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a \ - --hash=sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827 \ - --hash=sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17 \ - --hash=sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4 \ - --hash=sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a \ - --hash=sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701 \ - --hash=sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e \ - --hash=sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91 \ - --hash=sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66 \ - --hash=sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468 \ - --hash=sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217 \ - --hash=sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658 \ - --hash=sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418 \ - --hash=sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a \ - --hash=sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c \ - --hash=sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330 \ - --hash=sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402 \ - --hash=sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09 \ - --hash=sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930 \ - --hash=sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f \ - --hash=sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec \ - --hash=sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a \ - --hash=sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94 \ - --hash=sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468 \ - --hash=sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b \ - --hash=sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965 \ - --hash=sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8 \ - --hash=sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd \ - --hash=sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7 \ - --hash=sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c \ - --hash=sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777 \ - --hash=sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35 \ - --hash=sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9 \ - --hash=sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f \ - --hash=sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f \ - --hash=sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0 \ - --hash=sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c \ - --hash=sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71 \ - --hash=sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3 \ - --hash=sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838 \ - --hash=sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf \ - --hash=sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321 \ - --hash=sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26 \ - --hash=sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec \ - --hash=sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9 \ - --hash=sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65 \ - --hash=sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5 \ - --hash=sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e \ - --hash=sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d \ - --hash=sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198 \ - --hash=sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7 - # via streamlit pip-api==0.0.34 \ --hash=sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb \ --hash=sha256:9b75e958f14c5a2614bae415f2adf7eeb54d50a2cfbe7e24fd4826471bac3625 @@ -1252,72 +987,10 @@ pluggy==1.6.0 \ # via # pytest # pytest-cov -protobuf==7.35.1 \ - --hash=sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799 \ - --hash=sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87 \ - --hash=sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6 \ - --hash=sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30 \ - --hash=sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9 \ - --hash=sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4 \ - --hash=sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4 \ - --hash=sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a - # via streamlit py-serializable==2.1.0 \ --hash=sha256:9d5db56154a867a9b897c0163b33a793c804c80cee984116d02d49e4578fc103 \ --hash=sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304 # via cyclonedx-python-lib -pyarrow==24.0.0 \ - --hash=sha256:02b001b3ed4723caa44f6cd1af2d5c86aa2cf9971dacc2ffa55b21237713dfba \ - --hash=sha256:04920d6a71aabd08a0417709efce97d45ea8e6fb733d9ca9ecffb13c67839f68 \ - --hash=sha256:0b3537c00fb8d384f15ac1e79b6eb6db04a16514c8c1d22e59a9b95c8ba42868 \ - --hash=sha256:1183baeb14c5f587b1ec52831e665718ce632caab84b7cd6b85fd44f96114495 \ - --hash=sha256:14e31a3c9e35f1ab6356c6378f6f72830e6d2d5f1791df3774a7b097d18a6a1e \ - --hash=sha256:1617043b99bd33e5318ae18eb2919af09c71322ef1ca46566cdafc6e6712fb66 \ - --hash=sha256:1a4e45017efbf115032e4475ee876d525e0e36c742214fbe405332480ecd6275 \ - --hash=sha256:1b2fe7f9a5566401a0ef2571f197eb92358925c1f0c8dba305d6e43ea0871bb3 \ - --hash=sha256:1cc9057f0319e26333b357e17f3c2c022f1a83739b48a88b25bfd5fa2dc18838 \ - --hash=sha256:2392d954fcb920f42d230284b677605e4e2fbb11f2821e823e642abd67fbb491 \ - --hash=sha256:25ea65d868eb04015cd18e6df2fbe98f07e5bda2abefabcb88fce39a947716f6 \ - --hash=sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826 \ - --hash=sha256:2f16197705a230a78270cdd4ea8a1d57e86b2fdcbc34a1f6aebc72e65c986f9a \ - --hash=sha256:35405aecb474e683fb36af650618fd5340ee5471fc65a21b36076a18bbc6c981 \ - --hash=sha256:38be1808cdd068605b787e6ca9119b27eb275a0234e50212c3492331680c3b1e \ - --hash=sha256:3a577bd840ca83f646f0a625dbc571dba7044c43c2d1503afc378b570954345c \ - --hash=sha256:3b13dedfe76a0ad2d1d859b0811b53827a4e9d93a0bcb05cf59333ab4980cc7e \ - --hash=sha256:418e48ce50a45a6a6c73c454677203a9c75c966cb1e92ca3370959185f197a05 \ - --hash=sha256:55a3bc1e3df3b5567b7d27ef551b2283f0c68a5e86f1cd56abc569da4f31335b \ - --hash=sha256:6165461f55ef6314f026de6638d661188e3455d3ec49834556a0ebbdbace18bb \ - --hash=sha256:61a3d7eaa97a14768b542f3d284dc6400dd2470d9f080708b13cd46b6ae18136 \ - --hash=sha256:6233c9ed9ab9d1db47de57d9753256d9dcffbf42db341576099f0fd9f6bf4810 \ - --hash=sha256:641f795b361874ac9da5294f8f443dfdbee355cf2bd9e3b8d97aaac2306b9b37 \ - --hash=sha256:644a246325b8c69c595ad1dd4b463eba4b0cdb731370e4a86137d433208d6147 \ - --hash=sha256:6f066b179d68c413374294bc1735f68475457c933258df594443bb9d88ddc2a0 \ - --hash=sha256:7986f1fa71cee060ad00758bcc79d3a93bab8559bf978fab9e53472a2e25a17b \ - --hash=sha256:7c2b98645d576a0b9616892ead22b64a83a5f043c5e2ca15ebcefcb5b70c80cb \ - --hash=sha256:806f24b4085453c197a5078218d1ee08783ebbba271badd153d1ae22a3ee804f \ - --hash=sha256:85fe721a14dd823aca09127acbb06c3ca723efbd436c004f16bca601b04dcc83 \ - --hash=sha256:8adc8e6ce5fccf5dc707046ae4914fd537def529709cc0d285d37a7f9cd442ca \ - --hash=sha256:9700ebd9a51f5895ce75ff4ac4b3c47a7d4b42bc618be8e713e5d56bacf5f931 \ - --hash=sha256:9b18371ad2f44044b81a8d23bc2d8a9b6a6226dca775e8e16cfee640473d6c5d \ - --hash=sha256:a964266397740257f16f7bb2e4f08a0c81454004beab8ff59dd531b73610e9f2 \ - --hash=sha256:adbbedc55506cbdabb830890444fb856bfb0060c46c6f8026c6c2f2cf86ae795 \ - --hash=sha256:ae8a1145af31d903fa9bb166824d7abe9b4681a000b0159c9fb99c11bc11ad26 \ - --hash=sha256:b0e131f880cda8d04e076cee175a46fc0e8bc8b65c99c6c09dff6669335fde74 \ - --hash=sha256:b196eb3f931862af3fa84c2a253514d859c08e0d8fe020e07be12e75a5a9780c \ - --hash=sha256:b7d9a514e73bc42711e6a35aaccf3587c520024fe0a25d830a1a8a27c15f4f57 \ - --hash=sha256:bec9373df11544592b0ba7ec2af0e35059e5f0e7647c6183a854dedd193298f1 \ - --hash=sha256:c42ab9439498270139cc63e18847a02afe5c8b3ed9c931266533cfe378bd3591 \ - --hash=sha256:c91d00057f23b8d353039520dc3a6c09d8608164c692e9f59a175a42b2ae0c19 \ - --hash=sha256:d3e0b61e8efb24ed38898e5cdc5fffa9124be480008d401a1f8071500494ae42 \ - --hash=sha256:d7027eba1df3b2069e2e8d80f644fa0918b68c46432af3d088ddd390d063ecde \ - --hash=sha256:d8ddd2768da81d3ee08cfea9b597f4abb4e8e1dc8ae7e204b608d23a0d3ab699 \ - --hash=sha256:e3268e43984d0b1a185c89b4cfff282a7ead12fc93f56cfd7088bdbcbe727041 \ - --hash=sha256:e4505fc6583f7b05ab854934896bcac8253b04ac1171a77dfb73efef92076d91 \ - --hash=sha256:e56a1ffe9bf7b727432b89104cc0849c21582949dd7bdcb34f17b2001a351a76 \ - --hash=sha256:e6f1278ee4785b6db21229374a1c9e54ec7c549de5d1efc9630b6207de7e170b \ - --hash=sha256:f7616236ec1bc2b15bfdec22a71ab38851c86f8f05ff64f379e1278cf20c634a \ - --hash=sha256:fb24ac194bfc5e86839d7dcd52092ee31e5fe6733fe11f5e3b06ef0812b20072 - # via streamlit pycodestyle==2.14.0 \ --hash=sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783 \ --hash=sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d @@ -1326,10 +999,6 @@ pycparser==3.0 \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 # via cffi -pydeck==0.9.3 \ - --hash=sha256:695775cbfe51f5fdffbd9735ba469987fdc5efc96bc40a0ee4808170509c78b2 \ - --hash=sha256:d8a47c11c81fb12d51b1feb42427ff4f0e13cb599e48931021b2cba98b6849a6 - # via streamlit pyflakes==3.4.0 \ --hash=sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58 \ --hash=sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f @@ -1362,16 +1031,10 @@ pytest-cov==7.1.0 \ --hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \ --hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 # via -r requirements-dev.txt -python-dateutil==2.9.0.post0 \ - --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ - --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 - # via pandas python-multipart==0.0.32 \ --hash=sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e \ --hash=sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23 - # via - # -r requirements.txt - # streamlit + # via -r requirements.txt pytokens==0.4.1 \ --hash=sha256:0fc71786e629cef478cbf29d7ea1923299181d0699dbe7c3c0f4a583811d9fc1 \ --hash=sha256:11edda0942da80ff58c4408407616a310adecae1ddd22eef8c692fe266fa5009 \ @@ -1495,12 +1158,6 @@ readme-renderer==45.0 \ --hash=sha256:030a8fac74904f8fba11ad1bb6964e3f76e896dc7e5e71f16af190c9056696d1 \ --hash=sha256:3385ed220117104a2bceb4a9dac8c5fdf6d1f96890d7ea2a9c7174fd5c84091f # via twine -referencing==0.37.0 \ - --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ - --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 - # via - # jsonschema - # jsonschema-specifications requests==2.34.2 \ --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed @@ -1509,7 +1166,6 @@ requests==2.34.2 \ # pip-audit # requests-toolbelt # sphinx - # streamlit # twine requests-toolbelt==1.0.0 \ --hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \ @@ -1530,153 +1186,11 @@ roman-numerals==4.1.0 \ --hash=sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2 \ --hash=sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7 # via sphinx -rpds-py==2026.5.1 \ - --hash=sha256:01d17b29c0c23d82b1f4751147ec49cf451f1fc2554eb9ef5f957e55d2656ead \ - --hash=sha256:036a36a87fb1cd3b214d11c4b3c4f7d2ddad933625dca1c900b56a057c07740a \ - --hash=sha256:0408a24e44feb919423dc6d9da677cb5cddb894d2ca9e763967d156d9c60fab4 \ - --hash=sha256:07b24fea40541e28570e5b795a4a38fbdcd12550c06bd0748005ecc8116ca256 \ - --hash=sha256:0957cf3c2b8632ec7aaebffebea8005b353cc2a237b6e2ae3c2cac0820704cfb \ - --hash=sha256:0a5ae4dbe43c1076983b72616496919872ae7bbe7a1e21cc48336bc3154d130b \ - --hash=sha256:0a7d1eec967df0e9b22614a5e177622e0c89611d03727fa0cb48e45028907870 \ - --hash=sha256:0b35217adefe87f2fe4db7e9766cabe84744bfe9616d9667be18988928c7f2dc \ - --hash=sha256:0fa92420128dadce7f54bd73ba1825a273e9268fe9e35dbf7e6362890efa4e08 \ - --hash=sha256:141c9498daf2ace9eda35d2b0e376f9ea8b058d84f2aef4f96fccfd449a2f251 \ - --hash=sha256:1841d067089e117142d79b98aa0df2f08b52f2ecc1819dd2700636c0db74a473 \ - --hash=sha256:19cb09fab7b7fc96b2a6e28f2e34b72a3705ff27b37edb77455316e5d3f3dc9b \ - --hash=sha256:1c27c5f6102eac8c03e7595a00827a53b271ba40a53b59ff8709170e0855ea4a \ - --hash=sha256:1ebb2f0ab7e16132995a72de805170e0203df0c3dd22e1ef1cd1fdd90bd7a131 \ - --hash=sha256:1f2c391c3059798093b65df23aca2cac150460ae9c630d99dec83d703d9485b9 \ - --hash=sha256:205dde846f24332ab0c1188699a043b8d165b79bb84529ce272c45048ff6be01 \ - --hash=sha256:21846aac0ed2e0589f38c12dc44e77bb64e494b771eadbcf169cba00566ba7ba \ - --hash=sha256:21942f52dbbd5f8758bf021213d28bd45c39e873e65e2407faf5f1846f5761ad \ - --hash=sha256:277f6c82f0580848796c7ecc8a7173aa3bfb928e4ff831261c2f60a81dc270db \ - --hash=sha256:27b74c10ed6a8f190f4287f53bcfea348b92a84a9c9f70d30183d1e6172d580d \ - --hash=sha256:296c799becfa849c779c8725494fe9ed94959ed886787df4364b058465bad7f0 \ - --hash=sha256:2c595a1d9255dce0599e13130d1440ab2506654f2b50294226ee06402f8fef63 \ - --hash=sha256:2c817a189d4ee14290420e5ff051e4dd6baa13f3edf84685071dee07a6d538ee \ - --hash=sha256:2d88621d6a7d4dfa633d21abe90f280bb205274e16b1d1e61c6ad4640b2453b7 \ - --hash=sha256:3350ec808fb538fe71a1f94dfaa0e29c598dfad805ce49f0caec5ae3183c652b \ - --hash=sha256:3397a5ed7174dc2786bb214030232fc36fe8e5584fec43a9952cc542b1a12036 \ - --hash=sha256:3574b55c604b8f75dacb007136508bbc0db406e626301778096a133327e7f2fb \ - --hash=sha256:3609e9939a8a76cd904cf98a3f1f13b5dc7e150adeaee89e0ea09652ea213e16 \ - --hash=sha256:3684a59b158a7683aaeb8e25352e9a9dd2122cec78f2d8530266e4f91b4c7b3f \ - --hash=sha256:3966b82dd563176396df030f3dd52a6e54cb69b718e95e78bd555ed3d1e0185d \ - --hash=sha256:3abe24a66e57adcfa645d718063a5fa5103ecc71ddbf26d78af8f9368018ff1d \ - --hash=sha256:40ff257542e04796880e011e15cd4dc21c2599975df2aaa8f2c8495ca574e1a5 \ - --hash=sha256:413b424f7c4ee65ab5e5be91f5731be0f8b41a1ee2b12dfe810d716312e95a78 \ - --hash=sha256:42d0f20e85e549c870749d0e247f0c10d318a45b7e9676d575d2dcb04a1b2e66 \ - --hash=sha256:43bca78665423cabae77146f2fe7ce55272b6c8d55d82cca83effd42c7e13972 \ - --hash=sha256:453895624ecf7db7063b1004e44037522bbaef9ff6a945e59bc71662d7a03abd \ - --hash=sha256:4860b603ddda0475a8885499b3729e90229d480105b42651962a5397d995fa89 \ - --hash=sha256:4be8b1d2a705cc37d08256004e1d07de143fa0075c8e85a3df020b776f62b732 \ - --hash=sha256:4e237e139f94d3c036fd28eb9f564c99055476ff4ff05cd42be55ce349b5aa02 \ - --hash=sha256:4fb8d2e7cb2f850b169806d61d1b991738acec96500a75c30f49caf064ce7cef \ - --hash=sha256:55d8f9b7b78c9538fc9e04e82ec0e888ff0c3cffcfad152c77e57cd09351a98a \ - --hash=sha256:58b1d94308ddf0b1982f61f2eb54bf92997c9ece8a8093ef014250f4a517906c \ - --hash=sha256:5d333a7127d4b307601ac37792bee01bb95c867cbfacf21b6375b804d6bbd723 \ - --hash=sha256:613fc4ee9eaef26dc5840666214dd6fbcebcf32f46e76f4abc473059f4e13dda \ - --hash=sha256:6142dbd80c4df62a5d899f0d616d417f84e0bc8d32526c8e5589019d75d028a7 \ - --hash=sha256:62ae3853454fe9ef283a03c96c2d835d39e84b14643a9d62c82ef0fb87d702ca \ - --hash=sha256:63c2c4c213f1a4e3f3de28ecab029dbdee976324e729c0d7a55211be72576b02 \ - --hash=sha256:656a042550878f12d45752452d47094b7cfe5ad1e9d7b87b5a22ad3ae5ff8015 \ - --hash=sha256:66c93681c4729e4e3ecba31b8179fae083ff3118841672835140338b4b9867c1 \ - --hash=sha256:6736718bd4fc49cbcb538ba30516fdbef161522acefb739657d48b97bd864fed \ - --hash=sha256:68700371c5d7ae1412862ddfa719090925c93ecf351c566d66f09d04b136ea00 \ - --hash=sha256:6c3d771a46ec18b12af06ce36243a9a80b07a5d0515236332d90863ca8bb326a \ - --hash=sha256:6c7fcf61d44cacecaf3aea542b0e053db77972a4573e7ceda16fb2b399161195 \ - --hash=sha256:6f249f8b860a200ad35193af961183ebe9132710484e6f6ce0cf89fd83c63a9a \ - --hash=sha256:73c4bd4f70294737b5206a3e8e30ccadbf8a60301831c8ea23eec5dbeea1ecfa \ - --hash=sha256:7559f72b94ae52659086c595dfa017cde03155f7832071d30959049052cb3ece \ - --hash=sha256:75808f6c38ce7749bb68cc2770161aae5045e6c6f6781a9782e74b93304399df \ - --hash=sha256:77c004fdc7b891967106f78ddfd7b076bfe6813c6139c6fff6aed3bcaa960b26 \ - --hash=sha256:7818f8d0a415be74d2be3590b0a1c1f463a642f4d0217e7d10602dceef5b79aa \ - --hash=sha256:7944270ae71383f6e2657dd7d5ce4eeb4ac2d0059a6738f0510583d462ab4842 \ - --hash=sha256:7bd530e6a530bb3ea892f194fafa455f3516ac25ecf7143fd33c09be62b0470a \ - --hash=sha256:8213afbe8a3a906fb9acb2014423fe3359ee783d0bf90995f70623a3217bfa6c \ - --hash=sha256:83bcf894486c9d78dd290d3c0124ff6dd8875d3025e2090a8ec49fcc37c55fdd \ - --hash=sha256:85264a90ff4c05c1568dd65f5921c837614b67c60358fb4c17df3b7f2e90690a \ - --hash=sha256:88647f43a73c4e01be19b04ceef0c8d3a1958153604d13c773becd8016f2a0cf \ - --hash=sha256:8895840ac4809e5f60c88fd07617cd71326e73d6e5a8aa783c5c0f7c24985de2 \ - --hash=sha256:8ba264fa49be666cd9cc56bf34ec7002fb3d27a4aee5bcb4d43d0d18feb1bb6f \ - --hash=sha256:8bff7073db3899158fff55ebf57b113a67030af26f80a18978f9f0aa60250ddf \ - --hash=sha256:8c43a8a973270fd173bf48cdf80bbe66312421cba68d40845034f174f2389049 \ - --hash=sha256:90bd6630002a1c7f09e7843dd79f0d24f3d2897cc25a753480917865d14f15b3 \ - --hash=sha256:90f628283be835db980c941767d41c9a27b5239e54ba0a9c1335247e82406964 \ - --hash=sha256:94068eb3ae6d43f5a786b7db96a406a34e6d5c24489feef32fd6e8946ea7b291 \ - --hash=sha256:980450826cf22e133c57e0835070bdd0dd3f73b9b708c3ce223def2cb9469e14 \ - --hash=sha256:99ab6ba7bfa2cb0f96a04e3652355bf04e3f51aceb1e943b8541dab7ba4828cc \ - --hash=sha256:9af8905b8f854990e40d5206aa5ac58d9b0fe0b7f351ff2bb086c20f6c8c6a47 \ - --hash=sha256:9baffb505aff33acc69b422a19f77806680f3c8632227d79f48de8a810d1c2c5 \ - --hash=sha256:9cdddb6c1207d284d94fd1530adf57fbd797fe7c4b8704ba85f49414f2557e7d \ - --hash=sha256:9e25b7088f9ccbfc0dfcaa52bf969300ca229e10ecf758974ebcbb080a4b37bb \ - --hash=sha256:a04df86b3f0fade39ec8fd0e0aab089b1da9fbd2b48df778a57ef96f5e7d38df \ - --hash=sha256:a05fa4f41f37ec97c9c260441a940450a192f78d774d2b097eee1379f1e1246a \ - --hash=sha256:a2999883eedf72fdfb7520b92c7d4ec2572a71ff40239377aa604cc529eecafc \ - --hash=sha256:aad1bff7f666b9598e573815affd666aac6a13a585dde336f843e33350c7fadc \ - --hash=sha256:abe76bcdba31e576cb83eeb8797aa0d882b738fef6dc65d0601fc753806a5b46 \ - --hash=sha256:ad3773236e95f7f33991eb125224b7da66f206504d032a253a02da7e134519fb \ - --hash=sha256:af03e34e860047bc7a352b842856fcf78798fbb81132cc98bd2f907ab4eb9cd2 \ - --hash=sha256:b1b964e3ab599e718dc46c018d104b1ebc007cbc6567d827c94a687fca56d77e \ - --hash=sha256:b1be5c35683684d5331b93600c210e8367c254683d8a6df6bd21bd2da3a334fb \ - --hash=sha256:b317c87a13f769a4e787819bd508aaa5d69aa09b0880de9af6d3a8a54571cdec \ - --hash=sha256:b3cc20c0d800af78fd0fac68086e28c1856cec51ea528bb81ea851aa40d39325 \ - --hash=sha256:b4e4bc98639ec915f512fde3aa7a95e0041d95d9c3cc86eea841fa63cb1e8600 \ - --hash=sha256:b5c30f3f04eef4fbd362226a6f31d7c8895ca4fbb6e0b790f6890a98d8da8559 \ - --hash=sha256:b5f077b44a4f7808520f66dae234988d867deb9aed9be5da057ce9ba831b2a41 \ - --hash=sha256:b6825cc329b290e93c5f6a9be2393118a763f6ccf6abd83704e0c102ca583644 \ - --hash=sha256:b8d2f912928d426e8cfa396f7f3f8d29a59e6689c86dcca3c420730c1096322b \ - --hash=sha256:b95d5e11fc712b752081183a55a244c03cd00570489edd7014d8899f8ceb8162 \ - --hash=sha256:b9a6528956191c48c52294a592dbd4a8386d7048bdb25c0efcb6b966466c6d83 \ - --hash=sha256:ba05adbf15d994c38ec0b7ab32e858e5110c21e9009a00a86545fd220f84e038 \ - --hash=sha256:c0f920015df2a504bebaba6d4c31ccf3fcf942f92655c086da30b671aad19aa6 \ - --hash=sha256:c396c1304de421050b3681ea70f371874b54d41b0151e96109758144c231e30b \ - --hash=sha256:c39f5b67a8a2e67179ada2a954227d670fe65fa9098457f698f56ddf248709b3 \ - --hash=sha256:c3df104083952a0e0c6f10de33e440eabe98fb6317d23e1a58c68f6df08d01b9 \ - --hash=sha256:c74005a7bb87752acf351c93897ec63ad77a07a0da7ecad9c050e32e7286ba34 \ - --hash=sha256:c93c629be4636cf54337bd5f06c104d55e42ced54d681f6fe21ae510a65116f6 \ - --hash=sha256:ca653c6546386227cd9800d1bef6a348099acf8db4250341da6d90f663d6dfcb \ - --hash=sha256:cacedb7a6e167680acba45ad5716e89067d225dc80da0d7040cae8c81d4572fa \ - --hash=sha256:cc68e231a77a5f0d774ae278a1f8e55c0456501820847c1e4efb3829f3441df6 \ - --hash=sha256:ce87129d9f2c14fa6c4a8601fb80eb4488c80d38a20cd13758ef11123e14995d \ - --hash=sha256:cea68bcd53467561ae2f96a6bdad1544299ba97b5b0ddcd5ac3d376e5c781c24 \ - --hash=sha256:cef8ac28d26f4dda3533060c20fbf80a325458fa9fd23ea72a73cdfa8e978838 \ - --hash=sha256:d0efbe45632665e53e3db8fe1e5692db58fc5cb9bab4459d570b83efefe11164 \ - --hash=sha256:d3858b908218ee108d0bbfb2095ccc237648053c9bf98affad7cb079acaf1d97 \ - --hash=sha256:de42116e69cb53b911cc34aee5ab98f36c597b822545045d49e938818b99e5e4 \ - --hash=sha256:df1d2a1996755b24b9ecee92cb4d36c28f86f464a6a173349c26bab41e94b8c2 \ - --hash=sha256:e07be2a9d7122bd6e82dea89814ef8dc893feb1aae97fec1630f3263bbb30e55 \ - --hash=sha256:e0b360f316d966b048b085857630b3cc51f3db2f07b06f440eac8f695374d1e3 \ - --hash=sha256:e10464d17df3b582745c25cec695cb9558bca2cb6ddb631aee1787fc72c767b2 \ - --hash=sha256:e3a8ae58895ac107ed934a6bf51e5846f95c53b9b940c2c6d310838fd5846358 \ - --hash=sha256:e4abbf391a70be864920858bf360f4fb380577c9a0f732438a1996726e2c195b \ - --hash=sha256:eaaea962c68cdc68d4a533ba985ab8e9484277910bbfaa2ab3ef7732667bfed8 \ - --hash=sha256:ed0954b524873214369184a9c82b0eaa45a3fbb9a798cd95b17e0d98499e7ea0 \ - --hash=sha256:edf2765d84e42447f112ad877af8fe1db0089aaec5b28e88d6eab45e7fe99cea \ - --hash=sha256:ef1013a8625c74043210190b246f5b1551e09757c1f356c6e4160ef96c5bc081 \ - --hash=sha256:efef4ac29c6ff495531eb17ee705b62841ecaa291b7c7077e848ea03e237164d \ - --hash=sha256:f3a5b10e8ce894825f380a8f1b6444cf73c294dfea62afbb2d13e3a9e630cec1 \ - --hash=sha256:f3df3d16ded76f1f8c9cdebd0e1ea55fdf4c23b812de189814da7cf229c22a81 \ - --hash=sha256:f414556f6e3958300ff941e40c9f97e3dc9774ddd1b3434c475d73dd354bbed3 \ - --hash=sha256:fc09f82e63d4bcd58149572f857a431bae851dc747e313c3b5bdf7abb907fda8 \ - --hash=sha256:fc0c0f878ea770a0a8a462456c5ad36fc9fe6358e6b76fdadc7f17575e0b8bf1 \ - --hash=sha256:fe71bca7d547acb17027c7fd1624ff8aae623499c498d3e7011182c4de5c25e0 \ - --hash=sha256:fea6e836d10abbe191d557d33bd58bd5987725fe63aa1eefe557d230209855bd - # via - # jsonschema - # referencing secretstorage==3.5.0 ; sys_platform == "linux" \ --hash=sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137 # via # -r requirements-dev.txt # keyring -six==1.17.0 \ - --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ - --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 - # via python-dateutil -smmap==5.0.3 \ - --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ - --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f - # via gitdb snowballstemmer==3.1.1 \ --hash=sha256:7e207fa178741da09cdee59d3ecec3827ad5f92b1fc5c9ff3755b639f71f5752 \ --hash=sha256:e07bbc54a0d798fe6010a12398422e62a8bfbba95c394fd0956ef58cb4d3e260 @@ -1732,25 +1246,11 @@ sphinxcontrib-serializinghtml==2.0.0 \ starlette==1.3.1 \ --hash=sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0 \ --hash=sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6 - # via - # -r requirements.txt - # streamlit + # via -r requirements.txt stevedore==5.8.0 \ --hash=sha256:88eede9e66ca80e34085b9174e2327da2c61ac91f24f70e41c3ad76e4bb4872b \ --hash=sha256:b49867b32ca3016e94100e68dbf26e72aa7b8708d0a3f73c08aeb220370ac715 # via bandit -streamlit==1.59.2 \ - --hash=sha256:5014cb4f0064bd16c58fe334cb0d3c4b7e2be3d1ce4c02202c07114a33576dab \ - --hash=sha256:8fcb35df152868d33eec7ad2d89e276499a5351fb861eb1752b76476be7eb582 - # via -r requirements.txt -tenacity==9.1.4 \ - --hash=sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55 \ - --hash=sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a - # via streamlit -toml==0.10.2 \ - --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ - --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f - # via streamlit tomli==2.4.1 \ --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ @@ -1811,10 +1311,7 @@ twine==6.2.0 \ typing-extensions==4.16.0 \ --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 - # via - # altair - # mypy - # streamlit + # via mypy urllib3==2.7.0 \ --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 @@ -1825,152 +1322,7 @@ urllib3==2.7.0 \ uvicorn==0.51.0 \ --hash=sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b \ --hash=sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0 - # via - # -r requirements.txt - # streamlit -watchdog==6.0.0 \ - --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ - --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ - --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ - --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ - --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ - --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ - --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ - --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ - --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ - --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ - --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ - --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ - --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ - --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ - --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ - --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ - --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ - --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ - --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ - --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ - --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ - --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ - --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ - --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ - --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ - --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ - --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ - --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ - --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ - --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 # via -r requirements.txt -websockets==16.1.1 \ - --hash=sha256:01fbdcbac298efe19360b94bc0039c8f746f0220ba570f327577bfee81059175 \ - --hash=sha256:024193f8551a2b0eafbdd160911012c4e6c228c28430c84433253299a9e42d6a \ - --hash=sha256:04fd29a0e2fe9414a95b00e92c67ae51bf900c50c0f8a4b2dafdad621f49ea1d \ - --hash=sha256:056ae37939ed7e9974f364f5864e76e49182622d8f9751ac1903c0d09b013985 \ - --hash=sha256:0f62863e8a00a6d33c3d6566ec0b89f23787b747ffe0c3bc71ec0e76b82c94b1 \ - --hash=sha256:0ffd3031ea8bda8d61762e84220186105ba3b748b3c8da2ae4f7816fac03e573 \ - --hash=sha256:1214e673c404684b9bf7154f5cf43b45025b1a6160fac3a9e438e9c1a97e22cb \ - --hash=sha256:125f22dbefaf1554fea66fc83851490edb284ce4f501d37ffed2752f418332d9 \ - --hash=sha256:130937b167a52af203c8d58e78d67705874e82759862e3b9671a452fec4abc87 \ - --hash=sha256:1427fb4cf0d72f66333e2cacc3ff5f575bf2d7008166ce991a4a470b21d51a22 \ - --hash=sha256:195c978b065fa40910582464f99d6b15c8b314c68e0546549a55ed83f4735328 \ - --hash=sha256:1d27fa8462ad6a1cb36206a3d0640b2333340def181fae11ed7f9adeaa5c0747 \ - --hash=sha256:1db4de4a0e95673f7545d393c49eeb0c2f18ac1ef93073218c79d5cdb2ee75ab \ - --hash=sha256:1f79c89b5eb034d1722938a891916582f8f7f503f58ca22518a63c3f2cd18499 \ - --hash=sha256:23253dd5bcae3f9aaee0a1d30967a8dbd52e5d3cff93a2e5b84df57b77d4750d \ - --hash=sha256:249116b4a76063d930a46391ad56e135c286e4562a18309029fc2c73f4ed4c62 \ - --hash=sha256:29dfa8114c4a620c69591c5973860f768eac29d3fd6904f37f34266cb219c512 \ - --hash=sha256:2a606d9c24035242a3e256e9d5b77ed9cd6bccfcb7cf993e5ca3c0f6f68fb6a7 \ - --hash=sha256:2a636ff1e7a5c4edf71ef0e79adae7f25dba93b4fcbe3dc958733477ffeb0eaf \ - --hash=sha256:2bb5d041a8307d2e18782e7ce777f6fdb1e8c2f5d09291484b18c294b789d9aa \ - --hash=sha256:2e28e602bb13da44fbe518c1781a88e3b9d4c3d48d02c9bad83e546164336f57 \ - --hash=sha256:30bbe120437b5648a77d3519b7024ea09530e0b5b18d3698c5a0ae536fe0cc2e \ - --hash=sha256:34420aaa64440ebd51ac72ca8a45ef4626429438c9b02e633ae412ed43f925d3 \ - --hash=sha256:38565aca3e01ea8734e578fb2118dade0ecb0250533f29e22b8d1a7a196cf4d0 \ - --hash=sha256:387e8e4aa5df2f90b198fa3cad3478822a89cf905b6a6d6c97dc3664689640cc \ - --hash=sha256:39f2a024af5c345ffe8fcf1ee18c049c024c94df393bb09b044a6917c77bde43 \ - --hash=sha256:3df13f73af9b3b38ab1195eb299ecb67a4330c911c97ae04043ff74085728abe \ - --hash=sha256:414e596c75f74e0994084694189d7dc9229fb278e33064d6784b73ffbba3ca31 \ - --hash=sha256:41c8e77f17294c0ac18008a7309b99b34ee72247ef10b6dff4c3f8b5ac29896b \ - --hash=sha256:42290eb6db4ccaca7012656738214f8514082fb6fa40cdeb61bb9a471b52e383 \ - --hash=sha256:42f599f4d48c7e1a3338fdaac3acd075be3b3cf02d4b274f3bf2767aedd3d217 \ - --hash=sha256:43e3a9fdd7cbf7ba6040c31fae0faf84ca1474fef777c4e37912f1540f854499 \ - --hash=sha256:443aefe96b7fdb132e2a70806cca1f2af49bb3f28e47abcd7c2e9dcf4d8fa1b8 \ - --hash=sha256:46dcaa042cd1de6c59e7d9269fa63ff7572b6df40510600b678f0826b3c7af51 \ - --hash=sha256:496af849a472b531f758dbd4d61338f5000538cb1a7b3d20d9d32a264517f509 \ - --hash=sha256:49ae99bdfcae803a885c926bf14f886196e84925395bb3f568fef5c0f0979d7d \ - --hash=sha256:4b57693728576d84ede0a77987ab16881b783d2cd9f1dc180a8fbbc3f79c4428 \ - --hash=sha256:4e3b680b1e0a27457e727a0d572fd81dffa87b6dbf8b228ab57da64f7d85aead \ - --hash=sha256:4e8d01cc3bcae7bbf8167f944aeafefed590fae5693552bba9794a9df68371cc \ - --hash=sha256:5283810d2646741a0d8da2aa733d6aefa0545809afccb2a5d105a26bc45125f1 \ - --hash=sha256:53260c8930da5771cec89439bff99c20c8cb03ddb9588b980697355a83cd4bd3 \ - --hash=sha256:536676848fc5961aca9d20389951f59169508f765637a172403dc5434d722fa0 \ - --hash=sha256:54509b8e92fee4453e152b7558ddef37ce9705a044922f2095a6105e3f80c96f \ - --hash=sha256:56cd5fc4f10a9ea8aa0804bddb7b42506cf9e136046f3b4c27de8fec9e2ecba5 \ - --hash=sha256:5bfd1ac19b1b9986a9c95a82d5e23a391ebb09e12c34d7be6094b86efcc35731 \ - --hash=sha256:5c31aa7e39ee3e8a358573257f1c0bb5c52430d1b637030dd9c8cc2c282926be \ - --hash=sha256:5e3b7d601f6f84156b08cc4a5e541c2b50ad7b36cfc302b657a12477c904a5df \ - --hash=sha256:61922544a0587a13fd3f53e4c0e5e606510c7b0d9d22c8444e5fae22a06b38cb \ - --hash=sha256:6456ff333092d509127d75a638cb411afae8ff17f092635015d1902efec8a293 \ - --hash=sha256:69159730a823dde3ea8d08783e8d47ef135a6d7e8d44eb127e32b321c9db8e3e \ - --hash=sha256:69e52d175a0a7d1e13b4b67ad41c560b7d98e8c6f6126eb0bda496c784faf8c7 \ - --hash=sha256:6aaface73b9c71974c6497366d8b9628357f6c9749e09c4ea3610176c63f2ae3 \ - --hash=sha256:6abbd3e82c731c8e531714466acd5d87b5e88ac3243465337ba71d68e23ae7e3 \ - --hash=sha256:6ff9417c0ada4d0f7d212f928303e5579bdf3ace4c802fa4afabb30995da58c3 \ - --hash=sha256:7421fad442de870a8cbf2287d1cad7e706ece0dbfeba5e911df132cbdc1cb56a \ - --hash=sha256:7883388947767080f094950b342b30d35a2a06b849cd967c422fa0db72b40ea9 \ - --hash=sha256:79eace538c6a97e96d0d03d4f9d314f9677f5ed85a8a984992ffd90b13cb8a56 \ - --hash=sha256:7b1b19636af86a3c7995d4d028dbe376f39b4bf31541146f9c123582a6c94562 \ - --hash=sha256:7dfcad78ea1492ee3a9ec765cb7f51bbc17d477107aaf6b22abf7b2558d1c5a0 \ - --hash=sha256:8087e82f842609734c9b5a1330464f8e94e346ba0e18c832c08bafa4b0d63c15 \ - --hash=sha256:820fb8450edddae3812fd58cbc08e2bf22812cb248ecb5f06dbb82119a56e869 \ - --hash=sha256:8483c2096363120eea8b07c06ae7304d520f686665fffd4811fad423930a65d7 \ - --hash=sha256:84a2cef8deffbd9ab8ee0ea546a2a6a7030c28f44e6cdd4547dbfeb489eb8999 \ - --hash=sha256:86d7f0f8bdb25d2c632b72527325e4776430fd5bc61b9118de4e2b8ddb5f5b01 \ - --hash=sha256:8fe0b50da2d84535fb4f7b4bfa951280f97ce3d558a0443b541166d609e67b57 \ - --hash=sha256:90001d893bc368e302ef168d82130b4e4fdd27b85fa094682df9b667c2d48838 \ - --hash=sha256:9246a0d063cfcbcc85f2359dd6876d681213f4790832272aa16641b4ed5d64d4 \ - --hash=sha256:92b820d345f7a3fc7b8163949ee92df910f290c3fc517b3d5301c78065adafe1 \ - --hash=sha256:952303a7318d4cbe1011400839bb2051c9f84fa0a35923267f5daba34b15d458 \ - --hash=sha256:97fd3a0e8b53efa41970ac1dff3d8cf0d2884cadeb4caaf95db7ad1526926ee3 \ - --hash=sha256:9c1c5705e314449e3308872fe084b8571ce078ee4fc55a98a769bdefe5917392 \ - --hash=sha256:9c9f23004a3d40e89c01a7955d186a6cc83418d93b749701944ce2de3e95a1f3 \ - --hash=sha256:9f63bcef7f4b02b06b35fc01c93b96c43b5e88e1e8868676caacf493d5a31f3a \ - --hash=sha256:a0eadbbf2c30f01efa58e1f110eb6fa293261f6b0b1aa38f7f48707107690af9 \ - --hash=sha256:a28fcbc9b6baf54a2e23f8655f308e4ccc6afdd7266f8fe7954f320dcda0f785 \ - --hash=sha256:a6a61aff018180c9c50b7b0da33bfd29d378af3497429c95006c589a23a11648 \ - --hash=sha256:aabe464bfd13bd25f4821faf111da6fefdc389f870265a53105580e45b0a2e49 \ - --hash=sha256:ab59169ace05dcb49a1d4118f0bde139557adf45091bd85747e36bf5de984dd1 \ - --hash=sha256:b436f6ec4fc3a6b4237c84d3f83170ed2b40bb584222f0ac47a0c8a5921980c7 \ - --hash=sha256:b6b9dadbef0cccd9f4c4ee96b08898afa73e26803bbe0f6aeb5bb12b0074206d \ - --hash=sha256:b852788aa51764e2d8e4cf5493d559326bcae5e38d16ba25ffa322b034df272a \ - --hash=sha256:bae954c382e013d5ea5b190d2830526bfa45ad121c326da0049b8c769f185db6 \ - --hash=sha256:bcce07e23e5769375158f5efdcdafa8d5cd014b93c6683865b840ed65b96f231 \ - --hash=sha256:cc97814dfb786a83b6e2dc2e79351e1b83e6d715647d6887fcabd83026417a00 \ - --hash=sha256:cd2ca96a082a36964aca83e992f72abeb61b7306c1a6cba4c7d06a7b93750cac \ - --hash=sha256:cfb70b4eb56cac4da0a83588f3ad50d46beb0690391082f3d4e2d488c70b68ea \ - --hash=sha256:d0fcf657e9f13ff4b177960ab2200237b12994232dfb6df16f1cfe1d4339f93c \ - --hash=sha256:d14bfb217eb4701e850f1525c9d29d79c44794cdf1c299ead25f39f8c78dea81 \ - --hash=sha256:d57685547e0060cc6fd90ee6a28405d6bd395e525545f13c8d7cd99c78afd79f \ - --hash=sha256:d6bec75c290fe484a8ba4cacdf838501e17c06ecfbbf31eede81a9e431bd7751 \ - --hash=sha256:d9531d9cbeac99af6f038fb1bc351403531f7d634a2c2e10e2f7c854c6ed5b68 \ - --hash=sha256:da4ca1a9d72f9030b3146b8d7022719a9f3d478f61efe6f7dd51d243f61c51b2 \ - --hash=sha256:dab9eb87869da2d6ed3af3f3adf28414baae6ec9d4df355ffc18889132f3436c \ - --hash=sha256:db234eda965dcce15df96bb9709f587cd87d4d52aaf0e80e2f34ec04c7670c57 \ - --hash=sha256:dc0fad4933f427acd5b1cec210f3ea6dce7089e1724e4b9ec6ef47c6c04d1b3b \ - --hash=sha256:dc385593a42e31cd6fb60c19f0ecb015b386603818fc2c6c274fb42bd2bb4165 \ - --hash=sha256:dcc04fedf83effaeb9cce98abc9469bb1b42ef85f03e01c8c1f4438ef7555737 \ - --hash=sha256:e047dc87ef7ca50f4d309bf775ad4a71711c58556d75d7bd0604b2317f43e94b \ - --hash=sha256:e09f753a169951eb4f28c2c774f71069304f66e7277e0f5a2892423599cfa854 \ - --hash=sha256:ed5bb271084b46530ee2ddc0410537a9961152c5ccba2fc98c5276d992ccba87 \ - --hash=sha256:f0aa4aad3b1b69ad3fd85a0fd0952ec64331c762bd77ec51cc814170873890b2 \ - --hash=sha256:f17dbe07eb3ea7f99e4df9b7e0efefe80fbf30d37a8cc4d561a0aed310bc8847 \ - --hash=sha256:f2769a0344a09e9ccf5b3cce538bc75a51b53eff3275d3896310c8552049195d \ - --hash=sha256:f55f0b01956a094c8587146d9558c91937e78789c333860ffaf35931a6e5dbc4 \ - --hash=sha256:f5d497865f05bb222cab7016c6034542e84e5f29f49c6fd3f4939cda7197b5b8 \ - --hash=sha256:f70541f3104339f59f830522d94ebadb1bf47426287381623443d8bb1cdbf33d \ - --hash=sha256:fb9a0a6dc3d1b3986cb88091b6899f0396651e0f74e2c9766ab8d6ffc3842e29 \ - --hash=sha256:fce6c48559c86d1ac3632ccb1bebc7d5442fbe79bd9bb0e40379ee54be2a4051 \ - --hash=sha256:fd46fff7eb62c24804d234f0051c7a8ea81285ad63e0337d3dcf33ca82aee58a - # via streamlit wheel==0.47.0 \ --hash=sha256:212281cab4dff978f6cedd499cd893e1f620791ca6ff7107cf270781e587eced \ --hash=sha256:cc72bd1009ba0cf63922e28f94d9d83b920aa2bb28f798a31d0691b02fa3c9b3 diff --git a/requirements-lock.txt b/requirements-lock.txt index 97b38f0..4c3e154 100644 --- a/requirements-lock.txt +++ b/requirements-lock.txt @@ -4,34 +4,10 @@ # # pip-compile --generate-hashes --output-file=requirements-lock.txt requirements.txt # -altair==6.2.2 \ - --hash=sha256:94014f8ad8617c3cb163d1137359cd6db5ba134b9b46d93cfd8b609fd245a583 \ - --hash=sha256:a1ff9d9cfe81c75414641826312b9471780e19d39293ba0b012933f6b6cba0fe - # via streamlit anyio==4.14.2 \ --hash=sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494 \ --hash=sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f - # via - # starlette - # streamlit -attrs==26.1.0 \ - --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ - --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 - # via - # jsonschema - # referencing -blinker==1.9.0 \ - --hash=sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf \ - --hash=sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc - # via streamlit -cachetools==7.1.4 \ - --hash=sha256:323dc4127934744db5b54eb4924482d7edafbf9554e820d1531c2e08c0e4ef54 \ - --hash=sha256:437f55a4e0c1b01a4f3077cc470e6991d47430970e36fbcb77e2be0df4fc1cd6 - # via streamlit -certifi==2026.6.17 \ - --hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \ - --hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db - # via requests + # via starlette cffi==2.1.0 \ --hash=sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc \ --hash=sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd \ @@ -134,107 +110,10 @@ cffi==2.1.0 \ --hash=sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da \ --hash=sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f # via cryptography -charset-normalizer==3.4.9 \ - --hash=sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380 \ - --hash=sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62 \ - --hash=sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c \ - --hash=sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226 \ - --hash=sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5 \ - --hash=sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833 \ - --hash=sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b \ - --hash=sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99 \ - --hash=sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501 \ - --hash=sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec \ - --hash=sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698 \ - --hash=sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4 \ - --hash=sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a \ - --hash=sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3 \ - --hash=sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2 \ - --hash=sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a \ - --hash=sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e \ - --hash=sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4 \ - --hash=sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419 \ - --hash=sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84 \ - --hash=sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da \ - --hash=sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519 \ - --hash=sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe \ - --hash=sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381 \ - --hash=sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29 \ - --hash=sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614 \ - --hash=sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0 \ - --hash=sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe \ - --hash=sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29 \ - --hash=sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0 \ - --hash=sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917 \ - --hash=sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9 \ - --hash=sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32 \ - --hash=sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94 \ - --hash=sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63 \ - --hash=sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd \ - --hash=sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198 \ - --hash=sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde \ - --hash=sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012 \ - --hash=sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1 \ - --hash=sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15 \ - --hash=sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b \ - --hash=sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993 \ - --hash=sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4 \ - --hash=sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5 \ - --hash=sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8 \ - --hash=sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35 \ - --hash=sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642 \ - --hash=sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2 \ - --hash=sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d \ - --hash=sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9 \ - --hash=sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c \ - --hash=sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33 \ - --hash=sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db \ - --hash=sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf \ - --hash=sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9 \ - --hash=sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee \ - --hash=sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84 \ - --hash=sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44 \ - --hash=sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f \ - --hash=sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9 \ - --hash=sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9 \ - --hash=sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177 \ - --hash=sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8 \ - --hash=sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b \ - --hash=sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39 \ - --hash=sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41 \ - --hash=sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0 \ - --hash=sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616 \ - --hash=sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d \ - --hash=sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba \ - --hash=sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2 \ - --hash=sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b \ - --hash=sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9 \ - --hash=sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b \ - --hash=sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209 \ - --hash=sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48 \ - --hash=sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046 \ - --hash=sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632 \ - --hash=sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a \ - --hash=sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2 \ - --hash=sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1 \ - --hash=sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b \ - --hash=sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990 \ - --hash=sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5 \ - --hash=sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b \ - --hash=sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9 \ - --hash=sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534 \ - --hash=sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81 \ - --hash=sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a \ - --hash=sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d \ - --hash=sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf \ - --hash=sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115 - # via requests click==8.4.2 \ --hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \ --hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76 - # via - # streamlit - # uvicorn + # via uvicorn cryptography==49.0.0 \ --hash=sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001 \ --hash=sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122 \ @@ -283,14 +162,6 @@ cryptography==49.0.0 \ --hash=sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493 \ --hash=sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b # via -r requirements.txt -gitdb==4.0.12 \ - --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ - --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf - # via gitpython -gitpython==3.1.52 \ - --hash=sha256:79a36ee1f83523214a3f72d56cf1c4e490d577dc61af77e43dfe5862bd9da01a \ - --hash=sha256:de0a8ad86274c6e75ae8b37dd055ba68f19818c813108642263227b20775b48e - # via streamlit h11==0.16.0 \ --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 @@ -346,759 +217,28 @@ httptools==0.8.0 \ --hash=sha256:ef7c3c97f4311c7be57e2986629df89d49cb434dbff78eafcd48c2bff986b15a \ --hash=sha256:f256d6ce930c52ca1cb2a960b7da03548c454e7d28b06059ad41bfe789036ce0 \ --hash=sha256:fe2a4c95aeba2209434e7b31172da572846cae8ca0bf1e7013e61b99fbbf5e72 - # via - # -r requirements.txt - # streamlit + # via -r requirements.txt idna==3.18 \ --hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \ --hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848 - # via - # anyio - # requests -itsdangerous==2.2.0 \ - --hash=sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef \ - --hash=sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173 - # via streamlit -jinja2==3.1.6 \ - --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ - --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 - # via - # altair - # pydeck -jsonschema==4.26.0 \ - --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \ - --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce - # via altair -jsonschema-specifications==2025.9.1 \ - --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ - --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d - # via jsonschema -liboqs-python==0.15.0 \ - --hash=sha256:969b27c65c99f973f8c991472151331814c9f02642115fe4d6391bcdc33433a4 + # via anyio +liboqs-python==0.16.0 \ + --hash=sha256:50bb11a9767b88f68099cedef8de09f798f31eaba1aa18b483988bfcd50df440 \ + --hash=sha256:ee01445ccfbeab8dced956a642ce1eb5ba69438caba7ec291eea14083627d5c0 # via -r requirements.txt -markupsafe==3.0.3 \ - --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ - --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ - --hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \ - --hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \ - --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ - --hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \ - --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ - --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \ - --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \ - --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \ - --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ - --hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \ - --hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \ - --hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \ - --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \ - --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ - --hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \ - --hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \ - --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \ - --hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \ - --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ - --hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \ - --hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \ - --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ - --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \ - --hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \ - --hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \ - --hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \ - --hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \ - --hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \ - --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ - --hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \ - --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \ - --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ - --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \ - --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ - --hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \ - --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ - --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \ - --hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \ - --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \ - --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ - --hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \ - --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \ - --hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \ - --hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \ - --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \ - --hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \ - --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \ - --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \ - --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \ - --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ - --hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \ - --hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \ - --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \ - --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \ - --hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \ - --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \ - --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \ - --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \ - --hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \ - --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ - --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \ - --hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \ - --hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \ - --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ - --hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \ - --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \ - --hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \ - --hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \ - --hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \ - --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \ - --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \ - --hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \ - --hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \ - --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \ - --hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \ - --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ - --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ - --hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \ - --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ - --hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \ - --hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \ - --hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \ - --hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \ - --hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \ - --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ - --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ - --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 - # via jinja2 -narwhals==2.24.0 \ - --hash=sha256:42fdedf44e5b2ca7505630d45b4ac3058f38d8485cba9fe1652ca23152df7489 \ - --hash=sha256:b5c0f684ccd9d7475b564111e319a4964abcf2baf79d3cf6b1003d06ac9b828d - # via altair -numpy==2.4.6 \ - --hash=sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1 \ - --hash=sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4 \ - --hash=sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f \ - --hash=sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079 \ - --hash=sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096 \ - --hash=sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47 \ - --hash=sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66 \ - --hash=sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d \ - --hash=sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1 \ - --hash=sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e \ - --hash=sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147 \ - --hash=sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd \ - --hash=sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75 \ - --hash=sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063 \ - --hash=sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73 \ - --hash=sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab \ - --hash=sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4 \ - --hash=sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41 \ - --hash=sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402 \ - --hash=sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698 \ - --hash=sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7 \ - --hash=sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8 \ - --hash=sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b \ - --hash=sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8 \ - --hash=sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0 \ - --hash=sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662 \ - --hash=sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91 \ - --hash=sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0 \ - --hash=sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f \ - --hash=sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3 \ - --hash=sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f \ - --hash=sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67 \ - --hash=sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6 \ - --hash=sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997 \ - --hash=sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b \ - --hash=sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e \ - --hash=sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538 \ - --hash=sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627 \ - --hash=sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93 \ - --hash=sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02 \ - --hash=sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853 \ - --hash=sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c \ - --hash=sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43 \ - --hash=sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd \ - --hash=sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8 \ - --hash=sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089 \ - --hash=sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778 \ - --hash=sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1 \ - --hash=sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb \ - --hash=sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261 \ - --hash=sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb \ - --hash=sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a \ - --hash=sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8 \ - --hash=sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359 \ - --hash=sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5 \ - --hash=sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7 \ - --hash=sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751 \ - --hash=sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8 \ - --hash=sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605 \ - --hash=sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e \ - --hash=sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45 \ - --hash=sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2 \ - --hash=sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895 \ - --hash=sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe \ - --hash=sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb \ - --hash=sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a \ - --hash=sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577 \ - --hash=sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d \ - --hash=sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a \ - --hash=sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda \ - --hash=sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6 \ - --hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20 - # via - # pandas - # pydeck - # streamlit -packaging==26.2 \ - --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ - --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661 - # via - # altair - # streamlit -pandas==3.0.3 \ - --hash=sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c \ - --hash=sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2 \ - --hash=sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13 \ - --hash=sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04 \ - --hash=sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6 \ - --hash=sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824 \ - --hash=sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb \ - --hash=sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066 \ - --hash=sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e \ - --hash=sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76 \ - --hash=sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac \ - --hash=sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7 \ - --hash=sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5 \ - --hash=sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f \ - --hash=sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98 \ - --hash=sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d \ - --hash=sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1 \ - --hash=sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639 \ - --hash=sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2 \ - --hash=sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49 \ - --hash=sha256:5cc09a68b3120e0f54870dede8287a7bb1fa463907e4fcec1ea77cab6179bf7a \ - --hash=sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028 \ - --hash=sha256:6674ab18ad8c57802867264b00e15e7bb904700cdd9046e3b2fa1fce237439ea \ - --hash=sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa \ - --hash=sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc \ - --hash=sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9 \ - --hash=sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf \ - --hash=sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c \ - --hash=sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27 \ - --hash=sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a \ - --hash=sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a \ - --hash=sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977 \ - --hash=sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a \ - --hash=sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938 \ - --hash=sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44 \ - --hash=sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4 \ - --hash=sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1 \ - --hash=sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb \ - --hash=sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f \ - --hash=sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d \ - --hash=sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc \ - --hash=sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870 \ - --hash=sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8 \ - --hash=sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085 \ - --hash=sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd \ - --hash=sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360 \ - --hash=sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c \ - --hash=sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09 - # via streamlit -pillow==12.3.0 \ - --hash=sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756 \ - --hash=sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a \ - --hash=sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59 \ - --hash=sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45 \ - --hash=sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3 \ - --hash=sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df \ - --hash=sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139 \ - --hash=sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b \ - --hash=sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39 \ - --hash=sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e \ - --hash=sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8 \ - --hash=sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1 \ - --hash=sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8 \ - --hash=sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89 \ - --hash=sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5 \ - --hash=sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130 \ - --hash=sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd \ - --hash=sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d \ - --hash=sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b \ - --hash=sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed \ - --hash=sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace \ - --hash=sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb \ - --hash=sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931 \ - --hash=sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510 \ - --hash=sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6 \ - --hash=sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1 \ - --hash=sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce \ - --hash=sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385 \ - --hash=sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e \ - --hash=sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c \ - --hash=sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7 \ - --hash=sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace \ - --hash=sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c \ - --hash=sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f \ - --hash=sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64 \ - --hash=sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f \ - --hash=sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a \ - --hash=sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827 \ - --hash=sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17 \ - --hash=sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4 \ - --hash=sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a \ - --hash=sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701 \ - --hash=sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e \ - --hash=sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91 \ - --hash=sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66 \ - --hash=sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468 \ - --hash=sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217 \ - --hash=sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658 \ - --hash=sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418 \ - --hash=sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a \ - --hash=sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c \ - --hash=sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330 \ - --hash=sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402 \ - --hash=sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09 \ - --hash=sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930 \ - --hash=sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f \ - --hash=sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec \ - --hash=sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a \ - --hash=sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94 \ - --hash=sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468 \ - --hash=sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b \ - --hash=sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965 \ - --hash=sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8 \ - --hash=sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd \ - --hash=sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7 \ - --hash=sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c \ - --hash=sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777 \ - --hash=sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35 \ - --hash=sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9 \ - --hash=sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f \ - --hash=sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f \ - --hash=sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0 \ - --hash=sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c \ - --hash=sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71 \ - --hash=sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3 \ - --hash=sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838 \ - --hash=sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf \ - --hash=sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321 \ - --hash=sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26 \ - --hash=sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec \ - --hash=sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9 \ - --hash=sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65 \ - --hash=sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5 \ - --hash=sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e \ - --hash=sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d \ - --hash=sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198 \ - --hash=sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7 - # via streamlit -protobuf==7.35.1 \ - --hash=sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799 \ - --hash=sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87 \ - --hash=sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6 \ - --hash=sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30 \ - --hash=sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9 \ - --hash=sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4 \ - --hash=sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4 \ - --hash=sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a - # via streamlit -pyarrow==24.0.0 \ - --hash=sha256:02b001b3ed4723caa44f6cd1af2d5c86aa2cf9971dacc2ffa55b21237713dfba \ - --hash=sha256:04920d6a71aabd08a0417709efce97d45ea8e6fb733d9ca9ecffb13c67839f68 \ - --hash=sha256:0b3537c00fb8d384f15ac1e79b6eb6db04a16514c8c1d22e59a9b95c8ba42868 \ - --hash=sha256:1183baeb14c5f587b1ec52831e665718ce632caab84b7cd6b85fd44f96114495 \ - --hash=sha256:14e31a3c9e35f1ab6356c6378f6f72830e6d2d5f1791df3774a7b097d18a6a1e \ - --hash=sha256:1617043b99bd33e5318ae18eb2919af09c71322ef1ca46566cdafc6e6712fb66 \ - --hash=sha256:1a4e45017efbf115032e4475ee876d525e0e36c742214fbe405332480ecd6275 \ - --hash=sha256:1b2fe7f9a5566401a0ef2571f197eb92358925c1f0c8dba305d6e43ea0871bb3 \ - --hash=sha256:1cc9057f0319e26333b357e17f3c2c022f1a83739b48a88b25bfd5fa2dc18838 \ - --hash=sha256:2392d954fcb920f42d230284b677605e4e2fbb11f2821e823e642abd67fbb491 \ - --hash=sha256:25ea65d868eb04015cd18e6df2fbe98f07e5bda2abefabcb88fce39a947716f6 \ - --hash=sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826 \ - --hash=sha256:2f16197705a230a78270cdd4ea8a1d57e86b2fdcbc34a1f6aebc72e65c986f9a \ - --hash=sha256:35405aecb474e683fb36af650618fd5340ee5471fc65a21b36076a18bbc6c981 \ - --hash=sha256:38be1808cdd068605b787e6ca9119b27eb275a0234e50212c3492331680c3b1e \ - --hash=sha256:3a577bd840ca83f646f0a625dbc571dba7044c43c2d1503afc378b570954345c \ - --hash=sha256:3b13dedfe76a0ad2d1d859b0811b53827a4e9d93a0bcb05cf59333ab4980cc7e \ - --hash=sha256:418e48ce50a45a6a6c73c454677203a9c75c966cb1e92ca3370959185f197a05 \ - --hash=sha256:55a3bc1e3df3b5567b7d27ef551b2283f0c68a5e86f1cd56abc569da4f31335b \ - --hash=sha256:6165461f55ef6314f026de6638d661188e3455d3ec49834556a0ebbdbace18bb \ - --hash=sha256:61a3d7eaa97a14768b542f3d284dc6400dd2470d9f080708b13cd46b6ae18136 \ - --hash=sha256:6233c9ed9ab9d1db47de57d9753256d9dcffbf42db341576099f0fd9f6bf4810 \ - --hash=sha256:641f795b361874ac9da5294f8f443dfdbee355cf2bd9e3b8d97aaac2306b9b37 \ - --hash=sha256:644a246325b8c69c595ad1dd4b463eba4b0cdb731370e4a86137d433208d6147 \ - --hash=sha256:6f066b179d68c413374294bc1735f68475457c933258df594443bb9d88ddc2a0 \ - --hash=sha256:7986f1fa71cee060ad00758bcc79d3a93bab8559bf978fab9e53472a2e25a17b \ - --hash=sha256:7c2b98645d576a0b9616892ead22b64a83a5f043c5e2ca15ebcefcb5b70c80cb \ - --hash=sha256:806f24b4085453c197a5078218d1ee08783ebbba271badd153d1ae22a3ee804f \ - --hash=sha256:85fe721a14dd823aca09127acbb06c3ca723efbd436c004f16bca601b04dcc83 \ - --hash=sha256:8adc8e6ce5fccf5dc707046ae4914fd537def529709cc0d285d37a7f9cd442ca \ - --hash=sha256:9700ebd9a51f5895ce75ff4ac4b3c47a7d4b42bc618be8e713e5d56bacf5f931 \ - --hash=sha256:9b18371ad2f44044b81a8d23bc2d8a9b6a6226dca775e8e16cfee640473d6c5d \ - --hash=sha256:a964266397740257f16f7bb2e4f08a0c81454004beab8ff59dd531b73610e9f2 \ - --hash=sha256:adbbedc55506cbdabb830890444fb856bfb0060c46c6f8026c6c2f2cf86ae795 \ - --hash=sha256:ae8a1145af31d903fa9bb166824d7abe9b4681a000b0159c9fb99c11bc11ad26 \ - --hash=sha256:b0e131f880cda8d04e076cee175a46fc0e8bc8b65c99c6c09dff6669335fde74 \ - --hash=sha256:b196eb3f931862af3fa84c2a253514d859c08e0d8fe020e07be12e75a5a9780c \ - --hash=sha256:b7d9a514e73bc42711e6a35aaccf3587c520024fe0a25d830a1a8a27c15f4f57 \ - --hash=sha256:bec9373df11544592b0ba7ec2af0e35059e5f0e7647c6183a854dedd193298f1 \ - --hash=sha256:c42ab9439498270139cc63e18847a02afe5c8b3ed9c931266533cfe378bd3591 \ - --hash=sha256:c91d00057f23b8d353039520dc3a6c09d8608164c692e9f59a175a42b2ae0c19 \ - --hash=sha256:d3e0b61e8efb24ed38898e5cdc5fffa9124be480008d401a1f8071500494ae42 \ - --hash=sha256:d7027eba1df3b2069e2e8d80f644fa0918b68c46432af3d088ddd390d063ecde \ - --hash=sha256:d8ddd2768da81d3ee08cfea9b597f4abb4e8e1dc8ae7e204b608d23a0d3ab699 \ - --hash=sha256:e3268e43984d0b1a185c89b4cfff282a7ead12fc93f56cfd7088bdbcbe727041 \ - --hash=sha256:e4505fc6583f7b05ab854934896bcac8253b04ac1171a77dfb73efef92076d91 \ - --hash=sha256:e56a1ffe9bf7b727432b89104cc0849c21582949dd7bdcb34f17b2001a351a76 \ - --hash=sha256:e6f1278ee4785b6db21229374a1c9e54ec7c549de5d1efc9630b6207de7e170b \ - --hash=sha256:f7616236ec1bc2b15bfdec22a71ab38851c86f8f05ff64f379e1278cf20c634a \ - --hash=sha256:fb24ac194bfc5e86839d7dcd52092ee31e5fe6733fe11f5e3b06ef0812b20072 - # via streamlit pycparser==3.0 \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 # via cffi -pydeck==0.9.3 \ - --hash=sha256:695775cbfe51f5fdffbd9735ba469987fdc5efc96bc40a0ee4808170509c78b2 \ - --hash=sha256:d8a47c11c81fb12d51b1feb42427ff4f0e13cb599e48931021b2cba98b6849a6 - # via streamlit -python-dateutil==2.9.0.post0 \ - --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ - --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 - # via pandas python-multipart==0.0.32 \ --hash=sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e \ --hash=sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23 - # via - # -r requirements.txt - # streamlit -referencing==0.37.0 \ - --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ - --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 - # via - # jsonschema - # jsonschema-specifications -requests==2.34.2 \ - --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ - --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed - # via streamlit -rpds-py==2026.5.1 \ - --hash=sha256:01d17b29c0c23d82b1f4751147ec49cf451f1fc2554eb9ef5f957e55d2656ead \ - --hash=sha256:036a36a87fb1cd3b214d11c4b3c4f7d2ddad933625dca1c900b56a057c07740a \ - --hash=sha256:0408a24e44feb919423dc6d9da677cb5cddb894d2ca9e763967d156d9c60fab4 \ - --hash=sha256:07b24fea40541e28570e5b795a4a38fbdcd12550c06bd0748005ecc8116ca256 \ - --hash=sha256:0957cf3c2b8632ec7aaebffebea8005b353cc2a237b6e2ae3c2cac0820704cfb \ - --hash=sha256:0a5ae4dbe43c1076983b72616496919872ae7bbe7a1e21cc48336bc3154d130b \ - --hash=sha256:0a7d1eec967df0e9b22614a5e177622e0c89611d03727fa0cb48e45028907870 \ - --hash=sha256:0b35217adefe87f2fe4db7e9766cabe84744bfe9616d9667be18988928c7f2dc \ - --hash=sha256:0fa92420128dadce7f54bd73ba1825a273e9268fe9e35dbf7e6362890efa4e08 \ - --hash=sha256:141c9498daf2ace9eda35d2b0e376f9ea8b058d84f2aef4f96fccfd449a2f251 \ - --hash=sha256:1841d067089e117142d79b98aa0df2f08b52f2ecc1819dd2700636c0db74a473 \ - --hash=sha256:19cb09fab7b7fc96b2a6e28f2e34b72a3705ff27b37edb77455316e5d3f3dc9b \ - --hash=sha256:1c27c5f6102eac8c03e7595a00827a53b271ba40a53b59ff8709170e0855ea4a \ - --hash=sha256:1ebb2f0ab7e16132995a72de805170e0203df0c3dd22e1ef1cd1fdd90bd7a131 \ - --hash=sha256:1f2c391c3059798093b65df23aca2cac150460ae9c630d99dec83d703d9485b9 \ - --hash=sha256:205dde846f24332ab0c1188699a043b8d165b79bb84529ce272c45048ff6be01 \ - --hash=sha256:21846aac0ed2e0589f38c12dc44e77bb64e494b771eadbcf169cba00566ba7ba \ - --hash=sha256:21942f52dbbd5f8758bf021213d28bd45c39e873e65e2407faf5f1846f5761ad \ - --hash=sha256:277f6c82f0580848796c7ecc8a7173aa3bfb928e4ff831261c2f60a81dc270db \ - --hash=sha256:27b74c10ed6a8f190f4287f53bcfea348b92a84a9c9f70d30183d1e6172d580d \ - --hash=sha256:296c799becfa849c779c8725494fe9ed94959ed886787df4364b058465bad7f0 \ - --hash=sha256:2c595a1d9255dce0599e13130d1440ab2506654f2b50294226ee06402f8fef63 \ - --hash=sha256:2c817a189d4ee14290420e5ff051e4dd6baa13f3edf84685071dee07a6d538ee \ - --hash=sha256:2d88621d6a7d4dfa633d21abe90f280bb205274e16b1d1e61c6ad4640b2453b7 \ - --hash=sha256:3350ec808fb538fe71a1f94dfaa0e29c598dfad805ce49f0caec5ae3183c652b \ - --hash=sha256:3397a5ed7174dc2786bb214030232fc36fe8e5584fec43a9952cc542b1a12036 \ - --hash=sha256:3574b55c604b8f75dacb007136508bbc0db406e626301778096a133327e7f2fb \ - --hash=sha256:3609e9939a8a76cd904cf98a3f1f13b5dc7e150adeaee89e0ea09652ea213e16 \ - --hash=sha256:3684a59b158a7683aaeb8e25352e9a9dd2122cec78f2d8530266e4f91b4c7b3f \ - --hash=sha256:3966b82dd563176396df030f3dd52a6e54cb69b718e95e78bd555ed3d1e0185d \ - --hash=sha256:3abe24a66e57adcfa645d718063a5fa5103ecc71ddbf26d78af8f9368018ff1d \ - --hash=sha256:40ff257542e04796880e011e15cd4dc21c2599975df2aaa8f2c8495ca574e1a5 \ - --hash=sha256:413b424f7c4ee65ab5e5be91f5731be0f8b41a1ee2b12dfe810d716312e95a78 \ - --hash=sha256:42d0f20e85e549c870749d0e247f0c10d318a45b7e9676d575d2dcb04a1b2e66 \ - --hash=sha256:43bca78665423cabae77146f2fe7ce55272b6c8d55d82cca83effd42c7e13972 \ - --hash=sha256:453895624ecf7db7063b1004e44037522bbaef9ff6a945e59bc71662d7a03abd \ - --hash=sha256:4860b603ddda0475a8885499b3729e90229d480105b42651962a5397d995fa89 \ - --hash=sha256:4be8b1d2a705cc37d08256004e1d07de143fa0075c8e85a3df020b776f62b732 \ - --hash=sha256:4e237e139f94d3c036fd28eb9f564c99055476ff4ff05cd42be55ce349b5aa02 \ - --hash=sha256:4fb8d2e7cb2f850b169806d61d1b991738acec96500a75c30f49caf064ce7cef \ - --hash=sha256:55d8f9b7b78c9538fc9e04e82ec0e888ff0c3cffcfad152c77e57cd09351a98a \ - --hash=sha256:58b1d94308ddf0b1982f61f2eb54bf92997c9ece8a8093ef014250f4a517906c \ - --hash=sha256:5d333a7127d4b307601ac37792bee01bb95c867cbfacf21b6375b804d6bbd723 \ - --hash=sha256:613fc4ee9eaef26dc5840666214dd6fbcebcf32f46e76f4abc473059f4e13dda \ - --hash=sha256:6142dbd80c4df62a5d899f0d616d417f84e0bc8d32526c8e5589019d75d028a7 \ - --hash=sha256:62ae3853454fe9ef283a03c96c2d835d39e84b14643a9d62c82ef0fb87d702ca \ - --hash=sha256:63c2c4c213f1a4e3f3de28ecab029dbdee976324e729c0d7a55211be72576b02 \ - --hash=sha256:656a042550878f12d45752452d47094b7cfe5ad1e9d7b87b5a22ad3ae5ff8015 \ - --hash=sha256:66c93681c4729e4e3ecba31b8179fae083ff3118841672835140338b4b9867c1 \ - --hash=sha256:6736718bd4fc49cbcb538ba30516fdbef161522acefb739657d48b97bd864fed \ - --hash=sha256:68700371c5d7ae1412862ddfa719090925c93ecf351c566d66f09d04b136ea00 \ - --hash=sha256:6c3d771a46ec18b12af06ce36243a9a80b07a5d0515236332d90863ca8bb326a \ - --hash=sha256:6c7fcf61d44cacecaf3aea542b0e053db77972a4573e7ceda16fb2b399161195 \ - --hash=sha256:6f249f8b860a200ad35193af961183ebe9132710484e6f6ce0cf89fd83c63a9a \ - --hash=sha256:73c4bd4f70294737b5206a3e8e30ccadbf8a60301831c8ea23eec5dbeea1ecfa \ - --hash=sha256:7559f72b94ae52659086c595dfa017cde03155f7832071d30959049052cb3ece \ - --hash=sha256:75808f6c38ce7749bb68cc2770161aae5045e6c6f6781a9782e74b93304399df \ - --hash=sha256:77c004fdc7b891967106f78ddfd7b076bfe6813c6139c6fff6aed3bcaa960b26 \ - --hash=sha256:7818f8d0a415be74d2be3590b0a1c1f463a642f4d0217e7d10602dceef5b79aa \ - --hash=sha256:7944270ae71383f6e2657dd7d5ce4eeb4ac2d0059a6738f0510583d462ab4842 \ - --hash=sha256:7bd530e6a530bb3ea892f194fafa455f3516ac25ecf7143fd33c09be62b0470a \ - --hash=sha256:8213afbe8a3a906fb9acb2014423fe3359ee783d0bf90995f70623a3217bfa6c \ - --hash=sha256:83bcf894486c9d78dd290d3c0124ff6dd8875d3025e2090a8ec49fcc37c55fdd \ - --hash=sha256:85264a90ff4c05c1568dd65f5921c837614b67c60358fb4c17df3b7f2e90690a \ - --hash=sha256:88647f43a73c4e01be19b04ceef0c8d3a1958153604d13c773becd8016f2a0cf \ - --hash=sha256:8895840ac4809e5f60c88fd07617cd71326e73d6e5a8aa783c5c0f7c24985de2 \ - --hash=sha256:8ba264fa49be666cd9cc56bf34ec7002fb3d27a4aee5bcb4d43d0d18feb1bb6f \ - --hash=sha256:8bff7073db3899158fff55ebf57b113a67030af26f80a18978f9f0aa60250ddf \ - --hash=sha256:8c43a8a973270fd173bf48cdf80bbe66312421cba68d40845034f174f2389049 \ - --hash=sha256:90bd6630002a1c7f09e7843dd79f0d24f3d2897cc25a753480917865d14f15b3 \ - --hash=sha256:90f628283be835db980c941767d41c9a27b5239e54ba0a9c1335247e82406964 \ - --hash=sha256:94068eb3ae6d43f5a786b7db96a406a34e6d5c24489feef32fd6e8946ea7b291 \ - --hash=sha256:980450826cf22e133c57e0835070bdd0dd3f73b9b708c3ce223def2cb9469e14 \ - --hash=sha256:99ab6ba7bfa2cb0f96a04e3652355bf04e3f51aceb1e943b8541dab7ba4828cc \ - --hash=sha256:9af8905b8f854990e40d5206aa5ac58d9b0fe0b7f351ff2bb086c20f6c8c6a47 \ - --hash=sha256:9baffb505aff33acc69b422a19f77806680f3c8632227d79f48de8a810d1c2c5 \ - --hash=sha256:9cdddb6c1207d284d94fd1530adf57fbd797fe7c4b8704ba85f49414f2557e7d \ - --hash=sha256:9e25b7088f9ccbfc0dfcaa52bf969300ca229e10ecf758974ebcbb080a4b37bb \ - --hash=sha256:a04df86b3f0fade39ec8fd0e0aab089b1da9fbd2b48df778a57ef96f5e7d38df \ - --hash=sha256:a05fa4f41f37ec97c9c260441a940450a192f78d774d2b097eee1379f1e1246a \ - --hash=sha256:a2999883eedf72fdfb7520b92c7d4ec2572a71ff40239377aa604cc529eecafc \ - --hash=sha256:aad1bff7f666b9598e573815affd666aac6a13a585dde336f843e33350c7fadc \ - --hash=sha256:abe76bcdba31e576cb83eeb8797aa0d882b738fef6dc65d0601fc753806a5b46 \ - --hash=sha256:ad3773236e95f7f33991eb125224b7da66f206504d032a253a02da7e134519fb \ - --hash=sha256:af03e34e860047bc7a352b842856fcf78798fbb81132cc98bd2f907ab4eb9cd2 \ - --hash=sha256:b1b964e3ab599e718dc46c018d104b1ebc007cbc6567d827c94a687fca56d77e \ - --hash=sha256:b1be5c35683684d5331b93600c210e8367c254683d8a6df6bd21bd2da3a334fb \ - --hash=sha256:b317c87a13f769a4e787819bd508aaa5d69aa09b0880de9af6d3a8a54571cdec \ - --hash=sha256:b3cc20c0d800af78fd0fac68086e28c1856cec51ea528bb81ea851aa40d39325 \ - --hash=sha256:b4e4bc98639ec915f512fde3aa7a95e0041d95d9c3cc86eea841fa63cb1e8600 \ - --hash=sha256:b5c30f3f04eef4fbd362226a6f31d7c8895ca4fbb6e0b790f6890a98d8da8559 \ - --hash=sha256:b5f077b44a4f7808520f66dae234988d867deb9aed9be5da057ce9ba831b2a41 \ - --hash=sha256:b6825cc329b290e93c5f6a9be2393118a763f6ccf6abd83704e0c102ca583644 \ - --hash=sha256:b8d2f912928d426e8cfa396f7f3f8d29a59e6689c86dcca3c420730c1096322b \ - --hash=sha256:b95d5e11fc712b752081183a55a244c03cd00570489edd7014d8899f8ceb8162 \ - --hash=sha256:b9a6528956191c48c52294a592dbd4a8386d7048bdb25c0efcb6b966466c6d83 \ - --hash=sha256:ba05adbf15d994c38ec0b7ab32e858e5110c21e9009a00a86545fd220f84e038 \ - --hash=sha256:c0f920015df2a504bebaba6d4c31ccf3fcf942f92655c086da30b671aad19aa6 \ - --hash=sha256:c396c1304de421050b3681ea70f371874b54d41b0151e96109758144c231e30b \ - --hash=sha256:c39f5b67a8a2e67179ada2a954227d670fe65fa9098457f698f56ddf248709b3 \ - --hash=sha256:c3df104083952a0e0c6f10de33e440eabe98fb6317d23e1a58c68f6df08d01b9 \ - --hash=sha256:c74005a7bb87752acf351c93897ec63ad77a07a0da7ecad9c050e32e7286ba34 \ - --hash=sha256:c93c629be4636cf54337bd5f06c104d55e42ced54d681f6fe21ae510a65116f6 \ - --hash=sha256:ca653c6546386227cd9800d1bef6a348099acf8db4250341da6d90f663d6dfcb \ - --hash=sha256:cacedb7a6e167680acba45ad5716e89067d225dc80da0d7040cae8c81d4572fa \ - --hash=sha256:cc68e231a77a5f0d774ae278a1f8e55c0456501820847c1e4efb3829f3441df6 \ - --hash=sha256:ce87129d9f2c14fa6c4a8601fb80eb4488c80d38a20cd13758ef11123e14995d \ - --hash=sha256:cea68bcd53467561ae2f96a6bdad1544299ba97b5b0ddcd5ac3d376e5c781c24 \ - --hash=sha256:cef8ac28d26f4dda3533060c20fbf80a325458fa9fd23ea72a73cdfa8e978838 \ - --hash=sha256:d0efbe45632665e53e3db8fe1e5692db58fc5cb9bab4459d570b83efefe11164 \ - --hash=sha256:d3858b908218ee108d0bbfb2095ccc237648053c9bf98affad7cb079acaf1d97 \ - --hash=sha256:de42116e69cb53b911cc34aee5ab98f36c597b822545045d49e938818b99e5e4 \ - --hash=sha256:df1d2a1996755b24b9ecee92cb4d36c28f86f464a6a173349c26bab41e94b8c2 \ - --hash=sha256:e07be2a9d7122bd6e82dea89814ef8dc893feb1aae97fec1630f3263bbb30e55 \ - --hash=sha256:e0b360f316d966b048b085857630b3cc51f3db2f07b06f440eac8f695374d1e3 \ - --hash=sha256:e10464d17df3b582745c25cec695cb9558bca2cb6ddb631aee1787fc72c767b2 \ - --hash=sha256:e3a8ae58895ac107ed934a6bf51e5846f95c53b9b940c2c6d310838fd5846358 \ - --hash=sha256:e4abbf391a70be864920858bf360f4fb380577c9a0f732438a1996726e2c195b \ - --hash=sha256:eaaea962c68cdc68d4a533ba985ab8e9484277910bbfaa2ab3ef7732667bfed8 \ - --hash=sha256:ed0954b524873214369184a9c82b0eaa45a3fbb9a798cd95b17e0d98499e7ea0 \ - --hash=sha256:edf2765d84e42447f112ad877af8fe1db0089aaec5b28e88d6eab45e7fe99cea \ - --hash=sha256:ef1013a8625c74043210190b246f5b1551e09757c1f356c6e4160ef96c5bc081 \ - --hash=sha256:efef4ac29c6ff495531eb17ee705b62841ecaa291b7c7077e848ea03e237164d \ - --hash=sha256:f3a5b10e8ce894825f380a8f1b6444cf73c294dfea62afbb2d13e3a9e630cec1 \ - --hash=sha256:f3df3d16ded76f1f8c9cdebd0e1ea55fdf4c23b812de189814da7cf229c22a81 \ - --hash=sha256:f414556f6e3958300ff941e40c9f97e3dc9774ddd1b3434c475d73dd354bbed3 \ - --hash=sha256:fc09f82e63d4bcd58149572f857a431bae851dc747e313c3b5bdf7abb907fda8 \ - --hash=sha256:fc0c0f878ea770a0a8a462456c5ad36fc9fe6358e6b76fdadc7f17575e0b8bf1 \ - --hash=sha256:fe71bca7d547acb17027c7fd1624ff8aae623499c498d3e7011182c4de5c25e0 \ - --hash=sha256:fea6e836d10abbe191d557d33bd58bd5987725fe63aa1eefe557d230209855bd - # via - # jsonschema - # referencing -six==1.17.0 \ - --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ - --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 - # via python-dateutil -smmap==5.0.3 \ - --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ - --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f - # via gitdb + # via -r requirements.txt starlette==1.3.1 \ --hash=sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0 \ --hash=sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6 - # via - # -r requirements.txt - # streamlit -streamlit==1.59.2 \ - --hash=sha256:5014cb4f0064bd16c58fe334cb0d3c4b7e2be3d1ce4c02202c07114a33576dab \ - --hash=sha256:8fcb35df152868d33eec7ad2d89e276499a5351fb861eb1752b76476be7eb582 # via -r requirements.txt -tenacity==9.1.4 \ - --hash=sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55 \ - --hash=sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a - # via streamlit -toml==0.10.2 \ - --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ - --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f - # via streamlit -typing-extensions==4.16.0 \ - --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ - --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 - # via - # altair - # streamlit -urllib3==2.7.0 \ - --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ - --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 - # via requests uvicorn==0.51.0 \ --hash=sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b \ --hash=sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0 - # via - # -r requirements.txt - # streamlit -watchdog==6.0.0 \ - --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ - --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ - --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ - --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ - --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ - --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ - --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ - --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ - --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ - --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ - --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ - --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ - --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ - --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ - --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ - --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ - --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ - --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ - --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ - --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ - --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ - --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ - --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ - --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ - --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ - --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ - --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ - --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ - --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ - --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 # via -r requirements.txt -websockets==16.1.1 \ - --hash=sha256:01fbdcbac298efe19360b94bc0039c8f746f0220ba570f327577bfee81059175 \ - --hash=sha256:024193f8551a2b0eafbdd160911012c4e6c228c28430c84433253299a9e42d6a \ - --hash=sha256:04fd29a0e2fe9414a95b00e92c67ae51bf900c50c0f8a4b2dafdad621f49ea1d \ - --hash=sha256:056ae37939ed7e9974f364f5864e76e49182622d8f9751ac1903c0d09b013985 \ - --hash=sha256:0f62863e8a00a6d33c3d6566ec0b89f23787b747ffe0c3bc71ec0e76b82c94b1 \ - --hash=sha256:0ffd3031ea8bda8d61762e84220186105ba3b748b3c8da2ae4f7816fac03e573 \ - --hash=sha256:1214e673c404684b9bf7154f5cf43b45025b1a6160fac3a9e438e9c1a97e22cb \ - --hash=sha256:125f22dbefaf1554fea66fc83851490edb284ce4f501d37ffed2752f418332d9 \ - --hash=sha256:130937b167a52af203c8d58e78d67705874e82759862e3b9671a452fec4abc87 \ - --hash=sha256:1427fb4cf0d72f66333e2cacc3ff5f575bf2d7008166ce991a4a470b21d51a22 \ - --hash=sha256:195c978b065fa40910582464f99d6b15c8b314c68e0546549a55ed83f4735328 \ - --hash=sha256:1d27fa8462ad6a1cb36206a3d0640b2333340def181fae11ed7f9adeaa5c0747 \ - --hash=sha256:1db4de4a0e95673f7545d393c49eeb0c2f18ac1ef93073218c79d5cdb2ee75ab \ - --hash=sha256:1f79c89b5eb034d1722938a891916582f8f7f503f58ca22518a63c3f2cd18499 \ - --hash=sha256:23253dd5bcae3f9aaee0a1d30967a8dbd52e5d3cff93a2e5b84df57b77d4750d \ - --hash=sha256:249116b4a76063d930a46391ad56e135c286e4562a18309029fc2c73f4ed4c62 \ - --hash=sha256:29dfa8114c4a620c69591c5973860f768eac29d3fd6904f37f34266cb219c512 \ - --hash=sha256:2a606d9c24035242a3e256e9d5b77ed9cd6bccfcb7cf993e5ca3c0f6f68fb6a7 \ - --hash=sha256:2a636ff1e7a5c4edf71ef0e79adae7f25dba93b4fcbe3dc958733477ffeb0eaf \ - --hash=sha256:2bb5d041a8307d2e18782e7ce777f6fdb1e8c2f5d09291484b18c294b789d9aa \ - --hash=sha256:2e28e602bb13da44fbe518c1781a88e3b9d4c3d48d02c9bad83e546164336f57 \ - --hash=sha256:30bbe120437b5648a77d3519b7024ea09530e0b5b18d3698c5a0ae536fe0cc2e \ - --hash=sha256:34420aaa64440ebd51ac72ca8a45ef4626429438c9b02e633ae412ed43f925d3 \ - --hash=sha256:38565aca3e01ea8734e578fb2118dade0ecb0250533f29e22b8d1a7a196cf4d0 \ - --hash=sha256:387e8e4aa5df2f90b198fa3cad3478822a89cf905b6a6d6c97dc3664689640cc \ - --hash=sha256:39f2a024af5c345ffe8fcf1ee18c049c024c94df393bb09b044a6917c77bde43 \ - --hash=sha256:3df13f73af9b3b38ab1195eb299ecb67a4330c911c97ae04043ff74085728abe \ - --hash=sha256:414e596c75f74e0994084694189d7dc9229fb278e33064d6784b73ffbba3ca31 \ - --hash=sha256:41c8e77f17294c0ac18008a7309b99b34ee72247ef10b6dff4c3f8b5ac29896b \ - --hash=sha256:42290eb6db4ccaca7012656738214f8514082fb6fa40cdeb61bb9a471b52e383 \ - --hash=sha256:42f599f4d48c7e1a3338fdaac3acd075be3b3cf02d4b274f3bf2767aedd3d217 \ - --hash=sha256:43e3a9fdd7cbf7ba6040c31fae0faf84ca1474fef777c4e37912f1540f854499 \ - --hash=sha256:443aefe96b7fdb132e2a70806cca1f2af49bb3f28e47abcd7c2e9dcf4d8fa1b8 \ - --hash=sha256:46dcaa042cd1de6c59e7d9269fa63ff7572b6df40510600b678f0826b3c7af51 \ - --hash=sha256:496af849a472b531f758dbd4d61338f5000538cb1a7b3d20d9d32a264517f509 \ - --hash=sha256:49ae99bdfcae803a885c926bf14f886196e84925395bb3f568fef5c0f0979d7d \ - --hash=sha256:4b57693728576d84ede0a77987ab16881b783d2cd9f1dc180a8fbbc3f79c4428 \ - --hash=sha256:4e3b680b1e0a27457e727a0d572fd81dffa87b6dbf8b228ab57da64f7d85aead \ - --hash=sha256:4e8d01cc3bcae7bbf8167f944aeafefed590fae5693552bba9794a9df68371cc \ - --hash=sha256:5283810d2646741a0d8da2aa733d6aefa0545809afccb2a5d105a26bc45125f1 \ - --hash=sha256:53260c8930da5771cec89439bff99c20c8cb03ddb9588b980697355a83cd4bd3 \ - --hash=sha256:536676848fc5961aca9d20389951f59169508f765637a172403dc5434d722fa0 \ - --hash=sha256:54509b8e92fee4453e152b7558ddef37ce9705a044922f2095a6105e3f80c96f \ - --hash=sha256:56cd5fc4f10a9ea8aa0804bddb7b42506cf9e136046f3b4c27de8fec9e2ecba5 \ - --hash=sha256:5bfd1ac19b1b9986a9c95a82d5e23a391ebb09e12c34d7be6094b86efcc35731 \ - --hash=sha256:5c31aa7e39ee3e8a358573257f1c0bb5c52430d1b637030dd9c8cc2c282926be \ - --hash=sha256:5e3b7d601f6f84156b08cc4a5e541c2b50ad7b36cfc302b657a12477c904a5df \ - --hash=sha256:61922544a0587a13fd3f53e4c0e5e606510c7b0d9d22c8444e5fae22a06b38cb \ - --hash=sha256:6456ff333092d509127d75a638cb411afae8ff17f092635015d1902efec8a293 \ - --hash=sha256:69159730a823dde3ea8d08783e8d47ef135a6d7e8d44eb127e32b321c9db8e3e \ - --hash=sha256:69e52d175a0a7d1e13b4b67ad41c560b7d98e8c6f6126eb0bda496c784faf8c7 \ - --hash=sha256:6aaface73b9c71974c6497366d8b9628357f6c9749e09c4ea3610176c63f2ae3 \ - --hash=sha256:6abbd3e82c731c8e531714466acd5d87b5e88ac3243465337ba71d68e23ae7e3 \ - --hash=sha256:6ff9417c0ada4d0f7d212f928303e5579bdf3ace4c802fa4afabb30995da58c3 \ - --hash=sha256:7421fad442de870a8cbf2287d1cad7e706ece0dbfeba5e911df132cbdc1cb56a \ - --hash=sha256:7883388947767080f094950b342b30d35a2a06b849cd967c422fa0db72b40ea9 \ - --hash=sha256:79eace538c6a97e96d0d03d4f9d314f9677f5ed85a8a984992ffd90b13cb8a56 \ - --hash=sha256:7b1b19636af86a3c7995d4d028dbe376f39b4bf31541146f9c123582a6c94562 \ - --hash=sha256:7dfcad78ea1492ee3a9ec765cb7f51bbc17d477107aaf6b22abf7b2558d1c5a0 \ - --hash=sha256:8087e82f842609734c9b5a1330464f8e94e346ba0e18c832c08bafa4b0d63c15 \ - --hash=sha256:820fb8450edddae3812fd58cbc08e2bf22812cb248ecb5f06dbb82119a56e869 \ - --hash=sha256:8483c2096363120eea8b07c06ae7304d520f686665fffd4811fad423930a65d7 \ - --hash=sha256:84a2cef8deffbd9ab8ee0ea546a2a6a7030c28f44e6cdd4547dbfeb489eb8999 \ - --hash=sha256:86d7f0f8bdb25d2c632b72527325e4776430fd5bc61b9118de4e2b8ddb5f5b01 \ - --hash=sha256:8fe0b50da2d84535fb4f7b4bfa951280f97ce3d558a0443b541166d609e67b57 \ - --hash=sha256:90001d893bc368e302ef168d82130b4e4fdd27b85fa094682df9b667c2d48838 \ - --hash=sha256:9246a0d063cfcbcc85f2359dd6876d681213f4790832272aa16641b4ed5d64d4 \ - --hash=sha256:92b820d345f7a3fc7b8163949ee92df910f290c3fc517b3d5301c78065adafe1 \ - --hash=sha256:952303a7318d4cbe1011400839bb2051c9f84fa0a35923267f5daba34b15d458 \ - --hash=sha256:97fd3a0e8b53efa41970ac1dff3d8cf0d2884cadeb4caaf95db7ad1526926ee3 \ - --hash=sha256:9c1c5705e314449e3308872fe084b8571ce078ee4fc55a98a769bdefe5917392 \ - --hash=sha256:9c9f23004a3d40e89c01a7955d186a6cc83418d93b749701944ce2de3e95a1f3 \ - --hash=sha256:9f63bcef7f4b02b06b35fc01c93b96c43b5e88e1e8868676caacf493d5a31f3a \ - --hash=sha256:a0eadbbf2c30f01efa58e1f110eb6fa293261f6b0b1aa38f7f48707107690af9 \ - --hash=sha256:a28fcbc9b6baf54a2e23f8655f308e4ccc6afdd7266f8fe7954f320dcda0f785 \ - --hash=sha256:a6a61aff018180c9c50b7b0da33bfd29d378af3497429c95006c589a23a11648 \ - --hash=sha256:aabe464bfd13bd25f4821faf111da6fefdc389f870265a53105580e45b0a2e49 \ - --hash=sha256:ab59169ace05dcb49a1d4118f0bde139557adf45091bd85747e36bf5de984dd1 \ - --hash=sha256:b436f6ec4fc3a6b4237c84d3f83170ed2b40bb584222f0ac47a0c8a5921980c7 \ - --hash=sha256:b6b9dadbef0cccd9f4c4ee96b08898afa73e26803bbe0f6aeb5bb12b0074206d \ - --hash=sha256:b852788aa51764e2d8e4cf5493d559326bcae5e38d16ba25ffa322b034df272a \ - --hash=sha256:bae954c382e013d5ea5b190d2830526bfa45ad121c326da0049b8c769f185db6 \ - --hash=sha256:bcce07e23e5769375158f5efdcdafa8d5cd014b93c6683865b840ed65b96f231 \ - --hash=sha256:cc97814dfb786a83b6e2dc2e79351e1b83e6d715647d6887fcabd83026417a00 \ - --hash=sha256:cd2ca96a082a36964aca83e992f72abeb61b7306c1a6cba4c7d06a7b93750cac \ - --hash=sha256:cfb70b4eb56cac4da0a83588f3ad50d46beb0690391082f3d4e2d488c70b68ea \ - --hash=sha256:d0fcf657e9f13ff4b177960ab2200237b12994232dfb6df16f1cfe1d4339f93c \ - --hash=sha256:d14bfb217eb4701e850f1525c9d29d79c44794cdf1c299ead25f39f8c78dea81 \ - --hash=sha256:d57685547e0060cc6fd90ee6a28405d6bd395e525545f13c8d7cd99c78afd79f \ - --hash=sha256:d6bec75c290fe484a8ba4cacdf838501e17c06ecfbbf31eede81a9e431bd7751 \ - --hash=sha256:d9531d9cbeac99af6f038fb1bc351403531f7d634a2c2e10e2f7c854c6ed5b68 \ - --hash=sha256:da4ca1a9d72f9030b3146b8d7022719a9f3d478f61efe6f7dd51d243f61c51b2 \ - --hash=sha256:dab9eb87869da2d6ed3af3f3adf28414baae6ec9d4df355ffc18889132f3436c \ - --hash=sha256:db234eda965dcce15df96bb9709f587cd87d4d52aaf0e80e2f34ec04c7670c57 \ - --hash=sha256:dc0fad4933f427acd5b1cec210f3ea6dce7089e1724e4b9ec6ef47c6c04d1b3b \ - --hash=sha256:dc385593a42e31cd6fb60c19f0ecb015b386603818fc2c6c274fb42bd2bb4165 \ - --hash=sha256:dcc04fedf83effaeb9cce98abc9469bb1b42ef85f03e01c8c1f4438ef7555737 \ - --hash=sha256:e047dc87ef7ca50f4d309bf775ad4a71711c58556d75d7bd0604b2317f43e94b \ - --hash=sha256:e09f753a169951eb4f28c2c774f71069304f66e7277e0f5a2892423599cfa854 \ - --hash=sha256:ed5bb271084b46530ee2ddc0410537a9961152c5ccba2fc98c5276d992ccba87 \ - --hash=sha256:f0aa4aad3b1b69ad3fd85a0fd0952ec64331c762bd77ec51cc814170873890b2 \ - --hash=sha256:f17dbe07eb3ea7f99e4df9b7e0efefe80fbf30d37a8cc4d561a0aed310bc8847 \ - --hash=sha256:f2769a0344a09e9ccf5b3cce538bc75a51b53eff3275d3896310c8552049195d \ - --hash=sha256:f55f0b01956a094c8587146d9558c91937e78789c333860ffaf35931a6e5dbc4 \ - --hash=sha256:f5d497865f05bb222cab7016c6034542e84e5f29f49c6fd3f4939cda7197b5b8 \ - --hash=sha256:f70541f3104339f59f830522d94ebadb1bf47426287381623443d8bb1cdbf33d \ - --hash=sha256:fb9a0a6dc3d1b3986cb88091b6899f0396651e0f74e2c9766ab8d6ffc3842e29 \ - --hash=sha256:fce6c48559c86d1ac3632ccb1bebc7d5442fbe79bd9bb0e40379ee54be2a4051 \ - --hash=sha256:fd46fff7eb62c24804d234f0051c7a8ea81285ad63e0337d3dcf33ca82aee58a - # via streamlit diff --git a/requirements.txt b/requirements.txt index b088bce..2a6ac84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,8 @@ liboqs-python>=0.14.1,<1.0 cryptography>=42.0.0 -streamlit>=1.32.0 # Starlette <1.3.1 is affected by CVE-2026-54283. starlette>=1.3.1,<2 uvicorn>=0.49.0,<1 python-multipart>=0.0.32,<1 # Keep the locked runtime install portable on Ubuntu/Python 3.13. httptools>=0.8.0,<0.9 -# Streamlit pulls this on Linux; pin it explicitly so hashed locks stay portable. -watchdog>=2.1.5,<7 diff --git a/scripts/api_client.test.mjs b/scripts/api_client.test.mjs index 06afaa8..30af02e 100644 --- a/scripts/api_client.test.mjs +++ b/scripts/api_client.test.mjs @@ -1,22 +1,36 @@ import assert from "node:assert/strict"; -import { readFile } from "node:fs/promises"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; import test from "node:test"; +import { fileURLToPath, pathToFileURL } from "node:url"; import { transformWithOxc } from "vite"; let moduleSequence = 0; async function loadApiModule() { - const source = await readFile(new URL("../web/src/api.ts", import.meta.url), "utf8"); - const compiled = ( - await transformWithOxc(source, "api.ts", { + const tmpDirectory = new URL("../tmp/api-client-tests/", import.meta.url); + await mkdir(tmpDirectory, { recursive: true }); + + const contractsSource = await readFile(new URL("../web/src/api/contracts.ts", import.meta.url), "utf8"); + const contracts = ( + await transformWithOxc(contractsSource, "contracts.ts", { + lang: "ts", + sourcemap: false + }) + ).code; + await writeFile(new URL("contracts.mjs", tmpDirectory), contracts); + + const clientSource = await readFile(new URL("../web/src/api/client.ts", import.meta.url), "utf8"); + const client = ( + await transformWithOxc(clientSource.replace("./contracts", "./contracts.mjs"), "client.ts", { lang: "ts", sourcemap: false }) ).code; - const encoded = Buffer.from(compiled).toString("base64"); moduleSequence += 1; - return import(`data:text/javascript;base64,${encoded}#${moduleSequence}`); + const clientPath = new URL(`client-${moduleSequence}.mjs`, tmpDirectory); + await writeFile(clientPath, client); + return import(`${pathToFileURL(fileURLToPath(clientPath)).href}#${moduleSequence}`); } function healthPayload(apiToken) { @@ -24,6 +38,12 @@ function healthPayload(apiToken) { ok: true, backendReady: true, backendMessage: "Post-quantum backend ready.", + capabilities: { + inspect: { available: true, reason: "" }, + generate: { available: true, reason: "" }, + encrypt: { available: true, reason: "" }, + decrypt: { available: true, reason: "" } + }, formatVersion: 4, kem: "ML-KEM-768+X25519-v2", kemComponent: "ML-KEM-768", @@ -128,3 +148,43 @@ test("an unrelated authorization rejection is not retried", async (t) => { { url: "/api/keys/generate", token: "current-token" } ]); }); + +test("sensitive operation signals reach each state-changing fetch", async (t) => { + const originalFetch = globalThis.fetch; + t.after(() => { + globalThis.fetch = originalFetch; + }); + + const calls = []; + globalThis.fetch = async (input, init = {}) => { + const url = String(input); + calls.push({ url, signal: init.signal }); + if (url === "/api/health") return jsonResponse(healthPayload("current-token")); + if (url === "/api/keys/generate") return jsonResponse(generatedKeysPayload()); + if (url === "/api/files/encrypt" || url === "/api/files/decrypt") { + return new Response(new Blob([url]), { + status: 200, + headers: { "Content-Disposition": 'attachment; filename="result.bin"' } + }); + } + throw new Error(`Unexpected request: ${url}`); + }; + + const api = await loadApiModule(); + const controller = new AbortController(); + const file = new Blob(["file"]); + const key = new Blob(["key"]); + + await api.generateKeys("correct horse battery staple", controller.signal); + await api.encryptFile(file, key, "encrypted.pqc", controller.signal); + await api.decryptFile(file, key, "correct horse battery staple", "plain.txt", controller.signal); + + assert.deepEqual( + calls.filter(({ url }) => url !== "/api/health").map(({ url, signal }) => ({ url, signal })), + [ + { url: "/api/keys/generate", signal: controller.signal }, + { url: "/api/files/encrypt", signal: controller.signal }, + { url: "/api/files/decrypt", signal: controller.signal } + ] + ); +}); diff --git a/scripts/ui_native_smoke.mjs b/scripts/ui_native_smoke.mjs new file mode 100644 index 0000000..85db30e --- /dev/null +++ b/scripts/ui_native_smoke.mjs @@ -0,0 +1,111 @@ +import assert from "node:assert/strict"; +import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; + +import { chromium } from "playwright"; + +const baseUrl = process.env.UI_NATIVE_URL ?? "http://127.0.0.1:4000/"; +const password = "correct horse battery staple"; +const inputBytes = Buffer.from("native browser round trip"); + +function assertReadyHealth(health) { + const requiredCapabilities = ["generate", "encrypt", "decrypt"]; + const isReady = Boolean( + health?.ok && + health.backendReady && + requiredCapabilities.every((capability) => health.capabilities?.[capability]?.available) + ); + + assert.equal(isReady, true, "The native local engine is not ready for key generation, encryption, and decryption."); +} + +async function saveDownload(download, destination) { + await download.saveAs(destination); + return destination; +} + +async function downloadFromButton(page, name, destination) { + const downloadPromise = page.waitForEvent("download"); + await page.getByRole("button", { name }).click(); + return saveDownload(await downloadPromise, destination); +} + +async function run() { + let temporaryDirectory; + let browser; + + try { + temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), "quantum-encryptor-native-ui-")); + const inputPath = path.join(temporaryDirectory, "input.txt"); + const publicKeyPath = path.join(temporaryDirectory, "public.pem"); + const privateKeyPath = path.join(temporaryDirectory, "private.pem"); + const encryptedPath = path.join(temporaryDirectory, "input_encrypted.pqc"); + const decryptedPath = path.join(temporaryDirectory, "input_decrypted.txt"); + await writeFile(inputPath, inputBytes); + + browser = await chromium.launch({ headless: true }); + const context = await browser.newContext({ viewport: { width: 1440, height: 900 } }); + const page = await context.newPage(); + + await page.goto(baseUrl, { waitUntil: "networkidle" }); + await page.getByRole("heading", { name: "Encrypt a file" }).waitFor(); + + const health = await page.evaluate(async () => { + const response = await fetch("/api/health", { credentials: "same-origin" }); + if (!response.ok) return null; + return response.json(); + }); + assertReadyHealth(health); + await page.getByText("Ready", { exact: true }).first().waitFor({ state: "visible" }); + + await page.getByRole("button", { name: "Generate keys" }).click(); + await page.getByRole("heading", { name: "Generate keys" }).waitFor(); + await page.getByLabel("Private key password", { exact: true }).fill(password); + await page.getByLabel("Confirm private key password").fill(password); + await page.getByRole("button", { name: "Generate key pair" }).click(); + await page.getByText("Key pair generated", { exact: true }).waitFor({ state: "visible" }); + await downloadFromButton(page, "Download public key", publicKeyPath); + await downloadFromButton(page, "Download encrypted private key", privateKeyPath); + await page.getByRole("button", { name: "Clear generated keys" }).click(); + assert.equal(await page.getByRole("button", { name: "Download public key" }).count(), 0); + assert.equal(await page.getByRole("button", { name: "Download encrypted private key" }).count(), 0); + + await page.getByRole("button", { name: "Encrypt" }).first().click(); + await page.getByRole("heading", { name: "Encrypt a file" }).waitFor(); + await page.getByLabel("File to encrypt").setInputFiles(inputPath); + await page.getByLabel("Recipient public key").setInputFiles(publicKeyPath); + await page.getByText("Compatible public key", { exact: true }).waitFor({ state: "visible" }); + const encryptedDownload = page.waitForEvent("download"); + await page.getByRole("button", { name: "Encrypt file" }).click(); + await saveDownload(await encryptedDownload, encryptedPath); + await page.getByText("File encrypted", { exact: true }).waitFor({ state: "visible" }); + + await page.getByRole("button", { name: "Decrypt" }).first().click(); + await page.getByRole("heading", { name: "Decrypt a file" }).waitFor(); + await page.getByLabel("Encrypted file").setInputFiles(encryptedPath); + await page.getByLabel("Private key", { exact: true }).setInputFiles(privateKeyPath); + await page.getByText("Compatible private key", { exact: true }).waitFor({ state: "visible" }); + await page.getByLabel("Private key password", { exact: true }).fill(password); + const decryptedDownload = page.waitForEvent("download"); + await page.getByRole("button", { name: "Decrypt file" }).click(); + await saveDownload(await decryptedDownload, decryptedPath); + await page.getByText("File decrypted", { exact: true }).waitFor({ state: "visible" }); + + assert.deepEqual(await readFile(decryptedPath), inputBytes, "The native browser round trip returned different bytes."); + console.log("Native browser encryption round trip passed."); + } finally { + try { + await browser?.close(); + } finally { + if (temporaryDirectory) await rm(temporaryDirectory, { recursive: true, force: true }); + } + } +} + +try { + await run(); +} catch { + console.error("Native browser encryption round trip failed."); + process.exitCode = 1; +} diff --git a/scripts/ui_smoke.mjs b/scripts/ui_smoke.mjs index dad1865..2255ab8 100644 --- a/scripts/ui_smoke.mjs +++ b/scripts/ui_smoke.mjs @@ -1,50 +1,381 @@ +import assert from "node:assert/strict"; import { mkdir } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import AxeBuilder from "@axe-core/playwright"; import { chromium } from "playwright"; const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const outDir = path.join(rootDir, "tmp", "ui-smoke"); const baseUrl = process.env.UI_SMOKE_URL ?? "http://127.0.0.1:4000/"; +const localToken = "ui-smoke-local-token"; + +const publicInspection = { + ok: true, + keyInfo: { kem: "ML-KEM-768+X25519-v2", key_type: "public" }, + display: { + "Key Type": "Public key", + "Hybrid suite": "ML-KEM-768+X25519-v2" + } +}; + +const outdatedPublicInspection = { + ok: true, + keyInfo: { kem: "ML-KEM-768+X25519", key_type: "public" }, + display: { + "Key Type": "Public key", + "Hybrid suite": "ML-KEM-768+X25519" + } +}; + +const privateInspection = { + ok: true, + keyInfo: { + kem: "ML-KEM-768+X25519-v2", + key_type: "private", + private_key_encrypted: true, + private_key_format_version: 2, + private_key_kdf: "scrypt" + }, + display: { + "Key Type": "Encrypted private key", + "Key format": "2", + "Key KDF": "scrypt", + "Hybrid suite": "ML-KEM-768+X25519-v2" + } +}; + +function health({ limited = false, strictFileLimit = false } = {}) { + const available = { available: true, reason: "" }; + return { + ok: true, + backendReady: !limited, + backendMessage: limited + ? "The ML-KEM backend is not ready, so new keys and ciphertexts cannot be created. Compatible encrypted archives may still be decryptable." + : "Post-quantum backend ready.", + capabilities: limited + ? { + inspect: available, + generate: { available: false, reason: "Key generation is unavailable in this local engine." }, + encrypt: { available: false, reason: "Encryption is unavailable in this local engine." }, + decrypt: available + } + : { inspect: available, generate: available, encrypt: available, decrypt: available }, + formatVersion: 4, + kem: "ML-KEM-768+X25519-v2", + kemComponent: "ML-KEM-768", + configuredKem: "ML-KEM-768", + dem: "AES-256-GCM", + maxFileBytes: strictFileLimit ? 3 : 104857600, + maxEncryptedFileBytes: 105906314, + maxPemBytes: 131072, + apiToken: localToken, + passwordPolicy: { minChars: 16, minUniqueChars: 5 } + }; +} + +function json(route, payload, status = 200) { + return route.fulfill({ + status, + contentType: "application/json", + body: JSON.stringify(payload) + }); +} + +function errorPayload(errorCode, message) { + return { ok: false, error_code: errorCode, message }; +} + +function file(name, contents, mimeType = "application/octet-stream") { + return { name, mimeType, buffer: Buffer.from(contents) }; +} + +function activeElementLabel() { + const element = document.activeElement; + if (!(element instanceof HTMLElement)) return ""; + const associatedLabel = "labels" in element && element.labels?.[0]?.textContent?.trim(); + return element.getAttribute("aria-label") || associatedLabel || element.textContent?.trim() || element.id; +} + +async function collectTabOrder(page, limit = 40) { + await page.evaluate(() => (document.activeElement instanceof HTMLElement ? document.activeElement.blur() : undefined)); + const order = []; + for (let index = 0; index < limit; index += 1) { + await page.keyboard.press("Tab"); + order.push(await page.evaluate(activeElementLabel)); + } + return order; +} + +function assertLogicalTabOrder(order, labels) { + let lastIndex = -1; + for (const label of labels) { + const nextIndex = order.findIndex((value, index) => index > lastIndex && value === label); + assert.notEqual(nextIndex, -1, `Tab did not reach ${label}: ${JSON.stringify(order)}`); + lastIndex = nextIndex; + } +} + +async function assertNoHorizontalOverflow(page) { + for (const viewport of [ + { width: 390, height: 844 }, + { width: 768, height: 900 }, + { width: 1024, height: 768 }, + { width: 1440, height: 900 } + ]) { + await page.setViewportSize(viewport); + const overflow = await page.evaluate(() => document.documentElement.scrollWidth > window.innerWidth); + assert.equal(overflow, false, `horizontal overflow at ${viewport.width}`); + } +} + +async function assertAxe(page, label) { + const scan = await new AxeBuilder({ page }) + .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]) + .analyze(); + assert.deepEqual(scan.violations, [], `${label} accessibility violations: ${JSON.stringify(scan.violations, null, 2)}`); +} await mkdir(outDir, { recursive: true }); +let limitedHealth = false; +let strictFileLimit = false; +const unexpectedApiRequests = []; +const apiRequests = []; +let staleInspectionRoute = null; +let captureStaleInspectionRoute; +const staleInspectionRouteCaptured = new Promise((resolve) => { + captureStaleInspectionRoute = resolve; +}); const browser = await chromium.launch({ headless: true }); try { - const page = await browser.newPage({ viewport: { width: 1280, height: 720 } }); + const context = await browser.newContext({ viewport: { width: 1440, height: 900 } }); + const page = await context.newPage(); + + await page.route("**/api/**", async (route) => { + const request = route.request(); + const pathname = new URL(request.url()).pathname; + const method = request.method(); + const payload = request.postDataBuffer()?.toString("utf8") ?? ""; + apiRequests.push(`${method} ${pathname}`); + + if (method === "GET" && pathname === "/api/health") { + return json(route, health({ limited: limitedHealth, strictFileLimit })); + } + if (method === "POST" && pathname === "/api/keys/inspect") { + if (payload.includes("stale-first.pem")) { + staleInspectionRoute = route; + captureStaleInspectionRoute(); + return; + } + if (payload.includes("outdated-public.pem")) return json(route, outdatedPublicInspection); + if (payload.includes("wrong-key-type.pem")) return json(route, privateInspection); + return json(route, payload.includes("private.pem") ? privateInspection : publicInspection); + } + if (method === "POST" && pathname === "/api/keys/generate") { + return json(route, { + ok: true, + kem: "ML-KEM-768+X25519-v2", + publicPem: "PUBLIC-PEM", + privatePem: "PRIVATE-PEM", + publicFilename: "quantum_public.pem", + privateFilename: "quantum_private_encrypted.pem" + }); + } + if (method === "POST" && pathname === "/api/files/encrypt") { + if (payload.includes("unexpected-backend-error.txt")) { + return json(route, errorPayload("unexpected_backend_error", "Raw fixture detail: /not-for-the-user"), 500); + } + return route.fulfill({ + status: 200, + contentType: "application/octet-stream", + headers: { "Content-Disposition": 'attachment; filename="report_encrypted.pqc"' }, + body: "ciphertext" + }); + } + if (method === "POST" && pathname === "/api/files/decrypt") { + if (payload.includes("tampered_encrypted.pqc")) { + return json(route, errorPayload("decryption_failed", "Ciphertext authentication failed."), 422); + } + return route.fulfill({ + status: 200, + contentType: "application/octet-stream", + headers: { "Content-Disposition": 'attachment; filename="report.txt"' }, + body: "plaintext" + }); + } + unexpectedApiRequests.push(`${method} ${pathname}`); + return json(route, errorPayload("unexpected_ui_smoke_api_request", "Unexpected local test API request."), 500); + }); + await page.goto(baseUrl, { waitUntil: "networkidle" }); - const states = { - encryptDisabled: await page.getByRole("button", { name: "Encrypt File" }).last().isDisabled() - }; + await page.getByRole("heading", { name: "Encrypt a file" }).waitFor(); + assert.equal(await page.getByRole("main").count(), 1); + assert.equal(await page.getByRole("navigation", { name: "Workflows" }).count(), 1); + assert.equal(await page.getByRole("button", { name: "Encrypt" }).first().getAttribute("aria-current"), "page"); + await expectText(page, "Ready"); - await page.getByRole("button", { name: "Decrypt File" }).click(); - states.decryptVisible = await page.getByRole("heading", { name: "Decrypt File" }).isVisible(); - states.decryptDisabled = await page.getByRole("button", { name: "Decrypt File" }).last().isDisabled(); + strictFileLimit = true; + await page.reload({ waitUntil: "networkidle" }); + const encryptRequestsBeforeOversizedFile = apiRequests.filter((request) => request === "POST /api/files/encrypt").length; + await page.getByLabel("File to encrypt").setInputFiles(file("oversized.txt", "four", "text/plain")); + await expectText(page, "This file exceeds the 3 byte limit."); + assert.equal(await page.getByRole("button", { name: "Encrypt file" }).isDisabled(), true); + assert.equal( + apiRequests.filter((request) => request === "POST /api/files/encrypt").length, + encryptRequestsBeforeOversizedFile, + "oversized files must not trigger encryption requests" + ); - await page.getByRole("button", { name: "Generate Keys" }).click(); - states.generateVisible = await page.getByRole("heading", { name: "Generate Keys" }).isVisible(); - states.generateDisabled = await page.getByRole("button", { name: /Generate .* Key Pair/ }).isDisabled(); + strictFileLimit = false; + await page.reload({ waitUntil: "networkidle" }); - await page.getByRole("button", { name: "Inspect Key" }).click(); - states.inspectVisible = await page.getByRole("heading", { name: "Inspect Key" }).isVisible(); + await page.getByLabel("File to encrypt").setInputFiles(file("report.txt", "local report", "text/plain")); + await page.getByLabel("Recipient public key").setInputFiles(file("public.pem", "PUBLIC-PEM", "application/x-pem-file")); + await expectText(page, "Compatible public key"); + await page.getByRole("button", { name: "Encrypt file" }).waitFor({ state: "visible" }); + assert.equal(await page.getByRole("button", { name: "Encrypt file" }).isEnabled(), true); + assert.equal(await page.getByLabel("Output filename").inputValue(), "report_encrypted.pqc"); - await page.setViewportSize({ width: 1280, height: 720 }); - await page.getByRole("button", { name: "Encrypt File" }).click(); + const desktopTabOrder = await collectTabOrder(page); + assertLogicalTabOrder(desktopTabOrder, ["Encrypt", "File to encrypt", "Recipient public key", "Output filename", "Encrypt file", "Technical details"]); + assert.equal(await page.getByText("Technical details").first().evaluate((element) => element.parentElement?.open), false); + await page.getByText("Technical details").first().click(); + assert.equal(await page.getByText("Technical details").first().evaluate((element) => element.parentElement?.open), true); + await assertNoHorizontalOverflow(page); + await page.setViewportSize({ width: 1440, height: 900 }); + await assertAxe(page, "ready Encrypt screen"); await page.screenshot({ path: path.join(outDir, "quantum-encryptor-web.png"), fullPage: true }); + await page.getByRole("button", { name: "Encrypt file" }).click(); + await expectText(page, "File encrypted"); + await expectText(page, "Saved report_encrypted.pqc."); + + await page.getByLabel("Recipient public key").setInputFiles(file("outdated-public.pem", "OUTDATED", "application/x-pem-file")); + await expectText(page, "This public key uses ML-KEM-768+X25519; encryption requires ML-KEM-768+X25519-v2."); + assert.equal(await page.getByRole("button", { name: "Encrypt file" }).isDisabled(), true); + + await page.getByLabel("Recipient public key").setInputFiles(file("wrong-key-type.pem", "PRIVATE-PEM", "application/x-pem-file")); + await expectText(page, "Private key — not valid for encryption"); + assert.equal(await page.getByRole("button", { name: "Encrypt file" }).isDisabled(), true); + + await page.getByLabel("Recipient public key").setInputFiles(file("public.pem", "PUBLIC-PEM", "application/x-pem-file")); + await expectText(page, "Compatible public key"); + await page.getByLabel("File to encrypt").setInputFiles(file("unexpected-backend-error.txt", "safe local fixture", "text/plain")); + await page.getByRole("button", { name: "Encrypt file" }).click(); + await expectText(page, "Could not encrypt this file. Confirm the recipient key and try again."); + assert.equal(await page.getByText("Raw fixture detail: /not-for-the-user").count(), 0); + + await page.getByRole("button", { name: "Inspect key" }).first().click(); + await page.getByRole("heading", { name: "Inspect a key" }).waitFor(); + assert.equal(await page.getByRole("button", { name: "Inspect key" }).first().getAttribute("aria-current"), "page"); + await page.getByLabel("Key file").setInputFiles(file("public.pem", "PUBLIC-PEM", "application/x-pem-file")); + await expectText(page, "Public key"); + await page.getByText("Technical details").first().click(); + await expectText(page, "ML-KEM-768+X25519-v2"); + await page.getByLabel("Key file").setInputFiles(file("private.pem", "PRIVATE-PEM", "application/x-pem-file")); + await expectText(page, "Encrypted private key"); + await page.getByText("Technical details").first().click(); + await expectText(page, "scrypt"); + await page.getByLabel("Key file").setInputFiles(file("stale-first.pem", "STALE", "application/x-pem-file")); + await staleInspectionRouteCaptured; + await page.getByLabel("Key file").setInputFiles(file("public.pem", "PUBLIC-PEM", "application/x-pem-file")); + await expectText(page, "Public key"); + await staleInspectionRoute?.abort("failed"); + assert.equal(await page.getByText("Public key").count() > 0, true, "replaced inspection must remain current after cancellation"); + + await page.getByRole("button", { name: "Generate keys" }).click(); + await page.getByRole("heading", { name: "Generate keys" }).waitFor(); + await page.getByLabel("Private key password", { exact: true }).fill("correct-horse-battery-staple"); + await page.getByLabel("Confirm private key password").fill("correct-horse-battery-staple"); + await page.getByRole("button", { name: "Generate key pair" }).click(); + await expectText(page, "Key pair generated"); + await expectText(page, "quantum_public.pem"); + await expectText(page, "quantum_private_encrypted.pem"); + await page.getByRole("button", { name: "Clear generated keys" }).click(); + assert.equal(await page.getByRole("button", { name: "Download public key" }).count(), 0); + assert.equal(await page.getByRole("button", { name: "Download encrypted private key" }).count(), 0); + + await page.getByRole("button", { name: "Decrypt" }).first().click(); + await page.getByRole("heading", { name: "Decrypt a file" }).waitFor(); + await page.getByLabel("Encrypted file").setInputFiles(file("report_encrypted.pqc", "ciphertext")); + await page.getByLabel("Private key", { exact: true }).setInputFiles(file("private.pem", "PRIVATE-PEM", "application/x-pem-file")); + await expectText(page, "Supported encrypted private key; match not yet verified"); + await page.getByLabel("Private key password", { exact: true }).fill("correct-horse-battery-staple"); + assert.equal(await page.getByLabel("Output filename").inputValue(), "report"); + await page.getByRole("button", { name: "Decrypt file" }).click(); + await expectText(page, "File decrypted"); + await expectText(page, "Saved report.txt."); + + await page.getByLabel("Encrypted file").setInputFiles(file("tampered_encrypted.pqc", "tampered")); + await page.getByLabel("Private key password", { exact: true }).fill("correct-horse-battery-staple"); + await page.getByRole("button", { name: "Decrypt file" }).click(); + await expectText(page, "Decryption failed"); + await expectText(page, "The file could not be authenticated. Check the encrypted file, private key, and password."); + assert.equal(await page.getByText("Ciphertext authentication failed.").count(), 0); + await page.setViewportSize({ width: 390, height: 844 }); - await page.getByRole("button", { name: "Inspect Key" }).click(); + await page.getByRole("link", { name: "Inspect key" }).click(); + await page.getByRole("heading", { name: "Inspect a key" }).waitFor(); + assert.equal(await page.getByRole("link", { name: "Inspect key" }).getAttribute("aria-current"), "page"); + await page.getByLabel("Key file").setInputFiles(file("public.pem", "PUBLIC-PEM", "application/x-pem-file")); + await expectText(page, "Public key"); + await assertAxe(page, "mobile Inspect screen"); await page.screenshot({ path: path.join(outDir, "quantum-encryptor-mobile.png"), fullPage: true }); - if (!states.encryptDisabled || !states.decryptVisible || !states.decryptDisabled) { - throw new Error(`Unexpected file workflow state: ${JSON.stringify(states)}`); - } - if (!states.generateVisible || !states.generateDisabled || !states.inspectVisible) { - throw new Error(`Unexpected key workflow state: ${JSON.stringify(states)}`); - } + await page.emulateMedia({ reducedMotion: "reduce" }); + const reducedMotionDuration = await page.locator(".app-mobile-navigation a").first().evaluate( + (element) => getComputedStyle(element).transitionDuration + ); + assert.ok( + reducedMotionDuration.split(", ").every((duration) => Number.parseFloat(duration) <= 0.01), + `reduced-motion transition duration is too long: ${reducedMotionDuration}` + ); + + limitedHealth = true; + await page.setViewportSize({ width: 1440, height: 900 }); + await page.reload({ waitUntil: "networkidle" }); + await page.getByRole("heading", { name: "Encrypt a file" }).waitFor(); + await expectText(page, "Limited"); + await expectText(page, "Encryption is unavailable in this local engine."); + assert.equal(await page.getByLabel("File to encrypt").count(), 0); + await page.getByText("Capability details").first().click(); + await expectText(page, "Key generation is unavailable in this local engine."); + await expectText(page, "Encryption is unavailable in this local engine."); + + await page.getByRole("button", { name: "Inspect key" }).first().click(); + await page.getByRole("heading", { name: "Inspect a key" }).waitFor(); + assert.equal(await page.getByLabel("Key file").count(), 1); - console.log(JSON.stringify(states, null, 2)); + await page.getByRole("button", { name: "Generate keys" }).click(); + await page.getByRole("heading", { name: "Generate keys" }).waitFor(); + await expectText(page, "Key generation is unavailable in this local engine."); + assert.equal(await page.getByLabel("Private key password", { exact: true }).count(), 0); + assert.equal(await page.getByRole("button", { name: "Generate key pair" }).count(), 0); + + await page.getByRole("button", { name: "Encrypt" }).first().click(); + await page.getByRole("heading", { name: "Encrypt a file" }).waitFor(); + await expectText(page, "Encryption is unavailable in this local engine."); + assert.equal(await page.getByLabel("File to encrypt").count(), 0); + + await page.getByRole("button", { name: "Decrypt" }).first().click(); + await page.getByRole("heading", { name: "Decrypt a file" }).waitFor(); + assert.equal(await page.getByRole("button", { name: "Decrypt file" }).isDisabled(), true); + await expectText(page, "Choose an encrypted file."); + + assert.deepEqual(unexpectedApiRequests, [], `Unexpected API requests: ${unexpectedApiRequests.join(", ")}`); + + console.log(JSON.stringify({ + health: ["all capabilities", "inspect and decrypt"], + workflows: ["inspect", "generate", "encrypt", "decrypt", "decryption_failed"], + viewports: [390, 768, 1024, 1440], + screenshots: ["quantum-encryptor-web.png", "quantum-encryptor-mobile.png"] + }, null, 2)); } finally { await browser.close(); } + +async function expectText(page, text) { + await page.getByText(text, { exact: true }).filter({ visible: true }).first().waitFor({ state: "visible" }); +} diff --git a/start.sh b/start.sh index eb0be2a..b66ec1f 100755 --- a/start.sh +++ b/start.sh @@ -22,12 +22,6 @@ if [ -z "$PYTHON_BIN" ]; then exit 127 fi -if [ "${LEGACY_STREAMLIT:-0}" = "1" ]; then - exec "$PYTHON_BIN" -m streamlit run pqc_app.py \ - --server.address 127.0.0.1 \ - --server.port "$APP_PORT" -fi - if [ "${SKIP_WEB_BUILD:-0}" != "1" ]; then if [ ! -x "node_modules/.bin/vite" ]; then echo "Frontend dependencies are missing. Run npm install before ./start.sh." >&2 diff --git a/tests/test_api_app.py b/tests/test_api_app.py index 726476a..fd84fc2 100644 --- a/tests/test_api_app.py +++ b/tests/test_api_app.py @@ -47,6 +47,31 @@ def test_health_payload_reports_ready_backend(monkeypatch): assert payload["kemComponent"] == "ML-KEM-768" +def test_health_payload_reports_partial_capabilities(monkeypatch): + def missing_current_backend(_kem): + raise core.CryptoDependencyError("private backend detail") + + monkeypatch.setattr(core, "resolve_kem_algorithm", missing_current_backend) + monkeypatch.setattr(core, "available_decryption_kem_algorithms", lambda: ("Kyber768",)) + + payload = api_app._health_payload() + + assert payload["backendReady"] is False + assert payload["capabilities"] == { + "inspect": {"available": True, "reason": ""}, + "generate": { + "available": False, + "reason": "ML-KEM-768 is unavailable for new key generation.", + }, + "encrypt": { + "available": False, + "reason": "ML-KEM-768 is unavailable for new encryption.", + }, + "decrypt": {"available": True, "reason": ""}, + } + assert "private backend detail" not in str(payload) + + def test_content_disposition_quotes_download_filename(): header = api_app._content_disposition("encrypted file.pqc") diff --git a/tests/test_crypto_core.py b/tests/test_crypto_core.py index 1d644f5..cd50f30 100644 --- a/tests/test_crypto_core.py +++ b/tests/test_crypto_core.py @@ -163,6 +163,17 @@ class FakeOQS: return FakeOQS +def test_available_decryption_kem_algorithms_preserves_exact_identities(monkeypatch): + """Archive availability lists exact current and legacy KEM identities.""" + monkeypatch.setattr( + core, + "_enabled_kem_mechanisms", + lambda: ("Kyber768", "ML-KEM-768", "Other"), + ) + + assert core.available_decryption_kem_algorithms() == ("ML-KEM-768", "Kyber768") + + def _legacy_v3_blob(plaintext: bytes, mlkem_public: bytes) -> bytes: """Build a valid legacy v3 container using the deterministic fake backend.""" ciphertext_kem = b"C" * 32 diff --git a/tests/test_startup.py b/tests/test_startup.py new file mode 100644 index 0000000..de68435 --- /dev/null +++ b/tests/test_startup.py @@ -0,0 +1,43 @@ +import os +from pathlib import Path +import subprocess + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] + + +def test_start_script_uses_api_app_when_legacy_flag_is_set(tmp_path): + argv_log = tmp_path / "interpreter-argv.txt" + interpreter = tmp_path / "python-stub" + startup_script = tmp_path / "start.sh" + static_app = tmp_path / "static" / "app" + static_app.mkdir(parents=True) + (static_app / "index.html").write_text("", encoding="utf-8") + startup_script.write_text((REPOSITORY_ROOT / "start.sh").read_text(encoding="utf-8"), encoding="utf-8") + startup_script.chmod(0o755) + interpreter.write_text( + "#!/usr/bin/env sh\n" "set -eu\n" 'printf "%s\\n" "$@" > "$STARTUP_ARGV_LOG"\n', + encoding="utf-8", + ) + interpreter.chmod(0o755) + + environment = os.environ.copy() + environment.update( + { + "PYTHON": str(interpreter), + "LEGACY_STREAMLIT": "1", + "SKIP_WEB_BUILD": "1", + "STARTUP_ARGV_LOG": str(argv_log), + } + ) + + completed = subprocess.run( + [str(startup_script)], + cwd=tmp_path, + env=environment, + check=False, + capture_output=True, + text=True, + ) + + assert completed.returncode == 0, completed.stderr + assert argv_log.read_text(encoding="utf-8").splitlines() == ["-m", "api_app"] diff --git a/tsconfig.json b/tsconfig.json index 1a8a9f1..0dd3134 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,5 +16,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": ["web/src", "vite.config.ts"] + "include": ["web/src", "web/src/**/*.test.ts", "web/src/**/*.test.tsx", "vite.config.ts"] } diff --git a/ui_helpers.py b/ui_helpers.py index d78d6e9..56266ce 100644 --- a/ui_helpers.py +++ b/ui_helpers.py @@ -19,7 +19,7 @@ def guess_decrypted_filename(encrypted_filename: Path) -> str: def format_key_info_for_display(key_info: dict[str, object]) -> dict[str, str]: - """Format strict key-inspection metadata for Streamlit display.""" + """Format strict key-inspection metadata for local web display.""" display = { "Key Type": str(key_info["key_type"]).title(), "Algorithm": str(key_info["kem"]), diff --git a/vite.config.ts b/vite.config.ts index 52c0507..2778f58 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,3 +1,5 @@ +/// + import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; @@ -15,5 +17,11 @@ export default defineConfig({ build: { outDir: "../static/app", emptyOutDir: true + }, + test: { + environment: "jsdom", + setupFiles: ["./src/test/setup.ts"], + clearMocks: true, + restoreMocks: true } }); diff --git a/web/src/App.tsx b/web/src/App.tsx deleted file mode 100644 index 923a8d3..0000000 --- a/web/src/App.tsx +++ /dev/null @@ -1,632 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import { - ApiError, - decryptFile, - DownloadResult, - encryptFile, - fetchHealth, - generateKeys, - GeneratedKeys, - Health, - inspectKey, - KeyInspectResult -} from "./api"; - -type View = "encrypt" | "decrypt" | "generate" | "inspect"; -type NoticeKind = "info" | "success" | "warning" | "error"; -type Notice = { kind: NoticeKind; text: string }; - -const DEFAULT_HEALTH: Health = { - ok: true, - backendReady: false, - backendMessage: "Checking backend readiness.", - formatVersion: 4, - kem: "ML-KEM-768+X25519-v2", - kemComponent: "ML-KEM-768", - configuredKem: "ML-KEM-768", - dem: "AES-256-GCM", - maxFileBytes: 100 * 1024 * 1024, - maxEncryptedFileBytes: 101 * 1024 * 1024, - maxPemBytes: 128 * 1024, - apiToken: "", - passwordPolicy: { minChars: 16, minUniqueChars: 5 } -}; - -const views: Array<{ id: View; label: string; group: "File Workflows" | "Key Management" }> = [ - { id: "encrypt", label: "Encrypt File", group: "File Workflows" }, - { id: "decrypt", label: "Decrypt File", group: "File Workflows" }, - { id: "generate", label: "Generate Keys", group: "Key Management" }, - { id: "inspect", label: "Inspect Key", group: "Key Management" } -]; - -function formatBytes(bytes: number): string { - if (!Number.isFinite(bytes)) return "0 B"; - if (bytes < 1024) return `${bytes} B`; - const units = ["KiB", "MiB", "GiB"]; - let value = bytes / 1024; - let index = 0; - while (value >= 1024 && index < units.length - 1) { - value /= 1024; - index += 1; - } - return `${value.toFixed(value >= 10 ? 1 : 2)} ${units[index]}`; -} - -function downloadBlob(result: DownloadResult): void { - const url = URL.createObjectURL(result.blob); - const anchor = document.createElement("a"); - anchor.href = url; - anchor.download = result.filename; - document.body.append(anchor); - anchor.click(); - anchor.remove(); - window.setTimeout(() => URL.revokeObjectURL(url), 1000); -} - -function downloadText(filename: string, text: string): void { - downloadBlob({ filename, blob: new Blob([text], { type: "application/x-pem-file" }) }); -} - -function apiMessage(error: unknown): string { - if (error instanceof ApiError) return error.message; - if (error instanceof Error) return error.message; - return "Request failed."; -} - -function fileTooLarge(file: File | null, maxBytes: number): boolean { - return !!file && file.size > maxBytes; -} - -function sizeNotice(file: File | null, maxBytes: number, label: string): Notice | null { - if (!fileTooLarge(file, maxBytes)) return null; - return { - kind: "error", - text: `${label} is ${formatBytes(file?.size ?? 0)}. The maximum supported size is ${formatBytes(maxBytes)}.` - }; -} - -function suggestedEncryptedName(file: File | null): string { - if (!file) return "encrypted-file.pqc"; - const dot = file.name.lastIndexOf("."); - const stem = dot > 0 ? file.name.slice(0, dot) : file.name || "file"; - return `${stem}_encrypted.pqc`; -} - -function suggestedDecryptedName(file: File | null): string { - if (!file) return "decrypted.bin"; - const name = file.name; - if (name === ".pqc") return "decrypted.bin"; - if (name.endsWith("_encrypted.pqc")) return name.slice(0, -"_encrypted.pqc".length) || "decrypted.bin"; - if (name.endsWith(".pqc")) return `${name.slice(0, -".pqc".length)}_decrypted.bin`; - const dot = name.lastIndexOf("."); - if (dot > 0) return `${name.slice(0, dot)}_decrypted${name.slice(dot)}`; - return `${name}_decrypted.bin`; -} - -function useKeyInspection(file: File | null, maxPemBytes: number) { - const [result, setResult] = useState(null); - const [notice, setNotice] = useState(null); - const [loading, setLoading] = useState(false); - - useEffect(() => { - let cancelled = false; - setResult(null); - setNotice(null); - if (!file) return; - if (fileTooLarge(file, maxPemBytes)) { - setNotice(sizeNotice(file, maxPemBytes, "Key file")); - return; - } - setLoading(true); - inspectKey(file) - .then((payload) => { - if (!cancelled) setResult(payload); - }) - .catch((error) => { - if (!cancelled) setNotice({ kind: "error", text: apiMessage(error) }); - }) - .finally(() => { - if (!cancelled) setLoading(false); - }); - return () => { - cancelled = true; - }; - }, [file, maxPemBytes]); - - return { result, notice, loading }; -} - -function App() { - const [activeView, setActiveView] = useState("encrypt"); - const [health, setHealth] = useState(DEFAULT_HEALTH); - const [healthNotice, setHealthNotice] = useState(null); - - useEffect(() => { - let cancelled = false; - fetchHealth() - .then((payload) => { - if (!cancelled) setHealth(payload); - }) - .catch((error) => { - if (!cancelled) setHealthNotice({ kind: "error", text: apiMessage(error) }); - }); - return () => { - cancelled = true; - }; - }, []); - - const readinessNotice = healthNotice ?? { - kind: health.backendReady ? ("success" as const) : ("warning" as const), - text: health.backendMessage - }; - - return ( -

- -
- {activeView === "encrypt" && } - {activeView === "decrypt" && } - {activeView === "generate" && } - {activeView === "inspect" && } -
-
- ); -} - -function Sidebar({ activeView, health, onSelect }: { activeView: View; health: Health; onSelect: (view: View) => void }) { - return ( - - ); -} - -function MetaBadge({ label, value }: { label: string; value: string }) { - return ( -
- {label} - {value} -
- ); -} - -function NoticePanel({ notice }: { notice: Notice | null }) { - if (!notice) return null; - return ( -
- {notice.text} -
- ); -} - -function WorkflowHeader({ title, subtitle }: { title: string; subtitle: string }) { - return ( -
-
-

{title}

-

{subtitle}

-
-
- ); -} - -function Stepper({ steps, activeIndex }: { steps: string[]; activeIndex: number }) { - return ( -
    - {steps.map((step, index) => ( -
  1. - {index + 1} - {step} -
  2. - ))} -
- ); -} - -function FileDrop({ - id, - label, - hint, - accept, - file, - onFile -}: { - id: string; - label: string; - hint: string; - accept?: string; - file: File | null; - onFile: (file: File | null) => void; -}) { - return ( - - ); -} - -function FieldRow({ label, value }: { label: string; value: string }) { - return ( -
- {label} - {value} -
- ); -} - -function EncryptView({ health, readinessNotice }: { health: Health; readinessNotice: Notice }) { - const [file, setFile] = useState(null); - const [publicKey, setPublicKey] = useState(null); - const [outputName, setOutputName] = useState("encrypted-file.pqc"); - const [notice, setNotice] = useState(null); - const [working, setWorking] = useState(false); - const [downloadReady, setDownloadReady] = useState(false); - const keyInspection = useKeyInspection(publicKey, health.maxPemBytes); - - useEffect(() => { - setOutputName(suggestedEncryptedName(file)); - setDownloadReady(false); - }, [file]); - - const publicKeyReady = - keyInspection.result?.keyInfo.key_type === "public" && keyInspection.result.keyInfo.kem === health.kem; - const fileSizeNotice = sizeNotice(file, health.maxFileBytes, "Input file"); - const keySizeNotice = sizeNotice(publicKey, health.maxPemBytes, "Public key file"); - const activeIndex = downloadReady ? 4 : publicKeyReady && outputName ? 3 : file && publicKey ? 2 : file ? 1 : 0; - const canEncrypt = - health.backendReady && - !!file && - !fileSizeNotice && - publicKeyReady && - !keySizeNotice && - !!outputName && - !working; - - async function submit() { - if (!file || !publicKey || !canEncrypt) return; - setNotice(null); - setWorking(true); - try { - const result = await encryptFile(file, publicKey, outputName); - downloadBlob(result); - setDownloadReady(true); - setNotice({ kind: "success", text: `Encrypted file prepared as ${result.filename}.` }); - } catch (error) { - setNotice({ kind: "error", text: apiMessage(error) }); - } finally { - setWorking(false); - } - } - - return ( -
- - - -
-
-

Inputs

- - - - {keyInspection.loading && } - -
-
-

Review

- - - - - -
-
-
- ); -} - -function DecryptView({ health, readinessNotice }: { health: Health; readinessNotice: Notice }) { - const [file, setFile] = useState(null); - const [privateKey, setPrivateKey] = useState(null); - const [password, setPassword] = useState(""); - const [outputName, setOutputName] = useState("decrypted.bin"); - const [notice, setNotice] = useState(null); - const [working, setWorking] = useState(false); - const [downloadReady, setDownloadReady] = useState(false); - const keyInspection = useKeyInspection(privateKey, health.maxPemBytes); - - useEffect(() => { - setOutputName(suggestedDecryptedName(file)); - setDownloadReady(false); - }, [file]); - - const privateKeyReady = keyInspection.result?.keyInfo.key_type === "private"; - const fileSizeNotice = sizeNotice(file, health.maxEncryptedFileBytes, "Encrypted file"); - const keySizeNotice = sizeNotice(privateKey, health.maxPemBytes, "Private key file"); - const activeIndex = downloadReady ? 4 : privateKeyReady && password && outputName ? 3 : file && privateKey ? 2 : file ? 1 : 0; - const canDecrypt = - !!file && - !fileSizeNotice && - privateKeyReady && - !keySizeNotice && - !!password && - !!outputName && - !working; - - async function submit() { - if (!file || !privateKey || !canDecrypt) return; - setNotice(null); - setWorking(true); - try { - const result = await decryptFile(file, privateKey, password, outputName); - downloadBlob(result); - setDownloadReady(true); - setPassword(""); - setNotice({ kind: "success", text: `Decrypted file prepared as ${result.filename}.` }); - } catch (error) { - setNotice({ kind: "error", text: apiMessage(error) }); - } finally { - setWorking(false); - } - } - - return ( -
- - - -
-
-

Inputs

- - - - {keyInspection.loading && } - -
-
-

Review

- - - - - - -
-
-
- ); -} - -function GenerateKeysView({ health, readinessNotice }: { health: Health; readinessNotice: Notice }) { - const [password, setPassword] = useState(""); - const [confirm, setConfirm] = useState(""); - const [notice, setNotice] = useState(null); - const [working, setWorking] = useState(false); - const [keys, setKeys] = useState(null); - - const checks = useMemo( - () => [ - { label: `${health.passwordPolicy.minChars}+ characters`, ok: password.length >= health.passwordPolicy.minChars }, - { label: `${health.passwordPolicy.minUniqueChars}+ unique characters`, ok: new Set(password).size >= health.passwordPolicy.minUniqueChars }, - { label: "Confirmation matches", ok: password.length > 0 && password === confirm } - ], - [confirm, health.passwordPolicy.minChars, health.passwordPolicy.minUniqueChars, password] - ); - const canGenerate = health.backendReady && checks.every((check) => check.ok) && !working; - const activeIndex = keys ? 4 : canGenerate ? 2 : password || confirm ? 1 : 0; - - async function submit() { - if (!canGenerate) return; - setNotice(null); - setWorking(true); - setKeys(null); - try { - const result = await generateKeys(password); - setKeys(result); - setPassword(""); - setConfirm(""); - setNotice({ kind: "success", text: "Key pair generated. Download both PEM files now." }); - } catch (error) { - setNotice({ kind: "error", text: apiMessage(error) }); - } finally { - setWorking(false); - } - } - - return ( -
- - - -
-
-

Private key password

- - -
    - {checks.map((check) => ( -
  • -
  • - ))} -
- - -
-
-

Downloads

- {keys ? ( -
- - -
- ) : ( -

Generated PEM files will appear here for immediate download.

- )} -
-
-
- ); -} - -function InspectKeyView({ health }: { health: Health }) { - const [keyFile, setKeyFile] = useState(null); - const keyInspection = useKeyInspection(keyFile, health.maxPemBytes); - - return ( -
- - -
-
-

Key file

- - {keyInspection.loading && } - -
-
-

Metadata

- {keyInspection.result ? ( -
- {Object.entries(keyInspection.result.display).map(([label, value]) => ( - - ))} -
- ) : ( -

Supported key metadata will appear here.

- )} -
-
-
- ); -} - -export default App; diff --git a/web/src/api.ts b/web/src/api/client.ts similarity index 77% rename from web/src/api.ts rename to web/src/api/client.ts index ba32d30..9627710 100644 --- a/web/src/api.ts +++ b/web/src/api/client.ts @@ -1,47 +1,4 @@ -export type Health = { - ok: boolean; - backendReady: boolean; - backendMessage: string; - formatVersion: number; - kem: string; - kemComponent: string; - configuredKem: string; - dem: string; - maxFileBytes: number; - maxEncryptedFileBytes: number; - maxPemBytes: number; - apiToken: string; - passwordPolicy: { - minChars: number; - minUniqueChars: number; - }; -}; - -export type KeyInspectResult = { - ok: boolean; - keyInfo: { - kem: string; - key_type: "public" | "private"; - private_key_encrypted?: boolean; - private_key_format_version?: number; - private_key_kdf?: string; - }; - display: Record; -}; - -export type GeneratedKeys = { - ok: boolean; - kem: string; - publicPem: string; - privatePem: string; - publicFilename: string; - privateFilename: string; -}; - -export type DownloadResult = { - blob: Blob; - filename: string; -}; +import type { DownloadResult, GeneratedKeys, Health, KeyInspectResult } from "./contracts"; type ApiErrorPayload = { ok: false; @@ -138,28 +95,37 @@ export async function fetchHealth(): Promise { return healthRequest; } -export async function inspectKey(file: File): Promise { +export async function inspectKey(file: File, signal?: AbortSignal): Promise { const form = new FormData(); form.append("key", file); - const response = await fetchWithApiToken("/api/keys/inspect", { method: "POST", body: form }); + const response = await fetchWithApiToken("/api/keys/inspect", { + method: "POST", + body: form, + signal + }); if (!response.ok) await parseError(response); return (await response.json()) as KeyInspectResult; } -export async function generateKeys(password: string): Promise { +export async function generateKeys(password: string, signal?: AbortSignal): Promise { const form = new FormData(); form.append("password", password); - const response = await fetchWithApiToken("/api/keys/generate", { method: "POST", body: form }); + const response = await fetchWithApiToken("/api/keys/generate", { method: "POST", body: form, signal }); if (!response.ok) await parseError(response); return (await response.json()) as GeneratedKeys; } -export async function encryptFile(file: File, publicKey: File, outputFilename: string): Promise { +export async function encryptFile( + file: File, + publicKey: File, + outputFilename: string, + signal?: AbortSignal +): Promise { const form = new FormData(); form.append("file", file); form.append("public_key", publicKey); form.append("output_filename", outputFilename); - const response = await fetchWithApiToken("/api/files/encrypt", { method: "POST", body: form }); + const response = await fetchWithApiToken("/api/files/encrypt", { method: "POST", body: form, signal }); if (!response.ok) await parseError(response); return { blob: await response.blob(), @@ -171,14 +137,15 @@ export async function decryptFile( file: File, privateKey: File, password: string, - outputFilename: string + outputFilename: string, + signal?: AbortSignal ): Promise { const form = new FormData(); form.append("file", file); form.append("private_key", privateKey); form.append("password", password); form.append("output_filename", outputFilename); - const response = await fetchWithApiToken("/api/files/decrypt", { method: "POST", body: form }); + const response = await fetchWithApiToken("/api/files/decrypt", { method: "POST", body: form, signal }); if (!response.ok) await parseError(response); return { blob: await response.blob(), diff --git a/web/src/api/contracts.ts b/web/src/api/contracts.ts new file mode 100644 index 0000000..4aae2a1 --- /dev/null +++ b/web/src/api/contracts.ts @@ -0,0 +1,68 @@ +export type CapabilityName = "inspect" | "generate" | "encrypt" | "decrypt"; + +export type Capability = { + available: boolean; + reason: string; +}; + +export type Health = { + ok: boolean; + backendReady: boolean; + backendMessage: string; + capabilities: Record; + formatVersion: number; + kem: string; + kemComponent: string; + configuredKem: string; + dem: string; + maxFileBytes: number; + maxEncryptedFileBytes: number; + maxPemBytes: number; + apiToken: string; + passwordPolicy: { + minChars: number; + minUniqueChars: number; + }; +}; + +export type KeyInspectResult = { + ok: boolean; + keyInfo: { + kem: string; + key_type: "public" | "private"; + private_key_encrypted?: boolean; + private_key_format_version?: number; + private_key_kdf?: string; + }; + display: Record; +}; + +export type GeneratedKeys = { + ok: boolean; + kem: string; + publicPem: string; + privatePem: string; + publicFilename: string; + privateFilename: string; +}; + +export type DownloadResult = { + blob: Blob; + filename: string; +}; + +export type InspectKeyOperation = (file: File, signal?: AbortSignal) => Promise; +export type GenerateKeysOperation = (password: string, signal?: AbortSignal) => Promise; +export type EncryptFileOperation = ( + file: File, + publicKey: File, + outputFilename: string, + signal?: AbortSignal +) => Promise; +export type DecryptFileOperation = ( + file: File, + privateKey: File, + password: string, + outputFilename: string, + signal?: AbortSignal +) => Promise; diff --git a/web/src/api/errors.ts b/web/src/api/errors.ts new file mode 100644 index 0000000..68c278a --- /dev/null +++ b/web/src/api/errors.ts @@ -0,0 +1,18 @@ +import { ApiError } from "./client"; + +const LOCAL_SERVICE_UNAVAILABLE = "Could not reach the local service. Check that it is running and try again."; + +export function isAbortError(error: unknown): boolean { + return error instanceof DOMException + ? error.name === "AbortError" + : error instanceof Error && error.name === "AbortError"; +} + +export function safeOperationError(error: unknown, fallback: string): string { + if (error instanceof ApiError) { + if (error.status < 500 || error.code === "backend_unavailable") return error.message; + return fallback; + } + if (error instanceof TypeError) return LOCAL_SERVICE_UNAVAILABLE; + return fallback; +} diff --git a/web/src/api/index.ts b/web/src/api/index.ts new file mode 100644 index 0000000..589823a --- /dev/null +++ b/web/src/api/index.ts @@ -0,0 +1,13 @@ +export { ApiError, decryptFile, encryptFile, fetchHealth, generateKeys, inspectKey } from "./client"; +export type { + Capability, + CapabilityName, + DecryptFileOperation, + DownloadResult, + EncryptFileOperation, + GeneratedKeys, + GenerateKeysOperation, + Health, + InspectKeyOperation, + KeyInspectResult +} from "./contracts"; diff --git a/web/src/app/App.test.tsx b/web/src/app/App.test.tsx new file mode 100644 index 0000000..9c4c4c1 --- /dev/null +++ b/web/src/app/App.test.tsx @@ -0,0 +1,130 @@ +import { StrictMode } from "react"; +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { READY_HEALTH } from "../test/fixtures"; +import App from "./App"; + +const client = vi.hoisted(() => ({ + fetchHealth: vi.fn(), + generateKeys: vi.fn() +})); + +vi.mock("../api/client", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + fetchHealth: client.fetchHealth, + generateKeys: client.generateKeys + }; +}); + +async function openGeneratedKeys(user: ReturnType) { + await screen.findByRole("heading", { name: "Encrypt a file" }); + await user.click(screen.getByRole("button", { name: "Generate keys" })); + await screen.findByRole("heading", { name: "Generate keys" }); + await user.type(screen.getByLabelText("Private key password"), "correct horse battery staple"); + await user.type(screen.getByLabelText("Confirm private key password"), "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + await screen.findByRole("button", { name: "Download public key" }); +} + +beforeEach(() => { + client.fetchHealth.mockReset(); + client.fetchHealth.mockResolvedValue(READY_HEALTH); + client.generateKeys.mockReset(); + client.generateKeys.mockResolvedValue({ + ok: true, + kem: READY_HEALTH.kem, + publicPem: "PUBLIC-PEM", + privatePem: "ENCRYPTED-PRIVATE-PEM", + publicFilename: "recipient-public.pem", + privateFilename: "recipient-private.pem" + }); +}); + +describe("App", () => { + it("starts on file encryption and switches to key inspection", async () => { + const user = userEvent.setup(); + + render(); + + expect(await screen.findByRole("heading", { name: "Encrypt a file" })).toBeVisible(); + await user.click(screen.getByRole("button", { name: "Inspect key" })); + + expect(await screen.findByRole("heading", { name: "Inspect a key" })).toBeVisible(); + }); + + it("coalesces the initial health request in StrictMode while workflows stay unmounted", async () => { + let resolveHealth: (health: typeof READY_HEALTH) => void = () => undefined; + const pendingHealth = new Promise((resolve) => { + resolveHealth = resolve; + }); + client.fetchHealth.mockReturnValue(pendingHealth); + + render( + + + + ); + + expect(client.fetchHealth).toHaveBeenCalledTimes(1); + expect(screen.getByRole("status")).toHaveTextContent("Loading local engine status."); + expect(screen.queryByRole("heading", { name: "Encrypt a file" })).not.toBeInTheDocument(); + + resolveHealth(READY_HEALTH); + + expect(await screen.findByRole("heading", { name: "Encrypt a file" })).toBeVisible(); + }); + + it("retries a failed health request with a fresh request and safe recovery", async () => { + client.fetchHealth.mockRejectedValueOnce(new Error("raw backend connection details")); + client.fetchHealth.mockResolvedValueOnce(READY_HEALTH); + const user = userEvent.setup(); + + render(); + + expect( + await screen.findByText("The local engine status could not be loaded. Restart the app and try again.") + ).toBeVisible(); + expect(screen.getByRole("button", { name: "Retry" })).toBeEnabled(); + expect(screen.queryByText("raw backend connection details")).not.toBeInTheDocument(); + + await user.click(screen.getByRole("button", { name: "Retry" })); + + expect(client.fetchHealth).toHaveBeenCalledTimes(2); + expect(await screen.findByRole("heading", { name: "Encrypt a file" })).toBeVisible(); + }); + + it("keeps generated keys active when leaving is cancelled", async () => { + const user = userEvent.setup(); + const confirm = vi.spyOn(window, "confirm").mockReturnValue(false); + + render(); + await openGeneratedKeys(user); + await user.click(screen.getByRole("button", { name: "Inspect key" })); + + expect(confirm).toHaveBeenCalledWith("Generated keys are still available. Leave this workflow and clear them?"); + expect(screen.getByRole("heading", { name: "Generate keys" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Download public key" })).toBeVisible(); + }); + + it("clears generated-key state before leaving after confirmation", async () => { + const user = userEvent.setup(); + const confirm = vi.spyOn(window, "confirm").mockReturnValue(true); + + render(); + await openGeneratedKeys(user); + await user.click(screen.getByRole("button", { name: "Inspect key" })); + + expect(confirm).toHaveBeenCalledWith("Generated keys are still available. Leave this workflow and clear them?"); + expect(await screen.findByRole("heading", { name: "Inspect a key" })).toBeVisible(); + + await user.click(screen.getByRole("button", { name: "Generate keys" })); + await screen.findByRole("heading", { name: "Generate keys" }); + await user.click(screen.getByRole("button", { name: "Encrypt" })); + + await waitFor(() => expect(screen.getByRole("heading", { name: "Encrypt a file" })).toBeVisible()); + expect(confirm).toHaveBeenCalledTimes(1); + }); +}); diff --git a/web/src/app/App.tsx b/web/src/app/App.tsx new file mode 100644 index 0000000..1cb7e03 --- /dev/null +++ b/web/src/app/App.tsx @@ -0,0 +1,84 @@ +import { useCallback, useEffect, useRef, useState } from "react"; +import { fetchHealth } from "../api/client"; +import type { Health } from "../api/contracts"; +import { DecryptWorkflow } from "../features/decrypt/DecryptWorkflow"; +import { EncryptWorkflow } from "../features/encrypt/EncryptWorkflow"; +import { GenerateKeysWorkflow } from "../features/generate/GenerateKeysWorkflow"; +import { InspectKeyWorkflow } from "../features/inspect/InspectKeyWorkflow"; +import { AppShell } from "./AppShell"; +import type { View } from "./navigation"; + +const SENSITIVE_RESULT_CONFIRMATION = "Generated keys are still available. Leave this workflow and clear them?"; + +export default function App() { + const [activeView, setActiveView] = useState("encrypt"); + const [health, setHealth] = useState(null); + const [healthError, setHealthError] = useState(null); + const [hasGeneratedKeys, setHasGeneratedKeys] = useState(false); + const healthRequestId = useRef(0); + const initialHealthRequest = useRef | null>(null); + + const loadHealth = useCallback(async (retry = false) => { + const requestId = healthRequestId.current + 1; + healthRequestId.current = requestId; + setHealth(null); + setHealthError(null); + const request = retry + ? fetchHealth() + : (initialHealthRequest.current ?? (initialHealthRequest.current = fetchHealth())); + + try { + const nextHealth = await request; + if (requestId === healthRequestId.current) setHealth(nextHealth); + } catch { + if (requestId === healthRequestId.current) { + setHealthError("The local engine status could not be loaded. Restart the app and try again."); + } + } + }, []); + + useEffect(() => { + void loadHealth(); + return () => { + healthRequestId.current += 1; + }; + }, [loadHealth]); + + function navigate(nextView: View) { + if (nextView === activeView) return; + if (activeView === "generate" && hasGeneratedKeys) { + if (!window.confirm(SENSITIVE_RESULT_CONFIRMATION)) return; + setHasGeneratedKeys(false); + } + setActiveView(nextView); + } + + if (!health) { + return ( +
+ {healthError ? ( + <> +

Local engine unavailable

+

{healthError}

+ + + ) : ( +

Loading local engine status.

+ )} +
+ ); + } + + return ( + + {activeView === "encrypt" && } + {activeView === "decrypt" && } + {activeView === "generate" && ( + + )} + {activeView === "inspect" && } + + ); +} diff --git a/web/src/app/AppShell.test.tsx b/web/src/app/AppShell.test.tsx new file mode 100644 index 0000000..17ee297 --- /dev/null +++ b/web/src/app/AppShell.test.tsx @@ -0,0 +1,59 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { expect, it, vi } from "vitest"; +import { READY_HEALTH } from "../test/fixtures"; +import { AppShell } from "./AppShell"; + +it("exposes semantic navigation and changes workflows", async () => { + const user = userEvent.setup(); + const onNavigate = vi.fn(); + + render( + +

Encrypt a file

+
+ ); + + expect(screen.getByRole("navigation", { name: "Workflows" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Encrypt" })).toHaveAttribute("aria-current", "page"); + + await user.click(screen.getByRole("button", { name: "Decrypt" })); + + expect(onNavigate).toHaveBeenCalledWith("decrypt"); + expect(screen.getByText("Local engine")).toBeVisible(); +}); + +it("keeps a supplied availability reason in capability details", () => { + const health = { + ...READY_HEALTH, + capabilities: { + ...READY_HEALTH.capabilities, + encrypt: { + available: true, + reason: "Uses the device-bound crypto provider." + } + } + }; + + render( + undefined}> +

Encrypt a file

+
+ ); + + expect(screen.getAllByText("Uses the device-bound crypto provider.")).toHaveLength(2); +}); + +it("places narrow-layout workflow navigation before the main content in keyboard order", () => { + render( + undefined}> +

Encrypt a file

+
+ ); + + const mobileNavigation = screen.getByRole("navigation", { name: "Mobile workflows" }); + const main = screen.getByRole("main"); + + expect(mobileNavigation.compareDocumentPosition(main) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy(); + expect(mobileNavigation).toContainElement(screen.getByRole("link", { name: "Encrypt" })); +}); diff --git a/web/src/app/AppShell.tsx b/web/src/app/AppShell.tsx new file mode 100644 index 0000000..68c5567 --- /dev/null +++ b/web/src/app/AppShell.tsx @@ -0,0 +1,99 @@ +import type { ReactNode } from "react"; +import type { Health } from "../api"; +import { CapabilityStatus } from "../components/CapabilityStatus"; +import "../styles/components.css"; +import { NAV_ITEMS, type View } from "./navigation"; + +export type AppShellProps = { + activeView: View; + health: Health; + onNavigate: (view: View) => void; + children: ReactNode; +}; + +function Brand() { + return ( +
+ + + Quantum Encryptor + Local file security + +
+ ); +} + +function RailNavigation({ activeView, onNavigate }: Pick) { + return ( + + ); +} + +function HeaderNavigation({ activeView, health, onNavigate }: Omit) { + return ( +
+ + + +
+ ); +} + +function MobileNavigation({ activeView, onNavigate }: Pick) { + return ( +
+ ); +} + +export function AppShell({ activeView, health, onNavigate, children }: AppShellProps) { + return ( +
+ + + +
{children}
+
+ ); +} diff --git a/web/src/app/navigation.ts b/web/src/app/navigation.ts new file mode 100644 index 0000000..d1b922d --- /dev/null +++ b/web/src/app/navigation.ts @@ -0,0 +1,8 @@ +export type View = "encrypt" | "decrypt" | "generate" | "inspect"; + +export const NAV_ITEMS: ReadonlyArray<{ id: View; label: string }> = [ + { id: "encrypt", label: "Encrypt" }, + { id: "decrypt", label: "Decrypt" }, + { id: "generate", label: "Generate keys" }, + { id: "inspect", label: "Inspect key" } +]; diff --git a/web/src/components/ActionButton.tsx b/web/src/components/ActionButton.tsx new file mode 100644 index 0000000..1649449 --- /dev/null +++ b/web/src/components/ActionButton.tsx @@ -0,0 +1,14 @@ +import type { ButtonHTMLAttributes } from "react"; + +export type ActionButtonProps = ButtonHTMLAttributes & { + busy?: boolean; + busyLabel: string; +}; + +export function ActionButton({ busy = false, busyLabel, children, disabled, ...props }: ActionButtonProps) { + return ( + + ); +} diff --git a/web/src/components/CapabilityStatus.tsx b/web/src/components/CapabilityStatus.tsx new file mode 100644 index 0000000..1225722 --- /dev/null +++ b/web/src/components/CapabilityStatus.tsx @@ -0,0 +1,60 @@ +import type { Health } from "../api"; + +type CapabilityStatusProps = { + health: Health; + compact?: boolean; +}; + +const capabilityLabels = { + encrypt: "Encrypt", + decrypt: "Decrypt", + generate: "Generate keys", + inspect: "Inspect key" +} as const; + +function availabilityLabel(available: number): "Ready" | "Limited" | "Unavailable" { + if (available === 4) return "Ready"; + if (available === 0) return "Unavailable"; + return "Limited"; +} + +export function CapabilityStatus({ health, compact = false }: CapabilityStatusProps) { + const available = Object.values(health.capabilities).filter((capability) => capability.available).length; + const status = availabilityLabel(available); + const statusClass = status.toLowerCase(); + + return ( +
+

+

+
+ Capability details +
    + {(Object.keys(capabilityLabels) as Array).map((operation) => { + const capability = health.capabilities[operation]; + const reason = capability.reason || (capability.available ? "Available" : "Unavailable"); + return ( +
  • + {capabilityLabels[operation]} + {reason} +
  • + ); + })} +
+
+
+ ); +} diff --git a/web/src/components/FilePicker.tsx b/web/src/components/FilePicker.tsx new file mode 100644 index 0000000..ef1e8a6 --- /dev/null +++ b/web/src/components/FilePicker.tsx @@ -0,0 +1,69 @@ +import type { ChangeEvent, DragEvent } from "react"; +import { formatBytes } from "../lib/format"; + +export type FilePickerProps = { + id: string; + label: string; + hint: string; + accept?: string; + file: File | null; + error?: string; + disabled?: boolean; + onFile: (file: File | null) => void; +}; + +export function FilePicker({ id, label, hint, accept, file, error, disabled = false, onFile }: FilePickerProps) { + const descriptionId = `${id}-description`; + const errorId = `${id}-error`; + const describedBy = error ? `${descriptionId} ${errorId}` : descriptionId; + + function selectFile(event: ChangeEvent) { + if (disabled) return; + onFile(event.target.files?.item(0) ?? null); + } + + function allowDrop(event: DragEvent) { + event.preventDefault(); + } + + function dropFile(event: DragEvent) { + event.preventDefault(); + if (disabled) return; + onFile(event.dataTransfer.files.item(0) ?? null); + } + + return ( +
+ +

+ {hint} +

+ {error && ( + + )} +
+ ); +} diff --git a/web/src/components/Notice.tsx b/web/src/components/Notice.tsx new file mode 100644 index 0000000..61fa12a --- /dev/null +++ b/web/src/components/Notice.tsx @@ -0,0 +1,18 @@ +import type { ReactNode } from "react"; + +export type NoticeKind = "info" | "success" | "warning" | "error"; + +export type NoticeProps = { + kind: NoticeKind; + title?: string; + children: ReactNode; +}; + +export function Notice({ kind, title, children }: NoticeProps) { + return ( +
+ {title && {title}} +
{children}
+
+ ); +} diff --git a/web/src/components/PasswordField.tsx b/web/src/components/PasswordField.tsx new file mode 100644 index 0000000..f388fee --- /dev/null +++ b/web/src/components/PasswordField.tsx @@ -0,0 +1,35 @@ +import { useState } from "react"; + +export type PasswordFieldProps = { + id: string; + label: string; + value: string; + autoComplete: "new-password" | "current-password"; + describedBy?: string; + disabled?: boolean; + onChange: (value: string) => void; +}; + +export function PasswordField({ id, label, value, autoComplete, describedBy, disabled = false, onChange }: PasswordFieldProps) { + const [visible, setVisible] = useState(false); + + return ( +
+ +
+ onChange(event.target.value)} + type={visible ? "text" : "password"} + value={value} + /> + +
+
+ ); +} diff --git a/web/src/components/TechnicalDetails.tsx b/web/src/components/TechnicalDetails.tsx new file mode 100644 index 0000000..d7dff16 --- /dev/null +++ b/web/src/components/TechnicalDetails.tsx @@ -0,0 +1,14 @@ +import type { ReactNode } from "react"; + +export type TechnicalDetailsProps = { + children: ReactNode; +}; + +export function TechnicalDetails({ children }: TechnicalDetailsProps) { + return ( +
+ Technical details +
{children}
+
+ ); +} diff --git a/web/src/components/WorkflowLayout.tsx b/web/src/components/WorkflowLayout.tsx new file mode 100644 index 0000000..d1a5817 --- /dev/null +++ b/web/src/components/WorkflowLayout.tsx @@ -0,0 +1,39 @@ +import type { ReactNode } from "react"; +import type { Capability } from "../api"; +import type { WorkflowPhase } from "../lib/workflow"; +import { Notice } from "./Notice"; + +export type WorkflowLayoutProps = { + title: string; + description: string; + phase: WorkflowPhase; + capability: Capability; + busy?: boolean; + children: ReactNode; +}; + +const phaseLabels: Record = { + select: "Select", + review: "Review", + complete: "Complete" +}; + +export function WorkflowLayout({ title, description, phase, capability, busy = false, children }: WorkflowLayoutProps) { + return ( +
+
+

{title}

+

{description}

+
+
    + {(Object.keys(phaseLabels) as WorkflowPhase[]).map((value) => ( +
  1. + {phaseLabels[value]} +
  2. + ))} +
+ {!capability.available && {capability.reason}} +
{children}
+
+ ); +} diff --git a/web/src/components/components.test.tsx b/web/src/components/components.test.tsx new file mode 100644 index 0000000..0364ce9 --- /dev/null +++ b/web/src/components/components.test.tsx @@ -0,0 +1,83 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; +import { FilePicker } from "./FilePicker"; +import { PasswordField } from "./PasswordField"; +import { TechnicalDetails } from "./TechnicalDetails"; + +describe("shared controls", () => { + it("selects a file through the labeled native input", async () => { + const user = userEvent.setup(); + const onFile = vi.fn(); + render( + + ); + const file = new File(["hello"], "hello.txt", { type: "text/plain" }); + await user.upload(screen.getByLabelText("File to protect"), file); + expect(onFile).toHaveBeenCalledWith(file); + }); + + it("displays selected file sizes with the shared binary precision", () => { + const file = new File([new Uint8Array(1024)], "key.pem", { type: "application/x-pem-file" }); + render( + undefined} + /> + ); + expect(screen.getByText("key.pem · 1.00 KiB")).toBeVisible(); + }); + + it("keeps the visually hidden native file input in keyboard focus order", async () => { + const user = userEvent.setup(); + render( + undefined} + /> + ); + + await user.tab(); + + expect(screen.getByLabelText("Keyboard file")).toHaveFocus(); + }); + + it("announces password visibility through the button label", async () => { + const user = userEvent.setup(); + render( + undefined} + autoComplete="current-password" + /> + ); + await user.click(screen.getByRole("button", { name: "Show password" })); + expect(screen.getByLabelText("Private key password")).toHaveAttribute("type", "text"); + expect(screen.getByRole("button", { name: "Hide password" })).toBeVisible(); + }); + + it("uses a native disclosure with accurate expanded state", async () => { + const user = userEvent.setup(); + render( + + ML-KEM-768 + X25519 + + ); + await user.click(screen.getByText("Technical details")); + expect(screen.getByText("ML-KEM-768 + X25519")).toBeVisible(); + }); +}); diff --git a/web/src/features/decrypt/DecryptWorkflow.test.tsx b/web/src/features/decrypt/DecryptWorkflow.test.tsx new file mode 100644 index 0000000..a62bf6e --- /dev/null +++ b/web/src/features/decrypt/DecryptWorkflow.test.tsx @@ -0,0 +1,306 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; +import { ApiError } from "../../api"; +import { READY_HEALTH } from "../../test/fixtures"; +import { DecryptWorkflow } from "./DecryptWorkflow"; + +type Deferred = { + promise: Promise; + resolve: (value: T) => void; +}; + +function deferred(): Deferred { + let resolve!: (value: T) => void; + const promise = new Promise((resolvePromise) => { + resolve = resolvePromise; + }); + return { promise, resolve }; +} + +function privateKeyInspection() { + return { + ok: true, + keyInfo: { + kem: READY_HEALTH.kem, + key_type: "private" as const, + private_key_encrypted: true, + private_key_format_version: 3, + private_key_kdf: "scrypt" + }, + display: { + "Key Type": "Encrypted private key", + "Key Format": "3", + "Key KDF": "scrypt", + Algorithm: READY_HEALTH.kem + } + }; +} + +describe("DecryptWorkflow", () => { + it("decrypts with an inspected private key, saves the suggested filename, and clears the password", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const decrypt = vi.fn().mockResolvedValue({ + filename: "report", + blob: new Blob(["plaintext"]) + }); + const save = vi.fn(); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + expect(await screen.findByText("Supported encrypted private key; match not yet verified")).toBeVisible(); + + const password = screen.getByLabelText("Private key password"); + await user.type(password, "correct horse battery staple"); + expect(screen.getByLabelText("Output filename")).toHaveValue("report"); + + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + + await waitFor(() => + expect(decrypt).toHaveBeenCalledWith( + expect.objectContaining({ name: "report_encrypted.pqc" }), + expect.objectContaining({ name: "recipient_private.pem" }), + "correct horse battery staple", + "report", + expect.any(AbortSignal) + ) + ); + expect(save).toHaveBeenCalledWith(expect.objectContaining({ filename: "report" })); + expect(password).toHaveValue(""); + }); + + it("reports a browser download failure separately and still clears the password", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const decrypt = vi.fn().mockResolvedValue({ filename: "report", blob: new Blob(["plaintext"]) }); + const save = vi.fn(() => { + throw new TypeError("browser download failed"); + }); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + const password = screen.getByLabelText("Private key password"); + await user.type(password, "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + + expect( + await screen.findByText("The file was decrypted, but the download could not start. Try decrypting it again.") + ).toBeVisible(); + expect(screen.queryByText(/could not reach the local service/i)).not.toBeInTheDocument(); + expect(password).toHaveValue(""); + }); + + it("uses a safe authentication failure message without singling out a secret", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const decrypt = vi.fn().mockRejectedValue( + new ApiError( + 400, + "decryption_failed", + "Decryption failed. Check the private key, password, and encrypted file integrity." + ) + ); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + const password = screen.getByLabelText("Private key password"); + await user.type(password, "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + + expect( + await screen.findByText("The file could not be authenticated. Check the encrypted file, private key, and password.") + ).toBeVisible(); + expect(screen.queryByText(/decryption failed\. check/i)).not.toBeInTheDocument(); + expect(password).toHaveValue("correct horse battery staple"); + }); + + it("locks every causal input while a decryption request is in flight", async () => { + const inspection = vi.fn().mockResolvedValue(privateKeyInspection()); + const request = deferred<{ filename: string; blob: Blob }>(); + const decrypt = vi.fn().mockReturnValue(request.promise); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + const password = screen.getByLabelText("Private key password"); + await user.type(password, "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + await waitFor(() => expect(decrypt).toHaveBeenCalledTimes(1)); + + expect(screen.getByLabelText("Encrypted file")).toBeDisabled(); + expect(screen.getByLabelText("Private key")).toBeDisabled(); + expect(password).toBeDisabled(); + expect(screen.getByLabelText("Output filename")).toBeDisabled(); + await user.type(password, "x"); + expect(password).toHaveValue("correct horse battery staple"); + + request.resolve({ filename: "report", blob: new Blob(["plaintext"]) }); + }); + + it("clears a completed decryption outcome when the password changes while idle", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const decrypt = vi.fn().mockResolvedValue({ filename: "report", blob: new Blob(["plaintext"]) }); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + const password = screen.getByLabelText("Private key password"); + await user.type(password, "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + expect(await screen.findByText("Saved report.")).toBeVisible(); + + await user.type(password, "new"); + + expect(screen.queryByText("Saved report.")).not.toBeInTheDocument(); + expect(screen.queryByText("File decrypted")).not.toBeInTheDocument(); + }); + + it("hides inspection failure details while keeping decryption unavailable", async () => { + const inspect = vi.fn().mockRejectedValue(new Error("private parser detail: /secret/path/key.pem")); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + + expect(await screen.findByText("The private key could not be inspected.")).toBeVisible(); + expect(screen.queryByText(/private parser detail/i)).not.toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Decrypt file" })).toBeDisabled(); + }); + + it("rejects oversized encrypted files locally before decryption", async () => { + const health = { ...READY_HEALTH, maxEncryptedFileBytes: 3 }; + const decrypt = vi.fn(); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["four"], "report_encrypted.pqc")); + + expect(screen.getByText("This encrypted file exceeds the 3 byte limit.")).toBeVisible(); + expect(screen.getByRole("button", { name: "Decrypt file" })).toBeDisabled(); + expect(decrypt).not.toHaveBeenCalled(); + }); + + it("accepts a legacy private key classification without rejecting its suite before authentication", async () => { + const inspect = vi.fn().mockResolvedValue({ + ...privateKeyInspection(), + keyInfo: { + ...privateKeyInspection().keyInfo, + kem: "ML-KEM-768+X25519" + } + }); + const decrypt = vi.fn().mockResolvedValue({ filename: "report", blob: new Blob(["plaintext"]) }); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + await user.type(screen.getByLabelText("Private key password"), "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + + await waitFor(() => expect(decrypt).toHaveBeenCalledTimes(1)); + }); + + it("does not claim a selected container version or pre-authentication key match", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("Encrypted file"), new File(["legacy"], "archive.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "archive-private.pem")); + + expect(await screen.findByText("Supported encrypted private key; match not yet verified")).toBeVisible(); + expect(screen.queryByText("Compatible private key")).not.toBeInTheDocument(); + expect(screen.queryByText("File format version")).not.toBeInTheDocument(); + }); + + it("aborts an in-flight decryption request on unmount", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const decrypt = vi.fn( + (_file: File, _privateKey: File, _password: string, _outputFilename: string, _signal?: AbortSignal) => + new Promise<{ filename: string; blob: Blob }>(() => undefined) + ); + const user = userEvent.setup(); + const { unmount } = render( + + ); + + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + await user.type(screen.getByLabelText("Private key password"), "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + await waitFor(() => expect(decrypt).toHaveBeenCalledTimes(1)); + const signal = decrypt.mock.calls[0]?.[4] as AbortSignal; + + unmount(); + + expect(signal.aborted).toBe(true); + }); + + it("preserves backend and invalid-key guidance while distinguishing network failure", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const user = userEvent.setup(); + const renderFailure = async (failure: unknown) => { + const decrypt = vi.fn().mockRejectedValue(failure); + const rendered = render( + + ); + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + await user.type(screen.getByLabelText("Private key password"), "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + return rendered; + }; + + let rendered = await renderFailure(new ApiError(503, "backend_unavailable", "Post-quantum backend is not ready.")); + expect(await screen.findByText("Post-quantum backend is not ready.")).toBeVisible(); + rendered.unmount(); + + rendered = await renderFailure( + new ApiError(400, "invalid_private_key", "Upload a supported encrypted PQC private key PEM file.") + ); + expect(await screen.findByText("Upload a supported encrypted PQC private key PEM file.")).toBeVisible(); + rendered.unmount(); + + await renderFailure(new TypeError("fetch failed: private socket detail")); + expect(await screen.findByText("Could not reach the local service. Check that it is running and try again.")).toBeVisible(); + expect(screen.queryByText(/private socket detail/i)).not.toBeInTheDocument(); + }); + + it("does not render an AbortError as a decryption failure", async () => { + const inspect = vi.fn().mockResolvedValue(privateKeyInspection()); + const aborted = new Error("request aborted"); + aborted.name = "AbortError"; + const decrypt = vi.fn().mockRejectedValue(aborted); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("Encrypted file"), new File(["ciphertext"], "report_encrypted.pqc")); + await user.upload(screen.getByLabelText("Private key"), new File(["PEM"], "recipient_private.pem")); + await screen.findByText("Supported encrypted private key; match not yet verified"); + await user.type(screen.getByLabelText("Private key password"), "correct horse battery staple"); + await user.click(screen.getByRole("button", { name: "Decrypt file" })); + + await waitFor(() => expect(screen.getByRole("button", { name: "Decrypt file" })).toBeEnabled()); + expect(screen.queryByText("Decryption failed")).not.toBeInTheDocument(); + }); +}); diff --git a/web/src/features/decrypt/DecryptWorkflow.tsx b/web/src/features/decrypt/DecryptWorkflow.tsx new file mode 100644 index 0000000..49a4316 --- /dev/null +++ b/web/src/features/decrypt/DecryptWorkflow.tsx @@ -0,0 +1,298 @@ +import { useEffect, useMemo, useRef, useState, type FormEvent } from "react"; +import { + ApiError, + decryptFile, + type DecryptFileOperation, + type DownloadResult, + type Health, + type InspectKeyOperation +} from "../../api"; +import { isAbortError, safeOperationError } from "../../api/errors"; +import { ActionButton } from "../../components/ActionButton"; +import { FilePicker } from "../../components/FilePicker"; +import { Notice } from "../../components/Notice"; +import { PasswordField } from "../../components/PasswordField"; +import { TechnicalDetails } from "../../components/TechnicalDetails"; +import { WorkflowLayout } from "../../components/WorkflowLayout"; +import { useKeyInspection } from "../../hooks/useKeyInspection"; +import { downloadBlob } from "../../lib/download"; +import { suggestedDecryptedName } from "../../lib/filenames"; +import { formatBytes } from "../../lib/format"; +import { deriveWorkflowPhase } from "../../lib/workflow"; + +export type DecryptWorkflowProps = { + health: Health; + inspect?: InspectKeyOperation; + decrypt?: DecryptFileOperation; + save?: (result: DownloadResult) => void; +}; + +function limitMessage(label: string, maxBytes: number): string { + return `${label} exceeds the ${maxBytes.toLocaleString()} byte limit.`; +} + +function keyFormat(inspection: ReturnType["result"]): string { + const version = inspection?.keyInfo.private_key_format_version; + return version === undefined ? "Not available" : String(version); +} + +const AUTHENTICATION_ERROR_CODES = new Set(["decryption_failed", "private_key_failed"]); +const AUTHENTICATION_FAILURE = + "The file could not be authenticated. Check the encrypted file, private key, and password."; + +function decryptionError(caught: unknown): string { + if (caught instanceof ApiError && AUTHENTICATION_ERROR_CODES.has(caught.code)) return AUTHENTICATION_FAILURE; + return safeOperationError(caught, "The local service could not complete decryption. Try again."); +} + +export function DecryptWorkflow({ + health, + inspect, + decrypt = decryptFile, + save = downloadBlob +}: DecryptWorkflowProps) { + const [file, setFile] = useState(null); + const [privateKey, setPrivateKey] = useState(null); + const [password, setPassword] = useState(""); + const [outputFilename, setOutputFilename] = useState(""); + const [error, setError] = useState(null); + const [completedFilename, setCompletedFilename] = useState(null); + const [busy, setBusy] = useState(false); + const mountedRef = useRef(true); + const requestIdRef = useRef(0); + const inFlightRef = useRef(false); + const abortControllerRef = useRef(null); + const capability = health.capabilities.decrypt; + const { result: inspection, error: inspectionError, loading: inspecting } = useKeyInspection( + capability.available ? privateKey : null, + health.maxPemBytes, + inspect + ); + const fileError = file && file.size > health.maxEncryptedFileBytes + ? limitMessage("This encrypted file", health.maxEncryptedFileBytes) + : null; + const keyError = privateKey && privateKey.size > health.maxPemBytes + ? limitMessage("This key file", health.maxPemBytes) + : null; + const safeInspectionError = inspectionError ? "The private key could not be inspected." : null; + + const readinessReason = useMemo(() => { + if (!capability.available) return capability.reason; + if (!file) return "Choose an encrypted file."; + if (fileError) return fileError; + if (!privateKey) return "Choose a private key."; + if (keyError) return keyError; + if (inspecting) return "Inspecting private key."; + if (safeInspectionError) return safeInspectionError; + if (!inspection?.ok) return "The private key could not be inspected."; + if (inspection.keyInfo.key_type !== "private") return "A private key is required to decrypt a file."; + if (!password) return "Enter the private key password."; + if (!outputFilename.trim()) return "Enter an output filename."; + return null; + }, [ + capability.available, + capability.reason, + file, + fileError, + inspection, + inspecting, + keyError, + outputFilename, + password, + privateKey, + safeInspectionError + ]); + const canDecrypt = !readinessReason && !busy; + const phase = deriveWorkflowPhase({ + ready: Boolean(canDecrypt), + complete: Boolean(completedFilename) + }); + + useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + requestIdRef.current += 1; + inFlightRef.current = false; + abortControllerRef.current?.abort(); + abortControllerRef.current = null; + }; + }, []); + + function clearOutcome() { + requestIdRef.current += 1; + setError(null); + setCompletedFilename(null); + } + + function selectFile(nextFile: File | null) { + if (busy) return; + setFile(nextFile); + setOutputFilename(suggestedDecryptedName(nextFile)); + clearOutcome(); + } + + function selectPrivateKey(nextFile: File | null) { + if (busy) return; + setPrivateKey(nextFile); + clearOutcome(); + } + + function updateOutputFilename(value: string) { + if (busy) return; + setOutputFilename(value); + clearOutcome(); + } + + function updatePassword(value: string) { + if (busy) return; + setPassword(value); + clearOutcome(); + } + + async function submit(event: FormEvent) { + event.preventDefault(); + if (!canDecrypt || !file || !privateKey || inFlightRef.current) return; + + const requestId = requestIdRef.current + 1; + const controller = new AbortController(); + requestIdRef.current = requestId; + inFlightRef.current = true; + abortControllerRef.current = controller; + setBusy(true); + setError(null); + setCompletedFilename(null); + + try { + const result = await decrypt(file, privateKey, password, outputFilename.trim(), controller.signal); + if (!mountedRef.current || requestId !== requestIdRef.current) return; + setPassword(""); + try { + save(result); + } catch { + setError("The file was decrypted, but the download could not start. Try decrypting it again."); + return; + } + setCompletedFilename(result.filename); + } catch (caught: unknown) { + if (!mountedRef.current || requestId !== requestIdRef.current) return; + if (controller.signal.aborted || isAbortError(caught)) return; + setError(decryptionError(caught)); + } finally { + if (requestId === requestIdRef.current) inFlightRef.current = false; + if (abortControllerRef.current === controller) abortControllerRef.current = null; + if (mountedRef.current && requestId === requestIdRef.current) setBusy(false); + } + } + + const keyClassification = !inspection + ? null + : inspection.keyInfo.key_type === "private" + ? "Supported encrypted private key; match not yet verified" + : "Public key — not valid for decryption"; + + return ( + + {capability.available && ( +
+ + + + {inspecting && Checking safe key metadata locally.} + {safeInspectionError && {safeInspectionError}} + +
+

Review

+
+
+
Encrypted file
+
{file ? file.name : "Not selected"}
+
+
+
Size
+
{file ? formatBytes(file.size) : "Not selected"}
+
+
+
Private key
+
{keyClassification ?? (privateKey ? "Awaiting inspection" : "Not selected")}
+
+
+ +
+ + updateOutputFilename(event.target.value)} + type="text" + value={outputFilename} + /> +
+ {readinessReason && !busy && readinessReason !== fileError && readinessReason !== keyError && readinessReason !== safeInspectionError && ( +

{readinessReason}

+ )} +
+ + + Decrypt file + + + )} + + {error && {error}} + {completedFilename && ( + + Saved {completedFilename}. + + )} + + +
+
+
Key format
+
{keyFormat(inspection)}
+
+
+
Key KDF
+
{inspection?.keyInfo.private_key_kdf ?? "Not available"}
+
+
+
Hybrid suite
+
{inspection?.keyInfo.kem ?? health.kem}
+
+
+
+
+ ); +} diff --git a/web/src/features/encrypt/EncryptWorkflow.test.tsx b/web/src/features/encrypt/EncryptWorkflow.test.tsx new file mode 100644 index 0000000..e59bc0a --- /dev/null +++ b/web/src/features/encrypt/EncryptWorkflow.test.tsx @@ -0,0 +1,238 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; +import { ApiError } from "../../api"; +import { READY_HEALTH } from "../../test/fixtures"; +import { EncryptWorkflow } from "./EncryptWorkflow"; + +function publicKeyInspection() { + return { + ok: true, + keyInfo: { kem: READY_HEALTH.kem, key_type: "public" as const }, + display: { "Key Type": "Public", Algorithm: READY_HEALTH.kem } + }; +} + +async function prepareEncryption(user: ReturnType) { + await user.upload(screen.getByLabelText("File to encrypt"), new File(["report"], "report.pdf")); + await user.upload(screen.getByLabelText("Recipient public key"), new File(["PEM"], "recipient.pem")); + await screen.findByText("Compatible public key"); +} + +describe("EncryptWorkflow", () => { + it("encrypts with a compatible public key and saves the returned file", async () => { + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const encrypt = vi.fn().mockResolvedValue({ + filename: "report_encrypted.pqc", + blob: new Blob(["ciphertext"]) + }); + const save = vi.fn(); + const user = userEvent.setup(); + + render(); + + await user.upload(screen.getByLabelText("File to encrypt"), new File(["report"], "report.pdf")); + await user.upload( + screen.getByLabelText("Recipient public key"), + new File(["PEM"], "recipient.pem", { type: "application/x-pem-file" }) + ); + + expect(await screen.findByText("Compatible public key")).toBeVisible(); + expect(screen.getByLabelText("Output filename")).toHaveValue("report_encrypted.pqc"); + + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + + await waitFor(() => + expect(encrypt).toHaveBeenCalledWith( + expect.objectContaining({ name: "report.pdf" }), + expect.objectContaining({ name: "recipient.pem" }), + "report_encrypted.pqc", + expect.any(AbortSignal) + ) + ); + expect(save).toHaveBeenCalledWith(expect.objectContaining({ filename: "report_encrypted.pqc" })); + expect(await screen.findByText(/saved report_encrypted\.pqc/i)).toBeVisible(); + expect(screen.getByText("New file format version").nextElementSibling).toHaveTextContent("4"); + }); + + it("reports a browser download failure separately from a service failure", async () => { + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const encrypt = vi.fn().mockResolvedValue({ + filename: "report_encrypted.pqc", + blob: new Blob(["ciphertext"]) + }); + const save = vi.fn(() => { + throw new TypeError("browser download failed"); + }); + const user = userEvent.setup(); + + render(); + await prepareEncryption(user); + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + + expect( + await screen.findByText("The file was encrypted, but the download could not start. Try encrypting it again.") + ).toBeVisible(); + expect(screen.queryByText(/could not reach the local service/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/saved report_encrypted\.pqc/i)).not.toBeInTheDocument(); + }); + + it("keeps encryption disabled with a textual reason when the plaintext is oversized", async () => { + const health = { ...READY_HEALTH, maxFileBytes: 3 }; + const encrypt = vi.fn(); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("File to encrypt"), new File(["four"], "report.pdf")); + + expect(screen.getByRole("button", { name: "Encrypt file" })).toBeDisabled(); + expect(screen.getByText(/exceeds the 3 byte limit/i)).toBeVisible(); + expect(encrypt).not.toHaveBeenCalled(); + }); + + it("keeps encryption disabled when inspection finds a private key", async () => { + const inspect = vi.fn().mockResolvedValue({ + ok: true, + keyInfo: { + kem: READY_HEALTH.kem, + key_type: "private" + }, + display: { + "Key Type": "Encrypted private key", + Algorithm: READY_HEALTH.kem + } + }); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("File to encrypt"), new File(["report"], "report.pdf")); + await user.upload(screen.getByLabelText("Recipient public key"), new File(["PEM"], "recipient.pem")); + + expect(await screen.findByText(/a public key is required/i)).toBeVisible(); + expect(screen.getByRole("button", { name: "Encrypt file" })).toBeDisabled(); + }); + + it("does not submit a second encryption request while one is in progress", async () => { + let resolveEncryption: (value: { filename: string; blob: Blob }) => void; + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const encrypt = vi.fn( + (_file: File, _publicKey: File, _outputFilename: string, _signal?: AbortSignal) => + new Promise<{ filename: string; blob: Blob }>((resolve) => { + resolveEncryption = resolve; + }) + ); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("File to encrypt"), new File(["report"], "report.pdf")); + await user.upload(screen.getByLabelText("Recipient public key"), new File(["PEM"], "recipient.pem")); + await screen.findByText("Compatible public key"); + + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + await user.click(screen.getByRole("button", { name: "Encrypting locally" })); + + expect(encrypt).toHaveBeenCalledTimes(1); + expect(screen.getByLabelText("File to encrypt")).toBeDisabled(); + expect(screen.getByLabelText("Recipient public key")).toBeDisabled(); + expect(screen.getByLabelText("Output filename")).toBeDisabled(); + expect(encrypt.mock.calls[0]?.[3]).toBeInstanceOf(AbortSignal); + resolveEncryption!({ filename: "report_encrypted.pqc", blob: new Blob(["ciphertext"]) }); + expect(await screen.findByText(/saved report_encrypted\.pqc/i)).toBeVisible(); + }); + + it("does not accept a public key from a different hybrid suite", async () => { + const inspect = vi.fn().mockResolvedValue({ + ok: true, + keyInfo: { kem: "Kyber768", key_type: "public" }, + display: { "Key Type": "Public", Algorithm: "Kyber768" } + }); + const user = userEvent.setup(); + + render(); + await user.upload(screen.getByLabelText("File to encrypt"), new File(["report"], "report.pdf")); + await user.upload(screen.getByLabelText("Recipient public key"), new File(["PEM"], "recipient.pem")); + + expect(await screen.findByText(/encryption requires ML-KEM-768\+X25519-v2/i)).toBeVisible(); + expect(screen.getByRole("button", { name: "Encrypt file" })).toBeDisabled(); + }); + + it("aborts an in-flight encryption request on unmount", async () => { + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const encrypt = vi.fn( + (_file: File, _publicKey: File, _outputFilename: string, _signal?: AbortSignal) => + new Promise<{ filename: string; blob: Blob }>(() => undefined) + ); + const user = userEvent.setup(); + const { unmount } = render( + + ); + + await prepareEncryption(user); + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + await waitFor(() => expect(encrypt).toHaveBeenCalledTimes(1)); + const signal = encrypt.mock.calls[0]?.[3] as AbortSignal; + + unmount(); + + expect(signal.aborted).toBe(true); + }); + + it("preserves backend guidance and distinguishes network failure", async () => { + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const user = userEvent.setup(); + const backendFailure = vi.fn().mockRejectedValue( + new ApiError(503, "backend_unavailable", "Post-quantum backend is not ready.") + ); + const { unmount } = render( + + ); + + await prepareEncryption(user); + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + expect(await screen.findByText("Post-quantum backend is not ready.")).toBeVisible(); + + unmount(); + const networkFailure = vi.fn().mockRejectedValue(new TypeError("fetch failed: private socket detail")); + render(); + await prepareEncryption(user); + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + + expect(await screen.findByText("Could not reach the local service. Check that it is running and try again.")).toBeVisible(); + expect(screen.queryByText(/private socket detail/i)).not.toBeInTheDocument(); + }); + + it("preserves safe recipient-key guidance from the local API", async () => { + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const encrypt = vi.fn().mockRejectedValue( + new ApiError( + 400, + "legacy_public_key", + "Generate a new ML-KEM-768+X25519-v2 public key for encryption." + ) + ); + const user = userEvent.setup(); + + render(); + await prepareEncryption(user); + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + + expect( + await screen.findByText("Generate a new ML-KEM-768+X25519-v2 public key for encryption.") + ).toBeVisible(); + }); + + it("does not render an AbortError as an encryption failure", async () => { + const inspect = vi.fn().mockResolvedValue(publicKeyInspection()); + const aborted = new Error("request aborted"); + aborted.name = "AbortError"; + const encrypt = vi.fn().mockRejectedValue(aborted); + const user = userEvent.setup(); + + render(); + await prepareEncryption(user); + await user.click(screen.getByRole("button", { name: "Encrypt file" })); + + await waitFor(() => expect(screen.getByRole("button", { name: "Encrypt file" })).toBeEnabled()); + expect(screen.queryByText("Encryption failed")).not.toBeInTheDocument(); + }); +}); diff --git a/web/src/features/encrypt/EncryptWorkflow.tsx b/web/src/features/encrypt/EncryptWorkflow.tsx new file mode 100644 index 0000000..d24e06c --- /dev/null +++ b/web/src/features/encrypt/EncryptWorkflow.tsx @@ -0,0 +1,268 @@ +import { useEffect, useMemo, useRef, useState, type FormEvent } from "react"; +import { + encryptFile, + type DownloadResult, + type EncryptFileOperation, + type Health, + type InspectKeyOperation +} from "../../api"; +import { isAbortError, safeOperationError } from "../../api/errors"; +import { ActionButton } from "../../components/ActionButton"; +import { FilePicker } from "../../components/FilePicker"; +import { Notice } from "../../components/Notice"; +import { TechnicalDetails } from "../../components/TechnicalDetails"; +import { WorkflowLayout } from "../../components/WorkflowLayout"; +import { useKeyInspection } from "../../hooks/useKeyInspection"; +import { downloadBlob } from "../../lib/download"; +import { suggestedEncryptedName } from "../../lib/filenames"; +import { formatBytes } from "../../lib/format"; +import { deriveWorkflowPhase } from "../../lib/workflow"; + +export type EncryptWorkflowProps = { + health: Health; + inspect?: InspectKeyOperation; + encrypt?: EncryptFileOperation; + save?: (result: DownloadResult) => void; +}; + +function limitMessage(label: string, maxBytes: number): string { + return `${label} exceeds the ${maxBytes.toLocaleString()} byte limit.`; +} + +export function EncryptWorkflow({ + health, + inspect, + encrypt = encryptFile, + save = downloadBlob +}: EncryptWorkflowProps) { + const [file, setFile] = useState(null); + const [publicKey, setPublicKey] = useState(null); + const [outputFilename, setOutputFilename] = useState(""); + const [error, setError] = useState(null); + const [completedFilename, setCompletedFilename] = useState(null); + const [busy, setBusy] = useState(false); + const mountedRef = useRef(true); + const requestIdRef = useRef(0); + const inFlightRef = useRef(false); + const abortControllerRef = useRef(null); + const capability = health.capabilities.encrypt; + const { result: inspection, error: inspectionError, loading: inspecting } = useKeyInspection( + capability.available ? publicKey : null, + health.maxPemBytes, + inspect + ); + const fileError = file && file.size > health.maxFileBytes ? limitMessage("This file", health.maxFileBytes) : null; + const keyError = publicKey && publicKey.size > health.maxPemBytes ? limitMessage("This key file", health.maxPemBytes) : null; + const safeInspectionError = inspectionError ? "The recipient key could not be inspected." : null; + const compatiblePublicKey = Boolean( + inspection?.ok && inspection.keyInfo.key_type === "public" && inspection.keyInfo.kem === health.kem + ); + + const readinessReason = useMemo(() => { + if (!capability.available) return capability.reason; + if (!file) return "Choose a file to encrypt."; + if (fileError) return fileError; + if (!publicKey) return "Choose the recipient's public key."; + if (keyError) return keyError; + if (inspecting) return "Inspecting recipient key."; + if (safeInspectionError) return safeInspectionError; + if (!inspection?.ok) return "The recipient key could not be inspected."; + if (inspection.keyInfo.key_type !== "public") return "A public key is required to encrypt a file."; + if (inspection.keyInfo.kem !== health.kem) { + return `This public key uses ${inspection.keyInfo.kem}; encryption requires ${health.kem}.`; + } + if (!outputFilename.trim()) return "Enter an output filename."; + return null; + }, [ + capability.available, + capability.reason, + file, + fileError, + health.kem, + inspection, + inspecting, + keyError, + outputFilename, + publicKey, + safeInspectionError + ]); + const canEncrypt = !readinessReason && !busy; + const phase = deriveWorkflowPhase({ + ready: Boolean(canEncrypt), + complete: Boolean(completedFilename) + }); + + useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + requestIdRef.current += 1; + inFlightRef.current = false; + abortControllerRef.current?.abort(); + abortControllerRef.current = null; + }; + }, []); + + function clearOutcome() { + requestIdRef.current += 1; + setError(null); + setCompletedFilename(null); + } + + function selectFile(nextFile: File | null) { + if (busy) return; + setFile(nextFile); + setOutputFilename(suggestedEncryptedName(nextFile)); + clearOutcome(); + } + + function selectPublicKey(nextFile: File | null) { + if (busy) return; + setPublicKey(nextFile); + clearOutcome(); + } + + function updateOutputFilename(value: string) { + if (busy) return; + setOutputFilename(value); + clearOutcome(); + } + + async function submit(event: FormEvent) { + event.preventDefault(); + if (!canEncrypt || !file || !publicKey || inFlightRef.current) return; + + const requestId = requestIdRef.current + 1; + const controller = new AbortController(); + requestIdRef.current = requestId; + inFlightRef.current = true; + abortControllerRef.current = controller; + setBusy(true); + setError(null); + setCompletedFilename(null); + + try { + const result = await encrypt(file, publicKey, outputFilename.trim(), controller.signal); + if (!mountedRef.current || requestId !== requestIdRef.current) return; + try { + save(result); + } catch { + setError("The file was encrypted, but the download could not start. Try encrypting it again."); + return; + } + setCompletedFilename(result.filename); + } catch (caught: unknown) { + if (!mountedRef.current || requestId !== requestIdRef.current) return; + if (controller.signal.aborted || isAbortError(caught)) return; + setError(safeOperationError(caught, "Could not encrypt this file. Confirm the recipient key and try again.")); + } finally { + if (requestId === requestIdRef.current) inFlightRef.current = false; + if (abortControllerRef.current === controller) abortControllerRef.current = null; + if (mountedRef.current && requestId === requestIdRef.current) setBusy(false); + } + } + + const keyClassification = !inspection + ? null + : compatiblePublicKey + ? "Compatible public key" + : inspection.keyInfo.key_type === "private" + ? "Private key — not valid for encryption" + : "Public key — not compatible"; + + return ( + + {capability.available && ( +
+ + + + {inspecting && Checking safe key metadata locally.} + {safeInspectionError && {safeInspectionError}} + +
+

Review

+
+
+
File
+
{file ? file.name : "Not selected"}
+
+
+
Size
+
{file ? formatBytes(file.size) : "Not selected"}
+
+
+
Recipient key
+
{keyClassification ?? (publicKey ? "Awaiting inspection" : "Not selected")}
+
+
+
+ + updateOutputFilename(event.target.value)} + type="text" + value={outputFilename} + /> +
+ {readinessReason && !busy && readinessReason !== fileError && readinessReason !== keyError && readinessReason !== safeInspectionError && ( +

{readinessReason}

+ )} +
+ + + Encrypt file + + + )} + + {error && {error}} + {completedFilename && ( + + Saved {completedFilename}. + + )} + + +
+
+
Hybrid suite
+
{health.kem}
+
+
+
DEM
+
{health.dem}
+
+
+
New file format version
+
{health.formatVersion}
+
+
+
+
+ ); +} diff --git a/web/src/features/generate/GenerateKeysWorkflow.test.tsx b/web/src/features/generate/GenerateKeysWorkflow.test.tsx new file mode 100644 index 0000000..d357c4a --- /dev/null +++ b/web/src/features/generate/GenerateKeysWorkflow.test.tsx @@ -0,0 +1,257 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; +import { ApiError, type GeneratedKeys } from "../../api"; +import { READY_HEALTH } from "../../test/fixtures"; +import { GenerateKeysWorkflow } from "./GenerateKeysWorkflow"; + +function generatedKeys(overrides: Partial = {}): GeneratedKeys { + return { + ok: true, + kem: "ML-KEM-768+X25519-v2", + publicPem: "PUBLIC-PEM", + privatePem: "-----BEGIN PQC PRIVATE KEY-----\nPQC-Key-Format: 3\nENCRYPTED-PRIVATE-PEM\n-----END PQC PRIVATE KEY-----", + publicFilename: "recipient-public.pem", + privateFilename: "recipient-private.pem", + ...overrides + }; +} + +type Deferred = { + promise: Promise; + resolve: (value: T) => void; +}; + +function deferred(): Deferred { + let resolve!: (value: T) => void; + const promise = new Promise((resolvePromise) => { + resolve = resolvePromise; + }); + return { promise, resolve }; +} + +async function enterValidPasswords(user: ReturnType) { + await user.type(screen.getByLabelText("Private key password"), "correct horse battery staple"); + await user.type(screen.getByLabelText("Confirm private key password"), "correct horse battery staple"); +} + +describe("GenerateKeysWorkflow", () => { + it("keeps generation disabled for a server-blocked common password", async () => { + const user = userEvent.setup(); + + render(); + await user.type(screen.getByLabelText("Private key password"), "password12345678"); + await user.type(screen.getByLabelText("Confirm private key password"), "password12345678"); + + expect(screen.getByText("Not a common password").closest("li")).not.toHaveClass("password-policy-met"); + expect(screen.getByRole("button", { name: "Generate key pair" })).toBeDisabled(); + }); + + it("keeps generated key material in memory until the user explicitly clears it", async () => { + const generate = vi.fn().mockResolvedValue(generatedKeys()); + const onSensitiveResultChange = vi.fn(); + const user = userEvent.setup(); + + render( + + ); + + const generateButton = screen.getByRole("button", { name: "Generate key pair" }); + expect(generateButton).toBeDisabled(); + + await enterValidPasswords(user); + expect(generateButton).toBeEnabled(); + + await user.click(generateButton); + + await waitFor(() => + expect(generate).toHaveBeenCalledWith("correct horse battery staple", expect.any(AbortSignal)) + ); + expect(screen.queryByLabelText("Private key password")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Confirm private key password")).not.toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Download public key" })).toBeVisible(); + expect(screen.getByRole("button", { name: "Download encrypted private key" })).toBeVisible(); + expect(screen.queryByText("PUBLIC-PEM")).not.toBeInTheDocument(); + expect(screen.queryByText("ENCRYPTED-PRIVATE-PEM")).not.toBeInTheDocument(); + expect(onSensitiveResultChange).toHaveBeenCalledWith(true); + expect(screen.getByText("Private key format version").nextElementSibling).toHaveTextContent("3"); + + await user.click(screen.getByRole("button", { name: "Clear generated keys" })); + + expect(screen.queryByRole("button", { name: "Download public key" })).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Download encrypted private key" })).not.toBeInTheDocument(); + expect(onSensitiveResultChange).toHaveBeenLastCalledWith(false); + }); + + it("requires clearing generated keys before another key pair can be requested", async () => { + const secondRequest = new Promise(() => undefined); + const generate = vi.fn() + .mockResolvedValueOnce(generatedKeys()) + .mockReturnValueOnce(secondRequest); + const onSensitiveResultChange = vi.fn(); + const user = userEvent.setup(); + + render( + + ); + + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + await waitFor(() => expect(generate).toHaveBeenCalledTimes(1)); + expect(screen.getByRole("button", { name: "Download public key" })).toBeVisible(); + expect(onSensitiveResultChange).toHaveBeenLastCalledWith(true); + + expect(screen.queryByLabelText("Private key password")).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Generate key pair" })).not.toBeInTheDocument(); + expect(generate).toHaveBeenCalledTimes(1); + expect(screen.getByRole("button", { name: "Download encrypted private key" })).toBeVisible(); + expect(onSensitiveResultChange).toHaveBeenLastCalledWith(true); + + await user.click(screen.getByRole("button", { name: "Clear generated keys" })); + + expect(screen.getByLabelText("Private key password")).toBeVisible(); + expect(screen.getByRole("button", { name: "Generate key pair" })).toBeDisabled(); + expect(onSensitiveResultChange).toHaveBeenLastCalledWith(false); + }); + + it("notifies the shell to clear sensitive result state when unmounted", () => { + const onSensitiveResultChange = vi.fn(); + const { unmount } = render( + + ); + + unmount(); + + expect(onSensitiveResultChange).toHaveBeenCalledWith(false); + }); + + it("does not reassert sensitive state when an in-flight request resolves after unmount", async () => { + let resolveGeneration: (value: ReturnType) => void; + const generate = vi.fn( + (_password: string, _signal?: AbortSignal) => + new Promise>((resolve) => { + resolveGeneration = resolve; + }) + ); + const onSensitiveResultChange = vi.fn(); + const user = userEvent.setup(); + const { unmount } = render( + + ); + + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + await waitFor(() => expect(generate).toHaveBeenCalledTimes(1)); + const signal = generate.mock.calls[0]?.[1] as AbortSignal; + + unmount(); + expect(signal.aborted).toBe(true); + resolveGeneration!(generatedKeys()); + await Promise.resolve(); + + expect(onSensitiveResultChange).not.toHaveBeenCalledWith(true); + expect(onSensitiveResultChange).toHaveBeenLastCalledWith(false); + }); + + it("locks password controls while generation is in flight", async () => { + const request = deferred(); + const generate = vi.fn().mockReturnValue(request.promise); + const user = userEvent.setup(); + + render(); + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + await waitFor(() => expect(generate).toHaveBeenCalledTimes(1)); + + expect(screen.getByLabelText("Private key password")).toBeDisabled(); + expect(screen.getByLabelText("Confirm private key password")).toBeDisabled(); + for (const button of screen.getAllByRole("button", { name: "Show password" })) { + expect(button).toBeDisabled(); + } + expect(screen.getByRole("button", { name: "Generating key pair" })).toBeDisabled(); + + request.resolve(generatedKeys()); + expect(await screen.findByRole("button", { name: "Download public key" })).toBeVisible(); + }); + + it("preserves safe backend error categories and distinguishes network failure", async () => { + const backendFailure = vi.fn().mockRejectedValue( + new ApiError(503, "backend_unavailable", "Post-quantum backend is not ready.") + ); + const user = userEvent.setup(); + const { unmount } = render(); + + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + expect(await screen.findByText("Post-quantum backend is not ready.")).toBeVisible(); + + unmount(); + const networkFailure = vi.fn().mockRejectedValue(new TypeError("fetch failed: private socket detail")); + render(); + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + + expect(await screen.findByText("Could not reach the local service. Check that it is running and try again.")).toBeVisible(); + expect(screen.queryByText(/private socket detail/i)).not.toBeInTheDocument(); + }); + + it("preserves safe server password-policy guidance", async () => { + const generate = vi.fn().mockRejectedValue( + new ApiError(400, "weak_password", "Private-key password is too common.") + ); + const user = userEvent.setup(); + + render(); + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + + expect(await screen.findByText("Private-key password is too common.")).toBeVisible(); + }); + + it("does not render an AbortError as a key-generation failure", async () => { + const aborted = new Error("request aborted"); + aborted.name = "AbortError"; + const generate = vi.fn().mockRejectedValue(aborted); + const user = userEvent.setup(); + + render(); + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + + await waitFor(() => expect(screen.getByRole("button", { name: "Generate key pair" })).toBeEnabled()); + expect(screen.queryByText("Key generation failed")).not.toBeInTheDocument(); + }); + + it("does not announce or expose an unsuccessful generation response", async () => { + const generate = vi.fn().mockResolvedValue(generatedKeys({ ok: false })); + const onSensitiveResultChange = vi.fn(); + const user = userEvent.setup(); + + render( + + ); + + await enterValidPasswords(user); + await user.click(screen.getByRole("button", { name: "Generate key pair" })); + + expect(await screen.findByText("Could not generate keys. Check the password requirements and try again.")).toBeVisible(); + expect(screen.queryByRole("button", { name: "Download public key" })).not.toBeInTheDocument(); + expect(onSensitiveResultChange).not.toHaveBeenCalledWith(true); + }); +}); diff --git a/web/src/features/generate/GenerateKeysWorkflow.tsx b/web/src/features/generate/GenerateKeysWorkflow.tsx new file mode 100644 index 0000000..af68d4e --- /dev/null +++ b/web/src/features/generate/GenerateKeysWorkflow.tsx @@ -0,0 +1,223 @@ +import { useEffect, useMemo, useRef, useState, type FormEvent } from "react"; +import { generateKeys, type GenerateKeysOperation, type GeneratedKeys, type Health } from "../../api"; +import { isAbortError, safeOperationError } from "../../api/errors"; +import { ActionButton } from "../../components/ActionButton"; +import { Notice } from "../../components/Notice"; +import { PasswordField } from "../../components/PasswordField"; +import { TechnicalDetails } from "../../components/TechnicalDetails"; +import { WorkflowLayout } from "../../components/WorkflowLayout"; +import { downloadText } from "../../lib/download"; +import { deriveWorkflowPhase } from "../../lib/workflow"; +import { passwordPolicyChecks } from "./passwordPolicy"; + +export type GenerateKeysWorkflowProps = { + health: Health; + generate?: GenerateKeysOperation; + onSensitiveResultChange?: (present: boolean) => void; +}; + +type GeneratedKeyState = Omit & { + publicPem: string | null; + privatePem: string | null; +}; + +function privateKeyFormatVersion(privatePem: string | null | undefined): string | null { + if (!privatePem) return null; + return privatePem.match(/^PQC-Key-Format:\s*(\d+)\s*$/m)?.[1] ?? "Not declared"; +} + +export function GenerateKeysWorkflow({ health, generate = generateKeys, onSensitiveResultChange }: GenerateKeysWorkflowProps) { + const [password, setPassword] = useState(""); + const [confirmation, setConfirmation] = useState(""); + const [generatedKeys, setGeneratedKeys] = useState(null); + const [error, setError] = useState(null); + const [busy, setBusy] = useState(false); + const mountedRef = useRef(true); + const requestIdRef = useRef(0); + const inFlightRef = useRef(false); + const abortControllerRef = useRef(null); + const sensitiveResultChangeRef = useRef(onSensitiveResultChange); + const capability = health.capabilities.generate; + const checks = useMemo( + () => passwordPolicyChecks(password, confirmation, health.passwordPolicy), + [confirmation, health.passwordPolicy, password] + ); + const policySatisfied = checks.every((check) => check.met); + const hasGeneratedKeys = Boolean(generatedKeys?.publicPem && generatedKeys.privatePem); + const canGenerate = capability.available && policySatisfied && !busy && !hasGeneratedKeys; + const phase = deriveWorkflowPhase({ + ready: capability.available && policySatisfied, + complete: hasGeneratedKeys + }); + + useEffect(() => { + sensitiveResultChangeRef.current = onSensitiveResultChange; + }, [onSensitiveResultChange]); + + useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + requestIdRef.current += 1; + inFlightRef.current = false; + abortControllerRef.current?.abort(); + abortControllerRef.current = null; + sensitiveResultChangeRef.current?.(false); + }; + }, []); + + async function submit(event: FormEvent) { + event.preventDefault(); + if (!canGenerate || hasGeneratedKeys || inFlightRef.current) return; + + const requestId = requestIdRef.current + 1; + const controller = new AbortController(); + requestIdRef.current = requestId; + inFlightRef.current = true; + abortControllerRef.current = controller; + setBusy(true); + setError(null); + + try { + const result = await generate(password, controller.signal); + if (!mountedRef.current || requestId !== requestIdRef.current) return; + if (!result.ok) { + setError("Could not generate keys. Check the password requirements and try again."); + return; + } + setGeneratedKeys(result); + setPassword(""); + setConfirmation(""); + sensitiveResultChangeRef.current?.(true); + } catch (caught: unknown) { + if (!mountedRef.current || requestId !== requestIdRef.current) return; + if (controller.signal.aborted || isAbortError(caught)) return; + setError(safeOperationError(caught, "Could not generate keys. Check the password requirements and try again.")); + } finally { + if (requestId === requestIdRef.current) inFlightRef.current = false; + if (abortControllerRef.current === controller) abortControllerRef.current = null; + if (mountedRef.current && requestId === requestIdRef.current) { + setBusy(false); + } + } + } + + function clearGeneratedKeys() { + setGeneratedKeys((current) => + current + ? { + ...current, + publicPem: null, + privatePem: null + } + : null + ); + sensitiveResultChangeRef.current?.(false); + } + + return ( + + + Your private key password cannot be recovered. Save it in a secure password manager before generating keys. + + + {capability.available && !hasGeneratedKeys && ( +
+ { + if (!busy) setPassword(value); + }} + value={password} + /> + { + if (!busy) setConfirmation(value); + }} + value={confirmation} + /> +
    + {checks.map((check) => ( +
  • + + {check.label} +
  • + ))} +
+ + Generate key pair + + + )} + + {error && {error}} + + {hasGeneratedKeys && generatedKeys && ( +
+ + Save both files now. The public key is safe to share; keep the encrypted private key and password secure. + +
+ + +
+ + Clear generated keys + +
+ )} + + +
+
+
Hybrid suite
+
{health.kem}
+
+ {generatedKeys?.privatePem && ( +
+
Private key format version
+
{privateKeyFormatVersion(generatedKeys.privatePem)}
+
+ )} +
+
Password KDF
+
scrypt
+
+
+
Password requirements
+
{health.passwordPolicy.minChars} or more characters and {health.passwordPolicy.minUniqueChars} or more unique characters
+
+
+
+
+ ); +} diff --git a/web/src/features/generate/passwordPolicy.test.ts b/web/src/features/generate/passwordPolicy.test.ts new file mode 100644 index 0000000..5ab7f72 --- /dev/null +++ b/web/src/features/generate/passwordPolicy.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest"; +import { passwordPolicyChecks } from "./passwordPolicy"; + +describe("passwordPolicyChecks", () => { + it("reports the server-owned policy requirements and confirmation state", () => { + expect( + passwordPolicyChecks( + "correct horse battery staple", + "correct horse battery staple", + { minChars: 16, minUniqueChars: 5 } + ) + ).toEqual([ + { label: "16 or more characters", met: true }, + { label: "5 or more unique characters", met: true }, + { label: "Not a common password", met: true }, + { label: "Passwords match", met: true } + ]); + }); + + it.each([ + "passwordpassword", + "password12345678", + "qwertyuiopasdfgh", + " PassWord 12345678 ", + "Pass\u0085word12345678", + "Pass\u001cword12345678" + ])("matches the server normalization and rejects common password %j", (password) => { + const checks = passwordPolicyChecks(password, password, { minChars: 16, minUniqueChars: 5 }); + + expect(checks.find((check) => check.label === "Not a common password")).toEqual({ + label: "Not a common password", + met: false + }); + }); +}); diff --git a/web/src/features/generate/passwordPolicy.ts b/web/src/features/generate/passwordPolicy.ts new file mode 100644 index 0000000..c2b8eea --- /dev/null +++ b/web/src/features/generate/passwordPolicy.ts @@ -0,0 +1,44 @@ +import type { Health } from "../../api"; + +export type PasswordPolicyCheck = { + label: string; + met: boolean; +}; + +// Keep this usability check synchronized with crypto_core.COMMON_WEAK_PASSWORDS; the server remains authoritative. +const COMMON_WEAK_PASSWORDS = new Set([ + "passwordpassword", + "password12345678", + "qwertyuiopasdfgh" +]); +const PYTHON_SPLIT_WHITESPACE = /[\u0009-\u000d\u001c-\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]/gu; + +function isCommonPassword(password: string): boolean { + const normalized = password.toLowerCase().replace(PYTHON_SPLIT_WHITESPACE, ""); + return COMMON_WEAK_PASSWORDS.has(normalized); +} + +export function passwordPolicyChecks( + password: string, + confirmation: string, + policy: Health["passwordPolicy"] +): PasswordPolicyCheck[] { + return [ + { + label: `${policy.minChars} or more characters`, + met: password.length >= policy.minChars + }, + { + label: `${policy.minUniqueChars} or more unique characters`, + met: new Set(password).size >= policy.minUniqueChars + }, + { + label: "Not a common password", + met: password.length > 0 && !isCommonPassword(password) + }, + { + label: "Passwords match", + met: password.length > 0 && password === confirmation + } + ]; +} diff --git a/web/src/features/inspect/InspectKeyWorkflow.test.tsx b/web/src/features/inspect/InspectKeyWorkflow.test.tsx new file mode 100644 index 0000000..9281368 --- /dev/null +++ b/web/src/features/inspect/InspectKeyWorkflow.test.tsx @@ -0,0 +1,33 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; +import { READY_HEALTH } from "../../test/fixtures"; +import { InspectKeyWorkflow } from "./InspectKeyWorkflow"; + +describe("InspectKeyWorkflow", () => { + it("shows a safe key summary without rendering uploaded key material", async () => { + const inspect = vi.fn().mockResolvedValue({ + ok: true, + keyInfo: { + kem: "ML-KEM-768+X25519-v2", + key_type: "public" + }, + display: { + "Key Type": "Public", + Algorithm: "ML-KEM-768+X25519-v2" + } + }); + + const user = userEvent.setup(); + render(); + await user.upload( + screen.getByLabelText("Key file"), + new File(["PEM"], "recipient.pem", { type: "application/x-pem-file" }) + ); + + expect(await screen.findByText("Public key")).toBeVisible(); + await user.click(screen.getByText("Technical details")); + expect(screen.getByText("ML-KEM-768+X25519-v2")).toBeVisible(); + expect(screen.queryByText("PEM")).not.toBeInTheDocument(); + }); +}); diff --git a/web/src/features/inspect/InspectKeyWorkflow.tsx b/web/src/features/inspect/InspectKeyWorkflow.tsx new file mode 100644 index 0000000..d6c2b91 --- /dev/null +++ b/web/src/features/inspect/InspectKeyWorkflow.tsx @@ -0,0 +1,68 @@ +import { useState } from "react"; +import type { Health, InspectKeyOperation, KeyInspectResult } from "../../api"; +import { FilePicker } from "../../components/FilePicker"; +import { Notice } from "../../components/Notice"; +import { TechnicalDetails } from "../../components/TechnicalDetails"; +import { WorkflowLayout } from "../../components/WorkflowLayout"; +import { useKeyInspection } from "../../hooks/useKeyInspection"; +import { deriveWorkflowPhase } from "../../lib/workflow"; + +export type InspectKeyWorkflowProps = { + health: Health; + inspect?: InspectKeyOperation; +}; + +function summaryLabel(result: KeyInspectResult): string { + return result.keyInfo.key_type === "public" ? "Public key" : "Encrypted private key"; +} + +export function InspectKeyWorkflow({ health, inspect }: InspectKeyWorkflowProps) { + const [file, setFile] = useState(null); + const capability = health.capabilities.inspect; + const { result, error, loading } = useKeyInspection( + capability.available ? file : null, + health.maxPemBytes, + inspect + ); + const phase = deriveWorkflowPhase({ ready: capability.available && Boolean(file) && !error, complete: Boolean(result) }); + + return ( + + {capability.available && ( + + )} + {loading && Reading supported key metadata locally.} + {result && ( +
+ + Supported key metadata was read locally. + + +
+ {Object.entries(result.display).map(([label, value]) => ( +
+
{label}
+
{value}
+
+ ))} +
+
+
+ )} +
+ ); +} diff --git a/web/src/hooks/useKeyInspection.test.tsx b/web/src/hooks/useKeyInspection.test.tsx new file mode 100644 index 0000000..44db334 --- /dev/null +++ b/web/src/hooks/useKeyInspection.test.tsx @@ -0,0 +1,131 @@ +import { act, render, screen } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; +import type { InspectKeyOperation, KeyInspectResult } from "../api"; +import { useKeyInspection } from "./useKeyInspection"; + +type Deferred = { + promise: Promise; + resolve: (value: T) => void; + reject: (reason?: unknown) => void; +}; + +function deferred(): Deferred { + let resolve!: (value: T) => void; + let reject!: (reason?: unknown) => void; + const promise = new Promise((resolvePromise, rejectPromise) => { + resolve = resolvePromise; + reject = rejectPromise; + }); + return { promise, resolve, reject }; +} + +function result(kem: string): KeyInspectResult { + return { + ok: true, + keyInfo: { kem, key_type: "public" }, + display: { Algorithm: kem } + }; +} + +function InspectionProbe({ file, inspect }: { file: File | null; inspect: InspectKeyOperation }) { + const state = useKeyInspection(file, 1024, inspect); + return ( + + {state.result?.keyInfo.kem ?? "no result"}|{state.error ?? "no error"}|{state.loading ? "loading" : "idle"} + + ); +} + +describe("useKeyInspection", () => { + it("aborts the previous request when the selected file changes", () => { + const firstFile = new File(["first"], "first.pem", { type: "application/x-pem-file" }); + const secondFile = new File(["second"], "second.pem", { type: "application/x-pem-file" }); + let firstSignal: AbortSignal | undefined; + const inspect = vi.fn((file: File, signal?: AbortSignal) => { + if (file === firstFile) firstSignal = signal; + return new Promise(() => undefined); + }); + + const { rerender } = render(); + expect(screen.getByTestId("inspection-state")).toHaveTextContent("loading"); + + rerender(); + + expect(firstSignal?.aborted).toBe(true); + expect(inspect).toHaveBeenCalledWith(secondFile, expect.any(AbortSignal)); + }); + + it("does not render a completed result for a newly selected file", async () => { + const firstFile = new File(["first"], "first.pem", { type: "application/x-pem-file" }); + const secondFile = new File(["second"], "second.pem", { type: "application/x-pem-file" }); + const firstRequest = deferred(); + const secondRequest = deferred(); + const inspect = vi.fn((file: File) => (file === firstFile ? firstRequest.promise : secondRequest.promise)); + const { rerender } = render(); + + await act(async () => { + firstRequest.resolve(result("first-result")); + await firstRequest.promise; + }); + expect(screen.getByTestId("inspection-state")).toHaveTextContent("first-result"); + + rerender(); + + expect(screen.getByTestId("inspection-state")).not.toHaveTextContent("first-result"); + expect(screen.getByTestId("inspection-state")).toHaveTextContent("loading"); + }); + + it("ignores a previous request resolving after selection changes", async () => { + const firstFile = new File(["first"], "first.pem", { type: "application/x-pem-file" }); + const secondFile = new File(["second"], "second.pem", { type: "application/x-pem-file" }); + const firstRequest = deferred(); + const secondRequest = deferred(); + const inspect = vi.fn((file: File) => (file === firstFile ? firstRequest.promise : secondRequest.promise)); + const { rerender } = render(); + + rerender(); + await act(async () => { + firstRequest.resolve(result("first-result")); + await firstRequest.promise; + }); + + expect(screen.getByTestId("inspection-state")).not.toHaveTextContent("first-result"); + await act(async () => { + secondRequest.resolve(result("second-result")); + await secondRequest.promise; + }); + expect(screen.getByTestId("inspection-state")).toHaveTextContent("second-result"); + }); + + it("ignores a previous request rejecting after selection changes", async () => { + const firstFile = new File(["first"], "first.pem", { type: "application/x-pem-file" }); + const secondFile = new File(["second"], "second.pem", { type: "application/x-pem-file" }); + const firstRequest = deferred(); + const secondRequest = deferred(); + const inspect = vi.fn((file: File) => (file === firstFile ? firstRequest.promise : secondRequest.promise)); + const { rerender } = render(); + + rerender(); + await act(async () => { + firstRequest.reject(new Error("first error")); + await Promise.resolve(); + }); + + expect(screen.getByTestId("inspection-state")).not.toHaveTextContent("first error"); + await act(async () => { + secondRequest.resolve(result("second-result")); + await secondRequest.promise; + }); + expect(screen.getByTestId("inspection-state")).toHaveTextContent("second-result"); + }); + + it("rejects an oversized key locally without calling the API", async () => { + const inspect = vi.fn(); + const oversizedFile = new File([new Uint8Array(1025)], "oversized.pem", { type: "application/x-pem-file" }); + + render(); + + expect(await screen.findByText(/exceeds the 1,024 byte limit/)).toBeVisible(); + expect(inspect).not.toHaveBeenCalled(); + }); +}); diff --git a/web/src/hooks/useKeyInspection.ts b/web/src/hooks/useKeyInspection.ts new file mode 100644 index 0000000..832b4c6 --- /dev/null +++ b/web/src/hooks/useKeyInspection.ts @@ -0,0 +1,80 @@ +import { useEffect, useState } from "react"; +import { inspectKey, type InspectKeyOperation, type KeyInspectResult } from "../api"; + +type KeyInspectionState = { + sourceFile: File | null; + result: KeyInspectResult | null; + error: string | null; + loading: boolean; +}; + +type KeyInspectionValue = Omit; + +const INITIAL_STATE: KeyInspectionState = { + sourceFile: null, + result: null, + error: null, + loading: false +}; + +function errorMessage(error: unknown): string { + return error instanceof Error && error.message ? error.message : "Unable to inspect this key file."; +} + +export function useKeyInspection( + file: File | null, + maxBytes: number, + inspect: InspectKeyOperation = inspectKey +): KeyInspectionValue { + const [state, setState] = useState(INITIAL_STATE); + + useEffect(() => { + if (!file) { + setState(INITIAL_STATE); + return; + } + + if (file.size > maxBytes) { + setState({ + sourceFile: file, + result: null, + error: `This key file exceeds the ${maxBytes.toLocaleString()} byte limit.`, + loading: false + }); + return; + } + + const controller = new AbortController(); + let current = true; + setState({ sourceFile: file, result: null, error: null, loading: true }); + + inspect(file, controller.signal) + .then((result) => { + if (!current || controller.signal.aborted) return; + setState({ sourceFile: file, result, error: null, loading: false }); + }) + .catch((error: unknown) => { + if (!current || controller.signal.aborted || (error instanceof Error && error.name === "AbortError")) return; + setState({ sourceFile: file, result: null, error: errorMessage(error), loading: false }); + }); + + return () => { + current = false; + controller.abort(); + }; + }, [file, inspect, maxBytes]); + + if (state.sourceFile !== file) { + return { + result: null, + error: null, + loading: file !== null && file.size <= maxBytes + }; + } + + return { + result: state.result, + error: state.error, + loading: state.loading + }; +} diff --git a/web/src/lib/download.ts b/web/src/lib/download.ts new file mode 100644 index 0000000..0d624f8 --- /dev/null +++ b/web/src/lib/download.ts @@ -0,0 +1,19 @@ +import type { DownloadResult } from "../api/contracts"; + +export function downloadBlob(result: DownloadResult): void { + const url = URL.createObjectURL(result.blob); + const anchor = document.createElement("a"); + anchor.href = url; + anchor.download = result.filename; + document.body.append(anchor); + anchor.click(); + anchor.remove(); + window.setTimeout(() => URL.revokeObjectURL(url), 0); +} + +export function downloadText(filename: string, text: string): void { + downloadBlob({ + filename, + blob: new Blob([text], { type: "application/x-pem-file" }) + }); +} diff --git a/web/src/lib/filenames.test.ts b/web/src/lib/filenames.test.ts new file mode 100644 index 0000000..ab5306e --- /dev/null +++ b/web/src/lib/filenames.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from "vitest"; +import { suggestedDecryptedName, suggestedEncryptedName } from "./filenames"; + +describe("filename suggestions", () => { + it("creates the current encrypted filename convention", () => { + expect(suggestedEncryptedName(new File(["x"], "report.pdf"))).toBe( + "report_encrypted.pqc" + ); + }); + + it("recovers the original stem from the encrypted convention", () => { + expect(suggestedDecryptedName(new File(["x"], "report_encrypted.pqc"))).toBe( + "report" + ); + }); + + it("uses a safe fallback for a bare extension", () => { + expect(suggestedDecryptedName(new File(["x"], ".pqc"))).toBe("decrypted.bin"); + }); +}); diff --git a/web/src/lib/filenames.ts b/web/src/lib/filenames.ts new file mode 100644 index 0000000..31b5f7c --- /dev/null +++ b/web/src/lib/filenames.ts @@ -0,0 +1,19 @@ +export function suggestedEncryptedName(file: File | null): string { + if (!file) return "encrypted-file.pqc"; + const dot = file.name.lastIndexOf("."); + const stem = dot > 0 ? file.name.slice(0, dot) : file.name || "file"; + return `${stem}_encrypted.pqc`; +} + +export function suggestedDecryptedName(file: File | null): string { + if (!file) return "decrypted.bin"; + const name = file.name; + if (name === ".pqc") return "decrypted.bin"; + if (name.endsWith("_encrypted.pqc")) { + return name.slice(0, -"_encrypted.pqc".length) || "decrypted.bin"; + } + if (name.endsWith(".pqc")) return `${name.slice(0, -".pqc".length)}_decrypted.bin`; + const dot = name.lastIndexOf("."); + if (dot > 0) return `${name.slice(0, dot)}_decrypted${name.slice(dot)}`; + return `${name}_decrypted.bin`; +} diff --git a/web/src/lib/format.test.ts b/web/src/lib/format.test.ts new file mode 100644 index 0000000..1d36a26 --- /dev/null +++ b/web/src/lib/format.test.ts @@ -0,0 +1,10 @@ +import { describe, expect, it } from "vitest"; +import { formatBytes } from "./format"; + +describe("formatBytes", () => { + it("uses binary units without overstating precision", () => { + expect(formatBytes(0)).toBe("0 B"); + expect(formatBytes(1024)).toBe("1.00 KiB"); + expect(formatBytes(100 * 1024 * 1024)).toBe("100 MiB"); + }); +}); diff --git a/web/src/lib/format.ts b/web/src/lib/format.ts new file mode 100644 index 0000000..b0b4b79 --- /dev/null +++ b/web/src/lib/format.ts @@ -0,0 +1,13 @@ +export function formatBytes(bytes: number): string { + if (!Number.isFinite(bytes) || bytes <= 0) return "0 B"; + if (bytes < 1024) return String(bytes) + " B"; + const units = ["KiB", "MiB", "GiB"]; + let value = bytes / 1024; + let index = 0; + while (value >= 1024 && index < units.length - 1) { + value /= 1024; + index += 1; + } + const precision = value >= 100 ? 0 : value >= 10 ? 1 : 2; + return value.toFixed(precision) + " " + units[index]; +} diff --git a/web/src/lib/workflow.test.ts b/web/src/lib/workflow.test.ts new file mode 100644 index 0000000..aa9b469 --- /dev/null +++ b/web/src/lib/workflow.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from "vitest"; +import { deriveWorkflowPhase } from "./workflow"; + +describe("deriveWorkflowPhase", () => { + it("does not report review before all inputs are ready", () => { + expect(deriveWorkflowPhase({ ready: false, complete: false })).toBe("select"); + }); + + it("reports review only for ready inputs", () => { + expect(deriveWorkflowPhase({ ready: true, complete: false })).toBe("review"); + }); + + it("prioritizes a completed result", () => { + expect(deriveWorkflowPhase({ ready: true, complete: true })).toBe("complete"); + }); +}); diff --git a/web/src/lib/workflow.ts b/web/src/lib/workflow.ts new file mode 100644 index 0000000..dad440e --- /dev/null +++ b/web/src/lib/workflow.ts @@ -0,0 +1,6 @@ +export type WorkflowPhase = "select" | "review" | "complete"; + +export function deriveWorkflowPhase(state: { ready: boolean; complete: boolean }): WorkflowPhase { + if (state.complete) return "complete"; + return state.ready ? "review" : "select"; +} diff --git a/web/src/main.tsx b/web/src/main.tsx index fa1b97e..a41d533 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -1,7 +1,9 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import App from "./App"; -import "./styles.css"; +import App from "./app/App"; +import "./styles/tokens.css"; +import "./styles/global.css"; +import "./styles/components.css"; ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( diff --git a/web/src/styles.css b/web/src/styles.css deleted file mode 100644 index 46eb3dd..0000000 --- a/web/src/styles.css +++ /dev/null @@ -1,564 +0,0 @@ -:root { - color-scheme: dark; - font-family: - Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - background: #000000; - color: #f9fafb; - font-synthesis: none; - text-rendering: optimizeLegibility; - --bg: #000000; - --sidebar: #0d1321; - --surface: #07111f; - --surface-2: #0b1628; - --surface-3: #0e1c31; - --border: #1d2b44; - --border-strong: #2f4364; - --text: #f9fafb; - --muted: #b6c2d1; - --subtle: #748399; - --primary: #3b82f6; - --primary-strong: #2563eb; - --accent: #22d3ee; - --success: #22c55e; - --warning: #f59e0b; - --error: #ef4444; - --radius: 8px; -} - -* { - box-sizing: border-box; -} - -body { - margin: 0; - min-width: 320px; - min-height: 100vh; - background: - linear-gradient(140deg, rgba(7, 17, 31, 0.94), rgba(0, 0, 0, 0.94) 34%), - var(--bg); -} - -button, -input { - font: inherit; -} - -button { - cursor: pointer; -} - -button:disabled { - cursor: not-allowed; -} - -.app-shell { - min-height: 100vh; - display: grid; - grid-template-columns: 280px minmax(0, 1fr); -} - -.sidebar { - background: var(--sidebar); - border-right: 1px solid var(--border); - padding: 28px 20px; - display: flex; - flex-direction: column; - gap: 22px; -} - -.brand-block { - display: grid; - grid-template-columns: 44px 1fr; - gap: 12px; - align-items: center; -} - -.brand-mark { - display: grid; - place-items: center; - height: 44px; - border: 1px solid rgba(34, 211, 238, 0.44); - border-radius: var(--radius); - background: linear-gradient(135deg, rgba(34, 211, 238, 0.16), rgba(59, 130, 246, 0.18)); - color: var(--accent); - font-size: 13px; - font-weight: 800; - letter-spacing: 0; -} - -.brand-block h1, -.workflow-header h2, -.panel h3 { - margin: 0; - letter-spacing: 0; -} - -.brand-block h1 { - font-size: 18px; - line-height: 1.15; -} - -.brand-block p, -.workflow-header p, -.empty-copy { - margin: 5px 0 0; - color: var(--muted); -} - -.brand-block p { - font-size: 12px; -} - -.nav-group { - display: grid; - gap: 8px; -} - -.nav-heading, -.eyebrow { - margin: 0; - color: var(--subtle); - font-size: 11px; - font-weight: 800; - letter-spacing: 0.08em; - text-transform: uppercase; -} - -.nav-item { - width: 100%; - border: 1px solid transparent; - border-radius: var(--radius); - padding: 12px 12px; - background: transparent; - color: var(--muted); - text-align: left; -} - -.nav-item:hover, -.nav-item:focus-visible { - border-color: var(--border-strong); - color: var(--text); - outline: none; -} - -.nav-item.active { - border-color: rgba(59, 130, 246, 0.56); - background: rgba(59, 130, 246, 0.13); - color: var(--text); -} - -.system-card, -.notice, -.panel, -.meta-badge, -.file-drop, -.download-card { - border: 1px solid var(--border); - border-radius: var(--radius); - background: var(--surface); -} - -.system-card { - display: grid; - grid-template-columns: 10px 1fr; - gap: 12px; - padding: 14px; -} - -.status-dot { - width: 10px; - height: 10px; - border-radius: 999px; - margin-top: 4px; -} - -.status-dot.ready { - background: var(--success); - box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.12); -} - -.status-dot.warning { - background: var(--warning); - box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.12); -} - -.system-title { - margin: 0; - font-size: 13px; - font-weight: 800; -} - -.system-text { - margin: 4px 0 0; - color: var(--muted); - font-size: 12px; -} - -.metadata-grid { - display: grid; - grid-template-columns: 1fr; - gap: 8px; - margin-top: auto; -} - -.meta-badge { - padding: 10px 12px; -} - -.meta-badge span, -.field-row span, -.download-card span { - display: block; - color: var(--subtle); - font-size: 11px; - font-weight: 800; - letter-spacing: 0.06em; - text-transform: uppercase; -} - -.meta-badge strong, -.field-row strong, -.download-card strong { - display: block; - margin-top: 3px; - color: var(--text); - font-size: 13px; - word-break: break-word; -} - -.main-panel { - min-width: 0; - padding: 28px 38px 48px; -} - -.notice { - padding: 13px 14px; - color: var(--muted); - font-size: 13px; - line-height: 1.5; -} - -.notice.info { - border-color: rgba(96, 165, 250, 0.38); - background: rgba(96, 165, 250, 0.1); - color: #bfdbfe; -} - -.notice.success { - border-color: rgba(34, 197, 94, 0.38); - background: rgba(34, 197, 94, 0.1); - color: #bbf7d0; -} - -.notice.warning { - border-color: rgba(245, 158, 11, 0.44); - background: rgba(245, 158, 11, 0.11); - color: #fde68a; -} - -.notice.error { - border-color: rgba(239, 68, 68, 0.44); - background: rgba(239, 68, 68, 0.1); - color: #fecaca; -} - -.workflow { - max-width: 1120px; -} - -.workflow > .notice { - margin-bottom: 18px; -} - -.workflow-header { - display: flex; - align-items: end; - justify-content: space-between; - gap: 24px; - margin-bottom: 22px; -} - -.workflow-header h2 { - font-size: clamp(28px, 3vw, 38px); - line-height: 1.05; -} - -.workflow-header p { - max-width: 620px; - font-size: 15px; -} - -.stepper { - list-style: none; - margin: 0 0 22px; - padding: 0; - display: grid; - grid-template-columns: repeat(5, minmax(0, 1fr)); - gap: 10px; -} - -.step { - min-width: 0; - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 10px; - color: var(--subtle); - background: rgba(11, 22, 40, 0.52); - font-size: 12px; - font-weight: 800; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.step span { - display: inline-grid; - place-items: center; - width: 22px; - height: 22px; - margin-right: 8px; - border-radius: 999px; - background: #101c2e; - color: var(--muted); -} - -.step.active { - border-color: rgba(59, 130, 246, 0.52); - color: var(--text); -} - -.step.active span { - background: var(--primary); - color: white; -} - -.panel-grid { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(340px, 0.85fr); - gap: 18px; -} - -.panel { - padding: 20px; - background: linear-gradient(180deg, var(--surface-2), var(--surface)); -} - -.panel h3 { - margin-bottom: 16px; - font-size: 18px; -} - -.file-drop { - display: grid; - grid-template-columns: 118px 1fr; - align-items: center; - gap: 14px; - padding: 14px; - margin-bottom: 12px; - color: var(--muted); -} - -.file-drop:hover, -.file-drop:focus-within { - border-color: var(--border-strong); -} - -.file-drop.has-file { - border-color: rgba(34, 211, 238, 0.44); -} - -.file-drop input { - position: absolute; - inline-size: 1px; - block-size: 1px; - overflow: hidden; - opacity: 0; -} - -.file-action { - display: inline-grid; - place-items: center; - min-height: 44px; - border: 1px solid var(--border-strong); - border-radius: var(--radius); - background: rgba(0, 0, 0, 0.28); - color: var(--text); - font-size: 13px; - font-weight: 800; -} - -.file-copy { - min-width: 0; -} - -.file-copy strong, -.file-copy small { - display: block; -} - -.file-copy strong { - overflow: hidden; - color: var(--text); - font-size: 14px; - text-overflow: ellipsis; - white-space: nowrap; -} - -.file-copy small { - margin-top: 4px; - color: var(--subtle); - font-size: 12px; -} - -.field-row { - display: grid; - grid-template-columns: 132px minmax(0, 1fr); - gap: 12px; - align-items: start; - padding: 12px 0; - border-bottom: 1px solid rgba(29, 43, 68, 0.7); -} - -.field-row:first-of-type { - border-top: 1px solid rgba(29, 43, 68, 0.7); -} - -.input-label { - display: grid; - gap: 8px; - margin: 16px 0; - color: var(--muted); - font-size: 12px; - font-weight: 800; - letter-spacing: 0.05em; - text-transform: uppercase; -} - -.input-label input { - width: 100%; - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 13px 14px; - background: #050b14; - color: var(--text); - outline: none; - text-transform: none; - letter-spacing: 0; -} - -.input-label input:focus { - border-color: var(--primary); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.16); -} - -.primary-button { - width: 100%; - border: 1px solid rgba(59, 130, 246, 0.9); - border-radius: var(--radius); - padding: 13px 16px; - background: linear-gradient(180deg, var(--primary), var(--primary-strong)); - color: white; - font-size: 14px; - font-weight: 900; - box-shadow: 0 12px 28px rgba(37, 99, 235, 0.22); -} - -.primary-button:hover:not(:disabled), -.primary-button:focus-visible:not(:disabled) { - filter: brightness(1.08); - outline: none; -} - -.primary-button:disabled { - border-color: var(--border); - background: #101827; - color: var(--subtle); - box-shadow: none; -} - -.checklist { - list-style: none; - margin: 0 0 16px; - padding: 0; - display: grid; - gap: 8px; -} - -.checklist li { - display: flex; - align-items: center; - gap: 10px; - color: var(--muted); - font-size: 13px; -} - -.checklist span { - width: 12px; - height: 12px; - border: 1px solid var(--border-strong); - border-radius: 999px; -} - -.checklist li.ok span { - border-color: var(--success); - background: var(--success); -} - -.download-grid { - display: grid; - gap: 12px; -} - -.download-card { - padding: 16px; - text-align: left; - color: var(--text); -} - -.download-card:hover, -.download-card:focus-visible { - border-color: var(--primary); - outline: none; -} - -.download-card.danger { - border-color: rgba(245, 158, 11, 0.44); -} - -.metadata-table { - display: grid; -} - -@media (max-width: 980px) { - .app-shell { - grid-template-columns: 1fr; - } - - .sidebar { - position: static; - } - - .metadata-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .panel-grid { - grid-template-columns: 1fr; - } - - .stepper { - grid-template-columns: 1fr; - } -} - -@media (max-width: 560px) { - .main-panel, - .sidebar { - padding: 20px; - } - - .file-drop, - .field-row { - grid-template-columns: 1fr; - } -} diff --git a/web/src/styles/components.css b/web/src/styles/components.css new file mode 100644 index 0000000..629c77b --- /dev/null +++ b/web/src/styles/components.css @@ -0,0 +1,609 @@ +@import "./tokens.css"; + +button { + min-height: 44px; + border: 1px solid var(--color-border-strong); + border-radius: var(--radius); + padding: var(--space-2) var(--space-4); + background: var(--color-action); + color: var(--color-action-text); + font-weight: 700; + transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast); +} + +button:hover:not(:disabled) { + background: #ffffff; +} + +button:disabled { + border-color: var(--color-border); + background: var(--color-surface-raised); + color: var(--color-text-subtle); +} + +.file-picker-field, +.password-field { + display: grid; + gap: var(--space-2); +} + +.file-picker { + position: relative; + display: grid; + gap: var(--space-1); + align-content: center; + border: 1px dashed var(--color-border-strong); + border-radius: var(--radius); + padding: var(--space-4); + background: var(--color-surface); + cursor: pointer; + transition: border-color var(--transition-fast), background-color var(--transition-fast); +} + +.file-picker:hover, +.file-picker-selected { + border-color: var(--color-text-muted); + background: var(--color-surface-raised); +} + +.file-picker:focus-within { + border-color: var(--focus-ring); + outline: 2px solid var(--focus-ring); + outline-offset: 3px; + background: var(--color-surface-raised); +} + +.file-picker-label, +.password-field > label { + font-weight: 700; +} + +.file-picker-prompt, +.file-picker-selection, +.field-hint { + color: var(--color-text-muted); +} + +.file-picker-selection { + overflow-wrap: anywhere; +} + +.file-picker-input { + position: absolute; + inline-size: 1px; + block-size: 1px; + opacity: 0; +} + +.field-hint, +.field-error { + margin: 0; + font-size: 0.875rem; +} + +.field-error { + color: var(--color-error); +} + +.password-field-control { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: var(--space-2); +} + +.password-field input { + min-width: 0; + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: var(--space-2) var(--space-3); + background: var(--color-surface); + color: var(--color-text); +} + +.notice { + display: grid; + gap: var(--space-1); + border: 1px solid var(--color-border); + border-left-width: 4px; + border-radius: var(--radius); + padding: var(--space-3) var(--space-4); + background: var(--color-surface); + color: var(--color-text-muted); +} + +.notice-title { + color: var(--color-text); +} + +.notice-success { + border-left-color: var(--color-success); +} + +.notice-warning { + border-left-color: var(--color-warning); +} + +.notice-error { + border-left-color: var(--color-error); +} + +.technical-details { + border: 1px solid var(--color-border); + border-radius: var(--radius); + background: var(--color-surface); +} + +.technical-details summary { + padding: var(--space-3) var(--space-4); + cursor: pointer; + font-weight: 700; +} + +.technical-details-content { + border-top: 1px solid var(--color-border); + padding: var(--space-4); + color: var(--color-text-muted); +} + +.workflow-layout { + display: grid; + gap: var(--space-5); + max-width: 760px; + margin: 0 auto; + padding: var(--space-6) var(--space-4); +} + +.workflow-header h1, +.workflow-header p { + margin: 0; +} + +.workflow-header p { + margin-top: var(--space-2); + color: var(--color-text-muted); +} + +.workflow-phases { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-2); + margin: 0; + padding: 0; + list-style: none; +} + +.workflow-phases li { + border-bottom: 2px solid var(--color-border); + padding: var(--space-2) 0; + color: var(--color-text-subtle); + font-size: 0.875rem; + font-weight: 700; +} + +.workflow-phases .is-current { + border-color: var(--color-text); + color: var(--color-text); +} + +.workflow-content { + display: grid; + gap: var(--space-4); +} + +.key-inspection-result { + display: grid; + gap: var(--space-3); +} + +.generate-keys-form, +.generated-key-downloads { + display: grid; + gap: var(--space-4); +} + +.encryption-form, +.decryption-form, +.workflow-review, +.output-filename-field, +.review-list { + display: grid; + gap: var(--space-3); +} + +.workflow-review { + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: var(--space-4); + background: var(--color-surface); +} + +.workflow-review h2 { + margin: 0; + font-size: 1rem; +} + +.review-list { + margin: 0; +} + +.review-list > div { + display: grid; + grid-template-columns: minmax(8rem, 1fr) minmax(0, 2fr); + gap: var(--space-3); +} + +.review-list dt { + color: var(--color-text-subtle); + font-weight: 700; +} + +.review-list dd { + min-width: 0; + margin: 0; + overflow-wrap: anywhere; +} + +.output-filename-field label { + font-weight: 700; +} + +.output-filename-field input { + min-height: 44px; + min-width: 0; + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: var(--space-2) var(--space-3); + background: var(--color-surface); + color: var(--color-text); + font: inherit; +} + +.workflow-readiness-reason { + margin: 0; + color: var(--color-text-muted); + font-size: 0.875rem; +} + +.password-policy { + display: grid; + gap: var(--space-2); + margin: 0; + padding: 0; + list-style: none; + color: var(--color-text-muted); +} + +.password-policy li { + display: flex; + gap: var(--space-2); + align-items: center; +} + +.password-policy li span { + inline-size: 1.25rem; + color: var(--color-text-subtle); + font-weight: 700; + text-align: center; +} + +.password-policy .password-policy-met { + color: var(--color-text); +} + +.password-policy .password-policy-met span { + color: var(--color-success); +} + +.generated-key-download-actions { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--space-3); +} + +.generated-key-download-actions button { + display: grid; + gap: var(--space-1); + min-width: 0; + text-align: left; +} + +.generated-key-download-actions span { + color: var(--color-text-muted); + font-size: 0.875rem; + font-weight: 400; +} + +.generated-key-download-actions strong { + overflow-wrap: anywhere; +} + +.metadata-list { + display: grid; + gap: var(--space-2); + margin: 0; +} + +.metadata-list > div { + display: grid; + grid-template-columns: minmax(9rem, 1fr) minmax(0, 2fr); + gap: var(--space-3); +} + +.metadata-list dt { + color: var(--color-text-subtle); + font-weight: 700; +} + +.metadata-list dd { + min-width: 0; + margin: 0; + overflow-wrap: anywhere; +} + +@media (max-width: 520px) { + .generated-key-download-actions { + grid-template-columns: 1fr; + } + + .review-list > div { + grid-template-columns: 1fr; + gap: var(--space-1); + } +} + +.app-shell { + min-height: 100vh; + background: var(--color-canvas); +} + +.app-rail, +.app-header { + border-color: var(--color-border); + background: var(--color-rail); +} + +.app-rail { + display: none; +} + +.app-header { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(168px, 240px) auto; + gap: var(--space-3); + align-items: center; + border-bottom: 1px solid var(--color-border); + padding: var(--space-3) var(--space-4); +} + +.app-brand { + display: flex; + min-width: 0; + gap: var(--space-2); + align-items: center; +} + +.app-brand > span:last-child { + display: grid; + min-width: 0; +} + +.app-brand strong, +.app-brand small { + overflow-wrap: anywhere; +} + +.app-brand small { + color: var(--color-text-muted); +} + +.app-brand-mark { + display: grid; + flex: 0 0 44px; + place-items: center; + inline-size: 44px; + block-size: 44px; + border: 1px solid var(--color-border-strong); + border-radius: var(--radius); + color: var(--color-text); + font-size: 0.75rem; + font-weight: 800; +} + +.app-workflow-select { + display: grid; + gap: var(--space-1); + color: var(--color-text-muted); + font-size: 0.875rem; + font-weight: 700; +} + +.app-workflow-select select { + min-height: 44px; + max-width: 100%; + border: 1px solid var(--color-border-strong); + border-radius: var(--radius); + padding: 0 var(--space-3); + background: var(--color-surface); + color: var(--color-text); + font: inherit; +} + +.app-main { + min-width: 0; + width: 100%; + max-width: 1120px; + margin: 0 auto; + padding: var(--space-6); +} + +.app-rail-navigation { + display: grid; + gap: var(--space-2); +} + +.app-rail-navigation p { + margin: 0; + color: var(--color-text-subtle); + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.app-navigation-item { + width: 100%; + border-color: transparent; + background: transparent; + color: var(--color-text-muted); + text-align: left; +} + +.app-navigation-item:hover:not(:disabled), +.app-navigation-item.is-current { + border-color: var(--color-border-strong); + background: var(--color-surface-raised); + color: var(--color-text); +} + +.capability-status { + display: grid; + gap: var(--space-2); + border-top: 1px solid var(--color-border); + padding-top: var(--space-4); +} + +.capability-status-summary { + display: grid; + grid-template-columns: auto 1fr auto; + gap: var(--space-2); + align-items: center; + margin: 0; + color: var(--color-text-muted); +} + +.capability-status-summary strong { + color: var(--color-text); +} + +.capability-status-dot { + inline-size: 10px; + block-size: 10px; + border-radius: 50%; +} + +.capability-status-dot-ready { + background: var(--color-success); +} + +.capability-status-dot-limited { + background: var(--color-warning); +} + +.capability-status-dot-unavailable { + background: var(--color-error); +} + +.capability-status-details summary { + min-height: 44px; + cursor: pointer; + color: var(--color-text-muted); + font-weight: 700; +} + +.capability-status-details ul { + display: grid; + gap: var(--space-2); + margin: var(--space-2) 0 0; + padding: 0; + list-style: none; +} + +.capability-status-details li { + display: grid; + gap: var(--space-1); + padding: var(--space-2) 0; + border-top: 1px solid var(--color-border); +} + +.capability-status-details li span { + color: var(--color-text-muted); + overflow-wrap: anywhere; +} + +.capability-status-compact { + min-width: 180px; + border-top: 0; + padding-top: 0; +} + +.app-mobile-navigation { + display: none; +} + +@media (min-width: 1024px) { + .app-shell { + display: grid; + grid-template-columns: 256px minmax(0, 1fr); + } + + .app-rail { + display: flex; + flex-direction: column; + gap: var(--space-5); + min-height: 100vh; + border-right: 1px solid var(--color-border); + padding: var(--space-5) var(--space-4); + } + + .app-rail .capability-status { + margin-top: auto; + } + + .app-header, + .app-mobile-navigation { + display: none; + } +} + +@media (max-width: 767px) { + .app-header { + grid-template-columns: minmax(0, 1fr) auto; + } + + .app-workflow-select { + display: none; + } + + .capability-status-compact { + min-width: 0; + } + + .app-main { + padding: var(--space-4); + } + + .app-mobile-navigation { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + border-bottom: 1px solid var(--color-border); + background: var(--color-rail); + } + + .app-mobile-navigation a { + display: grid; + min-width: 0; + min-height: 44px; + place-items: center; + padding: var(--space-2); + color: var(--color-text-muted); + font-size: 0.75rem; + font-weight: 700; + text-align: center; + text-decoration: none; + } + + .app-mobile-navigation a[aria-current="page"] { + color: var(--color-text); + box-shadow: inset 0 -2px 0 var(--color-text); + } +} diff --git a/web/src/styles/global.css b/web/src/styles/global.css new file mode 100644 index 0000000..b905341 --- /dev/null +++ b/web/src/styles/global.css @@ -0,0 +1,29 @@ +@import "./tokens.css"; + +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-width: 320px; + min-height: 100vh; + background: var(--color-canvas); + color: var(--color-text); + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font-synthesis: none; + text-rendering: optimizeLegibility; +} + +button, +input { + font: inherit; +} + +button { + cursor: pointer; +} + +button:disabled { + cursor: not-allowed; +} diff --git a/web/src/styles/tokens.css b/web/src/styles/tokens.css new file mode 100644 index 0000000..7c3dd8d --- /dev/null +++ b/web/src/styles/tokens.css @@ -0,0 +1,50 @@ +:root { + color-scheme: dark; + --color-canvas: #090909; + --color-rail: #0d0d0d; + --color-surface: #141414; + --color-surface-raised: #1b1b1b; + --color-border: #343434; + --color-border-strong: #555555; + --color-text: #f2f2ee; + --color-text-muted: #aaa9a3; + --color-text-subtle: #8a8a85; + --color-action: #f2f2ee; + --color-action-text: #0b0b0b; + --color-success: #78b86b; + --color-warning: #d3a24c; + --color-error: #d66a63; + --focus-ring: #f2f2ee; + --radius: 10px; + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 24px; + --space-6: 32px; + --space-7: 48px; + --transition-fast: 140ms ease; +} + +:focus-visible { + outline: 2px solid var(--focus-ring); + outline-offset: 3px; +} + +button, +input, +summary, +.file-picker { + min-height: 44px; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + } +} diff --git a/web/src/test/fixtures.ts b/web/src/test/fixtures.ts new file mode 100644 index 0000000..6d57f2d --- /dev/null +++ b/web/src/test/fixtures.ts @@ -0,0 +1,26 @@ +import type { Health } from "../api/contracts"; + +export const READY_HEALTH: Health = { + ok: true, + backendReady: true, + backendMessage: "Post-quantum backend ready.", + capabilities: { + inspect: { available: true, reason: "" }, + generate: { available: true, reason: "" }, + encrypt: { available: true, reason: "" }, + decrypt: { available: true, reason: "" } + }, + formatVersion: 4, + kem: "ML-KEM-768+X25519-v2", + kemComponent: "ML-KEM-768", + configuredKem: "ML-KEM-768", + dem: "AES-256-GCM", + maxFileBytes: 104857600, + maxEncryptedFileBytes: 105906314, + maxPemBytes: 131072, + apiToken: "test-local-token", + passwordPolicy: { + minChars: 16, + minUniqueChars: 5 + } +}; diff --git a/web/src/test/setup.ts b/web/src/test/setup.ts new file mode 100644 index 0000000..e262193 --- /dev/null +++ b/web/src/test/setup.ts @@ -0,0 +1,7 @@ +import "@testing-library/jest-dom/vitest"; +import { cleanup } from "@testing-library/react"; +import { afterEach } from "vitest"; + +afterEach(() => { + cleanup(); +}); From efcc4d52e35a3053034e97feece99fa69e8af6d0 Mon Sep 17 00:00:00 2001 From: brainx <12695242+brainx@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:01:29 +0200 Subject: [PATCH 2/3] style: format decryption backend helper --- crypto_core.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crypto_core.py b/crypto_core.py index 9c5aff1..e516a78 100644 --- a/crypto_core.py +++ b/crypto_core.py @@ -223,11 +223,7 @@ def resolve_kem_algorithm(kem_alg: Optional[str] = None) -> str: def available_decryption_kem_algorithms() -> Tuple[str, ...]: """Return enabled, application-supported KEM identities in preference order.""" enabled = set(_enabled_kem_mechanisms()) - return tuple( - candidate - for candidate in (cfg.KEM_ALG, *cfg.LEGACY_KEM_ALGS) - if candidate in enabled - ) + return tuple(candidate for candidate in (cfg.KEM_ALG, *cfg.LEGACY_KEM_ALGS) if candidate in enabled) def resolve_decryption_kem_algorithms(suite: str) -> Tuple[str, ...]: From cc645b35b9091fe3b32645cd92930c94399c30bc Mon Sep 17 00:00:00 2001 From: brainx <12695242+brainx@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:11:11 +0200 Subject: [PATCH 3/3] test: align native browser smoke with decryption label --- scripts/ui_native_smoke.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/ui_native_smoke.mjs b/scripts/ui_native_smoke.mjs index 85db30e..246d38f 100644 --- a/scripts/ui_native_smoke.mjs +++ b/scripts/ui_native_smoke.mjs @@ -85,7 +85,9 @@ async function run() { await page.getByRole("heading", { name: "Decrypt a file" }).waitFor(); await page.getByLabel("Encrypted file").setInputFiles(encryptedPath); await page.getByLabel("Private key", { exact: true }).setInputFiles(privateKeyPath); - await page.getByText("Compatible private key", { exact: true }).waitFor({ state: "visible" }); + await page + .getByText("Supported encrypted private key; match not yet verified", { exact: true }) + .waitFor({ state: "visible" }); await page.getByLabel("Private key password", { exact: true }).fill(password); const decryptedDownload = page.waitForEvent("download"); await page.getByRole("button", { name: "Decrypt file" }).click();