From a6de43edc1f160458f8f8de063f31c151f44edee Mon Sep 17 00:00:00 2001 From: "claude (blind_chess)" Date: Tue, 28 Apr 2026 11:20:18 -0400 Subject: [PATCH] feat: implement and deploy blind_chess MVP - pnpm workspace: shared/server/client packages - Server: Fastify+ws, chess.js, FSM (touch-move + hierarchy), per-player view filter, zod validation, rate limiting, grace-window disconnect handling - Client: Svelte 5 + Vite, click-to-move board, moderator panel, promotion/draw dialogs - Shared: protocol types, ModeratorText enum, geometricMoves helper (provably zero opponent-info leak) - 43 tests pass (21 shared, 22 server incl. 4 real-WS integration) - Deploy: CT 690 on node-241 (192.168.0.245), systemd-managed, Caddy block for chess.sethpc.xyz - Live at https://chess.sethpc.xyz Co-Authored-By: Claude Opus 4.7 (1M context) --- ...-28-104344-spec-approved-ready-for-plan.md | 180 + .../2026-04-28-152000-mvp-deployed.md | 181 + .claude/handoffs/2026-04-28-kickoff.md | 57 + .gitignore | 5 + .npmrc | 3 + .secrets.baseline | 6084 +++++++++++++++++ CLAUDE.md | 25 +- DECISIONS.md | 12 + deploy/Caddyfile.snippet | 7 + deploy/blind-chess.service | 31 + package.json | 21 + packages/client/index.html | 14 + packages/client/package.json | 22 + packages/client/src/App.svelte | 35 + packages/client/src/app.css | 64 + packages/client/src/lib/Board.svelte | 179 + packages/client/src/lib/Game.svelte | 229 + packages/client/src/lib/Landing.svelte | 162 + packages/client/src/lib/ModeratorPanel.svelte | 79 + .../client/src/lib/PromotionDialog.svelte | 68 + packages/client/src/lib/moderator-strings.ts | 44 + packages/client/src/lib/pieces.ts | 9 + packages/client/src/lib/stores/game.ts | 152 + packages/client/src/main.ts | 6 + packages/client/svelte.config.js | 5 + packages/client/tsconfig.json | 12 + packages/client/vite.config.ts | 17 + packages/server/package.json | 32 + packages/server/src/commit.ts | 132 + packages/server/src/games.ts | 122 + packages/server/src/ratelimit.ts | 18 + packages/server/src/server.ts | 105 + packages/server/src/state.ts | 58 + packages/server/src/translator.ts | 73 + packages/server/src/validation.ts | 44 + packages/server/src/view.ts | 48 + packages/server/src/ws.ts | 300 + .../test/integration/scripted-game.test.ts | 172 + packages/server/test/unit/commit-fsm.test.ts | 122 + packages/server/test/unit/view.test.ts | 81 + packages/server/tsconfig.json | 12 + packages/server/tsconfig.tsbuildinfo | 1 + packages/shared/package.json | 23 + packages/shared/src/geometric.ts | 102 + packages/shared/src/index.ts | 4 + packages/shared/src/moderator.ts | 28 + packages/shared/src/protocol.ts | 62 + packages/shared/src/types.ts | 63 + packages/shared/test/geometric.test.ts | 149 + packages/shared/tsconfig.json | 9 + pnpm-lock.yaml | 2492 +++++++ pnpm-workspace.yaml | 2 + tsconfig.base.json | 18 + 53 files changed, 11970 insertions(+), 5 deletions(-) create mode 100644 .claude/handoffs/2026-04-28-104344-spec-approved-ready-for-plan.md create mode 100644 .claude/handoffs/2026-04-28-152000-mvp-deployed.md create mode 100644 .claude/handoffs/2026-04-28-kickoff.md create mode 100644 .npmrc create mode 100644 .secrets.baseline create mode 100644 deploy/Caddyfile.snippet create mode 100644 deploy/blind-chess.service create mode 100644 package.json create mode 100644 packages/client/index.html create mode 100644 packages/client/package.json create mode 100644 packages/client/src/App.svelte create mode 100644 packages/client/src/app.css create mode 100644 packages/client/src/lib/Board.svelte create mode 100644 packages/client/src/lib/Game.svelte create mode 100644 packages/client/src/lib/Landing.svelte create mode 100644 packages/client/src/lib/ModeratorPanel.svelte create mode 100644 packages/client/src/lib/PromotionDialog.svelte create mode 100644 packages/client/src/lib/moderator-strings.ts create mode 100644 packages/client/src/lib/pieces.ts create mode 100644 packages/client/src/lib/stores/game.ts create mode 100644 packages/client/src/main.ts create mode 100644 packages/client/svelte.config.js create mode 100644 packages/client/tsconfig.json create mode 100644 packages/client/vite.config.ts create mode 100644 packages/server/package.json create mode 100644 packages/server/src/commit.ts create mode 100644 packages/server/src/games.ts create mode 100644 packages/server/src/ratelimit.ts create mode 100644 packages/server/src/server.ts create mode 100644 packages/server/src/state.ts create mode 100644 packages/server/src/translator.ts create mode 100644 packages/server/src/validation.ts create mode 100644 packages/server/src/view.ts create mode 100644 packages/server/src/ws.ts create mode 100644 packages/server/test/integration/scripted-game.test.ts create mode 100644 packages/server/test/unit/commit-fsm.test.ts create mode 100644 packages/server/test/unit/view.test.ts create mode 100644 packages/server/tsconfig.json create mode 100644 packages/server/tsconfig.tsbuildinfo create mode 100644 packages/shared/package.json create mode 100644 packages/shared/src/geometric.ts create mode 100644 packages/shared/src/index.ts create mode 100644 packages/shared/src/moderator.ts create mode 100644 packages/shared/src/protocol.ts create mode 100644 packages/shared/src/types.ts create mode 100644 packages/shared/test/geometric.test.ts create mode 100644 packages/shared/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 tsconfig.base.json diff --git a/.claude/handoffs/2026-04-28-104344-spec-approved-ready-for-plan.md b/.claude/handoffs/2026-04-28-104344-spec-approved-ready-for-plan.md new file mode 100644 index 0000000..1c6198c --- /dev/null +++ b/.claude/handoffs/2026-04-28-104344-spec-approved-ready-for-plan.md @@ -0,0 +1,180 @@ +# Handoff: Spec approved, ready for implementation plan + +## Session Metadata + +- Created: 2026-04-28 10:43:44 +- Project: /home/claude/bin/blind_chess +- Branch: not a git repo (yet — see Pending Work) +- Session duration: ~90 minutes (single brainstorming session) +- Recent commits: none — repo not initialized yet. + +## Handoff Chain + +- **Continues from**: [2026-04-28-kickoff.md](./2026-04-28-kickoff.md) + - Previous title: blind_chess Kickoff (2026-04-28) +- **Supersedes**: None + +> Review the previous handoff for full context before filling this one. + +## Current State Summary + +A 90-minute brainstorming session walked the project from "IDEA.md is populated" through every major architectural and gameplay decision and produced a complete design spec. Seth reviewed and approved each of the five design sections (architecture, data model, protocol, state machine, error handling/security/testing). The spec is on disk at `docs/superpowers/specs/2026-04-28-blind-chess-design.md`. Self-review applied four small fixes inline. **Seth ended the session before reviewing the written spec or invoking the `writing-plans` skill** — those are the next steps for the resuming agent. + +## Architecture Overview + +Designed (not yet implemented): + +- **Language/stack:** Node 22 + TypeScript, Fastify + `ws`, Svelte + Vite, `chess.js`. +- **Repo shape:** pnpm workspace, three packages — `packages/server`, `packages/client`, `packages/shared`. Shared types are the load-bearing decision: the WS protocol drift surface is high-risk. +- **State:** in-memory only (`Map`). No DB. Server restart drops active games — acceptable for MVP. +- **Engine:** `chess.js` for rules + a custom ~80-LoC `geometricMoves` helper for pseudo-legal moves (chess.js doesn't expose those). The helper is a pure function of `(piece, from, ownSquares)` — provably no opponent input — so it can run on both server (for the `no_legal_moves` check) and client (for highlighting). It lives in `packages/shared`. +- **Deploy:** new LXC on node-241, Caddy CT 600 routes `chess.sethpc.xyz` → port 3000, systemd-managed Node service. Single-port everything (HTTP + WS + static). +- **Security boundary:** `buildView(game, viewer)` is the *only* function that emits board state to clients. Blind-mode views literally omit opponent pieces from the wire — they are absent, not encrypted-but-present. + +## Critical Files + +| File | Purpose | Relevance | +|------|---------|-----------| +| IDEA.md | Original project brief from Seth | Source of truth for "what is this game"; read first | +| docs/superpowers/specs/2026-04-28-blind-chess-design.md | Full design spec | The canonical artifact — everything from this session is here | +| CLAUDE.md | Project identity + tagline + current state | Updated this session; loads on every session | +| DECISIONS.md | 16 architecture/implementation decisions + 12 deferred/rejected | Updated this session | +| .claude/handoffs/2026-04-28-kickoff.md | Previous handoff (project scaffold) | Read second | +| .gitignore | Excludes `.superpowers/` and `.backup/` | Created this session | +| .superpowers/brainstorm/2734300-1777384084/content/ | Visual companion artifacts (3 mockup HTMLs) | Browse historically; not part of project | + +## Key Patterns Discovered + +- **Mode = view filter, not different game.** Vanilla and blind share one `chess.js` instance; the difference is what `buildView()` returns to each player. +- **Moderator vocabulary is an enum, never a string.** Display text lives client-side. Tests assert against `ModeratorText` values like `'wont_help'`. +- **Moderator-vocabulary "errors" come through as `Announcement` on the `update` message, NOT as protocol `error`.** They're game events. `error` is reserved for protocol failures (malformed, rate-limited, slot taken). +- **Highlights in blind+ON are purely geometric.** Function of `(piece type, position, own-piece set)`. Rays extend through unseen opponents. Stop at own pieces. Off-board excluded. **Zero opponent info leak.** +- **Touch-move FSM is server-side.** `game.armed: { color, from }` is the entire state. `no_legal_moves` and `wont_help` checks fire only on first commit with a piece; once committed, all subsequent failed attempts are `illegal_move` with the touch staying. +- **Single `commit { from, to? }` message** handles both drag-start (no `to`) and drag-drop / destination-click (with `to`). Uniform server FSM through one handler. + +## Tasks Finished + +- Read kickoff handoff and IDEA.md +- Offered visual companion, Seth accepted (URL was http://steel141.local:50816 during session — server now stale) +- Q1 scope: locked vanilla+blind day-one, shared engine +- Q2 stack: locked Node + TypeScript + chess.js +- Q3 "wont help you" semantics: locked check-resolution interpretation +- Q4 touch-move FSM: locked tap-arms-reversible, drag/destination-click commits +- Q5 lobby flow (5 sub-defaults): all locked +- Q6 highlighting: locked geometric-only rule for blind+ON (rays extend through unseen pieces) +- Q7 final cleanup batch (6 items: persistence, time controls, deploy target, promotion, mobile, endgame): all confirmed +- Architecture: 3 approaches proposed (SvelteKit monolith / pnpm workspace / framework-free), Seth picked B +- 5 design sections presented in terminal, each individually approved +- Spec written: `docs/superpowers/specs/2026-04-28-blind-chess-design.md` +- Spec self-review: 4 fixes applied inline (Announcement payload for promotion, geometricMoves signature, castling+highlighting note, promotion-required-as-protocol-error) +- CLAUDE.md updated (tagline, Project Identity, current state, key files, conventions) +- DECISIONS.md updated (16 settled decisions, 12 deferred/rejected) + +## Files Modified + +| File | Changes | Rationale | +|------|---------|-----------| +| CLAUDE.md | Replaced placeholder tagline + Project Identity; added current state, key files, conventions | Was a stub before brainstorming; now reflects approved spec | +| DECISIONS.md | Filled in 16 architecture/implementation decisions and 12 deferred/rejected items | Captures everything Seth confirmed | +| docs/superpowers/specs/2026-04-28-blind-chess-design.md | New file — full design spec | Output of brainstorming session per skill workflow | +| .gitignore | New file — excludes `.superpowers/` and `.backup/` | `.superpowers/` is the visual-companion working directory | + +## Decisions Made + +See the full list in `DECISIONS.md` (16 architecture + implementation, 12 deferred/rejected). Highlights: + +| Decision | Options Considered | Rationale | +|----------|-------------------|-----------| +| Stack: Node + TS + Fastify + Svelte + chess.js | SvelteKit monolith / framework-free / Python+FastAPI / Go | Single-language top-to-bottom; shared types catch protocol drift; Svelte fits reactive board state | +| Highlighting (blind+ON) is purely geometric | "Safe" (legal-empty only) / Full / None | Provably zero opponent info leak; rule is `f(piece, position, ownSquares)` only | +| Moderator hierarchy refined to 4 tiers | 2-tier / 3-tier / 4-tier with pseudo-legal | Pseudo-legal vs. legal distinction lets `wont_help` reveal "king is the problem" without revealing why | +| `Announcement` is enum, not string | Free-form strings / structured enum | Tests assert on enum, i18n trivial via translation table | +| In-memory state only | SQLite from day one / in-memory + later SQLite | Hobby-scale; restart drops games is acceptable; SQLite is a 1-day add later | +| Single `commit` message for arm + move | Two messages (arm + move) / three / one | Uniform server FSM; one handler covers all transitions | +| Castling NOT highlighted in blind+ON | Highlight always / partial highlight / never | Castling legality depends on opponent state; partial reveal would leak; player can still execute manually | + +## Immediate Next Steps + +1. **Have Seth review the written spec.** It's at `docs/superpowers/specs/2026-04-28-blind-chess-design.md`. This is the gate the brainstorming skill required before invoking `writing-plans`, but the session ended before Seth read the written form. Ask: "I've got the spec written at ``. Please review and let me know if anything needs to change before I draft the implementation plan." If Seth requests changes, edit inline and re-ask. + +2. **Propose Gitea repo creation, with Seth's OK.** The kickoff handoff's deferred step 5: `git init` + `gitea create blind_chess` + `gitea remote blind_chess` + `gitea push`. The session ended before this happened. **Do not init the repo without Seth's explicit confirmation** — the kickoff said "propose creating a Gitea repo … Once direction is clear", and Seth ended the session without saying go. Use the `gitea` CLI from `~/bin/gitea`. + +3. **Invoke the `superpowers:writing-plans` skill.** This is the terminal state of the brainstorming process. The plan should decompose the spec into concrete implementation tasks. Skill location: per CLAUDE.md plugin list. + +## Blockers/Open Questions + +- **Spec review by Seth not yet done.** He approved each of the 5 sections in conversation but did not look at the written spec. Self-review found 4 fixes that he hasn't seen — most notably the `Announcement.payload` field for promotions and the castling+highlighting clarification. +- **No Gitea repo yet.** Project is on disk only. If the resuming agent loses this directory or it gets clobbered, the spec + decisions are gone. Backup: `.backup/` is gitignored but currently empty (no edits to backup). + +## Deferred Items + +All deferred/rejected items are in `DECISIONS.md` "Deferred / Rejected" section. The implementation plan should NOT plan for: + +- Spectator mode, time controls, SQLite persistence, E2E browser tests, Authentik gate, public lobby/matchmaking/ratings, client-side AI hints, PGN export, CI/CD automation. +- Stretch goal (deferred, not rejected): pre-deploy "server restarting" warning to active players. + +## Important Context + +**The whole project is currently a design spec on disk — no code exists yet.** The next session's job is to (1) get spec sign-off, (2) create the repo, (3) invoke `writing-plans` to produce an implementation plan. Do not jump to writing code; the brainstorming skill's terminal state is `writing-plans`, and writing-plans then becomes the input to a future implementation session. + +**Seth approved each of the 5 design sections in conversation, but did NOT review the assembled written spec.** The brainstorming skill explicitly requires user review of the written artifact before transitioning to writing-plans. The four self-review fixes (Announcement payload, geometricMoves signature, castling-highlighting note, promotion-required handling) were applied without Seth seeing them — they're small and not contentious, but he should glance at them. + +**The visual companion server (port 50816, `http://steel141.local:50816`) is no longer running.** It was started during the session and would have been auto-killed after 30 minutes of inactivity. Three mockup HTMLs are persisted in `.superpowers/brainstorm/2734300-1777384084/content/`: `welcome.html`, `highlighting.html` (v1, superseded), `highlighting-v2.html` (the corrected geometric rule, the one Seth approved), `waiting.html`. Don't restart the server unless the next session does more visual work. + +**`gameId` format `^[a-z0-9]{8}$` is small but adequate** — only 32 bits of entropy, but the link IS the auth, lives a single game's worth of time, and we have rate limiting. If at any point the link becomes long-lived (e.g., post-game replay URLs), bump to 12+ chars. + +**The `geometricMoves` helper is the most-tested piece of code in this design.** Six golden-path test cases cover the moderator hierarchy decision table. Make sure its test file is one of the FIRST things implemented — everything else depends on it being right. + +## Assumptions Made + +- Seth wants Svelte not React (he didn't push back; my recommendation stood). +- Seth wants Fastify not Express (same — accepted by silence). +- Seth's homelab has node-241 with capacity for one more LXC (true at the time of CLAUDE.md last-update; verify with `pct list` on node-241 if uncertain). +- "Moving that piece will not help you" is purely a king-safety announcement, not a tactical-evaluation one. Seth confirmed explicitly during the session. +- 8-character `gameId` is unique enough at this scale (~tens of concurrent games max). Birthday-collision math: ~60K games active before 1% chance of any pair colliding. Way more than this project will see. + +## Potential Gotchas + +- **chess.js does not expose pseudo-legal moves directly.** Don't try to compute the `no_legal_moves` / `wont_help` distinction by calling chess.js's `moves()` alone — that returns *legal* moves only. You need both the geometric set and the legal set. The spec's `geometricMoves` helper is the missing piece. +- **chess.js `inCheck()` checks the side-to-move.** After a move is applied, the side-to-move is the opponent. So `inCheck()` true after white's move means *black* is in check (which is what `${opp}_in_check` already says — but easy to invert by accident). +- **`Announcement.payload.promotedTo` was added in self-review.** If the implementation skips it, the `white_promoted` announcement carries no piece-type info and the opponent has to guess. Don't drop it. +- **The same-token-second-tab rule (last-connect-wins) is a security AND UX feature.** Without it, a malicious client could open many sockets per token and cause server-side resource leaks. Don't be tempted to "be more permissive" here. +- **Castling is NOT in `geometricMoves`.** This is intentional. If a future contributor adds castling targets to the king's geometric set "for completeness", they'll either leak opponent info (by checking castling-legality) or mislead users (by suggesting illegal castling). Comment in the helper explaining this. +- **The visual companion's `.superpowers/` dir is gitignored.** If you want to share mockups (e.g., commit them for posterity), copy them to `docs/` first. +- **Files referenced in this handoff that don't exist yet:** `deploy/Caddyfile.snippet` and the test files (e.g., `packages/server/test/unit/geometric.test.ts`) are forward references — they'll be created during implementation. Don't be alarmed when the validator flags them as missing. + +## Environment State + +### Tools/Services Used + +- **chess.js**: not yet installed; will be a dependency in `packages/server` (and possibly `packages/client` for vanilla mode legal-moves computation). Pin via `package.json` once init'd. +- **gitea CLI**: `~/bin/gitea`. Used for repo create + push. Token at `~/.config/gitea/token`. Documented in `~/bin/CLAUDE.md`. +- **pnpm**: required for workspace. Version 9+ recommended. +- **Node 22 LTS**: deployment target. Local dev should match. +- **Caddy CT 600** (192.168.0.185): existing. Add a `chess.sethpc.xyz` block to the Caddyfile when deploying. Spec includes a `deploy/Caddyfile.snippet` to be created during implementation. + +### Active Processes + +- **None.** The visual companion server self-terminated after 30 minutes of inactivity. No long-running tasks were started. + +### Environment Variables + +- `HOMELAB_PASSWORD`: set globally, used for SSH/SMB/etc. Not needed for blind_chess work directly. +- (No project-specific env vars yet.) + +## Related Resources + +- Spec: `docs/superpowers/specs/2026-04-28-blind-chess-design.md` +- Project identity: `CLAUDE.md` +- Decisions: `DECISIONS.md` +- Original brief: `IDEA.md` +- Kickoff handoff: `.claude/handoffs/2026-04-28-kickoff.md` +- Visual companion mockups (gitignored): `.superpowers/brainstorm/2734300-1777384084/content/` +- Global homelab context: `~/bin/CLAUDE.md` +- Project scaffold recipe: `~/bin/CREATE_PROJECT.md` +- Gitea CLI: `~/bin/gitea` +- chess.js (intended dep): https://github.com/jhlywa/chess.js + +--- + +**Security Reminder**: Before finalizing, run `validate_handoff.py` to check for accidental secret exposure. diff --git a/.claude/handoffs/2026-04-28-152000-mvp-deployed.md b/.claude/handoffs/2026-04-28-152000-mvp-deployed.md new file mode 100644 index 0000000..c1303c8 --- /dev/null +++ b/.claude/handoffs/2026-04-28-152000-mvp-deployed.md @@ -0,0 +1,181 @@ +# Handoff: MVP deployed and live + +## Session Metadata + +- Created: 2026-04-28 ~15:20 UTC (terminal session, single user-driven workflow run) +- Project: /home/claude/bin/blind_chess +- Branch: `main` +- Repo: `git.sethpc.xyz/Seth/blind_chess` +- Recent commits: see `git log` after the wrap-up commit on this session. +- Live URL: **https://chess.sethpc.xyz** + +## Handoff Chain + +- **Continues from**: [2026-04-28-104344-spec-approved-ready-for-plan.md](./2026-04-28-104344-spec-approved-ready-for-plan.md) +- **Supersedes**: None + +## Current State Summary + +Seth invoked the workflow `handoff -> implementation -> deployment -> update context -> create handoff -> git commit -> close session`. In one session: created the Gitea repo, scaffolded the pnpm workspace, implemented `packages/{shared,server,client}`, wrote 43 passing tests, deployed an LXC on node-241, configured Caddy + systemd, and verified the live URL handles game creation, the SPA fallback, WebSocket upgrade, and the per-player blind-mode view filter end-to-end. The previous handoff's deferred steps (spec sign-off, Gitea creation, writing-plans) were skipped per Seth's explicit workflow direction; he chose direct execution from the spec rather than another planning round. + +The application works. Black gets `white_moved` announcements while seeing only black's 16 pieces — the spec's central security property is verified on the live URL. + +## Architecture Overview + +Implemented (matches the design spec exactly with two intentional deviations noted below): + +- **pnpm workspace**, three packages, all on Node 22 + TS 5.9. +- `packages/shared/` exports types, the `ModeratorText` enum, the WS `ClientMessage`/`ServerMessage` types, and `geometricMoves()`. Built to `dist/`; `package.json` `main`/`exports` point at the compiled JS. +- `packages/server/` runs Fastify + `@fastify/websocket` + `@fastify/static`. Single port 3000 serves `/api/games` (REST), `/api/health`, `/ws` (WS upgrade), and the static client. SPA fallback serves `index.html` for any 404 with `accept: text/html`. +- `packages/client/` is Svelte 5 + Vite. Hash routing with a pathname fallback so both `/g/` (share URL) and `/#/g/` (post-create URL) render the game. +- **Deploy:** CT 690 on node-241 (192.168.0.245), Debian 12, Node 22.22.2, systemd unit `blind-chess.service` with hardening (`NoNewPrivileges`, `ProtectSystem=strict`, `ProtectHome`, restricted user `blindchess`). Caddy CT 600 reverse-proxies `chess.sethpc.xyz` → `192.168.0.245:3000`. DNS rides the existing `*.sethpc.xyz` wildcard. + +**Intentional deviations from spec:** + +1. **Click-to-move only** — drag-and-drop deferred. Tap-arm + tap-destination implements the touch-move FSM correctly and is identical on phone and desktop. (The FSM doesn't care which input mode produces the `commit` message.) +2. **No CapturedTray UI yet.** The spec's captured-pieces tray would derive from `moveHistory[].capturedPieceType`. Implementation deferred — moderator panel is the primary opponent-event channel. + +## Critical Files + +| File | Purpose | +|------|---------| +| `packages/shared/src/geometric.ts` | `geometricMoves(piece, from, ownSquares)`. Signature is the proof of zero opponent leak. 21 tests in `packages/shared/test/geometric.test.ts`. | +| `packages/shared/src/protocol.ts` | `ClientMessage`, `ServerMessage`, `ErrorCode` — single source of truth, no drift. | +| `packages/shared/src/moderator.ts` | `ModeratorText` enum, `Announcement` type. | +| `packages/server/src/view.ts` | `buildView()` — the security boundary. Test: `packages/server/test/unit/view.test.ts` (snapshot per-viewer, blind/active white view contains zero black pieces). | +| `packages/server/src/commit.ts` | Touch-move FSM. Test: `packages/server/test/unit/commit-fsm.test.ts` (hierarchy table rows 1, 1b, 2, 3, 5, 6 plus touch-move enforcement and promotion). | +| `packages/server/src/translator.ts` | chess.js `Move` → `ModeratorText[]`. Half-move clock is read from FEN field 4. | +| `packages/server/src/ws.ts` | The WS dispatch + broadcast logic. Largest file. Includes the same-token-second-tab supersede behavior. | +| `packages/server/src/server.ts` | Fastify bootstrap, routes, SPA fallback, janitor interval. | +| `packages/client/src/lib/Board.svelte` | The 8×8 grid, click-to-arm/click-to-commit. Imports `geometricMoves` from shared for highlights. | +| `packages/client/src/lib/Game.svelte` | The game page (board + moderator panel + actions + dialogs). Owns the WS connection lifecycle. | +| `packages/client/src/lib/stores/game.ts` | Reactive game state via Svelte 5 `$state`. Handles WS reconnect, token persistence, message dispatch. | +| `deploy/blind-chess.service` | systemd unit (canonical at `/etc/systemd/system/blind-chess.service` on CT). | +| `deploy/Caddyfile.snippet` | Reverse-proxy block already merged into `/etc/caddy/Caddyfile` on CT 600. | + +## Tasks Finished + +- Read prior handoff and the design spec +- Created Gitea repo `Seth/blind_chess` and pushed initial scaffold +- Set up pnpm workspace, root `package.json`, `tsconfig.base.json`, `pnpm-workspace.yaml` +- Implemented `packages/shared`: types, protocol, moderator enum, geometric helper. **21 tests passing.** +- Implemented `packages/server`: state, games registry, view filter, translator, FSM, validation (zod), rate limiter, WS dispatch, Fastify bootstrap. **22 tests passing** (including 4 real-WS integration tests). +- Implemented `packages/client`: Svelte 5 + Vite, Landing/Game/Board/ModeratorPanel/PromotionDialog, hash+pathname routing, dark theme with Sethflix orange (#D35400) accents. Built bundle: 57 KB JS / 8 KB CSS gzipped to ~22 KB total. +- Provisioned LXC CT 690 on node-241, installed Node 22 from NodeSource, created `blindchess` user, deployed artifacts via rsync. +- Created systemd unit, enabled + started service. +- Added Caddy block for `chess.sethpc.xyz` → 192.168.0.245:3000, validated and reloaded. +- Verified live URL handles `/api/health`, `/api/games`, `/`, `/g/` SPA fallback, `/assets/*`, and `wss:///ws` end-to-end including the per-player view filter. +- Updated `CLAUDE.md` (project state, ops notes), `DECISIONS.md` (implementation outcomes), `~/bin/CLAUDE.md` (project listing). + +## Files Modified / Added + +(Refer to `git log` and `git diff` for exhaustive lists.) + +| File | Changes | +|------|---------| +| (new) `package.json`, `pnpm-workspace.yaml`, `tsconfig.base.json`, `.npmrc` | Workspace root | +| (new) `packages/shared/**` | 4 source files, 1 test file, 21 tests | +| (new) `packages/server/**` | 9 source files, 3 test files, 22 tests | +| (new) `packages/client/**` | 8 source/component files, Vite/Svelte config | +| (new) `deploy/blind-chess.service`, `deploy/Caddyfile.snippet` | Deployment artifacts | +| `CLAUDE.md` | "Current State" updated to "deployed and live", added "Operations" section | +| `DECISIONS.md` | Added "Implementation outcomes" section with 9 entries | +| `.gitignore` | Added node_modules, dist, .deploy-server, etc. | +| `~/bin/CLAUDE.md` | blind_chess project entry updated to reflect deployed state | + +## Decisions Made + +All implementation decisions are recorded in `DECISIONS.md` "Implementation outcomes" (2026-04-28). Highlights: + +- chess.js v1.4.0; use `Move.isEnPassant()` etc., NOT the deprecated `flags` string. +- Half-move clock comes from FEN field 4 — chess.js doesn't expose it. +- Shared package's `package.json` exports point at `dist/`, never `src/`. Always build shared before server (project refs handle this on `pnpm -r build`). +- Click-to-move (no drag-and-drop) is the only input mode for now. +- Hash routing in the SPA, with a pathname fallback for share URLs. + +## Immediate Next Steps + +The MVP is functional. Order of likely follow-ups, not committed: + +1. **Manual phone + desktop play-test.** Send the URL to a friend and play a real game in both modes. Check edge cases the integration tests don't cover: castling kingside and queenside (both colors), en passant, threefold repetition, draw offer/decline cycle, simultaneous tabs (last-connect-wins). +2. **Drag-and-drop input.** Useful for desktop. Adds nontrivial complexity to `Board.svelte` (need to handle `pointermove`, ghost element, snapping). Probably 200–300 LoC. +3. **CapturedTray.svelte.** Derive from `moveHistory[].capturedPieceType` (server already supplies this in `MoveRecord`). Need to wire the move history through `update` messages — currently it's only computed server-side. +4. **More integration tests.** Specifically: castling end-to-end, en passant, both-sides simultaneous disconnect, 5-minute grace expiry. Each is ~30 LoC of test plus existing scaffolding. +5. **Uptime Kuma.** Add a probe for `https://chess.sethpc.xyz/api/health` returning `{"ok":true}`. +6. **Stretch:** SQLite persistence for crash recovery (1-day add: serialize Map on `ExecStop`, deserialize on `ExecStart`). + +## Blockers / Open Questions + +- **Spec was never reviewed in written form by Seth.** The previous handoff said this was a gate before implementing. Seth waived it implicitly by directing me into the implementation workflow. If he reviews `docs/superpowers/specs/2026-04-28-blind-chess-design.md` and finds something he doesn't like, the implementation may need surgery. The four self-review fixes in the spec (Announcement payload for promotion, geometricMoves signature, castling+highlighting note, promotion-required-as-protocol-error) were all faithfully implemented. +- **Public-internet exposure.** `chess.sethpc.xyz` is reachable from the public internet. The link IS the auth, but anyone who guesses an 8-char gameId could try to connect. With `^[a-z0-9]{8}$`, that's 36^8 ≈ 2.8 trillion possibilities; rate limiting on commits (10/s, burst 20) makes mass scanning impractical. **No rate limiting on `hello` messages or `POST /api/games`** — if abuse becomes a concern, add a per-IP token bucket on those endpoints. +- **Server restart drops active games.** Acceptable for MVP per spec, but be mindful when deploying updates during active play. + +## Deferred Items + +See `DECISIONS.md` "Deferred / Rejected" — unchanged from prior handoff. Implementation didn't add new deferred items beyond the two MVP-scope reductions: drag-and-drop and CapturedTray (both deferred, not rejected). + +## Important Context + +- **The deploy bundle directory `.deploy-server/`** is created by `pnpm --filter @blind-chess/server deploy --prod --legacy .deploy-server` and is gitignored. Don't commit it. It contains ~93 production deps including `@blind-chess/shared` resolved as a real package (via legacy symlink). +- **Re-deploying** is the same flow: `pnpm -r build` → `pnpm --filter @blind-chess/server deploy --prod --legacy .deploy-server` → `rsync -a --delete .deploy-server/ root@192.168.0.245:/opt/blind-chess/server/` → `rsync -a --delete packages/client/dist/ root@192.168.0.245:/opt/blind-chess/client/dist/` → `ssh root@192.168.0.245 'chown -R blindchess:blindchess /opt/blind-chess && systemctl restart blind-chess'`. +- **CT root access** is via the `claude` user's ed25519 pubkey (pushed via `pct exec` then `cat > authorized_keys`). A throwaway password was set during `pct create` and **rotated** to something not stored anywhere; recover via `pct exec 690 -- passwd root` from any cluster node if needed. The CT is a stateless game server — losing root access only means re-provisioning, which takes ~3 minutes. +- **The integration tests open ephemeral ports** via `listen({ port: 0 })`. They don't depend on 3000 being free. Do NOT change to fixed ports without thinking — that breaks parallel `vitest`. +- **Svelte 5 runes mode** is what's in use (`$state`, `$derived`, `$effect`). Don't try to mix in Svelte 3/4 reactive `$:` syntax. +- **The visual-companion mockups** from the brainstorm session (`.superpowers/brainstorm/2734300-1777384084/content/`) are still on disk and gitignored. They're stale relative to the implementation (the actual UI uses different colors, spacing, layouts) — don't use them as a reference. The implementation IS the reference now. +- **chess.js's `Move.flags` field is deprecated.** The implementation uses the `is...()` methods. Don't use `.flags` if extending the translator. +- **Same-token-second-tab is implemented.** Opening a second browser tab on the same gameId closes the first tab's socket with reason `superseded`. The displaced tab does NOT yet show a "now open in another tab" banner; it just disconnects. This is a UX gap, not a correctness gap. + +## Assumptions Made + +- Seth's workflow shorthand is binding direction. The previous handoff's "do not init repo without explicit OK" was overridden by the explicit `implementation->deployment` step. (If Seth disagrees, only the Gitea repo is reversible: `gitea delete blind_chess` undoes it cleanly.) +- 192.168.0.245 was free at the time of LXC creation; verified by ICMP. Conflict is unlikely on a homelab where IPs are hand-assigned. +- CT 690 was free; verified via `pct list`. The hostname `blind-chess` is unique on the cluster. +- Node 22 LTS via NodeSource is acceptable. (Debian 12's apt Node is way too old.) + +## Potential Gotchas + +- **`pnpm install` after pulling on a fresh machine** will warn `Ignored build scripts: esbuild`. That's fine — `auto-install-peers=true` in `.npmrc` prevents prompts but esbuild prompts to opt in to running its postinstall. Vite + Svelte work without it; the warning is benign. +- **Pino in production mode** does NOT use `pino-pretty` (only in dev). The systemd unit sets `NODE_ENV=production`; logs in journald are JSON. To pretty-print: `journalctl -u blind-chess -o cat | pnpx pino-pretty`. +- **Caddy auto-issues a TLS cert** on first hit of `chess.sethpc.xyz`. The first hit (during smoke testing) took a few hundred ms longer than subsequent hits while the cert was being provisioned; subsequent hits were ~30 ms. +- **Test FENs need a black king.** Two unit tests had to be re-FEN'd because chess.js rejects a FEN with no black king. Always include both kings in test positions. +- **Pawn-promotion test position** must give the pawn a legal move. `4k3/4P3/8/8/8/8/8/4K3` looks fine but the black king blocks `e8`, so the pawn can't legally advance, so the FSM emits `wont_help` instead of letting the promotion happen. Use `7k/...` (king elsewhere) when testing promotion. +- **`ModeratorText` enum strings use `white_X` / `black_X`, not `w_X` / `b_X`.** Translator interpolates `moverWord` (`'white'`/`'black'`), not `move.color` (`'w'`/`'b'`). Old draft conflated them. +- **Hash routing + path routing coexist.** The post-create flow updates `location.hash` to `#/g/` (no full navigation, no LE re-cert). The share URL goes through `/g/` and the SPA fallback. Both work; opening the share URL twice gives a clean state, hash form keeps the `gameId` in the URL after creator navigates back to landing — minor; not visible to the user in normal flow. + +## Environment State + +### Tools/Services Used + +- `pnpm` 10.33.2 (corepack-installed at `~/.local/bin/pnpm`) +- Node 22.22.2 (system, both on dev and on CT) +- `gitea` CLI (`~/bin/gitea`) for repo create + remote +- ssh to `pve241`, then `pct exec 690` initially, then direct `ssh root@192.168.0.245` after pubkey injection +- ssh to `caddy` for Caddyfile edit + reload +- vitest 3.2.4 + +### Active Processes + +- `blind-chess.service` on CT 690 (192.168.0.245). Started 2026-04-28 ~15:12 UTC. systemd-managed, restarts on failure. +- Caddy on CT 600 (192.168.0.185). Reloaded 2026-04-28 ~15:13 UTC after Caddyfile append. + +### Environment Variables + +- `BLIND_CHESS_CT_IP=192.168.0.245` (in caddy block, hardcoded; if migrating, also update Caddyfile) +- `PUBLIC_BASE=https://chess.sethpc.xyz` (set in the systemd unit) + +## Related Resources + +- Live URL: https://chess.sethpc.xyz +- Repo: https://git.sethpc.xyz/Seth/blind_chess +- Spec: `docs/superpowers/specs/2026-04-28-blind-chess-design.md` +- Project identity: `CLAUDE.md` +- Decisions: `DECISIONS.md` +- Original brief: `IDEA.md` +- Prior handoffs: `.claude/handoffs/2026-04-28-104344-spec-approved-ready-for-plan.md`, `.claude/handoffs/2026-04-28-kickoff.md` +- chess.js: https://github.com/jhlywa/chess.js (v1.4.0) +- Caddy config: `/etc/caddy/Caddyfile` on CT 600 — search for `chess.sethpc.xyz` +- Systemd unit (canonical): `/etc/systemd/system/blind-chess.service` on CT 690 + +--- + +**Security Reminder**: This handoff contains the CT root password and operational details. Do not share publicly. diff --git a/.claude/handoffs/2026-04-28-kickoff.md b/.claude/handoffs/2026-04-28-kickoff.md new file mode 100644 index 0000000..fb7dbb4 --- /dev/null +++ b/.claude/handoffs/2026-04-28-kickoff.md @@ -0,0 +1,57 @@ +# Handoff: blind_chess Kickoff (2026-04-28) + +## What was done + +Project scaffolded per `~/bin/CREATE_PROJECT.md`: +- `~/bin/blind_chess/` directory created +- `.claude/handoffs/` initialized (this is the first entry) +- `GITEA_API.md` symlinked to `~/bin/GITEA_API.md` +- `IDEA.md` created with empty template (Seth populates manually before next session) +- `DECISIONS.md` created from local template +- `CLAUDE.md` created with minimal stub pointing at IDEA.md as source of truth + +No code, no repo, no deploy target yet. Project is in pure ideation. + +## Current State + +- **Phase:** ideation, pre-IDEA.md +- **Repo:** none +- **Branch:** n/a +- **What's running:** nothing + +## Next Steps (ordered) + +**1. Read `IDEA.md` first.** +Seth has populated it manually with the project brief between this session and the next. It is the authoritative source for what blind_chess is and what it should do. Do not skip — `CLAUDE.md`'s "Project Identity" section is intentionally empty and will be filled in *after* IDEA.md is read. + +**2. Update `CLAUDE.md`.** +Distill IDEA.md into: +- A real one-line tagline (replace "Tagline TBD") +- A one-paragraph "Project Identity" section (stable, won't change session-to-session) +- Initial entries in "Current State" if any decisions emerged from IDEA.md (e.g., language choice, deploy target) + +**3. Capture early decisions in `DECISIONS.md`.** +Anything Seth committed to in IDEA.md (language, framework, deployment, naming, scope boundaries) goes into `DECISIONS.md` under Architecture or Implementation. Format: `YYYY-MM-DD: `. Include rejected options under "Deferred / Rejected". + +**4. Brainstorm before building.** +If IDEA.md leaves architecture or approach open, do not jump to implementation. Use the `superpowers:brainstorming` skill — explore intent and design first. Get Seth's confirmation on direction before code. + +**5. Decide on Gitea repo.** +The scaffold's optional step 6 (git init + Gitea push) was skipped. Once direction is clear, propose creating a Gitea repo via the `gitea` CLI: +```bash +cd ~/bin/blind_chess +git init +gitea create blind_chess +gitea remote blind_chess +echo "GITEA_API.md" >> .gitignore +git add -A && git commit -m "init: scaffold project" && gitea push +``` + +## Open Questions + +- None yet — IDEA.md will surface these. + +## Notes for the next session + +- Project name spelled `blind_chess` (underscore, not hyphen). Convention in `~/bin/` is hyphen, but underscore was Seth's explicit choice — likely for Python module compatibility. Don't auto-rename. +- Inherits all global homelab conventions from `~/bin/CLAUDE.md`. No need to duplicate them here. diff --git a/.gitignore b/.gitignore index aa4bb9c..f7feee2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ dist/ build/ .svelte-kit/ .vite/ +*.tsbuildinfo # Logs / coverage *.log @@ -26,3 +27,7 @@ coverage/ # Handoff workspace artifacts (kept local) .claude/handoffs/*.draft.md +.deploy-server/ + +# Local-only symlink to ~/bin/GITEA_API.md +GITEA_API.md diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..83ed98e --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +auto-install-peers=true +shamefully-hoist=false +ignore-workspace-root-check=true diff --git a/.secrets.baseline b/.secrets.baseline new file mode 100644 index 0000000..4fa71fa --- /dev/null +++ b/.secrets.baseline @@ -0,0 +1,6084 @@ +{ + "version": "1.5.0", + "plugins_used": [ + { + "name": "ArtifactoryDetector" + }, + { + "name": "AWSKeyDetector" + }, + { + "name": "AzureStorageKeyDetector" + }, + { + "name": "Base64HighEntropyString", + "limit": 4.5 + }, + { + "name": "BasicAuthDetector" + }, + { + "name": "CloudantDetector" + }, + { + "name": "DiscordBotTokenDetector" + }, + { + "name": "GitHubTokenDetector" + }, + { + "name": "GitLabTokenDetector" + }, + { + "name": "HexHighEntropyString", + "limit": 3.0 + }, + { + "name": "IbmCloudIamDetector" + }, + { + "name": "IbmCosHmacDetector" + }, + { + "name": "IPPublicDetector" + }, + { + "name": "JwtTokenDetector" + }, + { + "name": "KeywordDetector", + "keyword_exclude": "" + }, + { + "name": "MailchimpDetector" + }, + { + "name": "NpmDetector" + }, + { + "name": "OpenAIDetector" + }, + { + "name": "PrivateKeyDetector" + }, + { + "name": "PypiTokenDetector" + }, + { + "name": "SendGridDetector" + }, + { + "name": "SlackDetector" + }, + { + "name": "SoftlayerDetector" + }, + { + "name": "SquareOAuthDetector" + }, + { + "name": "StripeDetector" + }, + { + "name": "TelegramBotTokenDetector" + }, + { + "name": "TwilioKeyDetector" + } + ], + "filters_used": [ + { + "path": "detect_secrets.filters.allowlist.is_line_allowlisted" + }, + { + "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", + "min_level": 2 + }, + { + "path": "detect_secrets.filters.heuristic.is_indirect_reference" + }, + { + "path": "detect_secrets.filters.heuristic.is_likely_id_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_lock_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_potential_uuid" + }, + { + "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" + }, + { + "path": "detect_secrets.filters.heuristic.is_sequential_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_swagger_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_templated_secret" + } + ], + "results": { + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/README.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/README.md", + "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", + "is_verified": false, + "line_number": 30 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/README.md", + "hashed_secret": "99d72c7fc3e2e145870beab37c0b70e343ea9c3b", + "is_verified": false, + "line_number": 268 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/README.md", + "hashed_secret": "f0578f1e7174b1a41c4ea8c6e17f7a8a3b88c92a", + "is_verified": false, + "line_number": 297 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/README.md", + "hashed_secret": "8be52126a6fde450a7162a3651d589bb51e9579d", + "is_verified": false, + "line_number": 298 + } + ], + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/benchmarks/basic.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/benchmarks/basic.js", + "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", + "is_verified": false, + "line_number": 7 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/benchmarks/basic.js", + "hashed_secret": "85f602a05757ade9f2c88f8c776c3956e37caf68", + "is_verified": false, + "line_number": 15 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/benchmarks/basic.js", + "hashed_secret": "7875cece6721a517e5a07b61ef98a98dc7f9f329", + "is_verified": false, + "line_number": 18 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/benchmarks/basic.js", + "hashed_secret": "95bed8893257c7f3076cfbbb1c289d6236ac4741", + "is_verified": false, + "line_number": 29 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/benchmarks/basic.js", + "hashed_secret": "b3e277a7042b986c43fe84d88c0150bbb3c419cb", + "is_verified": false, + "line_number": 35 + } + ], + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/actual-redact-comparison.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/actual-redact-comparison.test.js", + "hashed_secret": "bf24ed6d137d9eccff42af195e9b9522b0fbe5ac", + "is_verified": false, + "line_number": 67 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/actual-redact-comparison.test.js", + "hashed_secret": "459b8fc02e0c426a40f40b598723ac3cbd4e56b8", + "is_verified": false, + "line_number": 78 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/actual-redact-comparison.test.js", + "hashed_secret": "de3ed0e3bdda715aa4384db6336c9dfd37fcc050", + "is_verified": false, + "line_number": 90 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/actual-redact-comparison.test.js", + "hashed_secret": "0ce476a8ad4caa93cbbb76ac7063eadde8c8eea4", + "is_verified": false, + "line_number": 104 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/actual-redact-comparison.test.js", + "hashed_secret": "bddbb60883595f03b926b75faacbc13e115f31f0", + "is_verified": false, + "line_number": 126 + } + ], + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", + "is_verified": false, + "line_number": 29 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "99d72c7fc3e2e145870beab37c0b70e343ea9c3b", + "is_verified": false, + "line_number": 50 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "00cafd126182e8a9e7c01bb2f0dfd00496be724f", + "is_verified": false, + "line_number": 99 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "c636e8e238fd7af97e2e500f8c6f0f4c0bedafb0", + "is_verified": false, + "line_number": 100 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "196eafc69f81f6158cf15138d7cec89bb4f64731", + "is_verified": false, + "line_number": 250 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", + "is_verified": false, + "line_number": 438 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "8107759ababcbfa34bcb02bc4309caf6354982ab", + "is_verified": false, + "line_number": 488 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "43f7aa390f1a0265fc2de7010133951c0718a67e", + "is_verified": false, + "line_number": 489 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/index.test.js", + "hashed_secret": "f32b67c7e26342af42efabc674d441dca0a281c5", + "is_verified": false, + "line_number": 742 + } + ], + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js", + "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", + "is_verified": false, + "line_number": 23 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js", + "hashed_secret": "99d72c7fc3e2e145870beab37c0b70e343ea9c3b", + "is_verified": false, + "line_number": 35 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js", + "hashed_secret": "00cafd126182e8a9e7c01bb2f0dfd00496be724f", + "is_verified": false, + "line_number": 60 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js", + "hashed_secret": "c636e8e238fd7af97e2e500f8c6f0f4c0bedafb0", + "is_verified": false, + "line_number": 61 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js", + "hashed_secret": "996f426ada8b2fab1ac7d009984397652fd79cb5", + "is_verified": false, + "line_number": 258 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/integration.test.js", + "hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511", + "is_verified": false, + "line_number": 280 + } + ], + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "bf24ed6d137d9eccff42af195e9b9522b0fbe5ac", + "is_verified": false, + "line_number": 10 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "459b8fc02e0c426a40f40b598723ac3cbd4e56b8", + "is_verified": false, + "line_number": 11 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "de3ed0e3bdda715aa4384db6336c9dfd37fcc050", + "is_verified": false, + "line_number": 12 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "0ce476a8ad4caa93cbbb76ac7063eadde8c8eea4", + "is_verified": false, + "line_number": 32 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "717851151f1dbdb7f1ddd503fe4e8d8cbfefd873", + "is_verified": false, + "line_number": 59 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "dbdab9be92cacdae6a97e8601332bfaa8545800f", + "is_verified": false, + "line_number": 83 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4", + "is_verified": false, + "line_number": 126 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "00cafd126182e8a9e7c01bb2f0dfd00496be724f", + "is_verified": false, + "line_number": 182 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/multiple-wildcards.test.js", + "hashed_secret": "c636e8e238fd7af97e2e500f8c6f0f4c0bedafb0", + "is_verified": false, + "line_number": 183 + } + ], + "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/selective-clone.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/selective-clone.test.js", + "hashed_secret": "3d9b019e2f6692d0f08f59ae7e534539fbe9a601", + "is_verified": false, + "line_number": 40 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/selective-clone.test.js", + "hashed_secret": "196eafc69f81f6158cf15138d7cec89bb4f64731", + "is_verified": false, + "line_number": 41 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@pinojs+redact@0.4.0/node_modules/@pinojs/redact/test/selective-clone.test.js", + "hashed_secret": "99d72c7fc3e2e145870beab37c0b70e343ea9c3b", + "is_verified": false, + "line_number": 85 + } + ], + "node_modules/.pnpm/@types+chai@5.2.3/node_modules/@types/chai/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+chai@5.2.3/node_modules/@types/chai/package.json", + "hashed_secret": "1e55f0127cd102be037f6505c7158576853471af", + "is_verified": false, + "line_number": 73 + } + ], + "node_modules/.pnpm/@types+deep-eql@4.0.2/node_modules/@types/deep-eql/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+deep-eql@4.0.2/node_modules/@types/deep-eql/package.json", + "hashed_secret": "627873dc429703698cd7a66d07490b029a9ffc52", + "is_verified": false, + "line_number": 23 + } + ], + "node_modules/.pnpm/@types+estree@1.0.8/node_modules/@types/estree/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+estree@1.0.8/node_modules/@types/estree/package.json", + "hashed_secret": "23e230d08d037c7cfa5e947aef7fe0d177228259", + "is_verified": false, + "line_number": 24 + } + ], + "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/crypto.d.ts": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/crypto.d.ts", + "hashed_secret": "c4baf1bdf18f073485f2d19bb0bf096a17799931", + "is_verified": false, + "line_number": 788 + }, + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/crypto.d.ts", + "hashed_secret": "0658bfe8c79e41bf665348467c98bb06ee37ec8a", + "is_verified": false, + "line_number": 1073 + } + ], + "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/http.d.ts": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/http.d.ts", + "hashed_secret": "76bf9d6b63fae3a144a091047394129561d3ad22", + "is_verified": false, + "line_number": 769 + } + ], + "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "7e3f4362d67c7ac7f04804573e72161c7ba4a76c", + "is_verified": false, + "line_number": 459 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "355703785ceab653b7300914746f8cf2ca4fedb7", + "is_verified": false, + "line_number": 526 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "cef32cb56314ed0482ca4adae449c601524dec21", + "is_verified": false, + "line_number": 526 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "266203ae6fa238e6ee38dccb8107c4bd65671d5a", + "is_verified": false, + "line_number": 527 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "334cbfbbd3dc70599cb7658986364847643d58a2", + "is_verified": false, + "line_number": 527 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "781dc36af9a61812810dd161628a1bacca187fde", + "is_verified": false, + "line_number": 527 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "5bd62e755cb0b2fcb341bbab9e6c15482eede705", + "is_verified": false, + "line_number": 528 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/https.d.ts", + "hashed_secret": "d591eb4e61658fd67e71fdf170759cc68d2483f0", + "is_verified": false, + "line_number": 528 + } + ], + "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+node@22.19.17/node_modules/@types/node/package.json", + "hashed_secret": "c5b1b1cacc03d52864bd06aead44f2063a943168", + "is_verified": false, + "line_number": 143 + } + ], + "node_modules/.pnpm/@types+trusted-types@2.0.7/node_modules/@types/trusted-types/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+trusted-types@2.0.7/node_modules/@types/trusted-types/package.json", + "hashed_secret": "a6290f9a8ed440aed10986e949765321fa8b8b06", + "is_verified": false, + "line_number": 43 + } + ], + "node_modules/.pnpm/@types+ws@8.18.1/node_modules/@types/ws/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/@types+ws@8.18.1/node_modules/@types/ws/package.json", + "hashed_secret": "3d9b3bfd6a8282d71c84c088bace12ef2204b123", + "is_verified": false, + "line_number": 70 + } + ], + "node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/index.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/@vitest+utils@3.2.4/node_modules/@vitest/utils/dist/index.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 544 + } + ], + "node_modules/.pnpm/chess.js@1.4.0/node_modules/chess.js/README.md": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/chess.js@1.4.0/node_modules/chess.js/README.md", + "hashed_secret": "ce45a26c908223d3dbc98c2277fc07658acbf622", + "is_verified": false, + "line_number": 349 + } + ], + "node_modules/.pnpm/es-module-lexer@1.7.0/node_modules/es-module-lexer/dist/lexer.cjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/es-module-lexer@1.7.0/node_modules/es-module-lexer/dist/lexer.cjs", + "hashed_secret": "c2c8002d50715475a1f593d36f386b7d71f2bfe1", + "is_verified": false, + "line_number": 1 + } + ], + "node_modules/.pnpm/es-module-lexer@1.7.0/node_modules/es-module-lexer/dist/lexer.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/es-module-lexer@1.7.0/node_modules/es-module-lexer/dist/lexer.js", + "hashed_secret": "c2c8002d50715475a1f593d36f386b7d71f2bfe1", + "is_verified": false, + "line_number": 2 + } + ], + "node_modules/.pnpm/events@3.3.0/node_modules/events/.travis.yml": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/events@3.3.0/node_modules/events/.travis.yml", + "hashed_secret": "3e77e00ec038f73930e6b7adbf78e46c64eebf08", + "is_verified": false, + "line_number": 17 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/events@3.3.0/node_modules/events/.travis.yml", + "hashed_secret": "a0345eb9ebe10ee8f44ac619209ebd3ff96adc0b", + "is_verified": false, + "line_number": 18 + } + ], + "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/README.md": [ + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/README.md", + "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", + "is_verified": false, + "line_number": 41 + } + ], + "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/fixtures/uri-js-parse.json": [ + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/fixtures/uri-js-parse.json", + "hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684", + "is_verified": false, + "line_number": 78 + }, + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/fixtures/uri-js-parse.json", + "hashed_secret": "d7cd56f2a2a3f47830760edfb89946eb7b9e2cd1", + "is_verified": false, + "line_number": 104 + } + ], + "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/fixtures/uri-js-serialize.json": [ + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/fixtures/uri-js-serialize.json", + "hashed_secret": "62cdb7020ff920e5aa642c3d4066950dd1f01f4d", + "is_verified": false, + "line_number": 74 + } + ], + "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/serialize.test.js": [ + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/serialize.test.js", + "hashed_secret": "62cdb7020ff920e5aa642c3d4066950dd1f01f4d", + "is_verified": false, + "line_number": 38 + } + ], + "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/uri-js.test.js": [ + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/uri-js.test.js", + "hashed_secret": "62cdb7020ff920e5aa642c3d4066950dd1f01f4d", + "is_verified": false, + "line_number": 316 + }, + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/test/uri-js.test.js", + "hashed_secret": "32a0d67da7f6bc03fa239fe9a1e789e20f616fac", + "is_verified": false, + "line_number": 496 + } + ], + "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/docs/Guides/Database.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/docs/Guides/Database.md", + "hashed_secret": "c3499c2729730a7f807efb8676a92dcb6f8a3f8f", + "is_verified": false, + "line_number": 286 + } + ], + "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/docs/Reference/Routes.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/docs/Reference/Routes.md", + "hashed_secret": "beb371d0dc505d6be5091cb95db258dcae78b12f", + "is_verified": false, + "line_number": 267 + } + ], + "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/docs/Reference/Server.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/docs/Reference/Server.md", + "hashed_secret": "5c5a15a8b0b3e154d77746945e563ba40100681b", + "is_verified": false, + "line_number": 1538 + } + ], + "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/constrained-routes.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/constrained-routes.test.js", + "hashed_secret": "be76331b95dfc399cd776d2fc68021e0db03cc4f", + "is_verified": false, + "line_number": 134 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/constrained-routes.test.js", + "hashed_secret": "a295e0bdde1938d1fbfd343e5a3e569e868e1465", + "is_verified": false, + "line_number": 143 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/constrained-routes.test.js", + "hashed_secret": "ff70f4c33de2200b76651bbe1e54aa55fcd77447", + "is_verified": false, + "line_number": 178 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/constrained-routes.test.js", + "hashed_secret": "7d018bb3df0e523692845af1f27e992ce8a41650", + "is_verified": false, + "line_number": 284 + } + ], + "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/router-options.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/fastify@5.8.5/node_modules/fastify/test/router-options.test.js", + "hashed_secret": "be76331b95dfc399cd776d2fc68021e0db03cc4f", + "is_verified": false, + "line_number": 298 + } + ], + "node_modules/.pnpm/find-my-way@9.5.0/node_modules/find-my-way/README.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/find-my-way@9.5.0/node_modules/find-my-way/README.md", + "hashed_secret": "ecf5592666037e48e243f8cf991837fa3f64e069", + "is_verified": false, + "line_number": 175 + } + ], + "node_modules/.pnpm/find-my-way@9.5.0/node_modules/find-my-way/test/issue-254.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/find-my-way@9.5.0/node_modules/find-my-way/test/issue-254.test.js", + "hashed_secret": "be76331b95dfc399cd776d2fc68021e0db03cc4f", + "is_verified": false, + "line_number": 27 + } + ], + "node_modules/.pnpm/lock.yaml": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "d1b8345cd5758682c4e2be076930b6dee81a8f0a", + "is_verified": false, + "line_number": 98 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4fc407ff3fa666522e784402874b39ccaa9b9084", + "is_verified": false, + "line_number": 104 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "34fc2e926d119d522332afcf0b1e31be4943e728", + "is_verified": false, + "line_number": 110 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6e53b1d7147a431758aded05223f60a6cf8404b6", + "is_verified": false, + "line_number": 116 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ee9277ef9d8d4012e1b5e779ec43d5b9ec480348", + "is_verified": false, + "line_number": 122 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "21094ab4fc5b3c4b172a28c6e96d474b60d8f176", + "is_verified": false, + "line_number": 128 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b51ddd35a554c659b500b4c1169692da4f6cee67", + "is_verified": false, + "line_number": 134 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "57902bee1f6a5e12ed03dd3b3281ab07318ff81f", + "is_verified": false, + "line_number": 140 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "552658965b8efb6ebaf095b54636a6d54c8e4a6b", + "is_verified": false, + "line_number": 146 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3cfe66e44a47be9aa1a2b2570d4e6ca4fe8646d6", + "is_verified": false, + "line_number": 152 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "04e50569b26a331d6327f95e0a43e04435017c25", + "is_verified": false, + "line_number": 158 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6e9116d6ceb830c0e81b752f03b594c04b867404", + "is_verified": false, + "line_number": 164 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f427b0533ef2217b7b65d4be9d69dfb98e234645", + "is_verified": false, + "line_number": 170 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "92eb7bfdfe82cc5019dea1ead34c876de720e71f", + "is_verified": false, + "line_number": 176 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3f10b09e053c0d12d409925cdbee129e15aee7ee", + "is_verified": false, + "line_number": 182 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f83beff54841a17222f2c5d542077e07f0a640ce", + "is_verified": false, + "line_number": 188 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7cb36fd100cc7d0102797bb6a79a28f2c4a2a33d", + "is_verified": false, + "line_number": 194 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "de1558a98424f61bb30fd681ab33ebe9ac162b93", + "is_verified": false, + "line_number": 200 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2acca17ade2dd33b015ab19d80c162e241749350", + "is_verified": false, + "line_number": 206 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "0609a7c3993cb0b98d835bd299b5e78674c1c4e6", + "is_verified": false, + "line_number": 212 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "970ba53b3d18d68bf94e8458ec9c1b6326188d4f", + "is_verified": false, + "line_number": 218 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7cd72661910d8f1eae72b0783a01c7dcdb990036", + "is_verified": false, + "line_number": 224 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5d012814b5566671037c067991ea81d19cd07cbf", + "is_verified": false, + "line_number": 230 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c5b024f5526693865d3af7324ab65fc3ab1605fa", + "is_verified": false, + "line_number": 236 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "e0ed8c59207e32883f7f1b4b33356054c4214245", + "is_verified": false, + "line_number": 242 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7ea3a0d38529d3159199bb46bcf538993729a4ca", + "is_verified": false, + "line_number": 248 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "fa4f8c78da34eeb842b7c58de563aa7feabcb7b9", + "is_verified": false, + "line_number": 254 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "abac0dd92435eb969522a0ad244a7d5d3bcf9c90", + "is_verified": false, + "line_number": 260 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "762142615ab1dc453cd4c6e0d16d9abff71f7c3b", + "is_verified": false, + "line_number": 266 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "039980936156bd5bc0de9e386f1e385a9bbabcf0", + "is_verified": false, + "line_number": 272 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6385b43929b2ca3cd3fc11ddc7c9429aa6799e95", + "is_verified": false, + "line_number": 278 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ff2f515b75e908a3a079d6b0cf692f65bec13192", + "is_verified": false, + "line_number": 284 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3f729bd8163365c1bc85737b1a5091cb37d83829", + "is_verified": false, + "line_number": 290 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "43b4d7cc77f29c50ebc0ae65cdd5ae53c4610b89", + "is_verified": false, + "line_number": 296 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "00fbf776f031ec28f109bdb0502c86883d29ac01", + "is_verified": false, + "line_number": 302 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4080ae8ed6a6391c581edbf27618aa0806118784", + "is_verified": false, + "line_number": 308 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "afabc9199b55dca97a779220cf30689beace5333", + "is_verified": false, + "line_number": 314 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3e24f346b7ed723f027041976b3d2e7b555ebd90", + "is_verified": false, + "line_number": 320 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7cdd98d664bd97065578d2af7b793094d23fedb7", + "is_verified": false, + "line_number": 326 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2b88177306d91942e3df15d0361c1fd5125db60a", + "is_verified": false, + "line_number": 332 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "611d19d8a4d5842d0970db276cdd09ae44de3df6", + "is_verified": false, + "line_number": 338 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "68d8df9678250f3f17e3c6e65e8e29e1007cd5ba", + "is_verified": false, + "line_number": 344 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "20e89c354326f9aebacc5df3bcb782d7b36edf88", + "is_verified": false, + "line_number": 350 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a1d2a1836521ff0216663ecd5526c0a53ce86a4d", + "is_verified": false, + "line_number": 356 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ff07375cb2a21e51b33412e3316544b3c5d575a1", + "is_verified": false, + "line_number": 362 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b1265b06c14c30da47639c2ed791f50c8d80227f", + "is_verified": false, + "line_number": 368 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c93372223d2b5bbe594d85bfc0d21dfafea217b5", + "is_verified": false, + "line_number": 374 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "17e8e3b6a6567490ad87c92962f2fe73df1a95e3", + "is_verified": false, + "line_number": 380 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6e1232ec19c19bb978ed3a5bf123312c5648df9d", + "is_verified": false, + "line_number": 386 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b9ed31d4313f86c359571fc1caeced011e1549c8", + "is_verified": false, + "line_number": 392 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5fd341ad5e6bff70186ba90c6b39ca49c19fe297", + "is_verified": false, + "line_number": 398 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9234d6da8ceb8786f9a95485ab027085c326afee", + "is_verified": false, + "line_number": 404 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5fe3acc13d078fe4f1dc5c153bdb8514f78c1dd9", + "is_verified": false, + "line_number": 410 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6ebe9d7b6feeca2cbb04503532b053496601ea4c", + "is_verified": false, + "line_number": 413 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4c8137bba4c60ac8c70aa9dc26f17b833b0485b5", + "is_verified": false, + "line_number": 416 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "bf0f532d4fa6ce4da69534acc295afe5d9dce2d8", + "is_verified": false, + "line_number": 419 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "0a46ec56e14c6b0f3988c65531be78c66569c035", + "is_verified": false, + "line_number": 422 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "824b72098dc6947718d316f436bb00fbe3f3f3b5", + "is_verified": false, + "line_number": 425 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "11098cf4a6594cded115edc443cb1d6c38956f3b", + "is_verified": false, + "line_number": 428 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "bd79cc98321f7be3a979a8ecf9deedc8aba70a27", + "is_verified": false, + "line_number": 431 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a250c23ee71fb585be959874180b87fc5565084e", + "is_verified": false, + "line_number": 434 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "0da9ffd747e36f3c422029e7099e27dd5ccb412c", + "is_verified": false, + "line_number": 437 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1b3495fbdeef2dee0dc3f2ca206965663474a3d7", + "is_verified": false, + "line_number": 440 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8733ba82d33885a92ca3009eb6ba61e505a1ee9a", + "is_verified": false, + "line_number": 444 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3e3522c83d724aa4133ee6bb6d627e4390be31a5", + "is_verified": false, + "line_number": 447 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9d1b9dbec9f048e048f4dd38591947ca7deff5dd", + "is_verified": false, + "line_number": 450 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f60c00cacddf514ad090fbde7005d8721adc0b89", + "is_verified": false, + "line_number": 454 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b0e9cbf320ebe74507bcdaae3f0b40740459a092", + "is_verified": false, + "line_number": 457 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "393b2680ecbbb743a86d0b44313313f5d77ff202", + "is_verified": false, + "line_number": 460 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "559cb512c616ae4934092a7ceb3d42239213543d", + "is_verified": false, + "line_number": 464 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "80baf094c85a8b814390721f28df4426791950e2", + "is_verified": false, + "line_number": 467 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "19c871b99cc8a8066f7c372cc935250508cdbf7e", + "is_verified": false, + "line_number": 472 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "66eb29da9a96876a8e1b7fefb901f6b582e14b33", + "is_verified": false, + "line_number": 477 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5ce412f8142bfcc2b11a375e1c91a3a54ca8c0ae", + "is_verified": false, + "line_number": 482 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3e47d4fda361e2553fee0d1f059b0b135fcce98f", + "is_verified": false, + "line_number": 487 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7ce2d9200e0e41b2ee19b821089b6a95a39bc509", + "is_verified": false, + "line_number": 492 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b68b16505cf49c5f3cb98af1b54893a1a79565a5", + "is_verified": false, + "line_number": 497 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b41be781eb3b0c4750e39d09dcdd6a3494f1f357", + "is_verified": false, + "line_number": 503 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f99a49bc745631a8b7085149e82a79811d9bac8c", + "is_verified": false, + "line_number": 509 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "edeb02a82bcc0b255ba89f276f37e4091792f4fe", + "is_verified": false, + "line_number": 515 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7691f9054b1626b357caca8a9f8e83eb8ac84def", + "is_verified": false, + "line_number": 521 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b77dfdeb5ffee23aff3b2f97ff640802ad415a3c", + "is_verified": false, + "line_number": 527 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "94297c922da678a24c4fc963af0da51d961d8fe5", + "is_verified": false, + "line_number": 533 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1f0eb8fb4434346c68f359042c9fc254c1c46be6", + "is_verified": false, + "line_number": 539 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5d67ae5d1c2f8a622e078f0d8d16670619aa561e", + "is_verified": false, + "line_number": 545 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "fee3efd07b8abcb9d734d6f324253508f7501156", + "is_verified": false, + "line_number": 551 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1380cb2734346cc00e41eb54cdd94860f4859e2c", + "is_verified": false, + "line_number": 557 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5aea3dce81939048d287d7761e40642490194d09", + "is_verified": false, + "line_number": 563 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "11487ba85b40245c0bb0e34846085b8714439652", + "is_verified": false, + "line_number": 569 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9f2824e8182be80a655c1164a0c7d043abe0b2e8", + "is_verified": false, + "line_number": 575 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "87bb0e1e3669074c5cda58de04798789e0eda61d", + "is_verified": false, + "line_number": 580 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5423261b835b9649ae476fc59e957f6cb03b2369", + "is_verified": false, + "line_number": 585 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c62e701dc37732b77d24e97d4676d597a1e1ce41", + "is_verified": false, + "line_number": 590 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "58a0c6f04ab904bada0f96e79f61f7633b8e8554", + "is_verified": false, + "line_number": 595 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5ac63bbb4857e2c672bef90951ed012b5e1a3099", + "is_verified": false, + "line_number": 600 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "0e08e31e43853476fc57d10643d8c871082c08b3", + "is_verified": false, + "line_number": 605 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b31d08ed4329a2b257e3183cdb4917a06ff76acf", + "is_verified": false, + "line_number": 610 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b74484fafbbaf80a55364e035669088e7fd44b6c", + "is_verified": false, + "line_number": 618 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7739c7a36e8b5c9759887d54c3d3a252d017cb71", + "is_verified": false, + "line_number": 625 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "d4dda0583372eb865e22ea00ae160ceb315aa0df", + "is_verified": false, + "line_number": 628 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "904dae7e3147870781ad476afdbc281061d76e62", + "is_verified": false, + "line_number": 631 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4a96348ad16d0abe922e3e2c78b1b4d82a9b3f07", + "is_verified": false, + "line_number": 634 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5f411c7e6073b67aca1c9043e3e952322dc21d46", + "is_verified": false, + "line_number": 637 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "618a8148c9899b3b6bd69562f235038dc7953718", + "is_verified": false, + "line_number": 640 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5c4d2062f4b9170e2571cfe2b901592767edc7cd", + "is_verified": false, + "line_number": 643 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2a04ad8254d18f2f4403c9056e67951c1e0fb0a5", + "is_verified": false, + "line_number": 646 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a7655c0dea3997e8ee27a2090dc9eb749a7b1282", + "is_verified": false, + "line_number": 657 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2c684cbb0ceecbae320bff3152c0f2b1b3434c7e", + "is_verified": false, + "line_number": 660 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6ff1feade4ea98d27ec8f31fa2dbcfd3d2a5028f", + "is_verified": false, + "line_number": 663 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "359e9803b99c38d739e61ade83000c2ab5a22448", + "is_verified": false, + "line_number": 666 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b0af613d49499b2f6f2643ef7acf1a219e9e6fb6", + "is_verified": false, + "line_number": 669 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "86c936c2fd0b15334fb3e7e08ea42b385c42f7a1", + "is_verified": false, + "line_number": 672 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a3fde05f04dec549057c3104497d942072394189", + "is_verified": false, + "line_number": 676 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b2c03df0ed8f8caded3abab58c3b2e3b645dbb28", + "is_verified": false, + "line_number": 679 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4f6636587fecd2341ba754a447e6a26db011795f", + "is_verified": false, + "line_number": 684 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "07860d1f8563c118dfa14b8c27bfef9420e3f8c2", + "is_verified": false, + "line_number": 692 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5bb90e7e3d7847438b155c9fb564dfd279383855", + "is_verified": false, + "line_number": 695 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1c504c77e2b9f1ea0e1770e65673fd7f8b3f4c8f", + "is_verified": false, + "line_number": 699 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "6f5c4f8389922a6637a0b4fdb837095b494c0bfb", + "is_verified": false, + "line_number": 703 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "38604ae508f167b156742a5c072915272fb37857", + "is_verified": false, + "line_number": 707 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4a6acdb47bbd22c85e10baf5921ddbb3c09a787b", + "is_verified": false, + "line_number": 710 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "e0ed71a4c2836a6a251bef5e00b00401cfac286d", + "is_verified": false, + "line_number": 714 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7bb507ba2f47095177b03051a6340091be5871b2", + "is_verified": false, + "line_number": 718 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5389eb7ce46c53e5d6adc57d5bafb1180870b814", + "is_verified": false, + "line_number": 721 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9748716a465dd6d055354fd346c4cd105b7d39b1", + "is_verified": false, + "line_number": 725 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c56c76bc828483f5553df346fb2eaa6e3e6c4bba", + "is_verified": false, + "line_number": 728 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5620b727309eb0585715c051b3f1ad6560879967", + "is_verified": false, + "line_number": 732 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "fd40953175f0c99e010e94312afacb63e7f1a817", + "is_verified": false, + "line_number": 736 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8095985919187b5be33de4b775c7a5e7562aafee", + "is_verified": false, + "line_number": 740 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8ff61e34bccd3c9f85c8a24db9723d984fd74314", + "is_verified": false, + "line_number": 743 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5974b42acc3c558a08c734a45a10785534b5d382", + "is_verified": false, + "line_number": 747 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1dae660604ec052e4c8dfd54b0657636c412a22b", + "is_verified": false, + "line_number": 751 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f52956fa7c317746fde250d0f4e54d6115252cd4", + "is_verified": false, + "line_number": 754 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8f16039bc2ed9b93d8e319897b70cb25f25dfcc4", + "is_verified": false, + "line_number": 758 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "862951cd71d0412b5e52bae3e952725486a655b0", + "is_verified": false, + "line_number": 762 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ab4bcd85dbb08e2c7721a4842f74653506829466", + "is_verified": false, + "line_number": 766 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "d45062677e99f28b9a98f4b53e9af8f56b01bb10", + "is_verified": false, + "line_number": 769 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b4a9257558064dbd957e726d9d25d81b97837009", + "is_verified": false, + "line_number": 778 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c0c7aeed5e5a888b2aa3cdb739955fd27d25335e", + "is_verified": false, + "line_number": 782 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c5deff9c59d0e0419952da44431546620804d70e", + "is_verified": false, + "line_number": 786 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "d031e18cc14e54a719197084af4cd6b2372fd005", + "is_verified": false, + "line_number": 790 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "183c0616018161acd77ce39914e9bb5a22fcae49", + "is_verified": false, + "line_number": 794 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "309db07fa3cab58e7ea5fc5ba8f629a4430fa6a6", + "is_verified": false, + "line_number": 797 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "fc231c807593551488e1df5cd5d488e39f7db93f", + "is_verified": false, + "line_number": 800 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "d076e5a9f2245bcedf234f70abb7fa41d4d9f0dc", + "is_verified": false, + "line_number": 803 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "bf4a0e0cb4a648f94a1ceff84d8070ab01b0df0e", + "is_verified": false, + "line_number": 806 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "cab616f3cdb6eb3c372039eeae16f83314439923", + "is_verified": false, + "line_number": 811 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "cc0394ae9ff7278ac1f8ba8305e06627798ae34b", + "is_verified": false, + "line_number": 816 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4a1a266072e5f401e1aa928a9bf6d94bfeab4806", + "is_verified": false, + "line_number": 819 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "50c2ef2e538e117e2c5cb97fd9678257c05daea1", + "is_verified": false, + "line_number": 822 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "763f4272f5426f2cb52dd90f1f6a490a4ce61418", + "is_verified": false, + "line_number": 830 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "bdc1322162b3c2d06c4103afb50937bf6085ebf2", + "is_verified": false, + "line_number": 833 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3446aea3a08fd97b7eb1beac15a525d1b4586864", + "is_verified": false, + "line_number": 837 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "16d0c877fca994fd1c43bd7f131be967bf4f87b6", + "is_verified": false, + "line_number": 841 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "373eefae8f0bb627d355aa0997dbf702a2274642", + "is_verified": false, + "line_number": 845 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c7018ff5fd96eec2abbadb93bb97d56f00235687", + "is_verified": false, + "line_number": 848 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c0f64a532897bbd5497996fdfec7cfcd087540ce", + "is_verified": false, + "line_number": 851 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4e742e60616be1578b81769f2ffd9bef51586512", + "is_verified": false, + "line_number": 854 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5ffcc7770e283fe45a96c1ba2bc21dd7f38458b5", + "is_verified": false, + "line_number": 857 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "38a37f53e7403dabad025e1d953382e82ff53762", + "is_verified": false, + "line_number": 860 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a175423c144b95f8ef14eca365738012ae8ff166", + "is_verified": false, + "line_number": 863 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2f00e7db8ba09014a8f7ae078346fd4630c8ee54", + "is_verified": false, + "line_number": 866 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b3edf680cb58f88cd49833b666c6c1b310fd4c90", + "is_verified": false, + "line_number": 869 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "02031683c4d321f8660ff8b2d0258362940c8a6d", + "is_verified": false, + "line_number": 872 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "16fa3bfaeef78e32910c87baf9060e51490d09ad", + "is_verified": false, + "line_number": 875 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "74f497c18c464bd0d65adca16a8e96c0fafeefcb", + "is_verified": false, + "line_number": 884 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3aa0faf721de27687f7be4cc9ed4e61c745e6e44", + "is_verified": false, + "line_number": 888 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "d950cd8ef510429f57fb282e4a437321ca86158c", + "is_verified": false, + "line_number": 892 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3ad5ab41a177a3b1dbc7cc007170bfcc93c0607a", + "is_verified": false, + "line_number": 897 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5d204787c8c7979085337870c453871dbe65cb84", + "is_verified": false, + "line_number": 900 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4648471e6e277a4eb3eb85ed4ef695b6bfabe451", + "is_verified": false, + "line_number": 906 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9bad76463ceffd240ee9bd95c3faa98c0a4b94d0", + "is_verified": false, + "line_number": 909 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "82bb8edb4003308fc261a3cd2488be9862e99657", + "is_verified": false, + "line_number": 913 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "cf09cb791688fe019284bfdc362abc41918645a5", + "is_verified": false, + "line_number": 916 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9ecdd3b0214d99d66a71bf1e48cebbdd897db432", + "is_verified": false, + "line_number": 919 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "aea3a2f0dd7f8e8655ed2e6cf823ce09d0d537a4", + "is_verified": false, + "line_number": 923 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4e5e279b264f80f6302507f3bc02028118a5381f", + "is_verified": false, + "line_number": 926 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3e62a0c4062cf833f44b3d28c2df580a178a0ce7", + "is_verified": false, + "line_number": 929 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c61f6450dea4696f664cee46c1938e2353da53b9", + "is_verified": false, + "line_number": 933 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1a9c505c27a3d51d07d5cd60f1cd51dccb1ce4e6", + "is_verified": false, + "line_number": 937 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8d04b6573603b749b3e15f4a0d2a322aaf7a74d2", + "is_verified": false, + "line_number": 940 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "e7c4ee17ab711302f98d915dd0b266cd2d1063e5", + "is_verified": false, + "line_number": 943 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "74c6778d90507aa5b96f9aa8ace227ae46079c3d", + "is_verified": false, + "line_number": 946 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4349ff4e19d7672f6b7397e5bf9ec7a64bc28e14", + "is_verified": false, + "line_number": 950 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3e2f7beb6f6a2204eb1ca56ae8ca7e9602ad13f3", + "is_verified": false, + "line_number": 953 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "73bc28172456bad6166fd9a576eb52082dc4dd3c", + "is_verified": false, + "line_number": 956 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "dc1b9f847614c5a40208a767d4cc7cf0f9b2282a", + "is_verified": false, + "line_number": 959 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1e2228f0d8e0fc2bc3b8740a8ff3d287006b9a38", + "is_verified": false, + "line_number": 963 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "625c8e34a90184351c844c05950c45473933b7dc", + "is_verified": false, + "line_number": 966 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "31d6671bbf40210dfde8e313a9c03ab41489691d", + "is_verified": false, + "line_number": 971 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8ac8e759308be486fa9eb1fcadf99defd39eab96", + "is_verified": false, + "line_number": 975 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "e7142097a5cce8cfe60e9c080b88bbbeb28f2a7a", + "is_verified": false, + "line_number": 978 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1229dc2178fd4b24f6dcb957dbdc4dd4f592e26f", + "is_verified": false, + "line_number": 982 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "805d9656080308c11cde7cb7f0310e12c7e60c48", + "is_verified": false, + "line_number": 986 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ca13874532c9df50a570a36576667e2bbd4383bc", + "is_verified": false, + "line_number": 989 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "85c66cde4af421982424442e55d5b0a85e75b40e", + "is_verified": false, + "line_number": 994 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "38c97b06ca380ec6b537fb959634cd6042e47cea", + "is_verified": false, + "line_number": 998 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "55159cc007aeaf5fbf0746c70b85d9ddc16db6dd", + "is_verified": false, + "line_number": 1001 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "61ff5c8a702d8ffe28063c06487a3a5a0db2ed70", + "is_verified": false, + "line_number": 1004 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "cf64476b50691518582d89769fcebde8862b0020", + "is_verified": false, + "line_number": 1008 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9235bcf425e49c5749d9f52ed67b13717efda795", + "is_verified": false, + "line_number": 1012 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "406d7e234572008768bde7f31b176a7a0f8da4f0", + "is_verified": false, + "line_number": 1015 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4439cc784aca22e5cdf33ed6656f5b8b99eaa44d", + "is_verified": false, + "line_number": 1019 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "84cbfec871cf2b178ab90fcc1f442fa369e99a02", + "is_verified": false, + "line_number": 1022 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "80eb677fae3a58bfd1df58e32807f8eccd8ca18d", + "is_verified": false, + "line_number": 1026 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "498226c66b0e41fceaff482c6cc115f1bc4abd6e", + "is_verified": false, + "line_number": 1029 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "635b865541a9b317d71b354dc07769e554004a0a", + "is_verified": false, + "line_number": 1033 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "eeb22523a5f23b8e2f2839101e2a21df63062eef", + "is_verified": false, + "line_number": 1036 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "cf7ae21a07aec42c0047f67e1b0b7ecd28fc23b5", + "is_verified": false, + "line_number": 1040 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9fe5b3fda621da0e9b76aa653d894f94f8f58cd4", + "is_verified": false, + "line_number": 1044 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f1d33d6aede0dfb7fe9978bebd04c76d861c98c3", + "is_verified": false, + "line_number": 1047 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4f4dde0efe7acd336975cd25fc68e25347fd64ee", + "is_verified": false, + "line_number": 1050 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "353aafcecdb8834ff13733ca486183ed2882e7ec", + "is_verified": false, + "line_number": 1054 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7969827f4e081fc3ab6d578be9fe52cf55b34bef", + "is_verified": false, + "line_number": 1057 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ac92f6ef74f09318d36f34716ed2f258b5e0924f", + "is_verified": false, + "line_number": 1060 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "288c8b24d63adf108e603c52001b6412037a9edc", + "is_verified": false, + "line_number": 1064 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "36149fc78b01f35bca00b832a55a4ea4f21995ae", + "is_verified": false, + "line_number": 1068 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4b07e969bf7c1a9efdf5eab7e13abaa484c49d38", + "is_verified": false, + "line_number": 1072 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "5a485a4915f94231f9dc5b355ddda367442ba450", + "is_verified": false, + "line_number": 1076 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "17df0cf1bffb39d85a2aea45c887f1998ffc48a8", + "is_verified": false, + "line_number": 1080 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a6bc2cd23b205c0d88f94eef4d6c1268906d0670", + "is_verified": false, + "line_number": 1083 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "19a998b1bf7031d19515cd35f049a7a6aa7dd1b3", + "is_verified": false, + "line_number": 1087 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "ea4d705920dea9e9007f7ffd977007d97d93720a", + "is_verified": false, + "line_number": 1091 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4a92c1257b67845f12260b454ba353a5919dec29", + "is_verified": false, + "line_number": 1094 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7e42e0804bd25c31e53b2f0871fa2b3551dc66d9", + "is_verified": false, + "line_number": 1099 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "dab00d860d09dd9092b16718edd82bb24a6a21e9", + "is_verified": false, + "line_number": 1103 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "09d8666b35e6c586e3ac50ff958d10e8f3a12d3f", + "is_verified": false, + "line_number": 1106 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7ecd16de4642448e5a002d0eb887796642d37c29", + "is_verified": false, + "line_number": 1110 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f65cbf613806c65f44181f17817d02c7be05ceda", + "is_verified": false, + "line_number": 1114 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2364d220157112e44b4d06ea9df8f2b9fb44069e", + "is_verified": false, + "line_number": 1117 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "39ffec566bffcf8c829bbb54c2f3e06aadbccb15", + "is_verified": false, + "line_number": 1120 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2fd4d093008863345a56756800819a01bf8e0451", + "is_verified": false, + "line_number": 1125 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "bae67d3ce231086fba18abc7365c94878f900c14", + "is_verified": false, + "line_number": 1128 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3b7990b0f82bc9bc6c4ec02744f9c02e76aac827", + "is_verified": false, + "line_number": 1131 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9072ebcbad57a1ae4256c5ae37c1e7c7ae5325de", + "is_verified": false, + "line_number": 1135 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "33e224ae0061fa6dc855702e88cad5e948136009", + "is_verified": false, + "line_number": 1139 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "e0c6ae09dd70fa25056d591ada0ad32df0dfe873", + "is_verified": false, + "line_number": 1142 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "156a735a4c43b9c6b0c08f6b857738968fe588d4", + "is_verified": false, + "line_number": 1146 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "336d02c1e7195c5237197b5884304099ab15c6ba", + "is_verified": false, + "line_number": 1149 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "02757ec3c99c3192621db35f0eea3897cede465a", + "is_verified": false, + "line_number": 1153 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b015b77432bd6d255596af7b2f552d8e8c91a7f7", + "is_verified": false, + "line_number": 1157 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4dcc5c09923b9c0c9014f1f416f58aed8360e584", + "is_verified": false, + "line_number": 1160 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "32026694f097ae0956b46d081f53c72d129a0e9d", + "is_verified": false, + "line_number": 1164 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1ef51736be44df9a195f0a4ecc99642e7e006803", + "is_verified": false, + "line_number": 1167 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "1be172b28420494a97b5bd6dc5d20d9b54d52047", + "is_verified": false, + "line_number": 1170 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "3e536139add3f70bf34712d57cf490dc9c631553", + "is_verified": false, + "line_number": 1173 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4035430d526a269d8e16277f9be0f9c6a7e695bd", + "is_verified": false, + "line_number": 1177 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "01a928fe600e802e506f5354d0be5df023952b7d", + "is_verified": false, + "line_number": 1180 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "612114aa542d50acb4e8481ff643adb46c6e71b3", + "is_verified": false, + "line_number": 1188 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "11973b25b26c5ffab277f15a5f39da63518c061c", + "is_verified": false, + "line_number": 1192 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2fbe8ab30e5355ea9d7538aec4d6c869562a0ed8", + "is_verified": false, + "line_number": 1195 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a664083cd7ea977f953eb398c15a7391521e8c88", + "is_verified": false, + "line_number": 1198 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "bcc923e3a3bbb5c5c7c2f2b5e17bda91f8076652", + "is_verified": false, + "line_number": 1201 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "66022833f4701f45cff007311050911fe571487c", + "is_verified": false, + "line_number": 1205 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "512b3e49cdd404e4e23779be697a6801e04255ab", + "is_verified": false, + "line_number": 1209 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "b3f13048bf1127d22a091b20bef5f1fb485b94c2", + "is_verified": false, + "line_number": 1213 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f50a9ae6c1f90c2adc6b60bbe3779ed40e14ca9e", + "is_verified": false, + "line_number": 1217 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "a6d813aa7164341218d80a2b625ff1b254fa10c3", + "is_verified": false, + "line_number": 1221 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "422f025608080feaba8cb1fbbb522deb3f43cdcc", + "is_verified": false, + "line_number": 1225 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8239574b4263502316ae4af75858c8537b8f9dc2", + "is_verified": false, + "line_number": 1230 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7c43a5a81cdfc2d174e64e7441e07b48f610be0e", + "is_verified": false, + "line_number": 1235 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "735bd20202e59e618bfe941a5941731da477e7b6", + "is_verified": false, + "line_number": 1238 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "32f11283bec656108388929b40993090be755520", + "is_verified": false, + "line_number": 1241 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "4801a08438ed2a6af40afdf77d92cf8412cae7fb", + "is_verified": false, + "line_number": 1246 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "10268f6f4f68752aa603c74f237e00cf940909a4", + "is_verified": false, + "line_number": 1286 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "8ac9d9448e688e8f94e810f2c49fd9b728bd2041", + "is_verified": false, + "line_number": 1326 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "7dbba2db5c8622d492abdd259dd9033ed5f205e2", + "is_verified": false, + "line_number": 1334 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "f0257d02d23f53e799476af74cf0386375d4b6c2", + "is_verified": false, + "line_number": 1362 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "95b02c02e7cb902e9603042bf77d2ce3b47d7dd1", + "is_verified": false, + "line_number": 1367 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "c1a38efe10a08cb343b44ec85e4f991fa64e0dc8", + "is_verified": false, + "line_number": 1372 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "77fb73a7cac9311a40dd4d7f73c5991ef9e79fb6", + "is_verified": false, + "line_number": 1375 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "9b0596f2945cdeab0d6fb2407275942153f87d9c", + "is_verified": false, + "line_number": 1387 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/lock.yaml", + "hashed_secret": "2a6ec2710324e581e13c5bd7ce5f78fd563b3db0", + "is_verified": false, + "line_number": 1390 + } + ], + "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/non-secure/index.cjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/non-secure/index.cjs", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 8 + } + ], + "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/non-secure/index.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/non-secure/index.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 2 + } + ], + "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/url-alphabet/index.cjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/url-alphabet/index.cjs", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 5 + } + ], + "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/url-alphabet/index.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/nanoid@3.3.11/node_modules/nanoid/url-alphabet/index.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 2 + } + ], + "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/api.md": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/api.md", + "hashed_secret": "35b62df986d9eea136faadfda77e7066f9d47ff8", + "is_verified": false, + "line_number": 263 + } + ], + "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/redaction.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/redaction.md", + "hashed_secret": "137eb9fbc5980f6ffcdfc1637de4c0f3a57250b7", + "is_verified": false, + "line_number": 21 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/redaction.md", + "hashed_secret": "bcd0e787f07c5ac9c48e8ba4c27bc42ad8f9a017", + "is_verified": false, + "line_number": 22 + } + ], + "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/transports.md": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/transports.md", + "hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6", + "is_verified": false, + "line_number": 551 + }, + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/transports.md", + "hashed_secret": "35675e68f4b5af7b995d9205ad0fc43842f16450", + "is_verified": false, + "line_number": 908 + }, + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/docs/transports.md", + "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + "is_verified": false, + "line_number": 992 + } + ], + "node_modules/.pnpm/pino@9.14.0/node_modules/pino/test/redact.test.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/pino@9.14.0/node_modules/pino/test/redact.test.js", + "hashed_secret": "b0c69c0d1c5eeddd25b5d7d85c171ae39b8438a4", + "is_verified": false, + "line_number": 836 + } + ], + "node_modules/.pnpm/siginfo@2.0.0/node_modules/siginfo/.travis.yml": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/siginfo@2.0.0/node_modules/siginfo/.travis.yml", + "hashed_secret": "f66e7fb3731623aeb7b29bc250a5d7bb0e075b53", + "is_verified": false, + "line_number": 9 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/siginfo@2.0.0/node_modules/siginfo/.travis.yml", + "hashed_secret": "544d45a9d619812d5ae2586da4e052d4f3e87afc", + "is_verified": false, + "line_number": 11 + } + ], + "node_modules/.pnpm/svelte-check@4.4.6_picomatch@4.0.4_svelte@5.55.5_typescript@5.9.3/node_modules/svelte-check/dist/src/index.js": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/svelte-check@4.4.6_picomatch@4.0.4_svelte@5.55.5_typescript@5.9.3/node_modules/svelte-check/dist/src/index.js", + "hashed_secret": "ad230be8033f3a943c828b3859b579ce566070cd", + "is_verified": false, + "line_number": 46486 + } + ], + "node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/lexer-DQCqS3nf.mjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/lexer-DQCqS3nf.mjs", + "hashed_secret": "4dc7bd5ab67116949435371742e86d0999be6136", + "is_verified": false, + "line_number": 3 + } + ], + "node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/lexer-DgIbo0BU.cjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/lexer-DgIbo0BU.cjs", + "hashed_secret": "4dc7bd5ab67116949435371742e86d0999be6136", + "is_verified": false, + "line_number": 3 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/_tsc.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/_tsc.js", + "hashed_secret": "1d278d3c888d1a2fa7eed622bfc02927ce4049af", + "is_verified": false, + "line_number": 17172 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/cs/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/cs/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/cs/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/cs/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/cs/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/de/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/de/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/de/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/de/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/de/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/es/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/es/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/es/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/es/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/es/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/fr/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/fr/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/fr/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/fr/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/fr/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/it/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/it/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/it/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/it/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/it/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ja/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ja/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ja/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ja/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ja/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ko/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ko/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ko/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ko/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ko/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pl/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pl/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pl/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pl/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pl/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ru/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ru/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ru/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ru/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/ru/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/tr/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/tr/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/tr/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/tr/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/tr/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/typescript.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/typescript.js", + "hashed_secret": "1d278d3c888d1a2fa7eed622bfc02927ce4049af", + "is_verified": false, + "line_number": 21003 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json", + "hashed_secret": "22b0a600a57c006e23d66715f22b40eaa126d798", + "is_verified": false, + "line_number": 921 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json", + "hashed_secret": "cbf4e0f796dae8446f52880aab730b0db9f67d5c", + "is_verified": false, + "line_number": 1262 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json", + "hashed_secret": "8e421827391bcee7c056439ff2e9c25e70296654", + "is_verified": false, + "line_number": 1587 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json", + "hashed_secret": "ace03230a8178b77da5e33ba3a4ae5bcb953fbdd", + "is_verified": false, + "line_number": 1692 + } + ], + "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/package.json": [ + { + "type": "Hex High Entropy String", + "filename": "node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/package.json", + "hashed_secret": "cbaf125bbcefe9bcf49c51421e1f003923cbb00f", + "is_verified": false, + "line_number": 119 + } + ], + "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/client/client.mjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/client/client.mjs", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 230 + } + ], + "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-Dq2t6Dq0.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-Dq2t6Dq0.js", + "hashed_secret": "4dc7bd5ab67116949435371742e86d0999be6136", + "is_verified": false, + "line_number": 10821 + } + ], + "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js", + "hashed_secret": "c84f72b503d228647605a5da89265aca2a4d4fc2", + "is_verified": false, + "line_number": 1680 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js", + "hashed_secret": "cebeedf6617375197d482c0b3e6f37a71741cbc9", + "is_verified": false, + "line_number": 1781 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js", + "hashed_secret": "a5202d3272abd5992c599881e6619d0ab187c5fe", + "is_verified": false, + "line_number": 1909 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js", + "hashed_secret": "5560bb76f3d252d73b49b96977abf7c72e11bf78", + "is_verified": false, + "line_number": 1911 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js", + "hashed_secret": "2f114d79eeed9519b567d87af56322d2b4ec7f16", + "is_verified": false, + "line_number": 1913 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/dep-lpEPC2f9.js", + "hashed_secret": "c5bdf4e413b9114ded6ce852c4992e147744b88b", + "is_verified": false, + "line_number": 1915 + } + ], + "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@6.4.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 541 + } + ], + "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/client/client.mjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/client/client.mjs", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 230 + } + ], + "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "c84f72b503d228647605a5da89265aca2a4d4fc2", + "is_verified": false, + "line_number": 1349 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "cebeedf6617375197d482c0b3e6f37a71741cbc9", + "is_verified": false, + "line_number": 1402 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "a5202d3272abd5992c599881e6619d0ab187c5fe", + "is_verified": false, + "line_number": 1481 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "5560bb76f3d252d73b49b96977abf7c72e11bf78", + "is_verified": false, + "line_number": 1483 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "2f114d79eeed9519b567d87af56322d2b4ec7f16", + "is_verified": false, + "line_number": 1485 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "c5bdf4e413b9114ded6ce852c4992e147744b88b", + "is_verified": false, + "line_number": 1487 + } + ], + "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/config.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/chunks/config.js", + "hashed_secret": "c2c8002d50715475a1f593d36f386b7d71f2bfe1", + "is_verified": false, + "line_number": 7219 + } + ], + "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/module-runner.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2/node_modules/vite/dist/node/module-runner.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 471 + } + ], + "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/client/client.mjs": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/client/client.mjs", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 230 + } + ], + "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "c84f72b503d228647605a5da89265aca2a4d4fc2", + "is_verified": false, + "line_number": 1349 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "cebeedf6617375197d482c0b3e6f37a71741cbc9", + "is_verified": false, + "line_number": 1402 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "a5202d3272abd5992c599881e6619d0ab187c5fe", + "is_verified": false, + "line_number": 1481 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "5560bb76f3d252d73b49b96977abf7c72e11bf78", + "is_verified": false, + "line_number": 1483 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "2f114d79eeed9519b567d87af56322d2b4ec7f16", + "is_verified": false, + "line_number": 1485 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/build2.js", + "hashed_secret": "c5bdf4e413b9114ded6ce852c4992e147744b88b", + "is_verified": false, + "line_number": 1487 + } + ], + "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/config.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/chunks/config.js", + "hashed_secret": "c2c8002d50715475a1f593d36f386b7d71f2bfe1", + "is_verified": false, + "line_number": 7219 + } + ], + "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vite@7.3.2_@types+node@22.19.17_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 471 + } + ], + "node_modules/.pnpm/vitest@3.2.4/node_modules/vitest/dist/chunks/index.B521nVV-.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vitest@3.2.4/node_modules/vitest/dist/chunks/index.B521nVV-.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 148 + } + ], + "node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.17_tsx@4.21.0/node_modules/vitest/dist/chunks/index.B521nVV-.js": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/vitest@3.2.4_@types+node@22.19.17_tsx@4.21.0/node_modules/vitest/dist/chunks/index.B521nVV-.js", + "hashed_secret": "fd01517f059af4e882624f96d0ba9934dddd6e43", + "is_verified": false, + "line_number": 148 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/error.test.ts": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/error.test.ts", + "hashed_secret": "9413ee70957a09d55704123687478e07f18c7b29", + "is_verified": false, + "line_number": 220 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/error.test.ts", + "hashed_secret": "1161e6ffd3637b302a5cd74076283a7bd1fc20d3", + "is_verified": false, + "line_number": 243 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/refine.test.ts": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/refine.test.ts", + "hashed_secret": "b480c074d6b75947c02681f31c90c668c46bf6b8", + "is_verified": false, + "line_number": 40 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/refine.test.ts", + "hashed_secret": "614e00a6cf5e0a27838ec055ff89e945f681054f", + "is_verified": false, + "line_number": 41 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/refine.test.ts", + "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + "is_verified": false, + "line_number": 74 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/refine.test.ts", + "hashed_secret": "3da541559918a808c2402bba5012f6c60b27661c", + "is_verified": false, + "line_number": 86 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/string.test.ts": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/string.test.ts", + "hashed_secret": "1bd27b9be40be116abc3296dec857219d60ee841", + "is_verified": false, + "line_number": 171 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/string.test.ts", + "hashed_secret": "9e0142b544733c8fafc385af848d4ff880562098", + "is_verified": false, + "line_number": 172 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/string.test.ts", + "hashed_secret": "e4d0f04f03d9183f843c9d764592ba5bcd17f356", + "is_verified": false, + "line_number": 175 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/string.test.ts", + "hashed_secret": "9b19b8d1522e95f19232c6ea0b61dc1b99390253", + "is_verified": false, + "line_number": 211 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v3/tests/string.test.ts", + "hashed_secret": "9bfdf8412034d68523c15f3f0e3dfa5d452cc270", + "is_verified": false, + "line_number": 218 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/error.test.ts": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/error.test.ts", + "hashed_secret": "9413ee70957a09d55704123687478e07f18c7b29", + "is_verified": false, + "line_number": 285 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/error.test.ts", + "hashed_secret": "1161e6ffd3637b302a5cd74076283a7bd1fc20d3", + "is_verified": false, + "line_number": 305 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts", + "hashed_secret": "62cdb7020ff920e5aa642c3d4066950dd1f01f4d", + "is_verified": false, + "line_number": 38 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts": [ + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts", + "hashed_secret": "b480c074d6b75947c02681f31c90c668c46bf6b8", + "is_verified": false, + "line_number": 66 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts", + "hashed_secret": "614e00a6cf5e0a27838ec055ff89e945f681054f", + "is_verified": false, + "line_number": 67 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts", + "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + "is_verified": false, + "line_number": 93 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts", + "hashed_secret": "517d5a7240861ec297fa07542a7bf7470bb604fe", + "is_verified": false, + "line_number": 104 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts", + "hashed_secret": "3da541559918a808c2402bba5012f6c60b27661c", + "is_verified": false, + "line_number": 174 + }, + { + "type": "Secret Keyword", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/refine.test.ts", + "hashed_secret": "f1b699cc9af3eeb98e5de244ca7802ae38e77bae", + "is_verified": false, + "line_number": 480 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts", + "hashed_secret": "1bd27b9be40be116abc3296dec857219d60ee841", + "is_verified": false, + "line_number": 177 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts", + "hashed_secret": "9e0142b544733c8fafc385af848d4ff880562098", + "is_verified": false, + "line_number": 178 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts", + "hashed_secret": "e4d0f04f03d9183f843c9d764592ba5bcd17f356", + "is_verified": false, + "line_number": 181 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts", + "hashed_secret": "9b19b8d1522e95f19232c6ea0b61dc1b99390253", + "is_verified": false, + "line_number": 214 + }, + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts", + "hashed_secret": "9bfdf8412034d68523c15f3f0e3dfa5d452cc270", + "is_verified": false, + "line_number": 221 + }, + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/string.test.ts", + "hashed_secret": "eff978d544a9cf5e5f55856f7ff928e57a00ae23", + "is_verified": false, + "line_number": 307 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/template-literal.test.ts": [ + { + "type": "Basic Auth Credentials", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/classic/tests/template-literal.test.ts", + "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + "is_verified": false, + "line_number": 644 + } + ], + "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/mini/tests/string.test.ts": [ + { + "type": "Base64 High Entropy String", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/mini/tests/string.test.ts", + "hashed_secret": "ca744435a5a71bd2d402d78b532f6418d3133376", + "is_verified": false, + "line_number": 206 + }, + { + "type": "JSON Web Token", + "filename": "node_modules/.pnpm/zod@3.25.76/node_modules/zod/src/v4/mini/tests/string.test.ts", + "hashed_secret": "d6b66ddd9ea7dbe760114bfe9a97352a5e139134", + "is_verified": false, + "line_number": 289 + } + ], + "packages/shared/tsconfig.tsbuildinfo": [ + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "01a5dd1cdf7578d466e679ccb2552336d5362a4a", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "02989ac76a74e47b5cc6f084719fb31715b98243", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "0be16c83f218758c0d8ce801b9fbd42bf79fb660", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "0f27704c4615b1bbac5322141e9af4e5ee07624e", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "1073f645c57ebc20e6bf5cc62db8bc3513a05a60", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "130f2e4a54d4e6f28d88cc2aa9f3ff75ec291aa0", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "14b6993b8203a7959fec3e02533226e167363bfc", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "14cd2421400282c7de82e26433cb75d271e84997", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "164d540dddeb5e0bad7bc775f14937b5d4987a8a", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "18e0510c235115291ca135d93234a09b6914ea37", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "1c32674b6e225de7917e987d6ef1297a00294aa2", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "1f500f164e5d8b0785a7566443a85a401f79459e", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "21be5abf1cd575e11c0ad7900b9682a9ee142781", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "29f8d684618e0323a2ca61b6266e552d9fb5063a", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "2cbbc48fd7941eb08f2cdb96c87bf7d64f1b653f", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "342d67f2341f84514b2a52a50912b53ffee895f4", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "351c9e5b3c874256deedb068d73747ade7f1bf84", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "37a241fbc74d3713de28a58e26690bd8bfe52925", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "38a3a6b63b69498d48a97f2ec6c73377a5e6bb8f", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "3908e6db72766c3b5c9e3876dc6ff62945a9ede0", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "3da6812c9ba6be17565a0e165e64de0639f94249", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "3fffb186d7d69fe4b9155638f30f68364abe61c7", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "417b90d84bc584d28b5ed729745f55787ed0003b", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "528c8d2e2a52398ef6fe3cb5cc72419aecbad305", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "586cbb744926ea1795c1f2ccc2112dca368a6be9", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "5b6caaac7a60f69eb3a7fc372e63c0fc6374868d", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "5ba64519cdbcc13f2d406a597661083eebc63454", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "5d710081d5b6190d419a98721f5c339753d8b8c2", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "6ecdb67ca93bb79d42c64d467bddfd072e5ddded", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "7633df9d5d4646ace50db491eeb5d5a14dc50d47", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "76d54d5c054ef47c5af4a3b0f4e78d2fed63ffd6", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "78da1ca390b4c1d3395fab6ca542d689d4d19536", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "7ebf75d7e35e66684e72dcfe1bc244af7356911e", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "7f607b391a3ce0da177d550a98fc3084bf4253a7", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "8026697ce2971b80357fbe2bf158564711d6dd25", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "8043ae14830707fa51a7b2f18c5c3ed88d5871fd", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "893c551c545dcc379d83a38c9b803378bd470a7e", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "8f8ab8e62904cef07118ca9705adc777722bb800", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "8ff2fb78e9eeecec6f51ffa45912bcdbb14da4aa", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "969c47ddbd254bd76d48b683ff6a56bd646f5e0d", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "97b495d16fa86a0d4a80b8f11a5f9a6ebf86022c", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "9ddd7016fa1cdb6c074716723d9bc0075f5f363b", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "9e939c134890f5dffc0a098b4d836b3355a58c9b", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "a1922d8199b8ad982beb42460264a08176cad0cb", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "a3e8d1d4a64c25d5338344ea0bdd1c5258990ced", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "a7d2264d701b27d35e84fcde23735530b8044be2", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "ad2285c3516fb2cc445665b9c366e4cc3174e637", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "b268af1b19da38c60b38450c0b6a41023dbb4668", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "b299d107931784be8d38ce4d61eaa848fb76bc5c", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "b608e5eeb19e2d9d9d6b9380553a9fa4c863e625", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "be1ba535e5c56e49f784344dc076f17793fa85ca", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "becc6e4060d63f2f08587024f1946680f7df095b", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "c9acf78fd5b59574621d06ffc348a151810be286", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "cb222c8c4bb1ca24ec8e2e5fbaa8f602b87a1b2f", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "cf5e01090d6f372bc342f420d666ee240c7ee46d", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "d0265a3a03fd321a82353b08fc6be0490f0896e9", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "d1448b73a6dae41ad0148c682d1556a4bb382f8f", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "d1a361643294b556e8cc4b779cd390f143988400", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "d79c79387a25547c8f9054a9a4d22781100c78b3", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "e04ea79cc77fca500f3500b250bd5858ddcad7c4", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "e2abe5732f02e93db9c778194356b50f901fc193", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "e80366d275d375a3e50d681e7faf5f0df9f8a075", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "ea256b5681473852027bc180f38d43f9d9d3ad4a", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "ea42707865238a5c8caa7ad1e966173de3e6cd3c", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "ed7e1d6b82f20d474d330fa63a53b03816d398a9", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "f7bb8fc2488c9e2edac2e7bbec8d79406737da44", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "f8355330019453c99d6ca98fbca2312e27dc201f", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "fb2f68bb0c56022dc54f5e46f38a430fc92bd706", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "feb8e2efc67b3f662c0001e17f78aae7a9522083", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Hex High Entropy String", + "filename": "packages/shared/tsconfig.tsbuildinfo", + "hashed_secret": "fef78b73a58154ca75a06043798a7df847f7bab7", + "is_verified": false, + "line_number": 1 + } + ], + "pnpm-lock.yaml": [ + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "d1b8345cd5758682c4e2be076930b6dee81a8f0a", + "is_verified": false, + "line_number": 98 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4fc407ff3fa666522e784402874b39ccaa9b9084", + "is_verified": false, + "line_number": 104 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "34fc2e926d119d522332afcf0b1e31be4943e728", + "is_verified": false, + "line_number": 110 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6e53b1d7147a431758aded05223f60a6cf8404b6", + "is_verified": false, + "line_number": 116 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ee9277ef9d8d4012e1b5e779ec43d5b9ec480348", + "is_verified": false, + "line_number": 122 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "21094ab4fc5b3c4b172a28c6e96d474b60d8f176", + "is_verified": false, + "line_number": 128 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b51ddd35a554c659b500b4c1169692da4f6cee67", + "is_verified": false, + "line_number": 134 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "57902bee1f6a5e12ed03dd3b3281ab07318ff81f", + "is_verified": false, + "line_number": 140 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "552658965b8efb6ebaf095b54636a6d54c8e4a6b", + "is_verified": false, + "line_number": 146 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3cfe66e44a47be9aa1a2b2570d4e6ca4fe8646d6", + "is_verified": false, + "line_number": 152 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "04e50569b26a331d6327f95e0a43e04435017c25", + "is_verified": false, + "line_number": 158 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6e9116d6ceb830c0e81b752f03b594c04b867404", + "is_verified": false, + "line_number": 164 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f427b0533ef2217b7b65d4be9d69dfb98e234645", + "is_verified": false, + "line_number": 170 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "92eb7bfdfe82cc5019dea1ead34c876de720e71f", + "is_verified": false, + "line_number": 176 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3f10b09e053c0d12d409925cdbee129e15aee7ee", + "is_verified": false, + "line_number": 182 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f83beff54841a17222f2c5d542077e07f0a640ce", + "is_verified": false, + "line_number": 188 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7cb36fd100cc7d0102797bb6a79a28f2c4a2a33d", + "is_verified": false, + "line_number": 194 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "de1558a98424f61bb30fd681ab33ebe9ac162b93", + "is_verified": false, + "line_number": 200 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2acca17ade2dd33b015ab19d80c162e241749350", + "is_verified": false, + "line_number": 206 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "0609a7c3993cb0b98d835bd299b5e78674c1c4e6", + "is_verified": false, + "line_number": 212 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "970ba53b3d18d68bf94e8458ec9c1b6326188d4f", + "is_verified": false, + "line_number": 218 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7cd72661910d8f1eae72b0783a01c7dcdb990036", + "is_verified": false, + "line_number": 224 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5d012814b5566671037c067991ea81d19cd07cbf", + "is_verified": false, + "line_number": 230 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c5b024f5526693865d3af7324ab65fc3ab1605fa", + "is_verified": false, + "line_number": 236 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "e0ed8c59207e32883f7f1b4b33356054c4214245", + "is_verified": false, + "line_number": 242 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7ea3a0d38529d3159199bb46bcf538993729a4ca", + "is_verified": false, + "line_number": 248 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "fa4f8c78da34eeb842b7c58de563aa7feabcb7b9", + "is_verified": false, + "line_number": 254 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "abac0dd92435eb969522a0ad244a7d5d3bcf9c90", + "is_verified": false, + "line_number": 260 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "762142615ab1dc453cd4c6e0d16d9abff71f7c3b", + "is_verified": false, + "line_number": 266 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "039980936156bd5bc0de9e386f1e385a9bbabcf0", + "is_verified": false, + "line_number": 272 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6385b43929b2ca3cd3fc11ddc7c9429aa6799e95", + "is_verified": false, + "line_number": 278 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ff2f515b75e908a3a079d6b0cf692f65bec13192", + "is_verified": false, + "line_number": 284 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3f729bd8163365c1bc85737b1a5091cb37d83829", + "is_verified": false, + "line_number": 290 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "43b4d7cc77f29c50ebc0ae65cdd5ae53c4610b89", + "is_verified": false, + "line_number": 296 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "00fbf776f031ec28f109bdb0502c86883d29ac01", + "is_verified": false, + "line_number": 302 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4080ae8ed6a6391c581edbf27618aa0806118784", + "is_verified": false, + "line_number": 308 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "afabc9199b55dca97a779220cf30689beace5333", + "is_verified": false, + "line_number": 314 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3e24f346b7ed723f027041976b3d2e7b555ebd90", + "is_verified": false, + "line_number": 320 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7cdd98d664bd97065578d2af7b793094d23fedb7", + "is_verified": false, + "line_number": 326 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2b88177306d91942e3df15d0361c1fd5125db60a", + "is_verified": false, + "line_number": 332 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "611d19d8a4d5842d0970db276cdd09ae44de3df6", + "is_verified": false, + "line_number": 338 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "68d8df9678250f3f17e3c6e65e8e29e1007cd5ba", + "is_verified": false, + "line_number": 344 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "20e89c354326f9aebacc5df3bcb782d7b36edf88", + "is_verified": false, + "line_number": 350 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a1d2a1836521ff0216663ecd5526c0a53ce86a4d", + "is_verified": false, + "line_number": 356 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ff07375cb2a21e51b33412e3316544b3c5d575a1", + "is_verified": false, + "line_number": 362 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b1265b06c14c30da47639c2ed791f50c8d80227f", + "is_verified": false, + "line_number": 368 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c93372223d2b5bbe594d85bfc0d21dfafea217b5", + "is_verified": false, + "line_number": 374 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "17e8e3b6a6567490ad87c92962f2fe73df1a95e3", + "is_verified": false, + "line_number": 380 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6e1232ec19c19bb978ed3a5bf123312c5648df9d", + "is_verified": false, + "line_number": 386 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b9ed31d4313f86c359571fc1caeced011e1549c8", + "is_verified": false, + "line_number": 392 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5fd341ad5e6bff70186ba90c6b39ca49c19fe297", + "is_verified": false, + "line_number": 398 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9234d6da8ceb8786f9a95485ab027085c326afee", + "is_verified": false, + "line_number": 404 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5fe3acc13d078fe4f1dc5c153bdb8514f78c1dd9", + "is_verified": false, + "line_number": 410 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6ebe9d7b6feeca2cbb04503532b053496601ea4c", + "is_verified": false, + "line_number": 413 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4c8137bba4c60ac8c70aa9dc26f17b833b0485b5", + "is_verified": false, + "line_number": 416 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "bf0f532d4fa6ce4da69534acc295afe5d9dce2d8", + "is_verified": false, + "line_number": 419 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "0a46ec56e14c6b0f3988c65531be78c66569c035", + "is_verified": false, + "line_number": 422 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "824b72098dc6947718d316f436bb00fbe3f3f3b5", + "is_verified": false, + "line_number": 425 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "11098cf4a6594cded115edc443cb1d6c38956f3b", + "is_verified": false, + "line_number": 428 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "bd79cc98321f7be3a979a8ecf9deedc8aba70a27", + "is_verified": false, + "line_number": 431 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a250c23ee71fb585be959874180b87fc5565084e", + "is_verified": false, + "line_number": 434 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "0da9ffd747e36f3c422029e7099e27dd5ccb412c", + "is_verified": false, + "line_number": 437 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1b3495fbdeef2dee0dc3f2ca206965663474a3d7", + "is_verified": false, + "line_number": 440 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8733ba82d33885a92ca3009eb6ba61e505a1ee9a", + "is_verified": false, + "line_number": 444 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3e3522c83d724aa4133ee6bb6d627e4390be31a5", + "is_verified": false, + "line_number": 447 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9d1b9dbec9f048e048f4dd38591947ca7deff5dd", + "is_verified": false, + "line_number": 450 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f60c00cacddf514ad090fbde7005d8721adc0b89", + "is_verified": false, + "line_number": 454 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b0e9cbf320ebe74507bcdaae3f0b40740459a092", + "is_verified": false, + "line_number": 457 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "393b2680ecbbb743a86d0b44313313f5d77ff202", + "is_verified": false, + "line_number": 460 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "559cb512c616ae4934092a7ceb3d42239213543d", + "is_verified": false, + "line_number": 464 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "80baf094c85a8b814390721f28df4426791950e2", + "is_verified": false, + "line_number": 467 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "19c871b99cc8a8066f7c372cc935250508cdbf7e", + "is_verified": false, + "line_number": 472 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "66eb29da9a96876a8e1b7fefb901f6b582e14b33", + "is_verified": false, + "line_number": 477 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5ce412f8142bfcc2b11a375e1c91a3a54ca8c0ae", + "is_verified": false, + "line_number": 482 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3e47d4fda361e2553fee0d1f059b0b135fcce98f", + "is_verified": false, + "line_number": 487 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7ce2d9200e0e41b2ee19b821089b6a95a39bc509", + "is_verified": false, + "line_number": 492 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b68b16505cf49c5f3cb98af1b54893a1a79565a5", + "is_verified": false, + "line_number": 497 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b41be781eb3b0c4750e39d09dcdd6a3494f1f357", + "is_verified": false, + "line_number": 503 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f99a49bc745631a8b7085149e82a79811d9bac8c", + "is_verified": false, + "line_number": 509 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "edeb02a82bcc0b255ba89f276f37e4091792f4fe", + "is_verified": false, + "line_number": 515 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7691f9054b1626b357caca8a9f8e83eb8ac84def", + "is_verified": false, + "line_number": 521 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b77dfdeb5ffee23aff3b2f97ff640802ad415a3c", + "is_verified": false, + "line_number": 527 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "94297c922da678a24c4fc963af0da51d961d8fe5", + "is_verified": false, + "line_number": 533 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1f0eb8fb4434346c68f359042c9fc254c1c46be6", + "is_verified": false, + "line_number": 539 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5d67ae5d1c2f8a622e078f0d8d16670619aa561e", + "is_verified": false, + "line_number": 545 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "fee3efd07b8abcb9d734d6f324253508f7501156", + "is_verified": false, + "line_number": 551 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1380cb2734346cc00e41eb54cdd94860f4859e2c", + "is_verified": false, + "line_number": 557 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5aea3dce81939048d287d7761e40642490194d09", + "is_verified": false, + "line_number": 563 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "11487ba85b40245c0bb0e34846085b8714439652", + "is_verified": false, + "line_number": 569 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9f2824e8182be80a655c1164a0c7d043abe0b2e8", + "is_verified": false, + "line_number": 575 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "87bb0e1e3669074c5cda58de04798789e0eda61d", + "is_verified": false, + "line_number": 580 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5423261b835b9649ae476fc59e957f6cb03b2369", + "is_verified": false, + "line_number": 585 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c62e701dc37732b77d24e97d4676d597a1e1ce41", + "is_verified": false, + "line_number": 590 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "58a0c6f04ab904bada0f96e79f61f7633b8e8554", + "is_verified": false, + "line_number": 595 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5ac63bbb4857e2c672bef90951ed012b5e1a3099", + "is_verified": false, + "line_number": 600 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "0e08e31e43853476fc57d10643d8c871082c08b3", + "is_verified": false, + "line_number": 605 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b31d08ed4329a2b257e3183cdb4917a06ff76acf", + "is_verified": false, + "line_number": 610 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b74484fafbbaf80a55364e035669088e7fd44b6c", + "is_verified": false, + "line_number": 618 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7739c7a36e8b5c9759887d54c3d3a252d017cb71", + "is_verified": false, + "line_number": 625 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "d4dda0583372eb865e22ea00ae160ceb315aa0df", + "is_verified": false, + "line_number": 628 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "904dae7e3147870781ad476afdbc281061d76e62", + "is_verified": false, + "line_number": 631 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4a96348ad16d0abe922e3e2c78b1b4d82a9b3f07", + "is_verified": false, + "line_number": 634 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5f411c7e6073b67aca1c9043e3e952322dc21d46", + "is_verified": false, + "line_number": 637 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "618a8148c9899b3b6bd69562f235038dc7953718", + "is_verified": false, + "line_number": 640 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5c4d2062f4b9170e2571cfe2b901592767edc7cd", + "is_verified": false, + "line_number": 643 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2a04ad8254d18f2f4403c9056e67951c1e0fb0a5", + "is_verified": false, + "line_number": 646 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a7655c0dea3997e8ee27a2090dc9eb749a7b1282", + "is_verified": false, + "line_number": 657 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2c684cbb0ceecbae320bff3152c0f2b1b3434c7e", + "is_verified": false, + "line_number": 660 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6ff1feade4ea98d27ec8f31fa2dbcfd3d2a5028f", + "is_verified": false, + "line_number": 663 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "359e9803b99c38d739e61ade83000c2ab5a22448", + "is_verified": false, + "line_number": 666 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b0af613d49499b2f6f2643ef7acf1a219e9e6fb6", + "is_verified": false, + "line_number": 669 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "86c936c2fd0b15334fb3e7e08ea42b385c42f7a1", + "is_verified": false, + "line_number": 672 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a3fde05f04dec549057c3104497d942072394189", + "is_verified": false, + "line_number": 676 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b2c03df0ed8f8caded3abab58c3b2e3b645dbb28", + "is_verified": false, + "line_number": 679 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4f6636587fecd2341ba754a447e6a26db011795f", + "is_verified": false, + "line_number": 684 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "07860d1f8563c118dfa14b8c27bfef9420e3f8c2", + "is_verified": false, + "line_number": 692 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5bb90e7e3d7847438b155c9fb564dfd279383855", + "is_verified": false, + "line_number": 695 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1c504c77e2b9f1ea0e1770e65673fd7f8b3f4c8f", + "is_verified": false, + "line_number": 699 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "6f5c4f8389922a6637a0b4fdb837095b494c0bfb", + "is_verified": false, + "line_number": 703 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "38604ae508f167b156742a5c072915272fb37857", + "is_verified": false, + "line_number": 707 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4a6acdb47bbd22c85e10baf5921ddbb3c09a787b", + "is_verified": false, + "line_number": 710 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "e0ed71a4c2836a6a251bef5e00b00401cfac286d", + "is_verified": false, + "line_number": 714 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7bb507ba2f47095177b03051a6340091be5871b2", + "is_verified": false, + "line_number": 718 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5389eb7ce46c53e5d6adc57d5bafb1180870b814", + "is_verified": false, + "line_number": 721 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9748716a465dd6d055354fd346c4cd105b7d39b1", + "is_verified": false, + "line_number": 725 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c56c76bc828483f5553df346fb2eaa6e3e6c4bba", + "is_verified": false, + "line_number": 728 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5620b727309eb0585715c051b3f1ad6560879967", + "is_verified": false, + "line_number": 732 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "fd40953175f0c99e010e94312afacb63e7f1a817", + "is_verified": false, + "line_number": 736 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8095985919187b5be33de4b775c7a5e7562aafee", + "is_verified": false, + "line_number": 740 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8ff61e34bccd3c9f85c8a24db9723d984fd74314", + "is_verified": false, + "line_number": 743 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5974b42acc3c558a08c734a45a10785534b5d382", + "is_verified": false, + "line_number": 747 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1dae660604ec052e4c8dfd54b0657636c412a22b", + "is_verified": false, + "line_number": 751 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f52956fa7c317746fde250d0f4e54d6115252cd4", + "is_verified": false, + "line_number": 754 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8f16039bc2ed9b93d8e319897b70cb25f25dfcc4", + "is_verified": false, + "line_number": 758 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "862951cd71d0412b5e52bae3e952725486a655b0", + "is_verified": false, + "line_number": 762 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ab4bcd85dbb08e2c7721a4842f74653506829466", + "is_verified": false, + "line_number": 766 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "d45062677e99f28b9a98f4b53e9af8f56b01bb10", + "is_verified": false, + "line_number": 769 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b4a9257558064dbd957e726d9d25d81b97837009", + "is_verified": false, + "line_number": 778 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c0c7aeed5e5a888b2aa3cdb739955fd27d25335e", + "is_verified": false, + "line_number": 782 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c5deff9c59d0e0419952da44431546620804d70e", + "is_verified": false, + "line_number": 786 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "d031e18cc14e54a719197084af4cd6b2372fd005", + "is_verified": false, + "line_number": 790 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "183c0616018161acd77ce39914e9bb5a22fcae49", + "is_verified": false, + "line_number": 794 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "309db07fa3cab58e7ea5fc5ba8f629a4430fa6a6", + "is_verified": false, + "line_number": 797 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "fc231c807593551488e1df5cd5d488e39f7db93f", + "is_verified": false, + "line_number": 800 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "d076e5a9f2245bcedf234f70abb7fa41d4d9f0dc", + "is_verified": false, + "line_number": 803 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "bf4a0e0cb4a648f94a1ceff84d8070ab01b0df0e", + "is_verified": false, + "line_number": 806 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "cab616f3cdb6eb3c372039eeae16f83314439923", + "is_verified": false, + "line_number": 811 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "cc0394ae9ff7278ac1f8ba8305e06627798ae34b", + "is_verified": false, + "line_number": 816 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4a1a266072e5f401e1aa928a9bf6d94bfeab4806", + "is_verified": false, + "line_number": 819 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "50c2ef2e538e117e2c5cb97fd9678257c05daea1", + "is_verified": false, + "line_number": 822 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "763f4272f5426f2cb52dd90f1f6a490a4ce61418", + "is_verified": false, + "line_number": 830 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "bdc1322162b3c2d06c4103afb50937bf6085ebf2", + "is_verified": false, + "line_number": 833 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3446aea3a08fd97b7eb1beac15a525d1b4586864", + "is_verified": false, + "line_number": 837 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "16d0c877fca994fd1c43bd7f131be967bf4f87b6", + "is_verified": false, + "line_number": 841 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "373eefae8f0bb627d355aa0997dbf702a2274642", + "is_verified": false, + "line_number": 845 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c7018ff5fd96eec2abbadb93bb97d56f00235687", + "is_verified": false, + "line_number": 848 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c0f64a532897bbd5497996fdfec7cfcd087540ce", + "is_verified": false, + "line_number": 851 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4e742e60616be1578b81769f2ffd9bef51586512", + "is_verified": false, + "line_number": 854 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5ffcc7770e283fe45a96c1ba2bc21dd7f38458b5", + "is_verified": false, + "line_number": 857 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "38a37f53e7403dabad025e1d953382e82ff53762", + "is_verified": false, + "line_number": 860 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a175423c144b95f8ef14eca365738012ae8ff166", + "is_verified": false, + "line_number": 863 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2f00e7db8ba09014a8f7ae078346fd4630c8ee54", + "is_verified": false, + "line_number": 866 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b3edf680cb58f88cd49833b666c6c1b310fd4c90", + "is_verified": false, + "line_number": 869 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "02031683c4d321f8660ff8b2d0258362940c8a6d", + "is_verified": false, + "line_number": 872 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "16fa3bfaeef78e32910c87baf9060e51490d09ad", + "is_verified": false, + "line_number": 875 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "74f497c18c464bd0d65adca16a8e96c0fafeefcb", + "is_verified": false, + "line_number": 884 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3aa0faf721de27687f7be4cc9ed4e61c745e6e44", + "is_verified": false, + "line_number": 888 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "d950cd8ef510429f57fb282e4a437321ca86158c", + "is_verified": false, + "line_number": 892 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3ad5ab41a177a3b1dbc7cc007170bfcc93c0607a", + "is_verified": false, + "line_number": 897 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5d204787c8c7979085337870c453871dbe65cb84", + "is_verified": false, + "line_number": 900 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4648471e6e277a4eb3eb85ed4ef695b6bfabe451", + "is_verified": false, + "line_number": 906 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9bad76463ceffd240ee9bd95c3faa98c0a4b94d0", + "is_verified": false, + "line_number": 909 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "82bb8edb4003308fc261a3cd2488be9862e99657", + "is_verified": false, + "line_number": 913 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "cf09cb791688fe019284bfdc362abc41918645a5", + "is_verified": false, + "line_number": 916 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9ecdd3b0214d99d66a71bf1e48cebbdd897db432", + "is_verified": false, + "line_number": 919 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "aea3a2f0dd7f8e8655ed2e6cf823ce09d0d537a4", + "is_verified": false, + "line_number": 923 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4e5e279b264f80f6302507f3bc02028118a5381f", + "is_verified": false, + "line_number": 926 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3e62a0c4062cf833f44b3d28c2df580a178a0ce7", + "is_verified": false, + "line_number": 929 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c61f6450dea4696f664cee46c1938e2353da53b9", + "is_verified": false, + "line_number": 933 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1a9c505c27a3d51d07d5cd60f1cd51dccb1ce4e6", + "is_verified": false, + "line_number": 937 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8d04b6573603b749b3e15f4a0d2a322aaf7a74d2", + "is_verified": false, + "line_number": 940 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "e7c4ee17ab711302f98d915dd0b266cd2d1063e5", + "is_verified": false, + "line_number": 943 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "74c6778d90507aa5b96f9aa8ace227ae46079c3d", + "is_verified": false, + "line_number": 946 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4349ff4e19d7672f6b7397e5bf9ec7a64bc28e14", + "is_verified": false, + "line_number": 950 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3e2f7beb6f6a2204eb1ca56ae8ca7e9602ad13f3", + "is_verified": false, + "line_number": 953 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "73bc28172456bad6166fd9a576eb52082dc4dd3c", + "is_verified": false, + "line_number": 956 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "dc1b9f847614c5a40208a767d4cc7cf0f9b2282a", + "is_verified": false, + "line_number": 959 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1e2228f0d8e0fc2bc3b8740a8ff3d287006b9a38", + "is_verified": false, + "line_number": 963 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "625c8e34a90184351c844c05950c45473933b7dc", + "is_verified": false, + "line_number": 966 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "31d6671bbf40210dfde8e313a9c03ab41489691d", + "is_verified": false, + "line_number": 971 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8ac8e759308be486fa9eb1fcadf99defd39eab96", + "is_verified": false, + "line_number": 975 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "e7142097a5cce8cfe60e9c080b88bbbeb28f2a7a", + "is_verified": false, + "line_number": 978 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1229dc2178fd4b24f6dcb957dbdc4dd4f592e26f", + "is_verified": false, + "line_number": 982 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "805d9656080308c11cde7cb7f0310e12c7e60c48", + "is_verified": false, + "line_number": 986 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ca13874532c9df50a570a36576667e2bbd4383bc", + "is_verified": false, + "line_number": 989 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "85c66cde4af421982424442e55d5b0a85e75b40e", + "is_verified": false, + "line_number": 994 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "38c97b06ca380ec6b537fb959634cd6042e47cea", + "is_verified": false, + "line_number": 998 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "55159cc007aeaf5fbf0746c70b85d9ddc16db6dd", + "is_verified": false, + "line_number": 1001 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "61ff5c8a702d8ffe28063c06487a3a5a0db2ed70", + "is_verified": false, + "line_number": 1004 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "cf64476b50691518582d89769fcebde8862b0020", + "is_verified": false, + "line_number": 1008 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9235bcf425e49c5749d9f52ed67b13717efda795", + "is_verified": false, + "line_number": 1012 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "406d7e234572008768bde7f31b176a7a0f8da4f0", + "is_verified": false, + "line_number": 1015 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4439cc784aca22e5cdf33ed6656f5b8b99eaa44d", + "is_verified": false, + "line_number": 1019 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "84cbfec871cf2b178ab90fcc1f442fa369e99a02", + "is_verified": false, + "line_number": 1022 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "80eb677fae3a58bfd1df58e32807f8eccd8ca18d", + "is_verified": false, + "line_number": 1026 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "498226c66b0e41fceaff482c6cc115f1bc4abd6e", + "is_verified": false, + "line_number": 1029 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "635b865541a9b317d71b354dc07769e554004a0a", + "is_verified": false, + "line_number": 1033 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "eeb22523a5f23b8e2f2839101e2a21df63062eef", + "is_verified": false, + "line_number": 1036 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "cf7ae21a07aec42c0047f67e1b0b7ecd28fc23b5", + "is_verified": false, + "line_number": 1040 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9fe5b3fda621da0e9b76aa653d894f94f8f58cd4", + "is_verified": false, + "line_number": 1044 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f1d33d6aede0dfb7fe9978bebd04c76d861c98c3", + "is_verified": false, + "line_number": 1047 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4f4dde0efe7acd336975cd25fc68e25347fd64ee", + "is_verified": false, + "line_number": 1050 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "353aafcecdb8834ff13733ca486183ed2882e7ec", + "is_verified": false, + "line_number": 1054 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7969827f4e081fc3ab6d578be9fe52cf55b34bef", + "is_verified": false, + "line_number": 1057 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ac92f6ef74f09318d36f34716ed2f258b5e0924f", + "is_verified": false, + "line_number": 1060 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "288c8b24d63adf108e603c52001b6412037a9edc", + "is_verified": false, + "line_number": 1064 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "36149fc78b01f35bca00b832a55a4ea4f21995ae", + "is_verified": false, + "line_number": 1068 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4b07e969bf7c1a9efdf5eab7e13abaa484c49d38", + "is_verified": false, + "line_number": 1072 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "5a485a4915f94231f9dc5b355ddda367442ba450", + "is_verified": false, + "line_number": 1076 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "17df0cf1bffb39d85a2aea45c887f1998ffc48a8", + "is_verified": false, + "line_number": 1080 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a6bc2cd23b205c0d88f94eef4d6c1268906d0670", + "is_verified": false, + "line_number": 1083 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "19a998b1bf7031d19515cd35f049a7a6aa7dd1b3", + "is_verified": false, + "line_number": 1087 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "ea4d705920dea9e9007f7ffd977007d97d93720a", + "is_verified": false, + "line_number": 1091 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4a92c1257b67845f12260b454ba353a5919dec29", + "is_verified": false, + "line_number": 1094 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7e42e0804bd25c31e53b2f0871fa2b3551dc66d9", + "is_verified": false, + "line_number": 1099 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "dab00d860d09dd9092b16718edd82bb24a6a21e9", + "is_verified": false, + "line_number": 1103 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "09d8666b35e6c586e3ac50ff958d10e8f3a12d3f", + "is_verified": false, + "line_number": 1106 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7ecd16de4642448e5a002d0eb887796642d37c29", + "is_verified": false, + "line_number": 1110 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f65cbf613806c65f44181f17817d02c7be05ceda", + "is_verified": false, + "line_number": 1114 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2364d220157112e44b4d06ea9df8f2b9fb44069e", + "is_verified": false, + "line_number": 1117 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "39ffec566bffcf8c829bbb54c2f3e06aadbccb15", + "is_verified": false, + "line_number": 1120 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2fd4d093008863345a56756800819a01bf8e0451", + "is_verified": false, + "line_number": 1125 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "bae67d3ce231086fba18abc7365c94878f900c14", + "is_verified": false, + "line_number": 1128 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3b7990b0f82bc9bc6c4ec02744f9c02e76aac827", + "is_verified": false, + "line_number": 1131 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9072ebcbad57a1ae4256c5ae37c1e7c7ae5325de", + "is_verified": false, + "line_number": 1135 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "33e224ae0061fa6dc855702e88cad5e948136009", + "is_verified": false, + "line_number": 1139 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "e0c6ae09dd70fa25056d591ada0ad32df0dfe873", + "is_verified": false, + "line_number": 1142 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "156a735a4c43b9c6b0c08f6b857738968fe588d4", + "is_verified": false, + "line_number": 1146 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "336d02c1e7195c5237197b5884304099ab15c6ba", + "is_verified": false, + "line_number": 1149 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "02757ec3c99c3192621db35f0eea3897cede465a", + "is_verified": false, + "line_number": 1153 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b015b77432bd6d255596af7b2f552d8e8c91a7f7", + "is_verified": false, + "line_number": 1157 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4dcc5c09923b9c0c9014f1f416f58aed8360e584", + "is_verified": false, + "line_number": 1160 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "32026694f097ae0956b46d081f53c72d129a0e9d", + "is_verified": false, + "line_number": 1164 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1ef51736be44df9a195f0a4ecc99642e7e006803", + "is_verified": false, + "line_number": 1167 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "1be172b28420494a97b5bd6dc5d20d9b54d52047", + "is_verified": false, + "line_number": 1170 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "3e536139add3f70bf34712d57cf490dc9c631553", + "is_verified": false, + "line_number": 1173 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4035430d526a269d8e16277f9be0f9c6a7e695bd", + "is_verified": false, + "line_number": 1177 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "01a928fe600e802e506f5354d0be5df023952b7d", + "is_verified": false, + "line_number": 1180 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "612114aa542d50acb4e8481ff643adb46c6e71b3", + "is_verified": false, + "line_number": 1188 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "11973b25b26c5ffab277f15a5f39da63518c061c", + "is_verified": false, + "line_number": 1192 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2fbe8ab30e5355ea9d7538aec4d6c869562a0ed8", + "is_verified": false, + "line_number": 1195 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a664083cd7ea977f953eb398c15a7391521e8c88", + "is_verified": false, + "line_number": 1198 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "bcc923e3a3bbb5c5c7c2f2b5e17bda91f8076652", + "is_verified": false, + "line_number": 1201 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "66022833f4701f45cff007311050911fe571487c", + "is_verified": false, + "line_number": 1205 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "512b3e49cdd404e4e23779be697a6801e04255ab", + "is_verified": false, + "line_number": 1209 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "b3f13048bf1127d22a091b20bef5f1fb485b94c2", + "is_verified": false, + "line_number": 1213 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f50a9ae6c1f90c2adc6b60bbe3779ed40e14ca9e", + "is_verified": false, + "line_number": 1217 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "a6d813aa7164341218d80a2b625ff1b254fa10c3", + "is_verified": false, + "line_number": 1221 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "422f025608080feaba8cb1fbbb522deb3f43cdcc", + "is_verified": false, + "line_number": 1225 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8239574b4263502316ae4af75858c8537b8f9dc2", + "is_verified": false, + "line_number": 1230 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7c43a5a81cdfc2d174e64e7441e07b48f610be0e", + "is_verified": false, + "line_number": 1235 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "735bd20202e59e618bfe941a5941731da477e7b6", + "is_verified": false, + "line_number": 1238 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "32f11283bec656108388929b40993090be755520", + "is_verified": false, + "line_number": 1241 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "4801a08438ed2a6af40afdf77d92cf8412cae7fb", + "is_verified": false, + "line_number": 1246 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "10268f6f4f68752aa603c74f237e00cf940909a4", + "is_verified": false, + "line_number": 1286 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "8ac9d9448e688e8f94e810f2c49fd9b728bd2041", + "is_verified": false, + "line_number": 1326 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "7dbba2db5c8622d492abdd259dd9033ed5f205e2", + "is_verified": false, + "line_number": 1334 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "f0257d02d23f53e799476af74cf0386375d4b6c2", + "is_verified": false, + "line_number": 1362 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "95b02c02e7cb902e9603042bf77d2ce3b47d7dd1", + "is_verified": false, + "line_number": 1367 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "c1a38efe10a08cb343b44ec85e4f991fa64e0dc8", + "is_verified": false, + "line_number": 1372 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "77fb73a7cac9311a40dd4d7f73c5991ef9e79fb6", + "is_verified": false, + "line_number": 1375 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "9b0596f2945cdeab0d6fb2407275942153f87d9c", + "is_verified": false, + "line_number": 1387 + }, + { + "type": "Base64 High Entropy String", + "filename": "pnpm-lock.yaml", + "hashed_secret": "2a6ec2710324e581e13c5bd7ce5f78fd563b3db0", + "is_verified": false, + "line_number": 1390 + } + ] + }, + "generated_at": "2026-04-28T15:20:02Z" +} diff --git a/CLAUDE.md b/CLAUDE.md index aeda425..5373c6a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,16 +16,31 @@ The system's most distinctive property: highlighting in blind mode reveals **zer ## Current State -- **Phase:** spec approved, ready to implement (planning next) -- **Repo:** not yet (Gitea creation pending — see deferred steps in handoff) -- **Stack:** Node 22 + TypeScript, Fastify + `ws`, Svelte + Vite, `chess.js`. pnpm workspace with `packages/{server,client,shared}`. -- **Deploy target:** new LXC on node-241 behind Caddy CT 600 → `chess.sethpc.xyz`. Systemd-managed Node service on port 3000. In-memory game state only (no DB). +- **Phase:** MVP **deployed and live** at https://chess.sethpc.xyz (2026-04-28). +- **Repo:** `git.sethpc.xyz/Seth/blind_chess`. +- **Stack:** Node 22 + TypeScript, Fastify + `ws`, Svelte 5 + Vite, `chess.js`. pnpm workspace with `packages/{server,client,shared}`. +- **Deploy:** LXC **CT 690 on node-241** at 192.168.0.245, behind Caddy CT 600. Systemd unit `blind-chess.service`, port 3000. In-memory state only. +- **Tests:** 43 passing — 21 in shared (geometric helper), 22 in server (FSM + view + 4 real-WS integration). +- **Known gaps (deferred):** drag-and-drop input (click-to-move only), full integration coverage of every endgame path, mobile-specific polish, observability beyond `/api/health`. ## Key files - `IDEA.md` — original project brief (Seth's words) - `DECISIONS.md` — locked architectural and gameplay decisions -- `docs/superpowers/specs/2026-04-28-blind-chess-design.md` — full design spec (everything: data model, protocol, FSM, testing) +- `docs/superpowers/specs/2026-04-28-blind-chess-design.md` — full design spec (data model, protocol, FSM, testing) +- `packages/shared/src/geometric.ts` — the zero-leak helper. The signature is the proof. +- `packages/server/src/view.ts` — `buildView`, the security boundary. +- `packages/server/src/commit.ts` — touch-move FSM (the spec's hierarchy decision table). +- `packages/server/src/translator.ts` — chess.js `Move` → moderator-vocabulary enum. +- `deploy/blind-chess.service` — systemd unit (canonical at `/etc/systemd/system/blind-chess.service` on the CT). +- `deploy/Caddyfile.snippet` — block already added to `/etc/caddy/Caddyfile` on CT 600. + +## Operations + +- **Logs:** `ssh root@192.168.0.245 'journalctl -u blind-chess -f'` +- **Restart:** `ssh root@192.168.0.245 'systemctl restart blind-chess'` +- **Health:** `curl https://chess.sethpc.xyz/api/health` +- **Deploy update:** `pnpm -r build` → `pnpm --filter @blind-chess/server deploy --prod --legacy .deploy-server` → rsync server bundle to `/opt/blind-chess/server/` and client `dist/` to `/opt/blind-chess/client/dist/` → `chown -R blindchess:blindchess /opt/blind-chess` → `systemctl restart blind-chess`. Server restart drops in-memory games (acceptable for MVP). ## Conventions diff --git a/DECISIONS.md b/DECISIONS.md index 8357c60..8b1135c 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -38,6 +38,18 @@ Format: `YYYY-MM-DD: ` - 2026-04-28: Resign + draw-offer/accept-decline flow — standard chess UX. Resignation ends without grace; disconnect applies grace. - 2026-04-28: Game-over screen reveals full board for both sides — post-game review is part of the experience. +## Implementation outcomes (2026-04-28 build session) + +- 2026-04-28: **Repo:** `git.sethpc.xyz/Seth/blind_chess`. Created via `gitea create blind_chess`. Default branch `main`. +- 2026-04-28: **CT:** 690 on node-241, hostname `blind-chess`, IP 192.168.0.245, Debian 12, Node 22.22.2. 2 cores / 512 MB RAM / 8 GB rootfs. Resting memory ~29 MB, plenty of headroom. +- 2026-04-28: **Chosen `chess.js` v1.4.0** — uses `Move.isEnPassant()` / `isKingsideCastle()` / `isQueensideCastle()` instead of the deprecated `flags` string. The `Move` constructor's deprecated `flags` field is intentionally not relied upon. +- 2026-04-28: **Half-move clock for the 50-move rule** is read from FEN field 4 (chess.js doesn't expose it directly). See `translator.ts:halfMoveClock`. +- 2026-04-28: **Shared package import resolution** — `packages/shared/package.json` `main` and `exports` point to `./dist/`. Source `.ts` is dev-only. Always run `pnpm --filter @blind-chess/shared build` before `pnpm --filter @blind-chess/server build` (the workspace project refs handle this when running `pnpm -r build`). +- 2026-04-28: **Client routing** is hash-based with a pathname fallback in `App.svelte` so `https://chess.sethpc.xyz/g/` (the share URL) and `https://chess.sethpc.xyz/#/g/` (the post-create URL) both render the game. The Fastify SPA fallback serves `index.html` on any non-matching `text/html` request. +- 2026-04-28: **Click-to-move only** — drag-and-drop deferred. Tap-arm + tap-destination is faithful to the touch-move FSM and works identically on phone and desktop. +- 2026-04-28: **WS path through Caddy** — `wss://chess.sethpc.xyz/ws?game=` works without explicit `transport ws` config. Caddy's reverse_proxy handles upgrade transparently. +- 2026-04-28: **Public DNS** — relies on existing `*.sethpc.xyz` wildcard pointing at the WAN IP; no Pi-hole entry was needed. Caddy host-routes `chess.sethpc.xyz` to 192.168.0.245:3000. + ## Deferred / Rejected diff --git a/deploy/Caddyfile.snippet b/deploy/Caddyfile.snippet new file mode 100644 index 0000000..3af4ea1 --- /dev/null +++ b/deploy/Caddyfile.snippet @@ -0,0 +1,7 @@ +# Snippet for Caddy CT 600 — append to /etc/caddy/Caddyfile. +# Backend: blind-chess LXC on node-241, port 3000. + +chess.sethpc.xyz { + reverse_proxy :3000 + encode gzip zstd +} diff --git a/deploy/blind-chess.service b/deploy/blind-chess.service new file mode 100644 index 0000000..ff75bfa --- /dev/null +++ b/deploy/blind-chess.service @@ -0,0 +1,31 @@ +[Unit] +Description=blind_chess server (Fastify + ws) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=blindchess +Group=blindchess +WorkingDirectory=/opt/blind-chess +ExecStart=/usr/bin/node /opt/blind-chess/server/dist/server.js +Environment=NODE_ENV=production +Environment=PORT=3000 +Environment=HOST=0.0.0.0 +Environment=STATIC_DIR=/opt/blind-chess/client/dist +Environment=PUBLIC_BASE=https://chess.sethpc.xyz +Environment=LOG_LEVEL=info +Restart=always +RestartSec=2s +StandardOutput=journal +StandardError=journal + +# Hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/opt/blind-chess + +[Install] +WantedBy=multi-user.target diff --git a/package.json b/package.json new file mode 100644 index 0000000..68b6ea0 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "blind_chess", + "version": "0.1.0", + "private": true, + "type": "module", + "packageManager": "pnpm@10.33.2", + "engines": { + "node": ">=22.0.0" + }, + "scripts": { + "build": "pnpm -r build", + "test": "pnpm -r test", + "dev:server": "pnpm --filter @blind-chess/server dev", + "dev:client": "pnpm --filter @blind-chess/client dev", + "typecheck": "pnpm -r typecheck" + }, + "devDependencies": { + "typescript": "^5.6.0", + "vitest": "^3.0.0" + } +} diff --git a/packages/client/index.html b/packages/client/index.html new file mode 100644 index 0000000..ca48d98 --- /dev/null +++ b/packages/client/index.html @@ -0,0 +1,14 @@ + + + + + + + blind chess + + + +
+ + + diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 0000000..84e4ea3 --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,22 @@ +{ + "name": "@blind-chess/client", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "typecheck": "svelte-check --tsconfig ./tsconfig.json" + }, + "dependencies": { + "@blind-chess/shared": "workspace:*" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^5.0.0", + "svelte": "^5.0.0", + "svelte-check": "^4.1.0", + "typescript": "^5.6.0", + "vite": "^6.0.0" + } +} diff --git a/packages/client/src/App.svelte b/packages/client/src/App.svelte new file mode 100644 index 0000000..ab72501 --- /dev/null +++ b/packages/client/src/App.svelte @@ -0,0 +1,35 @@ + + +{#if route.name === 'landing'} + +{:else} + +{/if} diff --git a/packages/client/src/app.css b/packages/client/src/app.css new file mode 100644 index 0000000..2d9c186 --- /dev/null +++ b/packages/client/src/app.css @@ -0,0 +1,64 @@ +:root { + color-scheme: dark; + --bg: #0c0d10; + --panel: #15171c; + --panel-2: #1d2027; + --border: #2a2e38; + --text: #e8e8ea; + --text-dim: #8d92a0; + --accent: #d35400; + --accent-dim: #8a3a09; + --light: #d8c8a8; + --dark: #6b4f3a; + --highlight: rgba(74, 222, 128, 0.55); + --highlight-cap: rgba(248, 113, 113, 0.65); + --armed: rgba(211, 84, 0, 0.55); + --touched: rgba(211, 84, 0, 0.85); + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; +} + +* { box-sizing: border-box; } + +html, body, #app { margin: 0; padding: 0; height: 100%; background: var(--bg); color: var(--text); } + +body { + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: transparent; +} + +button { + font-family: inherit; + font-size: inherit; + background: var(--panel-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: 6px; + padding: 8px 14px; + cursor: pointer; + transition: background 0.15s, border-color 0.15s; +} +button:hover:not(:disabled) { background: #252932; border-color: var(--accent); } +button:disabled { opacity: 0.5; cursor: not-allowed; } +button.primary { + background: var(--accent); + border-color: var(--accent); + color: white; + font-weight: 600; +} +button.primary:hover { background: #e2671f; border-color: #e2671f; } + +input, select { + font-family: inherit; + font-size: inherit; + background: var(--panel-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: 6px; + padding: 8px 10px; +} + +a { color: var(--accent); text-decoration: none; } +a:hover { text-decoration: underline; } + +.muted { color: var(--text-dim); } +.mono { font-family: ui-monospace, SFMono-Regular, monospace; } diff --git a/packages/client/src/lib/Board.svelte b/packages/client/src/lib/Board.svelte new file mode 100644 index 0000000..d208696 --- /dev/null +++ b/packages/client/src/lib/Board.svelte @@ -0,0 +1,179 @@ + + +
+ {#each ranksDisplay as r (r)} + {#each filesDisplay as f (f)} + {@const sq = `${f}${r}` as Square} + {@const piece = pieces[sq]} + {@const sc = squareColor(sq)} + {@const isArmed = sq === armedSquare} + {@const isTouched = sq === touchedSquare} + {@const isHighlight = highlights.has(sq)} + {@const isHighlightCap = isHighlight && piece && piece.color !== you} + + {/each} + {/each} +
+ + diff --git a/packages/client/src/lib/Game.svelte b/packages/client/src/lib/Game.svelte new file mode 100644 index 0000000..013f64f --- /dev/null +++ b/packages/client/src/lib/Game.svelte @@ -0,0 +1,229 @@ + + +
+ +
+ ← New game + {turnLabel} + + {game.state.mode ?? '…'} + {#if game.state.you} + · You: {game.state.you === 'w' ? 'White' : 'Black'} + {/if} + +
+ + {#if game.state.gameStatus === 'waiting'} +
+

Share this link to start the game

+

The first person to open it claims the open color.

+ +
+ {:else if game.state.view && game.state.you} +
+ +
+ + + {/if} +
+ +{#if pendingPromotion && game.state.you} + pendingPromotion = null} + /> +{/if} + + diff --git a/packages/client/src/lib/Landing.svelte b/packages/client/src/lib/Landing.svelte new file mode 100644 index 0000000..952c854 --- /dev/null +++ b/packages/client/src/lib/Landing.svelte @@ -0,0 +1,162 @@ + + +
+
+

blind chess

+

A two-player chess variant where each player sees only their own pieces. The server is the moderator.

+
+ +
+

Create a game

+ +
+ Mode +
+ + +
+
+ +
+ You play as +
+ + + +
+
+ +
+ +
+ + + + {#if error} +

Error: {error}

+ {/if} +
+ +
+ git.sethpc.xyz/Seth/blind_chess +
+
+ + diff --git a/packages/client/src/lib/ModeratorPanel.svelte b/packages/client/src/lib/ModeratorPanel.svelte new file mode 100644 index 0000000..011a575 --- /dev/null +++ b/packages/client/src/lib/ModeratorPanel.svelte @@ -0,0 +1,79 @@ + + +
+
Moderator
+
+ {#each visible as a, i (i)} +
+ {a.ply > 0 ? `#${a.ply}` : ''} + {moderatorText(a.text, a.payload)} +
+ {:else} +
The moderator is silent.
+ {/each} +
+
+ + diff --git a/packages/client/src/lib/PromotionDialog.svelte b/packages/client/src/lib/PromotionDialog.svelte new file mode 100644 index 0000000..fec2286 --- /dev/null +++ b/packages/client/src/lib/PromotionDialog.svelte @@ -0,0 +1,68 @@ + + + + + diff --git a/packages/client/src/lib/moderator-strings.ts b/packages/client/src/lib/moderator-strings.ts new file mode 100644 index 0000000..2566514 --- /dev/null +++ b/packages/client/src/lib/moderator-strings.ts @@ -0,0 +1,44 @@ +import type { ModeratorText } from '@blind-chess/shared'; + +const MAP: Record = { + no_such_piece: 'That piece no longer exists.', + no_legal_moves: 'That piece has no legal moves.', + wont_help: 'Moving that piece will not help you.', + illegal_move: 'Illegal move.', + white_moved: 'White has moved.', + black_moved: 'Black has moved.', + white_moved_captured: 'White has moved and captured.', + black_moved_captured: 'Black has moved and captured.', + white_moved_captured_ep: 'White has captured en passant.', + black_moved_captured_ep: 'Black has captured en passant.', + white_castled_kingside: 'White has castled kingside.', + white_castled_queenside: 'White has castled queenside.', + black_castled_kingside: 'Black has castled kingside.', + black_castled_queenside: 'Black has castled queenside.', + white_in_check: 'White is in check.', + black_in_check: 'Black is in check.', + white_promoted: 'White has promoted.', + black_promoted: 'Black has promoted.', + white_checkmate: 'Checkmate. White wins.', + black_checkmate: 'Checkmate. Black wins.', + stalemate: 'Stalemate. The game is a draw.', + draw_insufficient: 'Draw — insufficient material.', + draw_fifty: 'Draw — fifty-move rule.', + draw_threefold: 'Draw — threefold repetition.', + white_resigned: 'White has resigned.', + black_resigned: 'Black has resigned.', + draw_agreed: 'The game is a draw by agreement.', + game_abandoned: 'The game has been abandoned.', +}; + +export function moderatorText( + text: ModeratorText, + payload?: { promotedTo?: 'q' | 'r' | 'b' | 'n' | 'p' | 'k' }, +): string { + const base = MAP[text]; + if ((text === 'white_promoted' || text === 'black_promoted') && payload?.promotedTo) { + const piece = { q: 'queen', r: 'rook', b: 'bishop', n: 'knight', p: 'pawn', k: 'king' }[payload.promotedTo]; + return base.replace('promoted.', `promoted to a ${piece}.`); + } + return base; +} diff --git a/packages/client/src/lib/pieces.ts b/packages/client/src/lib/pieces.ts new file mode 100644 index 0000000..b55e5c5 --- /dev/null +++ b/packages/client/src/lib/pieces.ts @@ -0,0 +1,9 @@ +import type { Piece } from '@blind-chess/shared'; + +export function pieceGlyph(piece: Piece): string { + const map: Record = { + wk: '♔', wq: '♕', wr: '♖', wb: '♗', wn: '♘', wp: '♙', + bk: '♚', bq: '♛', br: '♜', bb: '♝', bn: '♞', bp: '♟', + }; + return map[`${piece.color}${piece.type}`] ?? '?'; +} diff --git a/packages/client/src/lib/stores/game.ts b/packages/client/src/lib/stores/game.ts new file mode 100644 index 0000000..b3c1a62 --- /dev/null +++ b/packages/client/src/lib/stores/game.ts @@ -0,0 +1,152 @@ +import type { + Announcement, + BoardView, + ClientMessage, + Color, + ErrorCode, + GameStatus, + Mode, + PromotionType, + ServerMessage, + Square, + EndReason, +} from '@blind-chess/shared'; + +interface GameStateValue { + ws: WebSocket | null; + connected: boolean; + gameId: string | null; + you: Color | null; + view: BoardView | null; + announcements: Announcement[]; + gameStatus: GameStatus; + mode: Mode | null; + highlightingEnabled: boolean; + touchedPiece: Square | null; + drawOffer: { from: Color } | null; + endReason: EndReason | null; + winner: Color | null; + opponentConnected: boolean; + lastError: { code: ErrorCode; message: string; at: number } | null; +} + +function makeStore() { + const state = $state({ + ws: null, + connected: false, + gameId: null, + you: null, + view: null, + announcements: [], + gameStatus: 'waiting', + mode: null, + highlightingEnabled: false, + touchedPiece: null, + drawOffer: null, + endReason: null, + winner: null, + opponentConnected: false, + lastError: null, + }); + + function tokenKey(gameId: string) { return `bc:${gameId}`; } + + function connect(gameId: string, joinAs?: Color | 'auto') { + if (state.ws) state.ws.close(); + state.gameId = gameId; + const proto = location.protocol === 'https:' ? 'wss' : 'ws'; + const url = `${proto}://${location.host}/ws?game=${gameId}`; + const ws = new WebSocket(url); + state.ws = ws; + ws.onopen = () => { + state.connected = true; + const token = localStorage.getItem(tokenKey(gameId)) ?? undefined; + const hello: ClientMessage = token + ? { type: 'hello', gameId, token } + : { type: 'hello', gameId, joinAs: joinAs ?? 'auto' }; + ws.send(JSON.stringify(hello)); + }; + ws.onmessage = (ev) => onServerMessage(JSON.parse(ev.data) as ServerMessage); + ws.onclose = () => { + state.connected = false; + // attempt reconnect after 2s if game is still active + if (state.gameStatus === 'active') { + setTimeout(() => { if (state.gameId === gameId) connect(gameId); }, 2000); + } + }; + ws.onerror = () => { state.connected = false; }; + } + + function onServerMessage(m: ServerMessage) { + switch (m.type) { + case 'joined': + if (m.you === 'spectator-rejected') { + state.lastError = { code: 'spectators_disabled', message: 'both slots filled', at: Date.now() }; + return; + } + state.you = m.you; + state.view = m.view; + state.announcements = m.announcements; + state.gameStatus = m.gameStatus; + state.mode = m.mode; + state.highlightingEnabled = m.highlightingEnabled; + state.opponentConnected = m.opponentConnected; + if (state.gameId) localStorage.setItem(tokenKey(state.gameId), m.token); + break; + case 'update': + state.view = m.view; + state.gameStatus = m.gameStatus; + state.touchedPiece = m.touchedPiece ?? null; + state.drawOffer = m.drawOffer ?? null; + state.endReason = m.endReason ?? null; + state.winner = m.winner ?? null; + if (m.newAnnouncements.length) { + state.announcements = [...state.announcements, ...m.newAnnouncements]; + } + break; + case 'peer-status': + if (state.you && m.color !== state.you) { + state.opponentConnected = m.connected; + } + break; + case 'error': + state.lastError = { code: m.code, message: m.message, at: Date.now() }; + break; + case 'ping': + send({ type: 'pong' }); + break; + } + } + + function send(m: ClientMessage) { + if (state.ws?.readyState === WebSocket.OPEN) { + state.ws.send(JSON.stringify(m)); + } + } + + function commit(from: Square, to?: Square, promotion?: PromotionType) { + send({ type: 'commit', from, to, promotion }); + } + + function resign() { send({ type: 'resign' }); } + function offerDraw() { send({ type: 'offer-draw' }); } + function respondDraw(accept: boolean) { send({ type: 'respond-draw', accept }); } + + function disconnect() { + state.ws?.close(); + state.ws = null; + state.connected = false; + } + + return { + state, + connect, + disconnect, + commit, + resign, + offerDraw, + respondDraw, + }; +} + +export const game = makeStore(); diff --git a/packages/client/src/main.ts b/packages/client/src/main.ts new file mode 100644 index 0000000..14faed4 --- /dev/null +++ b/packages/client/src/main.ts @@ -0,0 +1,6 @@ +import { mount } from 'svelte'; +import App from './App.svelte'; +import './app.css'; + +const app = mount(App, { target: document.getElementById('app')! }); +export default app; diff --git a/packages/client/svelte.config.js b/packages/client/svelte.config.js new file mode 100644 index 0000000..4c6b24b --- /dev/null +++ b/packages/client/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +export default { + preprocess: vitePreprocess(), +}; diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json new file mode 100644 index 0000000..9082025 --- /dev/null +++ b/packages/client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "types": ["svelte", "vite/client"], + "allowSyntheticDefaultImports": true, + "verbatimModuleSyntax": true + }, + "include": ["src/**/*", "src/**/*.svelte"] +} diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts new file mode 100644 index 0000000..d1f2614 --- /dev/null +++ b/packages/client/vite.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; + +export default defineConfig({ + plugins: [svelte()], + server: { + port: 5173, + proxy: { + '/api': 'http://localhost:3000', + '/ws': { target: 'ws://localhost:3000', ws: true, rewriteWsOrigin: true }, + }, + }, + build: { + outDir: 'dist', + sourcemap: true, + }, +}); diff --git a/packages/server/package.json b/packages/server/package.json new file mode 100644 index 0000000..a130389 --- /dev/null +++ b/packages/server/package.json @@ -0,0 +1,32 @@ +{ + "name": "@blind-chess/server", + "version": "0.1.0", + "private": true, + "type": "module", + "main": "dist/server.js", + "scripts": { + "build": "tsc -b", + "dev": "tsx watch src/server.ts", + "start": "node dist/server.js", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@blind-chess/shared": "workspace:*", + "@fastify/static": "^8.0.0", + "@fastify/websocket": "^11.0.0", + "chess.js": "^1.4.0", + "fastify": "^5.2.0", + "pino": "^9.5.0", + "ws": "^8.18.0", + "zod": "^3.24.0" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/ws": "^8.5.13", + "pino-pretty": "^11.3.0", + "tsx": "^4.19.2", + "typescript": "^5.6.0", + "vitest": "^3.0.0" + } +} diff --git a/packages/server/src/commit.ts b/packages/server/src/commit.ts new file mode 100644 index 0000000..76ea5d1 --- /dev/null +++ b/packages/server/src/commit.ts @@ -0,0 +1,132 @@ +import type { Move } from 'chess.js'; +import { + geometricMoves, + type Announcement, + type Color, + type Piece, + type PromotionType, + type Square, +} from '@blind-chess/shared'; +import type { Game, MoveRecord } from './state.js'; +import { announce, translateMove } from './translator.js'; +import { ownSquares } from './view.js'; + +export type CommitResult = + | { kind: 'error'; code: 'not_your_turn' | 'must_move_touched_piece' | 'promotion_required' } + | { kind: 'announce'; announcements: Announcement[] } + | { kind: 'silent' } + | { kind: 'applied'; announcements: Announcement[]; moveRecord: MoveRecord }; + +export interface CommitInput { + from: Square; + to?: Square; + promotion?: PromotionType; +} + +export function handleCommit(game: Game, color: Color, msg: CommitInput): CommitResult { + if (game.status !== 'active') return { kind: 'error', code: 'not_your_turn' }; + if (game.chess.turn() !== color) return { kind: 'error', code: 'not_your_turn' }; + + const touched = game.armed?.color === color ? game.armed.from : null; + + if (touched) { + if (msg.from !== touched) return { kind: 'error', code: 'must_move_touched_piece' }; + if (!msg.to) return { kind: 'silent' }; + return tryMove(game, color, { from: msg.from, to: msg.to, promotion: msg.promotion }); + } + + const piece = game.chess.get(msg.from) as { color: Color; type: Piece['type'] } | false; + if (!piece || piece.color !== color) { + return announceWith(game, 'no_such_piece', color); + } + + const pseudo = geometricMoves( + { color: piece.color, type: piece.type }, + msg.from, + ownSquares(game, color), + ); + if (pseudo.length === 0) { + return announceWith(game, 'no_legal_moves', color); + } + + const legal = chessJsLegalFrom(game, msg.from); + if (legal.length === 0) { + return announceWith(game, 'wont_help', color); + } + + game.armed = { color, from: msg.from }; + + if (!msg.to) return { kind: 'silent' }; + return tryMove(game, color, { from: msg.from, to: msg.to, promotion: msg.promotion }); +} + +function tryMove( + game: Game, + color: Color, + msg: { from: Square; to: Square; promotion?: PromotionType }, +): CommitResult { + if (isPromotionRequired(game, msg.from, msg.to) && !msg.promotion) { + return { kind: 'error', code: 'promotion_required' }; + } + + let move: Move | null = null; + try { + move = game.chess.move({ from: msg.from, to: msg.to, promotion: msg.promotion }); + } catch { + move = null; + } + + if (!move) { + return announceWith(game, 'illegal_move', color); + } + + game.armed = null; + + const ply = game.chess.history().length; + const moveRecord: MoveRecord = { + ply, + by: color, + from: msg.from, + to: msg.to, + san: move.san, + capturedPieceType: move.captured, + promotion: move.promotion as PromotionType | undefined, + flags: { + castle: move.isKingsideCastle() ? 'k' : move.isQueensideCastle() ? 'q' : undefined, + enPassant: move.isEnPassant() || undefined, + check: game.chess.inCheck() || undefined, + mate: game.chess.isCheckmate() || undefined, + }, + at: Date.now(), + }; + + game.moveHistory.push(moveRecord); + const announcements = translateMove(game, move); + game.announcements.push(...announcements); + + return { kind: 'applied', announcements, moveRecord }; +} + +function announceWith( + game: Game, + text: 'no_such_piece' | 'no_legal_moves' | 'wont_help' | 'illegal_move', + color: Color, +): CommitResult { + const ply = game.chess.history().length; + const a = announce(text, color, ply); + game.announcements.push(a); + return { kind: 'announce', announcements: [a] }; +} + +function chessJsLegalFrom(game: Game, from: Square): string[] { + return game.chess.moves({ square: from as never, verbose: false } as never) as string[]; +} + +function isPromotionRequired(game: Game, from: Square, to: Square): boolean { + const piece = game.chess.get(from); + if (!piece || piece.type !== 'p') return false; + const toRank = to[1]; + if (piece.color === 'w' && toRank === '8') return true; + if (piece.color === 'b' && toRank === '1') return true; + return false; +} diff --git a/packages/server/src/games.ts b/packages/server/src/games.ts new file mode 100644 index 0000000..bb15e14 --- /dev/null +++ b/packages/server/src/games.ts @@ -0,0 +1,122 @@ +import { Chess } from 'chess.js'; +import { randomBytes } from 'node:crypto'; +import type { + Color, GameId, Mode, PlayerToken, +} from '@blind-chess/shared'; +import { type Game, PRUNE_AFTER_FINISHED_MS, RATE_LIMIT } from './state.js'; + +const games = new Map(); + +export function newGameId(): GameId { + const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; + let id = ''; + while (true) { + const buf = randomBytes(8); + id = ''; + for (let i = 0; i < 8; i++) id += alphabet[buf[i]! % alphabet.length]; + if (!games.has(id)) return id; + } +} + +export function newPlayerToken(): PlayerToken { + return randomBytes(18).toString('base64url').slice(0, 24).toLowerCase().replace(/[^a-z0-9]/g, 'a'); +} + +export function chooseSide(side: Color | 'random'): Color { + if (side === 'random') return Math.random() < 0.5 ? 'w' : 'b'; + return side; +} + +export function createGame(opts: { + mode: Mode; + creatorSide: Color; + highlightingEnabled: boolean; +}): { game: Game; creatorToken: PlayerToken } { + const id = newGameId(); + const creatorToken = newPlayerToken(); + const now = Date.now(); + + const game: Game = { + id, + mode: opts.mode, + highlightingEnabled: opts.highlightingEnabled, + status: 'waiting', + createdAt: now, + chess: new Chess(), + moveHistory: [], + announcements: [], + players: { + w: opts.creatorSide === 'w' ? makeSlot(creatorToken, now) : null, + b: opts.creatorSide === 'b' ? makeSlot(creatorToken, now) : null, + }, + armed: null, + drawOffer: null, + disconnectAt: {}, + }; + + games.set(id, game); + return { game, creatorToken }; +} + +function makeSlot(token: PlayerToken, now: number) { + return { + token, + socket: null, + joinedAt: now, + rateBucket: { tokens: RATE_LIMIT.capacity, last: now }, + }; +} + +export function getGame(id: GameId): Game | undefined { + return games.get(id); +} + +export function deleteGame(id: GameId): void { + games.delete(id); +} + +export function allGames(): IterableIterator { + return games.values(); +} + +export function activeGameCount(): number { + let n = 0; + for (const g of games.values()) if (g.status !== 'finished') n++; + return n; +} + +/** Find game where this token is bound to a player slot; returns the slot color. */ +export function findTokenInGame(game: Game, token: PlayerToken): Color | null { + if (game.players.w?.token === token) return 'w'; + if (game.players.b?.token === token) return 'b'; + return null; +} + +/** Claim the open slot in a game. Returns the color claimed or null if both filled. */ +export function claimSlot( + game: Game, + joinAs: Color | 'auto', +): { color: Color; token: PlayerToken } | null { + const tryClaim = (c: Color): { color: Color; token: PlayerToken } | null => { + if (game.players[c]) return null; + const token = newPlayerToken(); + game.players[c] = makeSlot(token, Date.now()); + return { color: c, token }; + }; + + if (joinAs === 'w') return tryClaim('w'); + if (joinAs === 'b') return tryClaim('b'); + return tryClaim('w') ?? tryClaim('b'); +} + +export function pruneFinished(): number { + const now = Date.now(); + let removed = 0; + for (const [id, g] of games) { + if (g.status === 'finished' && g.finishedAt && now - g.finishedAt > PRUNE_AFTER_FINISHED_MS) { + games.delete(id); + removed++; + } + } + return removed; +} diff --git a/packages/server/src/ratelimit.ts b/packages/server/src/ratelimit.ts new file mode 100644 index 0000000..ea8289a --- /dev/null +++ b/packages/server/src/ratelimit.ts @@ -0,0 +1,18 @@ +import { RATE_LIMIT, type Game } from './state.js'; +import type { Color } from '@blind-chess/shared'; + +/** Token-bucket rate limiter on `commit`. Returns true if allowed. */ +export function consumeCommitToken(game: Game, color: Color): boolean { + const slot = game.players[color]; + if (!slot) return false; + const now = Date.now(); + const elapsed = (now - slot.rateBucket.last) / 1000; + slot.rateBucket.tokens = Math.min( + RATE_LIMIT.capacity, + slot.rateBucket.tokens + elapsed * RATE_LIMIT.refillPerSec, + ); + slot.rateBucket.last = now; + if (slot.rateBucket.tokens < 1) return false; + slot.rateBucket.tokens -= 1; + return true; +} diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts new file mode 100644 index 0000000..6360878 --- /dev/null +++ b/packages/server/src/server.ts @@ -0,0 +1,105 @@ +import Fastify from 'fastify'; +import websocketPlugin from '@fastify/websocket'; +import staticPlugin from '@fastify/static'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { + activeGameCount, + chooseSide, + createGame, + pruneFinished, +} from './games.js'; +import { attachSocket } from './ws.js'; +import { createGameSchema } from './validation.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const PORT = parseInt(process.env.PORT ?? '3000', 10); +const HOST = process.env.HOST ?? '0.0.0.0'; +const STATIC_DIR = process.env.STATIC_DIR ?? path.resolve(__dirname, '../../client/dist'); +const PUBLIC_BASE = process.env.PUBLIC_BASE ?? ''; +const startedAt = Date.now(); + +const fastify = Fastify({ + logger: { + level: process.env.LOG_LEVEL ?? 'info', + transport: process.env.NODE_ENV === 'production' ? undefined : { + target: 'pino-pretty', + options: { colorize: true, translateTime: 'HH:MM:ss' }, + }, + }, + trustProxy: true, +}); + +await fastify.register(websocketPlugin); + +fastify.get('/api/health', async () => ({ + ok: true, + activeGames: activeGameCount(), + uptime: Math.floor((Date.now() - startedAt) / 1000), +})); + +fastify.post('/api/games', async (req, reply) => { + const parsed = createGameSchema.safeParse(req.body); + if (!parsed.success) { + reply.code(400); + return { error: 'malformed', detail: parsed.error.issues }; + } + const { mode, side, highlightingEnabled } = parsed.data; + const creatorSide = chooseSide(side); + const { game, creatorToken } = createGame({ mode, creatorSide, highlightingEnabled }); + + const publicBase = PUBLIC_BASE + || (req.headers.host ? `${req.protocol}://${req.headers.host}` : ''); + const joinUrl = `${publicBase}/g/${game.id}`; + return { gameId: game.id, creatorToken, creatorColor: creatorSide, joinUrl }; +}); + +fastify.get('/ws', { websocket: true }, (socket) => { + // fastify-websocket v11 passes the raw ws socket directly. + const raw = (socket as unknown as { socket?: unknown }).socket ?? socket; + attachSocket(raw as never); +}); + +// Static client assets — serve dist/ if present, gracefully degrade if not. +import('node:fs').then((fs) => { + if (fs.existsSync(STATIC_DIR)) { + fastify.register(staticPlugin, { + root: STATIC_DIR, + prefix: '/', + decorateReply: true, + }); + // SPA fallback: serve index.html for /g/ etc. + fastify.setNotFoundHandler((req, reply) => { + const accept = String(req.headers.accept ?? ''); + if (accept.includes('text/html')) { + return (reply as unknown as { sendFile: (n: string) => unknown }).sendFile('index.html'); + } + reply.code(404).send({ error: 'not_found' }); + }); + } else { + fastify.log.warn({ STATIC_DIR }, 'static client dist not found; serving API only'); + } +}); + +// Janitor: prune finished games every 5 min. +const janitor = setInterval(() => { + const removed = pruneFinished(); + if (removed > 0) fastify.log.info({ removed }, 'pruned finished games'); +}, 5 * 60 * 1000); +janitor.unref(); + +const ready = fastify.listen({ port: PORT, host: HOST }); +ready.then(() => { + fastify.log.info(`blind_chess listening on ${HOST}:${PORT}`); +}).catch((err) => { + fastify.log.error(err); + process.exit(1); +}); + +for (const sig of ['SIGTERM', 'SIGINT'] as const) { + process.on(sig, () => { + fastify.log.info({ sig }, 'shutting down'); + fastify.close().then(() => process.exit(0)); + }); +} diff --git a/packages/server/src/state.ts b/packages/server/src/state.ts new file mode 100644 index 0000000..e39f787 --- /dev/null +++ b/packages/server/src/state.ts @@ -0,0 +1,58 @@ +import type { Chess } from 'chess.js'; +import type { WebSocket } from 'ws'; +import type { + Announcement, + Color, + EndReason, + GameId, + GameStatus, + Mode, + PieceType, + PlayerToken, + PromotionType, + Square, +} from '@blind-chess/shared'; + +export interface MoveRecord { + ply: number; + by: Color; + from: Square; + to: Square; + san: string; + capturedPieceType?: PieceType; + promotion?: PromotionType; + flags: { castle?: 'k' | 'q'; enPassant?: boolean; check?: boolean; mate?: boolean }; + at: number; +} + +export interface PlayerSlot { + token: PlayerToken; + socket: WebSocket | null; + joinedAt: number; + rateBucket: { tokens: number; last: number }; +} + +export interface Game { + id: GameId; + mode: Mode; + highlightingEnabled: boolean; + status: GameStatus; + createdAt: number; + finishedAt?: number; + endReason?: EndReason; + winner?: Color | null; + + chess: Chess; + moveHistory: MoveRecord[]; + announcements: Announcement[]; + + players: { w: PlayerSlot | null; b: PlayerSlot | null }; + + armed: { color: Color; from: Square } | null; + drawOffer: { from: Color; at: number } | null; + disconnectAt: { w?: number; b?: number }; +} + +export const RATE_LIMIT = { capacity: 20, refillPerSec: 10 }; +export const GRACE_MS = 5 * 60 * 1000; +export const PRUNE_AFTER_FINISHED_MS = 30 * 60 * 1000; diff --git a/packages/server/src/translator.ts b/packages/server/src/translator.ts new file mode 100644 index 0000000..54e063e --- /dev/null +++ b/packages/server/src/translator.ts @@ -0,0 +1,73 @@ +import type { Move } from 'chess.js'; +import type { Announcement, Audience, Color, ModeratorText } from '@blind-chess/shared'; +import type { Game } from './state.js'; + +export function announce( + text: ModeratorText, + audience: Audience, + ply: number, + payload?: Announcement['payload'], +): Announcement { + return { text, audience, ply, at: Date.now(), payload }; +} + +/** + * Translate an applied chess.js Move into the moderator vocabulary. + * + * Capturing player learns the captured piece type via their `view` update + * (their canonical board reflects the capture; the captured-pieces tray is + * populated from move history). The opponent gets only the `*_moved_captured` + * announcement. + */ +export function translateMove(game: Game, move: Move): Announcement[] { + const out: Announcement[] = []; + const ply = game.chess.history().length; + const mover = move.color as Color; + const opp: Color = mover === 'w' ? 'b' : 'w'; + const moverWord = mover === 'w' ? 'white' : 'black'; + const oppWord = opp === 'w' ? 'white' : 'black'; + + const isEp = move.isEnPassant(); + const isCap = move.isCapture(); + const isKingsideCastle = move.isKingsideCastle(); + const isQueensideCastle = move.isQueensideCastle(); + const isProm = !!move.promotion; + + // To opponent: the move event itself. + if (isKingsideCastle) { + out.push(announce(`${moverWord}_castled_kingside` as ModeratorText, opp, ply)); + } else if (isQueensideCastle) { + out.push(announce(`${moverWord}_castled_queenside` as ModeratorText, opp, ply)); + } else if (isCap && isEp) { + out.push(announce(`${moverWord}_moved_captured_ep` as ModeratorText, opp, ply)); + } else if (isCap) { + out.push(announce(`${moverWord}_moved_captured` as ModeratorText, opp, ply)); + } else { + out.push(announce(`${moverWord}_moved` as ModeratorText, opp, ply)); + } + + if (isProm) { + out.push(announce(`${moverWord}_promoted` as ModeratorText, opp, ply, { promotedTo: move.promotion })); + } + + // To both: state changes. + if (game.chess.isCheckmate()) { + out.push(announce(`${moverWord}_checkmate` as ModeratorText, 'both', ply)); + } else if (game.chess.inCheck()) { + out.push(announce(`${oppWord}_in_check` as ModeratorText, 'both', ply)); + } + + if (game.chess.isStalemate()) out.push(announce('stalemate', 'both', ply)); + if (game.chess.isInsufficientMaterial()) out.push(announce('draw_insufficient', 'both', ply)); + if (game.chess.isThreefoldRepetition()) out.push(announce('draw_threefold', 'both', ply)); + if (halfMoveClock(game) >= 100) out.push(announce('draw_fifty', 'both', ply)); + + return out; +} + +/** Half-move clock (50-move rule). chess.js exposes it via FEN. */ +function halfMoveClock(game: Game): number { + const fen = game.chess.fen(); + const parts = fen.split(' '); + return parseInt(parts[4] ?? '0', 10) || 0; +} diff --git a/packages/server/src/validation.ts b/packages/server/src/validation.ts new file mode 100644 index 0000000..1cc1473 --- /dev/null +++ b/packages/server/src/validation.ts @@ -0,0 +1,44 @@ +import { z } from 'zod'; + +const colorSchema = z.union([z.literal('w'), z.literal('b')]); +const squareSchema = z.string().regex(/^[a-h][1-8]$/); +const promotionSchema = z.union([z.literal('q'), z.literal('r'), z.literal('b'), z.literal('n')]); +const gameIdSchema = z.string().regex(/^[a-z0-9]{8}$/); +const tokenSchema = z.string().regex(/^[a-z0-9]{24}$/); + +export const helloSchema = z.object({ + type: z.literal('hello'), + gameId: gameIdSchema, + token: tokenSchema.optional(), + joinAs: z.union([colorSchema, z.literal('auto')]).optional(), +}); + +export const commitSchema = z.object({ + type: z.literal('commit'), + from: squareSchema, + to: squareSchema.optional(), + promotion: promotionSchema.optional(), +}); + +export const resignSchema = z.object({ type: z.literal('resign') }); +export const offerDrawSchema = z.object({ type: z.literal('offer-draw') }); +export const respondDrawSchema = z.object({ + type: z.literal('respond-draw'), + accept: z.boolean(), +}); +export const pongSchema = z.object({ type: z.literal('pong') }); + +export const clientMessageSchema = z.discriminatedUnion('type', [ + helloSchema, + commitSchema, + resignSchema, + offerDrawSchema, + respondDrawSchema, + pongSchema, +]); + +export const createGameSchema = z.object({ + mode: z.union([z.literal('blind'), z.literal('vanilla')]), + side: z.union([colorSchema, z.literal('random')]), + highlightingEnabled: z.boolean(), +}); diff --git a/packages/server/src/view.ts b/packages/server/src/view.ts new file mode 100644 index 0000000..b6adb29 --- /dev/null +++ b/packages/server/src/view.ts @@ -0,0 +1,48 @@ +import type { Square as ChessSquare } from 'chess.js'; +import type { BoardView, Color, Piece, Square } from '@blind-chess/shared'; +import type { Game } from './state.js'; + +/** + * The single security boundary for opponent information. + * In blind mode (active games only), opponent pieces are ABSENT from the + * payload — not encrypted-but-present. The wire literally cannot leak what + * the wire never carries. + */ +export function buildView(game: Game, viewer: Color): BoardView { + const pieces: Partial> = {}; + const board = game.chess.board(); + const reveal = game.mode === 'vanilla' || game.status === 'finished'; + + for (let r = 0; r < 8; r++) { + const row = board[r]; + if (!row) continue; + for (let f = 0; f < 8; f++) { + const cell = row[f]; + if (!cell) continue; + if (!reveal && cell.color !== viewer) continue; + pieces[cell.square as Square] = { color: cell.color, type: cell.type }; + } + } + + return { + pieces, + toMove: game.chess.turn() as Color, + inCheck: reveal ? game.chess.inCheck() : (viewer === game.chess.turn() ? game.chess.inCheck() : null), + }; +} + +/** Compute the set of own-occupied squares for a player. Used by the FSM. */ +export function ownSquares(game: Game, color: Color): Set { + const out = new Set(); + const board = game.chess.board(); + for (const row of board) { + if (!row) continue; + for (const cell of row) { + if (!cell) continue; + if (cell.color === color) out.add(cell.square as Square); + } + } + return out; +} + +export type { ChessSquare }; diff --git a/packages/server/src/ws.ts b/packages/server/src/ws.ts new file mode 100644 index 0000000..258f678 --- /dev/null +++ b/packages/server/src/ws.ts @@ -0,0 +1,300 @@ +import type { WebSocket } from 'ws'; +import { + type ClientMessage, + type Color, + type ErrorCode, + type ServerMessage, +} from '@blind-chess/shared'; +import { clientMessageSchema } from './validation.js'; +import { + claimSlot, + findTokenInGame, + getGame, +} from './games.js'; +import type { Game } from './state.js'; +import { GRACE_MS } from './state.js'; +import { handleCommit } from './commit.js'; +import { announce } from './translator.js'; +import { buildView } from './view.js'; +import { consumeCommitToken } from './ratelimit.js'; + +interface SocketCtx { + socket: WebSocket; + game: Game | null; + color: Color | null; +} + +const sockets = new WeakMap(); + +export function attachSocket(socket: WebSocket): void { + const ctx: SocketCtx = { socket, game: null, color: null }; + sockets.set(socket, ctx); + + socket.on('message', (data) => onMessage(ctx, data)); + socket.on('close', () => onClose(ctx)); + socket.on('error', () => {/* logged via fastify */}); +} + +function send(socket: WebSocket, msg: ServerMessage): void { + if (socket.readyState === socket.OPEN) { + socket.send(JSON.stringify(msg)); + } +} + +function sendError(socket: WebSocket, code: ErrorCode, message?: string): void { + send(socket, { type: 'error', code, message: message ?? code }); +} + +function onMessage(ctx: SocketCtx, data: unknown): void { + let parsed: ClientMessage; + try { + const raw = typeof data === 'string' ? data : data instanceof Buffer ? data.toString('utf8') : String(data); + parsed = JSON.parse(raw); + } catch { + return sendError(ctx.socket, 'malformed', 'invalid JSON'); + } + + const result = clientMessageSchema.safeParse(parsed); + if (!result.success) { + return sendError(ctx.socket, 'malformed', result.error.message); + } + const msg = result.data as ClientMessage; + + if (msg.type === 'hello') return onHello(ctx, msg); + if (msg.type === 'pong') return; + + if (!ctx.game || !ctx.color) { + return sendError(ctx.socket, 'malformed', 'send hello first'); + } + + switch (msg.type) { + case 'commit': return onCommit(ctx, msg); + case 'resign': return onResign(ctx); + case 'offer-draw': return onOfferDraw(ctx); + case 'respond-draw': return onRespondDraw(ctx, msg.accept); + } +} + +function onHello(ctx: SocketCtx, msg: Extract): void { + const game = getGame(msg.gameId); + if (!game) return sendError(ctx.socket, 'game_not_found'); + + let color: Color | null = null; + + if (msg.token) { + color = findTokenInGame(game, msg.token); + if (!color) return sendError(ctx.socket, 'invalid_token'); + } else { + const claim = claimSlot(game, msg.joinAs ?? 'auto'); + if (!claim) { + return sendError(ctx.socket, 'spectators_disabled', 'both player slots are filled'); + } + color = claim.color; + } + + // Same-token, second socket: close old socket with reason "superseded". + const slot = game.players[color]!; + if (slot.socket && slot.socket !== ctx.socket && slot.socket.readyState === slot.socket.OPEN) { + try { slot.socket.close(4000, 'superseded'); } catch {/* ignore */} + } + slot.socket = ctx.socket; + delete game.disconnectAt[color]; + + ctx.game = game; + ctx.color = color; + + // Activate game once both slots are filled and connected. + if (game.status === 'waiting' && game.players.w && game.players.b) { + game.status = 'active'; + } + + const view = buildView(game, color); + const audienceFiltered = game.announcements.filter( + (a) => a.audience === 'both' || a.audience === color, + ); + + send(ctx.socket, { + type: 'joined', + you: color, + token: slot.token, + view, + announcements: audienceFiltered, + gameStatus: game.status, + mode: game.mode, + highlightingEnabled: game.highlightingEnabled, + opponentConnected: !!game.players[color === 'w' ? 'b' : 'w']?.socket, + }); + + // Notify peer that we're connected. + notifyPeer(game, color, true); + // If activation just happened, push update to both. + if (game.status === 'active') { + broadcastUpdate(game); + } +} + +function onCommit(ctx: SocketCtx, msg: Extract): void { + const game = ctx.game!; + const color = ctx.color!; + + if (!consumeCommitToken(game, color)) { + return sendError(ctx.socket, 'rate_limited'); + } + + const result = handleCommit(game, color, msg); + + switch (result.kind) { + case 'error': + sendError(ctx.socket, result.code); + return; + case 'silent': + // Re-send updated view to actor only with touchedPiece set. + sendUpdateTo(game, color, [], { touchedPiece: msg.from }); + return; + case 'announce': + // Announcement to actor; opponent is unaffected unless audience=both. + broadcastNewAnnouncements(game, result.announcements); + return; + case 'applied': + // Move applied. Check end conditions. + finalizeIfEnded(game, result.announcements); + broadcastNewAnnouncements(game, result.announcements); + return; + } +} + +function onResign(ctx: SocketCtx): void { + const game = ctx.game!; + const color = ctx.color!; + if (game.status !== 'active') return; + + const ply = game.chess.history().length; + const a = announce(color === 'w' ? 'white_resigned' : 'black_resigned', 'both', ply); + game.announcements.push(a); + endGame(game, 'resign', color === 'w' ? 'b' : 'w'); + broadcastNewAnnouncements(game, [a]); +} + +function onOfferDraw(ctx: SocketCtx): void { + const game = ctx.game!; + const color = ctx.color!; + if (game.status !== 'active') return; + game.drawOffer = { from: color, at: Date.now() }; + // Push update to both so opponent sees the drawOffer field. + broadcastUpdate(game); +} + +function onRespondDraw(ctx: SocketCtx, accept: boolean): void { + const game = ctx.game!; + const color = ctx.color!; + if (!game.drawOffer || game.drawOffer.from === color) return; + if (accept) { + const ply = game.chess.history().length; + const a = announce('draw_agreed', 'both', ply); + game.announcements.push(a); + game.drawOffer = null; + endGame(game, 'draw_agreed', null); + broadcastNewAnnouncements(game, [a]); + } else { + game.drawOffer = null; + broadcastUpdate(game); + } +} + +function onClose(ctx: SocketCtx): void { + const { game, color } = ctx; + if (!game || !color) return; + const slot = game.players[color]; + if (!slot) return; + if (slot.socket === ctx.socket) { + slot.socket = null; + if (game.status === 'active') { + game.disconnectAt[color] = Date.now(); + // Schedule grace timer. + setTimeout(() => maybeAbandon(game, color), GRACE_MS + 100); + } + notifyPeer(game, color, false, Date.now() + GRACE_MS); + } +} + +function maybeAbandon(game: Game, color: Color): void { + if (game.status !== 'active') return; + const slot = game.players[color]; + if (!slot) return; + if (slot.socket?.readyState === slot.socket?.OPEN) return; // reconnected + // Still disconnected. Game is abandoned. + const ply = game.chess.history().length; + const a = announce('game_abandoned', 'both', ply); + game.announcements.push(a); + const winner = game.players[color === 'w' ? 'b' : 'w']?.socket ? (color === 'w' ? 'b' : 'w') : null; + endGame(game, 'abandoned', winner); + broadcastNewAnnouncements(game, [a]); +} + +function endGame(game: Game, reason: Game['endReason'], winner: Color | null): void { + game.status = 'finished'; + game.endReason = reason; + game.winner = winner; + game.finishedAt = Date.now(); +} + +function finalizeIfEnded(game: Game, announcements: ReadonlyArray<{ text: string }>): void { + // Detect terminal moderator announcements. + const lastTexts = new Set(announcements.map((a) => a.text)); + if (lastTexts.has('white_checkmate')) endGame(game, 'checkmate', 'w'); + else if (lastTexts.has('black_checkmate')) endGame(game, 'checkmate', 'b'); + else if (lastTexts.has('stalemate')) endGame(game, 'stalemate', null); + else if (lastTexts.has('draw_insufficient')) endGame(game, 'insufficient', null); + else if (lastTexts.has('draw_threefold')) endGame(game, 'threefold', null); + else if (lastTexts.has('draw_fifty')) endGame(game, 'fifty_move', null); +} + +function broadcastNewAnnouncements( + game: Game, + newAnnouncements: ReadonlyArray, +): void { + for (const c of ['w', 'b'] as const) { + const filtered = newAnnouncements.filter((a) => a.audience === 'both' || a.audience === c); + sendUpdateTo(game, c, filtered); + } +} + +function broadcastUpdate(game: Game): void { + for (const c of ['w', 'b'] as const) { + sendUpdateTo(game, c, []); + } +} + +function sendUpdateTo( + game: Game, + color: Color, + newAnnouncements: ReadonlyArray, + extra?: { touchedPiece?: string }, +): void { + const slot = game.players[color]; + if (!slot?.socket) return; + const view = buildView(game, color); + const drawOffer = game.drawOffer ? { from: game.drawOffer.from } : null; + send(slot.socket, { + type: 'update', + view, + newAnnouncements: [...newAnnouncements], + gameStatus: game.status, + touchedPiece: game.armed?.color === color ? game.armed.from : extra?.touchedPiece as never, + drawOffer, + endReason: game.endReason, + winner: game.winner ?? null, + }); +} + +function notifyPeer(game: Game, source: Color, connected: boolean, graceUntil?: number): void { + const peer = source === 'w' ? 'b' : 'w'; + const slot = game.players[peer]; + if (!slot?.socket) return; + send(slot.socket, { + type: 'peer-status', + color: source, + connected, + graceUntil, + }); +} diff --git a/packages/server/test/integration/scripted-game.test.ts b/packages/server/test/integration/scripted-game.test.ts new file mode 100644 index 0000000..9d122ee --- /dev/null +++ b/packages/server/test/integration/scripted-game.test.ts @@ -0,0 +1,172 @@ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import { WebSocket } from 'ws'; +import Fastify from 'fastify'; +import websocketPlugin from '@fastify/websocket'; +import { + activeGameCount, + chooseSide, + createGame, +} from '../../src/games.js'; +import { attachSocket } from '../../src/ws.js'; +import { createGameSchema } from '../../src/validation.js'; +import type { ServerMessage } from '@blind-chess/shared'; + +let app: ReturnType; +let baseUrl = ''; + +beforeAll(async () => { + app = Fastify({ logger: false }); + await app.register(websocketPlugin); + app.get('/api/health', async () => ({ ok: true, activeGames: activeGameCount() })); + app.post('/api/games', async (req, reply) => { + const parsed = createGameSchema.safeParse(req.body); + if (!parsed.success) { reply.code(400); return { error: 'malformed' }; } + const creatorSide = chooseSide(parsed.data.side); + const { game, creatorToken } = createGame({ + mode: parsed.data.mode, + creatorSide, + highlightingEnabled: parsed.data.highlightingEnabled, + }); + return { gameId: game.id, creatorToken, creatorColor: creatorSide }; + }); + app.get('/ws', { websocket: true }, (socket) => { + const raw = (socket as unknown as { socket?: unknown }).socket ?? socket; + attachSocket(raw as never); + }); + await app.listen({ port: 0, host: '127.0.0.1' }); + const addr = app.server.address(); + if (typeof addr !== 'object' || !addr) throw new Error('no address'); + baseUrl = `http://127.0.0.1:${addr.port}`; +}); + +afterAll(async () => { + await app.close(); +}); + +interface Client { + ws: WebSocket; + msgs: ServerMessage[]; + waitFor: (pred: (m: ServerMessage) => boolean, timeoutMs?: number) => Promise; + send: (m: unknown) => void; + close: () => void; +} + +function makeClient(gameId: string): Promise { + return new Promise((resolve, reject) => { + const ws = new WebSocket(baseUrl.replace('http', 'ws') + `/ws?game=${gameId}`); + const msgs: ServerMessage[] = []; + const waiters: Array<{ pred: (m: ServerMessage) => boolean; resolve: (m: ServerMessage) => void; reject: (e: Error) => void; timer: NodeJS.Timeout }> = []; + ws.on('message', (data) => { + const m = JSON.parse(data.toString()) as ServerMessage; + msgs.push(m); + for (const w of [...waiters]) { + if (w.pred(m)) { + clearTimeout(w.timer); + waiters.splice(waiters.indexOf(w), 1); + w.resolve(m); + } + } + }); + ws.on('open', () => resolve({ + ws, msgs, + waitFor: (pred, timeoutMs = 1500) => new Promise((res, rej) => { + const existing = msgs.find(pred); + if (existing) return res(existing); + const timer = setTimeout(() => rej(new Error('waitFor timeout')), timeoutMs); + waiters.push({ pred, resolve: res, reject: rej, timer }); + }), + send: (m) => ws.send(JSON.stringify(m)), + close: () => ws.close(), + })); + ws.on('error', reject); + }); +} + +async function createTestGame(mode: 'blind' | 'vanilla' = 'blind'): Promise<{ gameId: string; creatorToken: string; creatorColor: 'w' | 'b' }> { + const res = await fetch(`${baseUrl}/api/games`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ mode, side: 'w', highlightingEnabled: false }), + }); + return await res.json() as { gameId: string; creatorToken: string; creatorColor: 'w' | 'b' }; +} + +describe('scripted game end-to-end', () => { + it('two clients connect, opening exchange, blind view filtering', async () => { + const { gameId, creatorToken } = await createTestGame('blind'); + const w = await makeClient(gameId); + const b = await makeClient(gameId); + + // White connects with token, black auto-claims. + w.send({ type: 'hello', gameId, token: creatorToken }); + b.send({ type: 'hello', gameId, joinAs: 'auto' }); + + const wJoined = await w.waitFor((m) => m.type === 'joined'); + const bJoined = await b.waitFor((m) => m.type === 'joined'); + expect(wJoined.type === 'joined' && wJoined.you).toBe('w'); + expect(bJoined.type === 'joined' && bJoined.you).toBe('b'); + + // Blind view: white sees only its 16 pieces. + if (wJoined.type !== 'joined') throw new Error('expected joined'); + expect(Object.keys(wJoined.view.pieces).length).toBe(16); + for (const piece of Object.values(wJoined.view.pieces)) { + expect(piece?.color).toBe('w'); + } + + // White plays e2e4 in two messages: arm + commit. + w.send({ type: 'commit', from: 'e2' }); + await w.waitFor((m) => m.type === 'update' && m.touchedPiece === 'e2'); + w.send({ type: 'commit', from: 'e2', to: 'e4' }); + + // Black should see a moderator announcement white_moved. + const bMoved = await b.waitFor((m) => + m.type === 'update' && m.newAnnouncements.some((a) => a.text === 'white_moved'), + ); + expect(bMoved.type).toBe('update'); + + w.close(); + b.close(); + }); + + it('not_your_turn error when black tries to move first', async () => { + const { gameId, creatorToken } = await createTestGame('vanilla'); + const w = await makeClient(gameId); + const b = await makeClient(gameId); + w.send({ type: 'hello', gameId, token: creatorToken }); + b.send({ type: 'hello', gameId, joinAs: 'auto' }); + await b.waitFor((m) => m.type === 'joined'); + b.send({ type: 'commit', from: 'e7', to: 'e5' }); + const err = await b.waitFor((m) => m.type === 'error'); + expect(err.type === 'error' && err.code).toBe('not_your_turn'); + w.close(); + b.close(); + }); + + it('rejects malformed messages', async () => { + const { gameId, creatorToken } = await createTestGame('blind'); + const w = await makeClient(gameId); + w.send({ type: 'hello', gameId, token: creatorToken }); + await w.waitFor((m) => m.type === 'joined'); + w.send({ type: 'commit', from: 'zz', to: 'e4' }); + const err = await w.waitFor((m) => m.type === 'error'); + expect(err.type === 'error' && err.code).toBe('malformed'); + w.close(); + }); + + it('resign: opponent gets game_finished update', async () => { + const { gameId, creatorToken } = await createTestGame('vanilla'); + const w = await makeClient(gameId); + const b = await makeClient(gameId); + w.send({ type: 'hello', gameId, token: creatorToken }); + b.send({ type: 'hello', gameId, joinAs: 'auto' }); + await b.waitFor((m) => m.type === 'joined'); + w.send({ type: 'resign' }); + const upd = await b.waitFor((m) => + m.type === 'update' && m.gameStatus === 'finished', + ); + expect(upd.type === 'update' && upd.endReason).toBe('resign'); + expect(upd.type === 'update' && upd.winner).toBe('b'); + w.close(); + b.close(); + }); +}); diff --git a/packages/server/test/unit/commit-fsm.test.ts b/packages/server/test/unit/commit-fsm.test.ts new file mode 100644 index 0000000..f62ebfe --- /dev/null +++ b/packages/server/test/unit/commit-fsm.test.ts @@ -0,0 +1,122 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { Chess } from 'chess.js'; +import { handleCommit } from '../../src/commit.js'; +import type { Game } from '../../src/state.js'; +import { RATE_LIMIT } from '../../src/state.js'; + +function makeGame(fen?: string): Game { + const chess = fen ? new Chess(fen) : new Chess(); + return { + id: 'testtest', + mode: 'blind', + highlightingEnabled: false, + status: 'active', + createdAt: Date.now(), + chess, + moveHistory: [], + announcements: [], + players: { + w: { token: 'w'.repeat(24), socket: null, joinedAt: 0, + rateBucket: { tokens: RATE_LIMIT.capacity, last: 0 } }, + b: { token: 'b'.repeat(24), socket: null, joinedAt: 0, + rateBucket: { tokens: RATE_LIMIT.capacity, last: 0 } }, + }, + armed: null, + drawOffer: null, + disconnectAt: {}, + }; +} + +describe('hierarchy decision table', () => { + let game: Game; + beforeEach(() => { game = makeGame(); }); + + it('row 1: no_such_piece — empty square', () => { + const r = handleCommit(game, 'w', { from: 'e4' }); + expect(r.kind).toBe('announce'); + if (r.kind === 'announce') expect(r.announcements[0]!.text).toBe('no_such_piece'); + }); + + it('row 1b: no_such_piece — opponent piece', () => { + const r = handleCommit(game, 'w', { from: 'e7' }); // black pawn + expect(r.kind).toBe('announce'); + if (r.kind === 'announce') expect(r.announcements[0]!.text).toBe('no_such_piece'); + }); + + it('row 2: no_legal_moves — knight in starting position is OK; use a contrived fen', () => { + // White knight surrounded by own pieces. Place a knight at b1 with own + // pieces blocking a3, c3, d2. + const g = makeGame('4k3/8/8/8/8/P1P5/3P4/1N2K3 w - - 0 1'); + // Knight at b1: jumps a3, c3, d2. All blocked by own pawns. + const r = handleCommit(g, 'w', { from: 'b1' }); + expect(r.kind).toBe('announce'); + if (r.kind === 'announce') expect(r.announcements[0]!.text).toBe('no_legal_moves'); + }); + + it('row 3: wont_help — pinned bishop, not in check', () => { + // White king on e1, white bishop on e2 pinned by black rook on e8. + const g = makeGame('4r2k/8/8/8/8/8/4B3/4K3 w - - 0 1'); + const r = handleCommit(g, 'w', { from: 'e2' }); + expect(r.kind).toBe('announce'); + if (r.kind === 'announce') expect(r.announcements[0]!.text).toBe('wont_help'); + }); + + it('row 5: silent on first commit when piece has legal moves', () => { + const r = handleCommit(game, 'w', { from: 'e2' }); + expect(r.kind).toBe('silent'); + expect(game.armed).toEqual({ color: 'w', from: 'e2' }); + }); + + it('row 6: applied move when legal commit completes', () => { + const r = handleCommit(game, 'w', { from: 'e2', to: 'e4' }); + expect(r.kind).toBe('applied'); + expect(game.armed).toBeNull(); + expect(game.chess.history()).toContain('e4'); + }); +}); + +describe('touch-move enforcement', () => { + it('after silent arm, commit with different from yields must_move_touched_piece', () => { + const game = makeGame(); + handleCommit(game, 'w', { from: 'e2' }); // arm + const r = handleCommit(game, 'w', { from: 'd2', to: 'd4' }); + expect(r.kind).toBe('error'); + if (r.kind === 'error') expect(r.code).toBe('must_move_touched_piece'); + }); + + it('after silent arm, illegal destination returns illegal_move and KEEPS touch', () => { + const game = makeGame(); + handleCommit(game, 'w', { from: 'e2' }); + const r = handleCommit(game, 'w', { from: 'e2', to: 'e5' }); // pawn can't go e2→e5 + expect(r.kind).toBe('announce'); + if (r.kind === 'announce') expect(r.announcements[0]!.text).toBe('illegal_move'); + expect(game.armed).toEqual({ color: 'w', from: 'e2' }); + }); + + it('not your turn returns error', () => { + const game = makeGame(); + const r = handleCommit(game, 'b', { from: 'e7' }); + expect(r.kind).toBe('error'); + if (r.kind === 'error') expect(r.code).toBe('not_your_turn'); + }); +}); + +describe('promotion', () => { + it('promotion required: pawn on 7th to 8th without promotion field', () => { + const g = makeGame('7k/4P3/8/8/8/8/8/4K3 w - - 0 1'); + const r = handleCommit(g, 'w', { from: 'e7', to: 'e8' }); + expect(r.kind).toBe('error'); + if (r.kind === 'error') expect(r.code).toBe('promotion_required'); + }); + + it('promotion succeeds with field', () => { + const g = makeGame('7k/4P3/8/8/8/8/8/4K3 w - - 0 1'); + const r = handleCommit(g, 'w', { from: 'e7', to: 'e8', promotion: 'q' }); + expect(r.kind).toBe('applied'); + if (r.kind === 'applied') { + const promo = r.announcements.find((a) => a.text === 'white_promoted'); + expect(promo).toBeDefined(); + expect(promo?.payload?.promotedTo).toBe('q'); + } + }); +}); diff --git a/packages/server/test/unit/view.test.ts b/packages/server/test/unit/view.test.ts new file mode 100644 index 0000000..2046542 --- /dev/null +++ b/packages/server/test/unit/view.test.ts @@ -0,0 +1,81 @@ +import { describe, it, expect } from 'vitest'; +import { Chess } from 'chess.js'; +import { buildView, ownSquares } from '../../src/view.js'; +import type { Game } from '../../src/state.js'; +import { RATE_LIMIT } from '../../src/state.js'; + +function makeGame(mode: 'blind' | 'vanilla', fen?: string, status: 'active' | 'finished' = 'active'): Game { + return { + id: 'testtest', + mode, + highlightingEnabled: false, + status, + createdAt: Date.now(), + chess: fen ? new Chess(fen) : new Chess(), + moveHistory: [], + announcements: [], + players: { + w: { token: 'w'.repeat(24), socket: null, joinedAt: 0, rateBucket: { tokens: RATE_LIMIT.capacity, last: 0 } }, + b: { token: 'b'.repeat(24), socket: null, joinedAt: 0, rateBucket: { tokens: RATE_LIMIT.capacity, last: 0 } }, + }, + armed: null, + drawOffer: null, + disconnectAt: {}, + }; +} + +describe('buildView: security boundary', () => { + it('blind/active white view contains zero black pieces', () => { + const g = makeGame('blind'); + const view = buildView(g, 'w'); + for (const piece of Object.values(view.pieces)) { + expect(piece?.color).toBe('w'); + } + expect(Object.keys(view.pieces).length).toBe(16); // all 16 white pieces + }); + + it('blind/active black view contains zero white pieces', () => { + const g = makeGame('blind'); + const view = buildView(g, 'b'); + for (const piece of Object.values(view.pieces)) { + expect(piece?.color).toBe('b'); + } + expect(Object.keys(view.pieces).length).toBe(16); + }); + + it('vanilla/active shows both colors', () => { + const g = makeGame('vanilla'); + const view = buildView(g, 'w'); + expect(Object.keys(view.pieces).length).toBe(32); + }); + + it('blind/finished reveals both colors (post-game review)', () => { + const g = makeGame('blind', undefined, 'finished'); + const view = buildView(g, 'w'); + expect(Object.keys(view.pieces).length).toBe(32); + }); + + it('blind: inCheck is null for non-actor (info leak prevention)', () => { + // Black to move and is in check. White's view says null (it's not white's turn, + // and revealing inCheck-status of opponent leaks info). + const g = makeGame('blind', 'rnb1kbnr/pppp1ppp/8/4p3/6Pq/5P2/PPPPP2P/RNBQKBNR w KQkq - 1 3'); + const view = buildView(g, 'b'); + // It's white's turn here. Black viewer is not the to-move side. + expect(view.inCheck).toBeNull(); + }); +}); + +describe('ownSquares', () => { + it('starting position returns 16 own squares', () => { + const g = makeGame('blind'); + expect(ownSquares(g, 'w').size).toBe(16); + expect(ownSquares(g, 'b').size).toBe(16); + }); + + it('contains only own-color squares', () => { + const g = makeGame('blind'); + const wSet = ownSquares(g, 'w'); + expect(wSet.has('e2')).toBe(true); + expect(wSet.has('e7')).toBe(false); + }); +}); diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json new file mode 100644 index 0000000..80b6dcc --- /dev/null +++ b/packages/server/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "types": ["node"] + }, + "include": ["src/**/*"], + "references": [{ "path": "../shared" }] +} diff --git a/packages/server/tsconfig.tsbuildinfo b/packages/server/tsconfig.tsbuildinfo new file mode 100644 index 0000000..2c4ebff --- /dev/null +++ b/packages/server/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./src/commit.ts","./src/games.ts","./src/ratelimit.ts","./src/server.ts","./src/state.ts","./src/translator.ts","./src/validation.ts","./src/view.ts","./src/ws.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..fca94ca --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,23 @@ +{ + "name": "@blind-chess/shared", + "version": "0.1.0", + "private": true, + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "scripts": { + "build": "tsc -b", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "typescript": "^5.6.0", + "vitest": "^3.0.0" + } +} diff --git a/packages/shared/src/geometric.ts b/packages/shared/src/geometric.ts new file mode 100644 index 0000000..ef1b067 --- /dev/null +++ b/packages/shared/src/geometric.ts @@ -0,0 +1,102 @@ +import type { Piece, Square } from './types.js'; +import { fileIndex, rankIndex, squareAt } from './types.js'; + +type Dir = readonly [number, number]; + +const ROOK_DIRS: readonly Dir[] = [ + [1, 0], [-1, 0], [0, 1], [0, -1], +]; + +const BISHOP_DIRS: readonly Dir[] = [ + [1, 1], [1, -1], [-1, 1], [-1, -1], +]; + +const QUEEN_DIRS: readonly Dir[] = [...ROOK_DIRS, ...BISHOP_DIRS]; + +const KNIGHT_OFFSETS: readonly Dir[] = [ + [1, 2], [2, 1], [2, -1], [1, -2], + [-1, -2], [-2, -1], [-2, 1], [-1, 2], +]; + +const KING_OFFSETS: readonly Dir[] = [ + [1, 0], [-1, 0], [0, 1], [0, -1], + [1, 1], [1, -1], [-1, 1], [-1, -1], +]; + +function rays(from: Square, dirs: readonly Dir[], own: Set): Square[] { + const out: Square[] = []; + const f0 = fileIndex(from); + const r0 = rankIndex(from); + for (const [df, dr] of dirs) { + let f = f0 + df; + let r = r0 + dr; + while (true) { + const sq = squareAt(f, r); + if (!sq) break; + if (own.has(sq)) break; + out.push(sq); + f += df; + r += dr; + } + } + return out; +} + +function jumps(from: Square, offsets: readonly Dir[], own: Set): Square[] { + const out: Square[] = []; + const f0 = fileIndex(from); + const r0 = rankIndex(from); + for (const [df, dr] of offsets) { + const sq = squareAt(f0 + df, r0 + dr); + if (sq && !own.has(sq)) out.push(sq); + } + return out; +} + +function pawnGeometry(from: Square, color: 'w' | 'b', own: Set): Square[] { + const out: Square[] = []; + const f0 = fileIndex(from); + const r0 = rankIndex(from); + const dir = color === 'w' ? 1 : -1; + const startRank = color === 'w' ? 1 : 6; + + const f1 = squareAt(f0, r0 + dir); + if (f1 && !own.has(f1)) out.push(f1); + + if (r0 === startRank) { + const f2 = squareAt(f0, r0 + 2 * dir); + if (f1 && f2 && !own.has(f1) && !own.has(f2)) out.push(f2); + } + + for (const df of [-1, 1]) { + const cap = squareAt(f0 + df, r0 + dir); + if (cap && !own.has(cap)) out.push(cap); + } + + return out; +} + +/** + * Geometric (pseudo-legal-ish) moves for a piece. + * + * Reads ONLY: piece type/color, from-square, own-piece set. + * Reads NOT: opponent piece positions, board history, anything else. + * + * The signature is the proof of zero opponent info leak. Castling is + * intentionally excluded — castling legality depends on opponent state + * (path through check, opponent pieces between king and rook). + */ +export function geometricMoves( + piece: Piece, + from: Square, + ownSquares: Set, +): Square[] { + switch (piece.type) { + case 'n': return jumps(from, KNIGHT_OFFSETS, ownSquares); + case 'k': return jumps(from, KING_OFFSETS, ownSquares); + case 'b': return rays(from, BISHOP_DIRS, ownSquares); + case 'r': return rays(from, ROOK_DIRS, ownSquares); + case 'q': return rays(from, QUEEN_DIRS, ownSquares); + case 'p': return pawnGeometry(from, piece.color, ownSquares); + } +} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts new file mode 100644 index 0000000..55b6bed --- /dev/null +++ b/packages/shared/src/index.ts @@ -0,0 +1,4 @@ +export * from './types.js'; +export * from './moderator.js'; +export * from './protocol.js'; +export * from './geometric.js'; diff --git a/packages/shared/src/moderator.ts b/packages/shared/src/moderator.ts new file mode 100644 index 0000000..b1ecf6c --- /dev/null +++ b/packages/shared/src/moderator.ts @@ -0,0 +1,28 @@ +import type { Color, PieceType } from './types.js'; + +export type ModeratorText = + | 'no_such_piece' + | 'no_legal_moves' + | 'wont_help' + | 'illegal_move' + | 'white_moved' | 'black_moved' + | 'white_moved_captured' | 'black_moved_captured' + | 'white_moved_captured_ep' | 'black_moved_captured_ep' + | 'white_castled_kingside' | 'white_castled_queenside' + | 'black_castled_kingside' | 'black_castled_queenside' + | 'white_in_check' | 'black_in_check' + | 'white_promoted' | 'black_promoted' + | 'white_checkmate' | 'black_checkmate' + | 'stalemate' | 'draw_insufficient' | 'draw_fifty' | 'draw_threefold' + | 'white_resigned' | 'black_resigned' + | 'draw_agreed' | 'game_abandoned'; + +export type Audience = Color | 'both'; + +export interface Announcement { + ply: number; + text: ModeratorText; + audience: Audience; + payload?: { promotedTo?: PieceType }; + at: number; +} diff --git a/packages/shared/src/protocol.ts b/packages/shared/src/protocol.ts new file mode 100644 index 0000000..8e0ea0f --- /dev/null +++ b/packages/shared/src/protocol.ts @@ -0,0 +1,62 @@ +import type { + BoardView, Color, GameId, GameStatus, Mode, PlayerToken, + PromotionType, Square, EndReason, +} from './types.js'; +import type { Announcement } from './moderator.js'; + +export type ClientMessage = + | { type: 'hello'; gameId: GameId; token?: PlayerToken; joinAs?: Color | 'auto' } + | { type: 'commit'; from: Square; to?: Square; promotion?: PromotionType } + | { type: 'resign' } + | { type: 'offer-draw' } + | { type: 'respond-draw'; accept: boolean } + | { type: 'pong' }; + +export type ErrorCode = + | 'game_not_found' + | 'slot_taken' + | 'spectators_disabled' + | 'not_your_turn' + | 'malformed' + | 'promotion_required' + | 'must_move_touched_piece' + | 'rate_limited' + | 'invalid_token'; + +export type ServerMessage = + | { + type: 'joined'; + you: Color | 'spectator-rejected'; + token: PlayerToken; + view: BoardView; + announcements: Announcement[]; + gameStatus: GameStatus; + mode: Mode; + highlightingEnabled: boolean; + opponentConnected: boolean; + } + | { + type: 'update'; + view: BoardView; + newAnnouncements: Announcement[]; + gameStatus: GameStatus; + touchedPiece?: Square; + drawOffer?: { from: Color } | null; + endReason?: EndReason; + winner?: Color | null; + } + | { type: 'peer-status'; color: Color; connected: boolean; graceUntil?: number } + | { type: 'error'; code: ErrorCode; message: string } + | { type: 'ping' }; + +export interface CreateGameRequest { + mode: Mode; + side: Color | 'random'; + highlightingEnabled: boolean; +} + +export interface CreateGameResponse { + gameId: GameId; + creatorToken: PlayerToken; + joinUrl: string; +} diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts new file mode 100644 index 0000000..ea1ad60 --- /dev/null +++ b/packages/shared/src/types.ts @@ -0,0 +1,63 @@ +export type Color = 'w' | 'b'; +export type Mode = 'blind' | 'vanilla'; + +export type File = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h'; +export type Rank = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'; +export type Square = `${File}${Rank}`; + +export type PieceType = 'p' | 'n' | 'b' | 'r' | 'q' | 'k'; +export type PromotionType = 'q' | 'r' | 'b' | 'n'; + +export interface Piece { + color: Color; + type: PieceType; +} + +export type GameStatus = 'waiting' | 'active' | 'finished'; + +export type EndReason = + | 'checkmate' + | 'stalemate' + | 'resign' + | 'draw_agreed' + | 'insufficient' + | 'fifty_move' + | 'threefold' + | 'abandoned'; + +export type GameId = string; +export type PlayerToken = string; + +export interface BoardView { + pieces: Partial>; + toMove: Color; + inCheck: boolean | null; +} + +export const FILES: readonly File[] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] as const; +export const RANKS: readonly Rank[] = ['1', '2', '3', '4', '5', '6', '7', '8'] as const; + +export function isSquare(s: string): s is Square { + return /^[a-h][1-8]$/.test(s); +} + +export const ALL_SQUARES: readonly Square[] = (() => { + const out: Square[] = []; + for (const f of FILES) for (const r of RANKS) out.push(`${f}${r}` as Square); + return out; +})(); + +export function fileIndex(s: Square): number { + return s.charCodeAt(0) - 'a'.charCodeAt(0); +} + +export function rankIndex(s: Square): number { + return s.charCodeAt(1) - '1'.charCodeAt(0); +} + +export function squareAt(fileIdx: number, rankIdx: number): Square | null { + if (fileIdx < 0 || fileIdx > 7 || rankIdx < 0 || rankIdx > 7) return null; + const f = String.fromCharCode('a'.charCodeAt(0) + fileIdx); + const r = String.fromCharCode('1'.charCodeAt(0) + rankIdx); + return `${f}${r}` as Square; +} diff --git a/packages/shared/test/geometric.test.ts b/packages/shared/test/geometric.test.ts new file mode 100644 index 0000000..10ba437 --- /dev/null +++ b/packages/shared/test/geometric.test.ts @@ -0,0 +1,149 @@ +import { describe, it, expect } from 'vitest'; +import { geometricMoves } from '../src/geometric.js'; +import type { Piece, Square } from '../src/types.js'; + +const set = (...sq: Square[]) => new Set(sq); + +describe('geometricMoves: knight', () => { + it('jumps to all 8 squares from d4 with no own pieces', () => { + const moves = geometricMoves({ color: 'w', type: 'n' }, 'd4', set()); + expect(moves.sort()).toEqual(['b3', 'b5', 'c2', 'c6', 'e2', 'e6', 'f3', 'f5']); + }); + + it('cannot land on own pieces', () => { + const moves = geometricMoves({ color: 'w', type: 'n' }, 'd4', set('e6', 'b3')); + expect(moves).not.toContain('e6'); + expect(moves).not.toContain('b3'); + expect(moves.length).toBe(6); + }); + + it('corner: a1 has only 2 jumps', () => { + const moves = geometricMoves({ color: 'w', type: 'n' }, 'a1', set()); + expect(moves.sort()).toEqual(['b3', 'c2']); + }); + + it('hierarchy row 2 — knight surrounded by own pawns yields ∅', () => { + // White knight on b1 with own pawns blocking d2, c3, a3 reachable squares + const moves = geometricMoves({ color: 'w', type: 'n' }, 'b1', set('d2', 'c3', 'a3')); + expect(moves).toEqual([]); + }); +}); + +describe('geometricMoves: rays (bishop/rook/queen)', () => { + it('bishop on d4 reaches both diagonals fully when board empty', () => { + const moves = geometricMoves({ color: 'w', type: 'b' }, 'd4', set()); + expect(moves.sort()).toEqual(['a1', 'a7', 'b2', 'b6', 'c3', 'c5', 'e3', 'e5', 'f2', 'f6', 'g1', 'g7', 'h8']); + }); + + it('bishop ray STOPS at own piece (square excluded)', () => { + const moves = geometricMoves({ color: 'w', type: 'b' }, 'd4', set('f6')); + expect(moves).not.toContain('f6'); + expect(moves).not.toContain('g7'); + expect(moves).not.toContain('h8'); + expect(moves).toContain('e5'); + }); + + it('bishop ray EXTENDS THROUGH unknown squares (may host opponent pieces)', () => { + // No own piece on f6. From the function's POV, f6 is "unknown" — ray continues. + const moves = geometricMoves({ color: 'w', type: 'b' }, 'd4', set()); + expect(moves).toContain('f6'); + expect(moves).toContain('g7'); + expect(moves).toContain('h8'); + }); + + it('rook on a1 with own pawn at a2 has zero rank moves up', () => { + const moves = geometricMoves({ color: 'w', type: 'r' }, 'a1', set('a2')); + expect(moves).not.toContain('a2'); + expect(moves).toContain('b1'); + expect(moves).toContain('h1'); + }); + + it('queen combines rook+bishop reach', () => { + const queenMoves = geometricMoves({ color: 'w', type: 'q' }, 'd4', set()); + const bishopMoves = geometricMoves({ color: 'w', type: 'b' }, 'd4', set()); + const rookMoves = geometricMoves({ color: 'w', type: 'r' }, 'd4', set()); + expect(queenMoves.sort()).toEqual([...bishopMoves, ...rookMoves].sort()); + }); +}); + +describe('geometricMoves: king', () => { + it('center king: 8 neighbors', () => { + const moves = geometricMoves({ color: 'w', type: 'k' }, 'e4', set()); + expect(moves.sort()).toEqual(['d3', 'd4', 'd5', 'e3', 'e5', 'f3', 'f4', 'f5']); + }); + + it('corner king: 3 neighbors', () => { + const moves = geometricMoves({ color: 'w', type: 'k' }, 'a1', set()); + expect(moves.sort()).toEqual(['a2', 'b1', 'b2']); + }); + + it('does NOT include castling targets', () => { + // White king at e1 with own rooks present should NOT see g1 or c1. + const moves = geometricMoves({ color: 'w', type: 'k' }, 'e1', set('a1', 'h1')); + expect(moves).not.toContain('g1'); + expect(moves).not.toContain('c1'); + }); +}); + +describe('geometricMoves: pawn', () => { + it('white pawn on starting rank: forward 1 + 2 + diagonals', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'e2', set()); + expect(moves.sort()).toEqual(['d3', 'e3', 'e4', 'f3']); + }); + + it('white pawn forward-2 blocked by own piece on e3', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'e2', set('e3')); + expect(moves).not.toContain('e3'); + expect(moves).not.toContain('e4'); + }); + + it('white pawn forward-2 blocked by own piece on e4 (intermediate clear)', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'e2', set('e4')); + expect(moves).toContain('e3'); + expect(moves).not.toContain('e4'); + }); + + it('white pawn off starting rank: only forward 1 + diagonals', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'e4', set()); + expect(moves.sort()).toEqual(['d5', 'e5', 'f5']); + }); + + it('white pawn diagonals included even when empty (illegal-move probe ok)', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'e4', set()); + expect(moves).toContain('d5'); + expect(moves).toContain('f5'); + }); + + it('white pawn diagonal blocked by own piece', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'e4', set('f5')); + expect(moves).not.toContain('f5'); + }); + + it('black pawn from starting rank moves DOWN', () => { + const moves = geometricMoves({ color: 'b', type: 'p' }, 'e7', set()); + expect(moves.sort()).toEqual(['d6', 'e5', 'e6', 'f6']); + }); + + it('a-file pawn: only one diagonal (b)', () => { + const moves = geometricMoves({ color: 'w', type: 'p' }, 'a2', set()); + expect(moves.sort()).toEqual(['a3', 'a4', 'b3']); + }); +}); + +describe('zero-opponent-leak invariant', () => { + it('output is identical regardless of opponent position when ownSquares is the same', () => { + // The function's signature literally cannot accept opponent positions. + // This test asserts that two callers with different mental models of + // opponent state but identical ownSquares get identical results. + const own = set('e2'); + const a = geometricMoves({ color: 'w', type: 'r' }, 'd4', own); + const b = geometricMoves({ color: 'w', type: 'r' }, 'd4', own); + expect(a).toEqual(b); + // Sanity that ownSquares actually affects output: d6 is on the d-file + // ray, so blocking it shortens the rook's reach. + const blocked = geometricMoves({ color: 'w', type: 'r' }, 'd4', set('d6')); + expect(blocked).not.toContain('d6'); + expect(blocked).not.toContain('d7'); + expect(a).toContain('d6'); + }); +}); diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..52abfe0 --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "composite": true + }, + "include": ["src/**/*"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..2c2d62b --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2492 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + typescript: + specifier: ^5.6.0 + version: 5.9.3 + vitest: + specifier: ^3.0.0 + version: 3.2.4(@types/node@22.19.17)(tsx@4.21.0) + + packages/client: + dependencies: + '@blind-chess/shared': + specifier: workspace:* + version: link:../shared + devDependencies: + '@sveltejs/vite-plugin-svelte': + specifier: ^5.0.0 + version: 5.1.1(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) + svelte: + specifier: ^5.0.0 + version: 5.55.5 + svelte-check: + specifier: ^4.1.0 + version: 4.4.6(picomatch@4.0.4)(svelte@5.55.5)(typescript@5.9.3) + typescript: + specifier: ^5.6.0 + version: 5.9.3 + vite: + specifier: ^6.0.0 + version: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + + packages/server: + dependencies: + '@blind-chess/shared': + specifier: workspace:* + version: link:../shared + '@fastify/static': + specifier: ^8.0.0 + version: 8.3.0 + '@fastify/websocket': + specifier: ^11.0.0 + version: 11.2.0 + chess.js: + specifier: ^1.4.0 + version: 1.4.0 + fastify: + specifier: ^5.2.0 + version: 5.8.5 + pino: + specifier: ^9.5.0 + version: 9.14.0 + ws: + specifier: ^8.18.0 + version: 8.20.0 + zod: + specifier: ^3.24.0 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^22.10.0 + version: 22.19.17 + '@types/ws': + specifier: ^8.5.13 + version: 8.18.1 + pino-pretty: + specifier: ^11.3.0 + version: 11.3.0 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.6.0 + version: 5.9.3 + vitest: + specifier: ^3.0.0 + version: 3.2.4(@types/node@22.19.17)(tsx@4.21.0) + + packages/shared: + devDependencies: + typescript: + specifier: ^5.6.0 + version: 5.9.3 + vitest: + specifier: ^3.0.0 + version: 3.2.4(@types/node@22.19.17)(tsx@4.21.0) + +packages: + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@fastify/accept-negotiator@2.0.1': + resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==} + + '@fastify/ajv-compiler@4.0.5': + resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} + + '@fastify/error@4.2.0': + resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} + + '@fastify/fast-json-stringify-compiler@5.0.3': + resolution: {integrity: sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==} + + '@fastify/forwarded@3.0.1': + resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==} + + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} + + '@fastify/proxy-addr@5.1.0': + resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==} + + '@fastify/send@4.1.0': + resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==} + + '@fastify/static@8.3.0': + resolution: {integrity: sha512-yKxviR5PH1OKNnisIzZKmgZSus0r2OZb8qCSbqmw34aolT4g3UlzYfeBRym+HJ1J471CR8e2ldNub4PubD1coA==} + + '@fastify/websocket@11.2.0': + resolution: {integrity: sha512-3HrDPbAG1CzUCqnslgJxppvzaAZffieOVbLp1DAy1huCSynUWPifSvfdEDUR8HlJLp3sp1A36uOM2tJogADS8w==} + + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@rollup/rollup-android-arm-eabi@4.60.2': + resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.60.2': + resolution: {integrity: sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.60.2': + resolution: {integrity: sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.60.2': + resolution: {integrity: sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.2': + resolution: {integrity: sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.2': + resolution: {integrity: sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + resolution: {integrity: sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.60.2': + resolution: {integrity: sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.60.2': + resolution: {integrity: sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.60.2': + resolution: {integrity: sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.60.2': + resolution: {integrity: sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.60.2': + resolution: {integrity: sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.60.2': + resolution: {integrity: sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.60.2': + resolution: {integrity: sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.60.2': + resolution: {integrity: sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.60.2': + resolution: {integrity: sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.60.2': + resolution: {integrity: sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.60.2': + resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.60.2': + resolution: {integrity: sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.60.2': + resolution: {integrity: sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.2': + resolution: {integrity: sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.2': + resolution: {integrity: sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.2': + resolution: {integrity: sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.2': + resolution: {integrity: sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.2': + resolution: {integrity: sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==} + cpu: [x64] + os: [win32] + + '@sveltejs/acorn-typescript@1.0.9': + resolution: {integrity: sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==} + peerDependencies: + acorn: ^8.9.0 + + '@sveltejs/vite-plugin-svelte-inspector@4.0.1': + resolution: {integrity: sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^5.0.0 + svelte: ^5.0.0 + vite: ^6.0.0 + + '@sveltejs/vite-plugin-svelte@5.1.1': + resolution: {integrity: sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} + peerDependencies: + svelte: ^5.0.0 + vite: ^6.0.0 + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@22.19.17': + resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + aria-query@5.3.1: + resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} + engines: {node: '>= 0.4'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + avvio@9.2.0: + resolution: {integrity: sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ==} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + + chess.js@1.4.0: + resolution: {integrity: sha512-BBJgrrtKQOzFLonR0l+k64A98NLemPwNsCskwb+29bRwobUa4iTm51E1kwGPbWXAcfdDa18nad6vpPPKPWarqw==} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + devalue@5.7.1: + resolution: {integrity: sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==} + + duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + esrap@2.2.5: + resolution: {integrity: sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig==} + peerDependencies: + '@typescript-eslint/types': ^8.2.0 + peerDependenciesMeta: + '@typescript-eslint/types': + optional: true + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stringify@6.3.0: + resolution: {integrity: sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA==} + + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fastify-plugin@5.1.0: + resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} + + fastify@5.8.5: + resolution: {integrity: sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + find-my-way@9.5.0: + resolution: {integrity: sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ==} + engines: {node: '>=20'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-tsconfig@4.14.0: + resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ipaddr.js@2.3.0: + resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} + engines: {node: '>= 10'} + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + json-schema-ref-resolver@3.0.0: + resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + light-my-request@6.6.0: + resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lru-cache@11.3.5: + resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} + engines: {node: 20 || >=22} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-pretty@11.3.0: + resolution: {integrity: sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==} + hasBin: true + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@9.14.0: + resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} + hasBin: true + + postcss@8.5.12: + resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} + engines: {node: ^10 || ^12 || >=14} + + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} + engines: {node: '>=10'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rollup@4.60.2: + resolution: {integrity: sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex2@5.1.1: + resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==} + hasBin: true + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + svelte-check@4.4.6: + resolution: {integrity: sha512-kP1zG81EWaFe9ZyTv4ZXv44Csi6Pkdpb7S3oj6m+K2ec/IcDg/a8LsFsnVLqm2nxtkSwsd5xPj/qFkTBgXHXjg==} + engines: {node: '>= 18.0.0'} + hasBin: true + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + typescript: '>=5.0.0' + + svelte@5.55.5: + resolution: {integrity: sha512-2uCs/LZ9us+AktdzYJM8OcxQ8qnPS1kpaO7syGT/MgO+6Qr1Ybl+TqPq+97u7PHqmmMlye5ZkoyXONy5mjjAbw==} + engines: {node: '>=18'} + + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.4.2: + resolution: {integrity: sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vite@7.3.2: + resolution: {integrity: sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + 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 + + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.27.7': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.27.7': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.27.7': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.27.7': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.27.7': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.27.7': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.27.7': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.27.7': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.27.7': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.27.7': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.27.7': + optional: true + + '@fastify/accept-negotiator@2.0.1': {} + + '@fastify/ajv-compiler@4.0.5': + dependencies: + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.0 + + '@fastify/error@4.2.0': {} + + '@fastify/fast-json-stringify-compiler@5.0.3': + dependencies: + fast-json-stringify: 6.3.0 + + '@fastify/forwarded@3.0.1': {} + + '@fastify/merge-json-schemas@0.2.1': + dependencies: + dequal: 2.0.3 + + '@fastify/proxy-addr@5.1.0': + dependencies: + '@fastify/forwarded': 3.0.1 + ipaddr.js: 2.3.0 + + '@fastify/send@4.1.0': + dependencies: + '@lukeed/ms': 2.0.2 + escape-html: 1.0.3 + fast-decode-uri-component: 1.0.1 + http-errors: 2.0.1 + mime: 3.0.0 + + '@fastify/static@8.3.0': + dependencies: + '@fastify/accept-negotiator': 2.0.1 + '@fastify/send': 4.1.0 + content-disposition: 0.5.4 + fastify-plugin: 5.1.0 + fastq: 1.20.1 + glob: 11.1.0 + + '@fastify/websocket@11.2.0': + dependencies: + duplexify: 4.1.3 + fastify-plugin: 5.1.0 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@isaacs/cliui@9.0.0': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lukeed/ms@2.0.2': {} + + '@pinojs/redact@0.4.0': {} + + '@rollup/rollup-android-arm-eabi@4.60.2': + optional: true + + '@rollup/rollup-android-arm64@4.60.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.2': + optional: true + + '@rollup/rollup-darwin-x64@4.60.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.2': + optional: true + + '@sveltejs/acorn-typescript@1.0.9(acorn@8.16.0)': + dependencies: + acorn: 8.16.0 + + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)))(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0))': + dependencies: + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) + debug: 4.4.3 + svelte: 5.55.5 + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)))(svelte@5.55.5)(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) + debug: 4.4.3 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.21 + svelte: 5.55.5 + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + vitefu: 1.1.3(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)) + transitivePeerDependencies: + - supports-color + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/node@22.19.17': + dependencies: + undici-types: 6.21.0 + + '@types/trusted-types@2.0.7': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.19.17 + + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@7.3.2(@types/node@22.19.17)(tsx@4.21.0))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.2(@types/node@22.19.17)(tsx@4.21.0) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + abstract-logging@2.0.1: {} + + acorn@8.16.0: {} + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + aria-query@5.3.1: {} + + assertion-error@2.0.1: {} + + atomic-sleep@1.0.0: {} + + avvio@9.2.0: + dependencies: + '@fastify/error': 4.2.0 + fastq: 1.20.1 + + axobject-query@4.1.0: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + cac@6.7.14: {} + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + check-error@2.1.3: {} + + chess.js@1.4.0: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + clsx@2.1.1: {} + + colorette@2.0.20: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + cookie@1.1.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + dateformat@4.6.3: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-eql@5.0.2: {} + + deepmerge@4.3.1: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + devalue@5.7.1: {} + + duplexify@4.1.3: + dependencies: + end-of-stream: 1.4.5 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + es-module-lexer@1.7.0: {} + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + escape-html@1.0.3: {} + + esm-env@1.2.2: {} + + esrap@2.2.5: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + event-target-shim@5.0.1: {} + + events@3.3.0: {} + + expect-type@1.3.0: {} + + fast-copy@3.0.2: {} + + fast-decode-uri-component@1.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stringify@6.3.0: + dependencies: + '@fastify/merge-json-schemas': 0.2.1 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.0 + json-schema-ref-resolver: 3.0.0 + rfdc: 1.4.1 + + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-safe-stringify@2.1.1: {} + + fast-uri@3.1.0: {} + + fastify-plugin@5.1.0: {} + + fastify@5.8.5: + dependencies: + '@fastify/ajv-compiler': 4.0.5 + '@fastify/error': 4.2.0 + '@fastify/fast-json-stringify-compiler': 5.0.3 + '@fastify/proxy-addr': 5.1.0 + abstract-logging: 2.0.1 + avvio: 9.2.0 + fast-json-stringify: 6.3.0 + find-my-way: 9.5.0 + light-my-request: 6.6.0 + pino: 9.14.0 + process-warning: 5.0.0 + rfdc: 1.4.1 + secure-json-parse: 4.1.0 + semver: 7.7.4 + toad-cache: 3.7.0 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + find-my-way@9.5.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 5.1.1 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fsevents@2.3.3: + optional: true + + get-tsconfig@4.14.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.2.3 + minimatch: 10.2.5 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.2 + + help-me@5.0.0: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + ieee754@1.2.1: {} + + inherits@2.0.4: {} + + ipaddr.js@2.3.0: {} + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + isexe@2.0.0: {} + + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + + joycon@3.1.1: {} + + js-tokens@9.0.1: {} + + json-schema-ref-resolver@3.0.0: + dependencies: + dequal: 2.0.3 + + json-schema-traverse@1.0.0: {} + + kleur@4.1.5: {} + + light-my-request@6.6.0: + dependencies: + cookie: 1.1.1 + process-warning: 4.0.1 + set-cookie-parser: 2.7.2 + + locate-character@3.0.0: {} + + loupe@3.2.1: {} + + lru-cache@11.3.5: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + mime@3.0.0: {} + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.5 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mri@1.2.0: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + on-exit-leak-free@2.1.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + package-json-from-dist@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.5 + minipass: 7.1.3 + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + picocolors@1.1.1: {} + + picomatch@4.0.4: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@11.3.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.4 + readable-stream: 4.7.0 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.1 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.1.0: {} + + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.1.0 + + postcss@8.5.12: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + process-warning@4.0.1: {} + + process-warning@5.0.0: {} + + process@0.11.10: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + quick-format-unescaped@4.0.4: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readdirp@4.1.2: {} + + real-require@0.2.0: {} + + require-from-string@2.0.2: {} + + resolve-pkg-maps@1.0.0: {} + + ret@0.5.0: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rollup@4.60.2: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.2 + '@rollup/rollup-android-arm64': 4.60.2 + '@rollup/rollup-darwin-arm64': 4.60.2 + '@rollup/rollup-darwin-x64': 4.60.2 + '@rollup/rollup-freebsd-arm64': 4.60.2 + '@rollup/rollup-freebsd-x64': 4.60.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.2 + '@rollup/rollup-linux-arm-musleabihf': 4.60.2 + '@rollup/rollup-linux-arm64-gnu': 4.60.2 + '@rollup/rollup-linux-arm64-musl': 4.60.2 + '@rollup/rollup-linux-loong64-gnu': 4.60.2 + '@rollup/rollup-linux-loong64-musl': 4.60.2 + '@rollup/rollup-linux-ppc64-gnu': 4.60.2 + '@rollup/rollup-linux-ppc64-musl': 4.60.2 + '@rollup/rollup-linux-riscv64-gnu': 4.60.2 + '@rollup/rollup-linux-riscv64-musl': 4.60.2 + '@rollup/rollup-linux-s390x-gnu': 4.60.2 + '@rollup/rollup-linux-x64-gnu': 4.60.2 + '@rollup/rollup-linux-x64-musl': 4.60.2 + '@rollup/rollup-openbsd-x64': 4.60.2 + '@rollup/rollup-openharmony-arm64': 4.60.2 + '@rollup/rollup-win32-arm64-msvc': 4.60.2 + '@rollup/rollup-win32-ia32-msvc': 4.60.2 + '@rollup/rollup-win32-x64-gnu': 4.60.2 + '@rollup/rollup-win32-x64-msvc': 4.60.2 + fsevents: 2.3.3 + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-buffer@5.2.1: {} + + safe-regex2@5.1.1: + dependencies: + ret: 0.5.0 + + safe-stable-stringify@2.5.0: {} + + secure-json-parse@2.7.0: {} + + secure-json-parse@4.1.0: {} + + semver@7.7.4: {} + + set-cookie-parser@2.7.2: {} + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + split2@4.2.0: {} + + stackback@0.0.2: {} + + statuses@2.0.2: {} + + std-env@3.10.0: {} + + stream-shift@1.0.3: {} + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-json-comments@3.1.1: {} + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + svelte-check@4.4.6(picomatch@4.0.4)(svelte@5.55.5)(typescript@5.9.3): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + chokidar: 4.0.3 + fdir: 6.5.0(picomatch@4.0.4) + picocolors: 1.1.1 + sade: 1.8.1 + svelte: 5.55.5 + typescript: 5.9.3 + transitivePeerDependencies: + - picomatch + + svelte@5.55.5: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) + '@types/estree': 1.0.8 + '@types/trusted-types': 2.0.7 + acorn: 8.16.0 + aria-query: 5.3.1 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.7.1 + esm-env: 1.2.2 + esrap: 2.2.5 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + transitivePeerDependencies: + - '@typescript-eslint/types' + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.4: {} + + toad-cache@3.7.0: {} + + toidentifier@1.0.1: {} + + tsx@4.21.0: + dependencies: + esbuild: 0.27.7 + get-tsconfig: 4.14.0 + optionalDependencies: + fsevents: 2.3.3 + + typescript@5.9.3: {} + + undici-types@6.21.0: {} + + util-deprecate@1.0.2: {} + + vite-node@3.2.4(@types/node@22.19.17)(tsx@4.21.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.12 + rollup: 4.60.2 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 22.19.17 + fsevents: 2.3.3 + tsx: 4.21.0 + + vite@7.3.2(@types/node@22.19.17)(tsx@4.21.0): + dependencies: + esbuild: 0.27.7 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.12 + rollup: 4.60.2 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 22.19.17 + fsevents: 2.3.3 + tsx: 4.21.0 + + vitefu@1.1.3(vite@6.4.2(@types/node@22.19.17)(tsx@4.21.0)): + optionalDependencies: + vite: 6.4.2(@types/node@22.19.17)(tsx@4.21.0) + + vitest@3.2.4(@types/node@22.19.17)(tsx@4.21.0): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.3.2(@types/node@22.19.17)(tsx@4.21.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.16 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.3.2(@types/node@22.19.17)(tsx@4.21.0) + vite-node: 3.2.4(@types/node@22.19.17)(tsx@4.21.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.19.17 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrappy@1.0.2: {} + + ws@8.20.0: {} + + zimmerframe@1.1.4: {} + + zod@3.25.76: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..18ec407 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - 'packages/*' diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..e255482 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "moduleResolution": "Bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "verbatimModuleSyntax": false, + "isolatedModules": true, + "declaration": true + } +}