From b5425e705ebee32169c0e48ce815a6f589a82e4d Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 14 Feb 2026 15:26:42 +0100 Subject: [PATCH] Apply full refactor updates plus pipeline/email UX confirmations --- CLAUDE.md | 776 +- DEPLOYMENT.md | 654 +- Notes.md | 804 +- build-check.txt | 288 + docker/Dockerfile | 146 +- docker/docker-compose.yml | 168 +- docker/docker-entrypoint.sh | 74 +- docs/Notes/notes-prototype-1.md | 30 +- docs/platform-review.md | 3672 +- .../README.md | 136 +- .../flowcharts/dependency-refit-map.md | 30 +- .../flowcharts/end-to-end-pipeline.md | 50 +- .../flowcharts/live-stage-controller.md | 30 +- .../flowcharts/main-vs-award-routing.md | 34 +- .../flowcharts/override-audit-flow.md | 28 +- .../master-implementation-plan.md | 190 +- .../acceptance-gates.md | 26 +- .../phase-00-contract-freeze/overview.md | 70 +- .../phase-00-contract-freeze/tasks.md | 62 +- .../acceptance-gates.md | 28 +- .../migration-cutover-plan.md | 96 +- .../overview.md | 54 +- .../schema-spec.md | 118 +- .../tasks.md | 48 +- .../acceptance-gates.md | 28 +- .../assignment-spec.md | 86 +- .../filtering-routing-spec.md | 110 +- .../live-control-spec.md | 64 +- .../overview.md | 46 +- .../stage-engine-spec.md | 92 +- .../phase-02-backend-orchestration/tasks.md | 60 +- .../acceptance-gates.md | 24 +- .../advanced-editor-spec.md | 68 +- .../form-behavior-and-validation.md | 60 +- .../overview.md | 46 +- .../phase-03-admin-control-plane-ux/tasks.md | 38 +- .../wizard-ia.md | 156 +- .../acceptance-gates.md | 22 +- .../applicant-experience-spec.md | 58 +- .../audience-live-vote-spec.md | 48 +- .../jury-experience-spec.md | 52 +- .../phase-04-participant-journeys/overview.md | 42 +- .../phase-04-participant-journeys/tasks.md | 42 +- .../acceptance-gates.md | 20 +- .../award-track-and-governance-spec.md | 78 +- .../overview.md | 42 +- .../tasks.md | 14 +- .../acceptance-gates.md | 24 +- .../module-refit-map.md | 52 +- .../overview.md | 42 +- .../symbol-sweep-checklist.md | 26 +- .../tasks.md | 16 +- .../acceptance-gates.md | 26 +- .../phase-07-validation-release/overview.md | 42 +- .../performance-and-resilience-plan.md | 54 +- .../phase-07-validation-release/runbook.md | 78 +- .../phase-07-validation-release/tasks.md | 14 +- .../shared/api-contracts.md | 194 +- .../shared/authz-matrix.md | 64 +- .../shared/decision-log.md | 32 +- .../shared/dependency-refit-inventory.md | 150 +- .../shared/domain-model.md | 312 +- .../shared/phase-gate-traceability.md | 64 +- .../shared/program-charter.md | 86 +- .../shared/release-evidence-template.md | 130 +- .../shared/risk-register.md | 34 +- .../shared/test-matrix.md | 114 +- .../phase-0-validation/domain-model-review.md | 1322 +- next.config.ts | 40 +- package-lock.json | 27888 ++++++++-------- package.json | 238 +- prisma/integrity-checks.ts | 492 +- .../20260130000000_init/migration.sql | 1818 +- .../migration.sql | 1100 +- .../migration.sql | 182 +- .../migration.sql | 82 +- .../migration.sql | 26 +- .../migration.sql | 60 +- .../migration.sql | 258 +- .../migration.sql | 4 +- .../migration.sql | 198 +- prisma/migrations/migration_lock.toml | 6 +- prisma/schema.prisma | 4200 +-- prisma/seed.ts | 2075 +- scripts/deploy.sh | 200 +- scripts/update.sh | 90 +- src/app/(admin)/admin/audit/page.tsx | 1500 +- .../(admin)/admin/awards/[id]/edit/page.tsx | 582 +- src/app/(admin)/admin/awards/[id]/page.tsx | 2446 +- src/app/(admin)/admin/awards/new/page.tsx | 454 +- src/app/(admin)/admin/awards/page.tsx | 476 +- src/app/(admin)/admin/dashboard-content.tsx | 2046 +- src/app/(admin)/admin/learning/[id]/page.tsx | 962 +- src/app/(admin)/admin/learning/new/page.tsx | 654 +- src/app/(admin)/admin/learning/page.tsx | 494 +- src/app/(admin)/admin/members/[id]/page.tsx | 10 +- src/app/(admin)/admin/members/invite/page.tsx | 2190 +- src/app/(admin)/admin/messages/page.tsx | 1402 +- .../(admin)/admin/messages/templates/page.tsx | 944 +- src/app/(admin)/admin/page.tsx | 144 +- src/app/(admin)/admin/partners/[id]/page.tsx | 564 +- src/app/(admin)/admin/partners/new/page.tsx | 340 +- src/app/(admin)/admin/partners/page.tsx | 518 +- .../programs/[id]/apply-settings/page.tsx | 2972 +- .../(admin)/admin/programs/[id]/edit/page.tsx | 548 +- .../admin/programs/[id]/mentorship/page.tsx | 866 +- src/app/(admin)/admin/programs/[id]/page.tsx | 280 +- src/app/(admin)/admin/programs/new/page.tsx | 266 +- src/app/(admin)/admin/programs/page.tsx | 552 +- .../(admin)/admin/projects/[id]/edit/page.tsx | 66 +- .../admin/projects/[id]/mentor/page.tsx | 786 +- src/app/(admin)/admin/projects/[id]/page.tsx | 1632 +- .../(admin)/admin/projects/import/page.tsx | 484 +- src/app/(admin)/admin/projects/new/page.tsx | 1300 +- src/app/(admin)/admin/projects/page.tsx | 101 +- src/app/(admin)/admin/projects/pool/page.tsx | 700 +- .../admin/projects/project-filters.tsx | 694 +- src/app/(admin)/admin/reports/page.tsx | 1868 +- src/app/(admin)/admin/reports/stages/page.tsx | 1342 +- .../admin/rounds/new-pipeline/page.tsx | 704 +- .../rounds/pipeline/[id]/advanced/page.tsx | 558 +- .../admin/rounds/pipeline/[id]/edit/page.tsx | 22 +- .../admin/rounds/pipeline/[id]/page.tsx | 1092 +- .../(admin)/admin/rounds/pipelines/page.tsx | 9 +- src/app/(admin)/admin/settings/page.tsx | 170 +- .../(admin)/admin/settings/webhooks/page.tsx | 1412 +- src/app/(admin)/error.tsx | 144 +- .../(applicant)/applicant/documents/page.tsx | 426 +- src/app/(applicant)/applicant/mentor/page.tsx | 276 +- src/app/(applicant)/applicant/page.tsx | 726 +- .../pipeline/[stageId]/documents/page.tsx | 334 +- .../pipeline/[stageId]/status/page.tsx | 556 +- .../(applicant)/applicant/pipeline/page.tsx | 534 +- src/app/(applicant)/applicant/team/page.tsx | 848 +- src/app/(applicant)/layout.tsx | 66 +- src/app/(auth)/accept-invite/page.tsx | 502 +- src/app/(auth)/error/page.tsx | 100 +- src/app/(auth)/login/page.tsx | 620 +- src/app/(auth)/onboarding/page.tsx | 1192 +- src/app/(auth)/set-password/page.tsx | 616 +- src/app/(auth)/verify-email/page.tsx | 62 +- src/app/(auth)/verify/page.tsx | 64 +- src/app/(jury)/error.tsx | 144 +- src/app/(jury)/jury/awards/[id]/page.tsx | 654 +- src/app/(jury)/jury/page.tsx | 1540 +- .../stages/[stageId]/assignments/page.tsx | 736 +- .../jury/stages/[stageId]/compare/page.tsx | 622 +- .../jury/stages/[stageId]/live/page.tsx | 538 +- .../projects/[projectId]/evaluate/page.tsx | 398 +- .../projects/[projectId]/evaluation/page.tsx | 470 +- .../[stageId]/projects/[projectId]/page.tsx | 434 +- src/app/(jury)/jury/stages/page.tsx | 494 +- src/app/(mentor)/error.tsx | 146 +- src/app/(mentor)/mentor/page.tsx | 796 +- .../(mentor)/mentor/projects/[id]/page.tsx | 1832 +- src/app/(mentor)/mentor/projects/page.tsx | 396 +- src/app/(observer)/error.tsx | 144 +- src/app/(observer)/observer/page.tsx | 24 +- src/app/(observer)/observer/reports/page.tsx | 1460 +- src/app/(public)/apply/[slug]/page.tsx | 130 +- .../apply/edition/[programSlug]/page.tsx | 130 +- .../(public)/email/change-password/page.tsx | 772 +- src/app/(public)/error.tsx | 144 +- .../(public)/live-scores/[sessionId]/page.tsx | 658 +- .../live-scores/stage/[sessionId]/page.tsx | 534 +- .../[id]/submission-detail-client.tsx | 808 +- .../(public)/my-submission/[id]/team/page.tsx | 864 +- .../my-submission/my-submission-client.tsx | 486 +- src/app/(public)/vote/[sessionId]/page.tsx | 782 +- .../(public)/vote/stage/[sessionId]/page.tsx | 430 +- src/app/(settings)/layout.tsx | 112 +- src/app/(settings)/settings/profile/page.tsx | 15 +- src/app/api/cron/audit-cleanup/route.ts | 96 +- src/app/api/cron/digest/route.ts | 78 +- src/app/api/cron/draft-cleanup/route.ts | 74 +- src/app/api/email/change-password/route.ts | 290 +- src/app/api/email/verify-credentials/route.ts | 168 +- src/app/api/files/bulk-download/route.ts | 248 +- src/app/api/live-voting/stream/route.ts | 430 +- .../api/sse/stage-live/[sessionId]/route.ts | 432 +- src/app/api/storage/local/route.ts | 250 +- src/app/error.tsx | 126 +- src/app/globals.css | 592 +- src/app/layout.tsx | 78 +- src/app/page.tsx | 356 +- src/app/providers.tsx | 128 +- .../admin/evaluation-summary-card.tsx | 670 +- .../admin/file-requirements-editor.tsx | 850 +- src/components/admin/members-content.tsx | 1124 +- src/components/admin/pdf-report.tsx | 332 +- .../pipeline/award-governance-editor.tsx | 358 + .../admin/pipeline/filtering-rules-editor.tsx | 379 + .../admin/pipeline/pipeline-flowchart.tsx | 552 +- .../admin/pipeline/pipeline-visualization.tsx | 242 +- .../admin/pipeline/routing-rules-editor.tsx | 464 + .../pipeline/sections/assignment-section.tsx | 296 +- .../pipeline/sections/awards-section.tsx | 514 +- .../pipeline/sections/basics-section.tsx | 198 +- .../pipeline/sections/filtering-section.tsx | 958 +- .../pipeline/sections/intake-section.tsx | 578 +- .../pipeline/sections/live-finals-section.tsx | 316 +- .../pipeline/sections/main-track-section.tsx | 456 +- .../sections/notifications-section.tsx | 332 +- .../pipeline/sections/results-section.tsx | 93 + .../pipeline/sections/review-section.tsx | 230 +- .../pipeline/sections/selection-section.tsx | 108 + .../admin/pipeline/stage-config-editor.tsx | 688 +- .../stage-panels/evaluation-panel.tsx | 272 +- .../pipeline/stage-panels/filter-panel.tsx | 368 +- .../pipeline/stage-panels/intake-panel.tsx | 270 +- .../stage-panels/live-final-panel.tsx | 346 +- .../pipeline/stage-panels/results-panel.tsx | 240 +- .../pipeline/stage-panels/selection-panel.tsx | 332 +- .../pipeline/stage-transitions-editor.tsx | 344 + src/components/admin/user-actions.tsx | 606 +- .../charts/cross-round-comparison.tsx | 306 +- src/components/charts/diversity-metrics.tsx | 558 +- src/components/charts/index.ts | 24 +- src/components/charts/juror-consistency.tsx | 342 +- .../forms/apply-steps/step-additional.tsx | 284 +- .../forms/apply-steps/step-contact.tsx | 260 +- .../forms/apply-steps/step-project.tsx | 260 +- .../forms/apply-steps/step-review.tsx | 412 +- .../forms/apply-steps/step-team.tsx | 372 +- .../forms/apply-steps/step-welcome.tsx | 238 +- src/components/forms/apply-wizard-dynamic.tsx | 1612 +- src/components/forms/csv-import-form.tsx | 1256 +- src/components/forms/evaluation-form.tsx | 2026 +- src/components/forms/notion-import-form.tsx | 978 +- src/components/forms/typeform-import-form.tsx | 1032 +- .../jury/collapsible-files-section.tsx | 152 +- src/components/jury/project-files-section.tsx | 184 +- src/components/layouts/admin-sidebar.tsx | 766 +- src/components/layouts/applicant-nav.tsx | 94 +- src/components/layouts/jury-nav.tsx | 154 +- src/components/layouts/mentor-nav.tsx | 74 +- src/components/layouts/observer-nav.tsx | 64 +- src/components/layouts/role-nav.tsx | 404 +- .../observer/observer-dashboard-content.tsx | 1044 +- src/components/settings/ai-settings-form.tsx | 706 +- src/components/settings/ai-usage-card.tsx | 588 +- .../settings/defaults-settings-form.tsx | 418 +- src/components/settings/settings-content.tsx | 1716 +- src/components/shared/animated-container.tsx | 56 +- src/components/shared/csv-export-dialog.tsx | 430 +- src/components/shared/discussion-thread.tsx | 290 +- src/components/shared/empty-state.tsx | 102 +- src/components/shared/export-pdf-button.tsx | 382 +- src/components/shared/file-preview.tsx | 206 +- src/components/shared/file-upload.tsx | 986 +- src/components/shared/file-viewer.tsx | 1678 +- .../shared/live-score-animation.tsx | 346 +- src/components/shared/logo-upload.tsx | 670 +- src/components/shared/logo.tsx | 110 +- src/components/shared/notification-bell.tsx | 850 +- src/components/shared/pagination.tsx | 172 +- src/components/shared/qr-code-display.tsx | 270 +- .../shared/requirement-upload-slot.tsx | 728 +- src/components/shared/stage-breadcrumb.tsx | 94 +- src/components/shared/stage-timeline.tsx | 410 +- src/components/shared/stage-window-badge.tsx | 266 +- src/components/shared/status-badge.tsx | 112 +- src/components/ui/country-select.tsx | 236 +- src/components/ui/editable-card.tsx | 242 +- src/components/ui/info-tooltip.tsx | 72 +- src/components/ui/inline-editable-text.tsx | 358 +- src/components/ui/progress.tsx | 68 +- src/components/ui/sidebar-stepper.tsx | 524 +- src/hooks/use-debounce.ts | 24 +- src/hooks/use-live-voting-sse.ts | 260 +- src/hooks/use-pipeline-inline-edit.ts | 92 +- src/hooks/use-stage-live-sse.ts | 306 +- src/lib/auth-redirect.ts | 60 +- src/lib/auth.config.ts | 182 +- src/lib/auth.ts | 632 +- src/lib/chunk-error-recovery.ts | 68 +- src/lib/countries.ts | 866 +- src/lib/email.ts | 3672 +- src/lib/file-type-categories.ts | 60 +- src/lib/minio.ts | 264 +- src/lib/password.ts | 186 +- src/lib/pdf-generator.ts | 844 +- src/lib/pipeline-defaults.ts | 288 +- src/lib/pipeline-validation.ts | 229 +- src/lib/prisma.ts | 52 +- src/lib/stage-config-schema.ts | 457 + src/lib/storage/index.ts | 262 +- src/lib/wizard-config.ts | 274 +- src/server/routers/_app.ts | 198 +- src/server/routers/analytics.ts | 2382 +- src/server/routers/applicant.ts | 2550 +- src/server/routers/application.ts | 1748 +- src/server/routers/assignment.ts | 2558 +- src/server/routers/audit.ts | 678 +- src/server/routers/avatar.ts | 222 +- src/server/routers/award.ts | 1122 +- src/server/routers/cohort.ts | 662 +- src/server/routers/dashboard.ts | 374 +- src/server/routers/decision.ts | 706 +- src/server/routers/evaluation.ts | 2490 +- src/server/routers/export.ts | 1266 +- src/server/routers/file.ts | 1993 +- src/server/routers/filtering.ts | 1745 +- src/server/routers/gracePeriod.ts | 410 +- src/server/routers/learningResource.ts | 986 +- src/server/routers/live-voting.ts | 2076 +- src/server/routers/live.ts | 1644 +- src/server/routers/logo.ts | 266 +- src/server/routers/mentor.ts | 2574 +- src/server/routers/message.ts | 810 +- src/server/routers/notification.ts | 762 +- src/server/routers/notion-import.ts | 478 +- src/server/routers/partner.ts | 702 +- src/server/routers/pipeline.ts | 2194 +- src/server/routers/program.ts | 598 +- src/server/routers/project-pool.ts | 406 +- src/server/routers/project.ts | 93 + src/server/routers/routing.ts | 620 +- src/server/routers/settings.ts | 1564 +- src/server/routers/specialAward.ts | 1504 +- src/server/routers/stage.ts | 1494 +- src/server/routers/stageAssignment.ts | 1264 +- src/server/routers/stageFiltering.ts | 1028 +- src/server/routers/tag.ts | 1598 +- src/server/routers/typeform-import.ts | 514 +- src/server/routers/user.ts | 99 +- src/server/routers/webhook.ts | 612 +- src/server/routers/wizard-template.ts | 152 +- src/server/services/ai-assignment.ts | 1186 +- src/server/services/ai-award-eligibility.ts | 684 +- src/server/services/ai-evaluation-summary.ts | 808 +- src/server/services/ai-filtering.ts | 1310 +- src/server/services/ai-tagging.ts | 844 +- src/server/services/award-eligibility-job.ts | 368 +- src/server/services/email-digest.ts | 552 +- src/server/services/evaluation-reminders.ts | 356 +- src/server/services/in-app-notification.ts | 964 +- src/server/services/live-control.ts | 1236 +- src/server/services/mentor-matching.ts | 972 +- src/server/services/routing-engine.ts | 1010 +- src/server/services/smart-assignment.ts | 1400 +- src/server/services/stage-assignment.ts | 1546 +- src/server/services/stage-engine.ts | 928 +- src/server/services/stage-filtering.ts | 1168 +- src/server/services/stage-notifications.ts | 1004 +- src/server/services/webhook-dispatcher.ts | 348 +- src/server/trpc.ts | 318 +- src/server/utils/audit.ts | 84 +- src/types/pipeline-wizard.ts | 266 +- src/types/wizard-config.ts | 310 +- tests/helpers.ts | 834 +- tests/integration/assignment-preview.test.ts | 184 +- tests/integration/award-exclusive.test.ts | 198 +- tests/integration/cohort-voting.test.ts | 312 +- tests/integration/decision-audit.test.ts | 230 +- tests/integration/live-runtime.test.ts | 278 +- tests/integration/pipeline-crud.test.ts | 290 +- tests/integration/stage-config.test.ts | 332 +- tests/integration/transition-routing.test.ts | 234 +- tests/setup.ts | 132 +- tests/unit/award-governance.test.ts | 308 +- tests/unit/live-control.test.ts | 376 +- tests/unit/override-validation.test.ts | 206 +- tests/unit/routing-engine.test.ts | 256 +- tests/unit/stage-assignment.test.ts | 340 +- tests/unit/stage-engine.test.ts | 350 +- tests/unit/stage-filtering.test.ts | 346 +- tsc-audit.txt | 1085 + tsc-check-final.txt | Bin 0 -> 27738 bytes tsc-check-new.txt | Bin 0 -> 27738 bytes tsc-check.txt | 0 tsc-output2.txt | 1 + tsc-output3.txt | 0 vitest.config.ts | 38 +- 374 files changed, 116737 insertions(+), 111969 deletions(-) create mode 100644 build-check.txt create mode 100644 src/components/admin/pipeline/award-governance-editor.tsx create mode 100644 src/components/admin/pipeline/filtering-rules-editor.tsx create mode 100644 src/components/admin/pipeline/routing-rules-editor.tsx create mode 100644 src/components/admin/pipeline/sections/results-section.tsx create mode 100644 src/components/admin/pipeline/sections/selection-section.tsx create mode 100644 src/components/admin/pipeline/stage-transitions-editor.tsx create mode 100644 src/lib/stage-config-schema.ts create mode 100644 tsc-audit.txt create mode 100644 tsc-check-final.txt create mode 100644 tsc-check-new.txt create mode 100644 tsc-check.txt create mode 100644 tsc-output2.txt create mode 100644 tsc-output3.txt diff --git a/CLAUDE.md b/CLAUDE.md index 2166654..bd5f08b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,388 +1,388 @@ -# MOPC Platform - Claude Code Context - -## Project Overview - -**MOPC (Monaco Ocean Protection Challenge)** is a secure jury online voting platform for managing project selection rounds. The platform enables jury members to evaluate submitted ocean conservation projects, with Phase 1 supporting two selection rounds: - -- **Round 1**: ~130 projects → ~60 semi-finalists -- **Round 2**: ~60 projects → 6 finalists - -**Domain**: `monaco-opc.com` - -The platform is designed for future expansion into a comprehensive program management system including learning hub, communication workflows, and partner modules. - -## Key Decisions - -| Decision | Choice | -|----------|--------| -| Evaluation Criteria | Fully configurable per round (admin defines) | -| CSV Import | Flexible column mapping (admin maps columns) | -| Max File Size | 500MB (for videos) | -| Observer Role | Included in Phase 1 | -| First Admin | Database seed script | -| Past Evaluations | Visible read-only after submit | -| Grace Period | Admin-configurable per juror/project | -| Smart Assignment | AI-powered (GPT) + Smart Algorithm fallback + geo-diversity, familiarity, COI scoring | -| AI Data Privacy | All data anonymized before sending to GPT | -| Evaluation Criteria Types | `numeric`, `text`, `boolean`, `section_header` (backward-compatible) | -| COI Workflow | Mandatory declaration before evaluation, admin review | -| Evaluation Reminders | Cron-based email reminders with countdown urgency | - -## Brand Identity - -| Name | Hex | Usage | -|------|-----|-------| -| Primary Red | `#de0f1e` | CTAs, alerts | -| Dark Blue | `#053d57` | Headers, sidebar | -| White | `#fefefe` | Backgrounds | -| Teal | `#557f8c` | Links, secondary | - -**Typography**: Montserrat (600/700 for headings, 300/400 for body) - -## Tech Stack - -| Layer | Technology | Version | -|-------|-----------|---------| -| **Framework** | Next.js (App Router) | 15.x | -| **Language** | TypeScript | 5.x | -| **UI Components** | shadcn/ui | latest | -| **Styling** | Tailwind CSS | 3.x | -| **API Layer** | tRPC | 11.x | -| **Database** | PostgreSQL | 16.x | -| **ORM** | Prisma | 6.x | -| **Authentication** | NextAuth.js (Auth.js) | 5.x | -| **AI** | OpenAI GPT | 4.x SDK | -| **Animation** | Motion (Framer Motion) | 11.x | -| **Notifications** | Sonner | 1.x | -| **Command Palette** | cmdk | 1.x | -| **File Storage** | MinIO (S3-compatible) | External | -| **Email** | Nodemailer + Poste.io | External | -| **Containerization** | Docker Compose | 2.x | -| **Reverse Proxy** | Nginx | External | - -## Architecture Principles - -1. **Type Safety First**: End-to-end TypeScript from database to UI via Prisma → tRPC → React -2. **Mobile-First Responsive**: All components designed for mobile, enhanced for desktop -3. **Full Control**: No black-box services; every component is understood and maintainable -4. **Extensible Data Model**: JSON fields for future attributes without schema migrations -5. **Security by Default**: RBAC, audit logging, secure file access with pre-signed URLs - -## File Structure - -``` -mopc-platform/ -├── CLAUDE.md # This file - project context -├── docs/ -│ └── architecture/ # Architecture documentation -│ ├── README.md # System overview -│ ├── database.md # Database design -│ ├── api.md # API design -│ ├── infrastructure.md # Deployment docs -│ └── ui.md # UI/UX patterns -├── src/ -│ ├── app/ # Next.js App Router pages -│ │ ├── (auth)/ # Public auth routes (login, verify) -│ │ ├── (admin)/ # Admin dashboard (protected) -│ │ ├── (jury)/ # Jury interface (protected) -│ │ ├── api/ # API routes -│ │ │ ├── trpc/ # tRPC endpoint -│ │ │ └── cron/ -│ │ │ └── reminders/ # Cron endpoint for evaluation reminders (F4) -│ │ ├── layout.tsx # Root layout -│ │ └── page.tsx # Home/landing -│ ├── components/ -│ │ ├── ui/ # shadcn/ui components -│ │ ├── admin/ # Admin-specific components -│ │ │ └── evaluation-summary-card.tsx # AI summary display -│ │ ├── forms/ # Form components -│ │ │ ├── evaluation-form.tsx # With progress indicator (F1) -│ │ │ ├── coi-declaration-dialog.tsx # COI blocking dialog (F5) -│ │ │ └── evaluation-form-with-coi.tsx # COI-gated wrapper (F5) -│ │ ├── layouts/ # Layout components (sidebar, nav) -│ │ └── shared/ # Shared components -│ │ └── countdown-timer.tsx # Live countdown with urgency (F4) -│ ├── lib/ -│ │ ├── auth.ts # NextAuth configuration -│ │ ├── prisma.ts # Prisma client singleton -│ │ ├── trpc/ # tRPC client & server setup -│ │ ├── minio.ts # MinIO client -│ │ └── email.ts # Email utilities -│ ├── server/ -│ │ ├── routers/ # tRPC routers by domain -│ │ │ ├── program.ts -│ │ │ ├── round.ts -│ │ │ ├── project.ts -│ │ │ ├── user.ts -│ │ │ ├── assignment.ts -│ │ │ ├── evaluation.ts -│ │ │ ├── audit.ts -│ │ │ ├── settings.ts -│ │ │ ├── gracePeriod.ts -│ │ │ ├── export.ts # CSV export incl. filtering results (F2) -│ │ │ ├── analytics.ts # Reports/analytics (observer access, F3) -│ │ │ └── mentor.ts # Mentor messaging endpoints (F10) -│ │ ├── services/ # Business logic services -│ │ │ ├── smart-assignment.ts # With geo/familiarity/COI scoring (F8) -│ │ │ ├── evaluation-reminders.ts # Email reminder service (F4) -│ │ │ └── ai-evaluation-summary.ts # GPT summary generation (F7) -│ │ └── middleware/ # RBAC & auth middleware -│ ├── hooks/ # React hooks -│ ├── types/ # Shared TypeScript types -│ └── utils/ # Utility functions -├── prisma/ -│ ├── schema.prisma # Database schema -│ ├── migrations/ # Migration files -│ └── seed.ts # Seed data -├── public/ # Static assets -├── docker/ -│ ├── Dockerfile # Production build -│ ├── docker-compose.yml # Production stack -│ └── docker-compose.dev.yml # Development stack -├── tests/ -│ ├── unit/ # Unit tests -│ └── e2e/ # End-to-end tests -└── config files... # package.json, tsconfig, etc. -``` - -## Coding Standards - -### TypeScript -- Strict mode enabled -- Explicit return types for functions -- Use `type` over `interface` for consistency (unless extending) -- Prefer `unknown` over `any` - -### React/Next.js -- Use Server Components by default -- `'use client'` only when needed (interactivity, hooks) -- Collocate components with their routes when specific to that route -- Use React Query (via tRPC) for server state - -### Naming Conventions -- **Files**: kebab-case (`user-profile.tsx`) -- **Components**: PascalCase (`UserProfile`) -- **Functions/Variables**: camelCase (`getUserById`) -- **Constants**: SCREAMING_SNAKE_CASE (`MAX_FILE_SIZE`) -- **Database Tables**: PascalCase in Prisma (`User`, `Project`) -- **Database Columns**: camelCase in Prisma (`createdAt`) - -### Styling -- Tailwind CSS utility classes -- Mobile-first: base styles for mobile, `md:` for tablet, `lg:` for desktop -- Use shadcn/ui components as base, customize via CSS variables -- No inline styles; no separate CSS files unless absolutely necessary - -### API Design (tRPC) -- Group by domain: `trpc.program.create()`, `trpc.round.list()` -- Use Zod for input validation -- Return consistent response shapes -- Throw `TRPCError` with appropriate codes - -## Common Commands - -```bash -# Development -npm run dev # Start Next.js dev server -npm run db:studio # Open Prisma Studio -npm run db:push # Push schema changes (dev only) -npm run db:migrate # Run migrations -npm run db:seed # Seed database - -# Testing -npm run test # Run unit tests -npm run test:e2e # Run E2E tests -npm run test:coverage # Test with coverage - -# Build & Deploy -npm run build # Production build -npm run start # Start production server -docker compose up -d # Start Docker stack -docker compose logs -f app # View app logs - -# Code Quality -npm run lint # ESLint -npm run format # Prettier -npm run typecheck # TypeScript check -``` - -## Windows Development Notes - -**IMPORTANT**: On Windows, all Docker commands AND all npm/node commands must be run using PowerShell (`powershell -ExecutionPolicy Bypass -Command "..."`), not bash/cmd. This is required for proper Docker Desktop integration and Node.js execution. - -**IMPORTANT**: When invoking PowerShell from bash, always use `-ExecutionPolicy Bypass` to skip the user profile script which is blocked by execution policy: -```bash -powershell -ExecutionPolicy Bypass -Command "..." -``` - -Examples: -```bash -# npm commands -powershell -ExecutionPolicy Bypass -Command "npm install" -powershell -ExecutionPolicy Bypass -Command "npm run build" -powershell -ExecutionPolicy Bypass -Command "npx prisma generate" - -# Docker commands -powershell -ExecutionPolicy Bypass -Command "docker compose -f docker/docker-compose.dev.yml up -d" -``` - -```powershell -# Docker commands on Windows (use PowerShell) -docker compose -f docker/docker-compose.dev.yml up -d -docker compose -f docker/docker-compose.dev.yml build --no-cache app -docker compose -f docker/docker-compose.dev.yml logs -f app -docker compose -f docker/docker-compose.dev.yml down -``` - -## Environment Variables - -```env -# Database -DATABASE_URL="postgresql://user:pass@localhost:5432/mopc" - -# NextAuth -NEXTAUTH_URL="https://monaco-opc.com" -NEXTAUTH_SECRET="your-secret-key" - -# MinIO (existing separate stack) -MINIO_ENDPOINT="http://localhost:9000" -MINIO_ACCESS_KEY="your-access-key" -MINIO_SECRET_KEY="your-secret-key" -MINIO_BUCKET="mopc-files" - -# Email (Poste.io - existing) -SMTP_HOST="localhost" -SMTP_PORT="587" -SMTP_USER="noreply@monaco-opc.com" -SMTP_PASS="your-smtp-password" -EMAIL_FROM="MOPC Platform " - -# OpenAI (for smart assignment and AI evaluation summaries) -OPENAI_API_KEY="your-openai-api-key" - -# Cron (for scheduled evaluation reminders) -CRON_SECRET="your-cron-secret-key" -``` - -## Key Architectural Decisions - -### 1. Next.js App Router over Pages Router -**Rationale**: Server Components reduce client bundle, better data fetching patterns, layouts system - -### 2. tRPC over REST -**Rationale**: End-to-end type safety without code generation, excellent DX with autocomplete - -### 3. Prisma over raw SQL -**Rationale**: Type-safe queries, migration system, works seamlessly with TypeScript - -### 4. NextAuth.js over custom auth -**Rationale**: Battle-tested, supports magic links, session management built-in - -### 5. MinIO (external) over local file storage -**Rationale**: S3-compatible, pre-signed URLs for security, scalable, already deployed - -### 6. JSON fields for extensibility -**Rationale**: `metadata_json`, `settings_json` allow adding attributes without migrations - -### 7. Soft deletes with status fields -**Rationale**: Audit trail preservation, recovery capability, referential integrity - -## User Roles (RBAC) - -| Role | Permissions | -|------|------------| -| **SUPER_ADMIN** | Full system access, all programs, user management | -| **PROGRAM_ADMIN** | Manage specific programs, rounds, projects, jury | -| **JURY_MEMBER** | View assigned projects only, submit evaluations, declare COI | -| **OBSERVER** | Read-only access to dashboards, all analytics/reports | -| **MENTOR** | View assigned projects, message applicants via `mentorProcedure` | -| **APPLICANT** | View own project status, upload documents per round, message mentor | - -## Important Constraints - -1. **Jury can only see assigned projects** - enforced at query level -2. **Voting windows are strict** - submissions blocked outside active window -3. **Evaluations are versioned** - edits create new versions -4. **All admin actions are audited** - immutable audit log -5. **Files accessed via pre-signed URLs** - no public bucket access -6. **Mobile responsiveness is mandatory** - every view must work on phones -7. **File downloads require project authorization** - jury/mentor must be assigned to the project -8. **Mentor endpoints require MENTOR role** - uses `mentorProcedure` middleware -9. **COI declaration required before evaluation** - blocking dialog gates evaluation form; admin reviews COI declarations -10. **Evaluation form supports multiple criterion types** - `numeric`, `text`, `boolean`, `section_header`; defaults to `numeric` for backward compatibility -11. **Smart assignment respects COI** - jurors with declared conflicts are skipped entirely; geo-diversity penalty and prior-round familiarity bonus applied -12. **Cron endpoints protected by CRON_SECRET** - `/api/cron/reminders` validates secret header -13. **Project status changes tracked** - every status update creates a `ProjectStatusHistory` record -14. **Per-round document management** - `ProjectFile` supports `roundId` scoping and `isLate` deadline tracking - -## Security Notes - -### CSRF Protection -tRPC mutations are protected against CSRF attacks because: -- tRPC uses `application/json` content type, which triggers CORS preflight on cross-origin requests -- Browsers block cross-origin JSON POSTs by default (Same-Origin Policy) -- NextAuth's own routes (`/api/auth/*`) have built-in CSRF token protection -- No custom CORS headers are configured to allow external origins - -**Do NOT add permissive CORS headers** (e.g., `Access-Control-Allow-Origin: *`) without also implementing explicit CSRF token validation on all mutation endpoints. - -### Rate Limiting -- tRPC API: 100 requests/minute per IP -- Auth endpoints: 10 POST requests/minute per IP -- Account lockout: 5 failed password attempts triggers 15-minute lockout - -## External Services (Pre-existing) - -These services are already running on the VPS in separate Docker Compose stacks: - -- **MinIO**: `http://localhost:9000` - S3-compatible storage -- **Poste.io**: `localhost:587` - SMTP server for emails -- **Nginx**: Host-level reverse proxy with SSL (certbot) - -The MOPC platform connects to these via environment variables. - -## Phase 1 Scope - -### In Scope -- Round management (create, configure, activate/close) -- Project import (CSV) and file uploads -- Jury invitation (magic link) -- Manual project assignment (single + bulk) -- Evaluation form (configurable criteria) -- Autosave + final submit -- Voting window enforcement -- Progress dashboards -- CSV export -- Audit logging -- **F1: Evaluation progress indicator** - sticky status bar with percentage tracking across criteria, global score, decision, feedback -- **F2: Export filtering results as CSV** - dynamic AI column flattening from `aiScreeningJson` -- **F3: Observer access to reports/analytics** - all 8 analytics procedures use `observerProcedure`; observer reports page with round selector, tabs, charts -- **F4: Countdown timer + email reminders** - live countdown with urgency colors; `EvaluationRemindersService` with cron endpoint (`/api/cron/reminders`) -- **F5: Conflict of Interest declaration** - `ConflictOfInterest` model; blocking dialog before evaluation; admin COI review page -- **F6: Bulk status update UI** - checkbox selection, floating toolbar, `ProjectStatusHistory` tracking -- **F7: AI-powered evaluation summary** - `EvaluationSummary` model; GPT-generated strengths/weaknesses, themes, scoring stats -- **F8: Smart assignment improvements** - `geoDiversityPenalty`, `previousRoundFamiliarity`, `coiPenalty` scoring factors -- **F9: Evaluation form flexibility** - extended criterion types (`numeric`, `text`, `boolean`, `section_header`); conditional visibility, section grouping -- **F10: Applicant portal enhancements** - `ProjectStatusHistory` timeline; per-round document management (`roundId` + `isLate` on `ProjectFile`); `MentorMessage` model for mentor-applicant chat - -### Out of Scope (Phase 2+) -- Typeform/Notion integrations -- WhatsApp notifications -- Learning hub -- Partner modules -- Public website - -## Testing Strategy - -- **Unit Tests**: Business logic, utilities, validators -- **Integration Tests**: tRPC routers with test database -- **E2E Tests**: Critical user flows (Playwright) -- **Manual Testing**: Responsive design on real devices - -## Documentation Links - -- [Architecture Overview](./docs/architecture/README.md) -- [Database Design](./docs/architecture/database.md) -- [API Design](./docs/architecture/api.md) -- [Infrastructure](./docs/architecture/infrastructure.md) -- [UI/UX Patterns](./docs/architecture/ui.md) +# MOPC Platform - Claude Code Context + +## Project Overview + +**MOPC (Monaco Ocean Protection Challenge)** is a secure jury online voting platform for managing project selection rounds. The platform enables jury members to evaluate submitted ocean conservation projects, with Phase 1 supporting two selection rounds: + +- **Round 1**: ~130 projects → ~60 semi-finalists +- **Round 2**: ~60 projects → 6 finalists + +**Domain**: `monaco-opc.com` + +The platform is designed for future expansion into a comprehensive program management system including learning hub, communication workflows, and partner modules. + +## Key Decisions + +| Decision | Choice | +|----------|--------| +| Evaluation Criteria | Fully configurable per round (admin defines) | +| CSV Import | Flexible column mapping (admin maps columns) | +| Max File Size | 500MB (for videos) | +| Observer Role | Included in Phase 1 | +| First Admin | Database seed script | +| Past Evaluations | Visible read-only after submit | +| Grace Period | Admin-configurable per juror/project | +| Smart Assignment | AI-powered (GPT) + Smart Algorithm fallback + geo-diversity, familiarity, COI scoring | +| AI Data Privacy | All data anonymized before sending to GPT | +| Evaluation Criteria Types | `numeric`, `text`, `boolean`, `section_header` (backward-compatible) | +| COI Workflow | Mandatory declaration before evaluation, admin review | +| Evaluation Reminders | Cron-based email reminders with countdown urgency | + +## Brand Identity + +| Name | Hex | Usage | +|------|-----|-------| +| Primary Red | `#de0f1e` | CTAs, alerts | +| Dark Blue | `#053d57` | Headers, sidebar | +| White | `#fefefe` | Backgrounds | +| Teal | `#557f8c` | Links, secondary | + +**Typography**: Montserrat (600/700 for headings, 300/400 for body) + +## Tech Stack + +| Layer | Technology | Version | +|-------|-----------|---------| +| **Framework** | Next.js (App Router) | 15.x | +| **Language** | TypeScript | 5.x | +| **UI Components** | shadcn/ui | latest | +| **Styling** | Tailwind CSS | 3.x | +| **API Layer** | tRPC | 11.x | +| **Database** | PostgreSQL | 16.x | +| **ORM** | Prisma | 6.x | +| **Authentication** | NextAuth.js (Auth.js) | 5.x | +| **AI** | OpenAI GPT | 4.x SDK | +| **Animation** | Motion (Framer Motion) | 11.x | +| **Notifications** | Sonner | 1.x | +| **Command Palette** | cmdk | 1.x | +| **File Storage** | MinIO (S3-compatible) | External | +| **Email** | Nodemailer + Poste.io | External | +| **Containerization** | Docker Compose | 2.x | +| **Reverse Proxy** | Nginx | External | + +## Architecture Principles + +1. **Type Safety First**: End-to-end TypeScript from database to UI via Prisma → tRPC → React +2. **Mobile-First Responsive**: All components designed for mobile, enhanced for desktop +3. **Full Control**: No black-box services; every component is understood and maintainable +4. **Extensible Data Model**: JSON fields for future attributes without schema migrations +5. **Security by Default**: RBAC, audit logging, secure file access with pre-signed URLs + +## File Structure + +``` +mopc-platform/ +├── CLAUDE.md # This file - project context +├── docs/ +│ └── architecture/ # Architecture documentation +│ ├── README.md # System overview +│ ├── database.md # Database design +│ ├── api.md # API design +│ ├── infrastructure.md # Deployment docs +│ └── ui.md # UI/UX patterns +├── src/ +│ ├── app/ # Next.js App Router pages +│ │ ├── (auth)/ # Public auth routes (login, verify) +│ │ ├── (admin)/ # Admin dashboard (protected) +│ │ ├── (jury)/ # Jury interface (protected) +│ │ ├── api/ # API routes +│ │ │ ├── trpc/ # tRPC endpoint +│ │ │ └── cron/ +│ │ │ └── reminders/ # Cron endpoint for evaluation reminders (F4) +│ │ ├── layout.tsx # Root layout +│ │ └── page.tsx # Home/landing +│ ├── components/ +│ │ ├── ui/ # shadcn/ui components +│ │ ├── admin/ # Admin-specific components +│ │ │ └── evaluation-summary-card.tsx # AI summary display +│ │ ├── forms/ # Form components +│ │ │ ├── evaluation-form.tsx # With progress indicator (F1) +│ │ │ ├── coi-declaration-dialog.tsx # COI blocking dialog (F5) +│ │ │ └── evaluation-form-with-coi.tsx # COI-gated wrapper (F5) +│ │ ├── layouts/ # Layout components (sidebar, nav) +│ │ └── shared/ # Shared components +│ │ └── countdown-timer.tsx # Live countdown with urgency (F4) +│ ├── lib/ +│ │ ├── auth.ts # NextAuth configuration +│ │ ├── prisma.ts # Prisma client singleton +│ │ ├── trpc/ # tRPC client & server setup +│ │ ├── minio.ts # MinIO client +│ │ └── email.ts # Email utilities +│ ├── server/ +│ │ ├── routers/ # tRPC routers by domain +│ │ │ ├── program.ts +│ │ │ ├── round.ts +│ │ │ ├── project.ts +│ │ │ ├── user.ts +│ │ │ ├── assignment.ts +│ │ │ ├── evaluation.ts +│ │ │ ├── audit.ts +│ │ │ ├── settings.ts +│ │ │ ├── gracePeriod.ts +│ │ │ ├── export.ts # CSV export incl. filtering results (F2) +│ │ │ ├── analytics.ts # Reports/analytics (observer access, F3) +│ │ │ └── mentor.ts # Mentor messaging endpoints (F10) +│ │ ├── services/ # Business logic services +│ │ │ ├── smart-assignment.ts # With geo/familiarity/COI scoring (F8) +│ │ │ ├── evaluation-reminders.ts # Email reminder service (F4) +│ │ │ └── ai-evaluation-summary.ts # GPT summary generation (F7) +│ │ └── middleware/ # RBAC & auth middleware +│ ├── hooks/ # React hooks +│ ├── types/ # Shared TypeScript types +│ └── utils/ # Utility functions +├── prisma/ +│ ├── schema.prisma # Database schema +│ ├── migrations/ # Migration files +│ └── seed.ts # Seed data +├── public/ # Static assets +├── docker/ +│ ├── Dockerfile # Production build +│ ├── docker-compose.yml # Production stack +│ └── docker-compose.dev.yml # Development stack +├── tests/ +│ ├── unit/ # Unit tests +│ └── e2e/ # End-to-end tests +└── config files... # package.json, tsconfig, etc. +``` + +## Coding Standards + +### TypeScript +- Strict mode enabled +- Explicit return types for functions +- Use `type` over `interface` for consistency (unless extending) +- Prefer `unknown` over `any` + +### React/Next.js +- Use Server Components by default +- `'use client'` only when needed (interactivity, hooks) +- Collocate components with their routes when specific to that route +- Use React Query (via tRPC) for server state + +### Naming Conventions +- **Files**: kebab-case (`user-profile.tsx`) +- **Components**: PascalCase (`UserProfile`) +- **Functions/Variables**: camelCase (`getUserById`) +- **Constants**: SCREAMING_SNAKE_CASE (`MAX_FILE_SIZE`) +- **Database Tables**: PascalCase in Prisma (`User`, `Project`) +- **Database Columns**: camelCase in Prisma (`createdAt`) + +### Styling +- Tailwind CSS utility classes +- Mobile-first: base styles for mobile, `md:` for tablet, `lg:` for desktop +- Use shadcn/ui components as base, customize via CSS variables +- No inline styles; no separate CSS files unless absolutely necessary + +### API Design (tRPC) +- Group by domain: `trpc.program.create()`, `trpc.round.list()` +- Use Zod for input validation +- Return consistent response shapes +- Throw `TRPCError` with appropriate codes + +## Common Commands + +```bash +# Development +npm run dev # Start Next.js dev server +npm run db:studio # Open Prisma Studio +npm run db:push # Push schema changes (dev only) +npm run db:migrate # Run migrations +npm run db:seed # Seed database + +# Testing +npm run test # Run unit tests +npm run test:e2e # Run E2E tests +npm run test:coverage # Test with coverage + +# Build & Deploy +npm run build # Production build +npm run start # Start production server +docker compose up -d # Start Docker stack +docker compose logs -f app # View app logs + +# Code Quality +npm run lint # ESLint +npm run format # Prettier +npm run typecheck # TypeScript check +``` + +## Windows Development Notes + +**IMPORTANT**: On Windows, all Docker commands AND all npm/node commands must be run using PowerShell (`powershell -ExecutionPolicy Bypass -Command "..."`), not bash/cmd. This is required for proper Docker Desktop integration and Node.js execution. + +**IMPORTANT**: When invoking PowerShell from bash, always use `-ExecutionPolicy Bypass` to skip the user profile script which is blocked by execution policy: +```bash +powershell -ExecutionPolicy Bypass -Command "..." +``` + +Examples: +```bash +# npm commands +powershell -ExecutionPolicy Bypass -Command "npm install" +powershell -ExecutionPolicy Bypass -Command "npm run build" +powershell -ExecutionPolicy Bypass -Command "npx prisma generate" + +# Docker commands +powershell -ExecutionPolicy Bypass -Command "docker compose -f docker/docker-compose.dev.yml up -d" +``` + +```powershell +# Docker commands on Windows (use PowerShell) +docker compose -f docker/docker-compose.dev.yml up -d +docker compose -f docker/docker-compose.dev.yml build --no-cache app +docker compose -f docker/docker-compose.dev.yml logs -f app +docker compose -f docker/docker-compose.dev.yml down +``` + +## Environment Variables + +```env +# Database +DATABASE_URL="postgresql://user:pass@localhost:5432/mopc" + +# NextAuth +NEXTAUTH_URL="https://monaco-opc.com" +NEXTAUTH_SECRET="your-secret-key" + +# MinIO (existing separate stack) +MINIO_ENDPOINT="http://localhost:9000" +MINIO_ACCESS_KEY="your-access-key" +MINIO_SECRET_KEY="your-secret-key" +MINIO_BUCKET="mopc-files" + +# Email (Poste.io - existing) +SMTP_HOST="localhost" +SMTP_PORT="587" +SMTP_USER="noreply@monaco-opc.com" +SMTP_PASS="your-smtp-password" +EMAIL_FROM="MOPC Platform " + +# OpenAI (for smart assignment and AI evaluation summaries) +OPENAI_API_KEY="your-openai-api-key" + +# Cron (for scheduled evaluation reminders) +CRON_SECRET="your-cron-secret-key" +``` + +## Key Architectural Decisions + +### 1. Next.js App Router over Pages Router +**Rationale**: Server Components reduce client bundle, better data fetching patterns, layouts system + +### 2. tRPC over REST +**Rationale**: End-to-end type safety without code generation, excellent DX with autocomplete + +### 3. Prisma over raw SQL +**Rationale**: Type-safe queries, migration system, works seamlessly with TypeScript + +### 4. NextAuth.js over custom auth +**Rationale**: Battle-tested, supports magic links, session management built-in + +### 5. MinIO (external) over local file storage +**Rationale**: S3-compatible, pre-signed URLs for security, scalable, already deployed + +### 6. JSON fields for extensibility +**Rationale**: `metadata_json`, `settings_json` allow adding attributes without migrations + +### 7. Soft deletes with status fields +**Rationale**: Audit trail preservation, recovery capability, referential integrity + +## User Roles (RBAC) + +| Role | Permissions | +|------|------------| +| **SUPER_ADMIN** | Full system access, all programs, user management | +| **PROGRAM_ADMIN** | Manage specific programs, rounds, projects, jury | +| **JURY_MEMBER** | View assigned projects only, submit evaluations, declare COI | +| **OBSERVER** | Read-only access to dashboards, all analytics/reports | +| **MENTOR** | View assigned projects, message applicants via `mentorProcedure` | +| **APPLICANT** | View own project status, upload documents per round, message mentor | + +## Important Constraints + +1. **Jury can only see assigned projects** - enforced at query level +2. **Voting windows are strict** - submissions blocked outside active window +3. **Evaluations are versioned** - edits create new versions +4. **All admin actions are audited** - immutable audit log +5. **Files accessed via pre-signed URLs** - no public bucket access +6. **Mobile responsiveness is mandatory** - every view must work on phones +7. **File downloads require project authorization** - jury/mentor must be assigned to the project +8. **Mentor endpoints require MENTOR role** - uses `mentorProcedure` middleware +9. **COI declaration required before evaluation** - blocking dialog gates evaluation form; admin reviews COI declarations +10. **Evaluation form supports multiple criterion types** - `numeric`, `text`, `boolean`, `section_header`; defaults to `numeric` for backward compatibility +11. **Smart assignment respects COI** - jurors with declared conflicts are skipped entirely; geo-diversity penalty and prior-round familiarity bonus applied +12. **Cron endpoints protected by CRON_SECRET** - `/api/cron/reminders` validates secret header +13. **Project status changes tracked** - every status update creates a `ProjectStatusHistory` record +14. **Per-round document management** - `ProjectFile` supports `roundId` scoping and `isLate` deadline tracking + +## Security Notes + +### CSRF Protection +tRPC mutations are protected against CSRF attacks because: +- tRPC uses `application/json` content type, which triggers CORS preflight on cross-origin requests +- Browsers block cross-origin JSON POSTs by default (Same-Origin Policy) +- NextAuth's own routes (`/api/auth/*`) have built-in CSRF token protection +- No custom CORS headers are configured to allow external origins + +**Do NOT add permissive CORS headers** (e.g., `Access-Control-Allow-Origin: *`) without also implementing explicit CSRF token validation on all mutation endpoints. + +### Rate Limiting +- tRPC API: 100 requests/minute per IP +- Auth endpoints: 10 POST requests/minute per IP +- Account lockout: 5 failed password attempts triggers 15-minute lockout + +## External Services (Pre-existing) + +These services are already running on the VPS in separate Docker Compose stacks: + +- **MinIO**: `http://localhost:9000` - S3-compatible storage +- **Poste.io**: `localhost:587` - SMTP server for emails +- **Nginx**: Host-level reverse proxy with SSL (certbot) + +The MOPC platform connects to these via environment variables. + +## Phase 1 Scope + +### In Scope +- Round management (create, configure, activate/close) +- Project import (CSV) and file uploads +- Jury invitation (magic link) +- Manual project assignment (single + bulk) +- Evaluation form (configurable criteria) +- Autosave + final submit +- Voting window enforcement +- Progress dashboards +- CSV export +- Audit logging +- **F1: Evaluation progress indicator** - sticky status bar with percentage tracking across criteria, global score, decision, feedback +- **F2: Export filtering results as CSV** - dynamic AI column flattening from `aiScreeningJson` +- **F3: Observer access to reports/analytics** - all 8 analytics procedures use `observerProcedure`; observer reports page with round selector, tabs, charts +- **F4: Countdown timer + email reminders** - live countdown with urgency colors; `EvaluationRemindersService` with cron endpoint (`/api/cron/reminders`) +- **F5: Conflict of Interest declaration** - `ConflictOfInterest` model; blocking dialog before evaluation; admin COI review page +- **F6: Bulk status update UI** - checkbox selection, floating toolbar, `ProjectStatusHistory` tracking +- **F7: AI-powered evaluation summary** - `EvaluationSummary` model; GPT-generated strengths/weaknesses, themes, scoring stats +- **F8: Smart assignment improvements** - `geoDiversityPenalty`, `previousRoundFamiliarity`, `coiPenalty` scoring factors +- **F9: Evaluation form flexibility** - extended criterion types (`numeric`, `text`, `boolean`, `section_header`); conditional visibility, section grouping +- **F10: Applicant portal enhancements** - `ProjectStatusHistory` timeline; per-round document management (`roundId` + `isLate` on `ProjectFile`); `MentorMessage` model for mentor-applicant chat + +### Out of Scope (Phase 2+) +- Typeform/Notion integrations +- WhatsApp notifications +- Learning hub +- Partner modules +- Public website + +## Testing Strategy + +- **Unit Tests**: Business logic, utilities, validators +- **Integration Tests**: tRPC routers with test database +- **E2E Tests**: Critical user flows (Playwright) +- **Manual Testing**: Responsive design on real devices + +## Documentation Links + +- [Architecture Overview](./docs/architecture/README.md) +- [Database Design](./docs/architecture/database.md) +- [API Design](./docs/architecture/api.md) +- [Infrastructure](./docs/architecture/infrastructure.md) +- [UI/UX Patterns](./docs/architecture/ui.md) diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 944a911..eb8e122 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,327 +1,327 @@ -# MOPC Platform - Server Deployment Guide - -Deployment guide for the MOPC platform on a Linux VPS with Docker. - -**Domain**: `portal.monaco-opc.com` -**App Port**: 7600 (behind Nginx reverse proxy) -**CI/CD**: Gitea Actions (Ubuntu runner) builds and pushes Docker images - -## CI/CD Pipeline - -The app is built automatically by a Gitea runner on every push to `main`: - -1. Gitea Actions workflow builds the Docker image on Ubuntu -2. Image is pushed to the Gitea container registry -3. On the server, `docker compose up -d` refreshes the image and restarts the app - -### Gitea Setup - -Configure the following in your Gitea repository settings: - -**Repository Variables** (Settings > Actions > Variables): - -| Variable | Value | -|----------|-------| -| `REGISTRY_URL` | Your Gitea registry URL (e.g. `gitea.example.com/your-org`) | - -**Repository Secrets** (Settings > Actions > Secrets): - -| Secret | Value | -|--------|-------| -| `REGISTRY_USER` | Gitea username with registry access | -| `REGISTRY_PASSWORD` | Gitea access token or password | - -The workflow file is at `.gitea/workflows/build.yml`. - -## Prerequisites - -- Linux VPS (Ubuntu 22.04+ recommended) -- Docker Engine 24+ with Compose v2 -- Nginx installed on the host -- Certbot for SSL certificates - -### Install Docker (if needed) - -```bash -curl -fsSL https://get.docker.com | sh -sudo usermod -aG docker $USER -# Log out and back in -``` - -### Install Nginx & Certbot (if needed) - -```bash -sudo apt update -sudo apt install nginx certbot python3-certbot-nginx -``` - -## First-Time Deployment - -### 1. Clone the repository - -```bash -git clone /opt/mopc -cd /opt/mopc -``` - -### 2. Configure environment variables - -```bash -cp docker/.env.production docker/.env -nano docker/.env -``` - -Fill in all `CHANGE_ME` values. Generate secrets with: - -```bash -openssl rand -base64 32 -``` - -Required variables: - -| Variable | Description | -|----------|-------------| -| `REGISTRY_URL` | Gitea registry URL (e.g. `gitea.example.com/your-org`) | -| `DB_PASSWORD` | PostgreSQL password | -| `NEXTAUTH_SECRET` | Auth session secret (openssl rand) | -| `NEXTAUTH_URL` | `https://portal.monaco-opc.com` | -| `MINIO_ENDPOINT` | MinIO internal URL (e.g. `http://localhost:9000`) | -| `MINIO_ACCESS_KEY` | MinIO access key | -| `MINIO_SECRET_KEY` | MinIO secret key | -| `MINIO_BUCKET` | MinIO bucket name (`mopc-files`) | -| `SMTP_HOST` | SMTP server host | -| `SMTP_PORT` | SMTP port (587) | -| `SMTP_USER` | SMTP username | -| `SMTP_PASS` | SMTP password | -| `EMAIL_FROM` | Sender address | - -### 3. Run the deploy script - -```bash -chmod +x scripts/deploy.sh scripts/seed.sh scripts/update.sh -./scripts/deploy.sh -``` - -This will: -- Log in to the container registry -- Pull the latest app image -- Start PostgreSQL + the app -- Run database migrations automatically on startup -- Wait for the health check - -### 4. Seed the database (one time only) - -```bash -./scripts/seed.sh -``` - -This seeds: -- Super admin user (`matt.ciaccio@gmail.com`) -- System settings -- Program & Round 1 configuration -- Evaluation form -- All candidature data from CSV - -### 5. Set up Nginx - -```bash -sudo ln -s /opt/mopc/docker/nginx/mopc-platform.conf /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl reload nginx -``` - -### 6. Set up SSL - -```bash -sudo certbot --nginx -d portal.monaco-opc.com -``` - -Auto-renewal is configured by default. Test with: - -```bash -sudo certbot renew --dry-run -``` - -### 7. Verify - -```bash -curl https://portal.monaco-opc.com/api/health -``` - -Expected response: - -```json -{"status":"healthy","timestamp":"...","services":{"database":"connected"}} -``` - -## Updating the Platform - -After Gitea CI builds a new image (push to `main`): - -```bash -cd /opt/mopc -./scripts/update.sh -``` - -This pulls the latest image from the registry, restarts only the app container (PostgreSQL stays running), runs migrations via the entrypoint, and waits for the health check. - -Manual equivalent: - -```bash -cd /opt/mopc/docker -docker compose up -d --pull always --force-recreate app -``` - -`prisma migrate deploy` runs automatically in the container entrypoint before the app starts. - -## Manual Operations - -### View logs - -```bash -cd /opt/mopc/docker -docker compose logs -f app # App logs -docker compose logs -f postgres # Database logs -``` - -### Run migrations manually - -```bash -cd /opt/mopc/docker -docker compose exec app npx prisma migrate deploy -``` - -### Open a shell in the app container - -```bash -cd /opt/mopc/docker -docker compose exec app sh -``` - -### Restart services - -```bash -cd /opt/mopc/docker -docker compose restart app # App only -docker compose restart # All services -``` - -### Stop everything - -```bash -cd /opt/mopc/docker -docker compose down # Stop containers (data preserved) -docker compose down -v # Stop AND delete volumes (data lost!) -``` - -## Database Backups - -### Create a backup - -```bash -docker exec mopc-postgres pg_dump -U mopc mopc | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz -``` - -### Restore a backup - -```bash -gunzip < backup_20260130_020000.sql.gz | docker exec -i mopc-postgres psql -U mopc mopc -``` - -### Set up daily backups (cron) - -```bash -sudo mkdir -p /data/backups/mopc - -cat > /opt/mopc/scripts/backup-db.sh << 'SCRIPT' -#!/bin/bash -BACKUP_DIR=/data/backups/mopc -DATE=$(date +%Y%m%d_%H%M%S) -docker exec mopc-postgres pg_dump -U mopc mopc | gzip > $BACKUP_DIR/mopc_$DATE.sql.gz -find $BACKUP_DIR -name "mopc_*.sql.gz" -mtime +30 -delete -SCRIPT - -chmod +x /opt/mopc/scripts/backup-db.sh -echo "0 2 * * * /opt/mopc/scripts/backup-db.sh >> /var/log/mopc-backup.log 2>&1" | sudo tee /etc/cron.d/mopc-backup -``` - -## Architecture - -``` -Gitea CI (Ubuntu runner) - | - v (docker push) -Container Registry - | - v (docker pull) -Linux VPS - | - v -Nginx (host, port 443) -- SSL termination - | - v -mopc-app (Docker, port 7600) -- Next.js standalone - | - v -mopc-postgres (Docker, port 5432) -- PostgreSQL 16 - -External services (separate Docker stacks): - - MinIO (port 9000) -- S3-compatible file storage - - Poste.io (port 587) -- SMTP email -``` - -## Troubleshooting - -### App won't start - -```bash -cd /opt/mopc/docker -docker compose logs app -docker compose exec postgres pg_isready -U mopc -``` - -### Can't pull image - -```bash -# Re-authenticate with registry -docker login - -# Check image exists -docker pull /mopc-app:latest -``` - -### Migration fails - -```bash -# Check migration status -docker compose exec app npx prisma migrate status - -# Reset (DESTROYS DATA): -docker compose exec app npx prisma migrate reset -``` - -### SSL certificate issues - -```bash -sudo certbot certificates -sudo certbot renew --force-renewal -``` - -### Port conflict - -The app runs on port 7600. If something else uses it: - -```bash -sudo ss -tlnp | grep 7600 -``` - -## Security Checklist - -- [ ] SSL certificate active and auto-renewing -- [ ] `docker/.env` has strong, unique passwords -- [ ] `NEXTAUTH_SECRET` is randomly generated -- [ ] Gitea registry credentials secured -- [ ] Firewall allows only ports 80, 443, 22 -- [ ] Docker daemon not exposed to network -- [ ] Daily backups configured -- [ ] Nginx security headers active +# MOPC Platform - Server Deployment Guide + +Deployment guide for the MOPC platform on a Linux VPS with Docker. + +**Domain**: `portal.monaco-opc.com` +**App Port**: 7600 (behind Nginx reverse proxy) +**CI/CD**: Gitea Actions (Ubuntu runner) builds and pushes Docker images + +## CI/CD Pipeline + +The app is built automatically by a Gitea runner on every push to `main`: + +1. Gitea Actions workflow builds the Docker image on Ubuntu +2. Image is pushed to the Gitea container registry +3. On the server, `docker compose up -d` refreshes the image and restarts the app + +### Gitea Setup + +Configure the following in your Gitea repository settings: + +**Repository Variables** (Settings > Actions > Variables): + +| Variable | Value | +|----------|-------| +| `REGISTRY_URL` | Your Gitea registry URL (e.g. `gitea.example.com/your-org`) | + +**Repository Secrets** (Settings > Actions > Secrets): + +| Secret | Value | +|--------|-------| +| `REGISTRY_USER` | Gitea username with registry access | +| `REGISTRY_PASSWORD` | Gitea access token or password | + +The workflow file is at `.gitea/workflows/build.yml`. + +## Prerequisites + +- Linux VPS (Ubuntu 22.04+ recommended) +- Docker Engine 24+ with Compose v2 +- Nginx installed on the host +- Certbot for SSL certificates + +### Install Docker (if needed) + +```bash +curl -fsSL https://get.docker.com | sh +sudo usermod -aG docker $USER +# Log out and back in +``` + +### Install Nginx & Certbot (if needed) + +```bash +sudo apt update +sudo apt install nginx certbot python3-certbot-nginx +``` + +## First-Time Deployment + +### 1. Clone the repository + +```bash +git clone /opt/mopc +cd /opt/mopc +``` + +### 2. Configure environment variables + +```bash +cp docker/.env.production docker/.env +nano docker/.env +``` + +Fill in all `CHANGE_ME` values. Generate secrets with: + +```bash +openssl rand -base64 32 +``` + +Required variables: + +| Variable | Description | +|----------|-------------| +| `REGISTRY_URL` | Gitea registry URL (e.g. `gitea.example.com/your-org`) | +| `DB_PASSWORD` | PostgreSQL password | +| `NEXTAUTH_SECRET` | Auth session secret (openssl rand) | +| `NEXTAUTH_URL` | `https://portal.monaco-opc.com` | +| `MINIO_ENDPOINT` | MinIO internal URL (e.g. `http://localhost:9000`) | +| `MINIO_ACCESS_KEY` | MinIO access key | +| `MINIO_SECRET_KEY` | MinIO secret key | +| `MINIO_BUCKET` | MinIO bucket name (`mopc-files`) | +| `SMTP_HOST` | SMTP server host | +| `SMTP_PORT` | SMTP port (587) | +| `SMTP_USER` | SMTP username | +| `SMTP_PASS` | SMTP password | +| `EMAIL_FROM` | Sender address | + +### 3. Run the deploy script + +```bash +chmod +x scripts/deploy.sh scripts/seed.sh scripts/update.sh +./scripts/deploy.sh +``` + +This will: +- Log in to the container registry +- Pull the latest app image +- Start PostgreSQL + the app +- Run database migrations automatically on startup +- Wait for the health check + +### 4. Seed the database (one time only) + +```bash +./scripts/seed.sh +``` + +This seeds: +- Super admin user (`matt.ciaccio@gmail.com`) +- System settings +- Program & Round 1 configuration +- Evaluation form +- All candidature data from CSV + +### 5. Set up Nginx + +```bash +sudo ln -s /opt/mopc/docker/nginx/mopc-platform.conf /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +### 6. Set up SSL + +```bash +sudo certbot --nginx -d portal.monaco-opc.com +``` + +Auto-renewal is configured by default. Test with: + +```bash +sudo certbot renew --dry-run +``` + +### 7. Verify + +```bash +curl https://portal.monaco-opc.com/api/health +``` + +Expected response: + +```json +{"status":"healthy","timestamp":"...","services":{"database":"connected"}} +``` + +## Updating the Platform + +After Gitea CI builds a new image (push to `main`): + +```bash +cd /opt/mopc +./scripts/update.sh +``` + +This pulls the latest image from the registry, restarts only the app container (PostgreSQL stays running), runs migrations via the entrypoint, and waits for the health check. + +Manual equivalent: + +```bash +cd /opt/mopc/docker +docker compose up -d --pull always --force-recreate app +``` + +`prisma migrate deploy` runs automatically in the container entrypoint before the app starts. + +## Manual Operations + +### View logs + +```bash +cd /opt/mopc/docker +docker compose logs -f app # App logs +docker compose logs -f postgres # Database logs +``` + +### Run migrations manually + +```bash +cd /opt/mopc/docker +docker compose exec app npx prisma migrate deploy +``` + +### Open a shell in the app container + +```bash +cd /opt/mopc/docker +docker compose exec app sh +``` + +### Restart services + +```bash +cd /opt/mopc/docker +docker compose restart app # App only +docker compose restart # All services +``` + +### Stop everything + +```bash +cd /opt/mopc/docker +docker compose down # Stop containers (data preserved) +docker compose down -v # Stop AND delete volumes (data lost!) +``` + +## Database Backups + +### Create a backup + +```bash +docker exec mopc-postgres pg_dump -U mopc mopc | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz +``` + +### Restore a backup + +```bash +gunzip < backup_20260130_020000.sql.gz | docker exec -i mopc-postgres psql -U mopc mopc +``` + +### Set up daily backups (cron) + +```bash +sudo mkdir -p /data/backups/mopc + +cat > /opt/mopc/scripts/backup-db.sh << 'SCRIPT' +#!/bin/bash +BACKUP_DIR=/data/backups/mopc +DATE=$(date +%Y%m%d_%H%M%S) +docker exec mopc-postgres pg_dump -U mopc mopc | gzip > $BACKUP_DIR/mopc_$DATE.sql.gz +find $BACKUP_DIR -name "mopc_*.sql.gz" -mtime +30 -delete +SCRIPT + +chmod +x /opt/mopc/scripts/backup-db.sh +echo "0 2 * * * /opt/mopc/scripts/backup-db.sh >> /var/log/mopc-backup.log 2>&1" | sudo tee /etc/cron.d/mopc-backup +``` + +## Architecture + +``` +Gitea CI (Ubuntu runner) + | + v (docker push) +Container Registry + | + v (docker pull) +Linux VPS + | + v +Nginx (host, port 443) -- SSL termination + | + v +mopc-app (Docker, port 7600) -- Next.js standalone + | + v +mopc-postgres (Docker, port 5432) -- PostgreSQL 16 + +External services (separate Docker stacks): + - MinIO (port 9000) -- S3-compatible file storage + - Poste.io (port 587) -- SMTP email +``` + +## Troubleshooting + +### App won't start + +```bash +cd /opt/mopc/docker +docker compose logs app +docker compose exec postgres pg_isready -U mopc +``` + +### Can't pull image + +```bash +# Re-authenticate with registry +docker login + +# Check image exists +docker pull /mopc-app:latest +``` + +### Migration fails + +```bash +# Check migration status +docker compose exec app npx prisma migrate status + +# Reset (DESTROYS DATA): +docker compose exec app npx prisma migrate reset +``` + +### SSL certificate issues + +```bash +sudo certbot certificates +sudo certbot renew --force-renewal +``` + +### Port conflict + +The app runs on port 7600. If something else uses it: + +```bash +sudo ss -tlnp | grep 7600 +``` + +## Security Checklist + +- [ ] SSL certificate active and auto-renewing +- [ ] `docker/.env` has strong, unique passwords +- [ ] `NEXTAUTH_SECRET` is randomly generated +- [ ] Gitea registry credentials secured +- [ ] Firewall allows only ports 80, 443, 22 +- [ ] Docker daemon not exposed to network +- [ ] Daily backups configured +- [ ] Nginx security headers active diff --git a/Notes.md b/Notes.md index f4e07e9..9dc9651 100644 --- a/Notes.md +++ b/Notes.md @@ -1,402 +1,402 @@ -Below is a “technical requirements” rendering (not an architecture diagram), structured so you can hand it to a dev team and derive system architecture + backlog from it. Phase 1 is the only critical deliverable; Phase 2+ are explicitly extendable. - ---- - -## 0) Product scope and phasing - -### Phase 1 (critical, delivery in ~2 weeks) - -**Secure Jury Online Voting Module** to run two selection rounds: - -* Round 1: ~130 projects → ~60 semi-finalists (Feb 18–23 voting window) -* Round 2: ~60 projects → 6 finalists (~April 13 week voting window) -* Voting is asynchronous, online, with assigned project access, scoring + feedback capture, and reporting dashboards. - -### Phase 2+ (mid-term) - -Centralized MOPC platform: - -* Applications/projects database -* Document management (MinIO S3) -* Jury spaces (history, comments, scoring) -* Learning hub / resources -* Communication workflows (email + possibly WhatsApp) -* Partner/sponsor visibility modules -* Potential website integration / shared back office - ---- - -## 1) Users, roles, permissions (RBAC) - -### Core roles - -1. **Platform Super Admin** - - * Full system configuration, security policies, integrations, user/role management, data export, audit access. -2. **Program Admin (MOPC Admin)** - - * Manages cycles/rounds, projects, jury members, assignments, voting windows, criteria forms, dashboards, exports. -3. **Jury Member** - - * Can access only assigned projects for active rounds; submit evaluations; view own submitted evaluations; optionally view aggregated results only if permitted. -4. **Read-only Observer (optional)** - - * Internal meeting viewer: can see dashboards/aggregates but cannot edit votes. - -### Permission model requirements - -* **Least privilege by default** -* **Round-scoped permissions**: access can be constrained per selection round/cycle. -* **Project-scoped access control**: jury sees only assigned projects (unless admin toggles “all projects visible”). -* **Admin override controls**: reassign projects, revoke access, reopen/lock evaluations, extend voting windows, invalidate votes with reason logging. - ---- - -## 2) Core domain objects (data model concepts) - -### Entities - -* **Program** (e.g., “MOPC 2026”) -* **Selection Cycle / Round** - - * Attributes: name, start/end of voting window, status (draft/active/closed/archived), required reviews per project (default ≥3), scoring form version, jury cohort. -* **Project** - - * Attributes: title, team name, description, tags, status (submitted/eligible/assigned/semi-finalist/finalist/etc.), submission metadata, external IDs (Typeform/Notion), files (exec summary, PDF deck, intro video). -* **File Asset** - - * Stored in MinIO (S3-compatible): object key, bucket, version/etag, mime type, size, upload timestamp, retention policy, access policy. -* **Jury Member** - - * Profile: name, email, organization (optional), role, expertise tags, status (invited/active/suspended). -* **Expertise Tag** - - * Managed vocabulary or free-form with admin approval. -* **Assignment** - - * Connects Jury Member ↔ Project ↔ Round - * Attributes: assignment method (manual/auto), created by, created timestamp, required review flag, completion status. -* **Evaluation (Vote)** - - * Per assignment: criterion scores + global score + binary decision + qualitative feedback - * Metadata: submitted_at, last_edited_at, finalization flag, versioning, IP/user-agent logging (optional), conflict handling. -* **Audit Log** - - * Immutable events: login, permission changes, voting window changes, assignments, overrides, exports, vote invalidations. - ---- - -## 3) Phase 1 functional requirements - -### 3.1 Jury authentication & access - -* Invite flow: - - * Admin imports jury list (CSV) or adds manually. - * System sends invitation email with secure link + account activation. -* Authentication options (choose one for Phase 1, keep others pluggable): - - * Email magic link (recommended for speed) - * Password + MFA optional -* Session requirements: - - * Configurable session duration - * Forced logout on role revocation -* Access gating: - - * Jury can only view projects for **active** rounds and only those assigned. - -### 3.2 Project ingestion & management - -Phase 1 can support either: - -* **Option A (fastest): Manual import** - - * Admin uploads CSV with project metadata + file links or uploads. -* **Option B (semi-integrated): Sync from Notion/Typeform** - - * Read projects from existing Notion DB and/or Typeform export. - -Minimum capabilities: - -* Admin CRUD on projects (create/update/archive) -* Project tagging (from “Which issue does your project address?” + additional admin tags) -* Attach required assets: - - * Executive summary (PDF/doc) - * PDF presentation - * 30s intro video (mp4) -* File storage via MinIO (see Section 6) - -### 3.3 Assignment system (≥3 reviews/project) - -Admin can: - -* Manually assign projects to jury members (bulk assign supported) -* Auto-assign (optional but strongly recommended): - - * Input: jury expertise tags + project tags + constraints - * Constraints: - - * Each project assigned to at least N jurors (N configurable; default 3) - * Load balancing across jurors (minimize variance) - * Avoid conflicts (optional): disallow assignment if juror marked conflict with project - * Output: assignment set + summary metrics (coverage, per-juror load, unmatched tags) -* Reassignment rules: - - * Admin can reassign at any time - * If an evaluation exists, admin can: - - * keep existing evaluation tied to original juror - * or invalidate/lock it (requires reason + audit event) - -### 3.4 Evaluation form & scoring logic - -Per project evaluation must capture: - -* **Criterion scores** (scale-based, define exact scale as configurable; e.g., 1–5 or 1–10) - - 1. Need clarity - 2. Solution relevance - 3. Gap analysis (market/competitors) - 4. Target customers clarity - 5. Ocean impact -* **Global score**: 1–10 -* **Binary decision**: “Select as semi-finalist?” (Yes/No) -* **Qualitative feedback**: long text - -Form requirements: - -* Admin-configurable criteria text, ordering, scales, and whether fields are mandatory -* Autosave drafts -* Final submit locks evaluation by default (admin can allow edits until window closes) -* Support multiple rounds with potentially different forms (versioned forms per round) - -### 3.5 Voting windows and enforcement (must-have) - -Admins must be able to configure and enforce: - -* Voting window start/end **per round** (date-time, timezone-aware) -* States: - - * Draft (admins only) - * Active (jury can submit) - * Closed (jury read-only) - * Archived (admin/export only) -* Enforcement rules: - - * Jury cannot submit outside the active window - * Admin “grace period” toggle to accept late submissions for specific jurors/projects - * Admin can extend the window (global or subset) with audit logging -* Dashboard countdown + clear messaging for jurors - -### 3.6 Dashboards & outputs - -Must produce: - -* **Jury member view** - - * Assigned projects list, completion status, quick access to files, evaluation status (not started/draft/submitted) -* **Admin dashboards** - - * Coverage: projects with (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /accept-invite couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} +Auth check failed in auth layout: Error: Dynamic server usage: Route /error couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error + at s (C:\Repos\MOPC\.next\server\chunks\4586.js:1:28328) + at m (C:\Repos\MOPC\.next\server\chunks\2171.js:437:9047) + at (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /error couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} + Generating static pages (9/37) +Auth check failed in auth layout: Error: Dynamic server usage: Route /verify-email couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error + at s (C:\Repos\MOPC\.next\server\chunks\4586.js:1:28328) + at m (C:\Repos\MOPC\.next\server\chunks\2171.js:437:9047) + at (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /verify-email couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} +Auth check failed in auth layout: Error: Dynamic server usage: Route /verify couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error + at s (C:\Repos\MOPC\.next\server\chunks\4586.js:1:28328) + at m (C:\Repos\MOPC\.next\server\chunks\2171.js:437:9047) + at (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /verify couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} +Auth check failed in auth layout: Error: Dynamic server usage: Route /onboarding couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error + at s (C:\Repos\MOPC\.next\server\chunks\4586.js:1:28328) + at m (C:\Repos\MOPC\.next\server\chunks\2171.js:437:9047) + at (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /onboarding couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} +Auth check failed in auth layout: Error: Dynamic server usage: Route /login couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error + at s (C:\Repos\MOPC\.next\server\chunks\4586.js:1:28328) + at m (C:\Repos\MOPC\.next\server\chunks\2171.js:437:9047) + at (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /login couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} +Auth check failed in auth layout: Error: Dynamic server usage: Route /set-password couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error + at s (C:\Repos\MOPC\.next\server\chunks\4586.js:1:28328) + at m (C:\Repos\MOPC\.next\server\chunks\2171.js:437:9047) + at (C:\Repos\MOPC\.next\server\chunks\2171.js:404:57912) + at h (C:\Repos\MOPC\.next\server\app\(auth)\error\page.js:1:4755) + at stringify () { + description: "Route /set-password couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error", + digest: 'DYNAMIC_SERVER_USAGE' +} + Generating static pages (18/37) + Generating static pages (27/37) + ✓ Generating static pages (37/37) + Finalizing page optimization ... + Collecting build traces ... + +Route (app) Size First Load JS +┌ ƒ / 182 B 112 kB +├ ○ /_not-found 171 B 103 kB +├ ƒ /accept-invite 5.17 kB 141 kB +├ ƒ /admin 3.54 kB 275 kB +├ ƒ /admin/audit 8.76 kB 172 kB +├ ƒ /admin/awards 4.82 kB 141 kB +├ ƒ /admin/awards/[id] 13.2 kB 196 kB +├ ƒ /admin/awards/[id]/edit 6.02 kB 182 kB +├ ƒ /admin/awards/new 5.71 kB 182 kB +├ ƒ /admin/learning 180 B 106 kB +├ ƒ /admin/learning/[id] 10.5 kB 190 kB +├ ƒ /admin/learning/new 7.85 kB 184 kB +├ ƒ /admin/members 12.5 kB 191 kB +├ ƒ /admin/members/[id] 5.71 kB 197 kB +├ ƒ /admin/members/invite 6.6 kB 188 kB +├ ƒ /admin/mentors 171 B 103 kB +├ ƒ /admin/mentors/[id] 171 B 103 kB +├ ƒ /admin/partners 180 B 106 kB +├ ƒ /admin/partners/[id] 7.44 kB 187 kB +├ ƒ /admin/partners/new 4.2 kB 181 kB +├ ƒ /admin/programs 2.47 kB 147 kB +├ ƒ /admin/programs/[id] 180 B 106 kB +├ ƒ /admin/programs/[id]/apply-settings 12.4 kB 224 kB +├ ƒ /admin/programs/[id]/edit 6.22 kB 186 kB +├ ƒ /admin/programs/new 4.83 kB 150 kB +├ ƒ /admin/projects 16.9 kB 207 kB +├ ƒ /admin/projects/[id] 10.1 kB 205 kB +├ ƒ /admin/projects/[id]/edit 7.67 kB 220 kB +├ ƒ /admin/projects/[id]/mentor 8.78 kB 154 kB +├ ƒ /admin/projects/import 10.5 kB 201 kB +├ ƒ /admin/projects/new 4.42 kB 195 kB +├ ƒ /admin/projects/pool 6.56 kB 186 kB +├ ƒ /admin/reports 4.6 kB 308 kB +├ ƒ /admin/rounds 9.6 kB 211 kB +├ ƒ /admin/rounds/[id] 16.4 kB 210 kB +├ ƒ /admin/rounds/[id]/assignments 16.2 kB 196 kB +├ ƒ /admin/rounds/[id]/coi 8.73 kB 188 kB +├ ƒ /admin/rounds/[id]/edit 10.2 kB 240 kB +├ ƒ /admin/rounds/[id]/filtering 504 B 103 kB +├ ƒ /admin/rounds/[id]/filtering/results 7.69 kB 187 kB +├ ƒ /admin/rounds/[id]/filtering/rules 8.18 kB 188 kB +├ ƒ /admin/rounds/[id]/live-voting 8.68 kB 169 kB +├ ƒ /admin/rounds/new 3.72 kB 227 kB +├ ƒ /admin/settings 21.6 kB 226 kB +├ ƒ /admin/settings/tags 8.33 kB 214 kB +├ ƒ /api/auth/[...nextauth] 171 B 103 kB +├ ƒ /api/cron/reminders 171 B 103 kB +├ ƒ /api/email/change-password 171 B 103 kB +├ ƒ /api/email/verify-credentials 171 B 103 kB +├ ƒ /api/health 171 B 103 kB +├ ƒ /api/storage/local 171 B 103 kB +├ ƒ /api/trpc/[trpc] 171 B 103 kB +├ ƒ /apply/[slug] 954 B 387 kB +├ ƒ /apply/edition/[programSlug] 959 B 388 kB +├ ○ /email/change-password 6.79 kB 118 kB +├ ƒ /error 4.01 kB 118 kB +├ ƒ /jury 4.37 kB 119 kB +├ ƒ /jury/assignments 180 B 106 kB +├ ƒ /jury/awards 3.11 kB 139 kB +├ ƒ /jury/awards/[id] 5.59 kB 151 kB +├ ƒ /jury/learning 5.09 kB 137 kB +├ ƒ /jury/live/[sessionId] 7.21 kB 149 kB +├ ƒ /jury/projects/[id] 4.12 kB 144 kB +├ ƒ /jury/projects/[id]/evaluate 13.2 kB 225 kB +├ ƒ /jury/projects/[id]/evaluation 2.09 kB 116 kB +├ ƒ /live-scores/[sessionId] 6.93 kB 139 kB +├ ƒ /login 6.09 kB 120 kB +├ ƒ /mentor 7.77 kB 144 kB +├ ƒ /mentor/projects 5.51 kB 141 kB +├ ƒ /mentor/projects/[id] 8.58 kB 148 kB +├ ƒ /mentor/resources 5.12 kB 137 kB +├ ƒ /my-submission 6.82 kB 146 kB +├ ƒ /my-submission/[id] 11.7 kB 155 kB +├ ƒ /my-submission/[id]/team 8 kB 216 kB +├ ƒ /observer 2.98 kB 114 kB +├ ƒ /observer/reports 5.63 kB 309 kB +├ ƒ /onboarding 5.44 kB 313 kB +├ ƒ /set-password 7.55 kB 143 kB +├ ƒ /settings/profile 4.25 kB 210 kB +├ ƒ /verify 180 B 106 kB +└ ƒ /verify-email 171 B 103 kB ++ First Load JS shared by all 103 kB + ├ chunks/1255-39d374166396f9e9.js 45.7 kB + ├ chunks/4bd1b696-100b9d70ed4e49c1.js 54.2 kB + └ other shared chunks (total) 2.87 kB + + +ƒ Middleware 86.5 kB + +○ (Static) prerendered as static content +ƒ (Dynamic) server-rendered on demand + diff --git a/docker/Dockerfile b/docker/Dockerfile index 357ae6f..6d6d1d0 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,73 +1,73 @@ -# ============================================================================= -# MOPC Platform - Production Dockerfile -# ============================================================================= -# Multi-stage build for optimized production image - -FROM node:22-alpine AS base - -# Install dependencies only when needed -FROM base AS deps -RUN apk add --no-cache libc6-compat -WORKDIR /app - -# Copy package files -COPY package.json package-lock.json* ./ -RUN npm ci - -# Rebuild the source code only when needed -FROM base AS builder -WORKDIR /app -COPY --from=deps /app/node_modules ./node_modules -COPY . . - -# Generate Prisma client -RUN npx prisma generate - -# Build Next.js -ENV NEXT_TELEMETRY_DISABLED=1 -RUN npm run build - -# Production image, copy all the files and run next -FROM base AS runner -WORKDIR /app - -ENV NODE_ENV=production -ENV NEXT_TELEMETRY_DISABLED=1 - -# Create non-root user for security -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nextjs - -# Install runtime dependencies for migrations and seeding -RUN apk add --no-cache libc6-compat - -# Copy built Next.js standalone output -COPY --from=builder /app/public ./public -COPY --from=builder /app/.next/standalone ./ -COPY --from=builder /app/.next/static ./.next/static - -# Copy full node_modules for prisma migrations and seeding -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/prisma ./prisma -COPY --from=builder /app/package.json ./package.json - -# Copy files needed for seeding (tsx needs tsconfig for path resolution) -COPY --from=builder /app/docs/Candidatures2026.csv ./docs/Candidatures2026.csv -COPY --from=builder /app/tsconfig.json ./tsconfig.json - -# Copy entrypoint script -COPY docker/docker-entrypoint.sh /app/docker-entrypoint.sh -RUN chmod +x /app/docker-entrypoint.sh - -# Set correct permissions -RUN chown -R nextjs:nodejs /app - -USER nextjs - -EXPOSE 7600 - -ENV PORT=7600 -ENV HOSTNAME="0.0.0.0" - -# Run via entrypoint (migrate then start) -CMD ["/app/docker-entrypoint.sh"] +# ============================================================================= +# MOPC Platform - Production Dockerfile +# ============================================================================= +# Multi-stage build for optimized production image + +FROM node:22-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Copy package files +COPY package.json package-lock.json* ./ +RUN npm ci + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Generate Prisma client +RUN npx prisma generate + +# Build Next.js +ENV NEXT_TELEMETRY_DISABLED=1 +RUN npm run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +# Create non-root user for security +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Install runtime dependencies for migrations and seeding +RUN apk add --no-cache libc6-compat + +# Copy built Next.js standalone output +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +# Copy full node_modules for prisma migrations and seeding +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/prisma ./prisma +COPY --from=builder /app/package.json ./package.json + +# Copy files needed for seeding (tsx needs tsconfig for path resolution) +COPY --from=builder /app/docs/Candidatures2026.csv ./docs/Candidatures2026.csv +COPY --from=builder /app/tsconfig.json ./tsconfig.json + +# Copy entrypoint script +COPY docker/docker-entrypoint.sh /app/docker-entrypoint.sh +RUN chmod +x /app/docker-entrypoint.sh + +# Set correct permissions +RUN chown -R nextjs:nodejs /app + +USER nextjs + +EXPOSE 7600 + +ENV PORT=7600 +ENV HOSTNAME="0.0.0.0" + +# Run via entrypoint (migrate then start) +CMD ["/app/docker-entrypoint.sh"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0a90e7d..c5a4da6 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,84 +1,84 @@ -# ============================================================================= -# MOPC Platform - Production Docker Compose -# ============================================================================= -# This stack contains only the Next.js app and PostgreSQL. -# MinIO and Poste.io are external services connected via environment variables. -# -# The app image is built by Gitea CI and pushed to the container registry. -# `pull_policy: always` ensures `docker compose up -d` checks for newer app images. -# The app entrypoint runs `prisma migrate deploy` before starting Next.js. - -services: - app: - image: ${REGISTRY_URL}/mopc-app:latest - pull_policy: always - container_name: mopc-app - restart: unless-stopped - dns: - - 8.8.8.8 - - 8.8.4.4 - ports: - - "127.0.0.1:7600:7600" - env_file: - - .env - environment: - - NODE_ENV=production - - DATABASE_URL=postgresql://mopc:${DB_PASSWORD}@postgres:5432/mopc - - NEXTAUTH_URL=${NEXTAUTH_URL} - - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} - - AUTH_SECRET=${NEXTAUTH_SECRET} - - AUTH_TRUST_HOST=true - - MINIO_ENDPOINT=${MINIO_ENDPOINT} - - MINIO_PUBLIC_ENDPOINT=${MINIO_PUBLIC_ENDPOINT:-} - - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} - - MINIO_SECRET_KEY=${MINIO_SECRET_KEY} - - MINIO_BUCKET=${MINIO_BUCKET} - - SMTP_HOST=${SMTP_HOST} - - SMTP_PORT=${SMTP_PORT} - - SMTP_USER=${SMTP_USER} - - SMTP_PASS=${SMTP_PASS} - - EMAIL_FROM=${EMAIL_FROM} - - POSTE_API_URL=${POSTE_API_URL:-https://mail.monaco-opc.com} - - POSTE_ADMIN_EMAIL=${POSTE_ADMIN_EMAIL} - - POSTE_ADMIN_PASSWORD=${POSTE_ADMIN_PASSWORD} - - POSTE_MAIL_DOMAIN=${POSTE_MAIL_DOMAIN:-monaco-opc.com} - - OPENAI_API_KEY=${OPENAI_API_KEY:-} - - OPENAI_MODEL=${OPENAI_MODEL:-gpt-4o} - - MAX_FILE_SIZE=${MAX_FILE_SIZE:-524288000} - depends_on: - postgres: - condition: service_healthy - networks: - - mopc-network - healthcheck: - test: ["CMD", "node", "-e", "fetch('http://localhost:7600/api/health').then(r=>{if(!r.ok)throw r;process.exit(0)}).catch(()=>process.exit(1))"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 60s - - postgres: - image: postgres:16-alpine - container_name: mopc-postgres - restart: unless-stopped - environment: - - POSTGRES_USER=mopc - - POSTGRES_PASSWORD=${DB_PASSWORD} - - POSTGRES_DB=mopc - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U mopc"] - interval: 10s - timeout: 5s - retries: 5 - networks: - - mopc-network - -volumes: - postgres_data: - driver: local - -networks: - mopc-network: - driver: bridge +# ============================================================================= +# MOPC Platform - Production Docker Compose +# ============================================================================= +# This stack contains only the Next.js app and PostgreSQL. +# MinIO and Poste.io are external services connected via environment variables. +# +# The app image is built by Gitea CI and pushed to the container registry. +# `pull_policy: always` ensures `docker compose up -d` checks for newer app images. +# The app entrypoint runs `prisma migrate deploy` before starting Next.js. + +services: + app: + image: ${REGISTRY_URL}/mopc-app:latest + pull_policy: always + container_name: mopc-app + restart: unless-stopped + dns: + - 8.8.8.8 + - 8.8.4.4 + ports: + - "127.0.0.1:7600:7600" + env_file: + - .env + environment: + - NODE_ENV=production + - DATABASE_URL=postgresql://mopc:${DB_PASSWORD}@postgres:5432/mopc + - NEXTAUTH_URL=${NEXTAUTH_URL} + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} + - AUTH_SECRET=${NEXTAUTH_SECRET} + - AUTH_TRUST_HOST=true + - MINIO_ENDPOINT=${MINIO_ENDPOINT} + - MINIO_PUBLIC_ENDPOINT=${MINIO_PUBLIC_ENDPOINT:-} + - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} + - MINIO_SECRET_KEY=${MINIO_SECRET_KEY} + - MINIO_BUCKET=${MINIO_BUCKET} + - SMTP_HOST=${SMTP_HOST} + - SMTP_PORT=${SMTP_PORT} + - SMTP_USER=${SMTP_USER} + - SMTP_PASS=${SMTP_PASS} + - EMAIL_FROM=${EMAIL_FROM} + - POSTE_API_URL=${POSTE_API_URL:-https://mail.monaco-opc.com} + - POSTE_ADMIN_EMAIL=${POSTE_ADMIN_EMAIL} + - POSTE_ADMIN_PASSWORD=${POSTE_ADMIN_PASSWORD} + - POSTE_MAIL_DOMAIN=${POSTE_MAIL_DOMAIN:-monaco-opc.com} + - OPENAI_API_KEY=${OPENAI_API_KEY:-} + - OPENAI_MODEL=${OPENAI_MODEL:-gpt-4o} + - MAX_FILE_SIZE=${MAX_FILE_SIZE:-524288000} + depends_on: + postgres: + condition: service_healthy + networks: + - mopc-network + healthcheck: + test: ["CMD", "node", "-e", "fetch('http://localhost:7600/api/health').then(r=>{if(!r.ok)throw r;process.exit(0)}).catch(()=>process.exit(1))"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + + postgres: + image: postgres:16-alpine + container_name: mopc-postgres + restart: unless-stopped + environment: + - POSTGRES_USER=mopc + - POSTGRES_PASSWORD=${DB_PASSWORD} + - POSTGRES_DB=mopc + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U mopc"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - mopc-network + +volumes: + postgres_data: + driver: local + +networks: + mopc-network: + driver: bridge diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 5767050..e9982bb 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -1,37 +1,37 @@ -#!/bin/sh -set -eu - -MAX_MIGRATION_RETRIES="${MIGRATION_MAX_RETRIES:-30}" -MIGRATION_RETRY_DELAY_SECONDS="${MIGRATION_RETRY_DELAY_SECONDS:-2}" -ATTEMPT=1 - -echo "==> Running database migrations (with retry)..." -until npx prisma migrate deploy; do - if [ "$ATTEMPT" -ge "$MAX_MIGRATION_RETRIES" ]; then - echo "ERROR: Migration failed after ${MAX_MIGRATION_RETRIES} attempts." - exit 1 - fi - echo "Migration attempt ${ATTEMPT} failed. Retrying in ${MIGRATION_RETRY_DELAY_SECONDS}s..." - ATTEMPT=$((ATTEMPT + 1)) - sleep "$MIGRATION_RETRY_DELAY_SECONDS" -done - -echo "==> Generating Prisma client..." -npx prisma generate - -# Auto-seed on first startup: check if Users table is empty -USER_COUNT=$(node -e " - const { PrismaClient } = require('@prisma/client'); - const p = new PrismaClient(); - p.user.count().then(c => { console.log(c); p.\$disconnect(); }).catch(() => { console.log('0'); p.\$disconnect(); }); -" 2>/dev/null || echo "0") - -if [ "$USER_COUNT" = "0" ]; then - echo "==> Empty database detected — running seed..." - npx prisma db seed || echo "WARNING: Seed script failed." -else - echo "==> Database already seeded ($USER_COUNT users found), skipping seed." -fi - -echo "==> Starting application..." -exec node server.js +#!/bin/sh +set -eu + +MAX_MIGRATION_RETRIES="${MIGRATION_MAX_RETRIES:-30}" +MIGRATION_RETRY_DELAY_SECONDS="${MIGRATION_RETRY_DELAY_SECONDS:-2}" +ATTEMPT=1 + +echo "==> Running database migrations (with retry)..." +until npx prisma migrate deploy; do + if [ "$ATTEMPT" -ge "$MAX_MIGRATION_RETRIES" ]; then + echo "ERROR: Migration failed after ${MAX_MIGRATION_RETRIES} attempts." + exit 1 + fi + echo "Migration attempt ${ATTEMPT} failed. Retrying in ${MIGRATION_RETRY_DELAY_SECONDS}s..." + ATTEMPT=$((ATTEMPT + 1)) + sleep "$MIGRATION_RETRY_DELAY_SECONDS" +done + +echo "==> Generating Prisma client..." +npx prisma generate + +# Auto-seed on first startup: check if Users table is empty +USER_COUNT=$(node -e " + const { PrismaClient } = require('@prisma/client'); + const p = new PrismaClient(); + p.user.count().then(c => { console.log(c); p.\$disconnect(); }).catch(() => { console.log('0'); p.\$disconnect(); }); +" 2>/dev/null || echo "0") + +if [ "$USER_COUNT" = "0" ]; then + echo "==> Empty database detected — running seed..." + npx prisma db seed || echo "WARNING: Seed script failed." +else + echo "==> Database already seeded ($USER_COUNT users found), skipping seed." +fi + +echo "==> Starting application..." +exec node server.js diff --git a/docs/Notes/notes-prototype-1.md b/docs/Notes/notes-prototype-1.md index d6bddba..ee996d4 100644 --- a/docs/Notes/notes-prototype-1.md +++ b/docs/Notes/notes-prototype-1.md @@ -1,15 +1,15 @@ -Notes: Filtering Round: Criteria- Older than 3 years (for all in the startup category), those who submit something random (like a spam project) (AI?) - --Add filters to the page (who sent documents, etc.) - --Partners section should be a semi-crm system to track possible sponsors and partners - --No translation into french (no localization) - --Ameliorate the user experience (make it more simple) - --Special Awards- Specific Jury Members (jury members will have to choose amongst projects that fit specific criteria (like the country they're based))- Spotlight on Africa, Coup de Coeur - Make a special award section and make a special case for judge invitation for special awards and allow us to make special awards and assign them to the selection of judges for the special awards specifically (And give them their own login space to see everything) --Invite jury member (with tag for special awards) --> Make special award (Criteria needed, Add a tag for special award (so for example, if a location is italy it will auto have the tag for COup de Coeur (since it's criteria is it only exists in certain countries))) - This is also a separate Jury Round - Use AI to sort through elligible projects based on the plain-language criteria (so the AI interprets the criteria and all projects and smart-assigns them to the round) - Make sure this round allows them to simply choose which project will win (since they have independent criteria) - Make a mix of voting for which project wins the project (or recommended project for the award), but also in the round they can simply assign a project to the award without any criteria requirements and such - - - +Notes: Filtering Round: Criteria- Older than 3 years (for all in the startup category), those who submit something random (like a spam project) (AI?) + +-Add filters to the page (who sent documents, etc.) + +-Partners section should be a semi-crm system to track possible sponsors and partners + +-No translation into french (no localization) + +-Ameliorate the user experience (make it more simple) + +-Special Awards- Specific Jury Members (jury members will have to choose amongst projects that fit specific criteria (like the country they're based))- Spotlight on Africa, Coup de Coeur - Make a special award section and make a special case for judge invitation for special awards and allow us to make special awards and assign them to the selection of judges for the special awards specifically (And give them their own login space to see everything) +-Invite jury member (with tag for special awards) --> Make special award (Criteria needed, Add a tag for special award (so for example, if a location is italy it will auto have the tag for COup de Coeur (since it's criteria is it only exists in certain countries))) - This is also a separate Jury Round - Use AI to sort through elligible projects based on the plain-language criteria (so the AI interprets the criteria and all projects and smart-assigns them to the round) - Make sure this round allows them to simply choose which project will win (since they have independent criteria) - Make a mix of voting for which project wins the project (or recommended project for the award), but also in the round they can simply assign a project to the award without any criteria requirements and such + + + diff --git a/docs/platform-review.md b/docs/platform-review.md index be67866..6376b82 100644 --- a/docs/platform-review.md +++ b/docs/platform-review.md @@ -1,1836 +1,1836 @@ -# MOPC Platform Review - -> **Status Legend**: Each finding is marked with its implementation status: -> - **DONE** - Implemented and verified -> - **DEFERRED** - Cannot be done now (requires infrastructure, design decisions, or is too risky) -> - **N/A** - Not actionable (positive observation or informational) -> - **SKIPPED** - Intentionally not addressed (low impact or not worth the risk) - -## 1. UI/UX Design Review - -**Reviewer**: UI/UX Design Reviewer -**Date**: 2026-02-05 -**Scope**: All pages, components, design patterns, mobile responsiveness, UX states, information architecture, interaction patterns, accessibility, visual polish - ---- - -### Overall Assessment - -The MOPC platform demonstrates strong foundational UI/UX work. shadcn/ui provides a consistent base, skeleton loading states are implemented throughout, and the evaluation form offers excellent UX with autosave and slider+button scoring. However, there are meaningful gaps in mobile responsiveness, navigation consistency, typography adherence, and error states that should be addressed before a public-facing launch. - ---- - -### 1.1 Design System & Theming - -#### DS-1: Public layout uses Inter font instead of Montserrat (Medium) — **DONE** - -**File**: `src/app/(public)/layout.tsx:4-5` - -The public layout imports Google's Inter font and applies it to the entire public section. The brand identity specifies Montserrat as the platform typeface (defined in `globals.css` via `@font-face`). Every other layout uses the root font (Montserrat via `font-sans`), but public pages render in Inter. - -```tsx -import { Inter } from 'next/font/google' -const inter = Inter({ subsets: ['latin'] }) -``` - -**Impact**: Brand inconsistency on the most externally-visible pages. - -**Recommendation**: Remove the Inter import and use the existing Montserrat font from the root layout. Apply `className="font-sans"` if needed. - ---- - -#### DS-2: Public layout uses placeholder logo instead of MOPC logo component (Low) — **DONE** - -**File**: `src/app/(public)/layout.tsx:20-22` - -The public layout renders a hardcoded `
` with "M" text instead of using the existing `Logo` component at `src/components/shared/logo.tsx`. - -```tsx -
- M -
-``` - -**Recommendation**: Import and use the `Logo` component with `variant="small"`. - ---- - -#### DS-3: Dark mode CSS defined but no toggle exposed (Low) — **DONE** - -**File**: `src/app/globals.css` (dark mode variables block) - -Full dark mode color tokens are defined in globals.css under `@media (prefers-color-scheme: dark)`, but there is no theme toggle anywhere in the UI. Users with dark system preferences will see the dark theme, but cannot switch. This creates an untested UX path. - -**Recommendation**: Either add a theme toggle in settings/nav (using `next-themes`), or remove the dark mode definitions to ensure consistent appearance. If dark mode is deferred, add `class="light"` to the `` tag to force light mode. - ---- - -#### DS-4: Card `CardTitle` default size is too large and always overridden (Low) — **DONE** - -**File**: `src/components/ui/card.tsx` - -`CardTitle` defaults to `text-2xl tracking-tight`, but nearly every usage in the codebase adds custom sizing classes. This suggests the default is not useful. - -**Recommendation**: Change the default to `text-lg font-semibold` which matches the most common override pattern. - ---- - -### 1.2 Navigation & Information Architecture - -#### NAV-1: Inconsistent active state styling across role navigation components (Medium) — **DONE** - -**Files**: -- `src/components/layouts/jury-nav.tsx` - Uses `bg-primary/10 text-primary` -- `src/components/layouts/mentor-nav.tsx` - Uses `bg-primary/10 text-primary` -- `src/components/layouts/observer-nav.tsx` - Uses `bg-primary text-primary-foreground` (solid background) - -The observer nav uses a completely different active state style (solid filled background) compared to jury and mentor navs (subtle tinted background). This inconsistency is jarring for users who switch between roles. - -**Recommendation**: Unify active state styling. Better yet, extract all three into a shared `RoleNav` component as noted in the code quality review (4.1.4). - ---- - -#### NAV-2: Notification bell links are hardcoded to admin paths (Medium) — **DONE** - -**File**: `src/components/shared/notification-bell.tsx` - -The notification bell component links to `/admin/settings` and `/admin/notifications` regardless of the user's role. Jury members, mentors, and observers will be redirected or see 403 errors when clicking these links. - -**Recommendation**: Use role-aware paths (e.g., `/${role}/notifications`) or a role-neutral `/notifications` route. - ---- - -#### NAV-3: Jury nav is missing Awards link (Low) — **DONE** - -**File**: `src/components/layouts/jury-nav.tsx` - -The jury navigation includes Dashboard, My Assignments, and Learning Hub. There is no link to special awards even though jury members may need to view award-eligible projects. The admin sidebar includes awards management, but there is no jury-facing awards view link. - -**Recommendation**: Add an Awards link to the jury navigation if jury members should be able to view special award results. - ---- - -#### NAV-4: Admin sidebar user section uses hardcoded colors (Low) — **DONE** - -**File**: `src/components/layouts/admin-sidebar.tsx:247-267` - -The user info section at the bottom of the admin sidebar uses hardcoded `slate-200`, `slate-300`, `slate-700`, `slate-400` colors instead of semantic tokens like `muted`, `muted-foreground`, `border`. - -**Recommendation**: Replace with semantic color tokens for consistency with the rest of the design system and proper dark mode support. - ---- - -### 1.3 Mobile Responsiveness - -#### MOB-1: Admin rounds table is not responsive (High) — **DONE** - -**File**: `src/app/(admin)/admin/rounds/page.tsx` - -The rounds management page uses a fixed 7-column grid (`grid-cols-7`) that does not adapt to mobile or tablet screens. On narrow viewports, content will overflow or become illegible. Unlike the projects page (which has separate table/card views), rounds has no mobile layout. - -**Recommendation**: Implement a mobile card layout for rounds similar to the project list's mobile view. Show the full table only on `lg:` screens. - ---- - -#### MOB-2: Pagination component is not mobile-optimized (Medium) — **DONE** - -**File**: `src/components/shared/pagination.tsx` - -The pagination component renders all page numbers without truncation. For datasets with many pages, this creates a long horizontal row that overflows on mobile. - -**Recommendation**: Show abbreviated pagination on mobile: first, previous, current, next, last. Use `hidden sm:flex` to show the full pagination only on larger screens. - ---- - -#### MOB-3: Admin dashboard stat cards lack stacking on small screens (Low) — **DONE** - -**File**: `src/app/(admin)/admin/page.tsx` - -The admin dashboard uses `grid-cols-2 md:grid-cols-4` for the stats grid. On very narrow phones (< 360px), two columns may still be too wide for the stat cards. - -**Recommendation**: Consider `grid-cols-1 sm:grid-cols-2 md:grid-cols-4` for the narrowest phones. - ---- - -### 1.4 UX States & Feedback - -#### UX-1: No global 404 or error pages (Medium) — **DONE** - -**Files**: Only `src/app/(auth)/error/page.tsx` exists (auth-specific errors) - -There is no `src/app/not-found.tsx` or `src/app/error.tsx`. Users who navigate to non-existent routes will see Next.js's default 404 page, which has no MOPC branding, navigation, or helpful direction. - -**Recommendation**: Create `src/app/not-found.tsx` with MOPC branding, a message, and a link back to the dashboard. Create `src/app/error.tsx` for runtime errors. - ---- - -#### UX-2: Profile settings page has three identical save buttons (Medium) — **DONE** - -**File**: `src/app/(settings)/settings/profile/page.tsx:240-252, 286-298, 321-333` - -The profile page has three separate "Save" buttons (Save Changes, Save Preferences, Save Expertise) that all call the same `handleSaveProfile` function. This means clicking "Save Expertise" also saves any pending name/bio changes, which may confuse users. - -**Recommendation**: Either use a single save button at the bottom of the page for all profile fields, or make each section save independently by splitting the mutation into separate API calls. - ---- - -#### UX-3: Form state initialized via conditional in render body (Low) — **DONE** - -**File**: `src/app/(settings)/settings/profile/page.tsx:76-84` - -```tsx -if (user && !profileLoaded) { - setName(user.name || '') - // ... - setProfileLoaded(true) -} -``` - -This pattern of calling `setState` during render is fragile. React may batch these calls unpredictably, and the `profileLoaded` guard can fail during concurrent rendering. - -**Recommendation**: Use `useEffect` to populate form state when user data loads, or use React Hook Form with `defaultValues` from the query data. - ---- - -#### UX-4: Mentor dashboard uses client-side loading instead of Suspense (Low) — **DONE** - -**File**: `src/app/(mentor)/mentor/page.tsx` - -The mentor dashboard conditionally renders a loading spinner based on `isLoading` from tRPC queries, rather than using React Suspense boundaries. Other dashboards (admin) use server components. This creates inconsistency in the loading experience. - -**Recommendation**: Convert to a server component with Suspense, or at minimum use skeleton loading states (as the admin dashboard does) instead of a centered spinner. - ---- - -### 1.5 Interaction Patterns - -#### INT-1: Evaluation form is excellent (Positive) — **N/A** - -**File**: `src/components/forms/evaluation-form.tsx` - -The evaluation form demonstrates outstanding UX: -- Autosave with debounce and visual status indicator -- Dual input for scores: slider drag + direct button click -- Score label changes dynamically based on value -- Sticky status bar showing save state -- Confirmation dialog before final submission -- Read-only mode for past evaluations -- Character counter on text fields - -This should be the UX benchmark for all forms in the platform. - ---- - -#### INT-2: Button press feedback is well-implemented (Positive) — **N/A** - -**File**: `src/components/ui/button.tsx` - -All buttons include `active:scale-[0.98]` for tactile press feedback. Combined with proper `disabled` states and loading spinners (`Loader2` with `animate-spin`), the button interactions feel responsive and polished. - ---- - -#### INT-3: File upload component is well-designed (Positive) — **N/A** - -**File**: `src/components/shared/file-upload.tsx` - -The file upload supports drag-and-drop with visual hover state, progress bar during upload, file type and size validation with clear error messages, and a preview of uploaded files. This is production-ready UX. - ---- - -#### INT-4: Onboarding wizard has strong UX (Positive) — **N/A** - -**File**: `src/app/(auth)/onboarding/page.tsx` - -The multi-step onboarding uses: -- Brand gradient background for visual distinction -- Step indicator with progress -- Form validation per step -- Expertise tag selection with TagInput component -- Smooth transitions between steps - ---- - -### 1.6 Accessibility - -#### A11Y-1: Muted foreground color may have insufficient contrast (Medium) — **DONE** - -**File**: `src/app/globals.css` - -The `--muted-foreground` color (used for secondary text, placeholders, descriptions) is defined as `hsl(215.4 16.3% 46.9%)` in light mode. This corresponds to approximately `#6b7280` which provides ~4.6:1 contrast against white. While this passes WCAG AA for normal text (4.5:1), it fails for small text and is very close to the threshold. - -Many description texts and helper texts throughout the platform use `text-muted-foreground` at small sizes (`text-xs`, `text-sm`). - -**Recommendation**: Darken `--muted-foreground` slightly to ensure comfortable reading, especially for `text-xs` usage. Aim for at least 5:1 contrast ratio. - ---- - -#### A11Y-2: Focus styles are properly implemented (Positive) — **N/A** - -**File**: `src/app/globals.css`, `src/components/ui/button.tsx` - -The design system includes `focus-visible:ring-2 focus-visible:ring-ring` on interactive elements. This provides clear keyboard navigation indicators without affecting mouse users. This is correctly implemented across all shadcn/ui base components. - ---- - -#### A11Y-3: Skeleton loading states provide good screen reader context (Positive) — **N/A** - -**Files**: Multiple pages using `` components - -Loading states use semantic skeleton placeholders instead of spinners, which gives screen readers (via `aria-busy` on parent containers) context about what is loading. - ---- - -### 1.7 Visual Polish - -#### VP-1: Landing page is minimal and unbranded (Medium) — **DONE** - -**File**: `src/app/page.tsx` - -The landing/home page is very minimal. For a platform representing the Monaco Ocean Protection Challenge, the entry point should convey the mission and brand more strongly. - -**Recommendation**: Enhance the landing page with the MOPC logo, brand colors, a brief mission statement, and a clear CTA to login or learn more. Use the brand gradient seen in the onboarding flow. - ---- - -#### VP-2: Auth error page is generic (Low) — **DONE** - -**File**: `src/app/(auth)/error/page.tsx` - -The auth error page shows a basic card with the error message. It does not use MOPC branding or provide helpful navigation (e.g., "Return to Login" or "Contact Support"). - -**Recommendation**: Add MOPC branding, a supportive error message, and navigation options. - ---- - -#### VP-3: Observer dashboard "read-only" notice could be more prominent (Low) — **DONE** - -**File**: `src/app/(observer)/observer/page.tsx` - -The observer dashboard shows a subtle info card noting read-only access. Given that observers might expect interactivity, this notice could be more visually distinct. - -**Recommendation**: Use a persistent banner or badge-style indicator near the page header. - ---- - -### 1.8 Summary Table - -| Category | Findings | High | Medium | Low | Positive | -|----------|----------|------|--------|-----|----------| -| Design System & Theming | 4 | 0 | 1 | 3 | 0 | -| Navigation & IA | 4 | 0 | 2 | 2 | 0 | -| Mobile Responsiveness | 3 | 1 | 1 | 1 | 0 | -| UX States & Feedback | 4 | 0 | 2 | 2 | 0 | -| Interaction Patterns | 4 | 0 | 0 | 0 | 4 | -| Accessibility | 3 | 0 | 1 | 0 | 2 | -| Visual Polish | 3 | 0 | 1 | 2 | 0 | -| **Total** | **25** | **1** | **8** | **10** | **6** | - ---- - -### Quick Wins (< 1 hour each) - -1. **DS-1**: Replace Inter with Montserrat in public layout -2. **DS-2**: Use Logo component in public layout -3. **NAV-4**: Replace hardcoded slate colors with semantic tokens -4. **UX-3**: Move form state initialization to useEffect -5. **VP-2**: Add branding and navigation to auth error page -6. **DS-4**: Adjust CardTitle default size -7. **NAV-3**: Add Awards link to jury nav (if applicable) - -### Longer-Term Improvements - -1. **MOB-1**: Build responsive card layout for rounds table (High priority) -2. **UX-1**: Create global 404 and error pages -3. **NAV-1/NAV-2**: Unify navigation components and fix notification paths -4. **A11Y-1**: Audit and improve muted-foreground contrast -5. **VP-1**: Redesign landing page with full MOPC branding -6. **MOB-2**: Implement truncated mobile pagination -7. **UX-2**: Fix profile settings save button behavior -8. **DS-3**: Either implement dark mode toggle or force light mode -9. **UX-4**: Standardize loading patterns across dashboards - ---- - -## 3. Database Schema & Implementation Review - -**Reviewer**: Database & Backend Reviewer -**Date**: 2026-02-05 -**Scope**: Prisma schema, tRPC routers, services, indexing, query patterns, data integrity - ---- - -### Overall Assessment - -The schema is well-structured for its domain with good use of Prisma features. The codebase demonstrates solid TypeScript/Prisma patterns, proper use of enums, composite unique constraints, and consistent audit logging. However, there are several areas where improvements in indexing, query efficiency, transaction usage, and data integrity would enhance performance and reliability, particularly as the platform scales beyond Phase 1. - ---- - -### Schema Design - -#### SD-1: Project.roundId is required but treated as optional (High) — **DEFERRED** (requires design decision on pool project architecture) - -**Files**: `prisma/schema.prisma:417`, `src/server/routers/round.ts:631-639` - -The `Project` model declares `roundId String` as a required (non-nullable) field and has a required relation `round Round @relation(...)`. However, in `round.removeProjects`, the code sets `roundId: null as unknown as string`, which is a type-unsafe workaround to force a null into a non-nullable field. Similarly, `project.listPool` queries for `roundId: null`, which would never match if the schema is enforced. - -**Impact**: Data integrity violation; Prisma may not enforce this at the DB level with `@default()` but PostgreSQL will reject nulls on a NOT NULL column. - -**Recommendation**: Either make `roundId` optional (`String?`) with an optional relation if projects can be unassigned from rounds, or implement a "pool" round concept. The current workaround is fragile and could fail at the database level. - ---- - -#### SD-2: Evaluation versioning is declared but not implemented (Medium) — **DONE** (documented as deferred in schema with TODO comment) - -**Files**: `prisma/schema.prisma:570`, `src/server/routers/evaluation.ts` - -The `Evaluation` model has a `version Int @default(1)` field and the CLAUDE.md states "Evaluations are versioned - edits create new versions." However, the evaluation router's `autosave` and `submit` mutations update in-place and never create new versioned rows. The version field is never incremented. - -**Impact**: The stated requirement for version history is not fulfilled. If an admin or auditor needs to see how an evaluation changed over time, that data is lost. - -**Recommendation**: Either implement proper versioning (create new Evaluation rows with incremented version on re-submission) or remove the `version` field to avoid confusion. If versioning is deferred, document it clearly. - ---- - -#### SD-3: Soft deletes not implemented (Medium) — **DEFERRED** (massive schema change, requires careful planning) - -**Files**: All routers using `.delete()`, `prisma/schema.prisma` - -The CLAUDE.md architecture decisions (ADR #7) state "Soft deletes: Audit trail, recovery, referential integrity." However, no model has a `deletedAt` field, and all delete operations use hard deletes (e.g., `project.delete`, `user.delete`, `round.delete`). The `User.delete` cascades through assignments, evaluations, and other relations. - -**Impact**: Once deleted, data cannot be recovered. For a jury voting platform where audit trails are critical, this is a significant gap. Deleting a user cascades through assignments and evaluations, potentially destroying evaluation data. - -**Recommendation**: Add `deletedAt DateTime?` to critical models (`User`, `Project`, `Evaluation`, `Assignment`), implement soft delete middleware via Prisma's `$extends`, and ensure all queries filter out soft-deleted records. - ---- - -#### SD-4: LiveVotingSession.status is a String, not an Enum (Low) — **DONE** - -**Files**: `prisma/schema.prisma:918` - -The `LiveVotingSession.status` field is typed as `String @default("NOT_STARTED")` with valid values documented in a comment. Other status fields use proper enums. - -**Impact**: No database-level validation of valid status values. - -**Recommendation**: Create a `LiveVotingSessionStatus` enum with values `NOT_STARTED`, `IN_PROGRESS`, `PAUSED`, `COMPLETED`. - ---- - -#### SD-5: InAppNotification.priority and type are Strings, not Enums (Low) — **DONE** - -**Files**: `prisma/schema.prisma:737-738` - -Similar to SD-4, `priority` and `type` on `InAppNotification` are strings but have a fixed set of known values. The service defines `NotificationPriority` as a TypeScript type but it's not enforced at the database level. - -**Recommendation**: Create enums for `priority` (low/normal/high/urgent). The `type` field has many values that expand over time, so keeping it as a string is acceptable, but `priority` should be an enum. - ---- - -#### SD-6: Redundant date fields on Round (Low) — **DEFERRED** (fields still actively used in application/round routers) - -**Files**: `prisma/schema.prisma:348-353` - -The `Round` model has both `submissionDeadline` and `submissionEndDate` with a comment "replaces submissionDeadline if set". Additionally, `phase1Deadline` and `phase2Deadline` exist but appear unused in any router. This creates confusion about which fields are authoritative. - -**Recommendation**: Remove deprecated fields (`submissionDeadline` if replaced by `submissionEndDate`) and either implement or remove `phase1Deadline`/`phase2Deadline`. - ---- - -### Indexing - -#### IX-1: Missing composite index on Evaluation for round-based queries (High) — **DONE** - -**Files**: `prisma/schema.prisma:554-584` - -Many queries filter evaluations by `assignment.roundId` (e.g., `evaluation.listByRound`, all analytics queries, `export.evaluations`). This requires a join through the `Assignment` table. There is no index on `Evaluation.formId` paired with `status`, and more critically, the join through `assignment.roundId` means these queries perform a nested lookup. - -**Impact**: As evaluation counts grow (130+ projects x 3+ reviews = 390+ evaluations per round), these queries will slow down. - -**Recommendation**: Consider denormalizing `roundId` onto the `Evaluation` table or adding a database view. At minimum, ensure the existing `@@index([status])` and `@@index([formId])` are sufficient with the join pattern. - ---- - -#### IX-2: AuditLog table will grow unbounded (Medium) — **DEFERRED** (requires DBA decision on partitioning strategy) - -**Files**: `prisma/schema.prisma:638-663` - -The `AuditLog` table has good indexes (`userId`, `action`, `entityType+entityId`, `timestamp`) but no partitioning or archival strategy. With every CRUD operation, status change, login, and export generating audit entries, this table will grow rapidly. - -**Impact**: Query performance degradation over time, especially for `audit.getStats` which does `groupBy` operations across the entire table. - -**Recommendation**: Implement time-based partitioning on `timestamp`, or add an archival job that moves old audit logs to a separate table. Consider adding a composite index on `(entityType, entityId, timestamp)` for the `getByEntity` query. - ---- - -#### IX-3: User.email has both @unique and @@index (Low) — **DONE** - -**Files**: `prisma/schema.prisma:192, 262` - -`email String @unique` already creates a unique index. The additional `@@index([email])` is redundant. - -**Impact**: Extra write overhead on every user insert/update for maintaining a duplicate index. - -**Recommendation**: Remove `@@index([email])`. - ---- - -#### IX-4: Missing index on GracePeriod for combined lookups (Low) — **DONE** - -**Files**: `prisma/schema.prisma:590-612` - -The `evaluation.submit` mutation queries grace periods with `roundId + userId + extendedUntil + projectId`. Individual indexes exist but no composite index covers this query pattern. - -**Recommendation**: Add `@@index([roundId, userId, extendedUntil])` for the common grace period lookup pattern. - ---- - -### Query Optimization - -#### QO-1: Analytics getProjectRankings loads all project data including all assignments and evaluations (High) — **DONE** - -**Files**: `src/server/routers/analytics.ts:148-207` - -The `getProjectRankings` query does `include: { assignments: { include: { evaluation: ... } } }` on ALL projects in a round, fetching complete project records with nested assignments and evaluations. For a round with 130 projects and 3+ evaluations each, this fetches 390+ evaluation records with full project data. - -**Impact**: Significant memory usage and query time. The response payload is very large even though only scores are needed for ranking. - -**Recommendation**: Use a raw SQL aggregate query or Prisma's `select` to only fetch the fields needed (project id, title, evaluation scores). Consider pre-computing rankings or caching results. - ---- - -#### QO-2: getTags fetches all projects to extract unique tags (Medium) — **DONE** - -**Files**: `src/server/routers/project.ts:580-599` - -The `getTags` query fetches ALL projects with `select: { tags: true }` then deduplicates in JavaScript. For 100+ projects, this is inefficient. - -**Impact**: Unnecessary data transfer and memory usage. - -**Recommendation**: Use Prisma's `$queryRaw` with `SELECT DISTINCT unnest(tags) FROM "Project"` or PostgreSQL's `array_agg(DISTINCT ...)` to get unique tags at the database level. - ---- - -#### QO-3: Project.list includes full files array for every project (Medium) — **DONE** - -**Files**: `src/server/routers/project.ts:133-134` - -The project list query includes `files: true`, fetching all file records for every project in the paginated list. Most list views only need to know whether files exist, not the full file details. - -**Impact**: Over-fetching data, larger payloads, slower queries. - -**Recommendation**: Use `_count: { select: { files: true } }` or `files: { select: { id: true, fileType: true } }` instead of `files: true`. - ---- - -#### QO-4: Sequential notification sends in bulk operations (Medium) — **DONE** - -**Files**: `src/server/routers/assignment.ts:476-490`, `src/server/routers/user.ts:559-596` - -In `assignment.bulkCreate` and `user.bulkCreate`, notifications are sent sequentially in a `for` loop with `await createNotification(...)`. Each `createNotification` call also queries the database for email settings and user preferences. - -**Impact**: Bulk operations are O(n) in database queries for notifications, significantly slowing down bulk assignment/invitation flows. - -**Recommendation**: Use `createBulkNotifications` (which already exists and uses `createMany`) instead of looping with `createNotification`. Batch the email checks as well. - ---- - -#### QO-5: Export queries fetch unbounded data (Medium) — **DONE** - -**Files**: `src/server/routers/export.ts:16-34, 106-118` - -Export queries for evaluations and project scores have no pagination and no limit (except audit logs with `take: 10000`). For large rounds, this could return thousands of records in a single response. - -**Impact**: Memory pressure on the server, potential timeout for large exports. - -**Recommendation**: Implement streaming or chunked export, or add a reasonable limit with warning to the user. - ---- - -#### QO-6: N+1 in mentor.getSuggestions (Medium) — **DONE** - -**Files**: `src/server/routers/mentor.ts:50-78` - -After getting AI suggestions, each mentor is fetched individually in a `Promise.all(suggestions.map(...))` loop. Each iteration makes a separate `user.findUnique` query. - -**Impact**: If there are 5 suggestions, this makes 5 additional database queries. - -**Recommendation**: Fetch all needed mentors in a single `user.findMany({ where: { id: { in: mentorIds } } })` query, then map results. - ---- - -#### QO-7: Audit log creation not batched or fire-and-forget (Low) — **DONE** (migrated to logAudit utility with try-catch) - -**Files**: All routers - -Every mutation `await`s the audit log creation, meaning the user's response is delayed by audit log write time. Audit logs are non-critical for the operation's success. - -**Recommendation**: Consider making audit log writes fire-and-forget (don't await) or use a background queue. Alternatively, batch audit logs within transactions where possible. - ---- - -### Data Integrity - -#### DI-1: Evaluation submission and assignment update are not in a transaction (High) — **DONE** - -**Files**: `src/server/routers/evaluation.ts:200-213` - -The `evaluation.submit` mutation updates the evaluation status to `SUBMITTED` and then separately updates the assignment's `isCompleted` to `true`. These two operations should be atomic - if the second fails, the evaluation is marked submitted but the assignment still shows as incomplete. - -**Impact**: Inconsistent state between evaluation and assignment records. - -**Recommendation**: Wrap both updates in a `$transaction`: -```typescript -await ctx.prisma.$transaction([ - ctx.prisma.evaluation.update({ where: { id }, data: { ...data, status: 'SUBMITTED', submittedAt: now } }), - ctx.prisma.assignment.update({ where: { id: evaluation.assignmentId }, data: { isCompleted: true } }), -]) -``` - ---- - -#### DI-2: Project create + audit log not in a transaction (Medium) — **DONE** - -**Files**: `src/server/routers/project.ts:299-323`, and similar patterns across all routers - -Across all routers, the pattern is: create/update entity, then create audit log as a separate operation. If the audit log creation fails, the entity operation succeeds but the audit trail has a gap. - -**Impact**: Missing audit entries for successful operations. - -**Recommendation**: For critical operations (especially ones involving evaluation submissions, status changes, and user modifications), wrap entity changes and audit log creation in a single transaction. For less critical operations, fire-and-forget the audit log. - ---- - -#### DI-3: bulkUpdateStatus does not check project ownership before notification (Medium) — **DONE** - -**Files**: `src/server/routers/project.ts:620-742` - -The `bulkUpdateStatus` mutation uses `updateMany` (which doesn't return updated records) and then separately fetches projects by ID to send notifications. If some IDs don't match the `roundId` filter, the notification list may not match the actually-updated projects. - -**Impact**: Notifications could be sent for projects that weren't actually updated. - -**Recommendation**: Fetch the matching projects before the update to ensure consistency between updates and notifications, or use the `updated.count` to validate. - ---- - -#### DI-4: Assignment uniqueness constraint may be bypassed by skipDuplicates (Low) — **DONE** - -**Files**: `src/server/routers/assignment.ts:427-434` - -The `bulkCreate` mutation uses `createMany({ skipDuplicates: true })`. While this prevents constraint violations, it silently drops assignments that already exist. The returned count may not reflect what the user intended. - -**Impact**: Users may not realize some assignments were skipped. - -**Recommendation**: Before `createMany`, check which assignments already exist and report the skip count to the user (similar to how `user.bulkCreate` handles it). - ---- - -#### DI-5: No foreign key constraint on SpecialAward.winnerOverriddenBy (Low) — **DONE** - -**Files**: `prisma/schema.prisma:1213` - -The `winnerProjectId` field has a relation to `Project` with `onDelete: SetNull`, which is appropriate. However, `winnerOverriddenBy` is just a `String?` with no relation to `User`, meaning there's no referential integrity check. - -**Recommendation**: Add a relation from `winnerOverriddenBy` to `User` to ensure referential integrity. - ---- - -### Performance - -#### PF-1: Large transaction in filtering.executeRules (High) — **DONE** - -**Files**: `src/server/routers/filtering.ts:503-531` - -The `executeRules` mutation creates a transaction with one `upsert` per project. For 130 projects, this is 130 sequential upserts in a single transaction, holding database locks for the duration. - -**Impact**: Long-running transaction that blocks other operations on the `FilteringResult` table. - -**Recommendation**: Batch the upserts into groups of 20-30, or use `createMany`/`updateMany` where possible. Alternatively, use `$executeRawUnsafe` with a bulk `INSERT ... ON CONFLICT` statement. - ---- - -#### PF-2: Description field text search uses ILIKE without text index (Medium) — **DEFERRED** (requires PostgreSQL full-text search extension) - -**Files**: `src/server/routers/project.ts:111-117` - -Project search uses `{ description: { contains: search, mode: 'insensitive' } }` which translates to `ILIKE '%search%'`. The `description` field is `@db.Text` (unlimited length). Without a text index, this performs a full table scan on potentially large text fields. - -**Impact**: Slow search queries as project count grows, especially with long descriptions. - -**Recommendation**: Add PostgreSQL full-text search (`tsvector`/`tsquery`) via a generated column and GIN index, or use Prisma's full-text search extension. Alternatively, limit search to `title` and `teamName` only for list views. - ---- - -#### PF-3: Assignment stats query makes 5 separate database calls (Low) — **DONE** - -**Files**: `src/server/routers/assignment.ts:530-554` - -The `getStats` query runs 4 parallel queries via `Promise.all` plus a separate `findUniqueOrThrow`. While parallel, this is still 5 database round-trips. - -**Recommendation**: Consolidate into fewer queries. The `projectCoverage` query already returns project data that could provide the total projects count, eliminating one query. - ---- - -### Positive Patterns Observed - -1. **Consistent use of `@@unique` composite constraints**: The schema properly uses composite unique constraints (`@@unique([userId, projectId, roundId])` on Assignment, `@@unique([awardId, projectId])` on AwardEligibility, etc.) to prevent duplicate records at the database level. - -2. **Good use of `select` to limit data fetching**: Many queries use `select` clauses to fetch only needed fields (e.g., `user.me`, `user.list`), reducing payload sizes. - -3. **`Promise.all` for parallel queries**: List queries consistently use `Promise.all([findMany, count])` for pagination, reducing latency. - -4. **RBAC enforced at query level**: Jury members are restricted to their assigned projects through `where` clause filtering, not just middleware checks. - -5. **Proper Zod validation**: All tRPC inputs use comprehensive Zod schemas with min/max constraints, enums, and proper typing. - -6. **Consistent audit logging**: Nearly every mutation creates an audit log entry with context (userId, action, entityType, entityId, detailsJson). - -7. **Background job pattern**: Long-running AI operations (filtering, assignment) use a job table with status tracking and progress callbacks, with fire-and-forget execution. - -8. **Cascade deletes on relations**: The schema consistently uses `onDelete: Cascade` for owned relations and `onDelete: SetNull` for references, which is appropriate. - -9. **Good use of JsonB for flexible data**: The use of `@db.JsonB` for criteria, settings, and metadata allows schema flexibility without migrations. - -10. **Pagination implemented consistently**: List endpoints consistently implement cursor or offset-based pagination with `page`/`perPage` parameters and return total counts. - ---- - -### Priority Summary - -| Priority | Count | Key Issues | -|----------|-------|------------| -| **High** | 4 | Missing transaction on evaluation submit (DI-1), large filtering transaction (PF-1), analytics over-fetching (QO-1), project.roundId nullability mismatch (SD-1) | -| **Medium** | 9 | Soft deletes not implemented (SD-3), evaluation versioning missing (SD-2), N+1 queries (QO-6), sequential notifications (QO-4), audit log growth (IX-2), export unbounded (QO-5), text search without index (PF-2), DI-2, DI-3 | -| **Low** | 7 | Redundant email index (IX-3), string status fields (SD-4, SD-5), deprecated date fields (SD-6), grace period composite index (IX-4), DI-4, DI-5, PF-3 | - ---- - -## 4. Code Quality Review - -### 4.1 Duplicate Code - -#### 4.1.1 `toProjectWithRelations` duplicated across 3 AI services — **DONE** -**Files:** -- `src/server/services/ai-tagging.ts:144` -- `src/server/services/ai-filtering.ts:281` -- `src/server/services/ai-award-eligibility.ts:137` - -All three files contain nearly identical `toProjectWithRelations()` functions that convert a project object to the `ProjectWithRelations` type for anonymization. The function body is the same each time: mapping fields, using `as any` casts, providing defaults for missing fields. - -**Recommendation:** Extract into a shared function in `src/server/services/anonymization.ts` (which already defines `ProjectWithRelations`). -**Effort:** Quick Fix - ---- - -#### 4.1.2 AI service batch processing boilerplate — **DEFERRED** (large refactor, high risk for no behavioral change) -**Files:** -- `src/server/services/ai-assignment.ts:273-377` -- `src/server/services/ai-filtering.ts:425-565` -- `src/server/services/ai-award-eligibility.ts:278-368` -- `src/server/services/mentor-matching.ts:202-337` - -All four AI services follow an identical pattern: -1. Get OpenAI client, check if null -> fallback -2. Get configured model -3. Anonymize data -4. Validate anonymization -5. Loop over batches, call `processXxxBatch()` -6. Track total tokens -7. Catch errors, classify with `classifyAIError`, log with `logAIError`, log usage with `logAIUsage` -8. Fallback to algorithm - -Each batch processor also repeats: build params -> call API -> extract usage -> log usage -> parse JSON -> deanonymize -> handle parse errors with identical error logging. - -**Recommendation:** Create a generic `processAIBatches()` utility that handles the shared orchestration, accepting callbacks for prompt building and result parsing. -**Effort:** Large Refactor - ---- - -#### 4.1.3 Avatar and Logo routers are structural clones — **DONE** -**Files:** -- `src/server/routers/avatar.ts` (187 lines) -- `src/server/routers/logo.ts` (196 lines) - -Both routers have identical structure with 4 endpoints each (`getUploadUrl`, `confirmUpload`, `getUrl`, `delete`) that follow the same pattern: -- Validate image type -- Generate storage key -- Get provider -- Upload/download/delete with provider -- Update database record -- Create audit log - -The only differences are: entity type (User vs Project), field names (profileImageKey vs logoKey), and auth level (protectedProcedure vs adminProcedure). - -**Recommendation:** Create a generic `createImageUploadRouter()` factory that accepts entity config. -**Effort:** Medium - ---- - -#### 4.1.4 Navigation components (jury, mentor, observer) are near-duplicates — **DONE** -**Files:** -- `src/components/layouts/jury-nav.tsx` -- `src/components/layouts/mentor-nav.tsx` -- `src/components/layouts/observer-nav.tsx` - -All three components share the same structure: mobile hamburger menu, desktop nav bar, user avatar dropdown with settings/sign-out, notification bell. They differ only in the navigation links array and the user prop interface name. - -**Recommendation:** Create a shared `RoleNav` component that accepts a `navigation` array and role-specific config as props. -**Effort:** Medium - ---- - -#### 4.1.5 Expertise matching logic duplicated between AI assignment fallback and smart assignment — **SKIPPED** (different scoring ranges 0-1 vs 0-40, consolidating would change algorithm behavior) -**Files:** -- `src/server/services/ai-assignment.ts:514-534` (`calculateExpertiseScore`) -- `src/server/services/smart-assignment.ts:140-163` (`calculateTagOverlapScore`) - -Both implement tag-based expertise matching with slight variations. The fallback in `ai-assignment.ts` uses set intersection, while `smart-assignment.ts` uses weighted confidence scores. The mentor-matching algorithmic fallback (`src/server/services/mentor-matching.ts:374-444`) also has its own keyword matching implementation. - -**Recommendation:** Consolidate expertise scoring into a single utility with configurable weighting. -**Effort:** Medium - ---- - -#### 4.1.6 Audit logging: two competing patterns — **DONE** -**Files:** -- `src/server/utils/audit.ts` - Shared `logAudit()` utility (wraps in try-catch) -- Used in: `src/server/routers/filtering.ts`, `src/server/routers/specialAward.ts` -- 19 other router files use inline `ctx.prisma.auditLog.create()` directly (79 total occurrences) - -Most routers create audit logs inline without try-catch, meaning an audit failure could break the operation. The `logAudit` utility exists specifically to prevent this but is only used in 2 of 21 routers. - -**Recommendation:** Migrate all 79 inline audit log calls to use the `logAudit` utility for consistent error handling. Or add audit logging as tRPC middleware. -**Effort:** Medium - ---- - -#### 4.1.7 Batch tagging logic duplicated between service and router — **DONE** (dead service functions removed) -**Files:** -- `src/server/services/ai-tagging.ts:456-551` (`batchTagProjects`) -- `src/server/services/ai-tagging.ts:558-655` (`batchTagProgramProjects`) -- `src/server/routers/tag.ts:20-170` (`runTaggingJob`) - -`batchTagProjects` and `batchTagProgramProjects` in the service are nearly identical (differ only in the Prisma `where` clause). The `runTaggingJob` in the router reimplements the same loop with progress tracking. - -**Recommendation:** The service functions (`batchTagProjects`, `batchTagProgramProjects`) appear to be dead code since the router uses `runTaggingJob` directly. Remove the unused service functions and consolidate into a single batch function with a flexible query parameter. -**Effort:** Medium - ---- - -### 4.2 Dead Code - -#### 4.2.1 `getObjectInfo` function in minio.ts is never called — **DONE** -**File:** `src/lib/minio.ts:115-120` - -The `getObjectInfo` function is exported but never imported or used anywhere in the codebase. - -**Recommendation:** Remove. -**Effort:** Quick Fix - ---- - -#### 4.2.2 `isValidImageSize` function in storage/index.ts is never called — **DONE** -**File:** `src/lib/storage/index.ts:136-138` - -Exported but never imported anywhere. Image size validation is not performed server-side. - -**Recommendation:** Remove, or actually use it in the avatar/logo upload flows. -**Effort:** Quick Fix - ---- - -#### 4.2.3 `clearStorageProviderCache` is never called — **DONE** -**File:** `src/lib/storage/index.ts:85-88` - -This function is defined to clear the cached storage provider when settings change, but it is never called from the settings router or anywhere else. This means changing the storage provider in settings has no effect until the server restarts. - -**Recommendation:** Call this function from the settings router when `storage_provider` is updated. -**Effort:** Quick Fix - ---- - -#### 4.2.4 `deleteObject` in minio.ts is only used indirectly — **DONE** -**File:** `src/lib/minio.ts:93-98` - -Only referenced via the S3 storage provider (`src/lib/storage/s3-provider.ts`). The direct export from minio.ts is never imported directly by any router or service. - -**Recommendation:** Consider making it non-exported (internal to the module) since it's only used by the S3 provider. -**Effort:** Quick Fix - ---- - -#### 4.2.5 Deprecated batch tag endpoints still exposed — **DONE** -**File:** `src/server/routers/tag.ts:763-814` - -Two endpoints are marked `@deprecated` (`batchTagProjects`, `batchTagProgramProjects`) but still included in the router. They duplicate the logic of `startTaggingJob`. - -**Recommendation:** Check if any frontend code calls these deprecated endpoints. If not, remove them. -**Effort:** Quick Fix - ---- - -#### 4.2.6 `batchTagProjects` and `batchTagProgramProjects` service functions likely unused — **DONE** -**Files:** -- `src/server/services/ai-tagging.ts:456-551` -- `src/server/services/ai-tagging.ts:558-655` - -These two exported functions are no longer called by the tag router (which uses `runTaggingJob` instead). No other files import them. - -**Recommendation:** Remove both functions. -**Effort:** Quick Fix - ---- - -#### 4.2.7 `twilio` npm package is never imported — **DONE** -**File:** `package.json:85` - -The `twilio` package (v5.4.0) is listed as a dependency, but the Twilio WhatsApp provider (`src/lib/whatsapp/twilio-provider.ts`) uses raw `fetch()` calls to the Twilio API instead of the SDK. The SDK is never imported anywhere. - -**Recommendation:** Remove `twilio` from dependencies to reduce bundle size and install footprint. -**Effort:** Quick Fix - ---- - -### 4.3 Redundant Code - -#### 4.3.1 Two storage abstraction layers: minio.ts and storage/ — **DONE** -**Files:** -- `src/lib/minio.ts` - Direct MinIO client with helper functions -- `src/lib/storage/` - Provider-based abstraction (S3Provider wraps minio.ts, LocalProvider) - -Some routers use `minio.ts` directly (`file.ts`, `partner.ts`, `learningResource.ts`, `applicant.ts`) while others use the storage abstraction (`avatar.ts`, `logo.ts`). This creates inconsistency: files uploaded through direct minio calls won't work if the admin switches to local storage. - -**Recommendation:** Migrate all direct `@/lib/minio` imports to use the `@/lib/storage` abstraction for consistent provider-agnostic file handling. -**Effort:** Medium - ---- - -#### 4.3.2 Debug console.log statements in user router — **DONE** -**File:** `src/server/routers/user.ts:246,256` - -Debug logging for a simple user fetch query: -``` -console.log('[user.get] Fetching user:', input.id) -console.log('[user.get] Found user:', user.email) -``` - -These appear to be leftover development debug statements, not structured logging. - -**Recommendation:** Remove. -**Effort:** Quick Fix - ---- - -#### 4.3.3 Excessive console.log in AI services — **DONE** (structured logger implemented) -**Files:** -- `src/server/services/ai-tagging.ts` - 22 console.log statements -- `src/server/services/ai-filtering.ts` - 5 console.log statements -- `src/server/services/ai-assignment.ts` - 5 console.log statements -- `src/server/services/ai-award-eligibility.ts` - 5 console.log statements -- `src/server/services/mentor-matching.ts` - 4 console.log statements -- `src/server/routers/tag.ts` - 10 console.log statements - -Total: ~51 console.log/warn/error statements across AI services. While useful for debugging, production code should use structured logging with configurable log levels. - -**Recommendation:** Implement a simple logger utility with configurable levels (debug, info, warn, error) and replace all console.log calls. -**Effort:** Medium - ---- - -### 4.4 Unfinished Code - -#### 4.4.1 TODO: Send invitation email to new team member — **DONE** -**File:** `src/server/routers/applicant.ts:659` - -```typescript -// TODO: Send invitation email to the new team member -``` - -The team member addition flow creates the team member record but never sends an invitation email. - -**Recommendation:** Implement email notification using the existing notification service. -**Effort:** Medium - ---- - -#### 4.4.2 `aiBoost` field always returns 0 — **DONE** (removed unused field) -**File:** `src/server/services/smart-assignment.ts:27,370` - -The `ScoreBreakdown` type includes an `aiBoost` field (described as "Reserved: 0-5 points (future AI boost)" in the comment), but it's always set to `0` in all score calculations. - -**Recommendation:** Either implement the AI boost feature or remove the field to avoid confusion. -**Effort:** Quick Fix (to remove) / Large Refactor (to implement) - ---- - -### 4.5 Unused Dependencies — **ALL DONE** - -| Package | Evidence | Recommendation | Status | -|---------|----------|----------------|--------| -| `twilio` (v5.4.0) | Never imported; Twilio provider uses raw `fetch()` | Remove from package.json | **DONE** | -| `autoprefixer` (v10.4.20) | Only referenced in postcss config; Tailwind v4 includes autoprefixer | Verify and potentially remove | **DONE** | -| `@types/leaflet` (v1.9.21) | Listed in `dependencies` not `devDependencies` | Move to devDependencies | **DONE** | - ---- - -### 4.6 Summary - -| Category | Count | Quick Fix | Medium | Large | -|----------|-------|-----------|--------|-------| -| Duplicate Code | 7 | 0 | 4 | 3 | -| Dead Code | 7 | 7 | 0 | 0 | -| Redundant Code | 3 | 2 | 1 | 0 | -| Unfinished Code | 2 | 1 | 1 | 0 | -| Unused Dependencies | 3 | 3 | 0 | 0 | -| **Total** | **22** | **13** | **6** | **3** | - -**Priority recommendations (highest impact, lowest effort):** -1. Remove unused `twilio` dependency (saves ~10MB in node_modules) -2. Remove dead code: `getObjectInfo`, `isValidImageSize`, deprecated batch endpoints, unused batch service functions -3. Call `clearStorageProviderCache` when storage settings change (bug fix) -4. Extract shared `toProjectWithRelations` to eliminate 3-way duplication -5. Migrate direct `@/lib/minio` imports to `@/lib/storage` for consistency - ---- - -## 2. Security Review - -**Reviewer**: Security Reviewer Agent -**Date**: 2026-02-05 -**Scope**: Authentication, authorization, input validation, file security, rate limiting, CSRF, data privacy, password security, API routes, injection prevention, XSS, audit logging, session security, environment variables, account lockout - ---- - -### Critical Findings - -#### CRIT-1: Path Traversal Bypass in Local Storage Provider — **DONE** - -**Affected file**: `src/lib/storage/local-provider.ts:65-68` - -The path traversal sanitization is insufficient. It only strips literal `..` sequences but does not account for encoded variants or alternative traversal techniques on Windows. Additionally, `path.join()` can resolve `..` segments inserted via other mechanisms. - -```typescript -private getFilePath(key: string): string { - const sanitizedKey = key.replace(/\.\./g, '').replace(/^\//, '') - return path.join(this.basePath, sanitizedKey) -} -``` - -**Impact**: An attacker with a valid signed URL (or who can manipulate the `key` parameter) could potentially read arbitrary files from the server filesystem. - -**Recommendation**: After constructing the full path with `path.resolve()`, verify it still starts with the expected base directory: -```typescript -const resolved = path.resolve(this.basePath, sanitizedKey) -if (!resolved.startsWith(path.resolve(this.basePath))) { - throw new Error('Invalid file path') -} -``` - ---- - -#### CRIT-2: Timing-Unsafe Signature Comparison — **DONE** - -**Affected file**: `src/lib/storage/local-provider.ts:56-63` - -The HMAC signature verification uses `===` string comparison, which is vulnerable to timing attacks. An attacker could theoretically determine the correct HMAC byte-by-byte by measuring response times. - -```typescript -return signature === expectedSignature && expiresAt > Date.now() / 1000 -``` - -**Impact**: In theory, an attacker could forge valid pre-signed URLs by progressively guessing the HMAC signature. While practical exploitation is difficult over the network, it remains a cryptographic best-practice violation. - -**Recommendation**: Use `crypto.timingSafeEqual()` for HMAC comparison: -```typescript -import { timingSafeEqual } from 'crypto' -const sigBuffer = Buffer.from(signature, 'hex') -const expectedBuffer = Buffer.from(expectedSignature, 'hex') -return sigBuffer.length === expectedBuffer.length - && timingSafeEqual(sigBuffer, expectedBuffer) - && expiresAt > Date.now() / 1000 -``` - ---- - -#### CRIT-3: Email/Password Change API Routes Lack Proper Authentication — **DONE** - -**Affected files**: `src/app/api/email/verify-credentials/route.ts`, `src/app/api/email/change-password/route.ts` - -These API routes accept `POST` requests with email and password credentials but have no session-based authentication verifying the caller. While the middleware `authorized` callback blocks unauthenticated users from non-public paths, these routes do not verify the authenticated user matches the email being acted upon. An authenticated user could verify credentials or change the Poste.io mailbox password of any `@monaco-opc.com` email address. - -The change-password route at `src/app/api/email/change-password/route.ts:97-109` sends the new password in plaintext to the Poste.io admin API using hardcoded admin credentials. - -**Impact**: An authenticated user could potentially change another user's email password. Rate limiting (3-5 attempts per 15 minutes) slows but does not prevent this. - -**Recommendation**: Add NextAuth session checks to both API routes. Verify that the authenticated user's email matches the email being acted upon. - ---- - -### High Severity Findings - -#### HIGH-1: In-Memory Rate Limiting Does Not Scale — **DEFERRED** (requires Redis infrastructure) - -**Affected files**: `src/lib/rate-limit.ts`, `src/lib/auth.ts:12` - -Both the rate limiter and the account lockout tracker use in-memory `Map` objects. In a multi-instance deployment (e.g., multiple Docker replicas behind a load balancer), rate limits and lockouts are per-instance, not global. - -```typescript -const failedAttempts = new Map() -``` - -**Impact**: An attacker could bypass rate limiting by having requests routed to different instances. Account lockout after 5 failed attempts would not work reliably across instances. This is acknowledged in the rate-limit.ts comment but still represents a deployment risk. - -**Recommendation**: Move to Redis-based rate limiting and lockout tracking before deploying with multiple instances. If running single-instance only, document this constraint clearly. - ---- - -#### HIGH-2: Health Check Endpoint Leaks Database Error Details — **DONE** - -**Affected file**: `src/app/api/health/route.ts:29` - -The health endpoint returns the actual error message when the database is disconnected: -```typescript -error: error instanceof Error ? error.message : 'Unknown error', -``` - -**Impact**: Database connection errors may contain hostnames, ports, connection strings, or other internal infrastructure details that aid attackers in reconnaissance. - -**Recommendation**: Log the full error server-side but return only a generic status to the client. If the health endpoint is meant for internal monitoring only, restrict access via network configuration or authentication. - ---- - -#### HIGH-3: Local Storage Fallback Secret Key — **DONE** - -**Affected file**: `src/lib/storage/local-provider.ts:6` - -```typescript -const SECRET_KEY = process.env.NEXTAUTH_SECRET || 'local-storage-secret' -``` - -If `NEXTAUTH_SECRET` is not set, the signing key falls back to a hardcoded value. While `NEXTAUTH_SECRET` should always be set in production, this fallback is dangerous if accidentally deployed without it. - -**Impact**: An attacker who knows the fallback value can forge pre-signed file download/upload URLs, bypassing all file access controls. - -**Recommendation**: Remove the fallback or throw an error at startup if `NEXTAUTH_SECRET` is not set. Never use hardcoded cryptographic secrets. - ---- - -#### HIGH-4: MinIO Client Defaults to Insecure Credentials — **DONE** - -**Affected file**: `src/lib/minio.ts:23-24` - -```typescript -accessKey: process.env.MINIO_ACCESS_KEY || 'minioadmin', -secretKey: process.env.MINIO_SECRET_KEY || 'minioadmin', -``` - -**Impact**: If environment variables are not set, the client uses default MinIO credentials (`minioadmin/minioadmin`). Combined with a misconfigured or exposed MinIO instance, this could grant full access to all stored files including jury evaluation documents and project submissions. - -**Recommendation**: Fail loudly in production when these environment variables are not set instead of falling back to defaults. - ---- - -#### HIGH-5: Application Submission Creates Users Without Verification — **DONE** (added rate limiting) - -**Affected file**: `src/server/routers/application.ts:148-341` - -The `application.submit` route uses `publicProcedure` (no authentication required) and creates new `User` records with the `APPLICANT` role, plus `TeamMember` records, based entirely on user-supplied email addresses. Any external user can: -1. Create arbitrary user accounts with the `APPLICANT` role -2. Create team member records linking arbitrary email addresses -3. Pollute the user table with fake data - -While the APPLICANT role has limited permissions, there is no CAPTCHA, no email verification, and the only rate limit is the global tRPC limit of 100 requests/minute per IP. - -**Impact**: User table pollution, spam applications, potential abuse of the notification system (applicants receive in-app notifications). - -**Recommendation**: Add CAPTCHA/reCAPTCHA verification to the submission endpoint. Implement a stricter rate limit specific to application submissions. Consider requiring email verification before creating user accounts and team memberships. - ---- - -### Medium Severity Findings - -#### MED-1: Password Policy Does Not Require Special Characters — **DONE** - -**Affected file**: `src/lib/password.ts:34-56` - -The password validation requires only 8 characters, one uppercase, one lowercase, and one digit. Special characters are not required. - -**Impact**: Passwords without special characters are more susceptible to dictionary and brute-force attacks. - -**Recommendation**: Consider requiring at least one special character, or increase the minimum length to 12 characters. Also consider checking against common password lists (e.g., "Have I Been Pwned" API or a local blocklist of the top 10,000 passwords). - ---- - -#### MED-2: Audit Logging Failures Are Silently Swallowed — **DONE** - -**Affected files**: `src/server/utils/audit.ts:29-32`, `src/lib/auth.ts:91,147`, and many router files - -Audit log failures are caught and silently ignored throughout the codebase: -```typescript -await prisma.auditLog.create({ ... }).catch(() => {}) -``` - -**Impact**: If the audit system fails (e.g., database connection issues, disk full), critical security events (login attempts, role changes, data exports) will not be recorded. This violates the stated requirement of an "immutable audit log." - -**Recommendation**: At minimum, log audit failures to a secondary logging system (e.g., file-based logger or error monitoring service like Sentry). Consider implementing a write-ahead buffer or retry mechanism for audit entries. - ---- - -#### MED-3: File Upload Has No Content-Type or Extension Validation — **DONE** - -**Affected file**: `src/server/routers/file.ts:75-125` - -The `getUploadUrl` procedure validates the `fileType` enum (EXEC_SUMMARY, PRESENTATION, VIDEO, OTHER) and accepts a `mimeType` string, but does not verify that the MIME type matches the file extension, nor does it block dangerous file types (e.g., `.exe`, `.sh`, `.php`, `.html`). - -The local storage upload route at `src/app/api/storage/local/route.ts:111-124` accepts any content-type from the request header without validation. - -**Impact**: An admin user could upload executable or HTML files. If these files are later served with their original content-type, this could lead to stored XSS or other browser-based attacks when other users download them. - -**Recommendation**: Implement server-side MIME type validation and file extension allowlisting. Serve uploaded files with `Content-Disposition: attachment` headers and sanitized content types. - ---- - -#### MED-4: File Deletion Does Not Remove Storage Objects — **DONE** - -**Affected file**: `src/server/routers/file.ts:143-171` - -When a file record is deleted, only the database entry is removed. The actual file in MinIO or local storage is not deleted: -```typescript -// Note: Actual MinIO deletion could be done here or via background job -// For now, we just delete the database record -``` - -**Impact**: Orphaned files accumulate in storage. Previously-issued pre-signed URLs remain valid until their expiry. This has data retention/GDPR compliance implications. - -**Recommendation**: Implement storage object deletion alongside database record deletion, or create a background cleanup job for orphaned files. - ---- - -#### MED-5: IP Address Extraction Relies on Spoofable Header — **DEFERRED** (requires Nginx proxy configuration) - -**Affected files**: `src/server/context.ts:13`, `src/app/api/trpc/[trpc]/route.ts:13-18`, `src/app/api/auth/[...nextauth]/route.ts:8-12` - -Client IP is extracted from the `x-forwarded-for` header: -```typescript -const ip = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown' -``` - -**Impact**: If the application is not behind a properly configured reverse proxy, clients can spoof their IP address by setting the `x-forwarded-for` header. This bypasses IP-based rate limiting and poisons audit log entries with false IP addresses. - -**Recommendation**: Configure the application to only trust `x-forwarded-for` from known proxy IPs. In production with Nginx, ensure the proxy overwrites (not appends to) this header and strips any client-supplied values. - ---- - -#### MED-6: Public Email Availability Check Enables Enumeration — **DONE** - -**Affected file**: `src/server/routers/application.ts:346-367` - -The `checkEmailAvailability` endpoint is a public procedure that reveals whether a specific email has already submitted an application for a given round: -```typescript -return { available: !existing, message: existing ? 'An application with this email...' : null } -``` - -**Impact**: An attacker can enumerate which emails have submitted applications for specific rounds, potentially revealing participation in the ocean protection challenge. - -**Recommendation**: Consider removing this endpoint or requiring authentication. If it is needed for UX, implement stricter rate limiting and CAPTCHA. - ---- - -#### MED-7: Assignment Job Status Accessible to All Authenticated Users — **DONE** - -**Affected file**: `src/server/routers/assignment.ts:1041-1061` - -The `getAIAssignmentJobStatus` endpoint uses `protectedProcedure` instead of `adminProcedure`: -```typescript -getAIAssignmentJobStatus: protectedProcedure - .input(z.object({ jobId: z.string() })) -``` - -**Impact**: Any authenticated user (including jury members, observers, applicants) can query the status of AI assignment jobs if they know or guess a job ID. While job IDs are UUIDs, this exposes internal platform operations unnecessarily. - -**Recommendation**: Change to `adminProcedure` to restrict to admin users only. - ---- - -#### MED-8: PII Logging in User Router — **DONE** - -**Affected file**: `src/server/routers/user.ts:246,256` - -Debug logging statements expose user data in server logs: -```typescript -console.log('[user.get] Fetching user:', input.id) -console.log('[user.get] Found user:', user.email) -``` - -**Impact**: User IDs and email addresses are written to server logs. Under GDPR, log files containing PII must be treated as personal data and properly managed (retention, access controls, etc.). - -**Recommendation**: Remove debug console.log statements or replace with a structured logger that respects log levels and redacts PII. - ---- - -### Low Severity Findings - -#### LOW-1: Session Configuration Could Be Hardened — **DONE** - -**Affected file**: `src/lib/auth.config.ts:88-90` - -The session uses JWT strategy with a default 24-hour maxAge. No explicit cookie configuration is visible. - -```typescript -session: { - strategy: 'jwt', - maxAge: parseInt(process.env.SESSION_MAX_AGE || '86400'), -}, -``` - -**Impact**: NextAuth v5 sets secure cookie defaults, but explicit configuration is better for defense-in-depth. A 24-hour session may be too long for admin users. - -**Recommendation**: Explicitly set cookie options: `httpOnly: true`, `secure: true` (production), `sameSite: 'lax'`. Consider shorter session lifetimes for admin roles. - ---- - -#### LOW-2: Export Endpoint Allows Large Data Fetches — **DONE** (reduced to 5000) - -**Affected file**: `src/server/routers/export.ts:266` - -```typescript -take: 10000, // Limit export to 10k records -``` - -**Impact**: Large exports could cause memory pressure or slow response times. Admin-only access mitigates the risk. - -**Recommendation**: Consider pagination or streaming exports for large datasets. - ---- - -#### LOW-3: Project List Allows Up to 5000 Items Per Page — **DONE** (reduced to 200) - -**Affected file**: `src/server/routers/project.ts:58` - -```typescript -perPage: z.number().int().min(1).max(5000).default(20), -``` - -**Impact**: A request for 5000 projects with full includes could cause significant memory usage and slow responses. - -**Recommendation**: Reduce the maximum to a reasonable value (e.g., 200) or implement cursor-based pagination for large result sets. - ---- - -#### LOW-4: No CSRF Protection on Custom API Routes — **DONE** - -**Affected files**: `src/app/api/email/verify-credentials/route.ts`, `src/app/api/email/change-password/route.ts`, `src/app/api/storage/local/route.ts` - -These custom API routes (outside of tRPC and NextAuth) accept POST/PUT requests without explicit CSRF token validation. While the Same-Origin Policy and Content-Type restrictions provide some protection, explicit CSRF tokens would add defense-in-depth. - -**Impact**: Low risk due to browser same-origin restrictions, but a defense-in-depth concern. - -**Recommendation**: Consider adding CSRF token validation for custom API routes, especially those that modify state (password change, file upload). - ---- - -#### LOW-5: Invite Token Validation Has No Specific Rate Limit — **N/A** (token entropy sufficient, no action needed) - -**Affected file**: `src/server/routers/user.ts:45-69` - -The `validateInviteToken` is a public procedure protected only by the global tRPC rate limit (100/min per IP). With 256 bits of entropy in the tokens, brute-force is computationally infeasible. - -**Impact**: Negligible due to the token entropy. Listed for completeness. - -**Recommendation**: No immediate action needed. The existing token entropy is sufficient. - ---- - -### Informational Findings (Positive Security Practices) - -#### INFO-1: Comprehensive Audit Logging — **N/A** - -The platform implements thorough audit logging across all critical operations: user management, authentication, evaluations, assignments, file access, exports, and settings changes. Each audit entry includes userId, action, entityType, entityId, details, IP address, and user agent. - -#### INFO-2: Well-Designed RBAC Architecture — **N/A** - -The tRPC middleware-based RBAC system is well-designed with clear role hierarchies (`publicProcedure`, `protectedProcedure`, `adminProcedure`, `superAdminProcedure`, `juryProcedure`, `mentorProcedure`). Role checks are enforced at the procedure level, with additional ownership checks in individual handlers. - -#### INFO-3: No SQL Injection Risk — **N/A** - -The codebase exclusively uses Prisma ORM for database access. The only raw query found is the health check's `SELECT 1`. No user input is interpolated into raw SQL anywhere in the application. - -#### INFO-4: No XSS via dangerouslySetInnerHTML — **N/A** - -No usage of `dangerouslySetInnerHTML` was found in the codebase. React's default escaping provides XSS protection for rendered content. - -#### INFO-5: Environment Variables Properly Gitignored — **N/A** - -All `.env` variants (`.env`, `.env.local`, `.env.development.local`, `.env.test.local`, `.env.production.local`, `docker/.env`) are listed in `.gitignore`. No hardcoded secrets were found in the source code beyond the noted fallback defaults. - -#### INFO-6: Thorough Data Anonymization for AI — **N/A** - -The anonymization service (`src/server/services/anonymization.ts`) comprehensively strips PII (emails, phones, URLs, SSNs, IP addresses) before sending data to OpenAI. GDPR compliance validation is enforced before every AI call. Both basic (assignment) and enhanced (filtering/awards) anonymization paths are implemented with validation. - -#### INFO-7: CSRF Protection via tRPC Content-Type — **N/A** - -tRPC uses `application/json` content type which triggers CORS preflight for cross-origin requests, providing natural CSRF protection. NextAuth routes have built-in CSRF token protection. No permissive CORS headers are configured. - -#### INFO-8: Strong Password Hashing — **N/A** - -bcrypt with 12 salt rounds provides strong password hashing. Account lockout after 5 failed attempts with a 15-minute lockout is implemented. Password reset does not reveal whether an email exists (anti-enumeration pattern). - -#### INFO-9: Jury Data Isolation — **N/A** - -Jury members can only see projects they are assigned to. This is enforced both at the query level (project list endpoint adds `assignments: { some: { userId: ctx.user.id } }`) and via explicit assignment checks in get/evaluation endpoints. - -#### INFO-10: Rate Limiting Coverage — **N/A** - -Rate limiting is applied to: all tRPC endpoints (100 requests/min), auth POST endpoints (10/min), email verification (5 per 15 min), and email password change (3 per 15 min). Headers expose rate limit status for client-side handling. - ---- - -### Security Review Summary - -| Severity | Count | Key Areas | -|----------|-------|-----------| -| Critical | 3 | Path traversal, timing-unsafe HMAC, unauthenticated email routes | -| High | 5 | In-memory rate limiting, error info leaks, hardcoded secrets, user creation without verification | -| Medium | 8 | Password policy, audit reliability, file validation, IP spoofing, access control gaps | -| Low | 5 | Session config, large exports, CSRF on custom routes | -| Informational | 10 | Positive practices observed | - -**Overall Assessment**: The platform demonstrates strong security fundamentals with comprehensive RBAC, audit logging, proper ORM usage (no SQL injection), XSS prevention, and data anonymization for AI services. The critical issues center around the local file storage provider (path traversal bypass, timing-unsafe HMAC comparison) and the email API routes lacking proper authorization checks. The high-severity items relate to deployment concerns (in-memory rate limiting, hardcoded fallback secrets) and the unauthenticated application submission endpoint's ability to create user records without verification. Addressing the critical and high-severity items should be prioritized before production deployment with external exposure. - ---- - -## 5. Feature Proposals & Improvements — **PARTIAL** (10 of 26 features implemented) - -*Reviewed by: Feature Proposer Agent* -*Date: 2026-02-05* - -This section proposes new features and improvements based on a thorough review of the platform's codebase, including all routers, services, pages, components, and data model. Proposals are organized by implementation effort and prioritized by impact. - -> **Note**: This section contains feature proposals for future development. None of these are bugs or issues — they are enhancement ideas preserved as a roadmap reference. - ---- - -### Quick Wins (Low Effort, High Impact) - -#### 5.1.1 Jury Evaluation Reminders & Deadline Countdown — **DONE** - -**What**: Add automated reminder notifications at configurable intervals before voting deadlines (e.g., 72h, 24h, 1h). Show a prominent countdown timer on the jury dashboard and assignment pages when deadline is approaching. - -**Why**: The platform already has `REMINDER_24H` and `REMINDER_1H` notification types defined in the email templates, but there is no scheduled job or cron mechanism to actually trigger these reminders. Jury members may forget deadlines, leading to incomplete evaluations. - -**Who benefits**: Jury Members, Program Admins (higher completion rates) - -**Scope**: Add a scheduled task (cron job or database-polling endpoint) that checks upcoming deadlines and sends notifications. Add countdown UI component to jury dashboard. ~2-3 days. - ---- - -#### 5.1.2 Evaluation Progress Indicator Per Project — **DONE** - -**What**: On the evaluation form page (`/jury/projects/[id]/evaluate`), show a visual progress indicator (e.g., "3 of 5 criteria scored") so jury members know how far along they are before submitting. - -**Why**: The current autosave system tracks partial scores, but there is no visual indicator showing the jury member how many criteria they have completed. This causes friction especially for forms with many criteria. - -**Who benefits**: Jury Members - -**Scope**: Frontend-only change. Add a progress bar or step indicator to the evaluation form component. ~0.5 day. - ---- - -#### 5.1.3 Bulk Status Update for Projects — **DONE** - -**What**: Allow admins to select multiple projects from the project list and change their status in bulk (e.g., mark 20 projects as SEMIFINALIST at once). - -**Why**: Currently, the project router has individual update capabilities but no bulk status change. After reviewing evaluations, admins need to advance multiple projects, which is tedious one-by-one. The filtering router has `finalizeResults` for automated advancement, but there is no manual bulk option outside of filtering. - -**Who benefits**: Program Admins, Super Admins - -**Scope**: Add `bulkUpdateStatus` mutation to project router, add checkbox selection UI to project list page. ~1-2 days. - ---- - -#### 5.1.4 Export Filtering Results as CSV — **DONE** - -**What**: Add CSV export capability for filtering results, similar to the existing evaluation and project score exports. - -**Why**: The export router currently supports evaluations, project scores, assignments, and audit logs, but not filtering results. Admins reviewing AI filtering outcomes may want to share or archive these results externally. - -**Who benefits**: Program Admins - -**Scope**: Add a new endpoint to the export router for filtering results. ~0.5 day. - ---- - -#### 5.1.5 Observer Access to Reports & Analytics — **DONE** - -**What**: Allow observers to view the Reports page (analytics charts and exports) in read-only mode. - -**Why**: The observer dashboard (`/observer`) shows basic stats (program count, project count, juror count, evaluation completion), but observers cannot access the detailed analytics charts (score distribution, evaluation timeline, juror workload, project rankings, geographic distribution) that are on the admin Reports page. The observer role is designed for stakeholders who need visibility without edit access. - -**Who benefits**: Observers (stakeholders, board members) - -**Scope**: Create an `/observer/reports` page that mirrors the admin analytics tab using the existing chart components. Requires adding observer-accessible query variants for the analytics router. ~1-2 days. - ---- - -#### 5.1.6 Conflict of Interest Declaration — **DONE** - -**What**: When a jury member starts an evaluation, prompt them to declare any conflicts of interest with the project. Store the declaration and allow admins to flag/reassign if needed. - -**Why**: In academic and grant judging, conflict of interest management is a standard requirement. Currently there is no mechanism for jurors to declare COI, which could undermine the integrity of the evaluation process. - -**Who benefits**: Jury Members, Program Admins, platform credibility - -**Scope**: Add a `conflictOfInterest` field to the Assignment or Evaluation model, add a COI declaration dialog before evaluation starts, add admin view for flagged COI. ~2-3 days. - ---- - -### Medium-Term (Moderate Effort) - -#### 5.2.1 Email Digest / Summary Notifications - -**What**: Implement a daily or weekly email digest that summarizes a user's pending actions: unfinished evaluations, upcoming deadlines, new assignments, new notifications. Configurable per user (daily/weekly/off). - -**Why**: The notification system sends individual emails per event, which can be noisy. A digest approach reduces email fatigue while ensuring users stay informed. The `NotificationEmailSetting` model exists but only controls per-type settings, not digest frequency. - -**Who benefits**: All roles (Jury Members, Mentors, Admins) - -**Scope**: Add user preference for digest frequency, create digest aggregation service, implement scheduled job to send digests. ~3-5 days. - ---- - -#### 5.2.2 Evaluation Calibration / Norming Session Tool - -**What**: Create a calibration mode where all jurors evaluate the same 2-3 "test" projects, then admins can view the variance in scores and use this to identify outlier jurors or adjust scoring guidance. - -**Why**: In large jury panels (handling 130+ projects), inter-rater reliability is a common challenge. Some jurors may be consistently lenient or harsh. A calibration round helps ensure scoring consistency and is standard practice in grant review and academic conferences. - -**Who benefits**: Program Admins (quality assurance), Jury Members (alignment) - -**Scope**: Add a "calibration round" type, mark specific projects as calibration, create comparison analytics showing juror variance on calibration projects. ~5-7 days. - ---- - -#### 5.2.3 Multi-Language Support (i18n) - -**What**: Add internationalization support, starting with French and English. The platform is for Monaco, which is French-speaking, but the jury may be international. - -**Why**: Monaco is a French-speaking principality, and many stakeholders and applicants may prefer French. The current platform is English-only. This is especially important for the public application form and applicant-facing pages. - -**Who benefits**: Applicants, Jury Members, all French-speaking users - -**Scope**: Integrate next-intl or similar i18n library, extract all user-facing strings, translate to French. Start with public-facing pages (application form, login, applicant portal). ~5-10 days for initial setup + French translation. - ---- - -#### 5.2.4 Project Comparison View for Jury - -**What**: Allow jury members to view 2-3 assigned projects side-by-side in a comparison view, showing key details (title, description, team, country, tags) next to each other. - -**Why**: When evaluating 15-20 projects, jurors often want to compare similar projects before assigning scores. Currently they must navigate between individual project pages, losing context. - -**Who benefits**: Jury Members - -**Scope**: Create a new comparison page that loads multiple projects, side-by-side layout. ~3-4 days. - ---- - -#### 5.2.5 Applicant Portal Enhancements — **DONE** - -**What**: Expand the applicant portal (`/my-submission`) with: -- Application status tracking with timeline (submitted -> under review -> semifinalist -> finalist) -- Ability to upload supplementary documents after initial submission (within a deadline) -- Team member management (add/remove members, update roles) -- Communication channel with mentors (if assigned) - -**Why**: The current applicant portal shows submission details and team management, but lacks a status timeline and post-submission document upload. These are standard features in grant/competition platforms. The team management page exists but could be enriched. - -**Who benefits**: Applicants - -**Scope**: Enhance the existing `/my-submission/[id]` pages with status timeline component, add supplementary upload endpoint, enrich team management. ~5-7 days. - ---- - -#### 5.2.6 Round Templates - -**What**: Allow admins to create round templates that pre-configure evaluation criteria, assignment constraints, voting windows, and filtering rules. When creating a new round, they can select a template instead of configuring everything from scratch. - -**Why**: If the MOPC runs annually, admins will repeat similar configurations each year. Templates reduce setup time and ensure consistency across editions. Currently, every new round requires manual configuration of all parameters. - -**Who benefits**: Program Admins, Super Admins - -**Scope**: Add a `RoundTemplate` model, create template management UI, add "Create from template" option in round creation. ~3-5 days. - ---- - -#### 5.2.7 Jury Member Availability & Workload Preferences - -**What**: Allow jury members to set their availability (date ranges when they can evaluate) and preferred workload (number of projects they are comfortable reviewing). Surface this to admins during assignment. - -**Why**: The current system has `maxAssignments` per user but no availability dates. Jurors may have travel or work conflicts during part of the voting window. Knowing availability helps admins assign projects more effectively. - -**Who benefits**: Jury Members, Program Admins - -**Scope**: Add availability fields to user profile, surface in assignment UI, factor into smart assignment algorithm. ~3-4 days. - ---- - -#### 5.2.8 Real-Time Voting Dashboard for Live Events - -**What**: Enhance the live voting feature with a real-time scoreboard using Server-Sent Events or WebSocket polling. Currently, the live voting uses standard HTTP polling. Add a large-screen "presentation mode" showing live score animations as votes come in. - -**Why**: The live voting feature (`/admin/rounds/[id]/live-voting`) and public scores page (`/live-scores/[sessionId]`) exist but use standard queries with manual refresh. For a live event with an audience, real-time updates with animations create a much more engaging experience. - -**Who benefits**: Event organizers, audience, Jury Members at live events - -**Scope**: Add SSE or WebSocket endpoint for vote updates, create presentation mode component with animations, add audience count display. ~5-7 days. - ---- - -#### 5.2.9 AI-Powered Evaluation Summary — **DONE** - -**What**: After all evaluations are submitted for a project, use AI to generate a summary of the jurors' collective feedback. Group common themes, highlight strengths and weaknesses mentioned by multiple jurors. - -**Why**: Admins currently see individual evaluation scores and feedback text. Synthesizing feedback from 3-5 jurors manually is time-consuming. An AI summary helps admins quickly understand the consensus view, and could be shared with applicants as constructive feedback. - -**Who benefits**: Program Admins, Applicants (if feedback is shared) - -**Scope**: Add AI summary service using existing OpenAI integration, create summary generation endpoint (on-demand, not automatic), add summary display in project detail view. ~3-5 days. - ---- - -### Long-Term (Ambitious, High Impact) - -#### 5.3.1 Public Website Module - -**What**: Build the public-facing website for monaco-opc.com, including: -- Homepage with program overview, timeline, and partner logos -- "Apply" landing page with program details and application form link -- Past winners gallery with project descriptions and photos/videos -- News/blog section for announcements -- Partner showcase page - -**Why**: Listed as a "Future" feature in CLAUDE.md. The platform currently has no public website -- only the internal portal. A public site is essential for program visibility, applicant recruitment, and sponsor recognition. - -**Who benefits**: Applicants (discovery), Partners (visibility), Program (credibility) - -**Scope**: Build Next.js pages under `(public)` route group, CMS-like content management for news/blog, integrate existing partner data. ~15-25 days. - ---- - -#### 5.3.2 Communication Hub - -**What**: Add an integrated messaging system within the platform: -- Admin-to-jury broadcast messages -- Admin-to-team (applicant) messages with templates -- Mentor-to-team direct messaging -- Message templates for common communications (congratulations, not selected, next steps) -- Integration with existing email notification system - -**Why**: Currently, communications happen outside the platform (email, potentially WhatsApp). The WhatsApp integration library exists (`src/lib/whatsapp/`) but is not wired to any router. An in-platform communication hub creates a single source of truth for all program communications and enables better audit trails. - -**Who benefits**: All roles - -**Scope**: Add Message model, create messaging router, build inbox/compose UI, integrate with email and potentially WhatsApp providers. ~10-15 days. - ---- - -#### 5.3.3 Advanced Analytics & Reporting Dashboard - -**What**: Expand analytics with: -- Cross-round comparison (how did scores change between Round 1 and Round 2 for advancing projects?) -- Juror consistency analysis (standard deviation per juror, score correlation between jurors) -- Diversity metrics (geographic distribution of advancing projects, category balance) -- Year-over-year trends (if multi-edition data exists) -- Exportable PDF reports with charts for board presentations -- Custom report builder (select metrics, date ranges, filters) - -**Why**: The current analytics router provides good per-round views (score distribution, timeline, workload, rankings, criteria scores, geographic distribution), but lacks cross-round and historical analysis. For a program that runs annually, trend analysis is valuable for demonstrating impact to stakeholders. - -**Who benefits**: Program Admins, Super Admins, Observers, Board Members - -**Scope**: Add cross-round query endpoints, create new chart components, build PDF export using a library like @react-pdf/renderer. ~10-15 days. - ---- - -#### 5.3.4 Applicant Self-Service with Draft Saving - -**What**: Enhance the public application form to support: -- Save as draft and resume later (using magic link or email verification) -- Multi-step form with progress saving between sessions -- File uploads during application (pitch deck, business plan, video) -- Application preview before final submission - -**Why**: The current application form (`/apply/[slug]`) submits everything in one go. For complex applications requiring a business plan and team details, applicants may need multiple sessions to complete their submission. Draft saving is standard in grant application platforms. - -**Who benefits**: Applicants - -**Scope**: Add draft application model, magic link authentication for applicants, file upload integration in application form, preview component. ~7-10 days. - ---- - -#### 5.3.5 Webhooks & API Integration Layer - -**What**: Add a webhook system that fires events when key actions occur: -- Application submitted -- Project status changed (advanced, rejected) -- Evaluation submitted -- Round status changed -- Award winner selected - -Allow admins to configure webhook URLs for external integrations (CRM, Slack, custom dashboards). - -**Why**: The platform is currently self-contained. Organizations often need to integrate with external systems (CRM for applicant tracking, Slack for admin notifications, donor databases). A webhook system enables this without custom code for each integration. - -**Who benefits**: Program Admins, Super Admins, external system integrations - -**Scope**: Add Webhook model (url, events, secret), create webhook dispatch service, add admin webhook configuration UI. ~5-7 days. - ---- - -#### 5.3.6 Peer Review / Collaborative Evaluation Notes - -**What**: After individual evaluations are submitted (and locked), allow jurors assigned to the same project to see anonymized summaries of other jurors' scores and feedback. Enable optional discussion threads for projects where scores diverge significantly. - -**Why**: In academic peer review, after independent evaluation, reviewers often discuss divergent opinions to reach consensus. Currently, jurors submit in isolation with no visibility into other evaluations. For borderline projects, discussion can improve decision quality. - -**Who benefits**: Jury Members, Program Admins (better decisions) - -**Scope**: Add post-evaluation discussion model, create discussion thread UI, implement anonymization for jury comments, add divergence detection logic. ~7-10 days. - ---- - -### Improvements to Existing Features - -#### 5.4.1 Smart Assignment Algorithm Improvements — **DONE** - -**Current state**: The smart assignment algorithm in `assignment.ts:getSuggestions` uses expertise matching (35%), load balancing (20%), and under-min-target bonus (15%). The AI assignment uses GPT for more nuanced matching. - -**Improvement**: Add the following factors to the algorithm: -- **Geographic diversity**: Ensure projects from the same country are not all assigned to the same juror -- **Previous round familiarity**: If a juror evaluated a project in Round 1, prioritize assigning them the same project in Round 2 for continuity (or explicitly avoid it for fresh perspective, configurable) -- **Conflict avoidance**: If COI declarations are implemented, auto-exclude conflicted jurors - -**Scope**: Modify the scoring algorithm in the getSuggestions and AI assignment services. ~2-3 days. - ---- - -#### 5.4.2 Evaluation Form Flexibility — **DONE** - -**Current state**: Evaluation criteria are configurable per round with labels, descriptions, scales, and weights. Criteria support numeric scoring (1-10). - -**Improvement**: -- Add support for **text-only criteria** (qualitative feedback without a numeric score) -- Add support for **yes/no criteria** (boolean questions like "Does this project have a viable business model?") -- Add **conditional criteria** (show criterion B only if criterion A score is above 7) -- Add **criterion grouping** (organize criteria into sections like "Innovation", "Impact", "Feasibility") - -**Scope**: Extend the criteria JSON schema, update the evaluation form component to render different input types. ~3-5 days. - ---- - -#### 5.4.3 Audit Log Enhancements - -**Current state**: Comprehensive audit logging exists for most actions. The audit page shows logs with filtering by user, action type, entity type, and date range. - -**Improvement**: -- Add **before/after diff** for update actions (store previous values alongside new values) -- Add **session tracking** (group actions from the same login session) -- Add **anomaly detection** (flag unusual patterns like bulk deletes or rapid score changes) -- Add **audit log retention policy** (auto-archive logs older than X months) - -**Scope**: Enhance audit log creation to capture previous state, add session ID tracking, build anomaly detection service. ~5-7 days. - ---- - -#### 5.4.4 File Management Improvements - -**Current state**: Files are uploaded to MinIO with pre-signed URLs. Files are associated with projects and have types (exec summary, presentation, video, etc.). - -**Improvement**: -- Add **file versioning** (track file replacements, keep history) -- Add **file preview** (inline PDF viewer, video player, image thumbnails) instead of download-only -- Add **file size and type validation** on upload (client-side + server-side) -- Add **virus scanning** integration for uploaded files -- Add **bulk file download** (zip multiple project files for offline review) - -**Scope**: Add file version tracking, integrate a PDF viewer component, add validation middleware. ~5-7 days. - ---- - -#### 5.4.5 Live Voting UX Improvements - -**Current state**: Live voting allows admin to control sessions, set project order, start/stop voting windows. Jury members vote on the current project. - -**Improvement**: -- Add **QR code generation** for the voting URL so audience members can scan and vote on their phones -- Add **countdown timer** with visual animations when time is running low -- Add **score reveal animation** after voting closes for each project -- Add **tie-breaking mechanism** configuration -- Add **audience vote** option (separate from jury vote, displayed alongside but not counted in official scoring) - -**Scope**: QR code generation, animation components, tie-breaking logic. ~5-7 days. - ---- - -#### 5.4.6 Mentor Dashboard Enhancements - -**Current state**: Mentors can view their assigned projects, project details, team members, and files. The mentor dashboard shows a list of assignments. - -**Improvement**: -- Add **mentoring milestones/checklist** (configurable per program: "Initial meeting", "Business plan review", "Pitch preparation") -- Add **mentor notes** on each project (private notes visible only to the mentor and admins) -- Add **mentor-to-team communication** within the platform -- Add **mentor activity tracking** (when did the mentor last view the project?) -- Add **mentorship completion status** tracking - -**Scope**: Add MentorNote model, milestone checklist model, enhance mentor project detail page. ~5-7 days. - ---- - -#### 5.4.7 Application Form Builder (Admin Configurable) - -**Current state**: The application form has a fixed schema defined in `application.ts` with hard-coded fields (category, contact info, project details, team members, additional info). - -**Improvement**: Allow admins to configure the application form fields per round, similar to how evaluation criteria are configurable. Support: -- Custom text fields, dropdowns, checkboxes -- Required vs optional fields -- Conditional fields (show field B if field A has value X) -- Custom validation rules -- Field ordering via drag-and-drop - -**Why**: Different programs or editions may require different application information. The current hard-coded form works for MOPC but limits reusability. - -**Scope**: Create form builder model (similar to EvaluationForm's criteriaJson), build form builder UI, dynamic form renderer. ~7-10 days. - ---- - -### Priority Matrix - -| Priority | Feature | Impact | Effort | Status | -|----------|---------|--------|--------|--------| -| P0 | 5.1.1 Jury Evaluation Reminders | High | Low | **DONE** | -| P0 | 5.1.2 Evaluation Progress Indicator | High | Very Low | **DONE** | -| P0 | 5.1.3 Bulk Project Status Update | High | Low | **DONE** | -| P0 | 5.1.6 Conflict of Interest Declaration | High | Low | **DONE** | -| P1 | 5.1.4 Export Filtering Results | Medium | Very Low | **DONE** | -| P1 | 5.1.5 Observer Access to Reports | Medium | Low | **DONE** | -| P1 | 5.2.1 Email Digest Notifications | High | Medium | | -| P1 | 5.2.5 Applicant Portal Enhancements | High | Medium | **DONE** | -| P1 | 5.2.9 AI Evaluation Summary | High | Medium | **DONE** | -| P1 | 5.4.2 Evaluation Form Flexibility | High | Medium | **DONE** | -| P2 | 5.2.2 Evaluation Calibration Tool | Medium | Medium | | -| P2 | 5.2.4 Project Comparison View | Medium | Medium | | -| P2 | 5.2.6 Round Templates | Medium | Medium | | -| P2 | 5.2.7 Jury Availability Preferences | Medium | Medium | | -| P2 | 5.2.8 Real-Time Live Voting | Medium | Medium | | -| P2 | 5.4.1 Smart Assignment Improvements | Medium | Low | **DONE** | -| P2 | 5.4.4 File Management Improvements | Medium | Medium | | -| P2 | 5.4.5 Live Voting UX Improvements | Medium | Medium | | -| P2 | 5.4.6 Mentor Dashboard Enhancements | Medium | Medium | | -| P3 | 5.2.3 Multi-Language Support | High | High | | -| P3 | 5.3.1 Public Website Module | High | High | | -| P3 | 5.3.2 Communication Hub | High | High | | -| P3 | 5.3.3 Advanced Analytics Dashboard | Medium | High | | -| P3 | 5.3.4 Applicant Self-Service Drafts | Medium | Medium | | -| P3 | 5.3.5 Webhooks & API Integration | Medium | Medium | | -| P3 | 5.3.6 Peer Review / Collaborative Notes | Medium | High | | -| P3 | 5.4.3 Audit Log Enhancements | Low | Medium | | -| P3 | 5.4.7 Application Form Builder | Medium | High | | +# MOPC Platform Review + +> **Status Legend**: Each finding is marked with its implementation status: +> - **DONE** - Implemented and verified +> - **DEFERRED** - Cannot be done now (requires infrastructure, design decisions, or is too risky) +> - **N/A** - Not actionable (positive observation or informational) +> - **SKIPPED** - Intentionally not addressed (low impact or not worth the risk) + +## 1. UI/UX Design Review + +**Reviewer**: UI/UX Design Reviewer +**Date**: 2026-02-05 +**Scope**: All pages, components, design patterns, mobile responsiveness, UX states, information architecture, interaction patterns, accessibility, visual polish + +--- + +### Overall Assessment + +The MOPC platform demonstrates strong foundational UI/UX work. shadcn/ui provides a consistent base, skeleton loading states are implemented throughout, and the evaluation form offers excellent UX with autosave and slider+button scoring. However, there are meaningful gaps in mobile responsiveness, navigation consistency, typography adherence, and error states that should be addressed before a public-facing launch. + +--- + +### 1.1 Design System & Theming + +#### DS-1: Public layout uses Inter font instead of Montserrat (Medium) — **DONE** + +**File**: `src/app/(public)/layout.tsx:4-5` + +The public layout imports Google's Inter font and applies it to the entire public section. The brand identity specifies Montserrat as the platform typeface (defined in `globals.css` via `@font-face`). Every other layout uses the root font (Montserrat via `font-sans`), but public pages render in Inter. + +```tsx +import { Inter } from 'next/font/google' +const inter = Inter({ subsets: ['latin'] }) +``` + +**Impact**: Brand inconsistency on the most externally-visible pages. + +**Recommendation**: Remove the Inter import and use the existing Montserrat font from the root layout. Apply `className="font-sans"` if needed. + +--- + +#### DS-2: Public layout uses placeholder logo instead of MOPC logo component (Low) — **DONE** + +**File**: `src/app/(public)/layout.tsx:20-22` + +The public layout renders a hardcoded `
` with "M" text instead of using the existing `Logo` component at `src/components/shared/logo.tsx`. + +```tsx +
+ M +
+``` + +**Recommendation**: Import and use the `Logo` component with `variant="small"`. + +--- + +#### DS-3: Dark mode CSS defined but no toggle exposed (Low) — **DONE** + +**File**: `src/app/globals.css` (dark mode variables block) + +Full dark mode color tokens are defined in globals.css under `@media (prefers-color-scheme: dark)`, but there is no theme toggle anywhere in the UI. Users with dark system preferences will see the dark theme, but cannot switch. This creates an untested UX path. + +**Recommendation**: Either add a theme toggle in settings/nav (using `next-themes`), or remove the dark mode definitions to ensure consistent appearance. If dark mode is deferred, add `class="light"` to the `` tag to force light mode. + +--- + +#### DS-4: Card `CardTitle` default size is too large and always overridden (Low) — **DONE** + +**File**: `src/components/ui/card.tsx` + +`CardTitle` defaults to `text-2xl tracking-tight`, but nearly every usage in the codebase adds custom sizing classes. This suggests the default is not useful. + +**Recommendation**: Change the default to `text-lg font-semibold` which matches the most common override pattern. + +--- + +### 1.2 Navigation & Information Architecture + +#### NAV-1: Inconsistent active state styling across role navigation components (Medium) — **DONE** + +**Files**: +- `src/components/layouts/jury-nav.tsx` - Uses `bg-primary/10 text-primary` +- `src/components/layouts/mentor-nav.tsx` - Uses `bg-primary/10 text-primary` +- `src/components/layouts/observer-nav.tsx` - Uses `bg-primary text-primary-foreground` (solid background) + +The observer nav uses a completely different active state style (solid filled background) compared to jury and mentor navs (subtle tinted background). This inconsistency is jarring for users who switch between roles. + +**Recommendation**: Unify active state styling. Better yet, extract all three into a shared `RoleNav` component as noted in the code quality review (4.1.4). + +--- + +#### NAV-2: Notification bell links are hardcoded to admin paths (Medium) — **DONE** + +**File**: `src/components/shared/notification-bell.tsx` + +The notification bell component links to `/admin/settings` and `/admin/notifications` regardless of the user's role. Jury members, mentors, and observers will be redirected or see 403 errors when clicking these links. + +**Recommendation**: Use role-aware paths (e.g., `/${role}/notifications`) or a role-neutral `/notifications` route. + +--- + +#### NAV-3: Jury nav is missing Awards link (Low) — **DONE** + +**File**: `src/components/layouts/jury-nav.tsx` + +The jury navigation includes Dashboard, My Assignments, and Learning Hub. There is no link to special awards even though jury members may need to view award-eligible projects. The admin sidebar includes awards management, but there is no jury-facing awards view link. + +**Recommendation**: Add an Awards link to the jury navigation if jury members should be able to view special award results. + +--- + +#### NAV-4: Admin sidebar user section uses hardcoded colors (Low) — **DONE** + +**File**: `src/components/layouts/admin-sidebar.tsx:247-267` + +The user info section at the bottom of the admin sidebar uses hardcoded `slate-200`, `slate-300`, `slate-700`, `slate-400` colors instead of semantic tokens like `muted`, `muted-foreground`, `border`. + +**Recommendation**: Replace with semantic color tokens for consistency with the rest of the design system and proper dark mode support. + +--- + +### 1.3 Mobile Responsiveness + +#### MOB-1: Admin rounds table is not responsive (High) — **DONE** + +**File**: `src/app/(admin)/admin/rounds/page.tsx` + +The rounds management page uses a fixed 7-column grid (`grid-cols-7`) that does not adapt to mobile or tablet screens. On narrow viewports, content will overflow or become illegible. Unlike the projects page (which has separate table/card views), rounds has no mobile layout. + +**Recommendation**: Implement a mobile card layout for rounds similar to the project list's mobile view. Show the full table only on `lg:` screens. + +--- + +#### MOB-2: Pagination component is not mobile-optimized (Medium) — **DONE** + +**File**: `src/components/shared/pagination.tsx` + +The pagination component renders all page numbers without truncation. For datasets with many pages, this creates a long horizontal row that overflows on mobile. + +**Recommendation**: Show abbreviated pagination on mobile: first, previous, current, next, last. Use `hidden sm:flex` to show the full pagination only on larger screens. + +--- + +#### MOB-3: Admin dashboard stat cards lack stacking on small screens (Low) — **DONE** + +**File**: `src/app/(admin)/admin/page.tsx` + +The admin dashboard uses `grid-cols-2 md:grid-cols-4` for the stats grid. On very narrow phones (< 360px), two columns may still be too wide for the stat cards. + +**Recommendation**: Consider `grid-cols-1 sm:grid-cols-2 md:grid-cols-4` for the narrowest phones. + +--- + +### 1.4 UX States & Feedback + +#### UX-1: No global 404 or error pages (Medium) — **DONE** + +**Files**: Only `src/app/(auth)/error/page.tsx` exists (auth-specific errors) + +There is no `src/app/not-found.tsx` or `src/app/error.tsx`. Users who navigate to non-existent routes will see Next.js's default 404 page, which has no MOPC branding, navigation, or helpful direction. + +**Recommendation**: Create `src/app/not-found.tsx` with MOPC branding, a message, and a link back to the dashboard. Create `src/app/error.tsx` for runtime errors. + +--- + +#### UX-2: Profile settings page has three identical save buttons (Medium) — **DONE** + +**File**: `src/app/(settings)/settings/profile/page.tsx:240-252, 286-298, 321-333` + +The profile page has three separate "Save" buttons (Save Changes, Save Preferences, Save Expertise) that all call the same `handleSaveProfile` function. This means clicking "Save Expertise" also saves any pending name/bio changes, which may confuse users. + +**Recommendation**: Either use a single save button at the bottom of the page for all profile fields, or make each section save independently by splitting the mutation into separate API calls. + +--- + +#### UX-3: Form state initialized via conditional in render body (Low) — **DONE** + +**File**: `src/app/(settings)/settings/profile/page.tsx:76-84` + +```tsx +if (user && !profileLoaded) { + setName(user.name || '') + // ... + setProfileLoaded(true) +} +``` + +This pattern of calling `setState` during render is fragile. React may batch these calls unpredictably, and the `profileLoaded` guard can fail during concurrent rendering. + +**Recommendation**: Use `useEffect` to populate form state when user data loads, or use React Hook Form with `defaultValues` from the query data. + +--- + +#### UX-4: Mentor dashboard uses client-side loading instead of Suspense (Low) — **DONE** + +**File**: `src/app/(mentor)/mentor/page.tsx` + +The mentor dashboard conditionally renders a loading spinner based on `isLoading` from tRPC queries, rather than using React Suspense boundaries. Other dashboards (admin) use server components. This creates inconsistency in the loading experience. + +**Recommendation**: Convert to a server component with Suspense, or at minimum use skeleton loading states (as the admin dashboard does) instead of a centered spinner. + +--- + +### 1.5 Interaction Patterns + +#### INT-1: Evaluation form is excellent (Positive) — **N/A** + +**File**: `src/components/forms/evaluation-form.tsx` + +The evaluation form demonstrates outstanding UX: +- Autosave with debounce and visual status indicator +- Dual input for scores: slider drag + direct button click +- Score label changes dynamically based on value +- Sticky status bar showing save state +- Confirmation dialog before final submission +- Read-only mode for past evaluations +- Character counter on text fields + +This should be the UX benchmark for all forms in the platform. + +--- + +#### INT-2: Button press feedback is well-implemented (Positive) — **N/A** + +**File**: `src/components/ui/button.tsx` + +All buttons include `active:scale-[0.98]` for tactile press feedback. Combined with proper `disabled` states and loading spinners (`Loader2` with `animate-spin`), the button interactions feel responsive and polished. + +--- + +#### INT-3: File upload component is well-designed (Positive) — **N/A** + +**File**: `src/components/shared/file-upload.tsx` + +The file upload supports drag-and-drop with visual hover state, progress bar during upload, file type and size validation with clear error messages, and a preview of uploaded files. This is production-ready UX. + +--- + +#### INT-4: Onboarding wizard has strong UX (Positive) — **N/A** + +**File**: `src/app/(auth)/onboarding/page.tsx` + +The multi-step onboarding uses: +- Brand gradient background for visual distinction +- Step indicator with progress +- Form validation per step +- Expertise tag selection with TagInput component +- Smooth transitions between steps + +--- + +### 1.6 Accessibility + +#### A11Y-1: Muted foreground color may have insufficient contrast (Medium) — **DONE** + +**File**: `src/app/globals.css` + +The `--muted-foreground` color (used for secondary text, placeholders, descriptions) is defined as `hsl(215.4 16.3% 46.9%)` in light mode. This corresponds to approximately `#6b7280` which provides ~4.6:1 contrast against white. While this passes WCAG AA for normal text (4.5:1), it fails for small text and is very close to the threshold. + +Many description texts and helper texts throughout the platform use `text-muted-foreground` at small sizes (`text-xs`, `text-sm`). + +**Recommendation**: Darken `--muted-foreground` slightly to ensure comfortable reading, especially for `text-xs` usage. Aim for at least 5:1 contrast ratio. + +--- + +#### A11Y-2: Focus styles are properly implemented (Positive) — **N/A** + +**File**: `src/app/globals.css`, `src/components/ui/button.tsx` + +The design system includes `focus-visible:ring-2 focus-visible:ring-ring` on interactive elements. This provides clear keyboard navigation indicators without affecting mouse users. This is correctly implemented across all shadcn/ui base components. + +--- + +#### A11Y-3: Skeleton loading states provide good screen reader context (Positive) — **N/A** + +**Files**: Multiple pages using `` components + +Loading states use semantic skeleton placeholders instead of spinners, which gives screen readers (via `aria-busy` on parent containers) context about what is loading. + +--- + +### 1.7 Visual Polish + +#### VP-1: Landing page is minimal and unbranded (Medium) — **DONE** + +**File**: `src/app/page.tsx` + +The landing/home page is very minimal. For a platform representing the Monaco Ocean Protection Challenge, the entry point should convey the mission and brand more strongly. + +**Recommendation**: Enhance the landing page with the MOPC logo, brand colors, a brief mission statement, and a clear CTA to login or learn more. Use the brand gradient seen in the onboarding flow. + +--- + +#### VP-2: Auth error page is generic (Low) — **DONE** + +**File**: `src/app/(auth)/error/page.tsx` + +The auth error page shows a basic card with the error message. It does not use MOPC branding or provide helpful navigation (e.g., "Return to Login" or "Contact Support"). + +**Recommendation**: Add MOPC branding, a supportive error message, and navigation options. + +--- + +#### VP-3: Observer dashboard "read-only" notice could be more prominent (Low) — **DONE** + +**File**: `src/app/(observer)/observer/page.tsx` + +The observer dashboard shows a subtle info card noting read-only access. Given that observers might expect interactivity, this notice could be more visually distinct. + +**Recommendation**: Use a persistent banner or badge-style indicator near the page header. + +--- + +### 1.8 Summary Table + +| Category | Findings | High | Medium | Low | Positive | +|----------|----------|------|--------|-----|----------| +| Design System & Theming | 4 | 0 | 1 | 3 | 0 | +| Navigation & IA | 4 | 0 | 2 | 2 | 0 | +| Mobile Responsiveness | 3 | 1 | 1 | 1 | 0 | +| UX States & Feedback | 4 | 0 | 2 | 2 | 0 | +| Interaction Patterns | 4 | 0 | 0 | 0 | 4 | +| Accessibility | 3 | 0 | 1 | 0 | 2 | +| Visual Polish | 3 | 0 | 1 | 2 | 0 | +| **Total** | **25** | **1** | **8** | **10** | **6** | + +--- + +### Quick Wins (< 1 hour each) + +1. **DS-1**: Replace Inter with Montserrat in public layout +2. **DS-2**: Use Logo component in public layout +3. **NAV-4**: Replace hardcoded slate colors with semantic tokens +4. **UX-3**: Move form state initialization to useEffect +5. **VP-2**: Add branding and navigation to auth error page +6. **DS-4**: Adjust CardTitle default size +7. **NAV-3**: Add Awards link to jury nav (if applicable) + +### Longer-Term Improvements + +1. **MOB-1**: Build responsive card layout for rounds table (High priority) +2. **UX-1**: Create global 404 and error pages +3. **NAV-1/NAV-2**: Unify navigation components and fix notification paths +4. **A11Y-1**: Audit and improve muted-foreground contrast +5. **VP-1**: Redesign landing page with full MOPC branding +6. **MOB-2**: Implement truncated mobile pagination +7. **UX-2**: Fix profile settings save button behavior +8. **DS-3**: Either implement dark mode toggle or force light mode +9. **UX-4**: Standardize loading patterns across dashboards + +--- + +## 3. Database Schema & Implementation Review + +**Reviewer**: Database & Backend Reviewer +**Date**: 2026-02-05 +**Scope**: Prisma schema, tRPC routers, services, indexing, query patterns, data integrity + +--- + +### Overall Assessment + +The schema is well-structured for its domain with good use of Prisma features. The codebase demonstrates solid TypeScript/Prisma patterns, proper use of enums, composite unique constraints, and consistent audit logging. However, there are several areas where improvements in indexing, query efficiency, transaction usage, and data integrity would enhance performance and reliability, particularly as the platform scales beyond Phase 1. + +--- + +### Schema Design + +#### SD-1: Project.roundId is required but treated as optional (High) — **DEFERRED** (requires design decision on pool project architecture) + +**Files**: `prisma/schema.prisma:417`, `src/server/routers/round.ts:631-639` + +The `Project` model declares `roundId String` as a required (non-nullable) field and has a required relation `round Round @relation(...)`. However, in `round.removeProjects`, the code sets `roundId: null as unknown as string`, which is a type-unsafe workaround to force a null into a non-nullable field. Similarly, `project.listPool` queries for `roundId: null`, which would never match if the schema is enforced. + +**Impact**: Data integrity violation; Prisma may not enforce this at the DB level with `@default()` but PostgreSQL will reject nulls on a NOT NULL column. + +**Recommendation**: Either make `roundId` optional (`String?`) with an optional relation if projects can be unassigned from rounds, or implement a "pool" round concept. The current workaround is fragile and could fail at the database level. + +--- + +#### SD-2: Evaluation versioning is declared but not implemented (Medium) — **DONE** (documented as deferred in schema with TODO comment) + +**Files**: `prisma/schema.prisma:570`, `src/server/routers/evaluation.ts` + +The `Evaluation` model has a `version Int @default(1)` field and the CLAUDE.md states "Evaluations are versioned - edits create new versions." However, the evaluation router's `autosave` and `submit` mutations update in-place and never create new versioned rows. The version field is never incremented. + +**Impact**: The stated requirement for version history is not fulfilled. If an admin or auditor needs to see how an evaluation changed over time, that data is lost. + +**Recommendation**: Either implement proper versioning (create new Evaluation rows with incremented version on re-submission) or remove the `version` field to avoid confusion. If versioning is deferred, document it clearly. + +--- + +#### SD-3: Soft deletes not implemented (Medium) — **DEFERRED** (massive schema change, requires careful planning) + +**Files**: All routers using `.delete()`, `prisma/schema.prisma` + +The CLAUDE.md architecture decisions (ADR #7) state "Soft deletes: Audit trail, recovery, referential integrity." However, no model has a `deletedAt` field, and all delete operations use hard deletes (e.g., `project.delete`, `user.delete`, `round.delete`). The `User.delete` cascades through assignments, evaluations, and other relations. + +**Impact**: Once deleted, data cannot be recovered. For a jury voting platform where audit trails are critical, this is a significant gap. Deleting a user cascades through assignments and evaluations, potentially destroying evaluation data. + +**Recommendation**: Add `deletedAt DateTime?` to critical models (`User`, `Project`, `Evaluation`, `Assignment`), implement soft delete middleware via Prisma's `$extends`, and ensure all queries filter out soft-deleted records. + +--- + +#### SD-4: LiveVotingSession.status is a String, not an Enum (Low) — **DONE** + +**Files**: `prisma/schema.prisma:918` + +The `LiveVotingSession.status` field is typed as `String @default("NOT_STARTED")` with valid values documented in a comment. Other status fields use proper enums. + +**Impact**: No database-level validation of valid status values. + +**Recommendation**: Create a `LiveVotingSessionStatus` enum with values `NOT_STARTED`, `IN_PROGRESS`, `PAUSED`, `COMPLETED`. + +--- + +#### SD-5: InAppNotification.priority and type are Strings, not Enums (Low) — **DONE** + +**Files**: `prisma/schema.prisma:737-738` + +Similar to SD-4, `priority` and `type` on `InAppNotification` are strings but have a fixed set of known values. The service defines `NotificationPriority` as a TypeScript type but it's not enforced at the database level. + +**Recommendation**: Create enums for `priority` (low/normal/high/urgent). The `type` field has many values that expand over time, so keeping it as a string is acceptable, but `priority` should be an enum. + +--- + +#### SD-6: Redundant date fields on Round (Low) — **DEFERRED** (fields still actively used in application/round routers) + +**Files**: `prisma/schema.prisma:348-353` + +The `Round` model has both `submissionDeadline` and `submissionEndDate` with a comment "replaces submissionDeadline if set". Additionally, `phase1Deadline` and `phase2Deadline` exist but appear unused in any router. This creates confusion about which fields are authoritative. + +**Recommendation**: Remove deprecated fields (`submissionDeadline` if replaced by `submissionEndDate`) and either implement or remove `phase1Deadline`/`phase2Deadline`. + +--- + +### Indexing + +#### IX-1: Missing composite index on Evaluation for round-based queries (High) — **DONE** + +**Files**: `prisma/schema.prisma:554-584` + +Many queries filter evaluations by `assignment.roundId` (e.g., `evaluation.listByRound`, all analytics queries, `export.evaluations`). This requires a join through the `Assignment` table. There is no index on `Evaluation.formId` paired with `status`, and more critically, the join through `assignment.roundId` means these queries perform a nested lookup. + +**Impact**: As evaluation counts grow (130+ projects x 3+ reviews = 390+ evaluations per round), these queries will slow down. + +**Recommendation**: Consider denormalizing `roundId` onto the `Evaluation` table or adding a database view. At minimum, ensure the existing `@@index([status])` and `@@index([formId])` are sufficient with the join pattern. + +--- + +#### IX-2: AuditLog table will grow unbounded (Medium) — **DEFERRED** (requires DBA decision on partitioning strategy) + +**Files**: `prisma/schema.prisma:638-663` + +The `AuditLog` table has good indexes (`userId`, `action`, `entityType+entityId`, `timestamp`) but no partitioning or archival strategy. With every CRUD operation, status change, login, and export generating audit entries, this table will grow rapidly. + +**Impact**: Query performance degradation over time, especially for `audit.getStats` which does `groupBy` operations across the entire table. + +**Recommendation**: Implement time-based partitioning on `timestamp`, or add an archival job that moves old audit logs to a separate table. Consider adding a composite index on `(entityType, entityId, timestamp)` for the `getByEntity` query. + +--- + +#### IX-3: User.email has both @unique and @@index (Low) — **DONE** + +**Files**: `prisma/schema.prisma:192, 262` + +`email String @unique` already creates a unique index. The additional `@@index([email])` is redundant. + +**Impact**: Extra write overhead on every user insert/update for maintaining a duplicate index. + +**Recommendation**: Remove `@@index([email])`. + +--- + +#### IX-4: Missing index on GracePeriod for combined lookups (Low) — **DONE** + +**Files**: `prisma/schema.prisma:590-612` + +The `evaluation.submit` mutation queries grace periods with `roundId + userId + extendedUntil + projectId`. Individual indexes exist but no composite index covers this query pattern. + +**Recommendation**: Add `@@index([roundId, userId, extendedUntil])` for the common grace period lookup pattern. + +--- + +### Query Optimization + +#### QO-1: Analytics getProjectRankings loads all project data including all assignments and evaluations (High) — **DONE** + +**Files**: `src/server/routers/analytics.ts:148-207` + +The `getProjectRankings` query does `include: { assignments: { include: { evaluation: ... } } }` on ALL projects in a round, fetching complete project records with nested assignments and evaluations. For a round with 130 projects and 3+ evaluations each, this fetches 390+ evaluation records with full project data. + +**Impact**: Significant memory usage and query time. The response payload is very large even though only scores are needed for ranking. + +**Recommendation**: Use a raw SQL aggregate query or Prisma's `select` to only fetch the fields needed (project id, title, evaluation scores). Consider pre-computing rankings or caching results. + +--- + +#### QO-2: getTags fetches all projects to extract unique tags (Medium) — **DONE** + +**Files**: `src/server/routers/project.ts:580-599` + +The `getTags` query fetches ALL projects with `select: { tags: true }` then deduplicates in JavaScript. For 100+ projects, this is inefficient. + +**Impact**: Unnecessary data transfer and memory usage. + +**Recommendation**: Use Prisma's `$queryRaw` with `SELECT DISTINCT unnest(tags) FROM "Project"` or PostgreSQL's `array_agg(DISTINCT ...)` to get unique tags at the database level. + +--- + +#### QO-3: Project.list includes full files array for every project (Medium) — **DONE** + +**Files**: `src/server/routers/project.ts:133-134` + +The project list query includes `files: true`, fetching all file records for every project in the paginated list. Most list views only need to know whether files exist, not the full file details. + +**Impact**: Over-fetching data, larger payloads, slower queries. + +**Recommendation**: Use `_count: { select: { files: true } }` or `files: { select: { id: true, fileType: true } }` instead of `files: true`. + +--- + +#### QO-4: Sequential notification sends in bulk operations (Medium) — **DONE** + +**Files**: `src/server/routers/assignment.ts:476-490`, `src/server/routers/user.ts:559-596` + +In `assignment.bulkCreate` and `user.bulkCreate`, notifications are sent sequentially in a `for` loop with `await createNotification(...)`. Each `createNotification` call also queries the database for email settings and user preferences. + +**Impact**: Bulk operations are O(n) in database queries for notifications, significantly slowing down bulk assignment/invitation flows. + +**Recommendation**: Use `createBulkNotifications` (which already exists and uses `createMany`) instead of looping with `createNotification`. Batch the email checks as well. + +--- + +#### QO-5: Export queries fetch unbounded data (Medium) — **DONE** + +**Files**: `src/server/routers/export.ts:16-34, 106-118` + +Export queries for evaluations and project scores have no pagination and no limit (except audit logs with `take: 10000`). For large rounds, this could return thousands of records in a single response. + +**Impact**: Memory pressure on the server, potential timeout for large exports. + +**Recommendation**: Implement streaming or chunked export, or add a reasonable limit with warning to the user. + +--- + +#### QO-6: N+1 in mentor.getSuggestions (Medium) — **DONE** + +**Files**: `src/server/routers/mentor.ts:50-78` + +After getting AI suggestions, each mentor is fetched individually in a `Promise.all(suggestions.map(...))` loop. Each iteration makes a separate `user.findUnique` query. + +**Impact**: If there are 5 suggestions, this makes 5 additional database queries. + +**Recommendation**: Fetch all needed mentors in a single `user.findMany({ where: { id: { in: mentorIds } } })` query, then map results. + +--- + +#### QO-7: Audit log creation not batched or fire-and-forget (Low) — **DONE** (migrated to logAudit utility with try-catch) + +**Files**: All routers + +Every mutation `await`s the audit log creation, meaning the user's response is delayed by audit log write time. Audit logs are non-critical for the operation's success. + +**Recommendation**: Consider making audit log writes fire-and-forget (don't await) or use a background queue. Alternatively, batch audit logs within transactions where possible. + +--- + +### Data Integrity + +#### DI-1: Evaluation submission and assignment update are not in a transaction (High) — **DONE** + +**Files**: `src/server/routers/evaluation.ts:200-213` + +The `evaluation.submit` mutation updates the evaluation status to `SUBMITTED` and then separately updates the assignment's `isCompleted` to `true`. These two operations should be atomic - if the second fails, the evaluation is marked submitted but the assignment still shows as incomplete. + +**Impact**: Inconsistent state between evaluation and assignment records. + +**Recommendation**: Wrap both updates in a `$transaction`: +```typescript +await ctx.prisma.$transaction([ + ctx.prisma.evaluation.update({ where: { id }, data: { ...data, status: 'SUBMITTED', submittedAt: now } }), + ctx.prisma.assignment.update({ where: { id: evaluation.assignmentId }, data: { isCompleted: true } }), +]) +``` + +--- + +#### DI-2: Project create + audit log not in a transaction (Medium) — **DONE** + +**Files**: `src/server/routers/project.ts:299-323`, and similar patterns across all routers + +Across all routers, the pattern is: create/update entity, then create audit log as a separate operation. If the audit log creation fails, the entity operation succeeds but the audit trail has a gap. + +**Impact**: Missing audit entries for successful operations. + +**Recommendation**: For critical operations (especially ones involving evaluation submissions, status changes, and user modifications), wrap entity changes and audit log creation in a single transaction. For less critical operations, fire-and-forget the audit log. + +--- + +#### DI-3: bulkUpdateStatus does not check project ownership before notification (Medium) — **DONE** + +**Files**: `src/server/routers/project.ts:620-742` + +The `bulkUpdateStatus` mutation uses `updateMany` (which doesn't return updated records) and then separately fetches projects by ID to send notifications. If some IDs don't match the `roundId` filter, the notification list may not match the actually-updated projects. + +**Impact**: Notifications could be sent for projects that weren't actually updated. + +**Recommendation**: Fetch the matching projects before the update to ensure consistency between updates and notifications, or use the `updated.count` to validate. + +--- + +#### DI-4: Assignment uniqueness constraint may be bypassed by skipDuplicates (Low) — **DONE** + +**Files**: `src/server/routers/assignment.ts:427-434` + +The `bulkCreate` mutation uses `createMany({ skipDuplicates: true })`. While this prevents constraint violations, it silently drops assignments that already exist. The returned count may not reflect what the user intended. + +**Impact**: Users may not realize some assignments were skipped. + +**Recommendation**: Before `createMany`, check which assignments already exist and report the skip count to the user (similar to how `user.bulkCreate` handles it). + +--- + +#### DI-5: No foreign key constraint on SpecialAward.winnerOverriddenBy (Low) — **DONE** + +**Files**: `prisma/schema.prisma:1213` + +The `winnerProjectId` field has a relation to `Project` with `onDelete: SetNull`, which is appropriate. However, `winnerOverriddenBy` is just a `String?` with no relation to `User`, meaning there's no referential integrity check. + +**Recommendation**: Add a relation from `winnerOverriddenBy` to `User` to ensure referential integrity. + +--- + +### Performance + +#### PF-1: Large transaction in filtering.executeRules (High) — **DONE** + +**Files**: `src/server/routers/filtering.ts:503-531` + +The `executeRules` mutation creates a transaction with one `upsert` per project. For 130 projects, this is 130 sequential upserts in a single transaction, holding database locks for the duration. + +**Impact**: Long-running transaction that blocks other operations on the `FilteringResult` table. + +**Recommendation**: Batch the upserts into groups of 20-30, or use `createMany`/`updateMany` where possible. Alternatively, use `$executeRawUnsafe` with a bulk `INSERT ... ON CONFLICT` statement. + +--- + +#### PF-2: Description field text search uses ILIKE without text index (Medium) — **DEFERRED** (requires PostgreSQL full-text search extension) + +**Files**: `src/server/routers/project.ts:111-117` + +Project search uses `{ description: { contains: search, mode: 'insensitive' } }` which translates to `ILIKE '%search%'`. The `description` field is `@db.Text` (unlimited length). Without a text index, this performs a full table scan on potentially large text fields. + +**Impact**: Slow search queries as project count grows, especially with long descriptions. + +**Recommendation**: Add PostgreSQL full-text search (`tsvector`/`tsquery`) via a generated column and GIN index, or use Prisma's full-text search extension. Alternatively, limit search to `title` and `teamName` only for list views. + +--- + +#### PF-3: Assignment stats query makes 5 separate database calls (Low) — **DONE** + +**Files**: `src/server/routers/assignment.ts:530-554` + +The `getStats` query runs 4 parallel queries via `Promise.all` plus a separate `findUniqueOrThrow`. While parallel, this is still 5 database round-trips. + +**Recommendation**: Consolidate into fewer queries. The `projectCoverage` query already returns project data that could provide the total projects count, eliminating one query. + +--- + +### Positive Patterns Observed + +1. **Consistent use of `@@unique` composite constraints**: The schema properly uses composite unique constraints (`@@unique([userId, projectId, roundId])` on Assignment, `@@unique([awardId, projectId])` on AwardEligibility, etc.) to prevent duplicate records at the database level. + +2. **Good use of `select` to limit data fetching**: Many queries use `select` clauses to fetch only needed fields (e.g., `user.me`, `user.list`), reducing payload sizes. + +3. **`Promise.all` for parallel queries**: List queries consistently use `Promise.all([findMany, count])` for pagination, reducing latency. + +4. **RBAC enforced at query level**: Jury members are restricted to their assigned projects through `where` clause filtering, not just middleware checks. + +5. **Proper Zod validation**: All tRPC inputs use comprehensive Zod schemas with min/max constraints, enums, and proper typing. + +6. **Consistent audit logging**: Nearly every mutation creates an audit log entry with context (userId, action, entityType, entityId, detailsJson). + +7. **Background job pattern**: Long-running AI operations (filtering, assignment) use a job table with status tracking and progress callbacks, with fire-and-forget execution. + +8. **Cascade deletes on relations**: The schema consistently uses `onDelete: Cascade` for owned relations and `onDelete: SetNull` for references, which is appropriate. + +9. **Good use of JsonB for flexible data**: The use of `@db.JsonB` for criteria, settings, and metadata allows schema flexibility without migrations. + +10. **Pagination implemented consistently**: List endpoints consistently implement cursor or offset-based pagination with `page`/`perPage` parameters and return total counts. + +--- + +### Priority Summary + +| Priority | Count | Key Issues | +|----------|-------|------------| +| **High** | 4 | Missing transaction on evaluation submit (DI-1), large filtering transaction (PF-1), analytics over-fetching (QO-1), project.roundId nullability mismatch (SD-1) | +| **Medium** | 9 | Soft deletes not implemented (SD-3), evaluation versioning missing (SD-2), N+1 queries (QO-6), sequential notifications (QO-4), audit log growth (IX-2), export unbounded (QO-5), text search without index (PF-2), DI-2, DI-3 | +| **Low** | 7 | Redundant email index (IX-3), string status fields (SD-4, SD-5), deprecated date fields (SD-6), grace period composite index (IX-4), DI-4, DI-5, PF-3 | + +--- + +## 4. Code Quality Review + +### 4.1 Duplicate Code + +#### 4.1.1 `toProjectWithRelations` duplicated across 3 AI services — **DONE** +**Files:** +- `src/server/services/ai-tagging.ts:144` +- `src/server/services/ai-filtering.ts:281` +- `src/server/services/ai-award-eligibility.ts:137` + +All three files contain nearly identical `toProjectWithRelations()` functions that convert a project object to the `ProjectWithRelations` type for anonymization. The function body is the same each time: mapping fields, using `as any` casts, providing defaults for missing fields. + +**Recommendation:** Extract into a shared function in `src/server/services/anonymization.ts` (which already defines `ProjectWithRelations`). +**Effort:** Quick Fix + +--- + +#### 4.1.2 AI service batch processing boilerplate — **DEFERRED** (large refactor, high risk for no behavioral change) +**Files:** +- `src/server/services/ai-assignment.ts:273-377` +- `src/server/services/ai-filtering.ts:425-565` +- `src/server/services/ai-award-eligibility.ts:278-368` +- `src/server/services/mentor-matching.ts:202-337` + +All four AI services follow an identical pattern: +1. Get OpenAI client, check if null -> fallback +2. Get configured model +3. Anonymize data +4. Validate anonymization +5. Loop over batches, call `processXxxBatch()` +6. Track total tokens +7. Catch errors, classify with `classifyAIError`, log with `logAIError`, log usage with `logAIUsage` +8. Fallback to algorithm + +Each batch processor also repeats: build params -> call API -> extract usage -> log usage -> parse JSON -> deanonymize -> handle parse errors with identical error logging. + +**Recommendation:** Create a generic `processAIBatches()` utility that handles the shared orchestration, accepting callbacks for prompt building and result parsing. +**Effort:** Large Refactor + +--- + +#### 4.1.3 Avatar and Logo routers are structural clones — **DONE** +**Files:** +- `src/server/routers/avatar.ts` (187 lines) +- `src/server/routers/logo.ts` (196 lines) + +Both routers have identical structure with 4 endpoints each (`getUploadUrl`, `confirmUpload`, `getUrl`, `delete`) that follow the same pattern: +- Validate image type +- Generate storage key +- Get provider +- Upload/download/delete with provider +- Update database record +- Create audit log + +The only differences are: entity type (User vs Project), field names (profileImageKey vs logoKey), and auth level (protectedProcedure vs adminProcedure). + +**Recommendation:** Create a generic `createImageUploadRouter()` factory that accepts entity config. +**Effort:** Medium + +--- + +#### 4.1.4 Navigation components (jury, mentor, observer) are near-duplicates — **DONE** +**Files:** +- `src/components/layouts/jury-nav.tsx` +- `src/components/layouts/mentor-nav.tsx` +- `src/components/layouts/observer-nav.tsx` + +All three components share the same structure: mobile hamburger menu, desktop nav bar, user avatar dropdown with settings/sign-out, notification bell. They differ only in the navigation links array and the user prop interface name. + +**Recommendation:** Create a shared `RoleNav` component that accepts a `navigation` array and role-specific config as props. +**Effort:** Medium + +--- + +#### 4.1.5 Expertise matching logic duplicated between AI assignment fallback and smart assignment — **SKIPPED** (different scoring ranges 0-1 vs 0-40, consolidating would change algorithm behavior) +**Files:** +- `src/server/services/ai-assignment.ts:514-534` (`calculateExpertiseScore`) +- `src/server/services/smart-assignment.ts:140-163` (`calculateTagOverlapScore`) + +Both implement tag-based expertise matching with slight variations. The fallback in `ai-assignment.ts` uses set intersection, while `smart-assignment.ts` uses weighted confidence scores. The mentor-matching algorithmic fallback (`src/server/services/mentor-matching.ts:374-444`) also has its own keyword matching implementation. + +**Recommendation:** Consolidate expertise scoring into a single utility with configurable weighting. +**Effort:** Medium + +--- + +#### 4.1.6 Audit logging: two competing patterns — **DONE** +**Files:** +- `src/server/utils/audit.ts` - Shared `logAudit()` utility (wraps in try-catch) +- Used in: `src/server/routers/filtering.ts`, `src/server/routers/specialAward.ts` +- 19 other router files use inline `ctx.prisma.auditLog.create()` directly (79 total occurrences) + +Most routers create audit logs inline without try-catch, meaning an audit failure could break the operation. The `logAudit` utility exists specifically to prevent this but is only used in 2 of 21 routers. + +**Recommendation:** Migrate all 79 inline audit log calls to use the `logAudit` utility for consistent error handling. Or add audit logging as tRPC middleware. +**Effort:** Medium + +--- + +#### 4.1.7 Batch tagging logic duplicated between service and router — **DONE** (dead service functions removed) +**Files:** +- `src/server/services/ai-tagging.ts:456-551` (`batchTagProjects`) +- `src/server/services/ai-tagging.ts:558-655` (`batchTagProgramProjects`) +- `src/server/routers/tag.ts:20-170` (`runTaggingJob`) + +`batchTagProjects` and `batchTagProgramProjects` in the service are nearly identical (differ only in the Prisma `where` clause). The `runTaggingJob` in the router reimplements the same loop with progress tracking. + +**Recommendation:** The service functions (`batchTagProjects`, `batchTagProgramProjects`) appear to be dead code since the router uses `runTaggingJob` directly. Remove the unused service functions and consolidate into a single batch function with a flexible query parameter. +**Effort:** Medium + +--- + +### 4.2 Dead Code + +#### 4.2.1 `getObjectInfo` function in minio.ts is never called — **DONE** +**File:** `src/lib/minio.ts:115-120` + +The `getObjectInfo` function is exported but never imported or used anywhere in the codebase. + +**Recommendation:** Remove. +**Effort:** Quick Fix + +--- + +#### 4.2.2 `isValidImageSize` function in storage/index.ts is never called — **DONE** +**File:** `src/lib/storage/index.ts:136-138` + +Exported but never imported anywhere. Image size validation is not performed server-side. + +**Recommendation:** Remove, or actually use it in the avatar/logo upload flows. +**Effort:** Quick Fix + +--- + +#### 4.2.3 `clearStorageProviderCache` is never called — **DONE** +**File:** `src/lib/storage/index.ts:85-88` + +This function is defined to clear the cached storage provider when settings change, but it is never called from the settings router or anywhere else. This means changing the storage provider in settings has no effect until the server restarts. + +**Recommendation:** Call this function from the settings router when `storage_provider` is updated. +**Effort:** Quick Fix + +--- + +#### 4.2.4 `deleteObject` in minio.ts is only used indirectly — **DONE** +**File:** `src/lib/minio.ts:93-98` + +Only referenced via the S3 storage provider (`src/lib/storage/s3-provider.ts`). The direct export from minio.ts is never imported directly by any router or service. + +**Recommendation:** Consider making it non-exported (internal to the module) since it's only used by the S3 provider. +**Effort:** Quick Fix + +--- + +#### 4.2.5 Deprecated batch tag endpoints still exposed — **DONE** +**File:** `src/server/routers/tag.ts:763-814` + +Two endpoints are marked `@deprecated` (`batchTagProjects`, `batchTagProgramProjects`) but still included in the router. They duplicate the logic of `startTaggingJob`. + +**Recommendation:** Check if any frontend code calls these deprecated endpoints. If not, remove them. +**Effort:** Quick Fix + +--- + +#### 4.2.6 `batchTagProjects` and `batchTagProgramProjects` service functions likely unused — **DONE** +**Files:** +- `src/server/services/ai-tagging.ts:456-551` +- `src/server/services/ai-tagging.ts:558-655` + +These two exported functions are no longer called by the tag router (which uses `runTaggingJob` instead). No other files import them. + +**Recommendation:** Remove both functions. +**Effort:** Quick Fix + +--- + +#### 4.2.7 `twilio` npm package is never imported — **DONE** +**File:** `package.json:85` + +The `twilio` package (v5.4.0) is listed as a dependency, but the Twilio WhatsApp provider (`src/lib/whatsapp/twilio-provider.ts`) uses raw `fetch()` calls to the Twilio API instead of the SDK. The SDK is never imported anywhere. + +**Recommendation:** Remove `twilio` from dependencies to reduce bundle size and install footprint. +**Effort:** Quick Fix + +--- + +### 4.3 Redundant Code + +#### 4.3.1 Two storage abstraction layers: minio.ts and storage/ — **DONE** +**Files:** +- `src/lib/minio.ts` - Direct MinIO client with helper functions +- `src/lib/storage/` - Provider-based abstraction (S3Provider wraps minio.ts, LocalProvider) + +Some routers use `minio.ts` directly (`file.ts`, `partner.ts`, `learningResource.ts`, `applicant.ts`) while others use the storage abstraction (`avatar.ts`, `logo.ts`). This creates inconsistency: files uploaded through direct minio calls won't work if the admin switches to local storage. + +**Recommendation:** Migrate all direct `@/lib/minio` imports to use the `@/lib/storage` abstraction for consistent provider-agnostic file handling. +**Effort:** Medium + +--- + +#### 4.3.2 Debug console.log statements in user router — **DONE** +**File:** `src/server/routers/user.ts:246,256` + +Debug logging for a simple user fetch query: +``` +console.log('[user.get] Fetching user:', input.id) +console.log('[user.get] Found user:', user.email) +``` + +These appear to be leftover development debug statements, not structured logging. + +**Recommendation:** Remove. +**Effort:** Quick Fix + +--- + +#### 4.3.3 Excessive console.log in AI services — **DONE** (structured logger implemented) +**Files:** +- `src/server/services/ai-tagging.ts` - 22 console.log statements +- `src/server/services/ai-filtering.ts` - 5 console.log statements +- `src/server/services/ai-assignment.ts` - 5 console.log statements +- `src/server/services/ai-award-eligibility.ts` - 5 console.log statements +- `src/server/services/mentor-matching.ts` - 4 console.log statements +- `src/server/routers/tag.ts` - 10 console.log statements + +Total: ~51 console.log/warn/error statements across AI services. While useful for debugging, production code should use structured logging with configurable log levels. + +**Recommendation:** Implement a simple logger utility with configurable levels (debug, info, warn, error) and replace all console.log calls. +**Effort:** Medium + +--- + +### 4.4 Unfinished Code + +#### 4.4.1 TODO: Send invitation email to new team member — **DONE** +**File:** `src/server/routers/applicant.ts:659` + +```typescript +// TODO: Send invitation email to the new team member +``` + +The team member addition flow creates the team member record but never sends an invitation email. + +**Recommendation:** Implement email notification using the existing notification service. +**Effort:** Medium + +--- + +#### 4.4.2 `aiBoost` field always returns 0 — **DONE** (removed unused field) +**File:** `src/server/services/smart-assignment.ts:27,370` + +The `ScoreBreakdown` type includes an `aiBoost` field (described as "Reserved: 0-5 points (future AI boost)" in the comment), but it's always set to `0` in all score calculations. + +**Recommendation:** Either implement the AI boost feature or remove the field to avoid confusion. +**Effort:** Quick Fix (to remove) / Large Refactor (to implement) + +--- + +### 4.5 Unused Dependencies — **ALL DONE** + +| Package | Evidence | Recommendation | Status | +|---------|----------|----------------|--------| +| `twilio` (v5.4.0) | Never imported; Twilio provider uses raw `fetch()` | Remove from package.json | **DONE** | +| `autoprefixer` (v10.4.20) | Only referenced in postcss config; Tailwind v4 includes autoprefixer | Verify and potentially remove | **DONE** | +| `@types/leaflet` (v1.9.21) | Listed in `dependencies` not `devDependencies` | Move to devDependencies | **DONE** | + +--- + +### 4.6 Summary + +| Category | Count | Quick Fix | Medium | Large | +|----------|-------|-----------|--------|-------| +| Duplicate Code | 7 | 0 | 4 | 3 | +| Dead Code | 7 | 7 | 0 | 0 | +| Redundant Code | 3 | 2 | 1 | 0 | +| Unfinished Code | 2 | 1 | 1 | 0 | +| Unused Dependencies | 3 | 3 | 0 | 0 | +| **Total** | **22** | **13** | **6** | **3** | + +**Priority recommendations (highest impact, lowest effort):** +1. Remove unused `twilio` dependency (saves ~10MB in node_modules) +2. Remove dead code: `getObjectInfo`, `isValidImageSize`, deprecated batch endpoints, unused batch service functions +3. Call `clearStorageProviderCache` when storage settings change (bug fix) +4. Extract shared `toProjectWithRelations` to eliminate 3-way duplication +5. Migrate direct `@/lib/minio` imports to `@/lib/storage` for consistency + +--- + +## 2. Security Review + +**Reviewer**: Security Reviewer Agent +**Date**: 2026-02-05 +**Scope**: Authentication, authorization, input validation, file security, rate limiting, CSRF, data privacy, password security, API routes, injection prevention, XSS, audit logging, session security, environment variables, account lockout + +--- + +### Critical Findings + +#### CRIT-1: Path Traversal Bypass in Local Storage Provider — **DONE** + +**Affected file**: `src/lib/storage/local-provider.ts:65-68` + +The path traversal sanitization is insufficient. It only strips literal `..` sequences but does not account for encoded variants or alternative traversal techniques on Windows. Additionally, `path.join()` can resolve `..` segments inserted via other mechanisms. + +```typescript +private getFilePath(key: string): string { + const sanitizedKey = key.replace(/\.\./g, '').replace(/^\//, '') + return path.join(this.basePath, sanitizedKey) +} +``` + +**Impact**: An attacker with a valid signed URL (or who can manipulate the `key` parameter) could potentially read arbitrary files from the server filesystem. + +**Recommendation**: After constructing the full path with `path.resolve()`, verify it still starts with the expected base directory: +```typescript +const resolved = path.resolve(this.basePath, sanitizedKey) +if (!resolved.startsWith(path.resolve(this.basePath))) { + throw new Error('Invalid file path') +} +``` + +--- + +#### CRIT-2: Timing-Unsafe Signature Comparison — **DONE** + +**Affected file**: `src/lib/storage/local-provider.ts:56-63` + +The HMAC signature verification uses `===` string comparison, which is vulnerable to timing attacks. An attacker could theoretically determine the correct HMAC byte-by-byte by measuring response times. + +```typescript +return signature === expectedSignature && expiresAt > Date.now() / 1000 +``` + +**Impact**: In theory, an attacker could forge valid pre-signed URLs by progressively guessing the HMAC signature. While practical exploitation is difficult over the network, it remains a cryptographic best-practice violation. + +**Recommendation**: Use `crypto.timingSafeEqual()` for HMAC comparison: +```typescript +import { timingSafeEqual } from 'crypto' +const sigBuffer = Buffer.from(signature, 'hex') +const expectedBuffer = Buffer.from(expectedSignature, 'hex') +return sigBuffer.length === expectedBuffer.length + && timingSafeEqual(sigBuffer, expectedBuffer) + && expiresAt > Date.now() / 1000 +``` + +--- + +#### CRIT-3: Email/Password Change API Routes Lack Proper Authentication — **DONE** + +**Affected files**: `src/app/api/email/verify-credentials/route.ts`, `src/app/api/email/change-password/route.ts` + +These API routes accept `POST` requests with email and password credentials but have no session-based authentication verifying the caller. While the middleware `authorized` callback blocks unauthenticated users from non-public paths, these routes do not verify the authenticated user matches the email being acted upon. An authenticated user could verify credentials or change the Poste.io mailbox password of any `@monaco-opc.com` email address. + +The change-password route at `src/app/api/email/change-password/route.ts:97-109` sends the new password in plaintext to the Poste.io admin API using hardcoded admin credentials. + +**Impact**: An authenticated user could potentially change another user's email password. Rate limiting (3-5 attempts per 15 minutes) slows but does not prevent this. + +**Recommendation**: Add NextAuth session checks to both API routes. Verify that the authenticated user's email matches the email being acted upon. + +--- + +### High Severity Findings + +#### HIGH-1: In-Memory Rate Limiting Does Not Scale — **DEFERRED** (requires Redis infrastructure) + +**Affected files**: `src/lib/rate-limit.ts`, `src/lib/auth.ts:12` + +Both the rate limiter and the account lockout tracker use in-memory `Map` objects. In a multi-instance deployment (e.g., multiple Docker replicas behind a load balancer), rate limits and lockouts are per-instance, not global. + +```typescript +const failedAttempts = new Map() +``` + +**Impact**: An attacker could bypass rate limiting by having requests routed to different instances. Account lockout after 5 failed attempts would not work reliably across instances. This is acknowledged in the rate-limit.ts comment but still represents a deployment risk. + +**Recommendation**: Move to Redis-based rate limiting and lockout tracking before deploying with multiple instances. If running single-instance only, document this constraint clearly. + +--- + +#### HIGH-2: Health Check Endpoint Leaks Database Error Details — **DONE** + +**Affected file**: `src/app/api/health/route.ts:29` + +The health endpoint returns the actual error message when the database is disconnected: +```typescript +error: error instanceof Error ? error.message : 'Unknown error', +``` + +**Impact**: Database connection errors may contain hostnames, ports, connection strings, or other internal infrastructure details that aid attackers in reconnaissance. + +**Recommendation**: Log the full error server-side but return only a generic status to the client. If the health endpoint is meant for internal monitoring only, restrict access via network configuration or authentication. + +--- + +#### HIGH-3: Local Storage Fallback Secret Key — **DONE** + +**Affected file**: `src/lib/storage/local-provider.ts:6` + +```typescript +const SECRET_KEY = process.env.NEXTAUTH_SECRET || 'local-storage-secret' +``` + +If `NEXTAUTH_SECRET` is not set, the signing key falls back to a hardcoded value. While `NEXTAUTH_SECRET` should always be set in production, this fallback is dangerous if accidentally deployed without it. + +**Impact**: An attacker who knows the fallback value can forge pre-signed file download/upload URLs, bypassing all file access controls. + +**Recommendation**: Remove the fallback or throw an error at startup if `NEXTAUTH_SECRET` is not set. Never use hardcoded cryptographic secrets. + +--- + +#### HIGH-4: MinIO Client Defaults to Insecure Credentials — **DONE** + +**Affected file**: `src/lib/minio.ts:23-24` + +```typescript +accessKey: process.env.MINIO_ACCESS_KEY || 'minioadmin', +secretKey: process.env.MINIO_SECRET_KEY || 'minioadmin', +``` + +**Impact**: If environment variables are not set, the client uses default MinIO credentials (`minioadmin/minioadmin`). Combined with a misconfigured or exposed MinIO instance, this could grant full access to all stored files including jury evaluation documents and project submissions. + +**Recommendation**: Fail loudly in production when these environment variables are not set instead of falling back to defaults. + +--- + +#### HIGH-5: Application Submission Creates Users Without Verification — **DONE** (added rate limiting) + +**Affected file**: `src/server/routers/application.ts:148-341` + +The `application.submit` route uses `publicProcedure` (no authentication required) and creates new `User` records with the `APPLICANT` role, plus `TeamMember` records, based entirely on user-supplied email addresses. Any external user can: +1. Create arbitrary user accounts with the `APPLICANT` role +2. Create team member records linking arbitrary email addresses +3. Pollute the user table with fake data + +While the APPLICANT role has limited permissions, there is no CAPTCHA, no email verification, and the only rate limit is the global tRPC limit of 100 requests/minute per IP. + +**Impact**: User table pollution, spam applications, potential abuse of the notification system (applicants receive in-app notifications). + +**Recommendation**: Add CAPTCHA/reCAPTCHA verification to the submission endpoint. Implement a stricter rate limit specific to application submissions. Consider requiring email verification before creating user accounts and team memberships. + +--- + +### Medium Severity Findings + +#### MED-1: Password Policy Does Not Require Special Characters — **DONE** + +**Affected file**: `src/lib/password.ts:34-56` + +The password validation requires only 8 characters, one uppercase, one lowercase, and one digit. Special characters are not required. + +**Impact**: Passwords without special characters are more susceptible to dictionary and brute-force attacks. + +**Recommendation**: Consider requiring at least one special character, or increase the minimum length to 12 characters. Also consider checking against common password lists (e.g., "Have I Been Pwned" API or a local blocklist of the top 10,000 passwords). + +--- + +#### MED-2: Audit Logging Failures Are Silently Swallowed — **DONE** + +**Affected files**: `src/server/utils/audit.ts:29-32`, `src/lib/auth.ts:91,147`, and many router files + +Audit log failures are caught and silently ignored throughout the codebase: +```typescript +await prisma.auditLog.create({ ... }).catch(() => {}) +``` + +**Impact**: If the audit system fails (e.g., database connection issues, disk full), critical security events (login attempts, role changes, data exports) will not be recorded. This violates the stated requirement of an "immutable audit log." + +**Recommendation**: At minimum, log audit failures to a secondary logging system (e.g., file-based logger or error monitoring service like Sentry). Consider implementing a write-ahead buffer or retry mechanism for audit entries. + +--- + +#### MED-3: File Upload Has No Content-Type or Extension Validation — **DONE** + +**Affected file**: `src/server/routers/file.ts:75-125` + +The `getUploadUrl` procedure validates the `fileType` enum (EXEC_SUMMARY, PRESENTATION, VIDEO, OTHER) and accepts a `mimeType` string, but does not verify that the MIME type matches the file extension, nor does it block dangerous file types (e.g., `.exe`, `.sh`, `.php`, `.html`). + +The local storage upload route at `src/app/api/storage/local/route.ts:111-124` accepts any content-type from the request header without validation. + +**Impact**: An admin user could upload executable or HTML files. If these files are later served with their original content-type, this could lead to stored XSS or other browser-based attacks when other users download them. + +**Recommendation**: Implement server-side MIME type validation and file extension allowlisting. Serve uploaded files with `Content-Disposition: attachment` headers and sanitized content types. + +--- + +#### MED-4: File Deletion Does Not Remove Storage Objects — **DONE** + +**Affected file**: `src/server/routers/file.ts:143-171` + +When a file record is deleted, only the database entry is removed. The actual file in MinIO or local storage is not deleted: +```typescript +// Note: Actual MinIO deletion could be done here or via background job +// For now, we just delete the database record +``` + +**Impact**: Orphaned files accumulate in storage. Previously-issued pre-signed URLs remain valid until their expiry. This has data retention/GDPR compliance implications. + +**Recommendation**: Implement storage object deletion alongside database record deletion, or create a background cleanup job for orphaned files. + +--- + +#### MED-5: IP Address Extraction Relies on Spoofable Header — **DEFERRED** (requires Nginx proxy configuration) + +**Affected files**: `src/server/context.ts:13`, `src/app/api/trpc/[trpc]/route.ts:13-18`, `src/app/api/auth/[...nextauth]/route.ts:8-12` + +Client IP is extracted from the `x-forwarded-for` header: +```typescript +const ip = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown' +``` + +**Impact**: If the application is not behind a properly configured reverse proxy, clients can spoof their IP address by setting the `x-forwarded-for` header. This bypasses IP-based rate limiting and poisons audit log entries with false IP addresses. + +**Recommendation**: Configure the application to only trust `x-forwarded-for` from known proxy IPs. In production with Nginx, ensure the proxy overwrites (not appends to) this header and strips any client-supplied values. + +--- + +#### MED-6: Public Email Availability Check Enables Enumeration — **DONE** + +**Affected file**: `src/server/routers/application.ts:346-367` + +The `checkEmailAvailability` endpoint is a public procedure that reveals whether a specific email has already submitted an application for a given round: +```typescript +return { available: !existing, message: existing ? 'An application with this email...' : null } +``` + +**Impact**: An attacker can enumerate which emails have submitted applications for specific rounds, potentially revealing participation in the ocean protection challenge. + +**Recommendation**: Consider removing this endpoint or requiring authentication. If it is needed for UX, implement stricter rate limiting and CAPTCHA. + +--- + +#### MED-7: Assignment Job Status Accessible to All Authenticated Users — **DONE** + +**Affected file**: `src/server/routers/assignment.ts:1041-1061` + +The `getAIAssignmentJobStatus` endpoint uses `protectedProcedure` instead of `adminProcedure`: +```typescript +getAIAssignmentJobStatus: protectedProcedure + .input(z.object({ jobId: z.string() })) +``` + +**Impact**: Any authenticated user (including jury members, observers, applicants) can query the status of AI assignment jobs if they know or guess a job ID. While job IDs are UUIDs, this exposes internal platform operations unnecessarily. + +**Recommendation**: Change to `adminProcedure` to restrict to admin users only. + +--- + +#### MED-8: PII Logging in User Router — **DONE** + +**Affected file**: `src/server/routers/user.ts:246,256` + +Debug logging statements expose user data in server logs: +```typescript +console.log('[user.get] Fetching user:', input.id) +console.log('[user.get] Found user:', user.email) +``` + +**Impact**: User IDs and email addresses are written to server logs. Under GDPR, log files containing PII must be treated as personal data and properly managed (retention, access controls, etc.). + +**Recommendation**: Remove debug console.log statements or replace with a structured logger that respects log levels and redacts PII. + +--- + +### Low Severity Findings + +#### LOW-1: Session Configuration Could Be Hardened — **DONE** + +**Affected file**: `src/lib/auth.config.ts:88-90` + +The session uses JWT strategy with a default 24-hour maxAge. No explicit cookie configuration is visible. + +```typescript +session: { + strategy: 'jwt', + maxAge: parseInt(process.env.SESSION_MAX_AGE || '86400'), +}, +``` + +**Impact**: NextAuth v5 sets secure cookie defaults, but explicit configuration is better for defense-in-depth. A 24-hour session may be too long for admin users. + +**Recommendation**: Explicitly set cookie options: `httpOnly: true`, `secure: true` (production), `sameSite: 'lax'`. Consider shorter session lifetimes for admin roles. + +--- + +#### LOW-2: Export Endpoint Allows Large Data Fetches — **DONE** (reduced to 5000) + +**Affected file**: `src/server/routers/export.ts:266` + +```typescript +take: 10000, // Limit export to 10k records +``` + +**Impact**: Large exports could cause memory pressure or slow response times. Admin-only access mitigates the risk. + +**Recommendation**: Consider pagination or streaming exports for large datasets. + +--- + +#### LOW-3: Project List Allows Up to 5000 Items Per Page — **DONE** (reduced to 200) + +**Affected file**: `src/server/routers/project.ts:58` + +```typescript +perPage: z.number().int().min(1).max(5000).default(20), +``` + +**Impact**: A request for 5000 projects with full includes could cause significant memory usage and slow responses. + +**Recommendation**: Reduce the maximum to a reasonable value (e.g., 200) or implement cursor-based pagination for large result sets. + +--- + +#### LOW-4: No CSRF Protection on Custom API Routes — **DONE** + +**Affected files**: `src/app/api/email/verify-credentials/route.ts`, `src/app/api/email/change-password/route.ts`, `src/app/api/storage/local/route.ts` + +These custom API routes (outside of tRPC and NextAuth) accept POST/PUT requests without explicit CSRF token validation. While the Same-Origin Policy and Content-Type restrictions provide some protection, explicit CSRF tokens would add defense-in-depth. + +**Impact**: Low risk due to browser same-origin restrictions, but a defense-in-depth concern. + +**Recommendation**: Consider adding CSRF token validation for custom API routes, especially those that modify state (password change, file upload). + +--- + +#### LOW-5: Invite Token Validation Has No Specific Rate Limit — **N/A** (token entropy sufficient, no action needed) + +**Affected file**: `src/server/routers/user.ts:45-69` + +The `validateInviteToken` is a public procedure protected only by the global tRPC rate limit (100/min per IP). With 256 bits of entropy in the tokens, brute-force is computationally infeasible. + +**Impact**: Negligible due to the token entropy. Listed for completeness. + +**Recommendation**: No immediate action needed. The existing token entropy is sufficient. + +--- + +### Informational Findings (Positive Security Practices) + +#### INFO-1: Comprehensive Audit Logging — **N/A** + +The platform implements thorough audit logging across all critical operations: user management, authentication, evaluations, assignments, file access, exports, and settings changes. Each audit entry includes userId, action, entityType, entityId, details, IP address, and user agent. + +#### INFO-2: Well-Designed RBAC Architecture — **N/A** + +The tRPC middleware-based RBAC system is well-designed with clear role hierarchies (`publicProcedure`, `protectedProcedure`, `adminProcedure`, `superAdminProcedure`, `juryProcedure`, `mentorProcedure`). Role checks are enforced at the procedure level, with additional ownership checks in individual handlers. + +#### INFO-3: No SQL Injection Risk — **N/A** + +The codebase exclusively uses Prisma ORM for database access. The only raw query found is the health check's `SELECT 1`. No user input is interpolated into raw SQL anywhere in the application. + +#### INFO-4: No XSS via dangerouslySetInnerHTML — **N/A** + +No usage of `dangerouslySetInnerHTML` was found in the codebase. React's default escaping provides XSS protection for rendered content. + +#### INFO-5: Environment Variables Properly Gitignored — **N/A** + +All `.env` variants (`.env`, `.env.local`, `.env.development.local`, `.env.test.local`, `.env.production.local`, `docker/.env`) are listed in `.gitignore`. No hardcoded secrets were found in the source code beyond the noted fallback defaults. + +#### INFO-6: Thorough Data Anonymization for AI — **N/A** + +The anonymization service (`src/server/services/anonymization.ts`) comprehensively strips PII (emails, phones, URLs, SSNs, IP addresses) before sending data to OpenAI. GDPR compliance validation is enforced before every AI call. Both basic (assignment) and enhanced (filtering/awards) anonymization paths are implemented with validation. + +#### INFO-7: CSRF Protection via tRPC Content-Type — **N/A** + +tRPC uses `application/json` content type which triggers CORS preflight for cross-origin requests, providing natural CSRF protection. NextAuth routes have built-in CSRF token protection. No permissive CORS headers are configured. + +#### INFO-8: Strong Password Hashing — **N/A** + +bcrypt with 12 salt rounds provides strong password hashing. Account lockout after 5 failed attempts with a 15-minute lockout is implemented. Password reset does not reveal whether an email exists (anti-enumeration pattern). + +#### INFO-9: Jury Data Isolation — **N/A** + +Jury members can only see projects they are assigned to. This is enforced both at the query level (project list endpoint adds `assignments: { some: { userId: ctx.user.id } }`) and via explicit assignment checks in get/evaluation endpoints. + +#### INFO-10: Rate Limiting Coverage — **N/A** + +Rate limiting is applied to: all tRPC endpoints (100 requests/min), auth POST endpoints (10/min), email verification (5 per 15 min), and email password change (3 per 15 min). Headers expose rate limit status for client-side handling. + +--- + +### Security Review Summary + +| Severity | Count | Key Areas | +|----------|-------|-----------| +| Critical | 3 | Path traversal, timing-unsafe HMAC, unauthenticated email routes | +| High | 5 | In-memory rate limiting, error info leaks, hardcoded secrets, user creation without verification | +| Medium | 8 | Password policy, audit reliability, file validation, IP spoofing, access control gaps | +| Low | 5 | Session config, large exports, CSRF on custom routes | +| Informational | 10 | Positive practices observed | + +**Overall Assessment**: The platform demonstrates strong security fundamentals with comprehensive RBAC, audit logging, proper ORM usage (no SQL injection), XSS prevention, and data anonymization for AI services. The critical issues center around the local file storage provider (path traversal bypass, timing-unsafe HMAC comparison) and the email API routes lacking proper authorization checks. The high-severity items relate to deployment concerns (in-memory rate limiting, hardcoded fallback secrets) and the unauthenticated application submission endpoint's ability to create user records without verification. Addressing the critical and high-severity items should be prioritized before production deployment with external exposure. + +--- + +## 5. Feature Proposals & Improvements — **PARTIAL** (10 of 26 features implemented) + +*Reviewed by: Feature Proposer Agent* +*Date: 2026-02-05* + +This section proposes new features and improvements based on a thorough review of the platform's codebase, including all routers, services, pages, components, and data model. Proposals are organized by implementation effort and prioritized by impact. + +> **Note**: This section contains feature proposals for future development. None of these are bugs or issues — they are enhancement ideas preserved as a roadmap reference. + +--- + +### Quick Wins (Low Effort, High Impact) + +#### 5.1.1 Jury Evaluation Reminders & Deadline Countdown — **DONE** + +**What**: Add automated reminder notifications at configurable intervals before voting deadlines (e.g., 72h, 24h, 1h). Show a prominent countdown timer on the jury dashboard and assignment pages when deadline is approaching. + +**Why**: The platform already has `REMINDER_24H` and `REMINDER_1H` notification types defined in the email templates, but there is no scheduled job or cron mechanism to actually trigger these reminders. Jury members may forget deadlines, leading to incomplete evaluations. + +**Who benefits**: Jury Members, Program Admins (higher completion rates) + +**Scope**: Add a scheduled task (cron job or database-polling endpoint) that checks upcoming deadlines and sends notifications. Add countdown UI component to jury dashboard. ~2-3 days. + +--- + +#### 5.1.2 Evaluation Progress Indicator Per Project — **DONE** + +**What**: On the evaluation form page (`/jury/projects/[id]/evaluate`), show a visual progress indicator (e.g., "3 of 5 criteria scored") so jury members know how far along they are before submitting. + +**Why**: The current autosave system tracks partial scores, but there is no visual indicator showing the jury member how many criteria they have completed. This causes friction especially for forms with many criteria. + +**Who benefits**: Jury Members + +**Scope**: Frontend-only change. Add a progress bar or step indicator to the evaluation form component. ~0.5 day. + +--- + +#### 5.1.3 Bulk Status Update for Projects — **DONE** + +**What**: Allow admins to select multiple projects from the project list and change their status in bulk (e.g., mark 20 projects as SEMIFINALIST at once). + +**Why**: Currently, the project router has individual update capabilities but no bulk status change. After reviewing evaluations, admins need to advance multiple projects, which is tedious one-by-one. The filtering router has `finalizeResults` for automated advancement, but there is no manual bulk option outside of filtering. + +**Who benefits**: Program Admins, Super Admins + +**Scope**: Add `bulkUpdateStatus` mutation to project router, add checkbox selection UI to project list page. ~1-2 days. + +--- + +#### 5.1.4 Export Filtering Results as CSV — **DONE** + +**What**: Add CSV export capability for filtering results, similar to the existing evaluation and project score exports. + +**Why**: The export router currently supports evaluations, project scores, assignments, and audit logs, but not filtering results. Admins reviewing AI filtering outcomes may want to share or archive these results externally. + +**Who benefits**: Program Admins + +**Scope**: Add a new endpoint to the export router for filtering results. ~0.5 day. + +--- + +#### 5.1.5 Observer Access to Reports & Analytics — **DONE** + +**What**: Allow observers to view the Reports page (analytics charts and exports) in read-only mode. + +**Why**: The observer dashboard (`/observer`) shows basic stats (program count, project count, juror count, evaluation completion), but observers cannot access the detailed analytics charts (score distribution, evaluation timeline, juror workload, project rankings, geographic distribution) that are on the admin Reports page. The observer role is designed for stakeholders who need visibility without edit access. + +**Who benefits**: Observers (stakeholders, board members) + +**Scope**: Create an `/observer/reports` page that mirrors the admin analytics tab using the existing chart components. Requires adding observer-accessible query variants for the analytics router. ~1-2 days. + +--- + +#### 5.1.6 Conflict of Interest Declaration — **DONE** + +**What**: When a jury member starts an evaluation, prompt them to declare any conflicts of interest with the project. Store the declaration and allow admins to flag/reassign if needed. + +**Why**: In academic and grant judging, conflict of interest management is a standard requirement. Currently there is no mechanism for jurors to declare COI, which could undermine the integrity of the evaluation process. + +**Who benefits**: Jury Members, Program Admins, platform credibility + +**Scope**: Add a `conflictOfInterest` field to the Assignment or Evaluation model, add a COI declaration dialog before evaluation starts, add admin view for flagged COI. ~2-3 days. + +--- + +### Medium-Term (Moderate Effort) + +#### 5.2.1 Email Digest / Summary Notifications + +**What**: Implement a daily or weekly email digest that summarizes a user's pending actions: unfinished evaluations, upcoming deadlines, new assignments, new notifications. Configurable per user (daily/weekly/off). + +**Why**: The notification system sends individual emails per event, which can be noisy. A digest approach reduces email fatigue while ensuring users stay informed. The `NotificationEmailSetting` model exists but only controls per-type settings, not digest frequency. + +**Who benefits**: All roles (Jury Members, Mentors, Admins) + +**Scope**: Add user preference for digest frequency, create digest aggregation service, implement scheduled job to send digests. ~3-5 days. + +--- + +#### 5.2.2 Evaluation Calibration / Norming Session Tool + +**What**: Create a calibration mode where all jurors evaluate the same 2-3 "test" projects, then admins can view the variance in scores and use this to identify outlier jurors or adjust scoring guidance. + +**Why**: In large jury panels (handling 130+ projects), inter-rater reliability is a common challenge. Some jurors may be consistently lenient or harsh. A calibration round helps ensure scoring consistency and is standard practice in grant review and academic conferences. + +**Who benefits**: Program Admins (quality assurance), Jury Members (alignment) + +**Scope**: Add a "calibration round" type, mark specific projects as calibration, create comparison analytics showing juror variance on calibration projects. ~5-7 days. + +--- + +#### 5.2.3 Multi-Language Support (i18n) + +**What**: Add internationalization support, starting with French and English. The platform is for Monaco, which is French-speaking, but the jury may be international. + +**Why**: Monaco is a French-speaking principality, and many stakeholders and applicants may prefer French. The current platform is English-only. This is especially important for the public application form and applicant-facing pages. + +**Who benefits**: Applicants, Jury Members, all French-speaking users + +**Scope**: Integrate next-intl or similar i18n library, extract all user-facing strings, translate to French. Start with public-facing pages (application form, login, applicant portal). ~5-10 days for initial setup + French translation. + +--- + +#### 5.2.4 Project Comparison View for Jury + +**What**: Allow jury members to view 2-3 assigned projects side-by-side in a comparison view, showing key details (title, description, team, country, tags) next to each other. + +**Why**: When evaluating 15-20 projects, jurors often want to compare similar projects before assigning scores. Currently they must navigate between individual project pages, losing context. + +**Who benefits**: Jury Members + +**Scope**: Create a new comparison page that loads multiple projects, side-by-side layout. ~3-4 days. + +--- + +#### 5.2.5 Applicant Portal Enhancements — **DONE** + +**What**: Expand the applicant portal (`/my-submission`) with: +- Application status tracking with timeline (submitted -> under review -> semifinalist -> finalist) +- Ability to upload supplementary documents after initial submission (within a deadline) +- Team member management (add/remove members, update roles) +- Communication channel with mentors (if assigned) + +**Why**: The current applicant portal shows submission details and team management, but lacks a status timeline and post-submission document upload. These are standard features in grant/competition platforms. The team management page exists but could be enriched. + +**Who benefits**: Applicants + +**Scope**: Enhance the existing `/my-submission/[id]` pages with status timeline component, add supplementary upload endpoint, enrich team management. ~5-7 days. + +--- + +#### 5.2.6 Round Templates + +**What**: Allow admins to create round templates that pre-configure evaluation criteria, assignment constraints, voting windows, and filtering rules. When creating a new round, they can select a template instead of configuring everything from scratch. + +**Why**: If the MOPC runs annually, admins will repeat similar configurations each year. Templates reduce setup time and ensure consistency across editions. Currently, every new round requires manual configuration of all parameters. + +**Who benefits**: Program Admins, Super Admins + +**Scope**: Add a `RoundTemplate` model, create template management UI, add "Create from template" option in round creation. ~3-5 days. + +--- + +#### 5.2.7 Jury Member Availability & Workload Preferences + +**What**: Allow jury members to set their availability (date ranges when they can evaluate) and preferred workload (number of projects they are comfortable reviewing). Surface this to admins during assignment. + +**Why**: The current system has `maxAssignments` per user but no availability dates. Jurors may have travel or work conflicts during part of the voting window. Knowing availability helps admins assign projects more effectively. + +**Who benefits**: Jury Members, Program Admins + +**Scope**: Add availability fields to user profile, surface in assignment UI, factor into smart assignment algorithm. ~3-4 days. + +--- + +#### 5.2.8 Real-Time Voting Dashboard for Live Events + +**What**: Enhance the live voting feature with a real-time scoreboard using Server-Sent Events or WebSocket polling. Currently, the live voting uses standard HTTP polling. Add a large-screen "presentation mode" showing live score animations as votes come in. + +**Why**: The live voting feature (`/admin/rounds/[id]/live-voting`) and public scores page (`/live-scores/[sessionId]`) exist but use standard queries with manual refresh. For a live event with an audience, real-time updates with animations create a much more engaging experience. + +**Who benefits**: Event organizers, audience, Jury Members at live events + +**Scope**: Add SSE or WebSocket endpoint for vote updates, create presentation mode component with animations, add audience count display. ~5-7 days. + +--- + +#### 5.2.9 AI-Powered Evaluation Summary — **DONE** + +**What**: After all evaluations are submitted for a project, use AI to generate a summary of the jurors' collective feedback. Group common themes, highlight strengths and weaknesses mentioned by multiple jurors. + +**Why**: Admins currently see individual evaluation scores and feedback text. Synthesizing feedback from 3-5 jurors manually is time-consuming. An AI summary helps admins quickly understand the consensus view, and could be shared with applicants as constructive feedback. + +**Who benefits**: Program Admins, Applicants (if feedback is shared) + +**Scope**: Add AI summary service using existing OpenAI integration, create summary generation endpoint (on-demand, not automatic), add summary display in project detail view. ~3-5 days. + +--- + +### Long-Term (Ambitious, High Impact) + +#### 5.3.1 Public Website Module + +**What**: Build the public-facing website for monaco-opc.com, including: +- Homepage with program overview, timeline, and partner logos +- "Apply" landing page with program details and application form link +- Past winners gallery with project descriptions and photos/videos +- News/blog section for announcements +- Partner showcase page + +**Why**: Listed as a "Future" feature in CLAUDE.md. The platform currently has no public website -- only the internal portal. A public site is essential for program visibility, applicant recruitment, and sponsor recognition. + +**Who benefits**: Applicants (discovery), Partners (visibility), Program (credibility) + +**Scope**: Build Next.js pages under `(public)` route group, CMS-like content management for news/blog, integrate existing partner data. ~15-25 days. + +--- + +#### 5.3.2 Communication Hub + +**What**: Add an integrated messaging system within the platform: +- Admin-to-jury broadcast messages +- Admin-to-team (applicant) messages with templates +- Mentor-to-team direct messaging +- Message templates for common communications (congratulations, not selected, next steps) +- Integration with existing email notification system + +**Why**: Currently, communications happen outside the platform (email, potentially WhatsApp). The WhatsApp integration library exists (`src/lib/whatsapp/`) but is not wired to any router. An in-platform communication hub creates a single source of truth for all program communications and enables better audit trails. + +**Who benefits**: All roles + +**Scope**: Add Message model, create messaging router, build inbox/compose UI, integrate with email and potentially WhatsApp providers. ~10-15 days. + +--- + +#### 5.3.3 Advanced Analytics & Reporting Dashboard + +**What**: Expand analytics with: +- Cross-round comparison (how did scores change between Round 1 and Round 2 for advancing projects?) +- Juror consistency analysis (standard deviation per juror, score correlation between jurors) +- Diversity metrics (geographic distribution of advancing projects, category balance) +- Year-over-year trends (if multi-edition data exists) +- Exportable PDF reports with charts for board presentations +- Custom report builder (select metrics, date ranges, filters) + +**Why**: The current analytics router provides good per-round views (score distribution, timeline, workload, rankings, criteria scores, geographic distribution), but lacks cross-round and historical analysis. For a program that runs annually, trend analysis is valuable for demonstrating impact to stakeholders. + +**Who benefits**: Program Admins, Super Admins, Observers, Board Members + +**Scope**: Add cross-round query endpoints, create new chart components, build PDF export using a library like @react-pdf/renderer. ~10-15 days. + +--- + +#### 5.3.4 Applicant Self-Service with Draft Saving + +**What**: Enhance the public application form to support: +- Save as draft and resume later (using magic link or email verification) +- Multi-step form with progress saving between sessions +- File uploads during application (pitch deck, business plan, video) +- Application preview before final submission + +**Why**: The current application form (`/apply/[slug]`) submits everything in one go. For complex applications requiring a business plan and team details, applicants may need multiple sessions to complete their submission. Draft saving is standard in grant application platforms. + +**Who benefits**: Applicants + +**Scope**: Add draft application model, magic link authentication for applicants, file upload integration in application form, preview component. ~7-10 days. + +--- + +#### 5.3.5 Webhooks & API Integration Layer + +**What**: Add a webhook system that fires events when key actions occur: +- Application submitted +- Project status changed (advanced, rejected) +- Evaluation submitted +- Round status changed +- Award winner selected + +Allow admins to configure webhook URLs for external integrations (CRM, Slack, custom dashboards). + +**Why**: The platform is currently self-contained. Organizations often need to integrate with external systems (CRM for applicant tracking, Slack for admin notifications, donor databases). A webhook system enables this without custom code for each integration. + +**Who benefits**: Program Admins, Super Admins, external system integrations + +**Scope**: Add Webhook model (url, events, secret), create webhook dispatch service, add admin webhook configuration UI. ~5-7 days. + +--- + +#### 5.3.6 Peer Review / Collaborative Evaluation Notes + +**What**: After individual evaluations are submitted (and locked), allow jurors assigned to the same project to see anonymized summaries of other jurors' scores and feedback. Enable optional discussion threads for projects where scores diverge significantly. + +**Why**: In academic peer review, after independent evaluation, reviewers often discuss divergent opinions to reach consensus. Currently, jurors submit in isolation with no visibility into other evaluations. For borderline projects, discussion can improve decision quality. + +**Who benefits**: Jury Members, Program Admins (better decisions) + +**Scope**: Add post-evaluation discussion model, create discussion thread UI, implement anonymization for jury comments, add divergence detection logic. ~7-10 days. + +--- + +### Improvements to Existing Features + +#### 5.4.1 Smart Assignment Algorithm Improvements — **DONE** + +**Current state**: The smart assignment algorithm in `assignment.ts:getSuggestions` uses expertise matching (35%), load balancing (20%), and under-min-target bonus (15%). The AI assignment uses GPT for more nuanced matching. + +**Improvement**: Add the following factors to the algorithm: +- **Geographic diversity**: Ensure projects from the same country are not all assigned to the same juror +- **Previous round familiarity**: If a juror evaluated a project in Round 1, prioritize assigning them the same project in Round 2 for continuity (or explicitly avoid it for fresh perspective, configurable) +- **Conflict avoidance**: If COI declarations are implemented, auto-exclude conflicted jurors + +**Scope**: Modify the scoring algorithm in the getSuggestions and AI assignment services. ~2-3 days. + +--- + +#### 5.4.2 Evaluation Form Flexibility — **DONE** + +**Current state**: Evaluation criteria are configurable per round with labels, descriptions, scales, and weights. Criteria support numeric scoring (1-10). + +**Improvement**: +- Add support for **text-only criteria** (qualitative feedback without a numeric score) +- Add support for **yes/no criteria** (boolean questions like "Does this project have a viable business model?") +- Add **conditional criteria** (show criterion B only if criterion A score is above 7) +- Add **criterion grouping** (organize criteria into sections like "Innovation", "Impact", "Feasibility") + +**Scope**: Extend the criteria JSON schema, update the evaluation form component to render different input types. ~3-5 days. + +--- + +#### 5.4.3 Audit Log Enhancements + +**Current state**: Comprehensive audit logging exists for most actions. The audit page shows logs with filtering by user, action type, entity type, and date range. + +**Improvement**: +- Add **before/after diff** for update actions (store previous values alongside new values) +- Add **session tracking** (group actions from the same login session) +- Add **anomaly detection** (flag unusual patterns like bulk deletes or rapid score changes) +- Add **audit log retention policy** (auto-archive logs older than X months) + +**Scope**: Enhance audit log creation to capture previous state, add session ID tracking, build anomaly detection service. ~5-7 days. + +--- + +#### 5.4.4 File Management Improvements + +**Current state**: Files are uploaded to MinIO with pre-signed URLs. Files are associated with projects and have types (exec summary, presentation, video, etc.). + +**Improvement**: +- Add **file versioning** (track file replacements, keep history) +- Add **file preview** (inline PDF viewer, video player, image thumbnails) instead of download-only +- Add **file size and type validation** on upload (client-side + server-side) +- Add **virus scanning** integration for uploaded files +- Add **bulk file download** (zip multiple project files for offline review) + +**Scope**: Add file version tracking, integrate a PDF viewer component, add validation middleware. ~5-7 days. + +--- + +#### 5.4.5 Live Voting UX Improvements + +**Current state**: Live voting allows admin to control sessions, set project order, start/stop voting windows. Jury members vote on the current project. + +**Improvement**: +- Add **QR code generation** for the voting URL so audience members can scan and vote on their phones +- Add **countdown timer** with visual animations when time is running low +- Add **score reveal animation** after voting closes for each project +- Add **tie-breaking mechanism** configuration +- Add **audience vote** option (separate from jury vote, displayed alongside but not counted in official scoring) + +**Scope**: QR code generation, animation components, tie-breaking logic. ~5-7 days. + +--- + +#### 5.4.6 Mentor Dashboard Enhancements + +**Current state**: Mentors can view their assigned projects, project details, team members, and files. The mentor dashboard shows a list of assignments. + +**Improvement**: +- Add **mentoring milestones/checklist** (configurable per program: "Initial meeting", "Business plan review", "Pitch preparation") +- Add **mentor notes** on each project (private notes visible only to the mentor and admins) +- Add **mentor-to-team communication** within the platform +- Add **mentor activity tracking** (when did the mentor last view the project?) +- Add **mentorship completion status** tracking + +**Scope**: Add MentorNote model, milestone checklist model, enhance mentor project detail page. ~5-7 days. + +--- + +#### 5.4.7 Application Form Builder (Admin Configurable) + +**Current state**: The application form has a fixed schema defined in `application.ts` with hard-coded fields (category, contact info, project details, team members, additional info). + +**Improvement**: Allow admins to configure the application form fields per round, similar to how evaluation criteria are configurable. Support: +- Custom text fields, dropdowns, checkboxes +- Required vs optional fields +- Conditional fields (show field B if field A has value X) +- Custom validation rules +- Field ordering via drag-and-drop + +**Why**: Different programs or editions may require different application information. The current hard-coded form works for MOPC but limits reusability. + +**Scope**: Create form builder model (similar to EvaluationForm's criteriaJson), build form builder UI, dynamic form renderer. ~7-10 days. + +--- + +### Priority Matrix + +| Priority | Feature | Impact | Effort | Status | +|----------|---------|--------|--------|--------| +| P0 | 5.1.1 Jury Evaluation Reminders | High | Low | **DONE** | +| P0 | 5.1.2 Evaluation Progress Indicator | High | Very Low | **DONE** | +| P0 | 5.1.3 Bulk Project Status Update | High | Low | **DONE** | +| P0 | 5.1.6 Conflict of Interest Declaration | High | Low | **DONE** | +| P1 | 5.1.4 Export Filtering Results | Medium | Very Low | **DONE** | +| P1 | 5.1.5 Observer Access to Reports | Medium | Low | **DONE** | +| P1 | 5.2.1 Email Digest Notifications | High | Medium | | +| P1 | 5.2.5 Applicant Portal Enhancements | High | Medium | **DONE** | +| P1 | 5.2.9 AI Evaluation Summary | High | Medium | **DONE** | +| P1 | 5.4.2 Evaluation Form Flexibility | High | Medium | **DONE** | +| P2 | 5.2.2 Evaluation Calibration Tool | Medium | Medium | | +| P2 | 5.2.4 Project Comparison View | Medium | Medium | | +| P2 | 5.2.6 Round Templates | Medium | Medium | | +| P2 | 5.2.7 Jury Availability Preferences | Medium | Medium | | +| P2 | 5.2.8 Real-Time Live Voting | Medium | Medium | | +| P2 | 5.4.1 Smart Assignment Improvements | Medium | Low | **DONE** | +| P2 | 5.4.4 File Management Improvements | Medium | Medium | | +| P2 | 5.4.5 Live Voting UX Improvements | Medium | Medium | | +| P2 | 5.4.6 Mentor Dashboard Enhancements | Medium | Medium | | +| P3 | 5.2.3 Multi-Language Support | High | High | | +| P3 | 5.3.1 Public Website Module | High | High | | +| P3 | 5.3.2 Communication Hub | High | High | | +| P3 | 5.3.3 Advanced Analytics Dashboard | Medium | High | | +| P3 | 5.3.4 Applicant Self-Service Drafts | Medium | Medium | | +| P3 | 5.3.5 Webhooks & API Integration | Medium | Medium | | +| P3 | 5.3.6 Peer Review / Collaborative Notes | Medium | High | | +| P3 | 5.4.3 Audit Log Enhancements | Low | Medium | | +| P3 | 5.4.7 Application Form Builder | Medium | High | | diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/README.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/README.md index 5b37404..5322362 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/README.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/README.md @@ -1,68 +1,68 @@ -# Mixed Round Design Implementation Docs - -## Purpose -This folder contains a single consolidated redesign program that intentionally blends: - -- Delivery rigor and governance discipline from `codex-round-system-redesign` -- Target architecture depth and runtime detail from `claude-round-system-redesign` -- Award governance semantics from `glm-5-round-redesign` (especially `AWARD_MASTER` and explicit decision modes) - -The goal is a complete, production-ready implementation plan for rebuilding round orchestration in MOPC with a full-cutover model. - -## Foundation and Blend Strategy - -### Foundation -The execution backbone is the `codex` style program model: - -1. Contract freeze first -2. Schema/runtime implementation in explicit phases -3. Platform-wide dependency refit (not just feature slices) -4. Mandatory phase gates with hard release blockers - -### Borrowed Enhancements -The plan imports high-value details from other proposals: - -- `claude`: richer canonical model (`Pipeline -> Track -> Stage`), explicit transition engine, routing and live-control runtime detail -- `glm-5`: award decision governance (`JURY_VOTE`, `AWARD_MASTER`, `ADMIN`) and explicit award track behavior options - -## Execution Model - -- Single destructive cutover -- Full reseed -- No backward-compatibility adapter layer -- No dual-write period -- One atomic release commit once all gates are green - -This model is intentionally selected because infrastructure reset/rebuild is allowed and preferred for architecture quality. - -## Architecture Summary - -- Competition lifecycle is stage-native, not round-pointer native. -- Projects progress through explicit `ProjectStageState` records. -- Special awards are first-class tracks, not bolt-on side tables. -- Routing is rule-driven with explainability payloads. -- Live finals are controlled by an admin cursor as the source of truth. -- Every override and decision is reasoned, immutable, and auditable. - -## Folder Layout - -- `master-implementation-plan.md`: end-to-end execution map -- `shared/`: cross-phase contracts, governance, test model, risks -- `phase-00-contract-freeze/` to `phase-07-validation-release/`: implementation phases -- `flowcharts/`: core control and routing diagrams - -## How to Use This Plan - -1. Start at `master-implementation-plan.md`. -2. Execute phases in order. -3. Do not start a phase unless all prior acceptance gates are complete. -4. Attach objective evidence for every gate. -5. Treat `phase-06-platform-dependency-refit` as mandatory release work, not cleanup. - -## Non-Negotiable Rules - -1. No hidden edit-only required settings. -2. Deterministic routing and ranking tie-break behavior. -3. Assignment coverage guarantees for eligible projects. -4. Explicit voting window control (schedules are advisory only). -5. No legacy orchestration contract references at release. +# Mixed Round Design Implementation Docs + +## Purpose +This folder contains a single consolidated redesign program that intentionally blends: + +- Delivery rigor and governance discipline from `codex-round-system-redesign` +- Target architecture depth and runtime detail from `claude-round-system-redesign` +- Award governance semantics from `glm-5-round-redesign` (especially `AWARD_MASTER` and explicit decision modes) + +The goal is a complete, production-ready implementation plan for rebuilding round orchestration in MOPC with a full-cutover model. + +## Foundation and Blend Strategy + +### Foundation +The execution backbone is the `codex` style program model: + +1. Contract freeze first +2. Schema/runtime implementation in explicit phases +3. Platform-wide dependency refit (not just feature slices) +4. Mandatory phase gates with hard release blockers + +### Borrowed Enhancements +The plan imports high-value details from other proposals: + +- `claude`: richer canonical model (`Pipeline -> Track -> Stage`), explicit transition engine, routing and live-control runtime detail +- `glm-5`: award decision governance (`JURY_VOTE`, `AWARD_MASTER`, `ADMIN`) and explicit award track behavior options + +## Execution Model + +- Single destructive cutover +- Full reseed +- No backward-compatibility adapter layer +- No dual-write period +- One atomic release commit once all gates are green + +This model is intentionally selected because infrastructure reset/rebuild is allowed and preferred for architecture quality. + +## Architecture Summary + +- Competition lifecycle is stage-native, not round-pointer native. +- Projects progress through explicit `ProjectStageState` records. +- Special awards are first-class tracks, not bolt-on side tables. +- Routing is rule-driven with explainability payloads. +- Live finals are controlled by an admin cursor as the source of truth. +- Every override and decision is reasoned, immutable, and auditable. + +## Folder Layout + +- `master-implementation-plan.md`: end-to-end execution map +- `shared/`: cross-phase contracts, governance, test model, risks +- `phase-00-contract-freeze/` to `phase-07-validation-release/`: implementation phases +- `flowcharts/`: core control and routing diagrams + +## How to Use This Plan + +1. Start at `master-implementation-plan.md`. +2. Execute phases in order. +3. Do not start a phase unless all prior acceptance gates are complete. +4. Attach objective evidence for every gate. +5. Treat `phase-06-platform-dependency-refit` as mandatory release work, not cleanup. + +## Non-Negotiable Rules + +1. No hidden edit-only required settings. +2. Deterministic routing and ranking tie-break behavior. +3. Assignment coverage guarantees for eligible projects. +4. Explicit voting window control (schedules are advisory only). +5. No legacy orchestration contract references at release. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/dependency-refit-map.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/dependency-refit-map.md index ef6ff83..140bbb8 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/dependency-refit-map.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/dependency-refit-map.md @@ -1,15 +1,15 @@ -# Dependency Refit Map - -```mermaid -flowchart LR - A[Schema Contracts] --> B[Router Refit] - A --> C[Service Refit] - B --> D[Admin UI Refit] - B --> E[Jury/Applicant/Public Refit] - C --> E - D --> F[Reporting/Exports] - E --> F - F --> G[Integration Consumer Validation] - G --> H[Legacy Symbol Sweep] - H --> I[Release Ready] -``` +# Dependency Refit Map + +```mermaid +flowchart LR + A[Schema Contracts] --> B[Router Refit] + A --> C[Service Refit] + B --> D[Admin UI Refit] + B --> E[Jury/Applicant/Public Refit] + C --> E + D --> F[Reporting/Exports] + E --> F + F --> G[Integration Consumer Validation] + G --> H[Legacy Symbol Sweep] + H --> I[Release Ready] +``` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/end-to-end-pipeline.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/end-to-end-pipeline.md index 67fc59b..9ff453f 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/end-to-end-pipeline.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/end-to-end-pipeline.md @@ -1,25 +1,25 @@ -# End-to-End Pipeline Flow - -```mermaid -flowchart TD - A[Intake Stage] --> B[Filter Stage] - B -->|pass| C[Main Evaluation Stage] - B -->|reject| R[Rejected with Notification] - B -->|award rule: parallel| W1[Award Track Entry] - B -->|award rule: exclusive| W2[Award Track Entry + Main Routed Out] - - C --> D[Selection Stage] - D --> E[Live Final Stage] - E --> F[Results Stage] - - W1 --> W3[Award Evaluation] - W2 --> W3[Award Evaluation] - W3 --> W4[Award Winner Decision] - - D -->|manual override| O[Override Action + Audit] - O --> D - - E --> L[Live Cursor + Cohort Windows] - L --> V[Jury and Audience Voting] - V --> F -``` +# End-to-End Pipeline Flow + +```mermaid +flowchart TD + A[Intake Stage] --> B[Filter Stage] + B -->|pass| C[Main Evaluation Stage] + B -->|reject| R[Rejected with Notification] + B -->|award rule: parallel| W1[Award Track Entry] + B -->|award rule: exclusive| W2[Award Track Entry + Main Routed Out] + + C --> D[Selection Stage] + D --> E[Live Final Stage] + E --> F[Results Stage] + + W1 --> W3[Award Evaluation] + W2 --> W3[Award Evaluation] + W3 --> W4[Award Winner Decision] + + D -->|manual override| O[Override Action + Audit] + O --> D + + E --> L[Live Cursor + Cohort Windows] + L --> V[Jury and Audience Voting] + V --> F +``` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/live-stage-controller.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/live-stage-controller.md index 4172c84..5998765 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/live-stage-controller.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/live-stage-controller.md @@ -1,15 +1,15 @@ -# Live Stage Controller - -```mermaid -flowchart TD - A[Admin Live Panel] --> B[Set Active Project Cursor] - B --> C[Persist Cursor Versioned Update] - C --> D[Broadcast Realtime Event] - D --> E[Jury Clients Sync] - D --> F[Audience Clients Sync] - - A --> G[Open Cohort Window] - A --> H[Close Cohort Window] - G --> I[Vote Acceptance On] - H --> J[Vote Acceptance Off] -``` +# Live Stage Controller + +```mermaid +flowchart TD + A[Admin Live Panel] --> B[Set Active Project Cursor] + B --> C[Persist Cursor Versioned Update] + C --> D[Broadcast Realtime Event] + D --> E[Jury Clients Sync] + D --> F[Audience Clients Sync] + + A --> G[Open Cohort Window] + A --> H[Close Cohort Window] + G --> I[Vote Acceptance On] + H --> J[Vote Acceptance Off] +``` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/main-vs-award-routing.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/main-vs-award-routing.md index 9df72e0..75463fa 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/main-vs-award-routing.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/main-vs-award-routing.md @@ -1,17 +1,17 @@ -# Main vs Award Routing - -```mermaid -flowchart LR - P[Project in Filter Stage] --> Q{Routing Rule Match?} - Q -->|No| M[Remain in Main Track] - Q -->|Yes| Z{Routing Mode} - - Z -->|PARALLEL| A[Create Award Stage State] - A --> B[Keep Main State Active] - - Z -->|EXCLUSIVE| C[Create Award Stage State] - C --> D[Mark Main State Routed] - - Z -->|POST_MAIN| E[Defer Route Until Gate Stage] - E --> F[Route After Main Gate Condition] -``` +# Main vs Award Routing + +```mermaid +flowchart LR + P[Project in Filter Stage] --> Q{Routing Rule Match?} + Q -->|No| M[Remain in Main Track] + Q -->|Yes| Z{Routing Mode} + + Z -->|PARALLEL| A[Create Award Stage State] + A --> B[Keep Main State Active] + + Z -->|EXCLUSIVE| C[Create Award Stage State] + C --> D[Mark Main State Routed] + + Z -->|POST_MAIN| E[Defer Route Until Gate Stage] + E --> F[Route After Main Gate Condition] +``` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/override-audit-flow.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/override-audit-flow.md index 5289ed3..5168a01 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/override-audit-flow.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/flowcharts/override-audit-flow.md @@ -1,14 +1,14 @@ -# Override Audit Flow - -```mermaid -flowchart TD - A[Override Request] --> B{Authz + Scope Check} - B -->|fail| X[FORBIDDEN] - B -->|pass| C{Reason Fields Present?} - C -->|no| Y[BAD_REQUEST] - C -->|yes| D[Fetch Current Value Snapshot] - D --> E[Apply Override Mutation] - E --> F[Persist Immutable OverrideAction] - F --> G[Append DecisionAuditLog] - G --> H[Return Updated Entity + Audit Ref] -``` +# Override Audit Flow + +```mermaid +flowchart TD + A[Override Request] --> B{Authz + Scope Check} + B -->|fail| X[FORBIDDEN] + B -->|pass| C{Reason Fields Present?} + C -->|no| Y[BAD_REQUEST] + C -->|yes| D[Fetch Current Value Snapshot] + D --> E[Apply Override Mutation] + E --> F[Persist Immutable OverrideAction] + F --> G[Append DecisionAuditLog] + G --> H[Return Updated Entity + Audit Ref] +``` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/master-implementation-plan.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/master-implementation-plan.md index a2dbf90..612533b 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/master-implementation-plan.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/master-implementation-plan.md @@ -1,95 +1,95 @@ -# Master Implementation Plan - -## Program Objective -Rebuild MOPC round orchestration from a round-centric model into a stage-native pipeline model that is easier to configure, more deterministic, and robust for main competition plus special awards and live finals. - -## Program Constraints - -- Preserve existing visual language and core UI component style. -- Complete architecture rebuild is allowed and encouraged. -- Delivery must be production-safe and verifiable. -- Release requires one atomic cutover commit after full validation. - -## Hard Invariants - -1. Every state transition is explicit, validated, and auditable. -2. Every override action captures `reasonCode` + `reasonText` + actor metadata. -3. No eligible project is left unassigned unless explicitly flagged as overflow with admin visibility. -4. Live active project state is admin-cursor driven. -5. Award routing behavior is explicit per award (`parallel`, `exclusive`, `post_main`). -6. Event contracts are deterministic and machine-readable. -7. At release, no runtime dependency on legacy `roundId` orchestration semantics remains. - -## Phase Chain - -1. Phase 00: Contract freeze -2. Phase 01: Schema and runtime foundation -3. Phase 02: Backend orchestration engine -4. Phase 03: Admin control-plane UX -5. Phase 04: Participant journeys -6. Phase 05: Special awards governance -7. Phase 06: Platform dependency refit -8. Phase 07: Validation and release - -## Required Deliverables by Phase - -- Phase 00: locked contracts, decision log, authz matrix, initial risk register -- Phase 01: canonical schema spec, migration/cutover scripts, reseed spec, integrity checks -- Phase 02: transition/routing/filtering/assignment/live runtime implementation specs -- Phase 03: wizard IA, advanced editor spec, form behavior and safety guardrails -- Phase 04: applicant/jury/audience runtime and UX contracts -- Phase 05: award governance modes and decision workflow implementation -- Phase 06: module-by-module refit completion + legacy symbol sweeps -- Phase 07: full test evidence, performance evidence, release runbook and sign-off - -## Entry and Exit Criteria (Program Level) - -### Entry - -- Shared contracts and decisions are locked. -- Team alignment on cutover model and no-compatibility policy. - -### Exit - -- All phase acceptance gates complete. -- Test matrix green for U/I/E/P suites. -- Performance and resilience evidence approved. -- Legacy symbol sweeps are empty. -- Release evidence report signed by Engineering + Product + Operations. - -## Release Blockers - -1. Any failing acceptance gate. -2. Any unresolved CRITICAL or HIGH risk without approved mitigation. -3. Any missing test evidence for mandatory scenario IDs. -4. Any legacy orchestration symbol found in runtime code paths. - -## Timeline Model - -- Phase 00: 2-3 days -- Phase 01: 1-1.5 weeks -- Phase 02: 1.5-2.5 weeks -- Phase 03: 1-1.5 weeks -- Phase 04: 1-1.5 weeks -- Phase 05: 0.75-1.25 weeks -- Phase 06: 1-1.5 weeks -- Phase 07: 1 week - -Total estimate: 8-11 weeks depending on test depth and refit complexity. - -## Evidence Standards - -Every acceptance gate requires at least one of: - -- Unit/integration/E2E output -- API response captures -- deterministic symbol sweeps -- migration integrity query output -- performance benchmark output -- release runbook logs - -## Enforcement Notes - -- No phase skipping. -- No deferred blocker carry-forward. -- No "ship and patch later" for contract-level gaps. +# Master Implementation Plan + +## Program Objective +Rebuild MOPC round orchestration from a round-centric model into a stage-native pipeline model that is easier to configure, more deterministic, and robust for main competition plus special awards and live finals. + +## Program Constraints + +- Preserve existing visual language and core UI component style. +- Complete architecture rebuild is allowed and encouraged. +- Delivery must be production-safe and verifiable. +- Release requires one atomic cutover commit after full validation. + +## Hard Invariants + +1. Every state transition is explicit, validated, and auditable. +2. Every override action captures `reasonCode` + `reasonText` + actor metadata. +3. No eligible project is left unassigned unless explicitly flagged as overflow with admin visibility. +4. Live active project state is admin-cursor driven. +5. Award routing behavior is explicit per award (`parallel`, `exclusive`, `post_main`). +6. Event contracts are deterministic and machine-readable. +7. At release, no runtime dependency on legacy `roundId` orchestration semantics remains. + +## Phase Chain + +1. Phase 00: Contract freeze +2. Phase 01: Schema and runtime foundation +3. Phase 02: Backend orchestration engine +4. Phase 03: Admin control-plane UX +5. Phase 04: Participant journeys +6. Phase 05: Special awards governance +7. Phase 06: Platform dependency refit +8. Phase 07: Validation and release + +## Required Deliverables by Phase + +- Phase 00: locked contracts, decision log, authz matrix, initial risk register +- Phase 01: canonical schema spec, migration/cutover scripts, reseed spec, integrity checks +- Phase 02: transition/routing/filtering/assignment/live runtime implementation specs +- Phase 03: wizard IA, advanced editor spec, form behavior and safety guardrails +- Phase 04: applicant/jury/audience runtime and UX contracts +- Phase 05: award governance modes and decision workflow implementation +- Phase 06: module-by-module refit completion + legacy symbol sweeps +- Phase 07: full test evidence, performance evidence, release runbook and sign-off + +## Entry and Exit Criteria (Program Level) + +### Entry + +- Shared contracts and decisions are locked. +- Team alignment on cutover model and no-compatibility policy. + +### Exit + +- All phase acceptance gates complete. +- Test matrix green for U/I/E/P suites. +- Performance and resilience evidence approved. +- Legacy symbol sweeps are empty. +- Release evidence report signed by Engineering + Product + Operations. + +## Release Blockers + +1. Any failing acceptance gate. +2. Any unresolved CRITICAL or HIGH risk without approved mitigation. +3. Any missing test evidence for mandatory scenario IDs. +4. Any legacy orchestration symbol found in runtime code paths. + +## Timeline Model + +- Phase 00: 2-3 days +- Phase 01: 1-1.5 weeks +- Phase 02: 1.5-2.5 weeks +- Phase 03: 1-1.5 weeks +- Phase 04: 1-1.5 weeks +- Phase 05: 0.75-1.25 weeks +- Phase 06: 1-1.5 weeks +- Phase 07: 1 week + +Total estimate: 8-11 weeks depending on test depth and refit complexity. + +## Evidence Standards + +Every acceptance gate requires at least one of: + +- Unit/integration/E2E output +- API response captures +- deterministic symbol sweeps +- migration integrity query output +- performance benchmark output +- release runbook logs + +## Enforcement Notes + +- No phase skipping. +- No deferred blocker carry-forward. +- No "ship and patch later" for contract-level gaps. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/acceptance-gates.md index ccaeb09..3bec3c1 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/acceptance-gates.md @@ -1,13 +1,13 @@ -# Phase 00 Acceptance Gates - -- [ ] G-00-1 Decision log locked (`shared/decision-log.md` signed by Eng + Product) -- [ ] G-00-2 Domain and API contracts approved -- [ ] G-00-3 Authz matrix approved -- [ ] G-00-4 Test matrix approved and mapped to owners -- [ ] G-00-5 Risk register initialized with owners and mitigation targets - -## Required Evidence - -- contract review notes -- sign-off comments or approval records -- updated risk register with owners +# Phase 00 Acceptance Gates + +- [ ] G-00-1 Decision log locked (`shared/decision-log.md` signed by Eng + Product) +- [ ] G-00-2 Domain and API contracts approved +- [ ] G-00-3 Authz matrix approved +- [ ] G-00-4 Test matrix approved and mapped to owners +- [ ] G-00-5 Risk register initialized with owners and mitigation targets + +## Required Evidence + +- contract review notes +- sign-off comments or approval records +- updated risk register with owners diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/overview.md index ba54caf..9454b83 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/overview.md @@ -1,35 +1,35 @@ -# Phase 00 Overview: Contract Freeze - -## Objective -Lock all cross-phase contracts before implementation so the program executes with stable boundaries and no semantic drift. - -## In Scope - -- decision locking -- API/type contract baseline -- authorization baseline -- gate and evidence baseline -- initial risk baseline - -## Out of Scope - -- schema implementation -- runtime implementation -- UI implementation - -## Inputs - -- `shared/program-charter.md` -- `shared/decision-log.md` -- `shared/domain-model.md` -- `shared/api-contracts.md` -- `shared/authz-matrix.md` -- `shared/test-matrix.md` - -## Exit Criteria - -1. Decision log marked locked with no unresolved critical decision. -2. API/type contracts accepted by backend and frontend owners. -3. Authz matrix accepted by security owner. -4. Risk register initialized with owners. -5. Phase 00 acceptance gates complete with evidence. +# Phase 00 Overview: Contract Freeze + +## Objective +Lock all cross-phase contracts before implementation so the program executes with stable boundaries and no semantic drift. + +## In Scope + +- decision locking +- API/type contract baseline +- authorization baseline +- gate and evidence baseline +- initial risk baseline + +## Out of Scope + +- schema implementation +- runtime implementation +- UI implementation + +## Inputs + +- `shared/program-charter.md` +- `shared/decision-log.md` +- `shared/domain-model.md` +- `shared/api-contracts.md` +- `shared/authz-matrix.md` +- `shared/test-matrix.md` + +## Exit Criteria + +1. Decision log marked locked with no unresolved critical decision. +2. API/type contracts accepted by backend and frontend owners. +3. Authz matrix accepted by security owner. +4. Risk register initialized with owners. +5. Phase 00 acceptance gates complete with evidence. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/tasks.md index 1f9d49a..bae72c6 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-00-contract-freeze/tasks.md @@ -1,31 +1,31 @@ -# Phase 00 Tasks - -## Task Set A: Contract Alignment - -- [ ] Validate `shared/domain-model.md` against current repository constraints. -- [ ] Validate `shared/api-contracts.md` names and payload conventions with router ownership. -- [ ] Validate event naming strategy with notification and webhook owners. - -## Task Set B: Governance Lock - -- [ ] Confirm `shared/decision-log.md` with Product + Engineering. -- [ ] Confirm cutover/no-compatibility policy in writing. -- [ ] Confirm override governance requirements and mandatory reason fields. - -## Task Set C: Access and Security - -- [ ] Validate `shared/authz-matrix.md` for each role. -- [ ] Define scope enforcement standard for program-scoped admin actions. -- [ ] Confirm audience vote abuse controls (token, rate-limit, dedupe key). - -## Task Set D: Validation Baseline - -- [ ] Validate `shared/test-matrix.md` coverage and practicality. -- [ ] Map each test ID to ownership. -- [ ] Confirm CI entry strategy for U/I/E/P layers. - -## Task Set E: Risk Baseline - -- [ ] Review `shared/risk-register.md` with owners. -- [ ] Add any repository-specific risks identified during contract review. -- [ ] Mark mitigation action owner and due phase per risk. +# Phase 00 Tasks + +## Task Set A: Contract Alignment + +- [ ] Validate `shared/domain-model.md` against current repository constraints. +- [ ] Validate `shared/api-contracts.md` names and payload conventions with router ownership. +- [ ] Validate event naming strategy with notification and webhook owners. + +## Task Set B: Governance Lock + +- [ ] Confirm `shared/decision-log.md` with Product + Engineering. +- [ ] Confirm cutover/no-compatibility policy in writing. +- [ ] Confirm override governance requirements and mandatory reason fields. + +## Task Set C: Access and Security + +- [ ] Validate `shared/authz-matrix.md` for each role. +- [ ] Define scope enforcement standard for program-scoped admin actions. +- [ ] Confirm audience vote abuse controls (token, rate-limit, dedupe key). + +## Task Set D: Validation Baseline + +- [ ] Validate `shared/test-matrix.md` coverage and practicality. +- [ ] Map each test ID to ownership. +- [ ] Confirm CI entry strategy for U/I/E/P layers. + +## Task Set E: Risk Baseline + +- [ ] Review `shared/risk-register.md` with owners. +- [ ] Add any repository-specific risks identified during contract review. +- [ ] Mark mitigation action owner and due phase per risk. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/acceptance-gates.md index 9e5c4d9..0a0fd2e 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/acceptance-gates.md @@ -1,14 +1,14 @@ -# Phase 01 Acceptance Gates - -- [ ] G-01-1 `prisma generate` succeeds -- [ ] G-01-2 reset/reseed succeeds in local and staging -- [ ] G-01-3 integrity queries return expected zero-error results -- [ ] G-01-4 required indexes confirmed in DB metadata -- [ ] G-01-5 phase artifacts stored and linked - -## Required Evidence - -- migration command output -- reseed logs -- integrity query result captures -- schema diff summary +# Phase 01 Acceptance Gates + +- [ ] G-01-1 `prisma generate` succeeds +- [ ] G-01-2 reset/reseed succeeds in local and staging +- [ ] G-01-3 integrity queries return expected zero-error results +- [ ] G-01-4 required indexes confirmed in DB metadata +- [ ] G-01-5 phase artifacts stored and linked + +## Required Evidence + +- migration command output +- reseed logs +- integrity query result captures +- schema diff summary diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/migration-cutover-plan.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/migration-cutover-plan.md index 7327f6d..d3a1e50 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/migration-cutover-plan.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/migration-cutover-plan.md @@ -1,48 +1,48 @@ -# Phase 01 Migration and Cutover Plan - -## Strategy -Perform architecture rebuild with reset/reseed as the official path. - -## Steps - -1. Finalize schema migration scripts. -2. Run local reset/reseed rehearsal. -3. Run staging reset/reseed rehearsal. -4. Execute integrity verification suite. -5. Lock schema contracts and produce baseline snapshot. - -## Verification Script Requirements - -- count checks for canonical entities -- FK integrity checks -- expected stage graph checks -- expected project intake state checks - -## Example Verification Queries - -```sql --- orphan project stage states -SELECT COUNT(*) -FROM "ProjectStageState" pss -LEFT JOIN "Project" p ON p.id = pss."projectId" -LEFT JOIN "Stage" s ON s.id = pss."stageId" -LEFT JOIN "Track" t ON t.id = pss."trackId" -WHERE p.id IS NULL OR s.id IS NULL OR t.id IS NULL; - --- project intake state coverage -SELECT COUNT(DISTINCT p.id) AS projects_without_intake -FROM "Project" p -LEFT JOIN "ProjectStageState" pss - ON pss."projectId" = p.id -LEFT JOIN "Stage" s - ON s.id = pss."stageId" -WHERE s."stageType" = 'INTAKE' - AND pss.id IS NULL; -``` - -## Cutover Readiness Artifacts Produced in Phase 01 - -- schema migration files -- seed scripts -- integrity query scripts -- reset/reseed execution logs +# Phase 01 Migration and Cutover Plan + +## Strategy +Perform architecture rebuild with reset/reseed as the official path. + +## Steps + +1. Finalize schema migration scripts. +2. Run local reset/reseed rehearsal. +3. Run staging reset/reseed rehearsal. +4. Execute integrity verification suite. +5. Lock schema contracts and produce baseline snapshot. + +## Verification Script Requirements + +- count checks for canonical entities +- FK integrity checks +- expected stage graph checks +- expected project intake state checks + +## Example Verification Queries + +```sql +-- orphan project stage states +SELECT COUNT(*) +FROM "ProjectStageState" pss +LEFT JOIN "Project" p ON p.id = pss."projectId" +LEFT JOIN "Stage" s ON s.id = pss."stageId" +LEFT JOIN "Track" t ON t.id = pss."trackId" +WHERE p.id IS NULL OR s.id IS NULL OR t.id IS NULL; + +-- project intake state coverage +SELECT COUNT(DISTINCT p.id) AS projects_without_intake +FROM "Project" p +LEFT JOIN "ProjectStageState" pss + ON pss."projectId" = p.id +LEFT JOIN "Stage" s + ON s.id = pss."stageId" +WHERE s."stageType" = 'INTAKE' + AND pss.id IS NULL; +``` + +## Cutover Readiness Artifacts Produced in Phase 01 + +- schema migration files +- seed scripts +- integrity query scripts +- reset/reseed execution logs diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/overview.md index 3e4562a..d52dcba 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/overview.md @@ -1,27 +1,27 @@ -# Phase 01 Overview: Schema and Runtime Foundation - -## Objective -Implement the canonical schema and reset/reseed capability that supports stage-native orchestration with award and live runtime primitives. - -## In Scope - -- prisma schema rebuild for canonical entities -- indexes and constraints for hot paths -- reset/reseed strategy and scripts -- data integrity verification scripts - -## Out of Scope - -- end-user UI behavior -- full router refit - -## Key Design Choice - -This phase uses full reset/reseed and does not attempt compatibility bridges. - -## Exit Criteria - -1. Schema compiles and generates client successfully. -2. Reset/reseed produces runnable dataset. -3. Integrity verification passes for FK/index and state initialization rules. -4. Phase 01 gates complete. +# Phase 01 Overview: Schema and Runtime Foundation + +## Objective +Implement the canonical schema and reset/reseed capability that supports stage-native orchestration with award and live runtime primitives. + +## In Scope + +- prisma schema rebuild for canonical entities +- indexes and constraints for hot paths +- reset/reseed strategy and scripts +- data integrity verification scripts + +## Out of Scope + +- end-user UI behavior +- full router refit + +## Key Design Choice + +This phase uses full reset/reseed and does not attempt compatibility bridges. + +## Exit Criteria + +1. Schema compiles and generates client successfully. +2. Reset/reseed produces runnable dataset. +3. Integrity verification passes for FK/index and state initialization rules. +4. Phase 01 gates complete. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/schema-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/schema-spec.md index 76af931..6005bd9 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/schema-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/schema-spec.md @@ -1,59 +1,59 @@ -# Phase 01 Schema Specification - -## Summary -Introduce the canonical orchestration entities and remove legacy dependency assumptions around single `roundId` progression. - -## New Canonical Tables - -1. `Pipeline` -2. `Track` -3. `Stage` -4. `StageTransition` -5. `ProjectStageState` -6. `RoutingRule` -7. `Cohort` -8. `CohortProject` -9. `LiveProgressCursor` -10. `NotificationPolicy` -11. `OverrideAction` -12. `DecisionAuditLog` - -## Award Governance Extensions - -- Add `DecisionMode = JURY_VOTE | AWARD_MASTER | ADMIN` -- Add award-scoped governance metadata to award track configs -- Add award winner finalization audit event contracts - -## Migration Model - -- Build new schema directly as canonical target. -- Keep migration files deterministic and replay-safe. -- Do not implement dual-write or compatibility tables. - -## Required Constraints - -1. `trackId + sortOrder` unique in `Stage` -2. `projectId + trackId + stageId` unique in `ProjectStageState` -3. `fromStageId + toStageId` unique in `StageTransition` -4. `cohortId + projectId` unique in `CohortProject` - -## Required Indexes - -- `ProjectStageState(projectId, trackId, state)` -- `ProjectStageState(stageId, state)` -- `RoutingRule(pipelineId, isActive, priority)` -- `StageTransition(fromStageId, priority)` -- `DecisionAuditLog(entityType, entityId, createdAt)` -- `LiveProgressCursor(stageId, sessionId)` - -## Data Initialization Rules - -- Every seeded project must start with one intake-stage state. -- Seed must include main track plus at least two award tracks with different routing modes. -- Seed must include representative roles: admins, jury, applicants, observer, audience contexts. - -## Integrity Checks - -- No orphan states. -- No invalid transition targets across pipelines. -- No duplicate active state rows for same `(project, track, stage)`. +# Phase 01 Schema Specification + +## Summary +Introduce the canonical orchestration entities and remove legacy dependency assumptions around single `roundId` progression. + +## New Canonical Tables + +1. `Pipeline` +2. `Track` +3. `Stage` +4. `StageTransition` +5. `ProjectStageState` +6. `RoutingRule` +7. `Cohort` +8. `CohortProject` +9. `LiveProgressCursor` +10. `NotificationPolicy` +11. `OverrideAction` +12. `DecisionAuditLog` + +## Award Governance Extensions + +- Add `DecisionMode = JURY_VOTE | AWARD_MASTER | ADMIN` +- Add award-scoped governance metadata to award track configs +- Add award winner finalization audit event contracts + +## Migration Model + +- Build new schema directly as canonical target. +- Keep migration files deterministic and replay-safe. +- Do not implement dual-write or compatibility tables. + +## Required Constraints + +1. `trackId + sortOrder` unique in `Stage` +2. `projectId + trackId + stageId` unique in `ProjectStageState` +3. `fromStageId + toStageId` unique in `StageTransition` +4. `cohortId + projectId` unique in `CohortProject` + +## Required Indexes + +- `ProjectStageState(projectId, trackId, state)` +- `ProjectStageState(stageId, state)` +- `RoutingRule(pipelineId, isActive, priority)` +- `StageTransition(fromStageId, priority)` +- `DecisionAuditLog(entityType, entityId, createdAt)` +- `LiveProgressCursor(stageId, sessionId)` + +## Data Initialization Rules + +- Every seeded project must start with one intake-stage state. +- Seed must include main track plus at least two award tracks with different routing modes. +- Seed must include representative roles: admins, jury, applicants, observer, audience contexts. + +## Integrity Checks + +- No orphan states. +- No invalid transition targets across pipelines. +- No duplicate active state rows for same `(project, track, stage)`. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/tasks.md index e0abca5..b4eee91 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-01-schema-runtime-foundation/tasks.md @@ -1,24 +1,24 @@ -# Phase 01 Tasks - -## Schema Build - -- [ ] Implement canonical entities and enums in `prisma/schema.prisma`. -- [ ] Add required constraints and indexes. -- [ ] Remove or isolate legacy-only orchestration semantics from canonical paths. - -## Seed and Fixtures - -- [ ] Implement reseed script with realistic data volumes and edge cases. -- [ ] Include parallel, exclusive, and post-main award routing seed examples. -- [ ] Include live cohort seed data. - -## Verification - -- [ ] Implement integrity SQL scripts. -- [ ] Implement automated verification command wrapper. -- [ ] Record baseline output and attach to gate evidence. - -## Documentation - -- [ ] Update schema change notes. -- [ ] Document reset/reseed assumptions. +# Phase 01 Tasks + +## Schema Build + +- [ ] Implement canonical entities and enums in `prisma/schema.prisma`. +- [ ] Add required constraints and indexes. +- [ ] Remove or isolate legacy-only orchestration semantics from canonical paths. + +## Seed and Fixtures + +- [ ] Implement reseed script with realistic data volumes and edge cases. +- [ ] Include parallel, exclusive, and post-main award routing seed examples. +- [ ] Include live cohort seed data. + +## Verification + +- [ ] Implement integrity SQL scripts. +- [ ] Implement automated verification command wrapper. +- [ ] Record baseline output and attach to gate evidence. + +## Documentation + +- [ ] Update schema change notes. +- [ ] Document reset/reseed assumptions. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/acceptance-gates.md index cbe9876..d7a829f 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/acceptance-gates.md @@ -1,14 +1,14 @@ -# Phase 02 Acceptance Gates - -- [ ] G-02-1 transition engine tests pass -- [ ] G-02-2 routing determinism tests pass -- [ ] G-02-3 filtering policy tests pass -- [ ] G-02-4 assignment guarantee tests pass -- [ ] G-02-5 live cursor and cohort window tests pass -- [ ] G-02-6 override/audit tests pass - -## Required Evidence - -- U/I test output for all mapped IDs -- sample API responses for major mutation endpoints -- audit payload examples for transition and override flows +# Phase 02 Acceptance Gates + +- [ ] G-02-1 transition engine tests pass +- [ ] G-02-2 routing determinism tests pass +- [ ] G-02-3 filtering policy tests pass +- [ ] G-02-4 assignment guarantee tests pass +- [ ] G-02-5 live cursor and cohort window tests pass +- [ ] G-02-6 override/audit tests pass + +## Required Evidence + +- U/I test output for all mapped IDs +- sample API responses for major mutation endpoints +- audit payload examples for transition and override flows diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/assignment-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/assignment-spec.md index 12c9a1d..0eb0730 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/assignment-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/assignment-spec.md @@ -1,43 +1,43 @@ -# Assignment Engine Specification - -## Objective -Generate high-quality, fair assignments while guaranteeing eligible project coverage. - -## Inputs - -- stage ID -- eligible project set -- assignee pool -- required reviews per project -- assignment strategy config -- availability and COI policies - -## Hard Constraints - -1. COI exclusion -2. role/status eligibility -3. explicit max-load cap -4. minimum review floor - -## Soft Scoring Dimensions - -- expertise overlap -- bio/project similarity -- availability weighting -- workload balancing -- optional geo diversity -- optional prior-familiarity weighting - -## Guarantee Rules - -1. No eligible project left uncovered. -2. If capacity insufficient, create overflow assignments with warning markers. -3. Preview and execution must match constraints and scoring semantics. - -## Output Contract - -- assigned count -- uncovered count (must be zero unless in explicit error mode) -- overflow assignment list -- conflict skips list -- fairness metrics (median load, max load) +# Assignment Engine Specification + +## Objective +Generate high-quality, fair assignments while guaranteeing eligible project coverage. + +## Inputs + +- stage ID +- eligible project set +- assignee pool +- required reviews per project +- assignment strategy config +- availability and COI policies + +## Hard Constraints + +1. COI exclusion +2. role/status eligibility +3. explicit max-load cap +4. minimum review floor + +## Soft Scoring Dimensions + +- expertise overlap +- bio/project similarity +- availability weighting +- workload balancing +- optional geo diversity +- optional prior-familiarity weighting + +## Guarantee Rules + +1. No eligible project left uncovered. +2. If capacity insufficient, create overflow assignments with warning markers. +3. Preview and execution must match constraints and scoring semantics. + +## Output Contract + +- assigned count +- uncovered count (must be zero unless in explicit error mode) +- overflow assignment list +- conflict skips list +- fairness metrics (median load, max load) diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/filtering-routing-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/filtering-routing-spec.md index 4160110..816b72d 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/filtering-routing-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/filtering-routing-spec.md @@ -1,55 +1,55 @@ -# Filtering and Routing Specification - -## Filtering Pipeline - -1. deterministic gates -2. AI rubric evaluation -3. confidence band decisioning -4. manual queue resolution - -## Deterministic Gates First Rule - -AI execution is prohibited unless deterministic gates pass. - -## AI Output Contract - -- criteria scores -- overall recommendation -- confidence -- rationale -- risk flags - -## Confidence Bands - -- `high`: auto decision path -- `medium`: manual queue -- `low`: reject or manual based on stage policy - -## Routing Rules - -### Evaluation Order - -1. stage-scoped rules -2. track-scoped rules -3. global rules -4. default fallback - -### Deterministic Tie-Break - -- highest priority wins -- if equal, lexical rule ID fallback - -### Explainability Persisted - -Each route persists: - -- matched rule ID -- predicate snapshot -- mode (`AUTO|MANUAL`) -- destination track/stage - -## Award Routing Modes - -- `PARALLEL`: keep main progression and add award state -- `EXCLUSIVE`: route out of main progression into award track only -- `POST_MAIN`: route only after configured main gate stage +# Filtering and Routing Specification + +## Filtering Pipeline + +1. deterministic gates +2. AI rubric evaluation +3. confidence band decisioning +4. manual queue resolution + +## Deterministic Gates First Rule + +AI execution is prohibited unless deterministic gates pass. + +## AI Output Contract + +- criteria scores +- overall recommendation +- confidence +- rationale +- risk flags + +## Confidence Bands + +- `high`: auto decision path +- `medium`: manual queue +- `low`: reject or manual based on stage policy + +## Routing Rules + +### Evaluation Order + +1. stage-scoped rules +2. track-scoped rules +3. global rules +4. default fallback + +### Deterministic Tie-Break + +- highest priority wins +- if equal, lexical rule ID fallback + +### Explainability Persisted + +Each route persists: + +- matched rule ID +- predicate snapshot +- mode (`AUTO|MANUAL`) +- destination track/stage + +## Award Routing Modes + +- `PARALLEL`: keep main progression and add award state +- `EXCLUSIVE`: route out of main progression into award track only +- `POST_MAIN`: route only after configured main gate stage diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/live-control-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/live-control-spec.md index 9ce21bc..d1de304 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/live-control-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/live-control-spec.md @@ -1,32 +1,32 @@ -# Live Control Specification - -## Source of Truth -Admin cursor state is the single source of truth for active project context during live stages. - -## Core Controls - -- start session -- next/previous -- jump to project -- reorder queue -- open/close cohort windows -- pause/resume session - -## Runtime Requirements - -1. cursor updates are versioned -2. race conditions return `CONFLICT` and require refresh/retry -3. real-time propagation to jury and audience clients -4. reconnect path converges to current cursor/window state - -## Vote Acceptance Rules - -- stage and cohort windows must be open -- dedupe key policy enforced (`session/cohort/project/voter/window`) -- closed windows reject submissions deterministically - -## Event Contract - -- `live.cursor.updated` -- `cohort.window.changed` -- `live.session.state.changed` +# Live Control Specification + +## Source of Truth +Admin cursor state is the single source of truth for active project context during live stages. + +## Core Controls + +- start session +- next/previous +- jump to project +- reorder queue +- open/close cohort windows +- pause/resume session + +## Runtime Requirements + +1. cursor updates are versioned +2. race conditions return `CONFLICT` and require refresh/retry +3. real-time propagation to jury and audience clients +4. reconnect path converges to current cursor/window state + +## Vote Acceptance Rules + +- stage and cohort windows must be open +- dedupe key policy enforced (`session/cohort/project/voter/window`) +- closed windows reject submissions deterministically + +## Event Contract + +- `live.cursor.updated` +- `cohort.window.changed` +- `live.session.state.changed` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/overview.md index 1ae6884..0ff84d4 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/overview.md @@ -1,23 +1,23 @@ -# Phase 02 Overview: Backend Orchestration Engine - -## Objective -Implement deterministic runtime behavior for stage transitions, routing, filtering, assignment, live cursor control, and notification/audit emission. - -## In Scope - -- transition engine -- routing engine -- filtering orchestration (gates + AI + manual queue) -- assignment orchestration with coverage guarantees -- live cursor and cohort window controls -- event and audit emission - -## Out of Scope - -- full admin UI and participant UI implementation - -## Exit Criteria - -1. Runtime contracts implemented and integration-tested. -2. Determinism and idempotency guarantees proven for critical mutations. -3. Mandatory phase gates complete with test evidence. +# Phase 02 Overview: Backend Orchestration Engine + +## Objective +Implement deterministic runtime behavior for stage transitions, routing, filtering, assignment, live cursor control, and notification/audit emission. + +## In Scope + +- transition engine +- routing engine +- filtering orchestration (gates + AI + manual queue) +- assignment orchestration with coverage guarantees +- live cursor and cohort window controls +- event and audit emission + +## Out of Scope + +- full admin UI and participant UI implementation + +## Exit Criteria + +1. Runtime contracts implemented and integration-tested. +2. Determinism and idempotency guarantees proven for critical mutations. +3. Mandatory phase gates complete with test evidence. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/stage-engine-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/stage-engine-spec.md index 0c835e6..4ace715 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/stage-engine-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/stage-engine-spec.md @@ -1,46 +1,46 @@ -# Stage Engine Specification - -## Responsibilities - -1. Validate transition legality. -2. Move project states transactionally. -3. Emit transition events and audit entries. -4. Enforce concurrency safety. - -## State Machine - -`PENDING -> IN_PROGRESS -> PASSED|REJECTED -> ROUTED -> COMPLETED` - -`WITHDRAWN` is terminal for participant-triggered withdrawal paths. - -## Transition Guards - -- source state row exists and is active -- destination stage is active and in same pipeline (unless routing rule applies) -- stage window and guard conditions satisfied -- no concurrent conflicting transition - -## Mutation Semantics - -- transactional updates per batch slice -- optimistic locking/version checks -- per-project result collection for partial failure reporting - -## Failure Codes - -- `PRECONDITION_FAILED`: guard not satisfied -- `CONFLICT`: state moved after read -- `BAD_REQUEST`: invalid transition target - -## Audit Contract - -`eventType = stage.transitioned` - -Payload includes: - -- actor -- source stage -- destination stage -- old/new state -- reason/context -- timestamp +# Stage Engine Specification + +## Responsibilities + +1. Validate transition legality. +2. Move project states transactionally. +3. Emit transition events and audit entries. +4. Enforce concurrency safety. + +## State Machine + +`PENDING -> IN_PROGRESS -> PASSED|REJECTED -> ROUTED -> COMPLETED` + +`WITHDRAWN` is terminal for participant-triggered withdrawal paths. + +## Transition Guards + +- source state row exists and is active +- destination stage is active and in same pipeline (unless routing rule applies) +- stage window and guard conditions satisfied +- no concurrent conflicting transition + +## Mutation Semantics + +- transactional updates per batch slice +- optimistic locking/version checks +- per-project result collection for partial failure reporting + +## Failure Codes + +- `PRECONDITION_FAILED`: guard not satisfied +- `CONFLICT`: state moved after read +- `BAD_REQUEST`: invalid transition target + +## Audit Contract + +`eventType = stage.transitioned` + +Payload includes: + +- actor +- source stage +- destination stage +- old/new state +- reason/context +- timestamp diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/tasks.md index 2ea1cb5..b494d96 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-02-backend-orchestration/tasks.md @@ -1,30 +1,30 @@ -# Phase 02 Tasks - -## Transition Engine - -- [ ] Implement transition guard and mutation logic. -- [ ] Implement optimistic concurrency handling. -- [ ] Implement transition event and audit emission. - -## Filtering and Routing - -- [ ] Implement deterministic gate-first pipeline. -- [ ] Implement confidence band decision handling. -- [ ] Implement routing rule engine with explainability payloads. - -## Assignment - -- [ ] Implement assignment preview and execute parity. -- [ ] Implement coverage guarantee and overflow semantics. -- [ ] Implement assignment metrics output. - -## Live Runtime - -- [ ] Implement admin cursor operations and conflict-safe update model. -- [ ] Implement cohort window control. -- [ ] Implement real-time event propagation path. - -## Notifications and Audit - -- [ ] Implement default event producers for stage transitions and outcomes. -- [ ] Implement immutable audit payload structure. +# Phase 02 Tasks + +## Transition Engine + +- [ ] Implement transition guard and mutation logic. +- [ ] Implement optimistic concurrency handling. +- [ ] Implement transition event and audit emission. + +## Filtering and Routing + +- [ ] Implement deterministic gate-first pipeline. +- [ ] Implement confidence band decision handling. +- [ ] Implement routing rule engine with explainability payloads. + +## Assignment + +- [ ] Implement assignment preview and execute parity. +- [ ] Implement coverage guarantee and overflow semantics. +- [ ] Implement assignment metrics output. + +## Live Runtime + +- [ ] Implement admin cursor operations and conflict-safe update model. +- [ ] Implement cohort window control. +- [ ] Implement real-time event propagation path. + +## Notifications and Audit + +- [ ] Implement default event producers for stage transitions and outcomes. +- [ ] Implement immutable audit payload structure. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/acceptance-gates.md index fd4ecca..edde412 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/acceptance-gates.md @@ -1,12 +1,12 @@ -# Phase 03 Acceptance Gates - -- [ ] G-03-1 wizard can complete full required setup (E-001) -- [ ] G-03-2 no hidden edit-only required settings remain -- [ ] G-03-3 advanced editor enforces graph/config guardrails -- [ ] G-03-4 modal and form safety regressions pass - -## Required Evidence - -- E2E wizard completion evidence -- parity checklist artifacts -- targeted UI regression test output +# Phase 03 Acceptance Gates + +- [ ] G-03-1 wizard can complete full required setup (E-001) +- [ ] G-03-2 no hidden edit-only required settings remain +- [ ] G-03-3 advanced editor enforces graph/config guardrails +- [ ] G-03-4 modal and form safety regressions pass + +## Required Evidence + +- E2E wizard completion evidence +- parity checklist artifacts +- targeted UI regression test output diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/advanced-editor-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/advanced-editor-spec.md index 77b83ad..7925f84 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/advanced-editor-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/advanced-editor-spec.md @@ -1,34 +1,34 @@ -# Advanced Editor Specification - -## Purpose -Provide direct manipulation of tracks, stages, transitions, and routing without polluting the default wizard path. - -## Panels - -1. Track/Stage List Panel -2. Stage Config Panel -3. Transition Graph Panel -4. Routing Rule Inspector -5. Simulation Panel - -## Required Capabilities - -- reorder stages within track -- move valid stages across tracks -- create/delete transitions -- edit rule predicates and priorities -- simulate outcomes for sample project IDs - -## Guardrails - -1. Block disconnected required paths. -2. Block orphan stage deletion. -3. Warn before destructive transition/rule removal. -4. Enforce schema validation for stage config payloads. - -## Save Model - -- draft buffer -- validation run -- transactional persist -- validation report artifact +# Advanced Editor Specification + +## Purpose +Provide direct manipulation of tracks, stages, transitions, and routing without polluting the default wizard path. + +## Panels + +1. Track/Stage List Panel +2. Stage Config Panel +3. Transition Graph Panel +4. Routing Rule Inspector +5. Simulation Panel + +## Required Capabilities + +- reorder stages within track +- move valid stages across tracks +- create/delete transitions +- edit rule predicates and priorities +- simulate outcomes for sample project IDs + +## Guardrails + +1. Block disconnected required paths. +2. Block orphan stage deletion. +3. Warn before destructive transition/rule removal. +4. Enforce schema validation for stage config payloads. + +## Save Model + +- draft buffer +- validation run +- transactional persist +- validation report artifact diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/form-behavior-and-validation.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/form-behavior-and-validation.md index 6ed2143..028c392 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/form-behavior-and-validation.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/form-behavior-and-validation.md @@ -1,30 +1,30 @@ -# Form Behavior and Validation Rules - -## Universal Rules - -1. Every required field has inline validation. -2. Every select has deterministic default value. -3. Save actions are idempotent and disabled while pending. -4. Unsafe changes surface explicit impact warnings. - -## Create/Edit Parity Requirements - -- intake windows -- upload policy -- file requirements -- assignment policy -- filtering policy -- routing policy -- live policy - -## Modal Safety Rules - -1. Modal close must not mutate persisted state. -2. Non-submit buttons must explicitly set `type="button"`. -3. Escape/cancel should only dismiss local draft state. - -## Payload Safety - -- replace raw free-text config where structured selectors exist -- normalize serialization format for config payloads -- reject unknown keys in strict mode contracts +# Form Behavior and Validation Rules + +## Universal Rules + +1. Every required field has inline validation. +2. Every select has deterministic default value. +3. Save actions are idempotent and disabled while pending. +4. Unsafe changes surface explicit impact warnings. + +## Create/Edit Parity Requirements + +- intake windows +- upload policy +- file requirements +- assignment policy +- filtering policy +- routing policy +- live policy + +## Modal Safety Rules + +1. Modal close must not mutate persisted state. +2. Non-submit buttons must explicitly set `type="button"`. +3. Escape/cancel should only dismiss local draft state. + +## Payload Safety + +- replace raw free-text config where structured selectors exist +- normalize serialization format for config payloads +- reject unknown keys in strict mode contracts diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/overview.md index 443ef23..859b1af 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/overview.md @@ -1,23 +1,23 @@ -# Phase 03 Overview: Admin Control-Plane UX - -## Objective -Deliver a wizard-first admin control plane that exposes full required configuration in create-time flow, with a safe advanced editor for power users. - -## In Scope - -- setup wizard IA and behavior -- advanced stage and routing editor -- simulation and validation panel -- create/edit parity - -## Out of Scope - -- visual redesign -- participant-facing workflows - -## Exit Criteria - -1. Full required setup possible from create flow. -2. No hidden edit-only required fields. -3. Validation and simulation guardrails implemented. -4. Phase gates complete. +# Phase 03 Overview: Admin Control-Plane UX + +## Objective +Deliver a wizard-first admin control plane that exposes full required configuration in create-time flow, with a safe advanced editor for power users. + +## In Scope + +- setup wizard IA and behavior +- advanced stage and routing editor +- simulation and validation panel +- create/edit parity + +## Out of Scope + +- visual redesign +- participant-facing workflows + +## Exit Criteria + +1. Full required setup possible from create flow. +2. No hidden edit-only required fields. +3. Validation and simulation guardrails implemented. +4. Phase gates complete. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/tasks.md index fb9b5d7..1a090a2 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/tasks.md @@ -1,19 +1,19 @@ -# Phase 03 Tasks - -## Wizard - -- [ ] Implement 8-step setup flow. -- [ ] Implement step-level validation and progress state. -- [ ] Implement review/publish summary and blockers. - -## Advanced Editor - -- [ ] Implement stage/transition/routing editing surfaces. -- [ ] Implement simulation runner and result panel. -- [ ] Implement destructive action confirmations. - -## Behavior and Safety - -- [ ] Enforce create/edit parity checklist. -- [ ] Enforce modal safety rules. -- [ ] Enforce strict payload validation. +# Phase 03 Tasks + +## Wizard + +- [ ] Implement 8-step setup flow. +- [ ] Implement step-level validation and progress state. +- [ ] Implement review/publish summary and blockers. + +## Advanced Editor + +- [ ] Implement stage/transition/routing editing surfaces. +- [ ] Implement simulation runner and result panel. +- [ ] Implement destructive action confirmations. + +## Behavior and Safety + +- [ ] Enforce create/edit parity checklist. +- [ ] Enforce modal safety rules. +- [ ] Enforce strict payload validation. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/wizard-ia.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/wizard-ia.md index f4c9f57..8d6d1bb 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/wizard-ia.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-03-admin-control-plane-ux/wizard-ia.md @@ -1,78 +1,78 @@ -# Admin Wizard IA - -## Step Sequence - -1. Intake Setup -2. Main Track Stage Setup -3. Filtering Strategy -4. Assignment Strategy -5. Special Awards -6. Live Finals Configuration -7. Notifications and Overrides -8. Review + Publish - -## Step Details - -### 1) Intake Setup - -- submission windows -- late policy -- file requirements -- MIME/size constraints -- applicant communication policy - -### 2) Main Track Stage Setup - -- stage list and ordering -- stage type assignment -- status defaults -- selection stage presets - -### 3) Filtering Strategy - -- deterministic gate definition -- AI rubric configuration -- confidence thresholds -- manual queue owners - -### 4) Assignment Strategy - -- required reviews -- max/min load settings -- availability weighting -- overflow handling policy - -### 5) Special Awards - -- award track enablement -- routing mode per award -- decision mode per award -- award jury restrictions - -### 6) Live Finals - -- cursor control mode -- jury vote config -- audience vote config -- cohort setup -- reveal policy - -### 7) Notifications and Overrides - -- default-on event toggles -- template overrides -- override governance policy - -### 8) Review + Publish - -- summary diff -- warnings/blockers -- simulation output -- publish action - -## UX Requirements - -- mobile-safe interaction and layout -- explicit required field indicators -- deterministic defaults for every select -- inline validation without hidden blockers +# Admin Wizard IA + +## Step Sequence + +1. Intake Setup +2. Main Track Stage Setup +3. Filtering Strategy +4. Assignment Strategy +5. Special Awards +6. Live Finals Configuration +7. Notifications and Overrides +8. Review + Publish + +## Step Details + +### 1) Intake Setup + +- submission windows +- late policy +- file requirements +- MIME/size constraints +- applicant communication policy + +### 2) Main Track Stage Setup + +- stage list and ordering +- stage type assignment +- status defaults +- selection stage presets + +### 3) Filtering Strategy + +- deterministic gate definition +- AI rubric configuration +- confidence thresholds +- manual queue owners + +### 4) Assignment Strategy + +- required reviews +- max/min load settings +- availability weighting +- overflow handling policy + +### 5) Special Awards + +- award track enablement +- routing mode per award +- decision mode per award +- award jury restrictions + +### 6) Live Finals + +- cursor control mode +- jury vote config +- audience vote config +- cohort setup +- reveal policy + +### 7) Notifications and Overrides + +- default-on event toggles +- template overrides +- override governance policy + +### 8) Review + Publish + +- summary diff +- warnings/blockers +- simulation output +- publish action + +## UX Requirements + +- mobile-safe interaction and layout +- explicit required field indicators +- deterministic defaults for every select +- inline validation without hidden blockers diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/acceptance-gates.md index 1078f08..26f9c51 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/acceptance-gates.md @@ -1,11 +1,11 @@ -# Phase 04 Acceptance Gates - -- [ ] G-04-1 applicant flow tests pass (E-002) -- [ ] G-04-2 jury flow tests pass (E-004) -- [ ] G-04-3 live audience tests pass (E-006/E-007) -- [ ] G-04-4 reconnect and realtime resilience evidence passes (P-004) - -## Required Evidence - -- E2E artifacts for applicant/jury/audience scenarios -- realtime and reconnect test captures +# Phase 04 Acceptance Gates + +- [ ] G-04-1 applicant flow tests pass (E-002) +- [ ] G-04-2 jury flow tests pass (E-004) +- [ ] G-04-3 live audience tests pass (E-006/E-007) +- [ ] G-04-4 reconnect and realtime resilience evidence passes (P-004) + +## Required Evidence + +- E2E artifacts for applicant/jury/audience scenarios +- realtime and reconnect test captures diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/applicant-experience-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/applicant-experience-spec.md index 27b6c7a..d2c3726 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/applicant-experience-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/applicant-experience-spec.md @@ -1,29 +1,29 @@ -# Applicant Experience Specification - -## Required Views - -1. current stage and timeline -2. stage-specific requirements -3. deadlines and late policy status -4. team invite/account status -5. decision history (policy-scoped) - -## Behavior Requirements - -- requirement upload slots are stage-aware -- accepted MIME/size and deadline checks enforced at submit time -- timeline updates reflect transition and decision events quickly -- role-scoped team collaboration controls enforced - -## Error States - -- missing requirement definition -- expired upload window -- invalid MIME/size -- stale session/permission mismatch - -## Notification Expectations - -- intake submitted confirmation -- advanced/rejected updates -- additional requirement requests when policy allows +# Applicant Experience Specification + +## Required Views + +1. current stage and timeline +2. stage-specific requirements +3. deadlines and late policy status +4. team invite/account status +5. decision history (policy-scoped) + +## Behavior Requirements + +- requirement upload slots are stage-aware +- accepted MIME/size and deadline checks enforced at submit time +- timeline updates reflect transition and decision events quickly +- role-scoped team collaboration controls enforced + +## Error States + +- missing requirement definition +- expired upload window +- invalid MIME/size +- stale session/permission mismatch + +## Notification Expectations + +- intake submitted confirmation +- advanced/rejected updates +- additional requirement requests when policy allows diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/audience-live-vote-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/audience-live-vote-spec.md index ed4c0e4..95a7b4a 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/audience-live-vote-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/audience-live-vote-spec.md @@ -1,24 +1,24 @@ -# Audience Live Vote Specification - -## Core Rules - -1. Audience sees only projects within active cohort/window policy. -2. Vote submission requires valid session eligibility and dedupe key check. -3. Closed windows reject submissions with typed error. - -## Voting Modes - -- per-project window -- per-cohort window -- optional criteria mode or simple score mode - -## Safety and Abuse Controls - -- tokenized access policy -- optional identity requirement -- rate-limit and dedupe enforcement - -## Realtime Requirements - -- active project state and window state sync in near real-time -- reconnect path restores current eligible ballot context +# Audience Live Vote Specification + +## Core Rules + +1. Audience sees only projects within active cohort/window policy. +2. Vote submission requires valid session eligibility and dedupe key check. +3. Closed windows reject submissions with typed error. + +## Voting Modes + +- per-project window +- per-cohort window +- optional criteria mode or simple score mode + +## Safety and Abuse Controls + +- tokenized access policy +- optional identity requirement +- rate-limit and dedupe enforcement + +## Realtime Requirements + +- active project state and window state sync in near real-time +- reconnect path restores current eligible ballot context diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/jury-experience-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/jury-experience-spec.md index dd3c8a8..2af5ca0 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/jury-experience-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/jury-experience-spec.md @@ -1,26 +1,26 @@ -# Jury Experience Specification - -## Assignment View - -- grouped by stage -- explicit open/close window indicators -- progress and completion states - -## Evaluation View - -- criteria loaded from stage config -- required criteria enforcement -- draft autosave and submit lock behavior -- COI declaration flow integrated - -## Access Rules - -- only assigned projects visible -- voting restricted to open windows -- prior-stage material visibility policy respected - -## Live Jury Behavior - -- active project context sync via realtime updates -- vote actions gated by cursor and window state -- reconnect restores current live context +# Jury Experience Specification + +## Assignment View + +- grouped by stage +- explicit open/close window indicators +- progress and completion states + +## Evaluation View + +- criteria loaded from stage config +- required criteria enforcement +- draft autosave and submit lock behavior +- COI declaration flow integrated + +## Access Rules + +- only assigned projects visible +- voting restricted to open windows +- prior-stage material visibility policy respected + +## Live Jury Behavior + +- active project context sync via realtime updates +- vote actions gated by cursor and window state +- reconnect restores current live context diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/overview.md index 6f8087b..24b69d8 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/overview.md @@ -1,21 +1,21 @@ -# Phase 04 Overview: Participant Journeys - -## Objective -Refit applicant, jury, observer, and audience experiences to stage-native contracts with correct realtime behavior. - -## In Scope - -- applicant intake/status flows -- jury assignment/evaluation/live flows -- audience voting and live score flows -- observer read-only reporting alignment - -## Out of Scope - -- admin config internals - -## Exit Criteria - -1. End-to-end participant paths pass mandatory E2E tests. -2. Realtime behavior converges under reconnect and window changes. -3. Policy enforcement matches authz and stage contracts. +# Phase 04 Overview: Participant Journeys + +## Objective +Refit applicant, jury, observer, and audience experiences to stage-native contracts with correct realtime behavior. + +## In Scope + +- applicant intake/status flows +- jury assignment/evaluation/live flows +- audience voting and live score flows +- observer read-only reporting alignment + +## Out of Scope + +- admin config internals + +## Exit Criteria + +1. End-to-end participant paths pass mandatory E2E tests. +2. Realtime behavior converges under reconnect and window changes. +3. Policy enforcement matches authz and stage contracts. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/tasks.md index da5e282..5e3f3a1 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-04-participant-journeys/tasks.md @@ -1,21 +1,21 @@ -# Phase 04 Tasks - -## Applicant - -- [ ] Implement stage-native timeline and requirement resolver. -- [ ] Implement strict upload gating and policy enforcement. - -## Jury - -- [ ] Implement stage-scoped assignment and evaluation surfaces. -- [ ] Implement live jury context sync and voting constraints. - -## Audience and Observer - -- [ ] Implement cohort-scoped audience ballot visibility. -- [ ] Implement observer read-only stage/track reporting alignment. - -## Realtime and Resilience - -- [ ] Implement reconnect-state convergence behavior. -- [ ] Validate realtime event consistency under cursor updates. +# Phase 04 Tasks + +## Applicant + +- [ ] Implement stage-native timeline and requirement resolver. +- [ ] Implement strict upload gating and policy enforcement. + +## Jury + +- [ ] Implement stage-scoped assignment and evaluation surfaces. +- [ ] Implement live jury context sync and voting constraints. + +## Audience and Observer + +- [ ] Implement cohort-scoped audience ballot visibility. +- [ ] Implement observer read-only stage/track reporting alignment. + +## Realtime and Resilience + +- [ ] Implement reconnect-state convergence behavior. +- [ ] Validate realtime event consistency under cursor updates. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/acceptance-gates.md index d2826cb..16d1ad5 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/acceptance-gates.md @@ -1,10 +1,10 @@ -# Phase 05 Acceptance Gates - -- [ ] G-05-1 routing mode behavior validated (`parallel`, `exclusive`, `post_main`) -- [ ] G-05-2 governance auth tests pass (`JURY_VOTE`, `AWARD_MASTER`, `ADMIN`) -- [ ] G-05-3 winner decision timeline and audit output validated - -## Required Evidence - -- integration test outputs for routing and governance -- audit timeline payload captures +# Phase 05 Acceptance Gates + +- [ ] G-05-1 routing mode behavior validated (`parallel`, `exclusive`, `post_main`) +- [ ] G-05-2 governance auth tests pass (`JURY_VOTE`, `AWARD_MASTER`, `ADMIN`) +- [ ] G-05-3 winner decision timeline and audit output validated + +## Required Evidence + +- integration test outputs for routing and governance +- audit timeline payload captures diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/award-track-and-governance-spec.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/award-track-and-governance-spec.md index 797acbc..1a37a93 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/award-track-and-governance-spec.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/award-track-and-governance-spec.md @@ -1,39 +1,39 @@ -# Award Track and Governance Specification - -## Award Track Principle -Awards share the same orchestration engine as the main competition; they are tracks, not detached side workflows. - -## Routing Modes - -- `PARALLEL`: award path runs while main path continues -- `EXCLUSIVE`: project exits main continuation path and runs award-only -- `POST_MAIN`: award route starts after configured main gate - -## Governance Modes - -- `JURY_VOTE`: assigned award jurors vote -- `AWARD_MASTER`: designated award owner decides within scope -- `ADMIN`: program/super admin decides - -## Decision Requirements - -- every winner/finalist decision emits audit entry -- manual overrides require reason code and text -- tie-break policy explicit and deterministic - -## Permission Enforcement - -- governance mode checked server-side on every decision mutation -- unauthorized attempts return `FORBIDDEN` - -## Representative Decision Payload - -```json -{ - "awardId": "award_123", - "decisionMode": "AWARD_MASTER", - "winnerProjectId": "project_789", - "reasonCode": "SPONSOR_DECISION", - "reasonText": "Award sponsor selected based on category fit" -} -``` +# Award Track and Governance Specification + +## Award Track Principle +Awards share the same orchestration engine as the main competition; they are tracks, not detached side workflows. + +## Routing Modes + +- `PARALLEL`: award path runs while main path continues +- `EXCLUSIVE`: project exits main continuation path and runs award-only +- `POST_MAIN`: award route starts after configured main gate + +## Governance Modes + +- `JURY_VOTE`: assigned award jurors vote +- `AWARD_MASTER`: designated award owner decides within scope +- `ADMIN`: program/super admin decides + +## Decision Requirements + +- every winner/finalist decision emits audit entry +- manual overrides require reason code and text +- tie-break policy explicit and deterministic + +## Permission Enforcement + +- governance mode checked server-side on every decision mutation +- unauthorized attempts return `FORBIDDEN` + +## Representative Decision Payload + +```json +{ + "awardId": "award_123", + "decisionMode": "AWARD_MASTER", + "winnerProjectId": "project_789", + "reasonCode": "SPONSOR_DECISION", + "reasonText": "Award sponsor selected based on category fit" +} +``` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/overview.md index f7f829f..bac0268 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/overview.md @@ -1,21 +1,21 @@ -# Phase 05 Overview: Special Awards and Governance - -## Objective -Implement special awards as first-class tracks with explicit routing and governance modes, including `AWARD_MASTER`. - -## In Scope - -- award track lifecycle -- routing semantics -- governance modes and permissions -- award decision and winner finalization workflows - -## Out of Scope - -- sponsor legal/contract process documentation - -## Exit Criteria - -1. Mixed award modes run without collision in a single edition. -2. Governance modes enforce correct permissions server-side. -3. Winner decision audit trails are complete and immutable. +# Phase 05 Overview: Special Awards and Governance + +## Objective +Implement special awards as first-class tracks with explicit routing and governance modes, including `AWARD_MASTER`. + +## In Scope + +- award track lifecycle +- routing semantics +- governance modes and permissions +- award decision and winner finalization workflows + +## Out of Scope + +- sponsor legal/contract process documentation + +## Exit Criteria + +1. Mixed award modes run without collision in a single edition. +2. Governance modes enforce correct permissions server-side. +3. Winner decision audit trails are complete and immutable. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/tasks.md index 02758fe..b078b00 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-05-special-awards-governance/tasks.md @@ -1,7 +1,7 @@ -# Phase 05 Tasks - -- [ ] Implement award track CRUD on canonical contracts. -- [ ] Implement award routing mode behaviors and edge-case handling. -- [ ] Implement governance mode permission checks. -- [ ] Implement winner finalization and audit timeline entries. -- [ ] Implement award-specific reporting outputs. +# Phase 05 Tasks + +- [ ] Implement award track CRUD on canonical contracts. +- [ ] Implement award routing mode behaviors and edge-case handling. +- [ ] Implement governance mode permission checks. +- [ ] Implement winner finalization and audit timeline entries. +- [ ] Implement award-specific reporting outputs. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/acceptance-gates.md index 529872b..46cfaa5 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/acceptance-gates.md @@ -1,12 +1,12 @@ -# Phase 06 Acceptance Gates - -- [ ] G-06-1 dependency refit inventory fully signed off -- [ ] G-06-2 symbol sweeps clean (no runtime legacy hits) -- [ ] G-06-3 integration consumer payload checks pass -- [ ] G-06-4 cross-role smoke tests pass - -## Required Evidence - -- module sign-off checklist with owners -- sweep outputs -- webhook/export consumer validation logs +# Phase 06 Acceptance Gates + +- [ ] G-06-1 dependency refit inventory fully signed off +- [ ] G-06-2 symbol sweeps clean (no runtime legacy hits) +- [ ] G-06-3 integration consumer payload checks pass +- [ ] G-06-4 cross-role smoke tests pass + +## Required Evidence + +- module sign-off checklist with owners +- sweep outputs +- webhook/export consumer validation logs diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/module-refit-map.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/module-refit-map.md index 06234e1..fc4a0b7 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/module-refit-map.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/module-refit-map.md @@ -1,26 +1,26 @@ -# Module Refit Map - -## Router Layer Actions - -- Rewrite orchestration endpoints to `pipeline/stage/routing` contracts. -- Refactor filtering, assignment, and live endpoints to stage-scoped semantics. -- Replace award detached flows with award-track-native contracts. - -## Service Layer Actions - -- Refactor AI filtering context to stage-native payloads. -- Refactor assignment engine to consume stage eligibility and availability. -- Refactor notification producers to new event taxonomy. -- Refactor reminders and summaries to stage references. - -## UI Layer Actions - -- Admin round pages become pipeline/stage control-plane pages. -- Jury and applicant pages consume stage timeline and stage requirement contracts. -- Public vote/live pages consume cohort and live cursor state. - -## Reporting and Export Actions - -- Replace round-grouped aggregations with stage/track aggregations. -- Update CSV/PDF payload field names to new contracts. -- Update observer dashboards and chart dimensions. +# Module Refit Map + +## Router Layer Actions + +- Rewrite orchestration endpoints to `pipeline/stage/routing` contracts. +- Refactor filtering, assignment, and live endpoints to stage-scoped semantics. +- Replace award detached flows with award-track-native contracts. + +## Service Layer Actions + +- Refactor AI filtering context to stage-native payloads. +- Refactor assignment engine to consume stage eligibility and availability. +- Refactor notification producers to new event taxonomy. +- Refactor reminders and summaries to stage references. + +## UI Layer Actions + +- Admin round pages become pipeline/stage control-plane pages. +- Jury and applicant pages consume stage timeline and stage requirement contracts. +- Public vote/live pages consume cohort and live cursor state. + +## Reporting and Export Actions + +- Replace round-grouped aggregations with stage/track aggregations. +- Update CSV/PDF payload field names to new contracts. +- Update observer dashboards and chart dimensions. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/overview.md index a1f22bd..d6402d1 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/overview.md @@ -1,21 +1,21 @@ -# Phase 06 Overview: Platform Dependency Refit - -## Objective -Refit every platform dependency from legacy round semantics to canonical stage contracts. - -## In Scope - -- module-by-module refit execution -- stale symbol removal -- integration payload consumer updates -- cross-role smoke validation - -## Out of Scope - -- new feature expansion not required for contract migration - -## Exit Criteria - -1. dependency checklist complete -2. legacy symbol sweeps clean -3. external integration consumers validated +# Phase 06 Overview: Platform Dependency Refit + +## Objective +Refit every platform dependency from legacy round semantics to canonical stage contracts. + +## In Scope + +- module-by-module refit execution +- stale symbol removal +- integration payload consumer updates +- cross-role smoke validation + +## Out of Scope + +- new feature expansion not required for contract migration + +## Exit Criteria + +1. dependency checklist complete +2. legacy symbol sweeps clean +3. external integration consumers validated diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/symbol-sweep-checklist.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/symbol-sweep-checklist.md index 4b2d28a..a704703 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/symbol-sweep-checklist.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/symbol-sweep-checklist.md @@ -1,13 +1,13 @@ -# Symbol Sweep Checklist - -All commands must return zero actionable runtime hits. - -- [ ] `rg "trpc\.round" src` -- [ ] `rg "\broundId\b" src/server src/components src/app` -- [ ] `rg "round\.settingsJson|roundType" src/server src/components src/app` -- [ ] `rg "model Round|enum RoundType" prisma/schema.prisma` - -## Exceptions - -- documentation-only references may be allowed with explicit annotation -- any code-path exception is release-blocking unless approved +# Symbol Sweep Checklist + +All commands must return zero actionable runtime hits. + +- [ ] `rg "trpc\.round" src` +- [ ] `rg "\broundId\b" src/server src/components src/app` +- [ ] `rg "round\.settingsJson|roundType" src/server src/components src/app` +- [ ] `rg "model Round|enum RoundType" prisma/schema.prisma` + +## Exceptions + +- documentation-only references may be allowed with explicit annotation +- any code-path exception is release-blocking unless approved diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/tasks.md index 5d441b4..b4b5617 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-06-platform-dependency-refit/tasks.md @@ -1,8 +1,8 @@ -# Phase 06 Tasks - -- [ ] Execute router-layer refit checklist. -- [ ] Execute service-layer refit checklist. -- [ ] Execute UI-layer refit checklist. -- [ ] Execute reporting/export integration checklist. -- [ ] Run and document legacy symbol sweeps. -- [ ] Resolve all remaining contract drift findings. +# Phase 06 Tasks + +- [ ] Execute router-layer refit checklist. +- [ ] Execute service-layer refit checklist. +- [ ] Execute UI-layer refit checklist. +- [ ] Execute reporting/export integration checklist. +- [ ] Run and document legacy symbol sweeps. +- [ ] Resolve all remaining contract drift findings. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/acceptance-gates.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/acceptance-gates.md index daa366f..aaa3604 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/acceptance-gates.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/acceptance-gates.md @@ -1,13 +1,13 @@ -# Phase 07 Acceptance Gates - -- [ ] G-07-1 U/I/E/P matrix all green -- [ ] G-07-2 performance and resilience evidence accepted -- [ ] G-07-3 release evidence report complete and signed -- [ ] G-07-4 atomic cutover executed with successful post-checks - -## Required Evidence - -- consolidated test reports -- benchmark output captures -- signed release evidence report -- runbook execution logs +# Phase 07 Acceptance Gates + +- [ ] G-07-1 U/I/E/P matrix all green +- [ ] G-07-2 performance and resilience evidence accepted +- [ ] G-07-3 release evidence report complete and signed +- [ ] G-07-4 atomic cutover executed with successful post-checks + +## Required Evidence + +- consolidated test reports +- benchmark output captures +- signed release evidence report +- runbook execution logs diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/overview.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/overview.md index cab7711..4d8177c 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/overview.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/overview.md @@ -1,21 +1,21 @@ -# Phase 07 Overview: Validation and Release - -## Objective -Execute complete validation suite, run final reset/reseed rehearsal, and perform atomic release cutover. - -## In Scope - -- full U/I/E/P test execution -- release evidence collation -- performance and resilience validation -- atomic release runbook execution - -## Out of Scope - -- post-release enhancements - -## Exit Criteria - -1. full test matrix green -2. release evidence signed -3. atomic cutover and post-cutover smoke checks complete +# Phase 07 Overview: Validation and Release + +## Objective +Execute complete validation suite, run final reset/reseed rehearsal, and perform atomic release cutover. + +## In Scope + +- full U/I/E/P test execution +- release evidence collation +- performance and resilience validation +- atomic release runbook execution + +## Out of Scope + +- post-release enhancements + +## Exit Criteria + +1. full test matrix green +2. release evidence signed +3. atomic cutover and post-cutover smoke checks complete diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/performance-and-resilience-plan.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/performance-and-resilience-plan.md index 297f74f..51e575d 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/performance-and-resilience-plan.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/performance-and-resilience-plan.md @@ -1,27 +1,27 @@ -# Performance and Resilience Plan - -## Scenarios - -### Assignment Throughput - -- workload: 1000+ eligible projects -- metrics: runtime, coverage latency, overload count - -### Filtering Throughput - -- workload: high-volume gate + AI queue -- metrics: gate throughput, queue completion, retry/error rate - -### Live Voting Burst - -- workload: peak audience voting during active cursor changes -- metrics: vote latency p50/p95/p99, event drop count, cursor propagation delay - -### Reconnect Recovery - -- workload: intentional network interruptions -- metrics: time to state convergence, stale cursor mismatch rate - -## Acceptance Policy - -Thresholds set before run and documented in release evidence. +# Performance and Resilience Plan + +## Scenarios + +### Assignment Throughput + +- workload: 1000+ eligible projects +- metrics: runtime, coverage latency, overload count + +### Filtering Throughput + +- workload: high-volume gate + AI queue +- metrics: gate throughput, queue completion, retry/error rate + +### Live Voting Burst + +- workload: peak audience voting during active cursor changes +- metrics: vote latency p50/p95/p99, event drop count, cursor propagation delay + +### Reconnect Recovery + +- workload: intentional network interruptions +- metrics: time to state convergence, stale cursor mismatch rate + +## Acceptance Policy + +Thresholds set before run and documented in release evidence. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/runbook.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/runbook.md index 96038da..ddb5ba3 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/runbook.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/runbook.md @@ -1,39 +1,39 @@ -# Release Runbook (Atomic Cutover) - -## Preconditions - -- all prior phase gates complete -- signed release checklist -- rollback owner and communication owner assigned - -## Cutover Sequence - -1. freeze non-release writes and announce maintenance window -2. execute final backup snapshot -3. deploy release candidate build -4. run reset/reseed as planned for production state model -5. run post-deploy integrity and smoke checks -6. run mandatory critical-path E2E subset -7. publish completion and monitor - -## Immediate Post-Cutover Checks - -- auth and role gating paths -- transition mutation sanity -- assignment preview/execute path -- live cursor operations -- audience vote acceptance and dedupe -- reporting endpoint correctness - -## Rollback Trigger Conditions - -- integrity check failures -- critical mutation path failure -- unacceptable error-rate spike - -## Rollback Plan (High Level) - -- restore backup snapshot -- redeploy previous stable build -- validate critical-path smoke tests -- issue incident communication and postmortem schedule +# Release Runbook (Atomic Cutover) + +## Preconditions + +- all prior phase gates complete +- signed release checklist +- rollback owner and communication owner assigned + +## Cutover Sequence + +1. freeze non-release writes and announce maintenance window +2. execute final backup snapshot +3. deploy release candidate build +4. run reset/reseed as planned for production state model +5. run post-deploy integrity and smoke checks +6. run mandatory critical-path E2E subset +7. publish completion and monitor + +## Immediate Post-Cutover Checks + +- auth and role gating paths +- transition mutation sanity +- assignment preview/execute path +- live cursor operations +- audience vote acceptance and dedupe +- reporting endpoint correctness + +## Rollback Trigger Conditions + +- integrity check failures +- critical mutation path failure +- unacceptable error-rate spike + +## Rollback Plan (High Level) + +- restore backup snapshot +- redeploy previous stable build +- validate critical-path smoke tests +- issue incident communication and postmortem schedule diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/tasks.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/tasks.md index 7573750..02c63d0 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/tasks.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/phase-07-validation-release/tasks.md @@ -1,7 +1,7 @@ -# Phase 07 Tasks - -- [ ] Execute full test matrix and store artifacts. -- [ ] Execute performance and resilience scenarios. -- [ ] Complete release evidence report. -- [ ] Run atomic cutover rehearsal and production runbook. -- [ ] Complete post-cutover smoke suite. +# Phase 07 Tasks + +- [ ] Execute full test matrix and store artifacts. +- [ ] Execute performance and resilience scenarios. +- [ ] Complete release evidence report. +- [ ] Run atomic cutover rehearsal and production runbook. +- [ ] Complete post-cutover smoke suite. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/api-contracts.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/api-contracts.md index c1f51ed..14d5bb7 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/api-contracts.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/api-contracts.md @@ -1,97 +1,97 @@ -# API Contracts - -## Contract Conventions - -- All mutations return typed `errorCode` and machine-readable `details` on failure. -- All state-changing operations emit deterministic audit events. -- All response shapes include stable identifiers for client cache invalidation. - -## Router Families - -### `pipeline` - -- `pipeline.create` -- `pipeline.update` -- `pipeline.simulate` -- `pipeline.publish` -- `pipeline.getSummary` - -### `stage` - -- `stage.create` -- `stage.updateConfig` -- `stage.list` -- `stage.transition` -- `stage.openWindow` -- `stage.closeWindow` - -### `routing` - -- `routing.preview` -- `routing.execute` -- `routing.listRules` -- `routing.upsertRule` -- `routing.toggleRule` - -### `filtering` - -- `filtering.previewBatch` -- `filtering.runStageFiltering` -- `filtering.getManualQueue` -- `filtering.resolveManualDecision` - -### `assignment` - -- `assignment.previewStageProjects` -- `assignment.assignStageProjects` -- `assignment.getCoverageReport` -- `assignment.rebalance` - -### `cohort` - -- `cohort.create` -- `cohort.assignProjects` -- `cohort.openVoting` -- `cohort.closeVoting` - -### `live` - -- `live.start` -- `live.setActiveProject` -- `live.jump` -- `live.reorder` -- `live.pause` -- `live.resume` - -### `decision` - -- `decision.override` -- `decision.auditTimeline` - -### `award` - -- `award.createTrack` -- `award.configureGovernance` -- `award.routeProjects` -- `award.finalizeWinners` - -## Error Contract - -- `BAD_REQUEST` -- `UNAUTHORIZED` -- `FORBIDDEN` -- `NOT_FOUND` -- `CONFLICT` -- `PRECONDITION_FAILED` -- `INTERNAL_SERVER_ERROR` - -## Event Contract (Representative) - -- `stage.transitioned` -- `routing.executed` -- `filtering.completed` -- `assignment.generated` -- `live.cursor.updated` -- `cohort.window.changed` -- `decision.overridden` -- `award.winner.finalized` +# API Contracts + +## Contract Conventions + +- All mutations return typed `errorCode` and machine-readable `details` on failure. +- All state-changing operations emit deterministic audit events. +- All response shapes include stable identifiers for client cache invalidation. + +## Router Families + +### `pipeline` + +- `pipeline.create` +- `pipeline.update` +- `pipeline.simulate` +- `pipeline.publish` +- `pipeline.getSummary` + +### `stage` + +- `stage.create` +- `stage.updateConfig` +- `stage.list` +- `stage.transition` +- `stage.openWindow` +- `stage.closeWindow` + +### `routing` + +- `routing.preview` +- `routing.execute` +- `routing.listRules` +- `routing.upsertRule` +- `routing.toggleRule` + +### `filtering` + +- `filtering.previewBatch` +- `filtering.runStageFiltering` +- `filtering.getManualQueue` +- `filtering.resolveManualDecision` + +### `assignment` + +- `assignment.previewStageProjects` +- `assignment.assignStageProjects` +- `assignment.getCoverageReport` +- `assignment.rebalance` + +### `cohort` + +- `cohort.create` +- `cohort.assignProjects` +- `cohort.openVoting` +- `cohort.closeVoting` + +### `live` + +- `live.start` +- `live.setActiveProject` +- `live.jump` +- `live.reorder` +- `live.pause` +- `live.resume` + +### `decision` + +- `decision.override` +- `decision.auditTimeline` + +### `award` + +- `award.createTrack` +- `award.configureGovernance` +- `award.routeProjects` +- `award.finalizeWinners` + +## Error Contract + +- `BAD_REQUEST` +- `UNAUTHORIZED` +- `FORBIDDEN` +- `NOT_FOUND` +- `CONFLICT` +- `PRECONDITION_FAILED` +- `INTERNAL_SERVER_ERROR` + +## Event Contract (Representative) + +- `stage.transitioned` +- `routing.executed` +- `filtering.completed` +- `assignment.generated` +- `live.cursor.updated` +- `cohort.window.changed` +- `decision.overridden` +- `award.winner.finalized` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/authz-matrix.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/authz-matrix.md index 00054fb..cb1c72e 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/authz-matrix.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/authz-matrix.md @@ -1,32 +1,32 @@ -# Authorization Matrix - -Roles: - -- `SUPER_ADMIN` -- `PROGRAM_ADMIN` -- `AWARD_MASTER` -- `JURY_MEMBER` -- `APPLICANT` -- `OBSERVER` -- `AUDIENCE` (public voting context) - -| Capability | Super Admin | Program Admin | Award Master | Jury | Applicant | Observer | Audience | -|---|---|---|---|---|---|---|---| -| Create/Edit Pipeline | Yes | Yes (scoped) | No | No | No | No | No | -| Publish Pipeline | Yes | Yes (scoped) | No | No | No | No | No | -| Configure Stage Rules | Yes | Yes (scoped) | No | No | No | No | No | -| Execute Manual Transition | Yes | Yes (scoped) | Limited (award scoped) | No | No | No | No | -| Override Decision | Yes | Yes (scoped) | Limited (award scoped) | No | No | No | No | -| View Audit Timeline | Yes | Yes (scoped) | Award scoped | Own actions | No | Read-only scoped | No | -| Assign Jurors | Yes | Yes (scoped) | Award scoped | No | No | No | No | -| Submit Evaluation | No | No | Optional (if configured) | Yes (assigned only) | No | No | No | -| Upload Intake Docs | No | No | No | No | Yes | No | No | -| Control Live Cursor | Yes | Yes (scoped) | No | No | No | No | No | -| Cast Audience Vote | No | No | No | No | Optional | No | Yes | - -## Policy Notes - -1. Program scoping applies to all admin operations. -2. `AWARD_MASTER` permissions are explicitly award-scoped and only active when governance mode allows it. -3. Jury endpoints always enforce assignment ownership and window constraints. -4. Audience endpoints enforce cohort membership + window state + dedupe key policy. +# Authorization Matrix + +Roles: + +- `SUPER_ADMIN` +- `PROGRAM_ADMIN` +- `AWARD_MASTER` +- `JURY_MEMBER` +- `APPLICANT` +- `OBSERVER` +- `AUDIENCE` (public voting context) + +| Capability | Super Admin | Program Admin | Award Master | Jury | Applicant | Observer | Audience | +|---|---|---|---|---|---|---|---| +| Create/Edit Pipeline | Yes | Yes (scoped) | No | No | No | No | No | +| Publish Pipeline | Yes | Yes (scoped) | No | No | No | No | No | +| Configure Stage Rules | Yes | Yes (scoped) | No | No | No | No | No | +| Execute Manual Transition | Yes | Yes (scoped) | Limited (award scoped) | No | No | No | No | +| Override Decision | Yes | Yes (scoped) | Limited (award scoped) | No | No | No | No | +| View Audit Timeline | Yes | Yes (scoped) | Award scoped | Own actions | No | Read-only scoped | No | +| Assign Jurors | Yes | Yes (scoped) | Award scoped | No | No | No | No | +| Submit Evaluation | No | No | Optional (if configured) | Yes (assigned only) | No | No | No | +| Upload Intake Docs | No | No | No | No | Yes | No | No | +| Control Live Cursor | Yes | Yes (scoped) | No | No | No | No | No | +| Cast Audience Vote | No | No | No | No | Optional | No | Yes | + +## Policy Notes + +1. Program scoping applies to all admin operations. +2. `AWARD_MASTER` permissions are explicitly award-scoped and only active when governance mode allows it. +3. Jury endpoints always enforce assignment ownership and window constraints. +4. Audience endpoints enforce cohort membership + window state + dedupe key policy. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/decision-log.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/decision-log.md index 2782f2a..00baccf 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/decision-log.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/decision-log.md @@ -1,16 +1,16 @@ -# Decision Log (Locked) - -| ID | Decision | Status | Rationale | Impacted Phases | -|---|---|---|---|---| -| MX-001 | Canonical model is `Pipeline -> Track -> Stage` | Locked | Supports multi-track orchestration cleanly | 01-07 | -| MX-002 | Project progression stored in `ProjectStageState` records | Locked | Replaces brittle single-pointer round state | 01-07 | -| MX-003 | Intake is stage-native (`INTAKE`) rather than implicit pre-round behavior | Locked | Removes hidden workflow behavior | 01-04 | -| MX-004 | Full-cutover delivery with no compatibility bridge | Locked | Faster convergence to clean runtime | 00-07 | -| MX-005 | Special awards are first-class `Track` entities | Locked | Prevents duplicated orchestration logic | 01-06 | -| MX-006 | Award routing modes are `parallel`, `exclusive`, `post_main` | Locked | Supports real sponsor policy diversity | 02,05 | -| MX-007 | Award governance modes include `JURY_VOTE`, `AWARD_MASTER`, `ADMIN` | Locked | Explicit and policy-aligned control surfaces | 05 | -| MX-008 | Live progression source of truth is admin cursor | Locked | Needed for non-linear live event control | 02,04 | -| MX-009 | Voting windows are explicit open/close operations | Locked | Schedules alone are insufficient during live operations | 02,04 | -| MX-010 | Assignment engine guarantees eligible project coverage | Locked | Operational fairness and delivery reliability | 02,04 | -| MX-011 | Overrides require reason and immutable audit entries | Locked | Governance and explainability | 02,05,07 | -| MX-012 | Release is blocked by legacy symbol sweep failures | Locked | Prevents half-migrated runtime behavior | 06,07 | +# Decision Log (Locked) + +| ID | Decision | Status | Rationale | Impacted Phases | +|---|---|---|---|---| +| MX-001 | Canonical model is `Pipeline -> Track -> Stage` | Locked | Supports multi-track orchestration cleanly | 01-07 | +| MX-002 | Project progression stored in `ProjectStageState` records | Locked | Replaces brittle single-pointer round state | 01-07 | +| MX-003 | Intake is stage-native (`INTAKE`) rather than implicit pre-round behavior | Locked | Removes hidden workflow behavior | 01-04 | +| MX-004 | Full-cutover delivery with no compatibility bridge | Locked | Faster convergence to clean runtime | 00-07 | +| MX-005 | Special awards are first-class `Track` entities | Locked | Prevents duplicated orchestration logic | 01-06 | +| MX-006 | Award routing modes are `parallel`, `exclusive`, `post_main` | Locked | Supports real sponsor policy diversity | 02,05 | +| MX-007 | Award governance modes include `JURY_VOTE`, `AWARD_MASTER`, `ADMIN` | Locked | Explicit and policy-aligned control surfaces | 05 | +| MX-008 | Live progression source of truth is admin cursor | Locked | Needed for non-linear live event control | 02,04 | +| MX-009 | Voting windows are explicit open/close operations | Locked | Schedules alone are insufficient during live operations | 02,04 | +| MX-010 | Assignment engine guarantees eligible project coverage | Locked | Operational fairness and delivery reliability | 02,04 | +| MX-011 | Overrides require reason and immutable audit entries | Locked | Governance and explainability | 02,05,07 | +| MX-012 | Release is blocked by legacy symbol sweep failures | Locked | Prevents half-migrated runtime behavior | 06,07 | diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/dependency-refit-inventory.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/dependency-refit-inventory.md index be84890..bdb9d51 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/dependency-refit-inventory.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/dependency-refit-inventory.md @@ -1,75 +1,75 @@ -# Dependency Refit Inventory - -This inventory is release-blocking. Every listed module must be validated against the new contracts. - -## Backend Routers - -- `src/server/routers/_app.ts` -- `src/server/routers/round.ts` -- `src/server/routers/filtering.ts` -- `src/server/routers/live-voting.ts` -- `src/server/routers/specialAward.ts` -- `src/server/routers/assignment.ts` -- `src/server/routers/evaluation.ts` -- `src/server/routers/file.ts` -- `src/server/routers/project.ts` -- `src/server/routers/project-pool.ts` -- `src/server/routers/application.ts` -- `src/server/routers/applicant.ts` -- `src/server/routers/export.ts` -- `src/server/routers/analytics.ts` -- `src/server/routers/program.ts` -- `src/server/routers/roundTemplate.ts` -- `src/server/routers/gracePeriod.ts` -- `src/server/routers/webhook.ts` - -## Backend Services - -- `src/server/services/smart-assignment.ts` -- `src/server/services/ai-filtering.ts` -- `src/server/services/ai-evaluation-summary.ts` -- `src/server/services/evaluation-reminders.ts` -- `src/server/services/in-app-notification.ts` -- `src/server/services/award-eligibility-job.ts` -- `src/server/services/webhook-dispatcher.ts` - -## Admin Surfaces - -- `src/app/(admin)/admin/rounds/**` -- `src/app/(admin)/admin/awards/**` -- `src/app/(admin)/admin/reports/page.tsx` -- `src/components/admin/round-pipeline.tsx` -- `src/components/admin/assign-projects-dialog.tsx` -- `src/components/admin/advance-projects-dialog.tsx` -- `src/components/admin/remove-projects-dialog.tsx` -- `src/components/admin/file-requirements-editor.tsx` -- `src/components/forms/round-type-settings.tsx` - -## Jury, Applicant, Public - -- `src/app/(jury)/jury/**` -- `src/components/jury/**` -- `src/app/(applicant)/applicant/**` -- `src/app/(public)/apply/**` -- `src/app/(public)/my-submission/**` -- `src/app/(public)/vote/**` -- `src/app/(public)/live-scores/**` - -## Reporting and Exports - -- chart and observer modules under `src/components/charts/**` and `src/components/observer/**` -- export and PDF paths under `src/components/shared/export-pdf-button.tsx`, `src/components/admin/pdf-report.tsx`, `src/server/routers/export.ts` - -## Schema and Seed Paths - -- `prisma/schema.prisma` -- relevant migrations and seed scripts under `prisma/` - -## Mandatory Legacy Sweep Queries (Release Blockers) - -1. `rg "trpc\.round" src` -2. `rg "\broundId\b" src/server src/components src/app` -3. `rg "round\.settingsJson|roundType" src/server src/components src/app` -4. `rg "model Round|enum RoundType" prisma/schema.prisma` - -Allowlist exceptions (if any) must be explicit and approved in Phase 06 gates. +# Dependency Refit Inventory + +This inventory is release-blocking. Every listed module must be validated against the new contracts. + +## Backend Routers + +- `src/server/routers/_app.ts` +- `src/server/routers/round.ts` +- `src/server/routers/filtering.ts` +- `src/server/routers/live-voting.ts` +- `src/server/routers/specialAward.ts` +- `src/server/routers/assignment.ts` +- `src/server/routers/evaluation.ts` +- `src/server/routers/file.ts` +- `src/server/routers/project.ts` +- `src/server/routers/project-pool.ts` +- `src/server/routers/application.ts` +- `src/server/routers/applicant.ts` +- `src/server/routers/export.ts` +- `src/server/routers/analytics.ts` +- `src/server/routers/program.ts` +- `src/server/routers/roundTemplate.ts` +- `src/server/routers/gracePeriod.ts` +- `src/server/routers/webhook.ts` + +## Backend Services + +- `src/server/services/smart-assignment.ts` +- `src/server/services/ai-filtering.ts` +- `src/server/services/ai-evaluation-summary.ts` +- `src/server/services/evaluation-reminders.ts` +- `src/server/services/in-app-notification.ts` +- `src/server/services/award-eligibility-job.ts` +- `src/server/services/webhook-dispatcher.ts` + +## Admin Surfaces + +- `src/app/(admin)/admin/rounds/**` +- `src/app/(admin)/admin/awards/**` +- `src/app/(admin)/admin/reports/page.tsx` +- `src/components/admin/round-pipeline.tsx` +- `src/components/admin/assign-projects-dialog.tsx` +- `src/components/admin/advance-projects-dialog.tsx` +- `src/components/admin/remove-projects-dialog.tsx` +- `src/components/admin/file-requirements-editor.tsx` +- `src/components/forms/round-type-settings.tsx` + +## Jury, Applicant, Public + +- `src/app/(jury)/jury/**` +- `src/components/jury/**` +- `src/app/(applicant)/applicant/**` +- `src/app/(public)/apply/**` +- `src/app/(public)/my-submission/**` +- `src/app/(public)/vote/**` +- `src/app/(public)/live-scores/**` + +## Reporting and Exports + +- chart and observer modules under `src/components/charts/**` and `src/components/observer/**` +- export and PDF paths under `src/components/shared/export-pdf-button.tsx`, `src/components/admin/pdf-report.tsx`, `src/server/routers/export.ts` + +## Schema and Seed Paths + +- `prisma/schema.prisma` +- relevant migrations and seed scripts under `prisma/` + +## Mandatory Legacy Sweep Queries (Release Blockers) + +1. `rg "trpc\.round" src` +2. `rg "\broundId\b" src/server src/components src/app` +3. `rg "round\.settingsJson|roundType" src/server src/components src/app` +4. `rg "model Round|enum RoundType" prisma/schema.prisma` + +Allowlist exceptions (if any) must be explicit and approved in Phase 06 gates. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/domain-model.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/domain-model.md index e71155e..304d35d 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/domain-model.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/domain-model.md @@ -1,156 +1,156 @@ -# Domain Model and Contracts - -## Canonical Enums - -- `StageType = INTAKE | FILTER | EVALUATION | SELECTION | LIVE_FINAL | RESULTS` -- `TrackKind = MAIN | AWARD | SHOWCASE` -- `RoutingMode = PARALLEL | EXCLUSIVE | POST_MAIN` -- `StageStatus = DRAFT | ACTIVE | CLOSED | ARCHIVED` -- `ProjectStageStateValue = PENDING | IN_PROGRESS | PASSED | REJECTED | ROUTED | COMPLETED | WITHDRAWN` -- `DecisionMode = JURY_VOTE | AWARD_MASTER | ADMIN` -- `OverrideReasonCode = DATA_CORRECTION | POLICY_EXCEPTION | JURY_CONFLICT | SPONSOR_DECISION | ADMIN_DISCRETION` - -## Core Entities - -### Pipeline - -- `id` -- `programId` -- `name` -- `slug` -- `status` -- `settingsJson` -- `createdAt`, `updatedAt` - -### Track - -- `id` -- `pipelineId` -- `kind` -- `specialAwardId?` -- `name` -- `slug` -- `sortOrder` -- `routingModeDefault?` -- `decisionMode?` - -### Stage - -- `id` -- `trackId` -- `stageType` -- `name` -- `slug` -- `sortOrder` -- `status` -- `configVersion` -- `configJson` -- `windowOpenAt?`, `windowCloseAt?` - -### StageTransition - -- `id` -- `fromStageId` -- `toStageId` -- `priority` -- `isDefault` -- `guardJson` -- `actionJson` - -### ProjectStageState - -- `id` -- `projectId` -- `trackId` -- `stageId` -- `state` -- `enteredAt`, `exitedAt` -- `decisionRef?` -- `outcomeJson` - -### RoutingRule - -- `id` -- `pipelineId` -- `scope` (`GLOBAL|TRACK|STAGE`) -- `predicateJson` -- `destinationTrackId` -- `destinationStageId?` -- `priority` -- `isActive` - -### Cohort and Live Runtime - -- `Cohort(id, stageId, name, votingMode, isOpen, windowOpenAt?, windowCloseAt?)` -- `CohortProject(cohortId, projectId, sortOrder)` -- `LiveProgressCursor(id, stageId, sessionId, activeProjectId?, activeOrderIndex?, updatedBy, updatedAt)` - -### Governance Entities - -- `OverrideAction(id, entityType, entityId, oldValueJson, newValueJson, reasonCode, reasonText, actedBy, actedAt)` -- `DecisionAuditLog(id, entityType, entityId, eventType, payloadJson, actorId?, createdAt)` - -## Stage Config Union Contracts - -### IntakeConfig - -- file requirements -- accepted MIME and size constraints -- deadline and late policy -- team invite policy - -### FilterConfig - -- deterministic gates -- AI rubric -- confidence thresholds -- manual queue policy -- rejection notification policy - -### EvaluationConfig - -- criteria schema -- assignment strategy -- review thresholds -- COI policy -- visibility rules - -### SelectionConfig - -- ranking source -- finalist target -- override permissions -- promotion mode (`auto_top_n`, `hybrid`, `manual`) - -### LiveFinalConfig - -- session behavior -- jury voting config -- audience voting config -- cohort policy -- reveal policy -- schedule hints (advisory) - -### ResultsConfig - -- ranking weight rules -- publication policy -- winner override rules - -## Constraint Rules - -1. Stage ordering unique per track (`trackId + sortOrder`). -2. `ProjectStageState` unique on (`projectId`, `trackId`, `stageId`). -3. `StageTransition` unique on (`fromStageId`, `toStageId`). -4. Transition destination must remain in same pipeline unless explicit routing rule applies. -5. Override records immutable after insert. -6. Decision audit log append-only. - -## Index Priorities - -1. `ProjectStageState(projectId, trackId, state)` -2. `ProjectStageState(stageId, state)` -3. `RoutingRule(pipelineId, isActive, priority)` -4. `StageTransition(fromStageId, priority)` -5. `LiveProgressCursor(stageId, sessionId)` -6. `DecisionAuditLog(entityType, entityId, createdAt)` +# Domain Model and Contracts + +## Canonical Enums + +- `StageType = INTAKE | FILTER | EVALUATION | SELECTION | LIVE_FINAL | RESULTS` +- `TrackKind = MAIN | AWARD | SHOWCASE` +- `RoutingMode = PARALLEL | EXCLUSIVE | POST_MAIN` +- `StageStatus = DRAFT | ACTIVE | CLOSED | ARCHIVED` +- `ProjectStageStateValue = PENDING | IN_PROGRESS | PASSED | REJECTED | ROUTED | COMPLETED | WITHDRAWN` +- `DecisionMode = JURY_VOTE | AWARD_MASTER | ADMIN` +- `OverrideReasonCode = DATA_CORRECTION | POLICY_EXCEPTION | JURY_CONFLICT | SPONSOR_DECISION | ADMIN_DISCRETION` + +## Core Entities + +### Pipeline + +- `id` +- `programId` +- `name` +- `slug` +- `status` +- `settingsJson` +- `createdAt`, `updatedAt` + +### Track + +- `id` +- `pipelineId` +- `kind` +- `specialAwardId?` +- `name` +- `slug` +- `sortOrder` +- `routingModeDefault?` +- `decisionMode?` + +### Stage + +- `id` +- `trackId` +- `stageType` +- `name` +- `slug` +- `sortOrder` +- `status` +- `configVersion` +- `configJson` +- `windowOpenAt?`, `windowCloseAt?` + +### StageTransition + +- `id` +- `fromStageId` +- `toStageId` +- `priority` +- `isDefault` +- `guardJson` +- `actionJson` + +### ProjectStageState + +- `id` +- `projectId` +- `trackId` +- `stageId` +- `state` +- `enteredAt`, `exitedAt` +- `decisionRef?` +- `outcomeJson` + +### RoutingRule + +- `id` +- `pipelineId` +- `scope` (`GLOBAL|TRACK|STAGE`) +- `predicateJson` +- `destinationTrackId` +- `destinationStageId?` +- `priority` +- `isActive` + +### Cohort and Live Runtime + +- `Cohort(id, stageId, name, votingMode, isOpen, windowOpenAt?, windowCloseAt?)` +- `CohortProject(cohortId, projectId, sortOrder)` +- `LiveProgressCursor(id, stageId, sessionId, activeProjectId?, activeOrderIndex?, updatedBy, updatedAt)` + +### Governance Entities + +- `OverrideAction(id, entityType, entityId, oldValueJson, newValueJson, reasonCode, reasonText, actedBy, actedAt)` +- `DecisionAuditLog(id, entityType, entityId, eventType, payloadJson, actorId?, createdAt)` + +## Stage Config Union Contracts + +### IntakeConfig + +- file requirements +- accepted MIME and size constraints +- deadline and late policy +- team invite policy + +### FilterConfig + +- deterministic gates +- AI rubric +- confidence thresholds +- manual queue policy +- rejection notification policy + +### EvaluationConfig + +- criteria schema +- assignment strategy +- review thresholds +- COI policy +- visibility rules + +### SelectionConfig + +- ranking source +- finalist target +- override permissions +- promotion mode (`auto_top_n`, `hybrid`, `manual`) + +### LiveFinalConfig + +- session behavior +- jury voting config +- audience voting config +- cohort policy +- reveal policy +- schedule hints (advisory) + +### ResultsConfig + +- ranking weight rules +- publication policy +- winner override rules + +## Constraint Rules + +1. Stage ordering unique per track (`trackId + sortOrder`). +2. `ProjectStageState` unique on (`projectId`, `trackId`, `stageId`). +3. `StageTransition` unique on (`fromStageId`, `toStageId`). +4. Transition destination must remain in same pipeline unless explicit routing rule applies. +5. Override records immutable after insert. +6. Decision audit log append-only. + +## Index Priorities + +1. `ProjectStageState(projectId, trackId, state)` +2. `ProjectStageState(stageId, state)` +3. `RoutingRule(pipelineId, isActive, priority)` +4. `StageTransition(fromStageId, priority)` +5. `LiveProgressCursor(stageId, sessionId)` +6. `DecisionAuditLog(entityType, entityId, createdAt)` diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/phase-gate-traceability.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/phase-gate-traceability.md index c074b77..96afcbe 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/phase-gate-traceability.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/phase-gate-traceability.md @@ -1,32 +1,32 @@ -# Phase Gate Traceability - -| Phase | Gate ID | Evidence Required | Test IDs / Checks | Blocking | -|---|---|---|---|---| -| 00 | G-00-1 | decision lock snapshot | decision-log review | Yes | -| 00 | G-00-2 | contract alignment review | API/type contract diff | Yes | -| 01 | G-01-1 | schema compile output | `prisma generate` | Yes | -| 01 | G-01-2 | reset/reseed output | seed logs + integrity queries | Yes | -| 01 | G-01-3 | index and FK evidence | SQL verification scripts | Yes | -| 02 | G-02-1 | transition runtime proof | U-001/U-002/I-001 | Yes | -| 02 | G-02-2 | routing determinism proof | U-003/I-003/I-004 | Yes | -| 02 | G-02-3 | filtering policy proof | U-004/U-005/E-003 | Yes | -| 02 | G-02-4 | assignment guarantees proof | U-006/U-007/I-005 | Yes | -| 02 | G-02-5 | audit/override proof | U-008/I-008 | Yes | -| 03 | G-03-1 | create/edit parity proof | parity checklist | Yes | -| 03 | G-03-2 | wizard completion proof | E-001 | Yes | -| 03 | G-03-3 | modal safety proof | targeted UI regressions | Yes | -| 04 | G-04-1 | applicant flow proof | E-002 | Yes | -| 04 | G-04-2 | jury flow proof | E-004 | Yes | -| 04 | G-04-3 | live audience proof | E-006/E-007/I-006/I-007 | Yes | -| 05 | G-05-1 | award routing proof | I-003/I-004 | Yes | -| 05 | G-05-2 | governance auth proof | U-010 + auth tests | Yes | -| 05 | G-05-3 | winner and audit proof | E-008 + I-008 | Yes | -| 06 | G-06-1 | dependency checklist complete | module sign-off evidence | Yes | -| 06 | G-06-2 | legacy sweeps clean | mandatory rg sweeps | Yes | -| 06 | G-06-3 | external consumer validation | webhook/export checks | Yes | -| 07 | G-07-1 | full test report | full matrix results | Yes | -| 07 | G-07-2 | performance report | P-001..P-004 evidence | Yes | -| 07 | G-07-3 | release evidence package | signed report template | Yes | -| 07 | G-07-4 | atomic cutover proof | release runbook logs | Yes | - -Rule: no phase closes until all gates are complete with linked artifacts. +# Phase Gate Traceability + +| Phase | Gate ID | Evidence Required | Test IDs / Checks | Blocking | +|---|---|---|---|---| +| 00 | G-00-1 | decision lock snapshot | decision-log review | Yes | +| 00 | G-00-2 | contract alignment review | API/type contract diff | Yes | +| 01 | G-01-1 | schema compile output | `prisma generate` | Yes | +| 01 | G-01-2 | reset/reseed output | seed logs + integrity queries | Yes | +| 01 | G-01-3 | index and FK evidence | SQL verification scripts | Yes | +| 02 | G-02-1 | transition runtime proof | U-001/U-002/I-001 | Yes | +| 02 | G-02-2 | routing determinism proof | U-003/I-003/I-004 | Yes | +| 02 | G-02-3 | filtering policy proof | U-004/U-005/E-003 | Yes | +| 02 | G-02-4 | assignment guarantees proof | U-006/U-007/I-005 | Yes | +| 02 | G-02-5 | audit/override proof | U-008/I-008 | Yes | +| 03 | G-03-1 | create/edit parity proof | parity checklist | Yes | +| 03 | G-03-2 | wizard completion proof | E-001 | Yes | +| 03 | G-03-3 | modal safety proof | targeted UI regressions | Yes | +| 04 | G-04-1 | applicant flow proof | E-002 | Yes | +| 04 | G-04-2 | jury flow proof | E-004 | Yes | +| 04 | G-04-3 | live audience proof | E-006/E-007/I-006/I-007 | Yes | +| 05 | G-05-1 | award routing proof | I-003/I-004 | Yes | +| 05 | G-05-2 | governance auth proof | U-010 + auth tests | Yes | +| 05 | G-05-3 | winner and audit proof | E-008 + I-008 | Yes | +| 06 | G-06-1 | dependency checklist complete | module sign-off evidence | Yes | +| 06 | G-06-2 | legacy sweeps clean | mandatory rg sweeps | Yes | +| 06 | G-06-3 | external consumer validation | webhook/export checks | Yes | +| 07 | G-07-1 | full test report | full matrix results | Yes | +| 07 | G-07-2 | performance report | P-001..P-004 evidence | Yes | +| 07 | G-07-3 | release evidence package | signed report template | Yes | +| 07 | G-07-4 | atomic cutover proof | release runbook logs | Yes | + +Rule: no phase closes until all gates are complete with linked artifacts. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/program-charter.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/program-charter.md index c123f4a..dfee0d9 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/program-charter.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/program-charter.md @@ -1,43 +1,43 @@ -# Program Charter - -## Mission -Deliver a complete, stage-native orchestration platform for MOPC that supports: - -- edition-scoped intake and progression -- deterministic filtering and assignment -- parallel and exclusive award flows -- admin-driven live finals operations -- full auditability and release-grade validation - -## Scope - -### In Scope - -- Canonical data model rebuild around pipeline/track/stage. -- Backend orchestration engine (transition, routing, filtering, assignment, live, notifications, audit). -- Admin setup and control-plane UX refit. -- Applicant, jury, observer, and audience flow refit to new contracts. -- Special award governance modes including `AWARD_MASTER`. -- Platform-wide dependency refit of schema/runtime consumers. -- Full validation and atomic release process. - -### Out of Scope - -- Legacy contract compatibility bridges. -- Cosmetic redesign or major brand refresh. -- Non-orchestration feature expansion unrelated to competition lifecycle. - -## Success Criteria - -1. Admin setup can fully configure required competition behavior in create-time flow. -2. Stage progression and routing are deterministic and explainable. -3. Award tracks run without ad hoc side logic. -4. Live event operations are resilient under reconnect and burst traffic. -5. All platform dependencies are migrated and verified before release. - -## Quality Bar - -- Typed contracts at schema, API, and UI boundaries. -- Idempotent mutation semantics for high-risk operations. -- Strong audit trails for every governance-sensitive action. -- Mobile-safe interaction quality for live audience and jury experiences. +# Program Charter + +## Mission +Deliver a complete, stage-native orchestration platform for MOPC that supports: + +- edition-scoped intake and progression +- deterministic filtering and assignment +- parallel and exclusive award flows +- admin-driven live finals operations +- full auditability and release-grade validation + +## Scope + +### In Scope + +- Canonical data model rebuild around pipeline/track/stage. +- Backend orchestration engine (transition, routing, filtering, assignment, live, notifications, audit). +- Admin setup and control-plane UX refit. +- Applicant, jury, observer, and audience flow refit to new contracts. +- Special award governance modes including `AWARD_MASTER`. +- Platform-wide dependency refit of schema/runtime consumers. +- Full validation and atomic release process. + +### Out of Scope + +- Legacy contract compatibility bridges. +- Cosmetic redesign or major brand refresh. +- Non-orchestration feature expansion unrelated to competition lifecycle. + +## Success Criteria + +1. Admin setup can fully configure required competition behavior in create-time flow. +2. Stage progression and routing are deterministic and explainable. +3. Award tracks run without ad hoc side logic. +4. Live event operations are resilient under reconnect and burst traffic. +5. All platform dependencies are migrated and verified before release. + +## Quality Bar + +- Typed contracts at schema, API, and UI boundaries. +- Idempotent mutation semantics for high-risk operations. +- Strong audit trails for every governance-sensitive action. +- Mobile-safe interaction quality for live audience and jury experiences. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/release-evidence-template.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/release-evidence-template.md index 6268ed4..cd7da81 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/release-evidence-template.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/release-evidence-template.md @@ -1,65 +1,65 @@ -# Release Evidence Report Template - -## Build Metadata - -- Date: -- Commit SHA: -- Environment: -- Operator: - -## Phase Completion Summary - -- Phase 00: -- Phase 01: -- Phase 02: -- Phase 03: -- Phase 04: -- Phase 05: -- Phase 06: -- Phase 07: - -## Test Summary - -- Unit: pass/fail counts -- Integration: pass/fail counts -- E2E: pass/fail counts -- Performance: pass/fail counts - -## Mandatory Scenario Results - -| ID | Result | Evidence Link | Notes | -|---|---|---|---| -| E-001 | | | | -| E-002 | | | | -| E-003 | | | | -| E-004 | | | | -| E-005 | | | | -| E-006 | | | | -| E-007 | | | | -| E-008 | | | | - -## Performance Results - -| ID | Result | Evidence Link | Notes | -|---|---|---|---| -| P-001 | | | | -| P-002 | | | | -| P-003 | | | | -| P-004 | | | | - -## Legacy Sweep Results - -- `trpc.round` references: -- `roundId` orchestration references: -- `round.settingsJson` behavior references: -- schema `Round` references: - -## Known Issues - -- None / list with severity and owner - -## Sign-Off - -- Engineering: -- Product: -- Operations: +# Release Evidence Report Template + +## Build Metadata + +- Date: +- Commit SHA: +- Environment: +- Operator: + +## Phase Completion Summary + +- Phase 00: +- Phase 01: +- Phase 02: +- Phase 03: +- Phase 04: +- Phase 05: +- Phase 06: +- Phase 07: + +## Test Summary + +- Unit: pass/fail counts +- Integration: pass/fail counts +- E2E: pass/fail counts +- Performance: pass/fail counts + +## Mandatory Scenario Results + +| ID | Result | Evidence Link | Notes | +|---|---|---|---| +| E-001 | | | | +| E-002 | | | | +| E-003 | | | | +| E-004 | | | | +| E-005 | | | | +| E-006 | | | | +| E-007 | | | | +| E-008 | | | | + +## Performance Results + +| ID | Result | Evidence Link | Notes | +|---|---|---|---| +| P-001 | | | | +| P-002 | | | | +| P-003 | | | | +| P-004 | | | | + +## Legacy Sweep Results + +- `trpc.round` references: +- `roundId` orchestration references: +- `round.settingsJson` behavior references: +- schema `Round` references: + +## Known Issues + +- None / list with severity and owner + +## Sign-Off + +- Engineering: +- Product: +- Operations: diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/risk-register.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/risk-register.md index 7cc6925..cb38626 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/risk-register.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/risk-register.md @@ -1,17 +1,17 @@ -# Risk Register - -| ID | Risk | Probability | Impact | Mitigation | Owner | Status | -|---|---|---|---|---|---|---| -| R-001 | Hidden legacy coupling after schema rebuild | Medium | High | Mandatory symbol sweeps + module refit gates | Eng Lead | Open | -| R-002 | Assignment coverage edge-case failures at scale | Medium | High | Hard overflow policy + P-001 load tests | Backend Lead | Open | -| R-003 | Award governance permission drift | Low | High | explicit authz tests for each decision mode | Security Lead | Open | -| R-004 | Live cursor race conditions during events | Medium | High | optimistic lock + replay-safe event handling | Realtime Lead | Open | -| R-005 | Audience vote dedupe regressions | Medium | Medium | dedupe key contract + E-007 + I-007 tests | Backend Lead | Open | -| R-006 | Migration/reseed script incompleteness | Low | High | repeatable reset/reseed rehearsals | DB Owner | Open | -| R-007 | Reporting consumers break on contract shift | Medium | Medium | phase-06 consumer validation checklist | Data Lead | Open | -| R-008 | Scope creep during dependency refit | High | Medium | strict out-of-scope policy, defer noncritical features | PM | Open | - -## Risk Handling Policy - -- `High impact` items require explicit mitigation evidence before phase close. -- `Open` high/high risks block release in Phase 07. +# Risk Register + +| ID | Risk | Probability | Impact | Mitigation | Owner | Status | +|---|---|---|---|---|---|---| +| R-001 | Hidden legacy coupling after schema rebuild | Medium | High | Mandatory symbol sweeps + module refit gates | Eng Lead | Open | +| R-002 | Assignment coverage edge-case failures at scale | Medium | High | Hard overflow policy + P-001 load tests | Backend Lead | Open | +| R-003 | Award governance permission drift | Low | High | explicit authz tests for each decision mode | Security Lead | Open | +| R-004 | Live cursor race conditions during events | Medium | High | optimistic lock + replay-safe event handling | Realtime Lead | Open | +| R-005 | Audience vote dedupe regressions | Medium | Medium | dedupe key contract + E-007 + I-007 tests | Backend Lead | Open | +| R-006 | Migration/reseed script incompleteness | Low | High | repeatable reset/reseed rehearsals | DB Owner | Open | +| R-007 | Reporting consumers break on contract shift | Medium | Medium | phase-06 consumer validation checklist | Data Lead | Open | +| R-008 | Scope creep during dependency refit | High | Medium | strict out-of-scope policy, defer noncritical features | PM | Open | + +## Risk Handling Policy + +- `High impact` items require explicit mitigation evidence before phase close. +- `Open` high/high risks block release in Phase 07. diff --git a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/test-matrix.md b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/test-matrix.md index e3e2a29..f3990e7 100644 --- a/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/test-matrix.md +++ b/docs/round-redesign-architecture-docs/mixed-round-design-implementation-docs/shared/test-matrix.md @@ -1,57 +1,57 @@ -# Test Matrix - -All IDs are mandatory unless explicitly marked non-blocking with sign-off. - -## Unit Tests - -| ID | Area | Scenario | Expected | -|---|---|---|---| -| U-001 | Transition Engine | legal transition | persisted with audit event | -| U-002 | Transition Engine | illegal transition | typed validation error | -| U-003 | Routing | multiple rule match | deterministic priority winner | -| U-004 | Filtering Gates | missing required docs | blocked before AI pass | -| U-005 | AI Banding | uncertain confidence band | routed to manual queue | -| U-006 | Assignment | COI conflict | excluded from pool | -| U-007 | Assignment | insufficient capacity | overflow flagged + coverage preserved | -| U-008 | Override | missing reason fields | mutation rejected | -| U-009 | Live Cursor | concurrent cursor update | conflict handled and retried | -| U-010 | Award Governance | `AWARD_MASTER` on unauthorized award | forbidden | - -## Integration Tests - -| ID | Area | Scenario | Expected | -|---|---|---|---| -| I-001 | Pipeline CRUD | create/update/publish | graph integrity maintained | -| I-002 | Stage Config | invalid config schema | rejected | -| I-003 | Transition + Routing | filter pass to main + award parallel | dual states created | -| I-004 | Award Exclusive Routing | exclusive route | removed from main continuation | -| I-005 | Assignment API | preview vs execute parity | same constraints and outcomes | -| I-006 | Live Runtime | jump + reorder + open/close windows | consistent cursor state | -| I-007 | Cohort Voting | closed window submit | vote rejected | -| I-008 | Decision Audit | override applied | complete immutable timeline | - -## End-to-End Tests - -| ID | Persona | Scenario | Expected | -|---|---|---|---| -| E-001 | Admin | complete setup via wizard | no hidden edit-only blockers | -| E-002 | Applicant | upload intake requirements | status and deadlines enforced | -| E-003 | Admin | run filtering stage | gates + AI + manual queue behave | -| E-004 | Jury | complete evaluation workflow | criteria and lock policy enforced | -| E-005 | Admin | selection + override | finalists and audit aligned | -| E-006 | Live Admin | advance/back/jump + reorder | jury and audience sync realtime | -| E-007 | Audience | vote by cohort on mobile | visibility and dedupe enforced | -| E-008 | Admin | finalize results | ranking and publish outputs valid | - -## Performance and Resilience - -| ID | Area | Scenario | Threshold | -|---|---|---|---| -| P-001 | Assignment | 1000+ project batch | under agreed SLA | -| P-002 | Filtering | large AI queue | deterministic retry, no dropped jobs | -| P-003 | Live Voting | peak audience burst | acceptable p95 and no data loss | -| P-004 | Reconnect | disconnect/reconnect | state converges quickly | - -## Release Block Rule - -Any failing `U-*`, `I-*`, `E-*`, or `P-*` is release-blocking unless signed waiver exists. +# Test Matrix + +All IDs are mandatory unless explicitly marked non-blocking with sign-off. + +## Unit Tests + +| ID | Area | Scenario | Expected | +|---|---|---|---| +| U-001 | Transition Engine | legal transition | persisted with audit event | +| U-002 | Transition Engine | illegal transition | typed validation error | +| U-003 | Routing | multiple rule match | deterministic priority winner | +| U-004 | Filtering Gates | missing required docs | blocked before AI pass | +| U-005 | AI Banding | uncertain confidence band | routed to manual queue | +| U-006 | Assignment | COI conflict | excluded from pool | +| U-007 | Assignment | insufficient capacity | overflow flagged + coverage preserved | +| U-008 | Override | missing reason fields | mutation rejected | +| U-009 | Live Cursor | concurrent cursor update | conflict handled and retried | +| U-010 | Award Governance | `AWARD_MASTER` on unauthorized award | forbidden | + +## Integration Tests + +| ID | Area | Scenario | Expected | +|---|---|---|---| +| I-001 | Pipeline CRUD | create/update/publish | graph integrity maintained | +| I-002 | Stage Config | invalid config schema | rejected | +| I-003 | Transition + Routing | filter pass to main + award parallel | dual states created | +| I-004 | Award Exclusive Routing | exclusive route | removed from main continuation | +| I-005 | Assignment API | preview vs execute parity | same constraints and outcomes | +| I-006 | Live Runtime | jump + reorder + open/close windows | consistent cursor state | +| I-007 | Cohort Voting | closed window submit | vote rejected | +| I-008 | Decision Audit | override applied | complete immutable timeline | + +## End-to-End Tests + +| ID | Persona | Scenario | Expected | +|---|---|---|---| +| E-001 | Admin | complete setup via wizard | no hidden edit-only blockers | +| E-002 | Applicant | upload intake requirements | status and deadlines enforced | +| E-003 | Admin | run filtering stage | gates + AI + manual queue behave | +| E-004 | Jury | complete evaluation workflow | criteria and lock policy enforced | +| E-005 | Admin | selection + override | finalists and audit aligned | +| E-006 | Live Admin | advance/back/jump + reorder | jury and audience sync realtime | +| E-007 | Audience | vote by cohort on mobile | visibility and dedupe enforced | +| E-008 | Admin | finalize results | ranking and publish outputs valid | + +## Performance and Resilience + +| ID | Area | Scenario | Threshold | +|---|---|---|---| +| P-001 | Assignment | 1000+ project batch | under agreed SLA | +| P-002 | Filtering | large AI queue | deterministic retry, no dropped jobs | +| P-003 | Live Voting | peak audience burst | acceptable p95 and no data loss | +| P-004 | Reconnect | disconnect/reconnect | state converges quickly | + +## Release Block Rule + +Any failing `U-*`, `I-*`, `E-*`, or `P-*` is release-blocking unless signed waiver exists. diff --git a/docs/round-redesign-architecture-docs/phase-0-validation/domain-model-review.md b/docs/round-redesign-architecture-docs/phase-0-validation/domain-model-review.md index 35a6da5..b998b76 100644 --- a/docs/round-redesign-architecture-docs/phase-0-validation/domain-model-review.md +++ b/docs/round-redesign-architecture-docs/phase-0-validation/domain-model-review.md @@ -1,661 +1,661 @@ -# Phase 0: Domain Model Validation - -**Date**: 2026-02-12 -**Status**: ✅ VALIDATED -**Reviewer**: Claude Sonnet 4.5 - ---- - -## Executive Summary - -This document validates the proposed canonical domain model from the redesign specification against the current MOPC Prisma schema. The validation confirms that all proposed entities, enums, and constraints are architecturally sound and can be implemented without conflicts. - -**Result**: ✅ **APPROVED** - Domain model is complete, unambiguous, and ready for implementation in Phase 1. - ---- - -## 1. Canonical Enums Validation - -### 1.1 New Enums (To be Added) - -| Enum Name | Values | Status | Notes | -|-----------|--------|--------|-------| -| **StageType** | `INTAKE`, `FILTER`, `EVALUATION`, `SELECTION`, `LIVE_FINAL`, `RESULTS` | ✅ Complete | Replaces implicit `RoundType` semantics | -| **TrackKind** | `MAIN`, `AWARD`, `SHOWCASE` | ✅ Complete | Enables first-class special awards | -| **RoutingMode** | `PARALLEL`, `EXCLUSIVE`, `POST_MAIN` | ✅ Complete | Controls award routing behavior | -| **StageStatus** | `DRAFT`, `ACTIVE`, `CLOSED`, `ARCHIVED` | ✅ Complete | Aligns with existing `RoundStatus` | -| **ProjectStageStateValue** | `PENDING`, `IN_PROGRESS`, `PASSED`, `REJECTED`, `ROUTED`, `COMPLETED`, `WITHDRAWN` | ✅ Complete | Explicit state machine for project progression | -| **DecisionMode** | `JURY_VOTE`, `AWARD_MASTER`, `ADMIN` | ✅ Complete | Award governance modes | -| **OverrideReasonCode** | `DATA_CORRECTION`, `POLICY_EXCEPTION`, `JURY_CONFLICT`, `SPONSOR_DECISION`, `ADMIN_DISCRETION` | ✅ Complete | Mandatory reason tracking for overrides | - -**Validation Notes**: -- All enum values are mutually exclusive and unambiguous -- No conflicts with existing enums -- `StageStatus` deliberately mirrors `RoundStatus` for familiarity -- `ProjectStageStateValue` provides complete state coverage - -### 1.2 Existing Enums (To be Extended or Deprecated) - -| Current Enum | Action | Rationale | -|--------------|--------|-----------| -| **RoundType** | ⚠️ DEPRECATE in Phase 6 | Replaced by `StageType` + stage config | -| **RoundStatus** | ⚠️ DEPRECATE in Phase 6 | Replaced by `StageStatus` | -| **UserRole** | ✅ EXTEND | Add `AWARD_MASTER` and `AUDIENCE` values | -| **ProjectStatus** | ⚠️ DEPRECATE in Phase 6 | Replaced by `ProjectStageState` records | - -**Action Items for Phase 1**: -- Add new enums to `prisma/schema.prisma` -- Extend `UserRole` with `AWARD_MASTER` and `AUDIENCE` -- Do NOT remove deprecated enums yet (Phase 6) - ---- - -## 2. Core Entities Validation - -### 2.1 New Core Models - -#### Pipeline -```prisma -model Pipeline { - id String @id @default(cuid()) - programId String - name String - slug String @unique - status StageStatus @default(DRAFT) - settingsJson Json? @db.JsonB - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - program Program @relation(fields: [programId], references: [id]) - tracks Track[] - routingRules RoutingRule[] -} -``` - -**Validation**: -- ✅ All fields align with domain model spec -- ✅ `programId` FK ensures proper scoping -- ✅ `slug` unique constraint enables URL-friendly references -- ✅ `settingsJson` provides extensibility -- ✅ Relationships properly defined - -#### Track -```prisma -model Track { - id String @id @default(cuid()) - pipelineId String - kind TrackKind @default(MAIN) - specialAwardId String? @unique - name String - slug String - sortOrder Int - routingModeDefault RoutingMode? - decisionMode DecisionMode? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) - specialAward SpecialAward? @relation(fields: [specialAwardId], references: [id]) - stages Stage[] - projectStageStates ProjectStageState[] - routingRules RoutingRule[] @relation("DestinationTrack") - - @@unique([pipelineId, slug]) - @@index([pipelineId, sortOrder]) -} -``` - -**Validation**: -- ✅ `kind` determines track type (MAIN vs AWARD vs SHOWCASE) -- ✅ `specialAwardId` nullable for MAIN tracks, required for AWARD tracks -- ✅ `sortOrder` enables explicit ordering -- ✅ `routingModeDefault` and `decisionMode` provide award-specific config -- ✅ Unique constraint on `(pipelineId, slug)` prevents duplicates -- ✅ Index on `(pipelineId, sortOrder)` optimizes ordering queries - -#### Stage -```prisma -model Stage { - id String @id @default(cuid()) - trackId String - stageType StageType - name String - slug String - sortOrder Int - status StageStatus @default(DRAFT) - configVersion Int @default(1) - configJson Json @db.JsonB - windowOpenAt DateTime? - windowCloseAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) - projectStageStates ProjectStageState[] - transitionsFrom StageTransition[] @relation("FromStage") - transitionsTo StageTransition[] @relation("ToStage") - cohorts Cohort[] - liveProgressCursor LiveProgressCursor? - - @@unique([trackId, slug]) - @@unique([trackId, sortOrder]) - @@index([trackId, status]) - @@index([status, windowOpenAt, windowCloseAt]) -} -``` - -**Validation**: -- ✅ `stageType` determines config schema (union type) -- ✅ `configVersion` enables config evolution -- ✅ `configJson` stores type-specific configuration -- ✅ `windowOpenAt`/`windowCloseAt` provide voting windows -- ✅ Unique constraints prevent duplicate `slug` or `sortOrder` per track -- ✅ Indexes optimize status and window queries - -#### StageTransition -```prisma -model StageTransition { - id String @id @default(cuid()) - fromStageId String - toStageId String - priority Int @default(0) - isDefault Boolean @default(false) - guardJson Json? @db.JsonB - actionJson Json? @db.JsonB - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - fromStage Stage @relation("FromStage", fields: [fromStageId], references: [id], onDelete: Cascade) - toStage Stage @relation("ToStage", fields: [toStageId], references: [id], onDelete: Cascade) - - @@unique([fromStageId, toStageId]) - @@index([fromStageId, priority]) -} -``` - -**Validation**: -- ✅ Explicit state machine definition -- ✅ `priority` enables deterministic tie-breaking -- ✅ `isDefault` marks default transition path -- ✅ `guardJson` and `actionJson` provide transition logic -- ✅ Unique constraint prevents duplicate transitions -- ✅ Index on `(fromStageId, priority)` optimizes transition lookup - -#### ProjectStageState -```prisma -model ProjectStageState { - id String @id @default(cuid()) - projectId String - trackId String - stageId String - state ProjectStageStateValue - enteredAt DateTime @default(now()) - exitedAt DateTime? - decisionRef String? - outcomeJson Json? @db.JsonB - - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@unique([projectId, trackId, stageId]) - @@index([projectId, trackId, state]) - @@index([stageId, state]) -} -``` - -**Validation**: -- ✅ Replaces single `roundId` pointer with explicit state records -- ✅ Unique constraint on `(projectId, trackId, stageId)` prevents duplicates -- ✅ `trackId` enables parallel track progression (main + awards) -- ✅ `state` provides current progression status -- ✅ `enteredAt`/`exitedAt` track state duration -- ✅ `decisionRef` links to decision audit -- ✅ `outcomeJson` stores stage-specific metadata -- ✅ Indexes optimize project queries and stage reporting - -#### RoutingRule -```prisma -model RoutingRule { - id String @id @default(cuid()) - pipelineId String - scope String // 'GLOBAL' | 'TRACK' | 'STAGE' - predicateJson Json @db.JsonB - destinationTrackId String - destinationStageId String? - priority Int @default(0) - isActive Boolean @default(true) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) - destinationTrack Track @relation("DestinationTrack", fields: [destinationTrackId], references: [id]) - - @@index([pipelineId, isActive, priority]) -} -``` - -**Validation**: -- ✅ `scope` determines rule evaluation context -- ✅ `predicateJson` contains matching logic -- ✅ `destinationTrackId` required, `destinationStageId` optional -- ✅ `priority` enables deterministic rule ordering -- ✅ `isActive` allows toggling without deletion -- ✅ Index on `(pipelineId, isActive, priority)` optimizes rule lookup - -### 2.2 Live Runtime Models - -#### Cohort -```prisma -model Cohort { - id String @id @default(cuid()) - stageId String - name String - votingMode String // 'JURY' | 'AUDIENCE' | 'HYBRID' - isOpen Boolean @default(false) - windowOpenAt DateTime? - windowCloseAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - cohortProjects CohortProject[] - - @@index([stageId, isOpen]) -} -``` - -**Validation**: -- ✅ Groups projects for live voting -- ✅ `votingMode` determines who can vote -- ✅ `isOpen` controls voting acceptance -- ✅ `windowOpenAt`/`windowCloseAt` provide time bounds -- ✅ Index on `(stageId, isOpen)` optimizes active cohort queries - -#### CohortProject -```prisma -model CohortProject { - id String @id @default(cuid()) - cohortId String - projectId String - sortOrder Int - createdAt DateTime @default(now()) - - cohort Cohort @relation(fields: [cohortId], references: [id], onDelete: Cascade) - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - - @@unique([cohortId, projectId]) - @@index([cohortId, sortOrder]) -} -``` - -**Validation**: -- ✅ Many-to-many join table for cohort membership -- ✅ `sortOrder` enables presentation ordering -- ✅ Unique constraint prevents duplicate membership -- ✅ Index on `(cohortId, sortOrder)` optimizes ordering queries - -#### LiveProgressCursor -```prisma -model LiveProgressCursor { - id String @id @default(cuid()) - stageId String @unique - sessionId String - activeProjectId String? - activeOrderIndex Int? - updatedBy String - updatedAt DateTime @updatedAt - - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@index([stageId, sessionId]) -} -``` - -**Validation**: -- ✅ Admin cursor as source of truth for live events -- ✅ `stageId` unique ensures one cursor per stage -- ✅ `sessionId` tracks live session -- ✅ `activeProjectId` and `activeOrderIndex` track current position -- ✅ `updatedBy` tracks admin actor -- ✅ Index on `(stageId, sessionId)` optimizes live queries - -### 2.3 Governance Models - -#### OverrideAction -```prisma -model OverrideAction { - id String @id @default(cuid()) - entityType String // 'PROJECT' | 'STAGE' | 'COHORT' | 'AWARD' - entityId String - oldValueJson Json? @db.JsonB - newValueJson Json @db.JsonB - reasonCode OverrideReasonCode - reasonText String - actedBy String - actedAt DateTime @default(now()) - - @@index([entityType, entityId, actedAt]) - @@index([actedBy, actedAt]) -} -``` - -**Validation**: -- ✅ Immutable override audit trail -- ✅ `reasonCode` enum ensures valid reasons -- ✅ `reasonText` captures human explanation -- ✅ `actedBy` tracks actor -- ✅ Indexes optimize entity and actor queries - -#### DecisionAuditLog -```prisma -model DecisionAuditLog { - id String @id @default(cuid()) - entityType String // 'STAGE' | 'ROUTING' | 'FILTERING' | 'ASSIGNMENT' | 'LIVE' | 'AWARD' - entityId String - eventType String // 'stage.transitioned' | 'routing.executed' | etc. - payloadJson Json @db.JsonB - actorId String? - createdAt DateTime @default(now()) - - @@index([entityType, entityId, createdAt]) - @@index([eventType, createdAt]) -} -``` - -**Validation**: -- ✅ Append-only audit log for all decisions -- ✅ `eventType` aligns with event taxonomy -- ✅ `payloadJson` captures full event context -- ✅ `actorId` nullable for system events -- ✅ Indexes optimize entity timeline and event queries - ---- - -## 3. Constraint Rules Validation - -### 3.1 Unique Constraints - -| Model | Constraint | Status | Purpose | -|-------|-----------|--------|---------| -| Pipeline | `slug` | ✅ Valid | URL-friendly unique identifier | -| Track | `(pipelineId, slug)` | ✅ Valid | Prevent duplicate slugs per pipeline | -| Track | `(pipelineId, sortOrder)` | ❌ MISSING | **Correction needed**: Add unique constraint per domain model spec | -| Stage | `(trackId, slug)` | ✅ Valid | Prevent duplicate slugs per track | -| Stage | `(trackId, sortOrder)` | ✅ Valid | Prevent duplicate sort orders per track | -| StageTransition | `(fromStageId, toStageId)` | ✅ Valid | Prevent duplicate transitions | -| ProjectStageState | `(projectId, trackId, stageId)` | ✅ Valid | One state record per project/track/stage combo | -| CohortProject | `(cohortId, projectId)` | ✅ Valid | Prevent duplicate cohort membership | - -**Action Items for Phase 1**: -- ✅ Most constraints align with spec -- ⚠️ **Add**: Unique constraint on `Track(pipelineId, sortOrder)` per domain model requirement - -### 3.2 Foreign Key Constraints - -All FK relationships validated: -- ✅ Cascade deletes properly configured -- ✅ Referential integrity preserved -- ✅ Nullable FKs appropriately marked - -### 3.3 Index Priorities - -All required indexes from domain model spec are present: -1. ✅ `ProjectStageState(projectId, trackId, state)` -2. ✅ `ProjectStageState(stageId, state)` -3. ✅ `RoutingRule(pipelineId, isActive, priority)` -4. ✅ `StageTransition(fromStageId, priority)` -5. ✅ `LiveProgressCursor(stageId, sessionId)` -6. ✅ `DecisionAuditLog(entityType, entityId, createdAt)` - -**Additional indexes added**: -- `Track(pipelineId, sortOrder)` - optimizes track ordering -- `Stage(trackId, status)` - optimizes status filtering -- `Stage(status, windowOpenAt, windowCloseAt)` - optimizes window queries -- `Cohort(stageId, isOpen)` - optimizes active cohort queries -- `CohortProject(cohortId, sortOrder)` - optimizes presentation ordering - ---- - -## 4. JSON Field Contracts Validation - -### 4.1 Pipeline.settingsJson -**Purpose**: Pipeline-level configuration -**Expected Schema**: -```typescript -{ - notificationDefaults?: { - enabled: boolean; - channels: string[]; - }; - aiConfig?: { - filteringEnabled: boolean; - assignmentEnabled: boolean; - }; - // ... extensible -} -``` -**Status**: ✅ Flexible, extensible design - -### 4.2 Stage.configJson -**Purpose**: Stage-type-specific configuration (union type) -**Expected Schemas** (by `stageType`): - -**INTAKE**: -```typescript -{ - fileRequirements: FileRequirement[]; - deadlinePolicy: 'strict' | 'flexible'; - lateSubmissionAllowed: boolean; - teamInvitePolicy: {...}; -} -``` - -**FILTER**: -```typescript -{ - deterministicGates: Gate[]; - aiRubric: {...}; - confidenceThresholds: {...}; - manualQueuePolicy: {...}; -} -``` - -**EVALUATION**: -```typescript -{ - criteria: Criterion[]; - assignmentStrategy: {...}; - reviewThresholds: {...}; - coiPolicy: {...}; -} -``` - -**SELECTION**: -```typescript -{ - rankingSource: 'scores' | 'votes' | 'hybrid'; - finalistTarget: number; - promotionMode: 'auto_top_n' | 'hybrid' | 'manual'; - overridePermissions: {...}; -} -``` - -**LIVE_FINAL**: -```typescript -{ - sessionBehavior: {...}; - juryVotingConfig: {...}; - audienceVotingConfig: {...}; - cohortPolicy: {...}; - revealPolicy: {...}; -} -``` - -**RESULTS**: -```typescript -{ - rankingWeightRules: {...}; - publicationPolicy: {...}; - winnerOverrideRules: {...}; -} -``` - -**Status**: ✅ Complete coverage, all stage types defined - -### 4.3 ProjectStageState.outcomeJson -**Purpose**: Stage-specific outcome metadata -**Expected Schema**: -```typescript -{ - scores?: Record; - decision?: string; - feedback?: string; - aiConfidence?: number; - manualReview?: boolean; - // ... extensible per stage type -} -``` -**Status**: ✅ Flexible, extensible design - -### 4.4 StageTransition.guardJson / actionJson -**Purpose**: Transition logic and side effects -**Expected Schemas**: - -**guardJson**: -```typescript -{ - conditions: Array<{ - field: string; - operator: 'eq' | 'gt' | 'lt' | 'in' | 'exists'; - value: any; - }>; - requireAll: boolean; -} -``` - -**actionJson**: -```typescript -{ - actions: Array<{ - type: 'notify' | 'update_field' | 'emit_event'; - config: any; - }>; -} -``` -**Status**: ✅ Provides transition programmability - -### 4.5 RoutingRule.predicateJson -**Purpose**: Rule matching logic -**Expected Schema**: -```typescript -{ - conditions: Array<{ - field: string; // e.g., 'project.category', 'project.tags' - operator: 'eq' | 'in' | 'contains' | 'matches'; - value: any; - }>; - matchAll: boolean; -} -``` -**Status**: ✅ Deterministic rule matching - ---- - -## 5. Data Initialization Rules Validation - -### 5.1 Seed Requirements - -**From Phase 1 spec**: -- ✅ Every seeded project must start with one intake-stage state -- ✅ Seed must include main track plus at least two award tracks with different routing modes -- ✅ Seed must include representative roles: admins, jury, applicants, observer, audience contexts - -**Validation**: -- Seed requirements are clear and achievable -- Will be implemented in `prisma/seed.ts` during Phase 1 - -### 5.2 Integrity Checks - -**Required checks** (from schema-spec.md): -- ✅ No orphan states -- ✅ No invalid transition targets across pipelines -- ✅ No duplicate active state rows for same `(project, track, stage)` - -**Validation**: -- Integrity check SQL will be created in Phase 1 -- Constraints and indexes prevent most integrity violations - ---- - -## 6. Compatibility with Existing Models - -### 6.1 Models That Remain Unchanged -- ✅ `User` - No changes needed -- ✅ `Program` - Gains `Pipeline` relation -- ✅ `Project` - Gains `ProjectStageState` relation, deprecates `roundId` -- ✅ `SpecialAward` - Gains `Track` relation -- ✅ `Evaluation` - No changes to core model -- ✅ `Assignment` - May need `stageId` addition (Phase 2) - -### 6.2 Models to be Deprecated (Phase 6) -- ⚠️ `Round` - Replaced by `Pipeline` + `Track` + `Stage` -- ⚠️ Round-specific relations will be refactored - -### 6.3 Integration Points -- ✅ `User.role` extends to include `AWARD_MASTER` and `AUDIENCE` -- ✅ `Program` gains `pipelines` relation -- ✅ `Project` gains `projectStageStates` relation -- ✅ `SpecialAward` gains `track` relation - ---- - -## 7. Validation Summary - -### ✅ Approved Elements -1. All 7 new canonical enums are complete and unambiguous -2. All 12 new core models align with domain model spec -3. All unique constraints match spec requirements (1 minor correction needed) -4. All foreign key relationships properly defined -5. All required indexes present (plus beneficial additions) -6. JSON field contracts provide flexibility and extensibility -7. Compatibility with existing models maintained - -### ⚠️ Corrections Needed for Phase 1 -1. **Track**: Add unique constraint on `(pipelineId, sortOrder)` to match spec -2. **UserRole**: Extend enum to add `AWARD_MASTER` and `AUDIENCE` values - -### 📋 Action Items for Phase 1 -- [ ] Implement all 7 new enums in `prisma/schema.prisma` -- [ ] Implement all 12 new models with proper constraints -- [ ] Extend `UserRole` enum with new values -- [ ] Add unique constraint on `Track(pipelineId, sortOrder)` -- [ ] Verify all indexes are created -- [ ] Create seed data with required representative examples -- [ ] Implement integrity check SQL queries - ---- - -## 8. Conclusion - -**Status**: ✅ **DOMAIN MODEL VALIDATED AND APPROVED** - -The proposed canonical domain model is architecturally sound, complete, and ready for implementation. All entities, enums, and constraints have been validated against both the design specification and the current MOPC codebase. - -**Key Strengths**: -- Explicit state machine eliminates implicit round progression logic -- First-class award tracks enable flexible routing and governance -- JSON config fields provide extensibility without schema migrations -- Comprehensive audit trail ensures governance and explainability -- Index strategy optimizes common query patterns - -**Minor Corrections**: -- 1 unique constraint addition needed (`Track.sortOrder`) -- 2 enum values to be added to existing `UserRole` - -**Next Step**: Proceed to Phase 1 schema implementation with confidence that the domain model is solid. - ---- - -**Signed**: Claude Sonnet 4.5 -**Date**: 2026-02-12 +# Phase 0: Domain Model Validation + +**Date**: 2026-02-12 +**Status**: ✅ VALIDATED +**Reviewer**: Claude Sonnet 4.5 + +--- + +## Executive Summary + +This document validates the proposed canonical domain model from the redesign specification against the current MOPC Prisma schema. The validation confirms that all proposed entities, enums, and constraints are architecturally sound and can be implemented without conflicts. + +**Result**: ✅ **APPROVED** - Domain model is complete, unambiguous, and ready for implementation in Phase 1. + +--- + +## 1. Canonical Enums Validation + +### 1.1 New Enums (To be Added) + +| Enum Name | Values | Status | Notes | +|-----------|--------|--------|-------| +| **StageType** | `INTAKE`, `FILTER`, `EVALUATION`, `SELECTION`, `LIVE_FINAL`, `RESULTS` | ✅ Complete | Replaces implicit `RoundType` semantics | +| **TrackKind** | `MAIN`, `AWARD`, `SHOWCASE` | ✅ Complete | Enables first-class special awards | +| **RoutingMode** | `PARALLEL`, `EXCLUSIVE`, `POST_MAIN` | ✅ Complete | Controls award routing behavior | +| **StageStatus** | `DRAFT`, `ACTIVE`, `CLOSED`, `ARCHIVED` | ✅ Complete | Aligns with existing `RoundStatus` | +| **ProjectStageStateValue** | `PENDING`, `IN_PROGRESS`, `PASSED`, `REJECTED`, `ROUTED`, `COMPLETED`, `WITHDRAWN` | ✅ Complete | Explicit state machine for project progression | +| **DecisionMode** | `JURY_VOTE`, `AWARD_MASTER`, `ADMIN` | ✅ Complete | Award governance modes | +| **OverrideReasonCode** | `DATA_CORRECTION`, `POLICY_EXCEPTION`, `JURY_CONFLICT`, `SPONSOR_DECISION`, `ADMIN_DISCRETION` | ✅ Complete | Mandatory reason tracking for overrides | + +**Validation Notes**: +- All enum values are mutually exclusive and unambiguous +- No conflicts with existing enums +- `StageStatus` deliberately mirrors `RoundStatus` for familiarity +- `ProjectStageStateValue` provides complete state coverage + +### 1.2 Existing Enums (To be Extended or Deprecated) + +| Current Enum | Action | Rationale | +|--------------|--------|-----------| +| **RoundType** | ⚠️ DEPRECATE in Phase 6 | Replaced by `StageType` + stage config | +| **RoundStatus** | ⚠️ DEPRECATE in Phase 6 | Replaced by `StageStatus` | +| **UserRole** | ✅ EXTEND | Add `AWARD_MASTER` and `AUDIENCE` values | +| **ProjectStatus** | ⚠️ DEPRECATE in Phase 6 | Replaced by `ProjectStageState` records | + +**Action Items for Phase 1**: +- Add new enums to `prisma/schema.prisma` +- Extend `UserRole` with `AWARD_MASTER` and `AUDIENCE` +- Do NOT remove deprecated enums yet (Phase 6) + +--- + +## 2. Core Entities Validation + +### 2.1 New Core Models + +#### Pipeline +```prisma +model Pipeline { + id String @id @default(cuid()) + programId String + name String + slug String @unique + status StageStatus @default(DRAFT) + settingsJson Json? @db.JsonB + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + program Program @relation(fields: [programId], references: [id]) + tracks Track[] + routingRules RoutingRule[] +} +``` + +**Validation**: +- ✅ All fields align with domain model spec +- ✅ `programId` FK ensures proper scoping +- ✅ `slug` unique constraint enables URL-friendly references +- ✅ `settingsJson` provides extensibility +- ✅ Relationships properly defined + +#### Track +```prisma +model Track { + id String @id @default(cuid()) + pipelineId String + kind TrackKind @default(MAIN) + specialAwardId String? @unique + name String + slug String + sortOrder Int + routingModeDefault RoutingMode? + decisionMode DecisionMode? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) + specialAward SpecialAward? @relation(fields: [specialAwardId], references: [id]) + stages Stage[] + projectStageStates ProjectStageState[] + routingRules RoutingRule[] @relation("DestinationTrack") + + @@unique([pipelineId, slug]) + @@index([pipelineId, sortOrder]) +} +``` + +**Validation**: +- ✅ `kind` determines track type (MAIN vs AWARD vs SHOWCASE) +- ✅ `specialAwardId` nullable for MAIN tracks, required for AWARD tracks +- ✅ `sortOrder` enables explicit ordering +- ✅ `routingModeDefault` and `decisionMode` provide award-specific config +- ✅ Unique constraint on `(pipelineId, slug)` prevents duplicates +- ✅ Index on `(pipelineId, sortOrder)` optimizes ordering queries + +#### Stage +```prisma +model Stage { + id String @id @default(cuid()) + trackId String + stageType StageType + name String + slug String + sortOrder Int + status StageStatus @default(DRAFT) + configVersion Int @default(1) + configJson Json @db.JsonB + windowOpenAt DateTime? + windowCloseAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) + projectStageStates ProjectStageState[] + transitionsFrom StageTransition[] @relation("FromStage") + transitionsTo StageTransition[] @relation("ToStage") + cohorts Cohort[] + liveProgressCursor LiveProgressCursor? + + @@unique([trackId, slug]) + @@unique([trackId, sortOrder]) + @@index([trackId, status]) + @@index([status, windowOpenAt, windowCloseAt]) +} +``` + +**Validation**: +- ✅ `stageType` determines config schema (union type) +- ✅ `configVersion` enables config evolution +- ✅ `configJson` stores type-specific configuration +- ✅ `windowOpenAt`/`windowCloseAt` provide voting windows +- ✅ Unique constraints prevent duplicate `slug` or `sortOrder` per track +- ✅ Indexes optimize status and window queries + +#### StageTransition +```prisma +model StageTransition { + id String @id @default(cuid()) + fromStageId String + toStageId String + priority Int @default(0) + isDefault Boolean @default(false) + guardJson Json? @db.JsonB + actionJson Json? @db.JsonB + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + fromStage Stage @relation("FromStage", fields: [fromStageId], references: [id], onDelete: Cascade) + toStage Stage @relation("ToStage", fields: [toStageId], references: [id], onDelete: Cascade) + + @@unique([fromStageId, toStageId]) + @@index([fromStageId, priority]) +} +``` + +**Validation**: +- ✅ Explicit state machine definition +- ✅ `priority` enables deterministic tie-breaking +- ✅ `isDefault` marks default transition path +- ✅ `guardJson` and `actionJson` provide transition logic +- ✅ Unique constraint prevents duplicate transitions +- ✅ Index on `(fromStageId, priority)` optimizes transition lookup + +#### ProjectStageState +```prisma +model ProjectStageState { + id String @id @default(cuid()) + projectId String + trackId String + stageId String + state ProjectStageStateValue + enteredAt DateTime @default(now()) + exitedAt DateTime? + decisionRef String? + outcomeJson Json? @db.JsonB + + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@unique([projectId, trackId, stageId]) + @@index([projectId, trackId, state]) + @@index([stageId, state]) +} +``` + +**Validation**: +- ✅ Replaces single `roundId` pointer with explicit state records +- ✅ Unique constraint on `(projectId, trackId, stageId)` prevents duplicates +- ✅ `trackId` enables parallel track progression (main + awards) +- ✅ `state` provides current progression status +- ✅ `enteredAt`/`exitedAt` track state duration +- ✅ `decisionRef` links to decision audit +- ✅ `outcomeJson` stores stage-specific metadata +- ✅ Indexes optimize project queries and stage reporting + +#### RoutingRule +```prisma +model RoutingRule { + id String @id @default(cuid()) + pipelineId String + scope String // 'GLOBAL' | 'TRACK' | 'STAGE' + predicateJson Json @db.JsonB + destinationTrackId String + destinationStageId String? + priority Int @default(0) + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) + destinationTrack Track @relation("DestinationTrack", fields: [destinationTrackId], references: [id]) + + @@index([pipelineId, isActive, priority]) +} +``` + +**Validation**: +- ✅ `scope` determines rule evaluation context +- ✅ `predicateJson` contains matching logic +- ✅ `destinationTrackId` required, `destinationStageId` optional +- ✅ `priority` enables deterministic rule ordering +- ✅ `isActive` allows toggling without deletion +- ✅ Index on `(pipelineId, isActive, priority)` optimizes rule lookup + +### 2.2 Live Runtime Models + +#### Cohort +```prisma +model Cohort { + id String @id @default(cuid()) + stageId String + name String + votingMode String // 'JURY' | 'AUDIENCE' | 'HYBRID' + isOpen Boolean @default(false) + windowOpenAt DateTime? + windowCloseAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + cohortProjects CohortProject[] + + @@index([stageId, isOpen]) +} +``` + +**Validation**: +- ✅ Groups projects for live voting +- ✅ `votingMode` determines who can vote +- ✅ `isOpen` controls voting acceptance +- ✅ `windowOpenAt`/`windowCloseAt` provide time bounds +- ✅ Index on `(stageId, isOpen)` optimizes active cohort queries + +#### CohortProject +```prisma +model CohortProject { + id String @id @default(cuid()) + cohortId String + projectId String + sortOrder Int + createdAt DateTime @default(now()) + + cohort Cohort @relation(fields: [cohortId], references: [id], onDelete: Cascade) + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + + @@unique([cohortId, projectId]) + @@index([cohortId, sortOrder]) +} +``` + +**Validation**: +- ✅ Many-to-many join table for cohort membership +- ✅ `sortOrder` enables presentation ordering +- ✅ Unique constraint prevents duplicate membership +- ✅ Index on `(cohortId, sortOrder)` optimizes ordering queries + +#### LiveProgressCursor +```prisma +model LiveProgressCursor { + id String @id @default(cuid()) + stageId String @unique + sessionId String + activeProjectId String? + activeOrderIndex Int? + updatedBy String + updatedAt DateTime @updatedAt + + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@index([stageId, sessionId]) +} +``` + +**Validation**: +- ✅ Admin cursor as source of truth for live events +- ✅ `stageId` unique ensures one cursor per stage +- ✅ `sessionId` tracks live session +- ✅ `activeProjectId` and `activeOrderIndex` track current position +- ✅ `updatedBy` tracks admin actor +- ✅ Index on `(stageId, sessionId)` optimizes live queries + +### 2.3 Governance Models + +#### OverrideAction +```prisma +model OverrideAction { + id String @id @default(cuid()) + entityType String // 'PROJECT' | 'STAGE' | 'COHORT' | 'AWARD' + entityId String + oldValueJson Json? @db.JsonB + newValueJson Json @db.JsonB + reasonCode OverrideReasonCode + reasonText String + actedBy String + actedAt DateTime @default(now()) + + @@index([entityType, entityId, actedAt]) + @@index([actedBy, actedAt]) +} +``` + +**Validation**: +- ✅ Immutable override audit trail +- ✅ `reasonCode` enum ensures valid reasons +- ✅ `reasonText` captures human explanation +- ✅ `actedBy` tracks actor +- ✅ Indexes optimize entity and actor queries + +#### DecisionAuditLog +```prisma +model DecisionAuditLog { + id String @id @default(cuid()) + entityType String // 'STAGE' | 'ROUTING' | 'FILTERING' | 'ASSIGNMENT' | 'LIVE' | 'AWARD' + entityId String + eventType String // 'stage.transitioned' | 'routing.executed' | etc. + payloadJson Json @db.JsonB + actorId String? + createdAt DateTime @default(now()) + + @@index([entityType, entityId, createdAt]) + @@index([eventType, createdAt]) +} +``` + +**Validation**: +- ✅ Append-only audit log for all decisions +- ✅ `eventType` aligns with event taxonomy +- ✅ `payloadJson` captures full event context +- ✅ `actorId` nullable for system events +- ✅ Indexes optimize entity timeline and event queries + +--- + +## 3. Constraint Rules Validation + +### 3.1 Unique Constraints + +| Model | Constraint | Status | Purpose | +|-------|-----------|--------|---------| +| Pipeline | `slug` | ✅ Valid | URL-friendly unique identifier | +| Track | `(pipelineId, slug)` | ✅ Valid | Prevent duplicate slugs per pipeline | +| Track | `(pipelineId, sortOrder)` | ❌ MISSING | **Correction needed**: Add unique constraint per domain model spec | +| Stage | `(trackId, slug)` | ✅ Valid | Prevent duplicate slugs per track | +| Stage | `(trackId, sortOrder)` | ✅ Valid | Prevent duplicate sort orders per track | +| StageTransition | `(fromStageId, toStageId)` | ✅ Valid | Prevent duplicate transitions | +| ProjectStageState | `(projectId, trackId, stageId)` | ✅ Valid | One state record per project/track/stage combo | +| CohortProject | `(cohortId, projectId)` | ✅ Valid | Prevent duplicate cohort membership | + +**Action Items for Phase 1**: +- ✅ Most constraints align with spec +- ⚠️ **Add**: Unique constraint on `Track(pipelineId, sortOrder)` per domain model requirement + +### 3.2 Foreign Key Constraints + +All FK relationships validated: +- ✅ Cascade deletes properly configured +- ✅ Referential integrity preserved +- ✅ Nullable FKs appropriately marked + +### 3.3 Index Priorities + +All required indexes from domain model spec are present: +1. ✅ `ProjectStageState(projectId, trackId, state)` +2. ✅ `ProjectStageState(stageId, state)` +3. ✅ `RoutingRule(pipelineId, isActive, priority)` +4. ✅ `StageTransition(fromStageId, priority)` +5. ✅ `LiveProgressCursor(stageId, sessionId)` +6. ✅ `DecisionAuditLog(entityType, entityId, createdAt)` + +**Additional indexes added**: +- `Track(pipelineId, sortOrder)` - optimizes track ordering +- `Stage(trackId, status)` - optimizes status filtering +- `Stage(status, windowOpenAt, windowCloseAt)` - optimizes window queries +- `Cohort(stageId, isOpen)` - optimizes active cohort queries +- `CohortProject(cohortId, sortOrder)` - optimizes presentation ordering + +--- + +## 4. JSON Field Contracts Validation + +### 4.1 Pipeline.settingsJson +**Purpose**: Pipeline-level configuration +**Expected Schema**: +```typescript +{ + notificationDefaults?: { + enabled: boolean; + channels: string[]; + }; + aiConfig?: { + filteringEnabled: boolean; + assignmentEnabled: boolean; + }; + // ... extensible +} +``` +**Status**: ✅ Flexible, extensible design + +### 4.2 Stage.configJson +**Purpose**: Stage-type-specific configuration (union type) +**Expected Schemas** (by `stageType`): + +**INTAKE**: +```typescript +{ + fileRequirements: FileRequirement[]; + deadlinePolicy: 'strict' | 'flexible'; + lateSubmissionAllowed: boolean; + teamInvitePolicy: {...}; +} +``` + +**FILTER**: +```typescript +{ + deterministicGates: Gate[]; + aiRubric: {...}; + confidenceThresholds: {...}; + manualQueuePolicy: {...}; +} +``` + +**EVALUATION**: +```typescript +{ + criteria: Criterion[]; + assignmentStrategy: {...}; + reviewThresholds: {...}; + coiPolicy: {...}; +} +``` + +**SELECTION**: +```typescript +{ + rankingSource: 'scores' | 'votes' | 'hybrid'; + finalistTarget: number; + promotionMode: 'auto_top_n' | 'hybrid' | 'manual'; + overridePermissions: {...}; +} +``` + +**LIVE_FINAL**: +```typescript +{ + sessionBehavior: {...}; + juryVotingConfig: {...}; + audienceVotingConfig: {...}; + cohortPolicy: {...}; + revealPolicy: {...}; +} +``` + +**RESULTS**: +```typescript +{ + rankingWeightRules: {...}; + publicationPolicy: {...}; + winnerOverrideRules: {...}; +} +``` + +**Status**: ✅ Complete coverage, all stage types defined + +### 4.3 ProjectStageState.outcomeJson +**Purpose**: Stage-specific outcome metadata +**Expected Schema**: +```typescript +{ + scores?: Record; + decision?: string; + feedback?: string; + aiConfidence?: number; + manualReview?: boolean; + // ... extensible per stage type +} +``` +**Status**: ✅ Flexible, extensible design + +### 4.4 StageTransition.guardJson / actionJson +**Purpose**: Transition logic and side effects +**Expected Schemas**: + +**guardJson**: +```typescript +{ + conditions: Array<{ + field: string; + operator: 'eq' | 'gt' | 'lt' | 'in' | 'exists'; + value: any; + }>; + requireAll: boolean; +} +``` + +**actionJson**: +```typescript +{ + actions: Array<{ + type: 'notify' | 'update_field' | 'emit_event'; + config: any; + }>; +} +``` +**Status**: ✅ Provides transition programmability + +### 4.5 RoutingRule.predicateJson +**Purpose**: Rule matching logic +**Expected Schema**: +```typescript +{ + conditions: Array<{ + field: string; // e.g., 'project.category', 'project.tags' + operator: 'eq' | 'in' | 'contains' | 'matches'; + value: any; + }>; + matchAll: boolean; +} +``` +**Status**: ✅ Deterministic rule matching + +--- + +## 5. Data Initialization Rules Validation + +### 5.1 Seed Requirements + +**From Phase 1 spec**: +- ✅ Every seeded project must start with one intake-stage state +- ✅ Seed must include main track plus at least two award tracks with different routing modes +- ✅ Seed must include representative roles: admins, jury, applicants, observer, audience contexts + +**Validation**: +- Seed requirements are clear and achievable +- Will be implemented in `prisma/seed.ts` during Phase 1 + +### 5.2 Integrity Checks + +**Required checks** (from schema-spec.md): +- ✅ No orphan states +- ✅ No invalid transition targets across pipelines +- ✅ No duplicate active state rows for same `(project, track, stage)` + +**Validation**: +- Integrity check SQL will be created in Phase 1 +- Constraints and indexes prevent most integrity violations + +--- + +## 6. Compatibility with Existing Models + +### 6.1 Models That Remain Unchanged +- ✅ `User` - No changes needed +- ✅ `Program` - Gains `Pipeline` relation +- ✅ `Project` - Gains `ProjectStageState` relation, deprecates `roundId` +- ✅ `SpecialAward` - Gains `Track` relation +- ✅ `Evaluation` - No changes to core model +- ✅ `Assignment` - May need `stageId` addition (Phase 2) + +### 6.2 Models to be Deprecated (Phase 6) +- ⚠️ `Round` - Replaced by `Pipeline` + `Track` + `Stage` +- ⚠️ Round-specific relations will be refactored + +### 6.3 Integration Points +- ✅ `User.role` extends to include `AWARD_MASTER` and `AUDIENCE` +- ✅ `Program` gains `pipelines` relation +- ✅ `Project` gains `projectStageStates` relation +- ✅ `SpecialAward` gains `track` relation + +--- + +## 7. Validation Summary + +### ✅ Approved Elements +1. All 7 new canonical enums are complete and unambiguous +2. All 12 new core models align with domain model spec +3. All unique constraints match spec requirements (1 minor correction needed) +4. All foreign key relationships properly defined +5. All required indexes present (plus beneficial additions) +6. JSON field contracts provide flexibility and extensibility +7. Compatibility with existing models maintained + +### ⚠️ Corrections Needed for Phase 1 +1. **Track**: Add unique constraint on `(pipelineId, sortOrder)` to match spec +2. **UserRole**: Extend enum to add `AWARD_MASTER` and `AUDIENCE` values + +### 📋 Action Items for Phase 1 +- [ ] Implement all 7 new enums in `prisma/schema.prisma` +- [ ] Implement all 12 new models with proper constraints +- [ ] Extend `UserRole` enum with new values +- [ ] Add unique constraint on `Track(pipelineId, sortOrder)` +- [ ] Verify all indexes are created +- [ ] Create seed data with required representative examples +- [ ] Implement integrity check SQL queries + +--- + +## 8. Conclusion + +**Status**: ✅ **DOMAIN MODEL VALIDATED AND APPROVED** + +The proposed canonical domain model is architecturally sound, complete, and ready for implementation. All entities, enums, and constraints have been validated against both the design specification and the current MOPC codebase. + +**Key Strengths**: +- Explicit state machine eliminates implicit round progression logic +- First-class award tracks enable flexible routing and governance +- JSON config fields provide extensibility without schema migrations +- Comprehensive audit trail ensures governance and explainability +- Index strategy optimizes common query patterns + +**Minor Corrections**: +- 1 unique constraint addition needed (`Track.sortOrder`) +- 2 enum values to be added to existing `UserRole` + +**Next Step**: Proceed to Phase 1 schema implementation with confidence that the domain model is solid. + +--- + +**Signed**: Claude Sonnet 4.5 +**Date**: 2026-02-12 diff --git a/next.config.ts b/next.config.ts index c58ba04..80e62ed 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,20 +1,20 @@ -import type { NextConfig } from 'next' - -const nextConfig: NextConfig = { - output: 'standalone', - typedRoutes: true, - serverExternalPackages: ['@prisma/client', 'minio'], - experimental: { - optimizePackageImports: ['lucide-react'], - }, - images: { - remotePatterns: [ - { - protocol: 'https', - hostname: '*.minio.local', - }, - ], - }, -} - -export default nextConfig +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + output: 'standalone', + typedRoutes: true, + serverExternalPackages: ['@prisma/client', 'minio'], + experimental: { + optimizePackageImports: ['lucide-react'], + }, + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: '*.minio.local', + }, + ], + }, +} + +export default nextConfig diff --git a/package-lock.json b/package-lock.json index 3cef1e2..e7921d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13944 +1,13944 @@ -{ - "name": "mopc-platform", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "mopc-platform", - "version": "0.1.0", - "dependencies": { - "@auth/prisma-adapter": "^2.7.4", - "@blocknote/core": "^0.46.2", - "@blocknote/mantine": "^0.46.2", - "@blocknote/react": "^0.46.2", - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^10.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@hookform/resolvers": "^3.9.1", - "@mantine/core": "^8.3.13", - "@mantine/hooks": "^8.3.13", - "@notionhq/client": "^2.3.0", - "@prisma/client": "^6.19.2", - "@radix-ui/react-alert-dialog": "^1.1.4", - "@radix-ui/react-avatar": "^1.1.2", - "@radix-ui/react-checkbox": "^1.1.3", - "@radix-ui/react-collapsible": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.4", - "@radix-ui/react-dropdown-menu": "^2.1.4", - "@radix-ui/react-label": "^2.1.1", - "@radix-ui/react-popover": "^1.1.4", - "@radix-ui/react-progress": "^1.1.1", - "@radix-ui/react-radio-group": "^1.2.2", - "@radix-ui/react-scroll-area": "^1.2.10", - "@radix-ui/react-select": "^2.1.4", - "@radix-ui/react-separator": "^1.1.1", - "@radix-ui/react-slider": "^1.2.2", - "@radix-ui/react-slot": "^1.1.1", - "@radix-ui/react-switch": "^1.1.2", - "@radix-ui/react-tabs": "^1.1.2", - "@radix-ui/react-tooltip": "^1.1.6", - "@tailwindcss/postcss": "^4.1.18", - "@tanstack/react-query": "^5.62.0", - "@trpc/client": "^11.0.0-rc.678", - "@trpc/react-query": "^11.0.0-rc.678", - "@trpc/server": "^11.0.0-rc.678", - "bcryptjs": "^3.0.3", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "cmdk": "^1.0.4", - "csv-parse": "^6.1.0", - "date-fns": "^4.1.0", - "html2canvas": "^1.4.1", - "jspdf": "^4.1.0", - "jspdf-autotable": "^5.0.7", - "leaflet": "^1.9.4", - "lucide-react": "^0.563.0", - "minio": "^8.0.2", - "motion": "^11.15.0", - "next": "^15.1.0", - "next-auth": "^5.0.0-beta.25", - "next-themes": "^0.4.6", - "nodemailer": "^7.0.7", - "openai": "^6.16.0", - "papaparse": "^5.4.1", - "react": "^19.0.0", - "react-day-picker": "^9.13.0", - "react-dom": "^19.0.0", - "react-easy-crop": "^5.5.6", - "react-hook-form": "^7.54.2", - "react-leaflet": "^5.0.0", - "react-phone-number-input": "^3.4.14", - "recharts": "^3.7.0", - "sonner": "^2.0.7", - "superjson": "^2.2.2", - "tailwind-merge": "^3.4.0", - "use-debounce": "^10.0.4", - "zod": "^3.24.1" - }, - "devDependencies": { - "@playwright/test": "^1.49.1", - "@types/bcryptjs": "^2.4.6", - "@types/leaflet": "^1.9.21", - "@types/node": "^25.0.10", - "@types/nodemailer": "^7.0.9", - "@types/papaparse": "^5.3.15", - "@types/react": "^19.0.2", - "@types/react-dom": "^19.0.2", - "eslint": "^9.17.0", - "eslint-config-next": "^15.1.0", - "postcss": "^8.4.49", - "prettier": "^3.4.2", - "prettier-plugin-tailwindcss": "^0.7.2", - "prisma": "^6.19.2", - "tailwindcss": "^4.1.18", - "tailwindcss-animate": "^1.0.7", - "tsx": "^4.19.2", - "typescript": "^5.7.2", - "vitest": "^4.0.18" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@auth/core": { - "version": "0.41.1", - "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.41.1.tgz", - "integrity": "sha512-t9cJ2zNYAdWMacGRMT6+r4xr1uybIdmYa49calBPeTqwgAFPV/88ac9TEvCR85pvATiSPt8VaNf+Gt24JIT/uw==", - "license": "ISC", - "dependencies": { - "@panva/hkdf": "^1.2.1", - "jose": "^6.0.6", - "oauth4webapi": "^3.3.0", - "preact": "10.24.3", - "preact-render-to-string": "6.5.11" - }, - "peerDependencies": { - "@simplewebauthn/browser": "^9.0.1", - "@simplewebauthn/server": "^9.0.2", - "nodemailer": "^7.0.7" - }, - "peerDependenciesMeta": { - "@simplewebauthn/browser": { - "optional": true - }, - "@simplewebauthn/server": { - "optional": true - }, - "nodemailer": { - "optional": true - } - } - }, - "node_modules/@auth/prisma-adapter": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@auth/prisma-adapter/-/prisma-adapter-2.11.1.tgz", - "integrity": "sha512-Ke7DXP0Fy0Mlmjz/ZJLXwQash2UkA4621xCM0rMtEczr1kppLc/njCbUkHkIQ/PnmILjqSPEKeTjDPsYruvkug==", - "license": "ISC", - "dependencies": { - "@auth/core": "0.41.1" - }, - "peerDependencies": { - "@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5 || >=6" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@blocknote/core": { - "version": "0.46.2", - "resolved": "https://registry.npmjs.org/@blocknote/core/-/core-0.46.2.tgz", - "integrity": "sha512-p+QFwrTQfQC08f7JoFg9uuwbAUkGhRakCXhHhY63Wd8ARS0ktHfc9eUnJderXQTEtWfHjACjZOyt2FifX6Lalw==", - "license": "MPL-2.0", - "dependencies": { - "@emoji-mart/data": "^1.2.1", - "@handlewithcare/prosemirror-inputrules": "^0.1.4", - "@shikijs/types": "^3", - "@tanstack/store": "^0.7.7", - "@tiptap/core": "^3.13.0", - "@tiptap/extension-bold": "^3.13.0", - "@tiptap/extension-code": "^3.13.0", - "@tiptap/extension-horizontal-rule": "^3.13.0", - "@tiptap/extension-italic": "^3.13.0", - "@tiptap/extension-link": "^3.13.0", - "@tiptap/extension-paragraph": "^3.13.0", - "@tiptap/extension-strike": "^3.13.0", - "@tiptap/extension-text": "^3.13.0", - "@tiptap/extension-underline": "^3.13.0", - "@tiptap/extensions": "^3.13.0", - "@tiptap/pm": "^3.13.0", - "emoji-mart": "^5.6.0", - "fast-deep-equal": "^3.1.3", - "hast-util-from-dom": "^5.0.1", - "prosemirror-dropcursor": "^1.8.2", - "prosemirror-highlight": "^0.13.0", - "prosemirror-model": "^1.25.4", - "prosemirror-state": "^1.4.4", - "prosemirror-tables": "^1.8.3", - "prosemirror-transform": "^1.10.5", - "prosemirror-view": "^1.41.4", - "rehype-format": "^5.0.1", - "rehype-parse": "^9.0.1", - "rehype-remark": "^10.0.1", - "rehype-stringify": "^10.0.1", - "remark-gfm": "^4.0.1", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.2", - "remark-stringify": "^11.0.0", - "unified": "^11.0.5", - "unist-util-visit": "^5.0.0", - "uuid": "^8.3.2", - "y-prosemirror": "^1.3.7", - "y-protocols": "^1.0.6", - "yjs": "^13.6.27" - }, - "peerDependencies": { - "@hocuspocus/provider": "^2.15.2 || ^3.0.0" - }, - "peerDependenciesMeta": { - "@hocuspocus/provider": { - "optional": true - } - } - }, - "node_modules/@blocknote/mantine": { - "version": "0.46.2", - "resolved": "https://registry.npmjs.org/@blocknote/mantine/-/mantine-0.46.2.tgz", - "integrity": "sha512-2/A82VIby8NNuQbJrXZURnGsksVMWiGWtUOfhvaawCTiB2thYDOV1XONFF1G4xZ2UreodOKLUTwhLm3u25lGrw==", - "license": "MPL-2.0", - "dependencies": { - "@blocknote/core": "0.46.2", - "@blocknote/react": "0.46.2", - "react-icons": "^5.5.0" - }, - "peerDependencies": { - "@mantine/core": "^8.3.11", - "@mantine/hooks": "^8.3.11", - "@mantine/utils": "^6.0.22", - "react": "^18.0 || ^19.0 || >= 19.0.0-rc", - "react-dom": "^18.0 || ^19.0 || >= 19.0.0-rc" - } - }, - "node_modules/@blocknote/react": { - "version": "0.46.2", - "resolved": "https://registry.npmjs.org/@blocknote/react/-/react-0.46.2.tgz", - "integrity": "sha512-2cl7MkOSa6Wxun5LFTT0BCeYq3Qw9DCw6VZ9qdtflrnsefds0cDx/SHMVEQygYwF5MhlDmSbIt61hkQ4j2QWSw==", - "license": "MPL-2.0", - "dependencies": { - "@blocknote/core": "0.46.2", - "@emoji-mart/data": "^1.2.1", - "@floating-ui/react": "^0.27.16", - "@floating-ui/utils": "0.2.10", - "@tanstack/react-store": "0.7.7", - "@tiptap/core": "^3.13.0", - "@tiptap/pm": "^3.13.0", - "@tiptap/react": "^3.13.0", - "@types/use-sync-external-store": "1.5.0", - "emoji-mart": "^5.6.0", - "fast-deep-equal": "^3.1.3", - "lodash.merge": "^4.6.2", - "react-icons": "^5.5.0", - "use-sync-external-store": "1.6.0" - }, - "peerDependencies": { - "react": "^18.0 || ^19.0 || >= 19.0.0-rc", - "react-dom": "^18.0 || ^19.0 || >= 19.0.0-rc" - } - }, - "node_modules/@blocknote/react/node_modules/@types/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-5dyB8nLC/qogMrlCizZnYWQTA4lnb/v+It+sqNl5YnSRAPMlIqY/X0Xn+gZw8vOL+TgTTr28VEbn3uf8fUtAkw==", - "license": "MIT" - }, - "node_modules/@date-fns/tz": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz", - "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==", - "license": "MIT" - }, - "node_modules/@dnd-kit/accessibility": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", - "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@dnd-kit/core": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", - "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", - "license": "MIT", - "dependencies": { - "@dnd-kit/accessibility": "^3.1.1", - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@dnd-kit/sortable": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", - "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", - "license": "MIT", - "dependencies": { - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "@dnd-kit/core": "^6.3.0", - "react": ">=16.8.0" - } - }, - "node_modules/@dnd-kit/utilities": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", - "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emoji-mart/data": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", - "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==", - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", - "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", - "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.4", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/react": { - "version": "0.27.17", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.17.tgz", - "integrity": "sha512-LGVZKHwmWGg6MRHjLLgsfyaX2y2aCNgnD1zT/E6B+/h+vxg+nIJUqHPAlTzsHDyqdgEpJ1Np5kxWuFEErXzoGg==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.1.7", - "@floating-ui/utils": "^0.2.10", - "tabbable": "^6.0.0" - }, - "peerDependencies": { - "react": ">=17.0.0", - "react-dom": ">=17.0.0" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz", - "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.7.5" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", - "license": "MIT" - }, - "node_modules/@handlewithcare/prosemirror-inputrules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@handlewithcare/prosemirror-inputrules/-/prosemirror-inputrules-0.1.4.tgz", - "integrity": "sha512-GMqlBeG2MKM+tXEFd2N+wIv5z4VvJTg8JtfJUrdjvFq2W6v+AW8oTgiWyFw8L3iEQwvtQcVJxU873iB0LXUNNw==", - "license": "MIT", - "dependencies": { - "prosemirror-history": "^1.4.1", - "prosemirror-transform": "^1.0.0" - }, - "peerDependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-view": "^1.0.0" - } - }, - "node_modules/@hookform/resolvers": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", - "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", - "license": "MIT", - "peerDependencies": { - "react-hook-form": "^7.0.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mantine/core": { - "version": "8.3.13", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.13.tgz", - "integrity": "sha512-ZgW4vqN4meaPyIMxzAufBvsgmJRfYZdTpsrAOcS8pWy7m9e8i685E7XsAxnwJCOIHudpvpvt+7Bx7VaIjEsYEw==", - "license": "MIT", - "dependencies": { - "@floating-ui/react": "^0.27.16", - "clsx": "^2.1.1", - "react-number-format": "^5.4.4", - "react-remove-scroll": "^2.7.1", - "react-textarea-autosize": "8.5.9", - "type-fest": "^4.41.0" - }, - "peerDependencies": { - "@mantine/hooks": "8.3.13", - "react": "^18.x || ^19.x", - "react-dom": "^18.x || ^19.x" - } - }, - "node_modules/@mantine/hooks": { - "version": "8.3.13", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.13.tgz", - "integrity": "sha512-7YMbMW/tR9E8m/9DbBW01+3RNApm2mE/JbRKXf9s9+KxgbjQvq0FYGWV8Y4+Sjz48AO4vtWk2qBriUTgBMKAyg==", - "license": "MIT", - "peerDependencies": { - "react": "^18.x || ^19.x" - } - }, - "node_modules/@mantine/utils": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-6.0.22.tgz", - "integrity": "sha512-RSKlNZvxhMCkOFZ6slbYvZYbWjHUM+PxDQnupIOxIdsTZQQjx/BFfrfJ7kQFOP+g7MtpOds8weAetEs5obwMOQ==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@next/env": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.10.tgz", - "integrity": "sha512-plg+9A/KoZcTS26fe15LHg+QxReTazrIOoKKUC3Uz4leGGeNPgLHdevVraAAOX0snnUs3WkRx3eUQpj9mreG6A==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.10.tgz", - "integrity": "sha512-fDpxcy6G7Il4lQVVsaJD0fdC2/+SmuBGTF+edRLlsR4ZFOE3W2VyzrrGYdg/pHW8TydeAdSVM+mIzITGtZ3yWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "3.3.1" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz", - "integrity": "sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz", - "integrity": "sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz", - "integrity": "sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz", - "integrity": "sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz", - "integrity": "sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz", - "integrity": "sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz", - "integrity": "sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz", - "integrity": "sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/@notionhq/client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@notionhq/client/-/client-2.3.0.tgz", - "integrity": "sha512-l7WqTCpQqC+HibkB9chghONQTYcxNQT0/rOJemBfmuKQRTu2vuV8B3yA395iKaUdDo7HI+0KvQaz9687Xskzkw==", - "license": "MIT", - "dependencies": { - "@types/node-fetch": "^2.5.10", - "node-fetch": "^2.6.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@panva/hkdf": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", - "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/@playwright/test": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.0.tgz", - "integrity": "sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "playwright": "1.58.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@prisma/client": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.2.tgz", - "integrity": "sha512-gR2EMvfK/aTxsuooaDA32D8v+us/8AAet+C3J1cc04SW35FPdZYgLF+iN4NDLUgAaUGTKdAB0CYenu1TAgGdMg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "prisma": "*", - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@prisma/config": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", - "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "c12": "3.1.0", - "deepmerge-ts": "7.1.5", - "effect": "3.18.4", - "empathic": "2.0.0" - } - }, - "node_modules/@prisma/debug": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", - "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", - "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.19.2", - "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "@prisma/fetch-engine": "6.19.2", - "@prisma/get-platform": "6.19.2" - } - }, - "node_modules/@prisma/engines-version": { - "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", - "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", - "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.19.2", - "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "@prisma/get-platform": "6.19.2" - } - }, - "node_modules/@prisma/get-platform": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.2.tgz", - "integrity": "sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.19.2" - } - }, - "node_modules/@radix-ui/number": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", - "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", - "license": "MIT" - }, - "node_modules/@radix-ui/primitive": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-alert-dialog": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", - "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dialog": "1.1.15", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-avatar": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz", - "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.1.3", - "@radix-ui/react-primitive": "2.1.4", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-is-hydrated": "0.1.0", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", - "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", - "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", - "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", - "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", - "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", - "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", - "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-menu": "2.1.16", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", - "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", - "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", - "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", - "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popover": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", - "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", - "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-rect": "1.1.1", - "@radix-ui/react-use-size": "1.1.1", - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", - "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.1.3", - "@radix-ui/react-primitive": "2.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", - "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", - "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", - "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", - "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-scroll-area": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", - "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", - "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", - "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", - "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slider": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", - "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", - "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", - "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", - "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", - "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-visually-hidden": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-is-hydrated": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", - "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", - "license": "MIT", - "dependencies": { - "use-sync-external-store": "^1.5.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", - "license": "MIT", - "dependencies": { - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", - "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", - "license": "MIT" - }, - "node_modules/@react-leaflet/core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz", - "integrity": "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==", - "license": "Hippocratic-2.1", - "peerDependencies": { - "leaflet": "^1.9.0", - "react": "^19.0.0", - "react-dom": "^19.0.0" - } - }, - "node_modules/@reduxjs/toolkit": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", - "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==", - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@standard-schema/utils": "^0.3.0", - "immer": "^11.0.0", - "redux": "^5.0.1", - "redux-thunk": "^3.1.0", - "reselect": "^5.1.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", - "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-redux": { - "optional": true - } - } - }, - "node_modules/@reduxjs/toolkit/node_modules/immer": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.3.tgz", - "integrity": "sha512-6jQTc5z0KJFtr1UgFpIL3N9XSC3saRaI9PwWtzM2pSqkNGtiNkYY2OSwkOGDK2XcTRcLb1pi/aNkKZz0nxVH4Q==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/@remirror/core-constants": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", - "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz", - "integrity": "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz", - "integrity": "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz", - "integrity": "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz", - "integrity": "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz", - "integrity": "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz", - "integrity": "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz", - "integrity": "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz", - "integrity": "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz", - "integrity": "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz", - "integrity": "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz", - "integrity": "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz", - "integrity": "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz", - "integrity": "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz", - "integrity": "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz", - "integrity": "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz", - "integrity": "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz", - "integrity": "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz", - "integrity": "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz", - "integrity": "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz", - "integrity": "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz", - "integrity": "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz", - "integrity": "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz", - "integrity": "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz", - "integrity": "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz", - "integrity": "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", - "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@shikijs/types": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.21.0.tgz", - "integrity": "sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==", - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "license": "MIT" - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "license": "MIT" - }, - "node_modules/@standard-schema/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", - "license": "MIT" - }, - "node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@tailwindcss/node": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", - "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.6.1", - "lightningcss": "1.30.2", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.18" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", - "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", - "license": "MIT", - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.18", - "@tailwindcss/oxide-darwin-arm64": "4.1.18", - "@tailwindcss/oxide-darwin-x64": "4.1.18", - "@tailwindcss/oxide-freebsd-x64": "4.1.18", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", - "@tailwindcss/oxide-linux-x64-musl": "4.1.18", - "@tailwindcss/oxide-wasm32-wasi": "4.1.18", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", - "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", - "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", - "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", - "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", - "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", - "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", - "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", - "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", - "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", - "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.0", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", - "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", - "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", - "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.18", - "@tailwindcss/oxide": "4.1.18", - "postcss": "^8.4.41", - "tailwindcss": "4.1.18" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.90.20", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz", - "integrity": "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.90.20", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.20.tgz", - "integrity": "sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.90.20" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "node_modules/@tanstack/react-store": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.7.7.tgz", - "integrity": "sha512-qqT0ufegFRDGSof9D/VqaZgjNgp4tRPHZIJq2+QIHkMUtHjaJ0lYrrXjeIUJvjnTbgPfSD1XgOMEt0lmANn6Zg==", - "license": "MIT", - "dependencies": { - "@tanstack/store": "0.7.7", - "use-sync-external-store": "^1.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@tanstack/store": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.7.tgz", - "integrity": "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tiptap/core": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.18.0.tgz", - "integrity": "sha512-Gczd4GbK1DNgy/QUPElMVozoa0GW9mW8E31VIi7Q4a9PHHz8PcrxPmuWwtJ2q0PF8MWpOSLuBXoQTWaXZRPRnQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/pm": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-bold": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.18.0.tgz", - "integrity": "sha512-xUgOvHCdGXh9Lfxd7DtgsSr0T/egIwBllWHIBWDjQEQQ0b+ICn+0+i703btHMB4hjdduZtgVDrhK8jAW3U6swA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-bubble-menu": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.18.0.tgz", - "integrity": "sha512-9kYG1fVYQcA3Kp5Bq96lrKCp9oLpQqceDsK688r7iT1yymQlBPMunaqaqb5ZLQGhnNYbhfG+8xcQsvEKjklErA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0", - "@tiptap/pm": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-code": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.18.0.tgz", - "integrity": "sha512-0SU53O0NRmdtRM2Hgzm372dVoHjs2F40o/dtB7ls4kocf4W89FyWeC2R6ZsFQqcXisNh9RTzLtYfbNyizGuZIw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-floating-menu": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.18.0.tgz", - "integrity": "sha512-a2cBQi0I/X0o3a9b+adwJvkdxLzQzJIkP9dc/v25qGTSCjC1+ycois5WQOn8T4T8t4g/fAH1UOXEWnkWyTxLIg==", - "license": "MIT", - "optional": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@floating-ui/dom": "^1.0.0", - "@tiptap/core": "^3.18.0", - "@tiptap/pm": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-horizontal-rule": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.18.0.tgz", - "integrity": "sha512-fEq7DwwQZ496RHNbMQypBVNqoWnhDEERbzWMBqlmfCfc/0FvJrHtsQkk3k4lgqMYqmBwym3Wp0SrRYiyKCPGTw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0", - "@tiptap/pm": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-italic": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.18.0.tgz", - "integrity": "sha512-1C4nB08psiRo0BPxAbpYq8peUOKnjQWtBCLPbE6B9ToTK3vmUk0AZTqLO11FvokuM1GF5l2Lg3sKrKFuC2hcjQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-link": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.18.0.tgz", - "integrity": "sha512-1J28C4+fKAMQi7q/UsTjAmgmKTnzjExXY98hEBneiVzFDxqF69n7+Vb7nVTNAIhmmJkZMA0DEcMhSiQC/1/u4A==", - "license": "MIT", - "dependencies": { - "linkifyjs": "^4.3.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0", - "@tiptap/pm": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-paragraph": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.18.0.tgz", - "integrity": "sha512-uvFhdwiur4NhhUdBmDsajxjGAIlg5qga55fYag2DzOXxIQE2M7/aVMRkRpuJzb88GY4EHSh8rY34HgMK2FJt2Q==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-strike": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.18.0.tgz", - "integrity": "sha512-kl/fa68LZg8NWUqTkRTfgyCx+IGqozBmzJxQDc1zxurrIU+VFptDV9UuZim587sbM2KGjCi/PNPjPGk1Uu0PVg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-text": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.18.0.tgz", - "integrity": "sha512-9TvctdnBCwK/zyTi9kS7nGFNl5OvGM8xE0u38ZmQw5t79JOqJHgOroyqMjw8LHK/1PWrozfNCmsZbpq4IZuKXw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extension-underline": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.18.0.tgz", - "integrity": "sha512-009IeXURNJ/sm1pBqbj+2YQgjQaBtNlJR3dbl6xu49C+qExqCmI7klhKQuwsVVGLR7ahsYlp7d9RlftnhCXIcQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0" - } - }, - "node_modules/@tiptap/extensions": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.18.0.tgz", - "integrity": "sha512-uSRIE9HGshBN6NRFR3LX2lZqBLvX92SgU5A9AvUbJD4MqU63E+HdruJnRjsVlX3kPrmbIDowxrzXlUcg3K0USQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0", - "@tiptap/pm": "^3.18.0" - } - }, - "node_modules/@tiptap/pm": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.18.0.tgz", - "integrity": "sha512-8RoI5gW0xBVCsuxahpK8vx7onAw6k2/uR3hbGBBnH+HocDMaAZKot3nTyY546ij8ospIC1mnQ7k4BhVUZesZDQ==", - "license": "MIT", - "dependencies": { - "prosemirror-changeset": "^2.3.0", - "prosemirror-collab": "^1.3.1", - "prosemirror-commands": "^1.6.2", - "prosemirror-dropcursor": "^1.8.1", - "prosemirror-gapcursor": "^1.3.2", - "prosemirror-history": "^1.4.1", - "prosemirror-inputrules": "^1.4.0", - "prosemirror-keymap": "^1.2.2", - "prosemirror-markdown": "^1.13.1", - "prosemirror-menu": "^1.2.4", - "prosemirror-model": "^1.24.1", - "prosemirror-schema-basic": "^1.2.3", - "prosemirror-schema-list": "^1.5.0", - "prosemirror-state": "^1.4.3", - "prosemirror-tables": "^1.6.4", - "prosemirror-trailing-node": "^3.0.0", - "prosemirror-transform": "^1.10.2", - "prosemirror-view": "^1.38.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - } - }, - "node_modules/@tiptap/react": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.18.0.tgz", - "integrity": "sha512-VC20YhoiWe2E03D1BRH+AVMgXeA7li+bzIoaBtpK9+AdizAC+TvWCb2I/9mQCy9m31zGYTD0vv0e7bVlJi+aKA==", - "license": "MIT", - "dependencies": { - "@types/use-sync-external-store": "^0.0.6", - "fast-equals": "^5.3.3", - "use-sync-external-store": "^1.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "optionalDependencies": { - "@tiptap/extension-bubble-menu": "^3.18.0", - "@tiptap/extension-floating-menu": "^3.18.0" - }, - "peerDependencies": { - "@tiptap/core": "^3.18.0", - "@tiptap/pm": "^3.18.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@trpc/client": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/@trpc/client/-/client-11.9.0.tgz", - "integrity": "sha512-3r4RT/GbR263QO+2gCPyrs5fEYaXua3/AzCs+GbWC09X0F+mVkyBpO3GRSDObiNU/N1YB597U7WGW3WA1d1TVw==", - "funding": [ - "https://trpc.io/sponsor" - ], - "license": "MIT", - "peerDependencies": { - "@trpc/server": "11.9.0", - "typescript": ">=5.7.2" - } - }, - "node_modules/@trpc/react-query": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-11.9.0.tgz", - "integrity": "sha512-9Gpj06ZcfsA77PB5A8VC2MFS/E7pPvoNqaSlSrAgLyRsKqy0gldFOW2RMKura69M6fwtgjg9+4i2+rOHKT7qLw==", - "funding": [ - "https://trpc.io/sponsor" - ], - "license": "MIT", - "peerDependencies": { - "@tanstack/react-query": "^5.80.3", - "@trpc/client": "11.9.0", - "@trpc/server": "11.9.0", - "react": ">=18.2.0", - "react-dom": ">=18.2.0", - "typescript": ">=5.7.2" - } - }, - "node_modules/@trpc/server": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/@trpc/server/-/server-11.9.0.tgz", - "integrity": "sha512-T8gC4NOCzx8tCsQEQ5sSjf24bN+9AEqXZRfpThG+YCEmcEwXfS7RP8VVrl5Vodt1S+zGEDyQSof4YVAj1zq/mg==", - "funding": [ - "https://trpc.io/sponsor" - ], - "license": "MIT", - "peerDependencies": { - "typescript": ">=5.7.2" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/bcryptjs": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", - "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/d3-array": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", - "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", - "license": "MIT" - }, - "node_modules/@types/d3-color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", - "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", - "license": "MIT" - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", - "license": "MIT" - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "license": "MIT", - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", - "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", - "license": "MIT" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-shape": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", - "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", - "license": "MIT", - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", - "license": "MIT" - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/leaflet": { - "version": "1.9.21", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", - "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "license": "MIT" - }, - "node_modules/@types/markdown-it": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", - "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", - "license": "MIT", - "dependencies": { - "@types/linkify-it": "^5", - "@types/mdurl": "^2" - } - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "25.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", - "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.4" - } - }, - "node_modules/@types/nodemailer": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.9.tgz", - "integrity": "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/pako": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", - "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", - "license": "MIT" - }, - "node_modules/@types/papaparse": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", - "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/raf": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", - "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", - "license": "MIT", - "optional": true - }, - "node_modules/@types/react": { - "version": "19.2.10", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz", - "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", - "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/type-utils": "8.54.0", - "@typescript-eslint/utils": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.54.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz", - "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", - "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.54.0", - "@typescript-eslint/types": "^8.54.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", - "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", - "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz", - "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0", - "@typescript-eslint/utils": "8.54.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", - "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", - "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.54.0", - "@typescript-eslint/tsconfig-utils": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", - "debug": "^4.4.3", - "minimatch": "^9.0.5", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", - "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", - "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.54.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "license": "ISC" - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.0.18", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@zxing/text-encoding": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", - "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", - "license": "(Unlicense OR Apache-2.0)", - "optional": true - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/aria-hidden": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", - "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", - "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", - "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz", - "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/bcryptjs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", - "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==", - "license": "BSD-3-Clause", - "bin": { - "bcrypt": "bin/bcrypt" - } - }, - "node_modules/block-stream2": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", - "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", - "license": "MIT", - "dependencies": { - "readable-stream": "^3.4.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-or-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", - "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==", - "license": "MIT" - }, - "node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" - }, - "peerDependencies": { - "magicast": "^0.3.5" - }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001766", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", - "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/canvg": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", - "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "@types/raf": "^3.4.0", - "core-js": "^3.8.3", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.7", - "rgbcolor": "^1.0.1", - "stackblur-canvas": "^2.0.0", - "svg-pathdata": "^6.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "consola": "^3.2.3" - } - }, - "node_modules/class-variance-authority": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", - "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", - "license": "Apache-2.0", - "dependencies": { - "clsx": "^2.1.1" - }, - "funding": { - "url": "https://polar.sh/cva" - } - }, - "node_modules/classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", - "license": "MIT" - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cmdk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", - "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-id": "^1.1.0", - "@radix-ui/react-primitive": "^2.0.2" - }, - "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "react-dom": "^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/copy-anything": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", - "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", - "license": "MIT", - "dependencies": { - "is-what": "^5.2.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/core-js": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz", - "integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/country-flag-icons": { - "version": "1.6.12", - "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.6.12.tgz", - "integrity": "sha512-tWxbBylam6Fkkg0nu+112jmny4WomHXgmdTQFobs/+evTyizSc06bCp//HAh4W1i+g1m06uqlbPuyLC5mrimkQ==", - "license": "MIT" - }, - "node_modules/crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-line-break": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", - "license": "MIT", - "dependencies": { - "utrie": "^1.0.2" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/csv-parse": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-6.1.0.tgz", - "integrity": "sha512-CEE+jwpgLn+MmtCpVcPtiCZpVtB6Z2OKPTr34pycYYoL7sxdOkXDdQ4lRiw6ioC0q6BLqhc6cKweCVvral8yhw==", - "license": "MIT" - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/date-fns-jalali": { - "version": "4.1.0-0", - "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", - "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", - "license": "MIT" - }, - "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "license": "MIT" - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optional": true, - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "devOptional": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/effect": { - "version": "3.18.4", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", - "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "fast-check": "^3.23.1" - } - }, - "node_modules/emoji-mart": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", - "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.18.4", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", - "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-abstract": { - "version": "1.24.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", - "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz", - "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.1", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.1.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.3.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.5", - "safe-array-concat": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-toolkit": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.44.0.tgz", - "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==", - "license": "MIT", - "workspaces": [ - "docs", - "benchmarks" - ] - }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-next": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.10.tgz", - "integrity": "sha512-AeYOVGiSbIfH4KXFT3d0fIDm7yTslR/AWGoHLdsXQ99MH0zFWmkRIin1H7I9SFlkKgf4PKm9ncsyWHq1aAfHBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@next/eslint-plugin-next": "15.5.10", - "@rushstack/eslint-patch": "^1.10.3", - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^5.0.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", - "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.4.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^2.0.0", - "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.13", - "unrs-resolver": "^1.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-import-resolver-typescript" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", - "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", - "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", - "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.9", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "license": "MIT" - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/exsolve": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", - "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-check": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", - "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT", - "dependencies": { - "pure-rand": "^6.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-equals": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", - "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-png": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz", - "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==", - "license": "MIT", - "dependencies": { - "@types/pako": "^2.0.3", - "iobuffer": "^5.3.2", - "pako": "^2.1.0" - } - }, - "node_modules/fast-xml-parser": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", - "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^1.1.1" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/framer-motion": { - "version": "11.18.2", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", - "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", - "license": "MIT", - "dependencies": { - "motion-dom": "^11.18.1", - "motion-utils": "^11.18.1", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" - }, - "bin": { - "giget": "dist/cli.mjs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-util-embedded": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", - "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-is-element": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-format": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", - "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-embedded": "^3.0.0", - "hast-util-minify-whitespace": "^1.0.0", - "hast-util-phrasing": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "html-whitespace-sensitive-tag-names": "^3.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-dom": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", - "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", - "license": "ISC", - "dependencies": { - "@types/hast": "^3.0.0", - "hastscript": "^9.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", - "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", - "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^9.0.0", - "property-information": "^7.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-has-property": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", - "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-body-ok-link": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", - "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-minify-whitespace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", - "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-embedded": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-phrasing": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", - "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-embedded": "^3.0.0", - "hast-util-has-property": "^3.0.0", - "hast-util-is-body-ok-link": "^3.0.0", - "hast-util-is-element": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-mdast": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.2.tgz", - "integrity": "sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-phrasing": "^3.0.0", - "hast-util-to-html": "^9.0.0", - "hast-util-to-text": "^4.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-minify-whitespace": "^6.0.0", - "trim-trailing-lines": "^2.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-text": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", - "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", - "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/html-whitespace-sensitive-tag-names": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", - "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html2canvas": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", - "license": "MIT", - "dependencies": { - "css-line-break": "^2.1.0", - "text-segmentation": "^1.0.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/immer": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", - "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/input-format": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/input-format/-/input-format-0.3.14.tgz", - "integrity": "sha512-gHMrgrbCgmT4uK5Um5eVDUohuV9lcs95ZUUN9Px2Y0VIfjTzT2wF8Q3Z4fwLFm7c5Z2OXCm53FHoovj6SlOKdg==", - "license": "MIT", - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "react": ">=18.1.0", - "react-dom": ">=18.1.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/iobuffer": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz", - "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==", - "license": "MIT" - }, - "node_modules/ipaddr.js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", - "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bun-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", - "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.7.1" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-what": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", - "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/isomorphic.js": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", - "license": "MIT", - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/jose": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", - "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jspdf": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.1.0.tgz", - "integrity": "sha512-xd1d/XRkwqnsq6FP3zH1Q+Ejqn2ULIJeDZ+FTKpaabVpZREjsJKRJwuokTNgdqOU+fl55KgbvgZ1pRTSWCP2kQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4", - "fast-png": "^6.2.0", - "fflate": "^0.8.1" - }, - "optionalDependencies": { - "canvg": "^3.0.11", - "core-js": "^3.6.0", - "dompurify": "^3.3.1", - "html2canvas": "^1.0.0-rc.5" - } - }, - "node_modules/jspdf-autotable": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-5.0.7.tgz", - "integrity": "sha512-2wr7H6liNDBYNwt25hMQwXkEWFOEopgKIvR1Eukuw6Zmprm/ZcnmLTQEjW7Xx3FCbD3v7pflLcnMAv/h1jFDQw==", - "license": "MIT", - "peerDependencies": { - "jspdf": "^2 || ^3 || ^4" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/leaflet": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", - "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", - "license": "BSD-2-Clause" - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lib0": { - "version": "0.2.117", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", - "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", - "license": "MIT", - "dependencies": { - "isomorphic.js": "^0.2.4" - }, - "bin": { - "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", - "0gentesthtml": "bin/gentesthtml.js", - "0serve": "bin/0serve.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, - "node_modules/libphonenumber-js": { - "version": "1.12.35", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.35.tgz", - "integrity": "sha512-T/Cz6iLcsZdb5jDncDcUNhSAJ0VlSC9TnsqtBNdpkaAmy24/R1RhErtNWVWBrcUZKs9hSgaVsBkc7HxYnazIfw==", - "license": "MIT" - }, - "node_modules/lightningcss": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", - "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.30.2", - "lightningcss-darwin-arm64": "1.30.2", - "lightningcss-darwin-x64": "1.30.2", - "lightningcss-freebsd-x64": "1.30.2", - "lightningcss-linux-arm-gnueabihf": "1.30.2", - "lightningcss-linux-arm64-gnu": "1.30.2", - "lightningcss-linux-arm64-musl": "1.30.2", - "lightningcss-linux-x64-gnu": "1.30.2", - "lightningcss-linux-x64-musl": "1.30.2", - "lightningcss-win32-arm64-msvc": "1.30.2", - "lightningcss-win32-x64-msvc": "1.30.2" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", - "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", - "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", - "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", - "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", - "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", - "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", - "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", - "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", - "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", - "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", - "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/linkifyjs": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", - "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "license": "MIT" - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lucide-react": { - "version": "0.563.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.563.0.tgz", - "integrity": "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minio": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.6.tgz", - "integrity": "sha512-sOeh2/b/XprRmEtYsnNRFtOqNRTPDvYtMWh+spWlfsuCV/+IdxNeKVUMKLqI7b5Dr07ZqCPuaRGU/rB9pZYVdQ==", - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.4", - "block-stream2": "^2.1.0", - "browser-or-node": "^2.1.1", - "buffer-crc32": "^1.0.0", - "eventemitter3": "^5.0.1", - "fast-xml-parser": "^4.4.1", - "ipaddr.js": "^2.0.1", - "lodash": "^4.17.21", - "mime-types": "^2.1.35", - "query-string": "^7.1.3", - "stream-json": "^1.8.0", - "through2": "^4.0.2", - "web-encoding": "^1.1.5", - "xml2js": "^0.5.0 || ^0.6.2" - }, - "engines": { - "node": "^16 || ^18 || >=20" - } - }, - "node_modules/motion": { - "version": "11.18.2", - "resolved": "https://registry.npmjs.org/motion/-/motion-11.18.2.tgz", - "integrity": "sha512-JLjvFDuFr42NFtcVoMAyC2sEjnpA8xpy6qWPyzQvCloznAyQ8FIXioxWfHiLtgYhoVpfUqSWpn1h9++skj9+Wg==", - "license": "MIT", - "dependencies": { - "framer-motion": "^11.18.2", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/motion-dom": { - "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", - "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", - "license": "MIT", - "dependencies": { - "motion-utils": "^11.18.1" - } - }, - "node_modules/motion-utils": { - "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", - "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-postinstall": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", - "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/next": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.10.tgz", - "integrity": "sha512-r0X65PNwyDDyOrWNKpQoZvOatw7BcsTPRKdwEqtc9cj3wv7mbBIk9tKed4klRaFXJdX0rugpuMTHslDrAU1bBg==", - "license": "MIT", - "dependencies": { - "@next/env": "15.5.10", - "@swc/helpers": "0.5.15", - "caniuse-lite": "^1.0.30001579", - "postcss": "8.4.31", - "styled-jsx": "5.1.6" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.7", - "@next/swc-darwin-x64": "15.5.7", - "@next/swc-linux-arm64-gnu": "15.5.7", - "@next/swc-linux-arm64-musl": "15.5.7", - "@next/swc-linux-x64-gnu": "15.5.7", - "@next/swc-linux-x64-musl": "15.5.7", - "@next/swc-win32-arm64-msvc": "15.5.7", - "@next/swc-win32-x64-msvc": "15.5.7", - "sharp": "^0.34.3" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.51.1", - "babel-plugin-react-compiler": "*", - "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next-auth": { - "version": "5.0.0-beta.30", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.30.tgz", - "integrity": "sha512-+c51gquM3F6nMVmoAusRJ7RIoY0K4Ts9HCCwyy/BRoe4mp3msZpOzYMyb5LAYc1wSo74PMQkGDcaghIO7W6Xjg==", - "license": "ISC", - "dependencies": { - "@auth/core": "0.41.0" - }, - "peerDependencies": { - "@simplewebauthn/browser": "^9.0.1", - "@simplewebauthn/server": "^9.0.2", - "next": "^14.0.0-0 || ^15.0.0 || ^16.0.0", - "nodemailer": "^7.0.7", - "react": "^18.2.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@simplewebauthn/browser": { - "optional": true - }, - "@simplewebauthn/server": { - "optional": true - }, - "nodemailer": { - "optional": true - } - } - }, - "node_modules/next-auth/node_modules/@auth/core": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.41.0.tgz", - "integrity": "sha512-Wd7mHPQ/8zy6Qj7f4T46vg3aoor8fskJm6g2Zyj064oQ3+p0xNZXAV60ww0hY+MbTesfu29kK14Zk5d5JTazXQ==", - "license": "ISC", - "dependencies": { - "@panva/hkdf": "^1.2.1", - "jose": "^6.0.6", - "oauth4webapi": "^3.3.0", - "preact": "10.24.3", - "preact-render-to-string": "6.5.11" - }, - "peerDependencies": { - "@simplewebauthn/browser": "^9.0.1", - "@simplewebauthn/server": "^9.0.2", - "nodemailer": "^6.8.0" - }, - "peerDependenciesMeta": { - "@simplewebauthn/browser": { - "optional": true - }, - "@simplewebauthn/server": { - "optional": true - }, - "nodemailer": { - "optional": true - } - } - }, - "node_modules/next-themes": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", - "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/nodemailer": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", - "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", - "license": "MIT-0", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/normalize-wheel": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz", - "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==", - "license": "BSD-3-Clause" - }, - "node_modules/nypm": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.4.tgz", - "integrity": "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "citty": "^0.2.0", - "pathe": "^2.0.3", - "tinyexec": "^1.0.2" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/nypm/node_modules/citty": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.0.tgz", - "integrity": "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/oauth4webapi": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.3.tgz", - "integrity": "sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", - "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/openai": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.16.0.tgz", - "integrity": "sha512-fZ1uBqjFUjXzbGc35fFtYKEOxd20kd9fDpFeqWtsOZWiubY8CZ1NAlXHW3iathaFvqmNtCWMIsosCuyeI7Joxg==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/orderedmap": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", - "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", - "license": "MIT" - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, - "node_modules/papaparse": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.3.tgz", - "integrity": "sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==", - "license": "MIT" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "license": "MIT", - "optional": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" - } - }, - "node_modules/playwright": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.0.tgz", - "integrity": "sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.58.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.0.tgz", - "integrity": "sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/preact": { - "version": "10.24.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", - "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, - "node_modules/preact-render-to-string": { - "version": "6.5.11", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz", - "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==", - "license": "MIT", - "peerDependencies": { - "preact": ">=10" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-tailwindcss": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.2.tgz", - "integrity": "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.19" - }, - "peerDependencies": { - "@ianvs/prettier-plugin-sort-imports": "*", - "@prettier/plugin-hermes": "*", - "@prettier/plugin-oxc": "*", - "@prettier/plugin-pug": "*", - "@shopify/prettier-plugin-liquid": "*", - "@trivago/prettier-plugin-sort-imports": "*", - "@zackad/prettier-plugin-twig": "*", - "prettier": "^3.0", - "prettier-plugin-astro": "*", - "prettier-plugin-css-order": "*", - "prettier-plugin-jsdoc": "*", - "prettier-plugin-marko": "*", - "prettier-plugin-multiline-arrays": "*", - "prettier-plugin-organize-attributes": "*", - "prettier-plugin-organize-imports": "*", - "prettier-plugin-sort-imports": "*", - "prettier-plugin-svelte": "*" - }, - "peerDependenciesMeta": { - "@ianvs/prettier-plugin-sort-imports": { - "optional": true - }, - "@prettier/plugin-hermes": { - "optional": true - }, - "@prettier/plugin-oxc": { - "optional": true - }, - "@prettier/plugin-pug": { - "optional": true - }, - "@shopify/prettier-plugin-liquid": { - "optional": true - }, - "@trivago/prettier-plugin-sort-imports": { - "optional": true - }, - "@zackad/prettier-plugin-twig": { - "optional": true - }, - "prettier-plugin-astro": { - "optional": true - }, - "prettier-plugin-css-order": { - "optional": true - }, - "prettier-plugin-jsdoc": { - "optional": true - }, - "prettier-plugin-marko": { - "optional": true - }, - "prettier-plugin-multiline-arrays": { - "optional": true - }, - "prettier-plugin-organize-attributes": { - "optional": true - }, - "prettier-plugin-organize-imports": { - "optional": true - }, - "prettier-plugin-sort-imports": { - "optional": true - }, - "prettier-plugin-svelte": { - "optional": true - } - } - }, - "node_modules/prisma": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", - "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/config": "6.19.2", - "@prisma/engines": "6.19.2" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/prosemirror-changeset": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz", - "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==", - "license": "MIT", - "dependencies": { - "prosemirror-transform": "^1.0.0" - } - }, - "node_modules/prosemirror-collab": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", - "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", - "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.0.0" - } - }, - "node_modules/prosemirror-commands": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", - "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", - "license": "MIT", - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.10.2" - } - }, - "node_modules/prosemirror-dropcursor": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", - "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", - "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0", - "prosemirror-view": "^1.1.0" - } - }, - "node_modules/prosemirror-gapcursor": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.0.tgz", - "integrity": "sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ==", - "license": "MIT", - "dependencies": { - "prosemirror-keymap": "^1.0.0", - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-view": "^1.0.0" - } - }, - "node_modules/prosemirror-highlight": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/prosemirror-highlight/-/prosemirror-highlight-0.13.0.tgz", - "integrity": "sha512-GIC2VCTUnukNdsEGLQWWOVpYPl/7/KrVp4xs7XMB48/4rhUrHK8hp8TEog4Irmv+2kmjx24RLnaisGOCP6U8jw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ocavue" - }, - "peerDependencies": { - "@shikijs/types": "^1.29.2 || ^2.0.0 || ^3.0.0", - "@types/hast": "^3.0.0", - "highlight.js": "^11.9.0", - "lowlight": "^3.1.0", - "prosemirror-model": "^1.19.3", - "prosemirror-state": "^1.4.3", - "prosemirror-transform": "^1.8.0", - "prosemirror-view": "^1.32.4", - "refractor": "^5.0.0", - "sugar-high": "^0.6.1 || ^0.7.0 || ^0.8.0 || ^0.9.0" - }, - "peerDependenciesMeta": { - "@shikijs/types": { - "optional": true - }, - "@types/hast": { - "optional": true - }, - "highlight.js": { - "optional": true - }, - "lowlight": { - "optional": true - }, - "prosemirror-model": { - "optional": true - }, - "prosemirror-state": { - "optional": true - }, - "prosemirror-transform": { - "optional": true - }, - "prosemirror-view": { - "optional": true - }, - "refractor": { - "optional": true - }, - "sugar-high": { - "optional": true - } - } - }, - "node_modules/prosemirror-history": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", - "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", - "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.2.2", - "prosemirror-transform": "^1.0.0", - "prosemirror-view": "^1.31.0", - "rope-sequence": "^1.3.0" - } - }, - "node_modules/prosemirror-inputrules": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz", - "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==", - "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.0.0" - } - }, - "node_modules/prosemirror-keymap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", - "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", - "license": "MIT", - "dependencies": { - "prosemirror-state": "^1.0.0", - "w3c-keyname": "^2.2.0" - } - }, - "node_modules/prosemirror-markdown": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.3.tgz", - "integrity": "sha512-3E+Et6cdXIH0EgN2tGYQ+EBT7N4kMiZFsW+hzx+aPtOmADDHWCdd2uUQb7yklJrfUYUOjEEu22BiN6UFgPe4cQ==", - "license": "MIT", - "dependencies": { - "@types/markdown-it": "^14.0.0", - "markdown-it": "^14.0.0", - "prosemirror-model": "^1.25.0" - } - }, - "node_modules/prosemirror-menu": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", - "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", - "license": "MIT", - "dependencies": { - "crelt": "^1.0.0", - "prosemirror-commands": "^1.0.0", - "prosemirror-history": "^1.0.0", - "prosemirror-state": "^1.0.0" - } - }, - "node_modules/prosemirror-model": { - "version": "1.25.4", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", - "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", - "license": "MIT", - "dependencies": { - "orderedmap": "^2.0.0" - } - }, - "node_modules/prosemirror-schema-basic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", - "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", - "license": "MIT", - "dependencies": { - "prosemirror-model": "^1.25.0" - } - }, - "node_modules/prosemirror-schema-list": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", - "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", - "license": "MIT", - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.7.3" - } - }, - "node_modules/prosemirror-state": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", - "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", - "license": "MIT", - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-transform": "^1.0.0", - "prosemirror-view": "^1.27.0" - } - }, - "node_modules/prosemirror-tables": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz", - "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==", - "license": "MIT", - "dependencies": { - "prosemirror-keymap": "^1.2.3", - "prosemirror-model": "^1.25.4", - "prosemirror-state": "^1.4.4", - "prosemirror-transform": "^1.10.5", - "prosemirror-view": "^1.41.4" - } - }, - "node_modules/prosemirror-trailing-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", - "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", - "license": "MIT", - "dependencies": { - "@remirror/core-constants": "3.0.0", - "escape-string-regexp": "^4.0.0" - }, - "peerDependencies": { - "prosemirror-model": "^1.22.1", - "prosemirror-state": "^1.4.2", - "prosemirror-view": "^1.33.8" - } - }, - "node_modules/prosemirror-transform": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.11.0.tgz", - "integrity": "sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw==", - "license": "MIT", - "dependencies": { - "prosemirror-model": "^1.21.0" - } - }, - "node_modules/prosemirror-view": { - "version": "1.41.5", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.5.tgz", - "integrity": "sha512-UDQbIPnDrjE8tqUBbPmCOZgtd75htE6W3r0JCmY9bL6W1iemDM37MZEKC49d+tdQ0v/CKx4gjxLoLsfkD2NiZA==", - "license": "MIT", - "dependencies": { - "prosemirror-model": "^1.20.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", - "license": "MIT", - "dependencies": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "license": "MIT", - "optional": true, - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/rc9": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", - "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "destr": "^2.0.3" - } - }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-day-picker": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.13.0.tgz", - "integrity": "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ==", - "license": "MIT", - "dependencies": { - "@date-fns/tz": "^1.4.1", - "date-fns": "^4.1.0", - "date-fns-jalali": "^4.1.0-0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/gpbl" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.4" - } - }, - "node_modules/react-easy-crop": { - "version": "5.5.6", - "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.5.6.tgz", - "integrity": "sha512-Jw3/ozs8uXj3NpL511Suc4AHY+mLRO23rUgipXvNYKqezcFSYHxe4QXibBymkOoY6oOtLVMPO2HNPRHYvMPyTw==", - "license": "MIT", - "dependencies": { - "normalize-wheel": "^1.0.1", - "tslib": "^2.0.1" - }, - "peerDependencies": { - "react": ">=16.4.0", - "react-dom": ">=16.4.0" - } - }, - "node_modules/react-hook-form": { - "version": "7.71.1", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz", - "integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/react-hook-form" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18 || ^19" - } - }, - "node_modules/react-icons": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", - "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", - "license": "MIT", - "peerDependencies": { - "react": "*" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, - "node_modules/react-leaflet": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz", - "integrity": "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==", - "license": "Hippocratic-2.1", - "dependencies": { - "@react-leaflet/core": "^3.0.0" - }, - "peerDependencies": { - "leaflet": "^1.9.0", - "react": "^19.0.0", - "react-dom": "^19.0.0" - } - }, - "node_modules/react-number-format": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz", - "integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==", - "license": "MIT", - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/react-phone-number-input": { - "version": "3.4.14", - "resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.14.tgz", - "integrity": "sha512-T9MziNuvthzv6+JAhKD71ab/jVXW5U20nQZRBJd6+q+ujmkC+/ISOf2GYo8pIi4VGjdIYRIHDftMAYn3WKZT3w==", - "license": "MIT", - "dependencies": { - "classnames": "^2.5.1", - "country-flag-icons": "^1.5.17", - "input-format": "^0.3.14", - "libphonenumber-js": "^1.12.27", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/react-redux": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", - "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "license": "MIT", - "dependencies": { - "@types/use-sync-external-store": "^0.0.6", - "use-sync-external-store": "^1.4.0" - }, - "peerDependencies": { - "@types/react": "^18.2.25 || ^19", - "react": "^18.0 || ^19", - "redux": "^5.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "redux": { - "optional": true - } - } - }, - "node_modules/react-remove-scroll": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", - "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", - "license": "MIT", - "dependencies": { - "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-remove-scroll-bar": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", - "license": "MIT", - "dependencies": { - "react-style-singleton": "^2.2.2", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-style-singleton": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", - "license": "MIT", - "dependencies": { - "get-nonce": "^1.0.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-textarea-autosize": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", - "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.20.13", - "use-composed-ref": "^1.3.0", - "use-latest": "^1.2.1" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/recharts": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz", - "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==", - "license": "MIT", - "workspaces": [ - "www" - ], - "dependencies": { - "@reduxjs/toolkit": "1.x.x || 2.x.x", - "clsx": "^2.1.1", - "decimal.js-light": "^2.5.1", - "es-toolkit": "^1.39.3", - "eventemitter3": "^5.0.1", - "immer": "^10.1.1", - "react-redux": "8.x.x || 9.x.x", - "reselect": "5.1.1", - "tiny-invariant": "^1.3.3", - "use-sync-external-store": "^1.2.2", - "victory-vendor": "^37.0.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/redux": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" - }, - "node_modules/redux-thunk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", - "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", - "license": "MIT", - "peerDependencies": { - "redux": "^5.0.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT", - "optional": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rehype-format": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", - "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-format": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-minify-whitespace": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", - "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-minify-whitespace": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-parse": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", - "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-html": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-remark": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-10.0.1.tgz", - "integrity": "sha512-EmDndlb5NVwXGfUa4c9GPK+lXeItTilLhE6ADSaQuHr4JUlKw9MidzGzx4HpqZrNCt6vnHmEifXQiiA+CEnjYQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "hast-util-to-mdast": "^10.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-stringify": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", - "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-to-html": "^9.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-gfm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/reselect": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rgbcolor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", - "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", - "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", - "optional": true, - "engines": { - "node": ">= 0.8.15" - } - }, - "node_modules/rollup": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", - "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.0", - "@rollup/rollup-android-arm64": "4.57.0", - "@rollup/rollup-darwin-arm64": "4.57.0", - "@rollup/rollup-darwin-x64": "4.57.0", - "@rollup/rollup-freebsd-arm64": "4.57.0", - "@rollup/rollup-freebsd-x64": "4.57.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", - "@rollup/rollup-linux-arm-musleabihf": "4.57.0", - "@rollup/rollup-linux-arm64-gnu": "4.57.0", - "@rollup/rollup-linux-arm64-musl": "4.57.0", - "@rollup/rollup-linux-loong64-gnu": "4.57.0", - "@rollup/rollup-linux-loong64-musl": "4.57.0", - "@rollup/rollup-linux-ppc64-gnu": "4.57.0", - "@rollup/rollup-linux-ppc64-musl": "4.57.0", - "@rollup/rollup-linux-riscv64-gnu": "4.57.0", - "@rollup/rollup-linux-riscv64-musl": "4.57.0", - "@rollup/rollup-linux-s390x-gnu": "4.57.0", - "@rollup/rollup-linux-x64-gnu": "4.57.0", - "@rollup/rollup-linux-x64-musl": "4.57.0", - "@rollup/rollup-openbsd-x64": "4.57.0", - "@rollup/rollup-openharmony-arm64": "4.57.0", - "@rollup/rollup-win32-arm64-msvc": "4.57.0", - "@rollup/rollup-win32-ia32-msvc": "4.57.0", - "@rollup/rollup-win32-x64-gnu": "4.57.0", - "@rollup/rollup-win32-x64-msvc": "4.57.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/rope-sequence": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", - "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", - "license": "MIT" - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=11.0.0" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "devOptional": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/sonner": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", - "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", - "license": "MIT", - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", - "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/stable-hash": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", - "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/stackblur-canvas": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", - "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.14" - } - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/stream-chain": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", - "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", - "license": "BSD-3-Clause" - }, - "node_modules/stream-json": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", - "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", - "license": "BSD-3-Clause", - "dependencies": { - "stream-chain": "^2.2.5" - } - }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", - "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/styled-jsx": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", - "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/superjson": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", - "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", - "license": "MIT", - "dependencies": { - "copy-anything": "^4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-pathdata": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", - "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/tabbable": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", - "license": "MIT" - }, - "node_modules/tailwind-merge": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", - "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/tailwindcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT" - }, - "node_modules/tailwindcss-animate": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", - "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" - } - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", - "license": "MIT", - "dependencies": { - "utrie": "^1.0.2" - } - }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "license": "MIT", - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trim-trailing-lines": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", - "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/tsx/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "license": "MIT" - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "license": "MIT" - }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", - "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-composed-ref": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", - "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-debounce": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.1.0.tgz", - "integrity": "sha512-lu87Za35V3n/MyMoEpD5zJv0k7hCn0p+V/fK2kWD+3k2u3kOCwO593UArbczg1fhfs2rqPEnHpULJ3KmGdDzvg==", - "license": "MIT", - "engines": { - "node": ">= 16.0.0" - }, - "peerDependencies": { - "react": "*" - } - }, - "node_modules/use-isomorphic-layout-effect": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", - "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-latest": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", - "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", - "license": "MIT", - "dependencies": { - "use-isomorphic-layout-effect": "^1.1.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "license": "MIT", - "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", - "license": "MIT", - "dependencies": { - "base64-arraybuffer": "^1.0.2" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/victory-vendor": { - "version": "37.3.6", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", - "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", - "license": "MIT AND ISC", - "dependencies": { - "@types/d3-array": "^3.0.3", - "@types/d3-ease": "^3.0.0", - "@types/d3-interpolate": "^3.0.1", - "@types/d3-scale": "^4.0.2", - "@types/d3-shape": "^3.1.0", - "@types/d3-time": "^3.0.0", - "@types/d3-timer": "^3.0.0", - "d3-array": "^3.1.6", - "d3-ease": "^3.0.1", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.1.0", - "d3-time": "^3.0.0", - "d3-timer": "^3.0.1" - } - }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "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 - } - } - }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^3.10.0", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "license": "MIT" - }, - "node_modules/web-encoding": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", - "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", - "license": "MIT", - "dependencies": { - "util": "^0.12.3" - }, - "optionalDependencies": { - "@zxing/text-encoding": "0.9.0" - } - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xml2js/node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/y-prosemirror": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/y-prosemirror/-/y-prosemirror-1.3.7.tgz", - "integrity": "sha512-NpM99WSdD4Fx4if5xOMDpPtU3oAmTSjlzh5U4353ABbRHl1HtAFUx6HlebLZfyFxXN9jzKMDkVbcRjqOZVkYQg==", - "license": "MIT", - "dependencies": { - "lib0": "^0.2.109" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - }, - "peerDependencies": { - "prosemirror-model": "^1.7.1", - "prosemirror-state": "^1.2.3", - "prosemirror-view": "^1.9.10", - "y-protocols": "^1.0.1", - "yjs": "^13.5.38" - } - }, - "node_modules/y-protocols": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz", - "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==", - "license": "MIT", - "dependencies": { - "lib0": "^0.2.85" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - }, - "peerDependencies": { - "yjs": "^13.0.0" - } - }, - "node_modules/yjs": { - "version": "13.6.29", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.29.tgz", - "integrity": "sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ==", - "license": "MIT", - "dependencies": { - "lib0": "^0.2.99" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} +{ + "name": "mopc-platform", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mopc-platform", + "version": "0.1.0", + "dependencies": { + "@auth/prisma-adapter": "^2.7.4", + "@blocknote/core": "^0.46.2", + "@blocknote/mantine": "^0.46.2", + "@blocknote/react": "^0.46.2", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@hookform/resolvers": "^3.9.1", + "@mantine/core": "^8.3.13", + "@mantine/hooks": "^8.3.13", + "@notionhq/client": "^2.3.0", + "@prisma/client": "^6.19.2", + "@radix-ui/react-alert-dialog": "^1.1.4", + "@radix-ui/react-avatar": "^1.1.2", + "@radix-ui/react-checkbox": "^1.1.3", + "@radix-ui/react-collapsible": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-dropdown-menu": "^2.1.4", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-popover": "^1.1.4", + "@radix-ui/react-progress": "^1.1.1", + "@radix-ui/react-radio-group": "^1.2.2", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.1.4", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-slider": "^1.2.2", + "@radix-ui/react-slot": "^1.1.1", + "@radix-ui/react-switch": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.2", + "@radix-ui/react-tooltip": "^1.1.6", + "@tailwindcss/postcss": "^4.1.18", + "@tanstack/react-query": "^5.62.0", + "@trpc/client": "^11.0.0-rc.678", + "@trpc/react-query": "^11.0.0-rc.678", + "@trpc/server": "^11.0.0-rc.678", + "bcryptjs": "^3.0.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.0.4", + "csv-parse": "^6.1.0", + "date-fns": "^4.1.0", + "html2canvas": "^1.4.1", + "jspdf": "^4.1.0", + "jspdf-autotable": "^5.0.7", + "leaflet": "^1.9.4", + "lucide-react": "^0.563.0", + "minio": "^8.0.2", + "motion": "^11.15.0", + "next": "^15.1.0", + "next-auth": "^5.0.0-beta.25", + "next-themes": "^0.4.6", + "nodemailer": "^7.0.7", + "openai": "^6.16.0", + "papaparse": "^5.4.1", + "react": "^19.0.0", + "react-day-picker": "^9.13.0", + "react-dom": "^19.0.0", + "react-easy-crop": "^5.5.6", + "react-hook-form": "^7.54.2", + "react-leaflet": "^5.0.0", + "react-phone-number-input": "^3.4.14", + "recharts": "^3.7.0", + "sonner": "^2.0.7", + "superjson": "^2.2.2", + "tailwind-merge": "^3.4.0", + "use-debounce": "^10.0.4", + "zod": "^3.24.1" + }, + "devDependencies": { + "@playwright/test": "^1.49.1", + "@types/bcryptjs": "^2.4.6", + "@types/leaflet": "^1.9.21", + "@types/node": "^25.0.10", + "@types/nodemailer": "^7.0.9", + "@types/papaparse": "^5.3.15", + "@types/react": "^19.0.2", + "@types/react-dom": "^19.0.2", + "eslint": "^9.17.0", + "eslint-config-next": "^15.1.0", + "postcss": "^8.4.49", + "prettier": "^3.4.2", + "prettier-plugin-tailwindcss": "^0.7.2", + "prisma": "^6.19.2", + "tailwindcss": "^4.1.18", + "tailwindcss-animate": "^1.0.7", + "tsx": "^4.19.2", + "typescript": "^5.7.2", + "vitest": "^4.0.18" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@auth/core": { + "version": "0.41.1", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.41.1.tgz", + "integrity": "sha512-t9cJ2zNYAdWMacGRMT6+r4xr1uybIdmYa49calBPeTqwgAFPV/88ac9TEvCR85pvATiSPt8VaNf+Gt24JIT/uw==", + "license": "ISC", + "dependencies": { + "@panva/hkdf": "^1.2.1", + "jose": "^6.0.6", + "oauth4webapi": "^3.3.0", + "preact": "10.24.3", + "preact-render-to-string": "6.5.11" + }, + "peerDependencies": { + "@simplewebauthn/browser": "^9.0.1", + "@simplewebauthn/server": "^9.0.2", + "nodemailer": "^7.0.7" + }, + "peerDependenciesMeta": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/@auth/prisma-adapter": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@auth/prisma-adapter/-/prisma-adapter-2.11.1.tgz", + "integrity": "sha512-Ke7DXP0Fy0Mlmjz/ZJLXwQash2UkA4621xCM0rMtEczr1kppLc/njCbUkHkIQ/PnmILjqSPEKeTjDPsYruvkug==", + "license": "ISC", + "dependencies": { + "@auth/core": "0.41.1" + }, + "peerDependencies": { + "@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5 || >=6" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@blocknote/core": { + "version": "0.46.2", + "resolved": "https://registry.npmjs.org/@blocknote/core/-/core-0.46.2.tgz", + "integrity": "sha512-p+QFwrTQfQC08f7JoFg9uuwbAUkGhRakCXhHhY63Wd8ARS0ktHfc9eUnJderXQTEtWfHjACjZOyt2FifX6Lalw==", + "license": "MPL-2.0", + "dependencies": { + "@emoji-mart/data": "^1.2.1", + "@handlewithcare/prosemirror-inputrules": "^0.1.4", + "@shikijs/types": "^3", + "@tanstack/store": "^0.7.7", + "@tiptap/core": "^3.13.0", + "@tiptap/extension-bold": "^3.13.0", + "@tiptap/extension-code": "^3.13.0", + "@tiptap/extension-horizontal-rule": "^3.13.0", + "@tiptap/extension-italic": "^3.13.0", + "@tiptap/extension-link": "^3.13.0", + "@tiptap/extension-paragraph": "^3.13.0", + "@tiptap/extension-strike": "^3.13.0", + "@tiptap/extension-text": "^3.13.0", + "@tiptap/extension-underline": "^3.13.0", + "@tiptap/extensions": "^3.13.0", + "@tiptap/pm": "^3.13.0", + "emoji-mart": "^5.6.0", + "fast-deep-equal": "^3.1.3", + "hast-util-from-dom": "^5.0.1", + "prosemirror-dropcursor": "^1.8.2", + "prosemirror-highlight": "^0.13.0", + "prosemirror-model": "^1.25.4", + "prosemirror-state": "^1.4.4", + "prosemirror-tables": "^1.8.3", + "prosemirror-transform": "^1.10.5", + "prosemirror-view": "^1.41.4", + "rehype-format": "^5.0.1", + "rehype-parse": "^9.0.1", + "rehype-remark": "^10.0.1", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-stringify": "^11.0.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.0.0", + "uuid": "^8.3.2", + "y-prosemirror": "^1.3.7", + "y-protocols": "^1.0.6", + "yjs": "^13.6.27" + }, + "peerDependencies": { + "@hocuspocus/provider": "^2.15.2 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@hocuspocus/provider": { + "optional": true + } + } + }, + "node_modules/@blocknote/mantine": { + "version": "0.46.2", + "resolved": "https://registry.npmjs.org/@blocknote/mantine/-/mantine-0.46.2.tgz", + "integrity": "sha512-2/A82VIby8NNuQbJrXZURnGsksVMWiGWtUOfhvaawCTiB2thYDOV1XONFF1G4xZ2UreodOKLUTwhLm3u25lGrw==", + "license": "MPL-2.0", + "dependencies": { + "@blocknote/core": "0.46.2", + "@blocknote/react": "0.46.2", + "react-icons": "^5.5.0" + }, + "peerDependencies": { + "@mantine/core": "^8.3.11", + "@mantine/hooks": "^8.3.11", + "@mantine/utils": "^6.0.22", + "react": "^18.0 || ^19.0 || >= 19.0.0-rc", + "react-dom": "^18.0 || ^19.0 || >= 19.0.0-rc" + } + }, + "node_modules/@blocknote/react": { + "version": "0.46.2", + "resolved": "https://registry.npmjs.org/@blocknote/react/-/react-0.46.2.tgz", + "integrity": "sha512-2cl7MkOSa6Wxun5LFTT0BCeYq3Qw9DCw6VZ9qdtflrnsefds0cDx/SHMVEQygYwF5MhlDmSbIt61hkQ4j2QWSw==", + "license": "MPL-2.0", + "dependencies": { + "@blocknote/core": "0.46.2", + "@emoji-mart/data": "^1.2.1", + "@floating-ui/react": "^0.27.16", + "@floating-ui/utils": "0.2.10", + "@tanstack/react-store": "0.7.7", + "@tiptap/core": "^3.13.0", + "@tiptap/pm": "^3.13.0", + "@tiptap/react": "^3.13.0", + "@types/use-sync-external-store": "1.5.0", + "emoji-mart": "^5.6.0", + "fast-deep-equal": "^3.1.3", + "lodash.merge": "^4.6.2", + "react-icons": "^5.5.0", + "use-sync-external-store": "1.6.0" + }, + "peerDependencies": { + "react": "^18.0 || ^19.0 || >= 19.0.0-rc", + "react-dom": "^18.0 || ^19.0 || >= 19.0.0-rc" + } + }, + "node_modules/@blocknote/react/node_modules/@types/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-5dyB8nLC/qogMrlCizZnYWQTA4lnb/v+It+sqNl5YnSRAPMlIqY/X0Xn+gZw8vOL+TgTTr28VEbn3uf8fUtAkw==", + "license": "MIT" + }, + "node_modules/@date-fns/tz": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz", + "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==", + "license": "MIT" + }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "license": "MIT", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.1", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emoji-mart/data": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", + "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", + "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.4", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.17", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.17.tgz", + "integrity": "sha512-LGVZKHwmWGg6MRHjLLgsfyaX2y2aCNgnD1zT/E6B+/h+vxg+nIJUqHPAlTzsHDyqdgEpJ1Np5kxWuFEErXzoGg==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.7", + "@floating-ui/utils": "^0.2.10", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz", + "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.5" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@handlewithcare/prosemirror-inputrules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@handlewithcare/prosemirror-inputrules/-/prosemirror-inputrules-0.1.4.tgz", + "integrity": "sha512-GMqlBeG2MKM+tXEFd2N+wIv5z4VvJTg8JtfJUrdjvFq2W6v+AW8oTgiWyFw8L3iEQwvtQcVJxU873iB0LXUNNw==", + "license": "MIT", + "dependencies": { + "prosemirror-history": "^1.4.1", + "prosemirror-transform": "^1.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/@hookform/resolvers": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", + "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", + "license": "MIT", + "peerDependencies": { + "react-hook-form": "^7.0.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mantine/core": { + "version": "8.3.13", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.13.tgz", + "integrity": "sha512-ZgW4vqN4meaPyIMxzAufBvsgmJRfYZdTpsrAOcS8pWy7m9e8i685E7XsAxnwJCOIHudpvpvt+7Bx7VaIjEsYEw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.27.16", + "clsx": "^2.1.1", + "react-number-format": "^5.4.4", + "react-remove-scroll": "^2.7.1", + "react-textarea-autosize": "8.5.9", + "type-fest": "^4.41.0" + }, + "peerDependencies": { + "@mantine/hooks": "8.3.13", + "react": "^18.x || ^19.x", + "react-dom": "^18.x || ^19.x" + } + }, + "node_modules/@mantine/hooks": { + "version": "8.3.13", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.13.tgz", + "integrity": "sha512-7YMbMW/tR9E8m/9DbBW01+3RNApm2mE/JbRKXf9s9+KxgbjQvq0FYGWV8Y4+Sjz48AO4vtWk2qBriUTgBMKAyg==", + "license": "MIT", + "peerDependencies": { + "react": "^18.x || ^19.x" + } + }, + "node_modules/@mantine/utils": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-6.0.22.tgz", + "integrity": "sha512-RSKlNZvxhMCkOFZ6slbYvZYbWjHUM+PxDQnupIOxIdsTZQQjx/BFfrfJ7kQFOP+g7MtpOds8weAetEs5obwMOQ==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.10.tgz", + "integrity": "sha512-plg+9A/KoZcTS26fe15LHg+QxReTazrIOoKKUC3Uz4leGGeNPgLHdevVraAAOX0snnUs3WkRx3eUQpj9mreG6A==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.10.tgz", + "integrity": "sha512-fDpxcy6G7Il4lQVVsaJD0fdC2/+SmuBGTF+edRLlsR4ZFOE3W2VyzrrGYdg/pHW8TydeAdSVM+mIzITGtZ3yWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz", + "integrity": "sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz", + "integrity": "sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz", + "integrity": "sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz", + "integrity": "sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz", + "integrity": "sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz", + "integrity": "sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz", + "integrity": "sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz", + "integrity": "sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@notionhq/client": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@notionhq/client/-/client-2.3.0.tgz", + "integrity": "sha512-l7WqTCpQqC+HibkB9chghONQTYcxNQT0/rOJemBfmuKQRTu2vuV8B3yA395iKaUdDo7HI+0KvQaz9687Xskzkw==", + "license": "MIT", + "dependencies": { + "@types/node-fetch": "^2.5.10", + "node-fetch": "^2.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@panva/hkdf": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", + "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/@playwright/test": { + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.0.tgz", + "integrity": "sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.58.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@prisma/client": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.2.tgz", + "integrity": "sha512-gR2EMvfK/aTxsuooaDA32D8v+us/8AAet+C3J1cc04SW35FPdZYgLF+iN4NDLUgAaUGTKdAB0CYenu1TAgGdMg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", + "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.18.4", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", + "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/fetch-engine": "6.19.2", + "@prisma/get-platform": "6.19.2" + } + }, + "node_modules/@prisma/engines-version": { + "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", + "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", + "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/get-platform": "6.19.2" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.2.tgz", + "integrity": "sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.2" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz", + "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", + "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@react-leaflet/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz", + "integrity": "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==", + "license": "Hippocratic-2.1", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", + "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.3.tgz", + "integrity": "sha512-6jQTc5z0KJFtr1UgFpIL3N9XSC3saRaI9PwWtzM2pSqkNGtiNkYY2OSwkOGDK2XcTRcLb1pi/aNkKZz0nxVH4Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz", + "integrity": "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz", + "integrity": "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz", + "integrity": "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz", + "integrity": "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz", + "integrity": "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz", + "integrity": "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz", + "integrity": "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz", + "integrity": "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz", + "integrity": "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz", + "integrity": "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz", + "integrity": "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz", + "integrity": "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz", + "integrity": "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz", + "integrity": "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz", + "integrity": "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz", + "integrity": "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz", + "integrity": "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz", + "integrity": "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz", + "integrity": "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz", + "integrity": "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz", + "integrity": "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz", + "integrity": "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz", + "integrity": "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz", + "integrity": "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz", + "integrity": "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", + "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@shikijs/types": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.21.0.tgz", + "integrity": "sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.18" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.0", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", + "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "postcss": "^8.4.41", + "tailwindcss": "4.1.18" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.90.20", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz", + "integrity": "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.90.20", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.20.tgz", + "integrity": "sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.90.20" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-store": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.7.7.tgz", + "integrity": "sha512-qqT0ufegFRDGSof9D/VqaZgjNgp4tRPHZIJq2+QIHkMUtHjaJ0lYrrXjeIUJvjnTbgPfSD1XgOMEt0lmANn6Zg==", + "license": "MIT", + "dependencies": { + "@tanstack/store": "0.7.7", + "use-sync-external-store": "^1.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/store": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.7.tgz", + "integrity": "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tiptap/core": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.18.0.tgz", + "integrity": "sha512-Gczd4GbK1DNgy/QUPElMVozoa0GW9mW8E31VIi7Q4a9PHHz8PcrxPmuWwtJ2q0PF8MWpOSLuBXoQTWaXZRPRnQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.18.0.tgz", + "integrity": "sha512-xUgOvHCdGXh9Lfxd7DtgsSr0T/egIwBllWHIBWDjQEQQ0b+ICn+0+i703btHMB4hjdduZtgVDrhK8jAW3U6swA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.18.0.tgz", + "integrity": "sha512-9kYG1fVYQcA3Kp5Bq96lrKCp9oLpQqceDsK688r7iT1yymQlBPMunaqaqb5ZLQGhnNYbhfG+8xcQsvEKjklErA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0", + "@tiptap/pm": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.18.0.tgz", + "integrity": "sha512-0SU53O0NRmdtRM2Hgzm372dVoHjs2F40o/dtB7ls4kocf4W89FyWeC2R6ZsFQqcXisNh9RTzLtYfbNyizGuZIw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.18.0.tgz", + "integrity": "sha512-a2cBQi0I/X0o3a9b+adwJvkdxLzQzJIkP9dc/v25qGTSCjC1+ycois5WQOn8T4T8t4g/fAH1UOXEWnkWyTxLIg==", + "license": "MIT", + "optional": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@floating-ui/dom": "^1.0.0", + "@tiptap/core": "^3.18.0", + "@tiptap/pm": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.18.0.tgz", + "integrity": "sha512-fEq7DwwQZ496RHNbMQypBVNqoWnhDEERbzWMBqlmfCfc/0FvJrHtsQkk3k4lgqMYqmBwym3Wp0SrRYiyKCPGTw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0", + "@tiptap/pm": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.18.0.tgz", + "integrity": "sha512-1C4nB08psiRo0BPxAbpYq8peUOKnjQWtBCLPbE6B9ToTK3vmUk0AZTqLO11FvokuM1GF5l2Lg3sKrKFuC2hcjQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-link": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.18.0.tgz", + "integrity": "sha512-1J28C4+fKAMQi7q/UsTjAmgmKTnzjExXY98hEBneiVzFDxqF69n7+Vb7nVTNAIhmmJkZMA0DEcMhSiQC/1/u4A==", + "license": "MIT", + "dependencies": { + "linkifyjs": "^4.3.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0", + "@tiptap/pm": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.18.0.tgz", + "integrity": "sha512-uvFhdwiur4NhhUdBmDsajxjGAIlg5qga55fYag2DzOXxIQE2M7/aVMRkRpuJzb88GY4EHSh8rY34HgMK2FJt2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.18.0.tgz", + "integrity": "sha512-kl/fa68LZg8NWUqTkRTfgyCx+IGqozBmzJxQDc1zxurrIU+VFptDV9UuZim587sbM2KGjCi/PNPjPGk1Uu0PVg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.18.0.tgz", + "integrity": "sha512-9TvctdnBCwK/zyTi9kS7nGFNl5OvGM8xE0u38ZmQw5t79JOqJHgOroyqMjw8LHK/1PWrozfNCmsZbpq4IZuKXw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extension-underline": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.18.0.tgz", + "integrity": "sha512-009IeXURNJ/sm1pBqbj+2YQgjQaBtNlJR3dbl6xu49C+qExqCmI7klhKQuwsVVGLR7ahsYlp7d9RlftnhCXIcQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0" + } + }, + "node_modules/@tiptap/extensions": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.18.0.tgz", + "integrity": "sha512-uSRIE9HGshBN6NRFR3LX2lZqBLvX92SgU5A9AvUbJD4MqU63E+HdruJnRjsVlX3kPrmbIDowxrzXlUcg3K0USQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0", + "@tiptap/pm": "^3.18.0" + } + }, + "node_modules/@tiptap/pm": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.18.0.tgz", + "integrity": "sha512-8RoI5gW0xBVCsuxahpK8vx7onAw6k2/uR3hbGBBnH+HocDMaAZKot3nTyY546ij8ospIC1mnQ7k4BhVUZesZDQ==", + "license": "MIT", + "dependencies": { + "prosemirror-changeset": "^2.3.0", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.24.1", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.5.0", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.4", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.38.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/react": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.18.0.tgz", + "integrity": "sha512-VC20YhoiWe2E03D1BRH+AVMgXeA7li+bzIoaBtpK9+AdizAC+TvWCb2I/9mQCy9m31zGYTD0vv0e7bVlJi+aKA==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "fast-equals": "^5.3.3", + "use-sync-external-store": "^1.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "optionalDependencies": { + "@tiptap/extension-bubble-menu": "^3.18.0", + "@tiptap/extension-floating-menu": "^3.18.0" + }, + "peerDependencies": { + "@tiptap/core": "^3.18.0", + "@tiptap/pm": "^3.18.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@trpc/client": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/@trpc/client/-/client-11.9.0.tgz", + "integrity": "sha512-3r4RT/GbR263QO+2gCPyrs5fEYaXua3/AzCs+GbWC09X0F+mVkyBpO3GRSDObiNU/N1YB597U7WGW3WA1d1TVw==", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "@trpc/server": "11.9.0", + "typescript": ">=5.7.2" + } + }, + "node_modules/@trpc/react-query": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-11.9.0.tgz", + "integrity": "sha512-9Gpj06ZcfsA77PB5A8VC2MFS/E7pPvoNqaSlSrAgLyRsKqy0gldFOW2RMKura69M6fwtgjg9+4i2+rOHKT7qLw==", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "@tanstack/react-query": "^5.80.3", + "@trpc/client": "11.9.0", + "@trpc/server": "11.9.0", + "react": ">=18.2.0", + "react-dom": ">=18.2.0", + "typescript": ">=5.7.2" + } + }, + "node_modules/@trpc/server": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/@trpc/server/-/server-11.9.0.tgz", + "integrity": "sha512-T8gC4NOCzx8tCsQEQ5sSjf24bN+9AEqXZRfpThG+YCEmcEwXfS7RP8VVrl5Vodt1S+zGEDyQSof4YVAj1zq/mg==", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "typescript": ">=5.7.2" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/leaflet": { + "version": "1.9.21", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", + "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", + "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.4" + } + }, + "node_modules/@types/nodemailer": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.9.tgz", + "integrity": "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", + "license": "MIT" + }, + "node_modules/@types/papaparse": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", + "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/react": { + "version": "19.2.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz", + "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", + "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/type-utils": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.54.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz", + "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", + "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.54.0", + "@typescript-eslint/types": "^8.54.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", + "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", + "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz", + "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", + "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", + "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.54.0", + "@typescript-eslint/tsconfig-utils": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", + "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", + "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitest/expect": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.18", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.18", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "license": "(Unlicense OR Apache-2.0)", + "optional": true + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz", + "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/bcryptjs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", + "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==", + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } + }, + "node_modules/block-stream2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", + "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", + "license": "MIT", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-or-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", + "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==", + "license": "MIT" + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001766", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvg": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", + "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cmdk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-id": "^1.1.0", + "@radix-ui/react-primitive": "^2.0.2" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz", + "integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/country-flag-icons": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.6.12.tgz", + "integrity": "sha512-tWxbBylam6Fkkg0nu+112jmny4WomHXgmdTQFobs/+evTyizSc06bCp//HAh4W1i+g1m06uqlbPuyLC5mrimkQ==", + "license": "MIT" + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/csv-parse": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-6.1.0.tgz", + "integrity": "sha512-CEE+jwpgLn+MmtCpVcPtiCZpVtB6Z2OKPTr34pycYYoL7sxdOkXDdQ4lRiw6ioC0q6BLqhc6cKweCVvral8yhw==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-jalali": { + "version": "4.1.0-0", + "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", + "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/effect": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", + "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/emoji-mart": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", + "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz", + "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.1", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-toolkit": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.44.0.tgz", + "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.10.tgz", + "integrity": "sha512-AeYOVGiSbIfH4KXFT3d0fIDm7yTslR/AWGoHLdsXQ99MH0zFWmkRIin1H7I9SFlkKgf4PKm9ncsyWHq1aAfHBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "15.5.10", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-png": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz", + "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==", + "license": "MIT", + "dependencies": { + "@types/pako": "^2.0.3", + "iobuffer": "^5.3.2", + "pako": "^2.1.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.1.1" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/framer-motion": { + "version": "11.18.2", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", + "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", + "license": "MIT", + "dependencies": { + "motion-dom": "^11.18.1", + "motion-utils": "^11.18.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", + "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "html-whitespace-sensitive-tag-names": "^3.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-dom": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", + "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", + "license": "ISC", + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^9.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-mdast": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.2.tgz", + "integrity": "sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "hast-util-to-text": "^4.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-minify-whitespace": "^6.0.0", + "trim-trailing-lines": "^2.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-whitespace-sensitive-tag-names": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", + "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/input-format": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/input-format/-/input-format-0.3.14.tgz", + "integrity": "sha512-gHMrgrbCgmT4uK5Um5eVDUohuV9lcs95ZUUN9Px2Y0VIfjTzT2wF8Q3Z4fwLFm7c5Z2OXCm53FHoovj6SlOKdg==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">=18.1.0", + "react-dom": ">=18.1.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/iobuffer": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz", + "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==", + "license": "MIT" + }, + "node_modules/ipaddr.js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "license": "MIT", + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jose": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", + "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jspdf": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.1.0.tgz", + "integrity": "sha512-xd1d/XRkwqnsq6FP3zH1Q+Ejqn2ULIJeDZ+FTKpaabVpZREjsJKRJwuokTNgdqOU+fl55KgbvgZ1pRTSWCP2kQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "fast-png": "^6.2.0", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.11", + "core-js": "^3.6.0", + "dompurify": "^3.3.1", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jspdf-autotable": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-5.0.7.tgz", + "integrity": "sha512-2wr7H6liNDBYNwt25hMQwXkEWFOEopgKIvR1Eukuw6Zmprm/ZcnmLTQEjW7Xx3FCbD3v7pflLcnMAv/h1jFDQw==", + "license": "MIT", + "peerDependencies": { + "jspdf": "^2 || ^3 || ^4" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lib0": { + "version": "0.2.117", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", + "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.12.35", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.35.tgz", + "integrity": "sha512-T/Cz6iLcsZdb5jDncDcUNhSAJ0VlSC9TnsqtBNdpkaAmy24/R1RhErtNWVWBrcUZKs9hSgaVsBkc7HxYnazIfw==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/linkifyjs": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", + "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lucide-react": { + "version": "0.563.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.563.0.tgz", + "integrity": "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minio": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.6.tgz", + "integrity": "sha512-sOeh2/b/XprRmEtYsnNRFtOqNRTPDvYtMWh+spWlfsuCV/+IdxNeKVUMKLqI7b5Dr07ZqCPuaRGU/rB9pZYVdQ==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.4", + "block-stream2": "^2.1.0", + "browser-or-node": "^2.1.1", + "buffer-crc32": "^1.0.0", + "eventemitter3": "^5.0.1", + "fast-xml-parser": "^4.4.1", + "ipaddr.js": "^2.0.1", + "lodash": "^4.17.21", + "mime-types": "^2.1.35", + "query-string": "^7.1.3", + "stream-json": "^1.8.0", + "through2": "^4.0.2", + "web-encoding": "^1.1.5", + "xml2js": "^0.5.0 || ^0.6.2" + }, + "engines": { + "node": "^16 || ^18 || >=20" + } + }, + "node_modules/motion": { + "version": "11.18.2", + "resolved": "https://registry.npmjs.org/motion/-/motion-11.18.2.tgz", + "integrity": "sha512-JLjvFDuFr42NFtcVoMAyC2sEjnpA8xpy6qWPyzQvCloznAyQ8FIXioxWfHiLtgYhoVpfUqSWpn1h9++skj9+Wg==", + "license": "MIT", + "dependencies": { + "framer-motion": "^11.18.2", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", + "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", + "license": "MIT", + "dependencies": { + "motion-utils": "^11.18.1" + } + }, + "node_modules/motion-utils": { + "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", + "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.10.tgz", + "integrity": "sha512-r0X65PNwyDDyOrWNKpQoZvOatw7BcsTPRKdwEqtc9cj3wv7mbBIk9tKed4klRaFXJdX0rugpuMTHslDrAU1bBg==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.10", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.7", + "@next/swc-darwin-x64": "15.5.7", + "@next/swc-linux-arm64-gnu": "15.5.7", + "@next/swc-linux-arm64-musl": "15.5.7", + "@next/swc-linux-x64-gnu": "15.5.7", + "@next/swc-linux-x64-musl": "15.5.7", + "@next/swc-win32-arm64-msvc": "15.5.7", + "@next/swc-win32-x64-msvc": "15.5.7", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-auth": { + "version": "5.0.0-beta.30", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.30.tgz", + "integrity": "sha512-+c51gquM3F6nMVmoAusRJ7RIoY0K4Ts9HCCwyy/BRoe4mp3msZpOzYMyb5LAYc1wSo74PMQkGDcaghIO7W6Xjg==", + "license": "ISC", + "dependencies": { + "@auth/core": "0.41.0" + }, + "peerDependencies": { + "@simplewebauthn/browser": "^9.0.1", + "@simplewebauthn/server": "^9.0.2", + "next": "^14.0.0-0 || ^15.0.0 || ^16.0.0", + "nodemailer": "^7.0.7", + "react": "^18.2.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/next-auth/node_modules/@auth/core": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.41.0.tgz", + "integrity": "sha512-Wd7mHPQ/8zy6Qj7f4T46vg3aoor8fskJm6g2Zyj064oQ3+p0xNZXAV60ww0hY+MbTesfu29kK14Zk5d5JTazXQ==", + "license": "ISC", + "dependencies": { + "@panva/hkdf": "^1.2.1", + "jose": "^6.0.6", + "oauth4webapi": "^3.3.0", + "preact": "10.24.3", + "preact-render-to-string": "6.5.11" + }, + "peerDependencies": { + "@simplewebauthn/browser": "^9.0.1", + "@simplewebauthn/server": "^9.0.2", + "nodemailer": "^6.8.0" + }, + "peerDependenciesMeta": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/nodemailer": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", + "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz", + "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==", + "license": "BSD-3-Clause" + }, + "node_modules/nypm": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.4.tgz", + "integrity": "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.2.0", + "pathe": "^2.0.3", + "tinyexec": "^1.0.2" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/nypm/node_modules/citty": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.0.tgz", + "integrity": "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/oauth4webapi": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.3.tgz", + "integrity": "sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/openai": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.16.0.tgz", + "integrity": "sha512-fZ1uBqjFUjXzbGc35fFtYKEOxd20kd9fDpFeqWtsOZWiubY8CZ1NAlXHW3iathaFvqmNtCWMIsosCuyeI7Joxg==", + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "license": "MIT" + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/papaparse": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.3.tgz", + "integrity": "sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==", + "license": "MIT" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT", + "optional": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/playwright": { + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.0.tgz", + "integrity": "sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.58.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.0.tgz", + "integrity": "sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.24.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", + "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/preact-render-to-string": { + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz", + "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==", + "license": "MIT", + "peerDependencies": { + "preact": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.2.tgz", + "integrity": "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "@zackad/prettier-plugin-twig": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-multiline-arrays": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "@zackad/prettier-plugin-twig": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-multiline-arrays": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + } + } + }, + "node_modules/prisma": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", + "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.19.2", + "@prisma/engines": "6.19.2" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/prosemirror-changeset": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz", + "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==", + "license": "MIT", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.0.tgz", + "integrity": "sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-highlight": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/prosemirror-highlight/-/prosemirror-highlight-0.13.0.tgz", + "integrity": "sha512-GIC2VCTUnukNdsEGLQWWOVpYPl/7/KrVp4xs7XMB48/4rhUrHK8hp8TEog4Irmv+2kmjx24RLnaisGOCP6U8jw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ocavue" + }, + "peerDependencies": { + "@shikijs/types": "^1.29.2 || ^2.0.0 || ^3.0.0", + "@types/hast": "^3.0.0", + "highlight.js": "^11.9.0", + "lowlight": "^3.1.0", + "prosemirror-model": "^1.19.3", + "prosemirror-state": "^1.4.3", + "prosemirror-transform": "^1.8.0", + "prosemirror-view": "^1.32.4", + "refractor": "^5.0.0", + "sugar-high": "^0.6.1 || ^0.7.0 || ^0.8.0 || ^0.9.0" + }, + "peerDependenciesMeta": { + "@shikijs/types": { + "optional": true + }, + "@types/hast": { + "optional": true + }, + "highlight.js": { + "optional": true + }, + "lowlight": { + "optional": true + }, + "prosemirror-model": { + "optional": true + }, + "prosemirror-state": { + "optional": true + }, + "prosemirror-transform": { + "optional": true + }, + "prosemirror-view": { + "optional": true + }, + "refractor": { + "optional": true + }, + "sugar-high": { + "optional": true + } + } + }, + "node_modules/prosemirror-history": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", + "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz", + "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.3.tgz", + "integrity": "sha512-3E+Et6cdXIH0EgN2tGYQ+EBT7N4kMiZFsW+hzx+aPtOmADDHWCdd2uUQb7yklJrfUYUOjEEu22BiN6UFgPe4cQ==", + "license": "MIT", + "dependencies": { + "@types/markdown-it": "^14.0.0", + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-menu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", + "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", + "license": "MIT", + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.4", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", + "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", + "license": "MIT", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", + "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", + "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz", + "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.2.3", + "prosemirror-model": "^1.25.4", + "prosemirror-state": "^1.4.4", + "prosemirror-transform": "^1.10.5", + "prosemirror-view": "^1.41.4" + } + }, + "node_modules/prosemirror-trailing-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", + "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", + "license": "MIT", + "dependencies": { + "@remirror/core-constants": "3.0.0", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.22.1", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.33.8" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.11.0.tgz", + "integrity": "sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.41.5", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.5.tgz", + "integrity": "sha512-UDQbIPnDrjE8tqUBbPmCOZgtd75htE6W3r0JCmY9bL6W1iemDM37MZEKC49d+tdQ0v/CKx4gjxLoLsfkD2NiZA==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "license": "MIT", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-day-picker": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.13.0.tgz", + "integrity": "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ==", + "license": "MIT", + "dependencies": { + "@date-fns/tz": "^1.4.1", + "date-fns": "^4.1.0", + "date-fns-jalali": "^4.1.0-0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/gpbl" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-easy-crop": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.5.6.tgz", + "integrity": "sha512-Jw3/ozs8uXj3NpL511Suc4AHY+mLRO23rUgipXvNYKqezcFSYHxe4QXibBymkOoY6oOtLVMPO2HNPRHYvMPyTw==", + "license": "MIT", + "dependencies": { + "normalize-wheel": "^1.0.1", + "tslib": "^2.0.1" + }, + "peerDependencies": { + "react": ">=16.4.0", + "react-dom": ">=16.4.0" + } + }, + "node_modules/react-hook-form": { + "version": "7.71.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz", + "integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-leaflet": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz", + "integrity": "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==", + "license": "Hippocratic-2.1", + "dependencies": { + "@react-leaflet/core": "^3.0.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "node_modules/react-number-format": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz", + "integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==", + "license": "MIT", + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-phone-number-input": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.14.tgz", + "integrity": "sha512-T9MziNuvthzv6+JAhKD71ab/jVXW5U20nQZRBJd6+q+ujmkC+/ISOf2GYo8pIi4VGjdIYRIHDftMAYn3WKZT3w==", + "license": "MIT", + "dependencies": { + "classnames": "^2.5.1", + "country-flag-icons": "^1.5.17", + "input-format": "^0.3.14", + "libphonenumber-js": "^1.12.27", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", + "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recharts": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz", + "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "1.x.x || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "optional": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rehype-format": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", + "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-format": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-minify-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", + "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-remark": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-10.0.1.tgz", + "integrity": "sha512-EmDndlb5NVwXGfUa4c9GPK+lXeItTilLhE6ADSaQuHr4JUlKw9MidzGzx4HpqZrNCt6vnHmEifXQiiA+CEnjYQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "hast-util-to-mdast": "^10.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, + "node_modules/rollup": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", + "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.0", + "@rollup/rollup-android-arm64": "4.57.0", + "@rollup/rollup-darwin-arm64": "4.57.0", + "@rollup/rollup-darwin-x64": "4.57.0", + "@rollup/rollup-freebsd-arm64": "4.57.0", + "@rollup/rollup-freebsd-x64": "4.57.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", + "@rollup/rollup-linux-arm-musleabihf": "4.57.0", + "@rollup/rollup-linux-arm64-gnu": "4.57.0", + "@rollup/rollup-linux-arm64-musl": "4.57.0", + "@rollup/rollup-linux-loong64-gnu": "4.57.0", + "@rollup/rollup-linux-loong64-musl": "4.57.0", + "@rollup/rollup-linux-ppc64-gnu": "4.57.0", + "@rollup/rollup-linux-ppc64-musl": "4.57.0", + "@rollup/rollup-linux-riscv64-gnu": "4.57.0", + "@rollup/rollup-linux-riscv64-musl": "4.57.0", + "@rollup/rollup-linux-s390x-gnu": "4.57.0", + "@rollup/rollup-linux-x64-gnu": "4.57.0", + "@rollup/rollup-linux-x64-musl": "4.57.0", + "@rollup/rollup-openbsd-x64": "4.57.0", + "@rollup/rollup-openharmony-arm64": "4.57.0", + "@rollup/rollup-win32-arm64-msvc": "4.57.0", + "@rollup/rollup-win32-ia32-msvc": "4.57.0", + "@rollup/rollup-win32-x64-gnu": "4.57.0", + "@rollup/rollup-win32-x64-msvc": "4.57.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", + "license": "MIT" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", + "license": "MIT" + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trim-trailing-lines": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", + "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-composed-ref": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-debounce": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.1.0.tgz", + "integrity": "sha512-lu87Za35V3n/MyMoEpD5zJv0k7hCn0p+V/fK2kWD+3k2u3kOCwO593UArbczg1fhfs2rqPEnHpULJ3KmGdDzvg==", + "license": "MIT", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", + "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "license": "MIT", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "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 + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.18", + "@vitest/mocker": "4.0.18", + "@vitest/pretty-format": "4.0.18", + "@vitest/runner": "4.0.18", + "@vitest/snapshot": "4.0.18", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.18", + "@vitest/browser-preview": "4.0.18", + "@vitest/browser-webdriverio": "4.0.18", + "@vitest/ui": "4.0.18", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "license": "MIT", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y-prosemirror": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/y-prosemirror/-/y-prosemirror-1.3.7.tgz", + "integrity": "sha512-NpM99WSdD4Fx4if5xOMDpPtU3oAmTSjlzh5U4353ABbRHl1HtAFUx6HlebLZfyFxXN9jzKMDkVbcRjqOZVkYQg==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.109" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "prosemirror-model": "^1.7.1", + "prosemirror-state": "^1.2.3", + "prosemirror-view": "^1.9.10", + "y-protocols": "^1.0.1", + "yjs": "^13.5.38" + } + }, + "node_modules/y-protocols": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz", + "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/yjs": { + "version": "13.6.29", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.29.tgz", + "integrity": "sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/package.json b/package.json index 793b322..9a47686 100644 --- a/package.json +++ b/package.json @@ -1,119 +1,119 @@ -{ - "name": "mopc-platform", - "version": "0.1.0", - "private": true, - "type": "module", - "scripts": { - "dev": "next dev --turbopack", - "build": "next build", - "start": "next start", - "lint": "next lint", - "format": "prettier --write .", - "typecheck": "tsc --noEmit", - "db:generate": "prisma generate", - "db:push": "prisma db push", - "db:migrate": "prisma migrate dev", - "db:migrate:deploy": "prisma migrate deploy", - "db:studio": "prisma studio", - "db:seed": "tsx prisma/seed.ts", - "db:seed:candidatures": "tsx prisma/seed-candidatures.ts", - "test": "vitest", - "test:e2e": "playwright test" - }, - "dependencies": { - "@auth/prisma-adapter": "^2.7.4", - "@blocknote/core": "^0.46.2", - "@blocknote/mantine": "^0.46.2", - "@blocknote/react": "^0.46.2", - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^10.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@hookform/resolvers": "^3.9.1", - "@mantine/core": "^8.3.13", - "@mantine/hooks": "^8.3.13", - "@notionhq/client": "^2.3.0", - "@prisma/client": "^6.19.2", - "@radix-ui/react-alert-dialog": "^1.1.4", - "@radix-ui/react-avatar": "^1.1.2", - "@radix-ui/react-checkbox": "^1.1.3", - "@radix-ui/react-collapsible": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.4", - "@radix-ui/react-dropdown-menu": "^2.1.4", - "@radix-ui/react-label": "^2.1.1", - "@radix-ui/react-popover": "^1.1.4", - "@radix-ui/react-progress": "^1.1.1", - "@radix-ui/react-radio-group": "^1.2.2", - "@radix-ui/react-scroll-area": "^1.2.10", - "@radix-ui/react-select": "^2.1.4", - "@radix-ui/react-separator": "^1.1.1", - "@radix-ui/react-slider": "^1.2.2", - "@radix-ui/react-slot": "^1.1.1", - "@radix-ui/react-switch": "^1.1.2", - "@radix-ui/react-tabs": "^1.1.2", - "@radix-ui/react-tooltip": "^1.1.6", - "@tailwindcss/postcss": "^4.1.18", - "@tanstack/react-query": "^5.62.0", - "@trpc/client": "^11.0.0-rc.678", - "@trpc/react-query": "^11.0.0-rc.678", - "@trpc/server": "^11.0.0-rc.678", - "bcryptjs": "^3.0.3", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "cmdk": "^1.0.4", - "csv-parse": "^6.1.0", - "date-fns": "^4.1.0", - "html2canvas": "^1.4.1", - "jspdf": "^4.1.0", - "jspdf-autotable": "^5.0.7", - "leaflet": "^1.9.4", - "lucide-react": "^0.563.0", - "minio": "^8.0.2", - "motion": "^11.15.0", - "next": "^15.1.0", - "next-auth": "^5.0.0-beta.25", - "next-themes": "^0.4.6", - "nodemailer": "^7.0.7", - "openai": "^6.16.0", - "papaparse": "^5.4.1", - "react": "^19.0.0", - "react-day-picker": "^9.13.0", - "react-dom": "^19.0.0", - "react-easy-crop": "^5.5.6", - "react-hook-form": "^7.54.2", - "react-leaflet": "^5.0.0", - "react-phone-number-input": "^3.4.14", - "recharts": "^3.7.0", - "sonner": "^2.0.7", - "superjson": "^2.2.2", - "tailwind-merge": "^3.4.0", - "use-debounce": "^10.0.4", - "zod": "^3.24.1" - }, - "devDependencies": { - "@playwright/test": "^1.49.1", - "@types/bcryptjs": "^2.4.6", - "@types/leaflet": "^1.9.21", - "@types/node": "^25.0.10", - "@types/nodemailer": "^7.0.9", - "@types/papaparse": "^5.3.15", - "@types/react": "^19.0.2", - "@types/react-dom": "^19.0.2", - "eslint": "^9.17.0", - "eslint-config-next": "^15.1.0", - "postcss": "^8.4.49", - "prettier": "^3.4.2", - "prettier-plugin-tailwindcss": "^0.7.2", - "prisma": "^6.19.2", - "tailwindcss": "^4.1.18", - "tailwindcss-animate": "^1.0.7", - "tsx": "^4.19.2", - "typescript": "^5.7.2", - "vitest": "^4.0.18" - }, - "engines": { - "node": ">=20.0.0" - }, - "prisma": { - "seed": "tsx prisma/seed.ts" - } -} +{ + "name": "mopc-platform", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint", + "format": "prettier --write .", + "typecheck": "tsc --noEmit", + "db:generate": "prisma generate", + "db:push": "prisma db push", + "db:migrate": "prisma migrate dev", + "db:migrate:deploy": "prisma migrate deploy", + "db:studio": "prisma studio", + "db:seed": "tsx prisma/seed.ts", + "db:seed:candidatures": "tsx prisma/seed-candidatures.ts", + "test": "vitest", + "test:e2e": "playwright test" + }, + "dependencies": { + "@auth/prisma-adapter": "^2.7.4", + "@blocknote/core": "^0.46.2", + "@blocknote/mantine": "^0.46.2", + "@blocknote/react": "^0.46.2", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@hookform/resolvers": "^3.9.1", + "@mantine/core": "^8.3.13", + "@mantine/hooks": "^8.3.13", + "@notionhq/client": "^2.3.0", + "@prisma/client": "^6.19.2", + "@radix-ui/react-alert-dialog": "^1.1.4", + "@radix-ui/react-avatar": "^1.1.2", + "@radix-ui/react-checkbox": "^1.1.3", + "@radix-ui/react-collapsible": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-dropdown-menu": "^2.1.4", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-popover": "^1.1.4", + "@radix-ui/react-progress": "^1.1.1", + "@radix-ui/react-radio-group": "^1.2.2", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.1.4", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-slider": "^1.2.2", + "@radix-ui/react-slot": "^1.1.1", + "@radix-ui/react-switch": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.2", + "@radix-ui/react-tooltip": "^1.1.6", + "@tailwindcss/postcss": "^4.1.18", + "@tanstack/react-query": "^5.62.0", + "@trpc/client": "^11.0.0-rc.678", + "@trpc/react-query": "^11.0.0-rc.678", + "@trpc/server": "^11.0.0-rc.678", + "bcryptjs": "^3.0.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.0.4", + "csv-parse": "^6.1.0", + "date-fns": "^4.1.0", + "html2canvas": "^1.4.1", + "jspdf": "^4.1.0", + "jspdf-autotable": "^5.0.7", + "leaflet": "^1.9.4", + "lucide-react": "^0.563.0", + "minio": "^8.0.2", + "motion": "^11.15.0", + "next": "^15.1.0", + "next-auth": "^5.0.0-beta.25", + "next-themes": "^0.4.6", + "nodemailer": "^7.0.7", + "openai": "^6.16.0", + "papaparse": "^5.4.1", + "react": "^19.0.0", + "react-day-picker": "^9.13.0", + "react-dom": "^19.0.0", + "react-easy-crop": "^5.5.6", + "react-hook-form": "^7.54.2", + "react-leaflet": "^5.0.0", + "react-phone-number-input": "^3.4.14", + "recharts": "^3.7.0", + "sonner": "^2.0.7", + "superjson": "^2.2.2", + "tailwind-merge": "^3.4.0", + "use-debounce": "^10.0.4", + "zod": "^3.24.1" + }, + "devDependencies": { + "@playwright/test": "^1.49.1", + "@types/bcryptjs": "^2.4.6", + "@types/leaflet": "^1.9.21", + "@types/node": "^25.0.10", + "@types/nodemailer": "^7.0.9", + "@types/papaparse": "^5.3.15", + "@types/react": "^19.0.2", + "@types/react-dom": "^19.0.2", + "eslint": "^9.17.0", + "eslint-config-next": "^15.1.0", + "postcss": "^8.4.49", + "prettier": "^3.4.2", + "prettier-plugin-tailwindcss": "^0.7.2", + "prisma": "^6.19.2", + "tailwindcss": "^4.1.18", + "tailwindcss-animate": "^1.0.7", + "tsx": "^4.19.2", + "typescript": "^5.7.2", + "vitest": "^4.0.18" + }, + "engines": { + "node": ">=20.0.0" + }, + "prisma": { + "seed": "tsx prisma/seed.ts" + } +} diff --git a/prisma/integrity-checks.ts b/prisma/integrity-checks.ts index 0ff0c6e..b2f10b0 100644 --- a/prisma/integrity-checks.ts +++ b/prisma/integrity-checks.ts @@ -1,246 +1,246 @@ -import { PrismaClient } from '@prisma/client' - -const prisma = new PrismaClient() - -interface CheckResult { - name: string - passed: boolean - details: string -} - -async function runChecks(): Promise { - const results: CheckResult[] = [] - - // 1. No orphan ProjectStageState (every PSS references valid project, track, stage) - const orphanStates = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "ProjectStageState" pss - WHERE NOT EXISTS (SELECT 1 FROM "Project" p WHERE p.id = pss."projectId") - OR NOT EXISTS (SELECT 1 FROM "Track" t WHERE t.id = pss."trackId") - OR NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = pss."stageId") - ` - const orphanCount = Number(orphanStates[0]?.count ?? 0) - results.push({ - name: 'No orphan ProjectStageState', - passed: orphanCount === 0, - details: orphanCount === 0 ? 'All PSS records reference valid entities' : `Found ${orphanCount} orphan records`, - }) - - // 2. Every project has at least one stage state - const projectsWithoutState = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "Project" p - WHERE NOT EXISTS (SELECT 1 FROM "ProjectStageState" pss WHERE pss."projectId" = p.id) - ` - const noStateCount = Number(projectsWithoutState[0]?.count ?? 0) - const totalProjects = await prisma.project.count() - results.push({ - name: 'Every project has at least one stage state', - passed: noStateCount === 0, - details: noStateCount === 0 - ? `All ${totalProjects} projects have stage states` - : `${noStateCount} projects missing stage states`, - }) - - // 3. No duplicate active states per (project, track, stage) - const duplicateStates = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM ( - SELECT "projectId", "trackId", "stageId", COUNT(*) as cnt - FROM "ProjectStageState" - WHERE "exitedAt" IS NULL - GROUP BY "projectId", "trackId", "stageId" - HAVING COUNT(*) > 1 - ) dupes - ` - const dupeCount = Number(duplicateStates[0]?.count ?? 0) - results.push({ - name: 'No duplicate active states per (project, track, stage)', - passed: dupeCount === 0, - details: dupeCount === 0 ? 'No duplicates found' : `Found ${dupeCount} duplicate active states`, - }) - - // 4. All transitions stay within same pipeline - const crossPipelineTransitions = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "StageTransition" st - JOIN "Stage" sf ON sf.id = st."fromStageId" - JOIN "Track" tf ON tf.id = sf."trackId" - JOIN "Stage" sto ON sto.id = st."toStageId" - JOIN "Track" tt ON tt.id = sto."trackId" - WHERE tf."pipelineId" != tt."pipelineId" - ` - const crossCount = Number(crossPipelineTransitions[0]?.count ?? 0) - results.push({ - name: 'All transitions stay within same pipeline', - passed: crossCount === 0, - details: crossCount === 0 ? 'All transitions are within pipeline' : `Found ${crossCount} cross-pipeline transitions`, - }) - - // 5. Stage sortOrder unique per track - const duplicateSortOrders = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM ( - SELECT "trackId", "sortOrder", COUNT(*) as cnt - FROM "Stage" - GROUP BY "trackId", "sortOrder" - HAVING COUNT(*) > 1 - ) dupes - ` - const dupeSortCount = Number(duplicateSortOrders[0]?.count ?? 0) - results.push({ - name: 'Stage sortOrder unique per track', - passed: dupeSortCount === 0, - details: dupeSortCount === 0 ? 'All sort orders unique' : `Found ${dupeSortCount} duplicate sort orders`, - }) - - // 6. Track sortOrder unique per pipeline - const duplicateTrackOrders = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM ( - SELECT "pipelineId", "sortOrder", COUNT(*) as cnt - FROM "Track" - GROUP BY "pipelineId", "sortOrder" - HAVING COUNT(*) > 1 - ) dupes - ` - const dupeTrackCount = Number(duplicateTrackOrders[0]?.count ?? 0) - results.push({ - name: 'Track sortOrder unique per pipeline', - passed: dupeTrackCount === 0, - details: dupeTrackCount === 0 ? 'All track orders unique' : `Found ${dupeTrackCount} duplicate track orders`, - }) - - // 7. Every Pipeline has at least one Track; every Track has at least one Stage - const emptyPipelines = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "Pipeline" p - WHERE NOT EXISTS (SELECT 1 FROM "Track" t WHERE t."pipelineId" = p.id) - ` - const emptyPipelineCount = Number(emptyPipelines[0]?.count ?? 0) - const emptyTracks = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "Track" t - WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s."trackId" = t.id) - ` - const emptyTrackCount = Number(emptyTracks[0]?.count ?? 0) - results.push({ - name: 'Every Pipeline has Tracks; every Track has Stages', - passed: emptyPipelineCount === 0 && emptyTrackCount === 0, - details: emptyPipelineCount === 0 && emptyTrackCount === 0 - ? 'All pipelines have tracks and all tracks have stages' - : `${emptyPipelineCount} empty pipelines, ${emptyTrackCount} empty tracks`, - }) - - // 8. RoutingRule destinations reference valid tracks in same pipeline - const badRoutingRules = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "RoutingRule" rr - WHERE rr."destinationTrackId" IS NOT NULL - AND NOT EXISTS ( - SELECT 1 FROM "Track" t - WHERE t.id = rr."destinationTrackId" - AND t."pipelineId" = rr."pipelineId" - ) - ` - const badRouteCount = Number(badRoutingRules[0]?.count ?? 0) - results.push({ - name: 'RoutingRule destinations reference valid tracks in same pipeline', - passed: badRouteCount === 0, - details: badRouteCount === 0 - ? 'All routing rules reference valid destination tracks' - : `Found ${badRouteCount} routing rules with invalid destinations`, - }) - - // 9. LiveProgressCursor references valid stage - const badCursors = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "LiveProgressCursor" lpc - WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = lpc."stageId") - ` - const badCursorCount = Number(badCursors[0]?.count ?? 0) - results.push({ - name: 'LiveProgressCursor references valid stage', - passed: badCursorCount === 0, - details: badCursorCount === 0 - ? 'All cursors reference valid stages' - : `Found ${badCursorCount} cursors with invalid stage references`, - }) - - // 10. Cohort references valid stage - const badCohorts = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "Cohort" c - WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = c."stageId") - ` - const badCohortCount = Number(badCohorts[0]?.count ?? 0) - results.push({ - name: 'Cohort references valid stage', - passed: badCohortCount === 0, - details: badCohortCount === 0 - ? 'All cohorts reference valid stages' - : `Found ${badCohortCount} cohorts with invalid stage references`, - }) - - // 11. Every EvaluationForm has a valid stageId - const badEvalForms = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "EvaluationForm" ef - WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = ef."stageId") - ` - const badFormCount = Number(badEvalForms[0]?.count ?? 0) - results.push({ - name: 'Every EvaluationForm references valid stage', - passed: badFormCount === 0, - details: badFormCount === 0 - ? 'All evaluation forms reference valid stages' - : `Found ${badFormCount} forms with invalid stage references`, - }) - - // 12. Every FileRequirement has a valid stageId - const badFileReqs = await prisma.$queryRaw<{ count: bigint }[]>` - SELECT COUNT(*) as count FROM "FileRequirement" fr - WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = fr."stageId") - ` - const badFileReqCount = Number(badFileReqs[0]?.count ?? 0) - results.push({ - name: 'Every FileRequirement references valid stage', - passed: badFileReqCount === 0, - details: badFileReqCount === 0 - ? 'All file requirements reference valid stages' - : `Found ${badFileReqCount} file requirements with invalid stage references`, - }) - - // 13. Count validation - const projectCountResult = await prisma.project.count() - const stageCount = await prisma.stage.count() - const trackCount = await prisma.track.count() - const pipelineCount = await prisma.pipeline.count() - const pssCount = await prisma.projectStageState.count() - results.push({ - name: 'Count validation', - passed: projectCountResult > 0 && stageCount > 0 && trackCount > 0, - details: `Pipelines: ${pipelineCount}, Tracks: ${trackCount}, Stages: ${stageCount}, Projects: ${projectCountResult}, StageStates: ${pssCount}`, - }) - - return results -} - -async function main() { - console.log('🔍 Running integrity checks...\n') - - const results = await runChecks() - - let allPassed = true - for (const result of results) { - const icon = result.passed ? '✅' : '❌' - console.log(`${icon} ${result.name}`) - console.log(` ${result.details}\n`) - if (!result.passed) allPassed = false - } - - console.log('='.repeat(50)) - if (allPassed) { - console.log('✅ All integrity checks passed!') - } else { - console.log('❌ Some integrity checks failed!') - process.exit(1) - } -} - -main() - .catch((e) => { - console.error('❌ Integrity check failed:', e) - process.exit(1) - }) - .finally(async () => { - await prisma.$disconnect() - }) +import { PrismaClient } from '@prisma/client' + +const prisma = new PrismaClient() + +interface CheckResult { + name: string + passed: boolean + details: string +} + +async function runChecks(): Promise { + const results: CheckResult[] = [] + + // 1. No orphan ProjectStageState (every PSS references valid project, track, stage) + const orphanStates = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "ProjectStageState" pss + WHERE NOT EXISTS (SELECT 1 FROM "Project" p WHERE p.id = pss."projectId") + OR NOT EXISTS (SELECT 1 FROM "Track" t WHERE t.id = pss."trackId") + OR NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = pss."stageId") + ` + const orphanCount = Number(orphanStates[0]?.count ?? 0) + results.push({ + name: 'No orphan ProjectStageState', + passed: orphanCount === 0, + details: orphanCount === 0 ? 'All PSS records reference valid entities' : `Found ${orphanCount} orphan records`, + }) + + // 2. Every project has at least one stage state + const projectsWithoutState = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "Project" p + WHERE NOT EXISTS (SELECT 1 FROM "ProjectStageState" pss WHERE pss."projectId" = p.id) + ` + const noStateCount = Number(projectsWithoutState[0]?.count ?? 0) + const totalProjects = await prisma.project.count() + results.push({ + name: 'Every project has at least one stage state', + passed: noStateCount === 0, + details: noStateCount === 0 + ? `All ${totalProjects} projects have stage states` + : `${noStateCount} projects missing stage states`, + }) + + // 3. No duplicate active states per (project, track, stage) + const duplicateStates = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM ( + SELECT "projectId", "trackId", "stageId", COUNT(*) as cnt + FROM "ProjectStageState" + WHERE "exitedAt" IS NULL + GROUP BY "projectId", "trackId", "stageId" + HAVING COUNT(*) > 1 + ) dupes + ` + const dupeCount = Number(duplicateStates[0]?.count ?? 0) + results.push({ + name: 'No duplicate active states per (project, track, stage)', + passed: dupeCount === 0, + details: dupeCount === 0 ? 'No duplicates found' : `Found ${dupeCount} duplicate active states`, + }) + + // 4. All transitions stay within same pipeline + const crossPipelineTransitions = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "StageTransition" st + JOIN "Stage" sf ON sf.id = st."fromStageId" + JOIN "Track" tf ON tf.id = sf."trackId" + JOIN "Stage" sto ON sto.id = st."toStageId" + JOIN "Track" tt ON tt.id = sto."trackId" + WHERE tf."pipelineId" != tt."pipelineId" + ` + const crossCount = Number(crossPipelineTransitions[0]?.count ?? 0) + results.push({ + name: 'All transitions stay within same pipeline', + passed: crossCount === 0, + details: crossCount === 0 ? 'All transitions are within pipeline' : `Found ${crossCount} cross-pipeline transitions`, + }) + + // 5. Stage sortOrder unique per track + const duplicateSortOrders = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM ( + SELECT "trackId", "sortOrder", COUNT(*) as cnt + FROM "Stage" + GROUP BY "trackId", "sortOrder" + HAVING COUNT(*) > 1 + ) dupes + ` + const dupeSortCount = Number(duplicateSortOrders[0]?.count ?? 0) + results.push({ + name: 'Stage sortOrder unique per track', + passed: dupeSortCount === 0, + details: dupeSortCount === 0 ? 'All sort orders unique' : `Found ${dupeSortCount} duplicate sort orders`, + }) + + // 6. Track sortOrder unique per pipeline + const duplicateTrackOrders = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM ( + SELECT "pipelineId", "sortOrder", COUNT(*) as cnt + FROM "Track" + GROUP BY "pipelineId", "sortOrder" + HAVING COUNT(*) > 1 + ) dupes + ` + const dupeTrackCount = Number(duplicateTrackOrders[0]?.count ?? 0) + results.push({ + name: 'Track sortOrder unique per pipeline', + passed: dupeTrackCount === 0, + details: dupeTrackCount === 0 ? 'All track orders unique' : `Found ${dupeTrackCount} duplicate track orders`, + }) + + // 7. Every Pipeline has at least one Track; every Track has at least one Stage + const emptyPipelines = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "Pipeline" p + WHERE NOT EXISTS (SELECT 1 FROM "Track" t WHERE t."pipelineId" = p.id) + ` + const emptyPipelineCount = Number(emptyPipelines[0]?.count ?? 0) + const emptyTracks = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "Track" t + WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s."trackId" = t.id) + ` + const emptyTrackCount = Number(emptyTracks[0]?.count ?? 0) + results.push({ + name: 'Every Pipeline has Tracks; every Track has Stages', + passed: emptyPipelineCount === 0 && emptyTrackCount === 0, + details: emptyPipelineCount === 0 && emptyTrackCount === 0 + ? 'All pipelines have tracks and all tracks have stages' + : `${emptyPipelineCount} empty pipelines, ${emptyTrackCount} empty tracks`, + }) + + // 8. RoutingRule destinations reference valid tracks in same pipeline + const badRoutingRules = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "RoutingRule" rr + WHERE rr."destinationTrackId" IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM "Track" t + WHERE t.id = rr."destinationTrackId" + AND t."pipelineId" = rr."pipelineId" + ) + ` + const badRouteCount = Number(badRoutingRules[0]?.count ?? 0) + results.push({ + name: 'RoutingRule destinations reference valid tracks in same pipeline', + passed: badRouteCount === 0, + details: badRouteCount === 0 + ? 'All routing rules reference valid destination tracks' + : `Found ${badRouteCount} routing rules with invalid destinations`, + }) + + // 9. LiveProgressCursor references valid stage + const badCursors = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "LiveProgressCursor" lpc + WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = lpc."stageId") + ` + const badCursorCount = Number(badCursors[0]?.count ?? 0) + results.push({ + name: 'LiveProgressCursor references valid stage', + passed: badCursorCount === 0, + details: badCursorCount === 0 + ? 'All cursors reference valid stages' + : `Found ${badCursorCount} cursors with invalid stage references`, + }) + + // 10. Cohort references valid stage + const badCohorts = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "Cohort" c + WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = c."stageId") + ` + const badCohortCount = Number(badCohorts[0]?.count ?? 0) + results.push({ + name: 'Cohort references valid stage', + passed: badCohortCount === 0, + details: badCohortCount === 0 + ? 'All cohorts reference valid stages' + : `Found ${badCohortCount} cohorts with invalid stage references`, + }) + + // 11. Every EvaluationForm has a valid stageId + const badEvalForms = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "EvaluationForm" ef + WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = ef."stageId") + ` + const badFormCount = Number(badEvalForms[0]?.count ?? 0) + results.push({ + name: 'Every EvaluationForm references valid stage', + passed: badFormCount === 0, + details: badFormCount === 0 + ? 'All evaluation forms reference valid stages' + : `Found ${badFormCount} forms with invalid stage references`, + }) + + // 12. Every FileRequirement has a valid stageId + const badFileReqs = await prisma.$queryRaw<{ count: bigint }[]>` + SELECT COUNT(*) as count FROM "FileRequirement" fr + WHERE NOT EXISTS (SELECT 1 FROM "Stage" s WHERE s.id = fr."stageId") + ` + const badFileReqCount = Number(badFileReqs[0]?.count ?? 0) + results.push({ + name: 'Every FileRequirement references valid stage', + passed: badFileReqCount === 0, + details: badFileReqCount === 0 + ? 'All file requirements reference valid stages' + : `Found ${badFileReqCount} file requirements with invalid stage references`, + }) + + // 13. Count validation + const projectCountResult = await prisma.project.count() + const stageCount = await prisma.stage.count() + const trackCount = await prisma.track.count() + const pipelineCount = await prisma.pipeline.count() + const pssCount = await prisma.projectStageState.count() + results.push({ + name: 'Count validation', + passed: projectCountResult > 0 && stageCount > 0 && trackCount > 0, + details: `Pipelines: ${pipelineCount}, Tracks: ${trackCount}, Stages: ${stageCount}, Projects: ${projectCountResult}, StageStates: ${pssCount}`, + }) + + return results +} + +async function main() { + console.log('🔍 Running integrity checks...\n') + + const results = await runChecks() + + let allPassed = true + for (const result of results) { + const icon = result.passed ? '✅' : '❌' + console.log(`${icon} ${result.name}`) + console.log(` ${result.details}\n`) + if (!result.passed) allPassed = false + } + + console.log('='.repeat(50)) + if (allPassed) { + console.log('✅ All integrity checks passed!') + } else { + console.log('❌ Some integrity checks failed!') + process.exit(1) + } +} + +main() + .catch((e) => { + console.error('❌ Integrity check failed:', e) + process.exit(1) + }) + .finally(async () => { + await prisma.$disconnect() + }) diff --git a/prisma/migrations/20260130000000_init/migration.sql b/prisma/migrations/20260130000000_init/migration.sql index 8fc05f3..2335837 100644 --- a/prisma/migrations/20260130000000_init/migration.sql +++ b/prisma/migrations/20260130000000_init/migration.sql @@ -1,909 +1,909 @@ --- CreateSchema -CREATE SCHEMA IF NOT EXISTS "public"; - --- CreateEnum -CREATE TYPE "UserRole" AS ENUM ('SUPER_ADMIN', 'PROGRAM_ADMIN', 'JURY_MEMBER', 'MENTOR', 'OBSERVER', 'APPLICANT'); - --- CreateEnum -CREATE TYPE "UserStatus" AS ENUM ('NONE', 'INVITED', 'ACTIVE', 'SUSPENDED'); - --- CreateEnum -CREATE TYPE "ProgramStatus" AS ENUM ('DRAFT', 'ACTIVE', 'ARCHIVED'); - --- CreateEnum -CREATE TYPE "RoundStatus" AS ENUM ('DRAFT', 'ACTIVE', 'CLOSED', 'ARCHIVED'); - --- CreateEnum -CREATE TYPE "ProjectStatus" AS ENUM ('SUBMITTED', 'ELIGIBLE', 'ASSIGNED', 'SEMIFINALIST', 'FINALIST', 'REJECTED'); - --- CreateEnum -CREATE TYPE "EvaluationStatus" AS ENUM ('NOT_STARTED', 'DRAFT', 'SUBMITTED', 'LOCKED'); - --- CreateEnum -CREATE TYPE "AssignmentMethod" AS ENUM ('MANUAL', 'BULK', 'AI_SUGGESTED', 'AI_AUTO', 'ALGORITHM'); - --- CreateEnum -CREATE TYPE "FileType" AS ENUM ('EXEC_SUMMARY', 'PRESENTATION', 'VIDEO', 'OTHER', 'BUSINESS_PLAN', 'VIDEO_PITCH', 'SUPPORTING_DOC'); - --- CreateEnum -CREATE TYPE "SubmissionSource" AS ENUM ('MANUAL', 'CSV', 'NOTION', 'TYPEFORM', 'PUBLIC_FORM'); - --- CreateEnum -CREATE TYPE "RoundType" AS ENUM ('FILTERING', 'EVALUATION', 'LIVE_EVENT'); - --- CreateEnum -CREATE TYPE "SettingType" AS ENUM ('STRING', 'NUMBER', 'BOOLEAN', 'JSON', 'SECRET'); - --- CreateEnum -CREATE TYPE "SettingCategory" AS ENUM ('AI', 'BRANDING', 'EMAIL', 'STORAGE', 'SECURITY', 'DEFAULTS', 'WHATSAPP'); - --- CreateEnum -CREATE TYPE "NotificationChannel" AS ENUM ('EMAIL', 'WHATSAPP', 'BOTH', 'NONE'); - --- CreateEnum -CREATE TYPE "ResourceType" AS ENUM ('PDF', 'VIDEO', 'DOCUMENT', 'LINK', 'OTHER'); - --- CreateEnum -CREATE TYPE "CohortLevel" AS ENUM ('ALL', 'SEMIFINALIST', 'FINALIST'); - --- CreateEnum -CREATE TYPE "PartnerVisibility" AS ENUM ('ADMIN_ONLY', 'JURY_VISIBLE', 'PUBLIC'); - --- CreateEnum -CREATE TYPE "PartnerType" AS ENUM ('SPONSOR', 'PARTNER', 'SUPPORTER', 'MEDIA', 'OTHER'); - --- CreateEnum -CREATE TYPE "FormFieldType" AS ENUM ('TEXT', 'TEXTAREA', 'NUMBER', 'EMAIL', 'PHONE', 'URL', 'DATE', 'DATETIME', 'SELECT', 'MULTI_SELECT', 'RADIO', 'CHECKBOX', 'CHECKBOX_GROUP', 'FILE', 'FILE_MULTIPLE', 'SECTION', 'INSTRUCTIONS'); - --- CreateEnum -CREATE TYPE "CompetitionCategory" AS ENUM ('STARTUP', 'BUSINESS_CONCEPT'); - --- CreateEnum -CREATE TYPE "OceanIssue" AS ENUM ('POLLUTION_REDUCTION', 'CLIMATE_MITIGATION', 'TECHNOLOGY_INNOVATION', 'SUSTAINABLE_SHIPPING', 'BLUE_CARBON', 'HABITAT_RESTORATION', 'COMMUNITY_CAPACITY', 'SUSTAINABLE_FISHING', 'CONSUMER_AWARENESS', 'OCEAN_ACIDIFICATION', 'OTHER'); - --- CreateEnum -CREATE TYPE "TeamMemberRole" AS ENUM ('LEAD', 'MEMBER', 'ADVISOR'); - --- CreateEnum -CREATE TYPE "MentorAssignmentMethod" AS ENUM ('MANUAL', 'AI_SUGGESTED', 'AI_AUTO', 'ALGORITHM'); - --- CreateTable -CREATE TABLE "User" ( - "id" TEXT NOT NULL, - "email" TEXT NOT NULL, - "name" TEXT, - "emailVerified" TIMESTAMP(3), - "role" "UserRole" NOT NULL DEFAULT 'JURY_MEMBER', - "status" "UserStatus" NOT NULL DEFAULT 'INVITED', - "expertiseTags" TEXT[] DEFAULT ARRAY[]::TEXT[], - "maxAssignments" INTEGER, - "metadataJson" JSONB, - "profileImageKey" TEXT, - "profileImageProvider" TEXT, - "phoneNumber" TEXT, - "phoneNumberVerified" BOOLEAN NOT NULL DEFAULT false, - "notificationPreference" "NotificationChannel" NOT NULL DEFAULT 'EMAIL', - "whatsappOptIn" BOOLEAN NOT NULL DEFAULT false, - "onboardingCompletedAt" TIMESTAMP(3), - "passwordHash" TEXT, - "passwordSetAt" TIMESTAMP(3), - "mustSetPassword" BOOLEAN NOT NULL DEFAULT true, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "lastLoginAt" TIMESTAMP(3), - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Account" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "type" TEXT NOT NULL, - "provider" TEXT NOT NULL, - "providerAccountId" TEXT NOT NULL, - "refresh_token" TEXT, - "access_token" TEXT, - "expires_at" INTEGER, - "token_type" TEXT, - "scope" TEXT, - "id_token" TEXT, - "session_state" TEXT, - - CONSTRAINT "Account_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Session" ( - "id" TEXT NOT NULL, - "sessionToken" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "expires" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Session_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "VerificationToken" ( - "identifier" TEXT NOT NULL, - "token" TEXT NOT NULL, - "expires" TIMESTAMP(3) NOT NULL -); - --- CreateTable -CREATE TABLE "Program" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "year" INTEGER NOT NULL, - "status" "ProgramStatus" NOT NULL DEFAULT 'DRAFT', - "description" TEXT, - "settingsJson" JSONB, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Program_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Round" ( - "id" TEXT NOT NULL, - "programId" TEXT NOT NULL, - "name" TEXT NOT NULL, - "slug" TEXT, - "status" "RoundStatus" NOT NULL DEFAULT 'DRAFT', - "roundType" "RoundType" NOT NULL DEFAULT 'EVALUATION', - "submissionDeadline" TIMESTAMP(3), - "submissionStartDate" TIMESTAMP(3), - "submissionEndDate" TIMESTAMP(3), - "lateSubmissionGrace" INTEGER, - "phase1Deadline" TIMESTAMP(3), - "phase2Deadline" TIMESTAMP(3), - "votingStartAt" TIMESTAMP(3), - "votingEndAt" TIMESTAMP(3), - "requiredReviews" INTEGER NOT NULL DEFAULT 3, - "settingsJson" JSONB, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Round_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "EvaluationForm" ( - "id" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "version" INTEGER NOT NULL DEFAULT 1, - "criteriaJson" JSONB NOT NULL, - "scalesJson" JSONB, - "isActive" BOOLEAN NOT NULL DEFAULT false, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "EvaluationForm_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Project" ( - "id" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "title" TEXT NOT NULL, - "teamName" TEXT, - "description" TEXT, - "status" "ProjectStatus" NOT NULL DEFAULT 'SUBMITTED', - "competitionCategory" "CompetitionCategory", - "oceanIssue" "OceanIssue", - "country" TEXT, - "geographicZone" TEXT, - "institution" TEXT, - "wantsMentorship" BOOLEAN NOT NULL DEFAULT false, - "phase1SubmissionUrl" TEXT, - "phase2SubmissionUrl" TEXT, - "referralSource" TEXT, - "internalComments" TEXT, - "applicationStatus" TEXT, - "submissionSource" "SubmissionSource" NOT NULL DEFAULT 'MANUAL', - "submittedByEmail" TEXT, - "submittedAt" TIMESTAMP(3), - "submittedByUserId" TEXT, - "logoKey" TEXT, - "logoProvider" TEXT, - "tags" TEXT[] DEFAULT ARRAY[]::TEXT[], - "metadataJson" JSONB, - "externalIdsJson" JSONB, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Project_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ProjectFile" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "fileType" "FileType" NOT NULL, - "fileName" TEXT NOT NULL, - "mimeType" TEXT NOT NULL, - "size" INTEGER NOT NULL, - "bucket" TEXT NOT NULL, - "objectKey" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "ProjectFile_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Assignment" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "method" "AssignmentMethod" NOT NULL DEFAULT 'MANUAL', - "isRequired" BOOLEAN NOT NULL DEFAULT true, - "isCompleted" BOOLEAN NOT NULL DEFAULT false, - "aiConfidenceScore" DOUBLE PRECISION, - "expertiseMatchScore" DOUBLE PRECISION, - "aiReasoning" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "createdBy" TEXT, - - CONSTRAINT "Assignment_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Evaluation" ( - "id" TEXT NOT NULL, - "assignmentId" TEXT NOT NULL, - "formId" TEXT NOT NULL, - "status" "EvaluationStatus" NOT NULL DEFAULT 'NOT_STARTED', - "criterionScoresJson" JSONB, - "globalScore" INTEGER, - "binaryDecision" BOOLEAN, - "feedbackText" TEXT, - "version" INTEGER NOT NULL DEFAULT 1, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "submittedAt" TIMESTAMP(3), - - CONSTRAINT "Evaluation_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "GracePeriod" ( - "id" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "projectId" TEXT, - "extendedUntil" TIMESTAMP(3) NOT NULL, - "reason" TEXT, - "grantedById" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "GracePeriod_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "SystemSettings" ( - "id" TEXT NOT NULL, - "key" TEXT NOT NULL, - "value" TEXT NOT NULL, - "type" "SettingType" NOT NULL DEFAULT 'STRING', - "category" "SettingCategory" NOT NULL, - "description" TEXT, - "isSecret" BOOLEAN NOT NULL DEFAULT false, - "updatedAt" TIMESTAMP(3) NOT NULL, - "updatedBy" TEXT, - - CONSTRAINT "SystemSettings_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "AuditLog" ( - "id" TEXT NOT NULL, - "userId" TEXT, - "action" TEXT NOT NULL, - "entityType" TEXT NOT NULL, - "entityId" TEXT, - "detailsJson" JSONB, - "ipAddress" TEXT, - "userAgent" TEXT, - "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "NotificationLog" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "channel" "NotificationChannel" NOT NULL, - "provider" TEXT, - "type" TEXT NOT NULL, - "status" TEXT NOT NULL, - "externalId" TEXT, - "errorMsg" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "NotificationLog_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "LearningResource" ( - "id" TEXT NOT NULL, - "programId" TEXT, - "title" TEXT NOT NULL, - "description" TEXT, - "contentJson" JSONB, - "resourceType" "ResourceType" NOT NULL, - "cohortLevel" "CohortLevel" NOT NULL DEFAULT 'ALL', - "fileName" TEXT, - "mimeType" TEXT, - "size" INTEGER, - "bucket" TEXT, - "objectKey" TEXT, - "externalUrl" TEXT, - "sortOrder" INTEGER NOT NULL DEFAULT 0, - "isPublished" BOOLEAN NOT NULL DEFAULT false, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "createdById" TEXT NOT NULL, - - CONSTRAINT "LearningResource_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ResourceAccess" ( - "id" TEXT NOT NULL, - "resourceId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "accessedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "ipAddress" TEXT, - - CONSTRAINT "ResourceAccess_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Partner" ( - "id" TEXT NOT NULL, - "programId" TEXT, - "name" TEXT NOT NULL, - "description" TEXT, - "website" TEXT, - "partnerType" "PartnerType" NOT NULL DEFAULT 'PARTNER', - "visibility" "PartnerVisibility" NOT NULL DEFAULT 'ADMIN_ONLY', - "logoFileName" TEXT, - "logoBucket" TEXT, - "logoObjectKey" TEXT, - "sortOrder" INTEGER NOT NULL DEFAULT 0, - "isActive" BOOLEAN NOT NULL DEFAULT true, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Partner_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ApplicationForm" ( - "id" TEXT NOT NULL, - "programId" TEXT, - "name" TEXT NOT NULL, - "description" TEXT, - "status" TEXT NOT NULL DEFAULT 'DRAFT', - "isPublic" BOOLEAN NOT NULL DEFAULT false, - "publicSlug" TEXT, - "submissionLimit" INTEGER, - "opensAt" TIMESTAMP(3), - "closesAt" TIMESTAMP(3), - "confirmationMessage" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "ApplicationForm_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ApplicationFormField" ( - "id" TEXT NOT NULL, - "formId" TEXT NOT NULL, - "fieldType" "FormFieldType" NOT NULL, - "name" TEXT NOT NULL, - "label" TEXT NOT NULL, - "description" TEXT, - "placeholder" TEXT, - "required" BOOLEAN NOT NULL DEFAULT false, - "minLength" INTEGER, - "maxLength" INTEGER, - "minValue" DOUBLE PRECISION, - "maxValue" DOUBLE PRECISION, - "optionsJson" JSONB, - "conditionJson" JSONB, - "sortOrder" INTEGER NOT NULL DEFAULT 0, - "width" TEXT NOT NULL DEFAULT 'full', - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "ApplicationFormField_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ApplicationFormSubmission" ( - "id" TEXT NOT NULL, - "formId" TEXT NOT NULL, - "email" TEXT, - "name" TEXT, - "dataJson" JSONB NOT NULL, - "status" TEXT NOT NULL DEFAULT 'SUBMITTED', - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "ApplicationFormSubmission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "SubmissionFile" ( - "id" TEXT NOT NULL, - "submissionId" TEXT NOT NULL, - "fieldName" TEXT NOT NULL, - "fileName" TEXT NOT NULL, - "mimeType" TEXT, - "size" INTEGER, - "bucket" TEXT NOT NULL, - "objectKey" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "SubmissionFile_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ExpertiseTag" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "category" TEXT, - "color" TEXT, - "isActive" BOOLEAN NOT NULL DEFAULT true, - "sortOrder" INTEGER NOT NULL DEFAULT 0, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "ExpertiseTag_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "LiveVotingSession" ( - "id" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "status" TEXT NOT NULL DEFAULT 'NOT_STARTED', - "currentProjectIndex" INTEGER NOT NULL DEFAULT 0, - "currentProjectId" TEXT, - "votingStartedAt" TIMESTAMP(3), - "votingEndsAt" TIMESTAMP(3), - "projectOrderJson" JSONB, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "LiveVotingSession_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "LiveVote" ( - "id" TEXT NOT NULL, - "sessionId" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "score" INTEGER NOT NULL, - "votedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "LiveVote_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "TeamMember" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "role" "TeamMemberRole" NOT NULL DEFAULT 'MEMBER', - "title" TEXT, - "joinedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "TeamMember_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MentorAssignment" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "mentorId" TEXT NOT NULL, - "method" "MentorAssignmentMethod" NOT NULL DEFAULT 'MANUAL', - "assignedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "assignedBy" TEXT, - "aiConfidenceScore" DOUBLE PRECISION, - "expertiseMatchScore" DOUBLE PRECISION, - "aiReasoning" TEXT, - - CONSTRAINT "MentorAssignment_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); - --- CreateIndex -CREATE INDEX "User_email_idx" ON "User"("email"); - --- CreateIndex -CREATE INDEX "User_role_idx" ON "User"("role"); - --- CreateIndex -CREATE INDEX "User_status_idx" ON "User"("status"); - --- CreateIndex -CREATE INDEX "Account_userId_idx" ON "Account"("userId"); - --- CreateIndex -CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId"); - --- CreateIndex -CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken"); - --- CreateIndex -CREATE INDEX "Session_userId_idx" ON "Session"("userId"); - --- CreateIndex -CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token"); - --- CreateIndex -CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token"); - --- CreateIndex -CREATE INDEX "Program_status_idx" ON "Program"("status"); - --- CreateIndex -CREATE UNIQUE INDEX "Program_name_year_key" ON "Program"("name", "year"); - --- CreateIndex -CREATE UNIQUE INDEX "Round_slug_key" ON "Round"("slug"); - --- CreateIndex -CREATE INDEX "Round_programId_idx" ON "Round"("programId"); - --- CreateIndex -CREATE INDEX "Round_status_idx" ON "Round"("status"); - --- CreateIndex -CREATE INDEX "Round_roundType_idx" ON "Round"("roundType"); - --- CreateIndex -CREATE INDEX "Round_votingStartAt_votingEndAt_idx" ON "Round"("votingStartAt", "votingEndAt"); - --- CreateIndex -CREATE INDEX "Round_submissionStartDate_submissionEndDate_idx" ON "Round"("submissionStartDate", "submissionEndDate"); - --- CreateIndex -CREATE INDEX "EvaluationForm_roundId_isActive_idx" ON "EvaluationForm"("roundId", "isActive"); - --- CreateIndex -CREATE UNIQUE INDEX "EvaluationForm_roundId_version_key" ON "EvaluationForm"("roundId", "version"); - --- CreateIndex -CREATE INDEX "Project_roundId_idx" ON "Project"("roundId"); - --- CreateIndex -CREATE INDEX "Project_status_idx" ON "Project"("status"); - --- CreateIndex -CREATE INDEX "Project_tags_idx" ON "Project"("tags"); - --- CreateIndex -CREATE INDEX "Project_submissionSource_idx" ON "Project"("submissionSource"); - --- CreateIndex -CREATE INDEX "Project_submittedByUserId_idx" ON "Project"("submittedByUserId"); - --- CreateIndex -CREATE INDEX "Project_competitionCategory_idx" ON "Project"("competitionCategory"); - --- CreateIndex -CREATE INDEX "Project_oceanIssue_idx" ON "Project"("oceanIssue"); - --- CreateIndex -CREATE INDEX "Project_country_idx" ON "Project"("country"); - --- CreateIndex -CREATE INDEX "ProjectFile_projectId_idx" ON "ProjectFile"("projectId"); - --- CreateIndex -CREATE INDEX "ProjectFile_fileType_idx" ON "ProjectFile"("fileType"); - --- CreateIndex -CREATE UNIQUE INDEX "ProjectFile_bucket_objectKey_key" ON "ProjectFile"("bucket", "objectKey"); - --- CreateIndex -CREATE INDEX "Assignment_userId_idx" ON "Assignment"("userId"); - --- CreateIndex -CREATE INDEX "Assignment_projectId_idx" ON "Assignment"("projectId"); - --- CreateIndex -CREATE INDEX "Assignment_roundId_idx" ON "Assignment"("roundId"); - --- CreateIndex -CREATE INDEX "Assignment_isCompleted_idx" ON "Assignment"("isCompleted"); - --- CreateIndex -CREATE UNIQUE INDEX "Assignment_userId_projectId_roundId_key" ON "Assignment"("userId", "projectId", "roundId"); - --- CreateIndex -CREATE UNIQUE INDEX "Evaluation_assignmentId_key" ON "Evaluation"("assignmentId"); - --- CreateIndex -CREATE INDEX "Evaluation_status_idx" ON "Evaluation"("status"); - --- CreateIndex -CREATE INDEX "Evaluation_submittedAt_idx" ON "Evaluation"("submittedAt"); - --- CreateIndex -CREATE INDEX "Evaluation_formId_idx" ON "Evaluation"("formId"); - --- CreateIndex -CREATE INDEX "GracePeriod_roundId_idx" ON "GracePeriod"("roundId"); - --- CreateIndex -CREATE INDEX "GracePeriod_userId_idx" ON "GracePeriod"("userId"); - --- CreateIndex -CREATE INDEX "GracePeriod_extendedUntil_idx" ON "GracePeriod"("extendedUntil"); - --- CreateIndex -CREATE INDEX "GracePeriod_grantedById_idx" ON "GracePeriod"("grantedById"); - --- CreateIndex -CREATE INDEX "GracePeriod_projectId_idx" ON "GracePeriod"("projectId"); - --- CreateIndex -CREATE UNIQUE INDEX "SystemSettings_key_key" ON "SystemSettings"("key"); - --- CreateIndex -CREATE INDEX "SystemSettings_category_idx" ON "SystemSettings"("category"); - --- CreateIndex -CREATE INDEX "AuditLog_userId_idx" ON "AuditLog"("userId"); - --- CreateIndex -CREATE INDEX "AuditLog_action_idx" ON "AuditLog"("action"); - --- CreateIndex -CREATE INDEX "AuditLog_entityType_entityId_idx" ON "AuditLog"("entityType", "entityId"); - --- CreateIndex -CREATE INDEX "AuditLog_timestamp_idx" ON "AuditLog"("timestamp"); - --- CreateIndex -CREATE INDEX "NotificationLog_userId_idx" ON "NotificationLog"("userId"); - --- CreateIndex -CREATE INDEX "NotificationLog_status_idx" ON "NotificationLog"("status"); - --- CreateIndex -CREATE INDEX "NotificationLog_createdAt_idx" ON "NotificationLog"("createdAt"); - --- CreateIndex -CREATE INDEX "LearningResource_programId_idx" ON "LearningResource"("programId"); - --- CreateIndex -CREATE INDEX "LearningResource_cohortLevel_idx" ON "LearningResource"("cohortLevel"); - --- CreateIndex -CREATE INDEX "LearningResource_isPublished_idx" ON "LearningResource"("isPublished"); - --- CreateIndex -CREATE INDEX "LearningResource_sortOrder_idx" ON "LearningResource"("sortOrder"); - --- CreateIndex -CREATE INDEX "ResourceAccess_resourceId_idx" ON "ResourceAccess"("resourceId"); - --- CreateIndex -CREATE INDEX "ResourceAccess_userId_idx" ON "ResourceAccess"("userId"); - --- CreateIndex -CREATE INDEX "ResourceAccess_accessedAt_idx" ON "ResourceAccess"("accessedAt"); - --- CreateIndex -CREATE INDEX "Partner_programId_idx" ON "Partner"("programId"); - --- CreateIndex -CREATE INDEX "Partner_partnerType_idx" ON "Partner"("partnerType"); - --- CreateIndex -CREATE INDEX "Partner_visibility_idx" ON "Partner"("visibility"); - --- CreateIndex -CREATE INDEX "Partner_isActive_idx" ON "Partner"("isActive"); - --- CreateIndex -CREATE INDEX "Partner_sortOrder_idx" ON "Partner"("sortOrder"); - --- CreateIndex -CREATE UNIQUE INDEX "ApplicationForm_publicSlug_key" ON "ApplicationForm"("publicSlug"); - --- CreateIndex -CREATE INDEX "ApplicationForm_programId_idx" ON "ApplicationForm"("programId"); - --- CreateIndex -CREATE INDEX "ApplicationForm_status_idx" ON "ApplicationForm"("status"); - --- CreateIndex -CREATE INDEX "ApplicationForm_isPublic_idx" ON "ApplicationForm"("isPublic"); - --- CreateIndex -CREATE INDEX "ApplicationFormField_formId_idx" ON "ApplicationFormField"("formId"); - --- CreateIndex -CREATE INDEX "ApplicationFormField_sortOrder_idx" ON "ApplicationFormField"("sortOrder"); - --- CreateIndex -CREATE INDEX "ApplicationFormSubmission_formId_idx" ON "ApplicationFormSubmission"("formId"); - --- CreateIndex -CREATE INDEX "ApplicationFormSubmission_status_idx" ON "ApplicationFormSubmission"("status"); - --- CreateIndex -CREATE INDEX "ApplicationFormSubmission_email_idx" ON "ApplicationFormSubmission"("email"); - --- CreateIndex -CREATE INDEX "ApplicationFormSubmission_createdAt_idx" ON "ApplicationFormSubmission"("createdAt"); - --- CreateIndex -CREATE INDEX "SubmissionFile_submissionId_idx" ON "SubmissionFile"("submissionId"); - --- CreateIndex -CREATE UNIQUE INDEX "SubmissionFile_bucket_objectKey_key" ON "SubmissionFile"("bucket", "objectKey"); - --- CreateIndex -CREATE UNIQUE INDEX "ExpertiseTag_name_key" ON "ExpertiseTag"("name"); - --- CreateIndex -CREATE INDEX "ExpertiseTag_category_idx" ON "ExpertiseTag"("category"); - --- CreateIndex -CREATE INDEX "ExpertiseTag_isActive_idx" ON "ExpertiseTag"("isActive"); - --- CreateIndex -CREATE INDEX "ExpertiseTag_sortOrder_idx" ON "ExpertiseTag"("sortOrder"); - --- CreateIndex -CREATE UNIQUE INDEX "LiveVotingSession_roundId_key" ON "LiveVotingSession"("roundId"); - --- CreateIndex -CREATE INDEX "LiveVotingSession_status_idx" ON "LiveVotingSession"("status"); - --- CreateIndex -CREATE INDEX "LiveVote_sessionId_idx" ON "LiveVote"("sessionId"); - --- CreateIndex -CREATE INDEX "LiveVote_projectId_idx" ON "LiveVote"("projectId"); - --- CreateIndex -CREATE INDEX "LiveVote_userId_idx" ON "LiveVote"("userId"); - --- CreateIndex -CREATE UNIQUE INDEX "LiveVote_sessionId_projectId_userId_key" ON "LiveVote"("sessionId", "projectId", "userId"); - --- CreateIndex -CREATE INDEX "TeamMember_projectId_idx" ON "TeamMember"("projectId"); - --- CreateIndex -CREATE INDEX "TeamMember_userId_idx" ON "TeamMember"("userId"); - --- CreateIndex -CREATE INDEX "TeamMember_role_idx" ON "TeamMember"("role"); - --- CreateIndex -CREATE UNIQUE INDEX "TeamMember_projectId_userId_key" ON "TeamMember"("projectId", "userId"); - --- CreateIndex -CREATE UNIQUE INDEX "MentorAssignment_projectId_key" ON "MentorAssignment"("projectId"); - --- CreateIndex -CREATE INDEX "MentorAssignment_mentorId_idx" ON "MentorAssignment"("mentorId"); - --- CreateIndex -CREATE INDEX "MentorAssignment_method_idx" ON "MentorAssignment"("method"); - --- AddForeignKey -ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Round" ADD CONSTRAINT "Round_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "EvaluationForm" ADD CONSTRAINT "EvaluationForm_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_submittedByUserId_fkey" FOREIGN KEY ("submittedByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_assignmentId_fkey" FOREIGN KEY ("assignmentId") REFERENCES "Assignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_formId_fkey" FOREIGN KEY ("formId") REFERENCES "EvaluationForm"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_grantedById_fkey" FOREIGN KEY ("grantedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "AuditLog" ADD CONSTRAINT "AuditLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "NotificationLog" ADD CONSTRAINT "NotificationLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "LearningResource" ADD CONSTRAINT "LearningResource_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "LearningResource" ADD CONSTRAINT "LearningResource_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ResourceAccess" ADD CONSTRAINT "ResourceAccess_resourceId_fkey" FOREIGN KEY ("resourceId") REFERENCES "LearningResource"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ResourceAccess" ADD CONSTRAINT "ResourceAccess_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Partner" ADD CONSTRAINT "Partner_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ApplicationForm" ADD CONSTRAINT "ApplicationForm_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ApplicationFormField" ADD CONSTRAINT "ApplicationFormField_formId_fkey" FOREIGN KEY ("formId") REFERENCES "ApplicationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ApplicationFormSubmission" ADD CONSTRAINT "ApplicationFormSubmission_formId_fkey" FOREIGN KEY ("formId") REFERENCES "ApplicationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "SubmissionFile" ADD CONSTRAINT "SubmissionFile_submissionId_fkey" FOREIGN KEY ("submissionId") REFERENCES "ApplicationFormSubmission"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "LiveVotingSession" ADD CONSTRAINT "LiveVotingSession_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TeamMember" ADD CONSTRAINT "TeamMember_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TeamMember" ADD CONSTRAINT "TeamMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorAssignment" ADD CONSTRAINT "MentorAssignment_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorAssignment" ADD CONSTRAINT "MentorAssignment_mentorId_fkey" FOREIGN KEY ("mentorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - +-- CreateSchema +CREATE SCHEMA IF NOT EXISTS "public"; + +-- CreateEnum +CREATE TYPE "UserRole" AS ENUM ('SUPER_ADMIN', 'PROGRAM_ADMIN', 'JURY_MEMBER', 'MENTOR', 'OBSERVER', 'APPLICANT'); + +-- CreateEnum +CREATE TYPE "UserStatus" AS ENUM ('NONE', 'INVITED', 'ACTIVE', 'SUSPENDED'); + +-- CreateEnum +CREATE TYPE "ProgramStatus" AS ENUM ('DRAFT', 'ACTIVE', 'ARCHIVED'); + +-- CreateEnum +CREATE TYPE "RoundStatus" AS ENUM ('DRAFT', 'ACTIVE', 'CLOSED', 'ARCHIVED'); + +-- CreateEnum +CREATE TYPE "ProjectStatus" AS ENUM ('SUBMITTED', 'ELIGIBLE', 'ASSIGNED', 'SEMIFINALIST', 'FINALIST', 'REJECTED'); + +-- CreateEnum +CREATE TYPE "EvaluationStatus" AS ENUM ('NOT_STARTED', 'DRAFT', 'SUBMITTED', 'LOCKED'); + +-- CreateEnum +CREATE TYPE "AssignmentMethod" AS ENUM ('MANUAL', 'BULK', 'AI_SUGGESTED', 'AI_AUTO', 'ALGORITHM'); + +-- CreateEnum +CREATE TYPE "FileType" AS ENUM ('EXEC_SUMMARY', 'PRESENTATION', 'VIDEO', 'OTHER', 'BUSINESS_PLAN', 'VIDEO_PITCH', 'SUPPORTING_DOC'); + +-- CreateEnum +CREATE TYPE "SubmissionSource" AS ENUM ('MANUAL', 'CSV', 'NOTION', 'TYPEFORM', 'PUBLIC_FORM'); + +-- CreateEnum +CREATE TYPE "RoundType" AS ENUM ('FILTERING', 'EVALUATION', 'LIVE_EVENT'); + +-- CreateEnum +CREATE TYPE "SettingType" AS ENUM ('STRING', 'NUMBER', 'BOOLEAN', 'JSON', 'SECRET'); + +-- CreateEnum +CREATE TYPE "SettingCategory" AS ENUM ('AI', 'BRANDING', 'EMAIL', 'STORAGE', 'SECURITY', 'DEFAULTS', 'WHATSAPP'); + +-- CreateEnum +CREATE TYPE "NotificationChannel" AS ENUM ('EMAIL', 'WHATSAPP', 'BOTH', 'NONE'); + +-- CreateEnum +CREATE TYPE "ResourceType" AS ENUM ('PDF', 'VIDEO', 'DOCUMENT', 'LINK', 'OTHER'); + +-- CreateEnum +CREATE TYPE "CohortLevel" AS ENUM ('ALL', 'SEMIFINALIST', 'FINALIST'); + +-- CreateEnum +CREATE TYPE "PartnerVisibility" AS ENUM ('ADMIN_ONLY', 'JURY_VISIBLE', 'PUBLIC'); + +-- CreateEnum +CREATE TYPE "PartnerType" AS ENUM ('SPONSOR', 'PARTNER', 'SUPPORTER', 'MEDIA', 'OTHER'); + +-- CreateEnum +CREATE TYPE "FormFieldType" AS ENUM ('TEXT', 'TEXTAREA', 'NUMBER', 'EMAIL', 'PHONE', 'URL', 'DATE', 'DATETIME', 'SELECT', 'MULTI_SELECT', 'RADIO', 'CHECKBOX', 'CHECKBOX_GROUP', 'FILE', 'FILE_MULTIPLE', 'SECTION', 'INSTRUCTIONS'); + +-- CreateEnum +CREATE TYPE "CompetitionCategory" AS ENUM ('STARTUP', 'BUSINESS_CONCEPT'); + +-- CreateEnum +CREATE TYPE "OceanIssue" AS ENUM ('POLLUTION_REDUCTION', 'CLIMATE_MITIGATION', 'TECHNOLOGY_INNOVATION', 'SUSTAINABLE_SHIPPING', 'BLUE_CARBON', 'HABITAT_RESTORATION', 'COMMUNITY_CAPACITY', 'SUSTAINABLE_FISHING', 'CONSUMER_AWARENESS', 'OCEAN_ACIDIFICATION', 'OTHER'); + +-- CreateEnum +CREATE TYPE "TeamMemberRole" AS ENUM ('LEAD', 'MEMBER', 'ADVISOR'); + +-- CreateEnum +CREATE TYPE "MentorAssignmentMethod" AS ENUM ('MANUAL', 'AI_SUGGESTED', 'AI_AUTO', 'ALGORITHM'); + +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "email" TEXT NOT NULL, + "name" TEXT, + "emailVerified" TIMESTAMP(3), + "role" "UserRole" NOT NULL DEFAULT 'JURY_MEMBER', + "status" "UserStatus" NOT NULL DEFAULT 'INVITED', + "expertiseTags" TEXT[] DEFAULT ARRAY[]::TEXT[], + "maxAssignments" INTEGER, + "metadataJson" JSONB, + "profileImageKey" TEXT, + "profileImageProvider" TEXT, + "phoneNumber" TEXT, + "phoneNumberVerified" BOOLEAN NOT NULL DEFAULT false, + "notificationPreference" "NotificationChannel" NOT NULL DEFAULT 'EMAIL', + "whatsappOptIn" BOOLEAN NOT NULL DEFAULT false, + "onboardingCompletedAt" TIMESTAMP(3), + "passwordHash" TEXT, + "passwordSetAt" TIMESTAMP(3), + "mustSetPassword" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "lastLoginAt" TIMESTAMP(3), + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Account" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "type" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "refresh_token" TEXT, + "access_token" TEXT, + "expires_at" INTEGER, + "token_type" TEXT, + "scope" TEXT, + "id_token" TEXT, + "session_state" TEXT, + + CONSTRAINT "Account_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Session" ( + "id" TEXT NOT NULL, + "sessionToken" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Session_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "VerificationToken" ( + "identifier" TEXT NOT NULL, + "token" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL +); + +-- CreateTable +CREATE TABLE "Program" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "year" INTEGER NOT NULL, + "status" "ProgramStatus" NOT NULL DEFAULT 'DRAFT', + "description" TEXT, + "settingsJson" JSONB, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Program_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Round" ( + "id" TEXT NOT NULL, + "programId" TEXT NOT NULL, + "name" TEXT NOT NULL, + "slug" TEXT, + "status" "RoundStatus" NOT NULL DEFAULT 'DRAFT', + "roundType" "RoundType" NOT NULL DEFAULT 'EVALUATION', + "submissionDeadline" TIMESTAMP(3), + "submissionStartDate" TIMESTAMP(3), + "submissionEndDate" TIMESTAMP(3), + "lateSubmissionGrace" INTEGER, + "phase1Deadline" TIMESTAMP(3), + "phase2Deadline" TIMESTAMP(3), + "votingStartAt" TIMESTAMP(3), + "votingEndAt" TIMESTAMP(3), + "requiredReviews" INTEGER NOT NULL DEFAULT 3, + "settingsJson" JSONB, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Round_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "EvaluationForm" ( + "id" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "version" INTEGER NOT NULL DEFAULT 1, + "criteriaJson" JSONB NOT NULL, + "scalesJson" JSONB, + "isActive" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "EvaluationForm_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Project" ( + "id" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "title" TEXT NOT NULL, + "teamName" TEXT, + "description" TEXT, + "status" "ProjectStatus" NOT NULL DEFAULT 'SUBMITTED', + "competitionCategory" "CompetitionCategory", + "oceanIssue" "OceanIssue", + "country" TEXT, + "geographicZone" TEXT, + "institution" TEXT, + "wantsMentorship" BOOLEAN NOT NULL DEFAULT false, + "phase1SubmissionUrl" TEXT, + "phase2SubmissionUrl" TEXT, + "referralSource" TEXT, + "internalComments" TEXT, + "applicationStatus" TEXT, + "submissionSource" "SubmissionSource" NOT NULL DEFAULT 'MANUAL', + "submittedByEmail" TEXT, + "submittedAt" TIMESTAMP(3), + "submittedByUserId" TEXT, + "logoKey" TEXT, + "logoProvider" TEXT, + "tags" TEXT[] DEFAULT ARRAY[]::TEXT[], + "metadataJson" JSONB, + "externalIdsJson" JSONB, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Project_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProjectFile" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "fileType" "FileType" NOT NULL, + "fileName" TEXT NOT NULL, + "mimeType" TEXT NOT NULL, + "size" INTEGER NOT NULL, + "bucket" TEXT NOT NULL, + "objectKey" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "ProjectFile_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Assignment" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "method" "AssignmentMethod" NOT NULL DEFAULT 'MANUAL', + "isRequired" BOOLEAN NOT NULL DEFAULT true, + "isCompleted" BOOLEAN NOT NULL DEFAULT false, + "aiConfidenceScore" DOUBLE PRECISION, + "expertiseMatchScore" DOUBLE PRECISION, + "aiReasoning" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "createdBy" TEXT, + + CONSTRAINT "Assignment_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Evaluation" ( + "id" TEXT NOT NULL, + "assignmentId" TEXT NOT NULL, + "formId" TEXT NOT NULL, + "status" "EvaluationStatus" NOT NULL DEFAULT 'NOT_STARTED', + "criterionScoresJson" JSONB, + "globalScore" INTEGER, + "binaryDecision" BOOLEAN, + "feedbackText" TEXT, + "version" INTEGER NOT NULL DEFAULT 1, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "submittedAt" TIMESTAMP(3), + + CONSTRAINT "Evaluation_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "GracePeriod" ( + "id" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "projectId" TEXT, + "extendedUntil" TIMESTAMP(3) NOT NULL, + "reason" TEXT, + "grantedById" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "GracePeriod_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "SystemSettings" ( + "id" TEXT NOT NULL, + "key" TEXT NOT NULL, + "value" TEXT NOT NULL, + "type" "SettingType" NOT NULL DEFAULT 'STRING', + "category" "SettingCategory" NOT NULL, + "description" TEXT, + "isSecret" BOOLEAN NOT NULL DEFAULT false, + "updatedAt" TIMESTAMP(3) NOT NULL, + "updatedBy" TEXT, + + CONSTRAINT "SystemSettings_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "AuditLog" ( + "id" TEXT NOT NULL, + "userId" TEXT, + "action" TEXT NOT NULL, + "entityType" TEXT NOT NULL, + "entityId" TEXT, + "detailsJson" JSONB, + "ipAddress" TEXT, + "userAgent" TEXT, + "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "NotificationLog" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "channel" "NotificationChannel" NOT NULL, + "provider" TEXT, + "type" TEXT NOT NULL, + "status" TEXT NOT NULL, + "externalId" TEXT, + "errorMsg" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "NotificationLog_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "LearningResource" ( + "id" TEXT NOT NULL, + "programId" TEXT, + "title" TEXT NOT NULL, + "description" TEXT, + "contentJson" JSONB, + "resourceType" "ResourceType" NOT NULL, + "cohortLevel" "CohortLevel" NOT NULL DEFAULT 'ALL', + "fileName" TEXT, + "mimeType" TEXT, + "size" INTEGER, + "bucket" TEXT, + "objectKey" TEXT, + "externalUrl" TEXT, + "sortOrder" INTEGER NOT NULL DEFAULT 0, + "isPublished" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "createdById" TEXT NOT NULL, + + CONSTRAINT "LearningResource_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ResourceAccess" ( + "id" TEXT NOT NULL, + "resourceId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "accessedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "ipAddress" TEXT, + + CONSTRAINT "ResourceAccess_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Partner" ( + "id" TEXT NOT NULL, + "programId" TEXT, + "name" TEXT NOT NULL, + "description" TEXT, + "website" TEXT, + "partnerType" "PartnerType" NOT NULL DEFAULT 'PARTNER', + "visibility" "PartnerVisibility" NOT NULL DEFAULT 'ADMIN_ONLY', + "logoFileName" TEXT, + "logoBucket" TEXT, + "logoObjectKey" TEXT, + "sortOrder" INTEGER NOT NULL DEFAULT 0, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Partner_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ApplicationForm" ( + "id" TEXT NOT NULL, + "programId" TEXT, + "name" TEXT NOT NULL, + "description" TEXT, + "status" TEXT NOT NULL DEFAULT 'DRAFT', + "isPublic" BOOLEAN NOT NULL DEFAULT false, + "publicSlug" TEXT, + "submissionLimit" INTEGER, + "opensAt" TIMESTAMP(3), + "closesAt" TIMESTAMP(3), + "confirmationMessage" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ApplicationForm_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ApplicationFormField" ( + "id" TEXT NOT NULL, + "formId" TEXT NOT NULL, + "fieldType" "FormFieldType" NOT NULL, + "name" TEXT NOT NULL, + "label" TEXT NOT NULL, + "description" TEXT, + "placeholder" TEXT, + "required" BOOLEAN NOT NULL DEFAULT false, + "minLength" INTEGER, + "maxLength" INTEGER, + "minValue" DOUBLE PRECISION, + "maxValue" DOUBLE PRECISION, + "optionsJson" JSONB, + "conditionJson" JSONB, + "sortOrder" INTEGER NOT NULL DEFAULT 0, + "width" TEXT NOT NULL DEFAULT 'full', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ApplicationFormField_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ApplicationFormSubmission" ( + "id" TEXT NOT NULL, + "formId" TEXT NOT NULL, + "email" TEXT, + "name" TEXT, + "dataJson" JSONB NOT NULL, + "status" TEXT NOT NULL DEFAULT 'SUBMITTED', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ApplicationFormSubmission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "SubmissionFile" ( + "id" TEXT NOT NULL, + "submissionId" TEXT NOT NULL, + "fieldName" TEXT NOT NULL, + "fileName" TEXT NOT NULL, + "mimeType" TEXT, + "size" INTEGER, + "bucket" TEXT NOT NULL, + "objectKey" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "SubmissionFile_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ExpertiseTag" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "category" TEXT, + "color" TEXT, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "sortOrder" INTEGER NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ExpertiseTag_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "LiveVotingSession" ( + "id" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'NOT_STARTED', + "currentProjectIndex" INTEGER NOT NULL DEFAULT 0, + "currentProjectId" TEXT, + "votingStartedAt" TIMESTAMP(3), + "votingEndsAt" TIMESTAMP(3), + "projectOrderJson" JSONB, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "LiveVotingSession_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "LiveVote" ( + "id" TEXT NOT NULL, + "sessionId" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "score" INTEGER NOT NULL, + "votedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "LiveVote_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "TeamMember" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "role" "TeamMemberRole" NOT NULL DEFAULT 'MEMBER', + "title" TEXT, + "joinedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "TeamMember_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MentorAssignment" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "mentorId" TEXT NOT NULL, + "method" "MentorAssignmentMethod" NOT NULL DEFAULT 'MANUAL', + "assignedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "assignedBy" TEXT, + "aiConfidenceScore" DOUBLE PRECISION, + "expertiseMatchScore" DOUBLE PRECISION, + "aiReasoning" TEXT, + + CONSTRAINT "MentorAssignment_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE INDEX "User_email_idx" ON "User"("email"); + +-- CreateIndex +CREATE INDEX "User_role_idx" ON "User"("role"); + +-- CreateIndex +CREATE INDEX "User_status_idx" ON "User"("status"); + +-- CreateIndex +CREATE INDEX "Account_userId_idx" ON "Account"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken"); + +-- CreateIndex +CREATE INDEX "Session_userId_idx" ON "Session"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token"); + +-- CreateIndex +CREATE INDEX "Program_status_idx" ON "Program"("status"); + +-- CreateIndex +CREATE UNIQUE INDEX "Program_name_year_key" ON "Program"("name", "year"); + +-- CreateIndex +CREATE UNIQUE INDEX "Round_slug_key" ON "Round"("slug"); + +-- CreateIndex +CREATE INDEX "Round_programId_idx" ON "Round"("programId"); + +-- CreateIndex +CREATE INDEX "Round_status_idx" ON "Round"("status"); + +-- CreateIndex +CREATE INDEX "Round_roundType_idx" ON "Round"("roundType"); + +-- CreateIndex +CREATE INDEX "Round_votingStartAt_votingEndAt_idx" ON "Round"("votingStartAt", "votingEndAt"); + +-- CreateIndex +CREATE INDEX "Round_submissionStartDate_submissionEndDate_idx" ON "Round"("submissionStartDate", "submissionEndDate"); + +-- CreateIndex +CREATE INDEX "EvaluationForm_roundId_isActive_idx" ON "EvaluationForm"("roundId", "isActive"); + +-- CreateIndex +CREATE UNIQUE INDEX "EvaluationForm_roundId_version_key" ON "EvaluationForm"("roundId", "version"); + +-- CreateIndex +CREATE INDEX "Project_roundId_idx" ON "Project"("roundId"); + +-- CreateIndex +CREATE INDEX "Project_status_idx" ON "Project"("status"); + +-- CreateIndex +CREATE INDEX "Project_tags_idx" ON "Project"("tags"); + +-- CreateIndex +CREATE INDEX "Project_submissionSource_idx" ON "Project"("submissionSource"); + +-- CreateIndex +CREATE INDEX "Project_submittedByUserId_idx" ON "Project"("submittedByUserId"); + +-- CreateIndex +CREATE INDEX "Project_competitionCategory_idx" ON "Project"("competitionCategory"); + +-- CreateIndex +CREATE INDEX "Project_oceanIssue_idx" ON "Project"("oceanIssue"); + +-- CreateIndex +CREATE INDEX "Project_country_idx" ON "Project"("country"); + +-- CreateIndex +CREATE INDEX "ProjectFile_projectId_idx" ON "ProjectFile"("projectId"); + +-- CreateIndex +CREATE INDEX "ProjectFile_fileType_idx" ON "ProjectFile"("fileType"); + +-- CreateIndex +CREATE UNIQUE INDEX "ProjectFile_bucket_objectKey_key" ON "ProjectFile"("bucket", "objectKey"); + +-- CreateIndex +CREATE INDEX "Assignment_userId_idx" ON "Assignment"("userId"); + +-- CreateIndex +CREATE INDEX "Assignment_projectId_idx" ON "Assignment"("projectId"); + +-- CreateIndex +CREATE INDEX "Assignment_roundId_idx" ON "Assignment"("roundId"); + +-- CreateIndex +CREATE INDEX "Assignment_isCompleted_idx" ON "Assignment"("isCompleted"); + +-- CreateIndex +CREATE UNIQUE INDEX "Assignment_userId_projectId_roundId_key" ON "Assignment"("userId", "projectId", "roundId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Evaluation_assignmentId_key" ON "Evaluation"("assignmentId"); + +-- CreateIndex +CREATE INDEX "Evaluation_status_idx" ON "Evaluation"("status"); + +-- CreateIndex +CREATE INDEX "Evaluation_submittedAt_idx" ON "Evaluation"("submittedAt"); + +-- CreateIndex +CREATE INDEX "Evaluation_formId_idx" ON "Evaluation"("formId"); + +-- CreateIndex +CREATE INDEX "GracePeriod_roundId_idx" ON "GracePeriod"("roundId"); + +-- CreateIndex +CREATE INDEX "GracePeriod_userId_idx" ON "GracePeriod"("userId"); + +-- CreateIndex +CREATE INDEX "GracePeriod_extendedUntil_idx" ON "GracePeriod"("extendedUntil"); + +-- CreateIndex +CREATE INDEX "GracePeriod_grantedById_idx" ON "GracePeriod"("grantedById"); + +-- CreateIndex +CREATE INDEX "GracePeriod_projectId_idx" ON "GracePeriod"("projectId"); + +-- CreateIndex +CREATE UNIQUE INDEX "SystemSettings_key_key" ON "SystemSettings"("key"); + +-- CreateIndex +CREATE INDEX "SystemSettings_category_idx" ON "SystemSettings"("category"); + +-- CreateIndex +CREATE INDEX "AuditLog_userId_idx" ON "AuditLog"("userId"); + +-- CreateIndex +CREATE INDEX "AuditLog_action_idx" ON "AuditLog"("action"); + +-- CreateIndex +CREATE INDEX "AuditLog_entityType_entityId_idx" ON "AuditLog"("entityType", "entityId"); + +-- CreateIndex +CREATE INDEX "AuditLog_timestamp_idx" ON "AuditLog"("timestamp"); + +-- CreateIndex +CREATE INDEX "NotificationLog_userId_idx" ON "NotificationLog"("userId"); + +-- CreateIndex +CREATE INDEX "NotificationLog_status_idx" ON "NotificationLog"("status"); + +-- CreateIndex +CREATE INDEX "NotificationLog_createdAt_idx" ON "NotificationLog"("createdAt"); + +-- CreateIndex +CREATE INDEX "LearningResource_programId_idx" ON "LearningResource"("programId"); + +-- CreateIndex +CREATE INDEX "LearningResource_cohortLevel_idx" ON "LearningResource"("cohortLevel"); + +-- CreateIndex +CREATE INDEX "LearningResource_isPublished_idx" ON "LearningResource"("isPublished"); + +-- CreateIndex +CREATE INDEX "LearningResource_sortOrder_idx" ON "LearningResource"("sortOrder"); + +-- CreateIndex +CREATE INDEX "ResourceAccess_resourceId_idx" ON "ResourceAccess"("resourceId"); + +-- CreateIndex +CREATE INDEX "ResourceAccess_userId_idx" ON "ResourceAccess"("userId"); + +-- CreateIndex +CREATE INDEX "ResourceAccess_accessedAt_idx" ON "ResourceAccess"("accessedAt"); + +-- CreateIndex +CREATE INDEX "Partner_programId_idx" ON "Partner"("programId"); + +-- CreateIndex +CREATE INDEX "Partner_partnerType_idx" ON "Partner"("partnerType"); + +-- CreateIndex +CREATE INDEX "Partner_visibility_idx" ON "Partner"("visibility"); + +-- CreateIndex +CREATE INDEX "Partner_isActive_idx" ON "Partner"("isActive"); + +-- CreateIndex +CREATE INDEX "Partner_sortOrder_idx" ON "Partner"("sortOrder"); + +-- CreateIndex +CREATE UNIQUE INDEX "ApplicationForm_publicSlug_key" ON "ApplicationForm"("publicSlug"); + +-- CreateIndex +CREATE INDEX "ApplicationForm_programId_idx" ON "ApplicationForm"("programId"); + +-- CreateIndex +CREATE INDEX "ApplicationForm_status_idx" ON "ApplicationForm"("status"); + +-- CreateIndex +CREATE INDEX "ApplicationForm_isPublic_idx" ON "ApplicationForm"("isPublic"); + +-- CreateIndex +CREATE INDEX "ApplicationFormField_formId_idx" ON "ApplicationFormField"("formId"); + +-- CreateIndex +CREATE INDEX "ApplicationFormField_sortOrder_idx" ON "ApplicationFormField"("sortOrder"); + +-- CreateIndex +CREATE INDEX "ApplicationFormSubmission_formId_idx" ON "ApplicationFormSubmission"("formId"); + +-- CreateIndex +CREATE INDEX "ApplicationFormSubmission_status_idx" ON "ApplicationFormSubmission"("status"); + +-- CreateIndex +CREATE INDEX "ApplicationFormSubmission_email_idx" ON "ApplicationFormSubmission"("email"); + +-- CreateIndex +CREATE INDEX "ApplicationFormSubmission_createdAt_idx" ON "ApplicationFormSubmission"("createdAt"); + +-- CreateIndex +CREATE INDEX "SubmissionFile_submissionId_idx" ON "SubmissionFile"("submissionId"); + +-- CreateIndex +CREATE UNIQUE INDEX "SubmissionFile_bucket_objectKey_key" ON "SubmissionFile"("bucket", "objectKey"); + +-- CreateIndex +CREATE UNIQUE INDEX "ExpertiseTag_name_key" ON "ExpertiseTag"("name"); + +-- CreateIndex +CREATE INDEX "ExpertiseTag_category_idx" ON "ExpertiseTag"("category"); + +-- CreateIndex +CREATE INDEX "ExpertiseTag_isActive_idx" ON "ExpertiseTag"("isActive"); + +-- CreateIndex +CREATE INDEX "ExpertiseTag_sortOrder_idx" ON "ExpertiseTag"("sortOrder"); + +-- CreateIndex +CREATE UNIQUE INDEX "LiveVotingSession_roundId_key" ON "LiveVotingSession"("roundId"); + +-- CreateIndex +CREATE INDEX "LiveVotingSession_status_idx" ON "LiveVotingSession"("status"); + +-- CreateIndex +CREATE INDEX "LiveVote_sessionId_idx" ON "LiveVote"("sessionId"); + +-- CreateIndex +CREATE INDEX "LiveVote_projectId_idx" ON "LiveVote"("projectId"); + +-- CreateIndex +CREATE INDEX "LiveVote_userId_idx" ON "LiveVote"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "LiveVote_sessionId_projectId_userId_key" ON "LiveVote"("sessionId", "projectId", "userId"); + +-- CreateIndex +CREATE INDEX "TeamMember_projectId_idx" ON "TeamMember"("projectId"); + +-- CreateIndex +CREATE INDEX "TeamMember_userId_idx" ON "TeamMember"("userId"); + +-- CreateIndex +CREATE INDEX "TeamMember_role_idx" ON "TeamMember"("role"); + +-- CreateIndex +CREATE UNIQUE INDEX "TeamMember_projectId_userId_key" ON "TeamMember"("projectId", "userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "MentorAssignment_projectId_key" ON "MentorAssignment"("projectId"); + +-- CreateIndex +CREATE INDEX "MentorAssignment_mentorId_idx" ON "MentorAssignment"("mentorId"); + +-- CreateIndex +CREATE INDEX "MentorAssignment_method_idx" ON "MentorAssignment"("method"); + +-- AddForeignKey +ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Round" ADD CONSTRAINT "Round_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EvaluationForm" ADD CONSTRAINT "EvaluationForm_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_submittedByUserId_fkey" FOREIGN KEY ("submittedByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_assignmentId_fkey" FOREIGN KEY ("assignmentId") REFERENCES "Assignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_formId_fkey" FOREIGN KEY ("formId") REFERENCES "EvaluationForm"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_grantedById_fkey" FOREIGN KEY ("grantedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AuditLog" ADD CONSTRAINT "AuditLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "NotificationLog" ADD CONSTRAINT "NotificationLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LearningResource" ADD CONSTRAINT "LearningResource_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LearningResource" ADD CONSTRAINT "LearningResource_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ResourceAccess" ADD CONSTRAINT "ResourceAccess_resourceId_fkey" FOREIGN KEY ("resourceId") REFERENCES "LearningResource"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ResourceAccess" ADD CONSTRAINT "ResourceAccess_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Partner" ADD CONSTRAINT "Partner_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ApplicationForm" ADD CONSTRAINT "ApplicationForm_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ApplicationFormField" ADD CONSTRAINT "ApplicationFormField_formId_fkey" FOREIGN KEY ("formId") REFERENCES "ApplicationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ApplicationFormSubmission" ADD CONSTRAINT "ApplicationFormSubmission_formId_fkey" FOREIGN KEY ("formId") REFERENCES "ApplicationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "SubmissionFile" ADD CONSTRAINT "SubmissionFile_submissionId_fkey" FOREIGN KEY ("submissionId") REFERENCES "ApplicationFormSubmission"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LiveVotingSession" ADD CONSTRAINT "LiveVotingSession_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TeamMember" ADD CONSTRAINT "TeamMember_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TeamMember" ADD CONSTRAINT "TeamMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorAssignment" ADD CONSTRAINT "MentorAssignment_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorAssignment" ADD CONSTRAINT "MentorAssignment_mentorId_fkey" FOREIGN KEY ("mentorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + diff --git a/prisma/migrations/20260205223133_add_15_features/migration.sql b/prisma/migrations/20260205223133_add_15_features/migration.sql index 5ce6014..6bf7951 100644 --- a/prisma/migrations/20260205223133_add_15_features/migration.sql +++ b/prisma/migrations/20260205223133_add_15_features/migration.sql @@ -1,550 +1,550 @@ -/* - Warnings: - - - You are about to drop the `ApplicationForm` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `ApplicationFormField` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `ApplicationFormSubmission` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `OnboardingStep` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `SubmissionFile` table. If the table is not empty, all the data it contains will be lost. - -*/ --- AlterEnum --- This migration adds more than one value to an enum. --- With PostgreSQL versions 11 and earlier, this is not possible --- in a single migration. This can be worked around by creating --- multiple migrations, each migration adding only one value to --- the enum. - - -ALTER TYPE "SettingCategory" ADD VALUE 'DIGEST'; -ALTER TYPE "SettingCategory" ADD VALUE 'ANALYTICS'; -ALTER TYPE "SettingCategory" ADD VALUE 'AUDIT_CONFIG'; -ALTER TYPE "SettingCategory" ADD VALUE 'INTEGRATIONS'; -ALTER TYPE "SettingCategory" ADD VALUE 'LOCALIZATION'; -ALTER TYPE "SettingCategory" ADD VALUE 'COMMUNICATION'; - --- DropForeignKey -ALTER TABLE "ApplicationForm" DROP CONSTRAINT "ApplicationForm_programId_fkey"; - --- DropForeignKey -ALTER TABLE "ApplicationForm" DROP CONSTRAINT "ApplicationForm_roundId_fkey"; - --- DropForeignKey -ALTER TABLE "ApplicationFormField" DROP CONSTRAINT "ApplicationFormField_formId_fkey"; - --- DropForeignKey -ALTER TABLE "ApplicationFormField" DROP CONSTRAINT "ApplicationFormField_stepId_fkey"; - --- DropForeignKey -ALTER TABLE "ApplicationFormSubmission" DROP CONSTRAINT "ApplicationFormSubmission_formId_fkey"; - --- DropForeignKey -ALTER TABLE "OnboardingStep" DROP CONSTRAINT "OnboardingStep_formId_fkey"; - --- DropForeignKey -ALTER TABLE "SubmissionFile" DROP CONSTRAINT "SubmissionFile_submissionId_fkey"; - --- DropIndex -DROP INDEX "User_email_idx"; - --- AlterTable -ALTER TABLE "AssignmentJob" ALTER COLUMN "updatedAt" DROP DEFAULT; - --- AlterTable -ALTER TABLE "AuditLog" ADD COLUMN "previousDataJson" JSONB, -ADD COLUMN "sessionId" TEXT; - --- AlterTable -ALTER TABLE "FilteringJob" ALTER COLUMN "updatedAt" DROP DEFAULT; - --- AlterTable -ALTER TABLE "LiveVote" ADD COLUMN "isAudienceVote" BOOLEAN NOT NULL DEFAULT false; - --- AlterTable -ALTER TABLE "LiveVotingSession" ADD COLUMN "allowAudienceVotes" BOOLEAN NOT NULL DEFAULT false, -ADD COLUMN "audienceVoteWeight" DOUBLE PRECISION NOT NULL DEFAULT 0, -ADD COLUMN "presentationSettingsJson" JSONB, -ADD COLUMN "tieBreakerMethod" TEXT NOT NULL DEFAULT 'admin_decides'; - --- AlterTable -ALTER TABLE "MentorAssignment" ADD COLUMN "completionStatus" TEXT NOT NULL DEFAULT 'in_progress', -ADD COLUMN "lastViewedAt" TIMESTAMP(3); - --- AlterTable -ALTER TABLE "NotificationEmailSetting" ALTER COLUMN "updatedAt" DROP DEFAULT; - --- AlterTable -ALTER TABLE "Project" ADD COLUMN "draftDataJson" JSONB, -ADD COLUMN "draftExpiresAt" TIMESTAMP(3), -ADD COLUMN "isDraft" BOOLEAN NOT NULL DEFAULT false; - --- AlterTable -ALTER TABLE "ProjectFile" ADD COLUMN "isLate" BOOLEAN NOT NULL DEFAULT false, -ADD COLUMN "replacedById" TEXT, -ADD COLUMN "roundId" TEXT, -ADD COLUMN "version" INTEGER NOT NULL DEFAULT 1; - --- AlterTable -ALTER TABLE "TaggingJob" ALTER COLUMN "updatedAt" DROP DEFAULT; - --- AlterTable -ALTER TABLE "User" ADD COLUMN "availabilityJson" JSONB, -ADD COLUMN "digestFrequency" TEXT NOT NULL DEFAULT 'none', -ADD COLUMN "preferredWorkload" INTEGER; - --- DropTable -DROP TABLE "ApplicationForm"; - --- DropTable -DROP TABLE "ApplicationFormField"; - --- DropTable -DROP TABLE "ApplicationFormSubmission"; - --- DropTable -DROP TABLE "OnboardingStep"; - --- DropTable -DROP TABLE "SubmissionFile"; - --- DropEnum -DROP TYPE "FormFieldType"; - --- DropEnum -DROP TYPE "SpecialFieldType"; - --- CreateTable -CREATE TABLE "ReminderLog" ( - "id" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "type" TEXT NOT NULL, - "sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "ReminderLog_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ConflictOfInterest" ( - "id" TEXT NOT NULL, - "assignmentId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "hasConflict" BOOLEAN NOT NULL DEFAULT false, - "conflictType" TEXT, - "description" TEXT, - "declaredAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "reviewedById" TEXT, - "reviewedAt" TIMESTAMP(3), - "reviewAction" TEXT, - - CONSTRAINT "ConflictOfInterest_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "EvaluationSummary" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "summaryJson" JSONB NOT NULL, - "generatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "generatedById" TEXT NOT NULL, - "model" TEXT NOT NULL, - "tokensUsed" INTEGER NOT NULL, - - CONSTRAINT "EvaluationSummary_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "ProjectStatusHistory" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "status" "ProjectStatus" NOT NULL, - "changedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "changedBy" TEXT, - - CONSTRAINT "ProjectStatusHistory_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MentorMessage" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "senderId" TEXT NOT NULL, - "message" TEXT NOT NULL, - "isRead" BOOLEAN NOT NULL DEFAULT false, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "MentorMessage_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "DigestLog" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "digestType" TEXT NOT NULL, - "contentJson" JSONB NOT NULL, - "sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "DigestLog_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "RoundTemplate" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "programId" TEXT, - "roundType" "RoundType" NOT NULL DEFAULT 'EVALUATION', - "criteriaJson" JSONB NOT NULL, - "settingsJson" JSONB, - "assignmentConfig" JSONB, - "createdBy" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "RoundTemplate_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MentorNote" ( - "id" TEXT NOT NULL, - "mentorAssignmentId" TEXT NOT NULL, - "authorId" TEXT NOT NULL, - "content" TEXT NOT NULL, - "isVisibleToAdmin" BOOLEAN NOT NULL DEFAULT true, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "MentorNote_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MentorMilestone" ( - "id" TEXT NOT NULL, - "programId" TEXT NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "isRequired" BOOLEAN NOT NULL DEFAULT false, - "deadlineOffsetDays" INTEGER, - "sortOrder" INTEGER NOT NULL DEFAULT 0, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "MentorMilestone_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MentorMilestoneCompletion" ( - "id" TEXT NOT NULL, - "milestoneId" TEXT NOT NULL, - "mentorAssignmentId" TEXT NOT NULL, - "completedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "completedById" TEXT NOT NULL, - - CONSTRAINT "MentorMilestoneCompletion_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Message" ( - "id" TEXT NOT NULL, - "senderId" TEXT NOT NULL, - "recipientType" TEXT NOT NULL, - "recipientFilter" JSONB, - "roundId" TEXT, - "templateId" TEXT, - "subject" TEXT NOT NULL, - "body" TEXT NOT NULL, - "deliveryChannels" TEXT[], - "scheduledAt" TIMESTAMP(3), - "sentAt" TIMESTAMP(3), - "metadata" JSONB, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "Message_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MessageTemplate" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "category" TEXT NOT NULL, - "subject" TEXT NOT NULL, - "body" TEXT NOT NULL, - "variables" JSONB, - "isActive" BOOLEAN NOT NULL DEFAULT true, - "createdBy" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "MessageTemplate_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MessageRecipient" ( - "id" TEXT NOT NULL, - "messageId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "channel" TEXT NOT NULL, - "isRead" BOOLEAN NOT NULL DEFAULT false, - "readAt" TIMESTAMP(3), - "deliveredAt" TIMESTAMP(3), - - CONSTRAINT "MessageRecipient_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Webhook" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "url" TEXT NOT NULL, - "secret" TEXT NOT NULL, - "events" TEXT[], - "headers" JSONB, - "isActive" BOOLEAN NOT NULL DEFAULT true, - "maxRetries" INTEGER NOT NULL DEFAULT 3, - "createdById" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Webhook_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "WebhookDelivery" ( - "id" TEXT NOT NULL, - "webhookId" TEXT NOT NULL, - "event" TEXT NOT NULL, - "payload" JSONB NOT NULL, - "responseStatus" INTEGER, - "responseBody" TEXT, - "attempts" INTEGER NOT NULL DEFAULT 0, - "lastAttemptAt" TIMESTAMP(3), - "status" TEXT NOT NULL DEFAULT 'PENDING', - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "WebhookDelivery_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "EvaluationDiscussion" ( - "id" TEXT NOT NULL, - "projectId" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "status" TEXT NOT NULL DEFAULT 'open', - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "closedAt" TIMESTAMP(3), - "closedById" TEXT, - - CONSTRAINT "EvaluationDiscussion_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "DiscussionComment" ( - "id" TEXT NOT NULL, - "discussionId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "content" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "DiscussionComment_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE INDEX "ReminderLog_roundId_idx" ON "ReminderLog"("roundId"); - --- CreateIndex -CREATE UNIQUE INDEX "ReminderLog_roundId_userId_type_key" ON "ReminderLog"("roundId", "userId", "type"); - --- CreateIndex -CREATE UNIQUE INDEX "ConflictOfInterest_assignmentId_key" ON "ConflictOfInterest"("assignmentId"); - --- CreateIndex -CREATE INDEX "ConflictOfInterest_userId_idx" ON "ConflictOfInterest"("userId"); - --- CreateIndex -CREATE INDEX "ConflictOfInterest_roundId_hasConflict_idx" ON "ConflictOfInterest"("roundId", "hasConflict"); - --- CreateIndex -CREATE INDEX "EvaluationSummary_roundId_idx" ON "EvaluationSummary"("roundId"); - --- CreateIndex -CREATE UNIQUE INDEX "EvaluationSummary_projectId_roundId_key" ON "EvaluationSummary"("projectId", "roundId"); - --- CreateIndex -CREATE INDEX "ProjectStatusHistory_projectId_changedAt_idx" ON "ProjectStatusHistory"("projectId", "changedAt"); - --- CreateIndex -CREATE INDEX "MentorMessage_projectId_createdAt_idx" ON "MentorMessage"("projectId", "createdAt"); - --- CreateIndex -CREATE INDEX "DigestLog_userId_idx" ON "DigestLog"("userId"); - --- CreateIndex -CREATE INDEX "DigestLog_sentAt_idx" ON "DigestLog"("sentAt"); - --- CreateIndex -CREATE INDEX "RoundTemplate_programId_idx" ON "RoundTemplate"("programId"); - --- CreateIndex -CREATE INDEX "MentorNote_mentorAssignmentId_idx" ON "MentorNote"("mentorAssignmentId"); - --- CreateIndex -CREATE INDEX "MentorMilestone_programId_idx" ON "MentorMilestone"("programId"); - --- CreateIndex -CREATE INDEX "MentorMilestone_sortOrder_idx" ON "MentorMilestone"("sortOrder"); - --- CreateIndex -CREATE INDEX "MentorMilestoneCompletion_mentorAssignmentId_idx" ON "MentorMilestoneCompletion"("mentorAssignmentId"); - --- CreateIndex -CREATE UNIQUE INDEX "MentorMilestoneCompletion_milestoneId_mentorAssignmentId_key" ON "MentorMilestoneCompletion"("milestoneId", "mentorAssignmentId"); - --- CreateIndex -CREATE INDEX "Message_senderId_idx" ON "Message"("senderId"); - --- CreateIndex -CREATE INDEX "Message_sentAt_idx" ON "Message"("sentAt"); - --- CreateIndex -CREATE INDEX "Message_scheduledAt_idx" ON "Message"("scheduledAt"); - --- CreateIndex -CREATE INDEX "MessageTemplate_category_idx" ON "MessageTemplate"("category"); - --- CreateIndex -CREATE INDEX "MessageTemplate_isActive_idx" ON "MessageTemplate"("isActive"); - --- CreateIndex -CREATE INDEX "MessageRecipient_messageId_idx" ON "MessageRecipient"("messageId"); - --- CreateIndex -CREATE INDEX "MessageRecipient_userId_isRead_idx" ON "MessageRecipient"("userId", "isRead"); - --- CreateIndex -CREATE INDEX "Webhook_isActive_idx" ON "Webhook"("isActive"); - --- CreateIndex -CREATE INDEX "WebhookDelivery_webhookId_idx" ON "WebhookDelivery"("webhookId"); - --- CreateIndex -CREATE INDEX "WebhookDelivery_status_idx" ON "WebhookDelivery"("status"); - --- CreateIndex -CREATE INDEX "WebhookDelivery_createdAt_idx" ON "WebhookDelivery"("createdAt"); - --- CreateIndex -CREATE INDEX "EvaluationDiscussion_roundId_idx" ON "EvaluationDiscussion"("roundId"); - --- CreateIndex -CREATE INDEX "EvaluationDiscussion_status_idx" ON "EvaluationDiscussion"("status"); - --- CreateIndex -CREATE UNIQUE INDEX "EvaluationDiscussion_projectId_roundId_key" ON "EvaluationDiscussion"("projectId", "roundId"); - --- CreateIndex -CREATE INDEX "DiscussionComment_discussionId_createdAt_idx" ON "DiscussionComment"("discussionId", "createdAt"); - --- CreateIndex -CREATE INDEX "AuditLog_entityType_entityId_timestamp_idx" ON "AuditLog"("entityType", "entityId", "timestamp"); - --- CreateIndex -CREATE INDEX "Evaluation_status_formId_idx" ON "Evaluation"("status", "formId"); - --- CreateIndex -CREATE INDEX "GracePeriod_roundId_userId_extendedUntil_idx" ON "GracePeriod"("roundId", "userId", "extendedUntil"); - --- CreateIndex -CREATE INDEX "LiveVote_isAudienceVote_idx" ON "LiveVote"("isAudienceVote"); - --- CreateIndex -CREATE INDEX "ProjectFile_roundId_idx" ON "ProjectFile"("roundId"); - --- AddForeignKey -ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "SpecialAward" ADD CONSTRAINT "SpecialAward_winnerOverriddenBy_fkey" FOREIGN KEY ("winnerOverriddenBy") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ReminderLog" ADD CONSTRAINT "ReminderLog_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ReminderLog" ADD CONSTRAINT "ReminderLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ConflictOfInterest" ADD CONSTRAINT "ConflictOfInterest_assignmentId_fkey" FOREIGN KEY ("assignmentId") REFERENCES "Assignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ConflictOfInterest" ADD CONSTRAINT "ConflictOfInterest_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ConflictOfInterest" ADD CONSTRAINT "ConflictOfInterest_reviewedById_fkey" FOREIGN KEY ("reviewedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "EvaluationSummary" ADD CONSTRAINT "EvaluationSummary_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "EvaluationSummary" ADD CONSTRAINT "EvaluationSummary_generatedById_fkey" FOREIGN KEY ("generatedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ProjectStatusHistory" ADD CONSTRAINT "ProjectStatusHistory_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorMessage" ADD CONSTRAINT "MentorMessage_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorMessage" ADD CONSTRAINT "MentorMessage_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "DigestLog" ADD CONSTRAINT "DigestLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorNote" ADD CONSTRAINT "MentorNote_mentorAssignmentId_fkey" FOREIGN KEY ("mentorAssignmentId") REFERENCES "MentorAssignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorNote" ADD CONSTRAINT "MentorNote_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorMilestone" ADD CONSTRAINT "MentorMilestone_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorMilestoneCompletion" ADD CONSTRAINT "MentorMilestoneCompletion_milestoneId_fkey" FOREIGN KEY ("milestoneId") REFERENCES "MentorMilestone"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorMilestoneCompletion" ADD CONSTRAINT "MentorMilestoneCompletion_mentorAssignmentId_fkey" FOREIGN KEY ("mentorAssignmentId") REFERENCES "MentorAssignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MentorMilestoneCompletion" ADD CONSTRAINT "MentorMilestoneCompletion_completedById_fkey" FOREIGN KEY ("completedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Message" ADD CONSTRAINT "Message_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Message" ADD CONSTRAINT "Message_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "MessageTemplate"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MessageRecipient" ADD CONSTRAINT "MessageRecipient_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "Message"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MessageRecipient" ADD CONSTRAINT "MessageRecipient_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Webhook" ADD CONSTRAINT "Webhook_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "WebhookDelivery" ADD CONSTRAINT "WebhookDelivery_webhookId_fkey" FOREIGN KEY ("webhookId") REFERENCES "Webhook"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_closedById_fkey" FOREIGN KEY ("closedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "DiscussionComment" ADD CONSTRAINT "DiscussionComment_discussionId_fkey" FOREIGN KEY ("discussionId") REFERENCES "EvaluationDiscussion"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "DiscussionComment" ADD CONSTRAINT "DiscussionComment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +/* + Warnings: + + - You are about to drop the `ApplicationForm` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `ApplicationFormField` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `ApplicationFormSubmission` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `OnboardingStep` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `SubmissionFile` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- AlterEnum +-- This migration adds more than one value to an enum. +-- With PostgreSQL versions 11 and earlier, this is not possible +-- in a single migration. This can be worked around by creating +-- multiple migrations, each migration adding only one value to +-- the enum. + + +ALTER TYPE "SettingCategory" ADD VALUE 'DIGEST'; +ALTER TYPE "SettingCategory" ADD VALUE 'ANALYTICS'; +ALTER TYPE "SettingCategory" ADD VALUE 'AUDIT_CONFIG'; +ALTER TYPE "SettingCategory" ADD VALUE 'INTEGRATIONS'; +ALTER TYPE "SettingCategory" ADD VALUE 'LOCALIZATION'; +ALTER TYPE "SettingCategory" ADD VALUE 'COMMUNICATION'; + +-- DropForeignKey +ALTER TABLE "ApplicationForm" DROP CONSTRAINT "ApplicationForm_programId_fkey"; + +-- DropForeignKey +ALTER TABLE "ApplicationForm" DROP CONSTRAINT "ApplicationForm_roundId_fkey"; + +-- DropForeignKey +ALTER TABLE "ApplicationFormField" DROP CONSTRAINT "ApplicationFormField_formId_fkey"; + +-- DropForeignKey +ALTER TABLE "ApplicationFormField" DROP CONSTRAINT "ApplicationFormField_stepId_fkey"; + +-- DropForeignKey +ALTER TABLE "ApplicationFormSubmission" DROP CONSTRAINT "ApplicationFormSubmission_formId_fkey"; + +-- DropForeignKey +ALTER TABLE "OnboardingStep" DROP CONSTRAINT "OnboardingStep_formId_fkey"; + +-- DropForeignKey +ALTER TABLE "SubmissionFile" DROP CONSTRAINT "SubmissionFile_submissionId_fkey"; + +-- DropIndex +DROP INDEX "User_email_idx"; + +-- AlterTable +ALTER TABLE "AssignmentJob" ALTER COLUMN "updatedAt" DROP DEFAULT; + +-- AlterTable +ALTER TABLE "AuditLog" ADD COLUMN "previousDataJson" JSONB, +ADD COLUMN "sessionId" TEXT; + +-- AlterTable +ALTER TABLE "FilteringJob" ALTER COLUMN "updatedAt" DROP DEFAULT; + +-- AlterTable +ALTER TABLE "LiveVote" ADD COLUMN "isAudienceVote" BOOLEAN NOT NULL DEFAULT false; + +-- AlterTable +ALTER TABLE "LiveVotingSession" ADD COLUMN "allowAudienceVotes" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "audienceVoteWeight" DOUBLE PRECISION NOT NULL DEFAULT 0, +ADD COLUMN "presentationSettingsJson" JSONB, +ADD COLUMN "tieBreakerMethod" TEXT NOT NULL DEFAULT 'admin_decides'; + +-- AlterTable +ALTER TABLE "MentorAssignment" ADD COLUMN "completionStatus" TEXT NOT NULL DEFAULT 'in_progress', +ADD COLUMN "lastViewedAt" TIMESTAMP(3); + +-- AlterTable +ALTER TABLE "NotificationEmailSetting" ALTER COLUMN "updatedAt" DROP DEFAULT; + +-- AlterTable +ALTER TABLE "Project" ADD COLUMN "draftDataJson" JSONB, +ADD COLUMN "draftExpiresAt" TIMESTAMP(3), +ADD COLUMN "isDraft" BOOLEAN NOT NULL DEFAULT false; + +-- AlterTable +ALTER TABLE "ProjectFile" ADD COLUMN "isLate" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "replacedById" TEXT, +ADD COLUMN "roundId" TEXT, +ADD COLUMN "version" INTEGER NOT NULL DEFAULT 1; + +-- AlterTable +ALTER TABLE "TaggingJob" ALTER COLUMN "updatedAt" DROP DEFAULT; + +-- AlterTable +ALTER TABLE "User" ADD COLUMN "availabilityJson" JSONB, +ADD COLUMN "digestFrequency" TEXT NOT NULL DEFAULT 'none', +ADD COLUMN "preferredWorkload" INTEGER; + +-- DropTable +DROP TABLE "ApplicationForm"; + +-- DropTable +DROP TABLE "ApplicationFormField"; + +-- DropTable +DROP TABLE "ApplicationFormSubmission"; + +-- DropTable +DROP TABLE "OnboardingStep"; + +-- DropTable +DROP TABLE "SubmissionFile"; + +-- DropEnum +DROP TYPE "FormFieldType"; + +-- DropEnum +DROP TYPE "SpecialFieldType"; + +-- CreateTable +CREATE TABLE "ReminderLog" ( + "id" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "type" TEXT NOT NULL, + "sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "ReminderLog_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ConflictOfInterest" ( + "id" TEXT NOT NULL, + "assignmentId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "hasConflict" BOOLEAN NOT NULL DEFAULT false, + "conflictType" TEXT, + "description" TEXT, + "declaredAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "reviewedById" TEXT, + "reviewedAt" TIMESTAMP(3), + "reviewAction" TEXT, + + CONSTRAINT "ConflictOfInterest_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "EvaluationSummary" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "summaryJson" JSONB NOT NULL, + "generatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "generatedById" TEXT NOT NULL, + "model" TEXT NOT NULL, + "tokensUsed" INTEGER NOT NULL, + + CONSTRAINT "EvaluationSummary_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProjectStatusHistory" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "status" "ProjectStatus" NOT NULL, + "changedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "changedBy" TEXT, + + CONSTRAINT "ProjectStatusHistory_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MentorMessage" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "senderId" TEXT NOT NULL, + "message" TEXT NOT NULL, + "isRead" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "MentorMessage_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "DigestLog" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "digestType" TEXT NOT NULL, + "contentJson" JSONB NOT NULL, + "sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "DigestLog_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RoundTemplate" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "programId" TEXT, + "roundType" "RoundType" NOT NULL DEFAULT 'EVALUATION', + "criteriaJson" JSONB NOT NULL, + "settingsJson" JSONB, + "assignmentConfig" JSONB, + "createdBy" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "RoundTemplate_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MentorNote" ( + "id" TEXT NOT NULL, + "mentorAssignmentId" TEXT NOT NULL, + "authorId" TEXT NOT NULL, + "content" TEXT NOT NULL, + "isVisibleToAdmin" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "MentorNote_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MentorMilestone" ( + "id" TEXT NOT NULL, + "programId" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "isRequired" BOOLEAN NOT NULL DEFAULT false, + "deadlineOffsetDays" INTEGER, + "sortOrder" INTEGER NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "MentorMilestone_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MentorMilestoneCompletion" ( + "id" TEXT NOT NULL, + "milestoneId" TEXT NOT NULL, + "mentorAssignmentId" TEXT NOT NULL, + "completedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "completedById" TEXT NOT NULL, + + CONSTRAINT "MentorMilestoneCompletion_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Message" ( + "id" TEXT NOT NULL, + "senderId" TEXT NOT NULL, + "recipientType" TEXT NOT NULL, + "recipientFilter" JSONB, + "roundId" TEXT, + "templateId" TEXT, + "subject" TEXT NOT NULL, + "body" TEXT NOT NULL, + "deliveryChannels" TEXT[], + "scheduledAt" TIMESTAMP(3), + "sentAt" TIMESTAMP(3), + "metadata" JSONB, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Message_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MessageTemplate" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "category" TEXT NOT NULL, + "subject" TEXT NOT NULL, + "body" TEXT NOT NULL, + "variables" JSONB, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdBy" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "MessageTemplate_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MessageRecipient" ( + "id" TEXT NOT NULL, + "messageId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "channel" TEXT NOT NULL, + "isRead" BOOLEAN NOT NULL DEFAULT false, + "readAt" TIMESTAMP(3), + "deliveredAt" TIMESTAMP(3), + + CONSTRAINT "MessageRecipient_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Webhook" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "url" TEXT NOT NULL, + "secret" TEXT NOT NULL, + "events" TEXT[], + "headers" JSONB, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "maxRetries" INTEGER NOT NULL DEFAULT 3, + "createdById" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Webhook_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "WebhookDelivery" ( + "id" TEXT NOT NULL, + "webhookId" TEXT NOT NULL, + "event" TEXT NOT NULL, + "payload" JSONB NOT NULL, + "responseStatus" INTEGER, + "responseBody" TEXT, + "attempts" INTEGER NOT NULL DEFAULT 0, + "lastAttemptAt" TIMESTAMP(3), + "status" TEXT NOT NULL DEFAULT 'PENDING', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "WebhookDelivery_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "EvaluationDiscussion" ( + "id" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'open', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "closedAt" TIMESTAMP(3), + "closedById" TEXT, + + CONSTRAINT "EvaluationDiscussion_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "DiscussionComment" ( + "id" TEXT NOT NULL, + "discussionId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "DiscussionComment_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "ReminderLog_roundId_idx" ON "ReminderLog"("roundId"); + +-- CreateIndex +CREATE UNIQUE INDEX "ReminderLog_roundId_userId_type_key" ON "ReminderLog"("roundId", "userId", "type"); + +-- CreateIndex +CREATE UNIQUE INDEX "ConflictOfInterest_assignmentId_key" ON "ConflictOfInterest"("assignmentId"); + +-- CreateIndex +CREATE INDEX "ConflictOfInterest_userId_idx" ON "ConflictOfInterest"("userId"); + +-- CreateIndex +CREATE INDEX "ConflictOfInterest_roundId_hasConflict_idx" ON "ConflictOfInterest"("roundId", "hasConflict"); + +-- CreateIndex +CREATE INDEX "EvaluationSummary_roundId_idx" ON "EvaluationSummary"("roundId"); + +-- CreateIndex +CREATE UNIQUE INDEX "EvaluationSummary_projectId_roundId_key" ON "EvaluationSummary"("projectId", "roundId"); + +-- CreateIndex +CREATE INDEX "ProjectStatusHistory_projectId_changedAt_idx" ON "ProjectStatusHistory"("projectId", "changedAt"); + +-- CreateIndex +CREATE INDEX "MentorMessage_projectId_createdAt_idx" ON "MentorMessage"("projectId", "createdAt"); + +-- CreateIndex +CREATE INDEX "DigestLog_userId_idx" ON "DigestLog"("userId"); + +-- CreateIndex +CREATE INDEX "DigestLog_sentAt_idx" ON "DigestLog"("sentAt"); + +-- CreateIndex +CREATE INDEX "RoundTemplate_programId_idx" ON "RoundTemplate"("programId"); + +-- CreateIndex +CREATE INDEX "MentorNote_mentorAssignmentId_idx" ON "MentorNote"("mentorAssignmentId"); + +-- CreateIndex +CREATE INDEX "MentorMilestone_programId_idx" ON "MentorMilestone"("programId"); + +-- CreateIndex +CREATE INDEX "MentorMilestone_sortOrder_idx" ON "MentorMilestone"("sortOrder"); + +-- CreateIndex +CREATE INDEX "MentorMilestoneCompletion_mentorAssignmentId_idx" ON "MentorMilestoneCompletion"("mentorAssignmentId"); + +-- CreateIndex +CREATE UNIQUE INDEX "MentorMilestoneCompletion_milestoneId_mentorAssignmentId_key" ON "MentorMilestoneCompletion"("milestoneId", "mentorAssignmentId"); + +-- CreateIndex +CREATE INDEX "Message_senderId_idx" ON "Message"("senderId"); + +-- CreateIndex +CREATE INDEX "Message_sentAt_idx" ON "Message"("sentAt"); + +-- CreateIndex +CREATE INDEX "Message_scheduledAt_idx" ON "Message"("scheduledAt"); + +-- CreateIndex +CREATE INDEX "MessageTemplate_category_idx" ON "MessageTemplate"("category"); + +-- CreateIndex +CREATE INDEX "MessageTemplate_isActive_idx" ON "MessageTemplate"("isActive"); + +-- CreateIndex +CREATE INDEX "MessageRecipient_messageId_idx" ON "MessageRecipient"("messageId"); + +-- CreateIndex +CREATE INDEX "MessageRecipient_userId_isRead_idx" ON "MessageRecipient"("userId", "isRead"); + +-- CreateIndex +CREATE INDEX "Webhook_isActive_idx" ON "Webhook"("isActive"); + +-- CreateIndex +CREATE INDEX "WebhookDelivery_webhookId_idx" ON "WebhookDelivery"("webhookId"); + +-- CreateIndex +CREATE INDEX "WebhookDelivery_status_idx" ON "WebhookDelivery"("status"); + +-- CreateIndex +CREATE INDEX "WebhookDelivery_createdAt_idx" ON "WebhookDelivery"("createdAt"); + +-- CreateIndex +CREATE INDEX "EvaluationDiscussion_roundId_idx" ON "EvaluationDiscussion"("roundId"); + +-- CreateIndex +CREATE INDEX "EvaluationDiscussion_status_idx" ON "EvaluationDiscussion"("status"); + +-- CreateIndex +CREATE UNIQUE INDEX "EvaluationDiscussion_projectId_roundId_key" ON "EvaluationDiscussion"("projectId", "roundId"); + +-- CreateIndex +CREATE INDEX "DiscussionComment_discussionId_createdAt_idx" ON "DiscussionComment"("discussionId", "createdAt"); + +-- CreateIndex +CREATE INDEX "AuditLog_entityType_entityId_timestamp_idx" ON "AuditLog"("entityType", "entityId", "timestamp"); + +-- CreateIndex +CREATE INDEX "Evaluation_status_formId_idx" ON "Evaluation"("status", "formId"); + +-- CreateIndex +CREATE INDEX "GracePeriod_roundId_userId_extendedUntil_idx" ON "GracePeriod"("roundId", "userId", "extendedUntil"); + +-- CreateIndex +CREATE INDEX "LiveVote_isAudienceVote_idx" ON "LiveVote"("isAudienceVote"); + +-- CreateIndex +CREATE INDEX "ProjectFile_roundId_idx" ON "ProjectFile"("roundId"); + +-- AddForeignKey +ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "SpecialAward" ADD CONSTRAINT "SpecialAward_winnerOverriddenBy_fkey" FOREIGN KEY ("winnerOverriddenBy") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ReminderLog" ADD CONSTRAINT "ReminderLog_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ReminderLog" ADD CONSTRAINT "ReminderLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConflictOfInterest" ADD CONSTRAINT "ConflictOfInterest_assignmentId_fkey" FOREIGN KEY ("assignmentId") REFERENCES "Assignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConflictOfInterest" ADD CONSTRAINT "ConflictOfInterest_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConflictOfInterest" ADD CONSTRAINT "ConflictOfInterest_reviewedById_fkey" FOREIGN KEY ("reviewedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EvaluationSummary" ADD CONSTRAINT "EvaluationSummary_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EvaluationSummary" ADD CONSTRAINT "EvaluationSummary_generatedById_fkey" FOREIGN KEY ("generatedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectStatusHistory" ADD CONSTRAINT "ProjectStatusHistory_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorMessage" ADD CONSTRAINT "MentorMessage_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorMessage" ADD CONSTRAINT "MentorMessage_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "DigestLog" ADD CONSTRAINT "DigestLog_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorNote" ADD CONSTRAINT "MentorNote_mentorAssignmentId_fkey" FOREIGN KEY ("mentorAssignmentId") REFERENCES "MentorAssignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorNote" ADD CONSTRAINT "MentorNote_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorMilestone" ADD CONSTRAINT "MentorMilestone_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorMilestoneCompletion" ADD CONSTRAINT "MentorMilestoneCompletion_milestoneId_fkey" FOREIGN KEY ("milestoneId") REFERENCES "MentorMilestone"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorMilestoneCompletion" ADD CONSTRAINT "MentorMilestoneCompletion_mentorAssignmentId_fkey" FOREIGN KEY ("mentorAssignmentId") REFERENCES "MentorAssignment"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MentorMilestoneCompletion" ADD CONSTRAINT "MentorMilestoneCompletion_completedById_fkey" FOREIGN KEY ("completedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Message" ADD CONSTRAINT "Message_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Message" ADD CONSTRAINT "Message_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "MessageTemplate"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MessageRecipient" ADD CONSTRAINT "MessageRecipient_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "Message"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MessageRecipient" ADD CONSTRAINT "MessageRecipient_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Webhook" ADD CONSTRAINT "Webhook_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "WebhookDelivery" ADD CONSTRAINT "WebhookDelivery_webhookId_fkey" FOREIGN KEY ("webhookId") REFERENCES "Webhook"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_closedById_fkey" FOREIGN KEY ("closedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "DiscussionComment" ADD CONSTRAINT "DiscussionComment_discussionId_fkey" FOREIGN KEY ("discussionId") REFERENCES "EvaluationDiscussion"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "DiscussionComment" ADD CONSTRAINT "DiscussionComment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20260207000000_universal_apply_programid/migration.sql b/prisma/migrations/20260207000000_universal_apply_programid/migration.sql index 190b9e9..e1c7693 100644 --- a/prisma/migrations/20260207000000_universal_apply_programid/migration.sql +++ b/prisma/migrations/20260207000000_universal_apply_programid/migration.sql @@ -1,91 +1,91 @@ --- Universal Apply Page: Make Project.roundId nullable and add programId FK --- This migration enables projects to be submitted to a program/edition without being assigned to a specific round --- NOTE: Written to be idempotent (safe to re-run if partially applied) - --- Step 1: Add Program.slug for edition-wide apply URLs (nullable for existing programs) -ALTER TABLE "Program" ADD COLUMN IF NOT EXISTS "slug" TEXT; -CREATE UNIQUE INDEX IF NOT EXISTS "Program_slug_key" ON "Program"("slug"); - --- Step 2: Add programId column (nullable initially to handle existing data) -ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "programId" TEXT; - --- Step 3: Backfill programId from existing round relationships --- Only update rows where programId is still NULL (idempotent) -UPDATE "Project" p -SET "programId" = r."programId" -FROM "Round" r -WHERE p."roundId" = r.id - AND p."programId" IS NULL; - --- Step 4: Handle orphaned projects (no roundId = no way to derive programId) --- Assign them to the first available program, or delete them if no program exists -DO $$ -DECLARE - null_count INTEGER; - fallback_program_id TEXT; -BEGIN - SELECT COUNT(*) INTO null_count FROM "Project" WHERE "programId" IS NULL; - IF null_count > 0 THEN - SELECT id INTO fallback_program_id FROM "Program" ORDER BY "createdAt" ASC LIMIT 1; - IF fallback_program_id IS NOT NULL THEN - UPDATE "Project" SET "programId" = fallback_program_id WHERE "programId" IS NULL; - RAISE NOTICE 'Assigned % orphaned projects to fallback program %', null_count, fallback_program_id; - ELSE - DELETE FROM "Project" WHERE "programId" IS NULL; - RAISE NOTICE 'Deleted % orphaned projects (no program exists to assign them to)', null_count; - END IF; - END IF; -END $$; - --- Step 5: Make programId required (NOT NULL constraint) - safe if already NOT NULL -DO $$ -BEGIN - IF EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_name = 'Project' AND column_name = 'programId' AND is_nullable = 'YES' - ) THEN - ALTER TABLE "Project" ALTER COLUMN "programId" SET NOT NULL; - END IF; -END $$; - --- Step 6: Add foreign key constraint for programId (skip if already exists) -DO $$ -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.table_constraints - WHERE constraint_name = 'Project_programId_fkey' AND table_name = 'Project' - ) THEN - ALTER TABLE "Project" ADD CONSTRAINT "Project_programId_fkey" - FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE; - END IF; -END $$; - --- Step 7: Make roundId nullable (allow projects without round assignment) --- Safe: DROP NOT NULL is idempotent if already nullable -DO $$ -BEGIN - IF EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_name = 'Project' AND column_name = 'roundId' AND is_nullable = 'NO' - ) THEN - ALTER TABLE "Project" ALTER COLUMN "roundId" DROP NOT NULL; - END IF; -END $$; - --- Step 8: Update round FK to SET NULL on delete (instead of CASCADE) --- Projects should remain in the database if their round is deleted -DO $$ -BEGIN - IF EXISTS ( - SELECT 1 FROM information_schema.table_constraints - WHERE constraint_name = 'Project_roundId_fkey' AND table_name = 'Project' - ) THEN - ALTER TABLE "Project" DROP CONSTRAINT "Project_roundId_fkey"; - END IF; - ALTER TABLE "Project" ADD CONSTRAINT "Project_roundId_fkey" - FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL; -END $$; - --- Step 9: Add performance indexes -CREATE INDEX IF NOT EXISTS "Project_programId_idx" ON "Project"("programId"); -CREATE INDEX IF NOT EXISTS "Project_programId_roundId_idx" ON "Project"("programId", "roundId"); +-- Universal Apply Page: Make Project.roundId nullable and add programId FK +-- This migration enables projects to be submitted to a program/edition without being assigned to a specific round +-- NOTE: Written to be idempotent (safe to re-run if partially applied) + +-- Step 1: Add Program.slug for edition-wide apply URLs (nullable for existing programs) +ALTER TABLE "Program" ADD COLUMN IF NOT EXISTS "slug" TEXT; +CREATE UNIQUE INDEX IF NOT EXISTS "Program_slug_key" ON "Program"("slug"); + +-- Step 2: Add programId column (nullable initially to handle existing data) +ALTER TABLE "Project" ADD COLUMN IF NOT EXISTS "programId" TEXT; + +-- Step 3: Backfill programId from existing round relationships +-- Only update rows where programId is still NULL (idempotent) +UPDATE "Project" p +SET "programId" = r."programId" +FROM "Round" r +WHERE p."roundId" = r.id + AND p."programId" IS NULL; + +-- Step 4: Handle orphaned projects (no roundId = no way to derive programId) +-- Assign them to the first available program, or delete them if no program exists +DO $$ +DECLARE + null_count INTEGER; + fallback_program_id TEXT; +BEGIN + SELECT COUNT(*) INTO null_count FROM "Project" WHERE "programId" IS NULL; + IF null_count > 0 THEN + SELECT id INTO fallback_program_id FROM "Program" ORDER BY "createdAt" ASC LIMIT 1; + IF fallback_program_id IS NOT NULL THEN + UPDATE "Project" SET "programId" = fallback_program_id WHERE "programId" IS NULL; + RAISE NOTICE 'Assigned % orphaned projects to fallback program %', null_count, fallback_program_id; + ELSE + DELETE FROM "Project" WHERE "programId" IS NULL; + RAISE NOTICE 'Deleted % orphaned projects (no program exists to assign them to)', null_count; + END IF; + END IF; +END $$; + +-- Step 5: Make programId required (NOT NULL constraint) - safe if already NOT NULL +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'Project' AND column_name = 'programId' AND is_nullable = 'YES' + ) THEN + ALTER TABLE "Project" ALTER COLUMN "programId" SET NOT NULL; + END IF; +END $$; + +-- Step 6: Add foreign key constraint for programId (skip if already exists) +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.table_constraints + WHERE constraint_name = 'Project_programId_fkey' AND table_name = 'Project' + ) THEN + ALTER TABLE "Project" ADD CONSTRAINT "Project_programId_fkey" + FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE; + END IF; +END $$; + +-- Step 7: Make roundId nullable (allow projects without round assignment) +-- Safe: DROP NOT NULL is idempotent if already nullable +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'Project' AND column_name = 'roundId' AND is_nullable = 'NO' + ) THEN + ALTER TABLE "Project" ALTER COLUMN "roundId" DROP NOT NULL; + END IF; +END $$; + +-- Step 8: Update round FK to SET NULL on delete (instead of CASCADE) +-- Projects should remain in the database if their round is deleted +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.table_constraints + WHERE constraint_name = 'Project_roundId_fkey' AND table_name = 'Project' + ) THEN + ALTER TABLE "Project" DROP CONSTRAINT "Project_roundId_fkey"; + END IF; + ALTER TABLE "Project" ADD CONSTRAINT "Project_roundId_fkey" + FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL; +END $$; + +-- Step 9: Add performance indexes +CREATE INDEX IF NOT EXISTS "Project_programId_idx" ON "Project"("programId"); +CREATE INDEX IF NOT EXISTS "Project_programId_roundId_idx" ON "Project"("programId", "roundId"); diff --git a/prisma/migrations/20260208000000_add_missing_fks_indexes/migration.sql b/prisma/migrations/20260208000000_add_missing_fks_indexes/migration.sql index c269885..2347175 100644 --- a/prisma/migrations/20260208000000_add_missing_fks_indexes/migration.sql +++ b/prisma/migrations/20260208000000_add_missing_fks_indexes/migration.sql @@ -1,41 +1,41 @@ --- Reconciliation migration: Add missing foreign keys and indexes --- The add_15_features migration omitted some FKs and indexes that the schema expects --- This migration brings the database in line with the Prisma schema - --- ===================================================== --- Missing Foreign Keys --- ===================================================== - --- RoundTemplate → Program -ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_programId_fkey" - FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- RoundTemplate → User (creator) -ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_createdBy_fkey" - FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- Message → Round -ALTER TABLE "Message" ADD CONSTRAINT "Message_roundId_fkey" - FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- EvaluationDiscussion → Round -ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_roundId_fkey" - FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- ProjectFile → ProjectFile (self-relation for file versioning) -ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_replacedById_fkey" - FOREIGN KEY ("replacedById") REFERENCES "ProjectFile"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- ===================================================== --- Missing Indexes --- ===================================================== - -CREATE INDEX "RoundTemplate_roundType_idx" ON "RoundTemplate"("roundType"); -CREATE INDEX "MentorNote_authorId_idx" ON "MentorNote"("authorId"); -CREATE INDEX "MentorMilestoneCompletion_completedById_idx" ON "MentorMilestoneCompletion"("completedById"); -CREATE INDEX "Webhook_createdById_idx" ON "Webhook"("createdById"); -CREATE INDEX "WebhookDelivery_event_idx" ON "WebhookDelivery"("event"); -CREATE INDEX "Message_roundId_idx" ON "Message"("roundId"); -CREATE INDEX "EvaluationDiscussion_closedById_idx" ON "EvaluationDiscussion"("closedById"); -CREATE INDEX "DiscussionComment_discussionId_idx" ON "DiscussionComment"("discussionId"); -CREATE INDEX "DiscussionComment_userId_idx" ON "DiscussionComment"("userId"); +-- Reconciliation migration: Add missing foreign keys and indexes +-- The add_15_features migration omitted some FKs and indexes that the schema expects +-- This migration brings the database in line with the Prisma schema + +-- ===================================================== +-- Missing Foreign Keys +-- ===================================================== + +-- RoundTemplate → Program +ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_programId_fkey" + FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- RoundTemplate → User (creator) +ALTER TABLE "RoundTemplate" ADD CONSTRAINT "RoundTemplate_createdBy_fkey" + FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- Message → Round +ALTER TABLE "Message" ADD CONSTRAINT "Message_roundId_fkey" + FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- EvaluationDiscussion → Round +ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_roundId_fkey" + FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- ProjectFile → ProjectFile (self-relation for file versioning) +ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_replacedById_fkey" + FOREIGN KEY ("replacedById") REFERENCES "ProjectFile"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- ===================================================== +-- Missing Indexes +-- ===================================================== + +CREATE INDEX "RoundTemplate_roundType_idx" ON "RoundTemplate"("roundType"); +CREATE INDEX "MentorNote_authorId_idx" ON "MentorNote"("authorId"); +CREATE INDEX "MentorMilestoneCompletion_completedById_idx" ON "MentorMilestoneCompletion"("completedById"); +CREATE INDEX "Webhook_createdById_idx" ON "Webhook"("createdById"); +CREATE INDEX "WebhookDelivery_event_idx" ON "WebhookDelivery"("event"); +CREATE INDEX "Message_roundId_idx" ON "Message"("roundId"); +CREATE INDEX "EvaluationDiscussion_closedById_idx" ON "EvaluationDiscussion"("closedById"); +CREATE INDEX "DiscussionComment_discussionId_idx" ON "DiscussionComment"("discussionId"); +CREATE INDEX "DiscussionComment_userId_idx" ON "DiscussionComment"("userId"); diff --git a/prisma/migrations/20260210000000_fix_round_delete_cascades/migration.sql b/prisma/migrations/20260210000000_fix_round_delete_cascades/migration.sql index 2461453..d22d6a8 100644 --- a/prisma/migrations/20260210000000_fix_round_delete_cascades/migration.sql +++ b/prisma/migrations/20260210000000_fix_round_delete_cascades/migration.sql @@ -1,13 +1,13 @@ --- Fix round deletion FK constraint errors --- Add CASCADE on Evaluation.formId so deleting EvaluationForm cascades to Evaluations --- Add SET NULL on ProjectFile.roundId so deleting Round nullifies the reference - --- AlterTable: Evaluation.formId -> onDelete CASCADE -ALTER TABLE "Evaluation" DROP CONSTRAINT "Evaluation_formId_fkey"; -ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_formId_fkey" - FOREIGN KEY ("formId") REFERENCES "EvaluationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AlterTable: ProjectFile.roundId -> onDelete SET NULL -ALTER TABLE "ProjectFile" DROP CONSTRAINT "ProjectFile_roundId_fkey"; -ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_roundId_fkey" - FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- Fix round deletion FK constraint errors +-- Add CASCADE on Evaluation.formId so deleting EvaluationForm cascades to Evaluations +-- Add SET NULL on ProjectFile.roundId so deleting Round nullifies the reference + +-- AlterTable: Evaluation.formId -> onDelete CASCADE +ALTER TABLE "Evaluation" DROP CONSTRAINT "Evaluation_formId_fkey"; +ALTER TABLE "Evaluation" ADD CONSTRAINT "Evaluation_formId_fkey" + FOREIGN KEY ("formId") REFERENCES "EvaluationForm"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AlterTable: ProjectFile.roundId -> onDelete SET NULL +ALTER TABLE "ProjectFile" DROP CONSTRAINT "ProjectFile_roundId_fkey"; +ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_roundId_fkey" + FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20260211000000_add_file_requirements/migration.sql b/prisma/migrations/20260211000000_add_file_requirements/migration.sql index d132a75..79e69b0 100644 --- a/prisma/migrations/20260211000000_add_file_requirements/migration.sql +++ b/prisma/migrations/20260211000000_add_file_requirements/migration.sql @@ -1,30 +1,30 @@ --- CreateTable -CREATE TABLE "FileRequirement" ( - "id" TEXT NOT NULL, - "roundId" TEXT NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "acceptedMimeTypes" TEXT[], - "maxSizeMB" INTEGER, - "isRequired" BOOLEAN NOT NULL DEFAULT true, - "sortOrder" INTEGER NOT NULL DEFAULT 0, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "FileRequirement_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE INDEX "FileRequirement_roundId_idx" ON "FileRequirement"("roundId"); - --- AddForeignKey -ALTER TABLE "FileRequirement" ADD CONSTRAINT "FileRequirement_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AlterTable: add requirementId to ProjectFile -ALTER TABLE "ProjectFile" ADD COLUMN "requirementId" TEXT; - --- CreateIndex -CREATE INDEX "ProjectFile_requirementId_idx" ON "ProjectFile"("requirementId"); - --- AddForeignKey -ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_requirementId_fkey" FOREIGN KEY ("requirementId") REFERENCES "FileRequirement"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- CreateTable +CREATE TABLE "FileRequirement" ( + "id" TEXT NOT NULL, + "roundId" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "acceptedMimeTypes" TEXT[], + "maxSizeMB" INTEGER, + "isRequired" BOOLEAN NOT NULL DEFAULT true, + "sortOrder" INTEGER NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "FileRequirement_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "FileRequirement_roundId_idx" ON "FileRequirement"("roundId"); + +-- AddForeignKey +ALTER TABLE "FileRequirement" ADD CONSTRAINT "FileRequirement_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AlterTable: add requirementId to ProjectFile +ALTER TABLE "ProjectFile" ADD COLUMN "requirementId" TEXT; + +-- CreateIndex +CREATE INDEX "ProjectFile_requirementId_idx" ON "ProjectFile"("requirementId"); + +-- AddForeignKey +ALTER TABLE "ProjectFile" ADD CONSTRAINT "ProjectFile_requirementId_fkey" FOREIGN KEY ("requirementId") REFERENCES "FileRequirement"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20260211100000_add_missing_schema_elements/migration.sql b/prisma/migrations/20260211100000_add_missing_schema_elements/migration.sql index 6c13c7b..8e2d397 100644 --- a/prisma/migrations/20260211100000_add_missing_schema_elements/migration.sql +++ b/prisma/migrations/20260211100000_add_missing_schema_elements/migration.sql @@ -1,129 +1,129 @@ --- Migration: Add all missing schema elements not covered by previous migrations --- This brings the database fully in line with prisma/schema.prisma --- Uses IF NOT EXISTS / DO $$ guards for idempotent execution - --- ============================================================================= --- 1. MISSING TABLE: WizardTemplate --- ============================================================================= - -CREATE TABLE IF NOT EXISTS "WizardTemplate" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "config" JSONB NOT NULL, - "isGlobal" BOOLEAN NOT NULL DEFAULT false, - "programId" TEXT, - "createdBy" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "WizardTemplate_pkey" PRIMARY KEY ("id") -); - -CREATE INDEX IF NOT EXISTS "WizardTemplate_programId_idx" ON "WizardTemplate"("programId"); -CREATE INDEX IF NOT EXISTS "WizardTemplate_isGlobal_idx" ON "WizardTemplate"("isGlobal"); - -DO $$ BEGIN - ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_programId_fkey" - FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; -EXCEPTION WHEN duplicate_object THEN NULL; END $$; - -DO $$ BEGIN - ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_createdBy_fkey" - FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -EXCEPTION WHEN duplicate_object THEN NULL; END $$; - --- ============================================================================= --- 2. MISSING COLUMNS ON SpecialAward: eligibility job tracking fields --- ============================================================================= - -ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStatus" TEXT; -ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobTotal" INTEGER; -ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobDone" INTEGER; -ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobError" TEXT; -ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStarted" TIMESTAMP(3); - --- ============================================================================= --- 3. Project.referralSource: Already in init migration. No action needed. --- Round.slug: Already in init migration. No action needed. --- ============================================================================= - --- ============================================================================= --- 5. MISSING INDEXES --- ============================================================================= - --- 5a. Assignment: @@index([projectId, userId]) -CREATE INDEX IF NOT EXISTS "Assignment_projectId_userId_idx" ON "Assignment"("projectId", "userId"); - --- 5b. AuditLog: @@index([sessionId]) -CREATE INDEX IF NOT EXISTS "AuditLog_sessionId_idx" ON "AuditLog"("sessionId"); - --- 5c. ProjectFile: @@index([projectId, roundId]) -CREATE INDEX IF NOT EXISTS "ProjectFile_projectId_roundId_idx" ON "ProjectFile"("projectId", "roundId"); - --- 5d. MessageRecipient: @@index([userId]) -CREATE INDEX IF NOT EXISTS "MessageRecipient_userId_idx" ON "MessageRecipient"("userId"); - --- 5e. MessageRecipient: @@unique([messageId, userId, channel]) -CREATE UNIQUE INDEX IF NOT EXISTS "MessageRecipient_messageId_userId_channel_key" ON "MessageRecipient"("messageId", "userId", "channel"); - --- 5f. AwardEligibility: @@index([awardId, eligible]) - composite index -CREATE INDEX IF NOT EXISTS "AwardEligibility_awardId_eligible_idx" ON "AwardEligibility"("awardId", "eligible"); - --- ============================================================================= --- 6. REMOVE STALE INDEX: Message_scheduledAt_idx --- The schema does NOT have @@index([scheduledAt]) on Message. --- The add_15_features migration created it, but the schema doesn't list it. --- Leaving it as-is since it's harmless and could be useful. --- ============================================================================= - --- ============================================================================= --- 7. VERIFY: All models from add_15_features are present --- DigestLog, RoundTemplate, MentorNote, MentorMilestone, --- MentorMilestoneCompletion, Message, MessageTemplate, MessageRecipient, --- Webhook, WebhookDelivery, EvaluationDiscussion, DiscussionComment --- -> All confirmed created in 20260205223133_add_15_features migration. --- -> All FKs confirmed in add_15_features + 20260208000000_add_missing_fks_indexes. --- ============================================================================= - --- ============================================================================= --- 8. VERIFY: Existing tables from init and subsequent migrations --- All core tables (User, Account, Session, VerificationToken, Program, Round, --- EvaluationForm, Project, ProjectFile, Assignment, Evaluation, GracePeriod, --- SystemSettings, AuditLog, AIUsageLog, NotificationLog, InAppNotification, --- NotificationEmailSetting, LearningResource, ResourceAccess, Partner, --- ExpertiseTag, ProjectTag, LiveVotingSession, LiveVote, TeamMember, --- MentorAssignment, FilteringRule, FilteringResult, FilteringJob, --- AssignmentJob, TaggingJob, SpecialAward, AwardEligibility, AwardJuror, --- AwardVote, ReminderLog, ConflictOfInterest, EvaluationSummary, --- ProjectStatusHistory, MentorMessage, FileRequirement) --- -> All confirmed present in migrations. --- ============================================================================= - --- ============================================================================= --- SUMMARY OF CHANGES IN THIS MIGRATION: --- --- NEW TABLE: --- - WizardTemplate (with programId FK, createdBy FK, indexes) --- --- NEW COLUMNS: --- - SpecialAward.eligibilityJobStatus (TEXT, nullable) --- - SpecialAward.eligibilityJobTotal (INTEGER, nullable) --- - SpecialAward.eligibilityJobDone (INTEGER, nullable) --- - SpecialAward.eligibilityJobError (TEXT, nullable) --- - SpecialAward.eligibilityJobStarted (TIMESTAMP, nullable) --- --- NEW INDEXES: --- - Assignment_projectId_userId_idx --- - AuditLog_sessionId_idx --- - ProjectFile_projectId_roundId_idx --- - MessageRecipient_userId_idx --- - MessageRecipient_messageId_userId_channel_key (UNIQUE) --- - AwardEligibility_awardId_eligible_idx --- - WizardTemplate_programId_idx --- - WizardTemplate_isGlobal_idx --- --- NEW FOREIGN KEYS: --- - WizardTemplate_programId_fkey -> Program(id) ON DELETE CASCADE --- - WizardTemplate_createdBy_fkey -> User(id) ON DELETE RESTRICT --- ============================================================================= +-- Migration: Add all missing schema elements not covered by previous migrations +-- This brings the database fully in line with prisma/schema.prisma +-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution + +-- ============================================================================= +-- 1. MISSING TABLE: WizardTemplate +-- ============================================================================= + +CREATE TABLE IF NOT EXISTS "WizardTemplate" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "config" JSONB NOT NULL, + "isGlobal" BOOLEAN NOT NULL DEFAULT false, + "programId" TEXT, + "createdBy" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "WizardTemplate_pkey" PRIMARY KEY ("id") +); + +CREATE INDEX IF NOT EXISTS "WizardTemplate_programId_idx" ON "WizardTemplate"("programId"); +CREATE INDEX IF NOT EXISTS "WizardTemplate_isGlobal_idx" ON "WizardTemplate"("isGlobal"); + +DO $$ BEGIN + ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_programId_fkey" + FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; +EXCEPTION WHEN duplicate_object THEN NULL; END $$; + +DO $$ BEGIN + ALTER TABLE "WizardTemplate" ADD CONSTRAINT "WizardTemplate_createdBy_fkey" + FOREIGN KEY ("createdBy") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +EXCEPTION WHEN duplicate_object THEN NULL; END $$; + +-- ============================================================================= +-- 2. MISSING COLUMNS ON SpecialAward: eligibility job tracking fields +-- ============================================================================= + +ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStatus" TEXT; +ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobTotal" INTEGER; +ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobDone" INTEGER; +ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobError" TEXT; +ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "eligibilityJobStarted" TIMESTAMP(3); + +-- ============================================================================= +-- 3. Project.referralSource: Already in init migration. No action needed. +-- Round.slug: Already in init migration. No action needed. +-- ============================================================================= + +-- ============================================================================= +-- 5. MISSING INDEXES +-- ============================================================================= + +-- 5a. Assignment: @@index([projectId, userId]) +CREATE INDEX IF NOT EXISTS "Assignment_projectId_userId_idx" ON "Assignment"("projectId", "userId"); + +-- 5b. AuditLog: @@index([sessionId]) +CREATE INDEX IF NOT EXISTS "AuditLog_sessionId_idx" ON "AuditLog"("sessionId"); + +-- 5c. ProjectFile: @@index([projectId, roundId]) +CREATE INDEX IF NOT EXISTS "ProjectFile_projectId_roundId_idx" ON "ProjectFile"("projectId", "roundId"); + +-- 5d. MessageRecipient: @@index([userId]) +CREATE INDEX IF NOT EXISTS "MessageRecipient_userId_idx" ON "MessageRecipient"("userId"); + +-- 5e. MessageRecipient: @@unique([messageId, userId, channel]) +CREATE UNIQUE INDEX IF NOT EXISTS "MessageRecipient_messageId_userId_channel_key" ON "MessageRecipient"("messageId", "userId", "channel"); + +-- 5f. AwardEligibility: @@index([awardId, eligible]) - composite index +CREATE INDEX IF NOT EXISTS "AwardEligibility_awardId_eligible_idx" ON "AwardEligibility"("awardId", "eligible"); + +-- ============================================================================= +-- 6. REMOVE STALE INDEX: Message_scheduledAt_idx +-- The schema does NOT have @@index([scheduledAt]) on Message. +-- The add_15_features migration created it, but the schema doesn't list it. +-- Leaving it as-is since it's harmless and could be useful. +-- ============================================================================= + +-- ============================================================================= +-- 7. VERIFY: All models from add_15_features are present +-- DigestLog, RoundTemplate, MentorNote, MentorMilestone, +-- MentorMilestoneCompletion, Message, MessageTemplate, MessageRecipient, +-- Webhook, WebhookDelivery, EvaluationDiscussion, DiscussionComment +-- -> All confirmed created in 20260205223133_add_15_features migration. +-- -> All FKs confirmed in add_15_features + 20260208000000_add_missing_fks_indexes. +-- ============================================================================= + +-- ============================================================================= +-- 8. VERIFY: Existing tables from init and subsequent migrations +-- All core tables (User, Account, Session, VerificationToken, Program, Round, +-- EvaluationForm, Project, ProjectFile, Assignment, Evaluation, GracePeriod, +-- SystemSettings, AuditLog, AIUsageLog, NotificationLog, InAppNotification, +-- NotificationEmailSetting, LearningResource, ResourceAccess, Partner, +-- ExpertiseTag, ProjectTag, LiveVotingSession, LiveVote, TeamMember, +-- MentorAssignment, FilteringRule, FilteringResult, FilteringJob, +-- AssignmentJob, TaggingJob, SpecialAward, AwardEligibility, AwardJuror, +-- AwardVote, ReminderLog, ConflictOfInterest, EvaluationSummary, +-- ProjectStatusHistory, MentorMessage, FileRequirement) +-- -> All confirmed present in migrations. +-- ============================================================================= + +-- ============================================================================= +-- SUMMARY OF CHANGES IN THIS MIGRATION: +-- +-- NEW TABLE: +-- - WizardTemplate (with programId FK, createdBy FK, indexes) +-- +-- NEW COLUMNS: +-- - SpecialAward.eligibilityJobStatus (TEXT, nullable) +-- - SpecialAward.eligibilityJobTotal (INTEGER, nullable) +-- - SpecialAward.eligibilityJobDone (INTEGER, nullable) +-- - SpecialAward.eligibilityJobError (TEXT, nullable) +-- - SpecialAward.eligibilityJobStarted (TIMESTAMP, nullable) +-- +-- NEW INDEXES: +-- - Assignment_projectId_userId_idx +-- - AuditLog_sessionId_idx +-- - ProjectFile_projectId_roundId_idx +-- - MessageRecipient_userId_idx +-- - MessageRecipient_messageId_userId_channel_key (UNIQUE) +-- - AwardEligibility_awardId_eligible_idx +-- - WizardTemplate_programId_idx +-- - WizardTemplate_isGlobal_idx +-- +-- NEW FOREIGN KEYS: +-- - WizardTemplate_programId_fkey -> Program(id) ON DELETE CASCADE +-- - WizardTemplate_createdBy_fkey -> User(id) ON DELETE RESTRICT +-- ============================================================================= diff --git a/prisma/migrations/20260211120000_add_award_vote_composite_index/migration.sql b/prisma/migrations/20260211120000_add_award_vote_composite_index/migration.sql index 51717bd..99e82b0 100644 --- a/prisma/migrations/20260211120000_add_award_vote_composite_index/migration.sql +++ b/prisma/migrations/20260211120000_add_award_vote_composite_index/migration.sql @@ -1,2 +1,2 @@ --- CreateIndex -CREATE INDEX "AwardVote_awardId_userId_idx" ON "AwardVote"("awardId", "userId"); +-- CreateIndex +CREATE INDEX "AwardVote_awardId_userId_idx" ON "AwardVote"("awardId", "userId"); diff --git a/prisma/migrations/20260212000000_add_live_voting_enhancements/migration.sql b/prisma/migrations/20260212000000_add_live_voting_enhancements/migration.sql index 4e0bb87..6e7bcd4 100644 --- a/prisma/migrations/20260212000000_add_live_voting_enhancements/migration.sql +++ b/prisma/migrations/20260212000000_add_live_voting_enhancements/migration.sql @@ -1,99 +1,99 @@ --- Migration: Add live voting enhancements (criteria voting, audience voting, AudienceVoter) --- Brings LiveVotingSession, LiveVote, and new AudienceVoter model in sync with schema.prisma --- Uses IF NOT EXISTS / DO $$ guards for idempotent execution - --- ============================================================================= --- 1. LiveVotingSession: Add criteria-based & audience voting columns --- ============================================================================= - -ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "votingMode" TEXT NOT NULL DEFAULT 'simple'; -ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "criteriaJson" JSONB; -ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingMode" TEXT NOT NULL DEFAULT 'disabled'; -ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceMaxFavorites" INTEGER NOT NULL DEFAULT 3; -ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceRequireId" BOOLEAN NOT NULL DEFAULT false; -ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingDuration" INTEGER; - --- ============================================================================= --- 2. LiveVote: Add criteria scores, audience voter link, make userId nullable --- ============================================================================= - -ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "criterionScoresJson" JSONB; -ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "audienceVoterId" TEXT; - --- Make userId nullable (was NOT NULL in init migration) -ALTER TABLE "LiveVote" ALTER COLUMN "userId" DROP NOT NULL; - --- ============================================================================= --- 3. AudienceVoter: New table for audience participation --- ============================================================================= - -CREATE TABLE IF NOT EXISTS "AudienceVoter" ( - "id" TEXT NOT NULL, - "sessionId" TEXT NOT NULL, - "token" TEXT NOT NULL, - "identifier" TEXT, - "identifierType" TEXT, - "ipAddress" TEXT, - "userAgent" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "AudienceVoter_pkey" PRIMARY KEY ("id") -); - --- Unique constraint on token -DO $$ BEGIN - ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_token_key" UNIQUE ("token"); -EXCEPTION WHEN duplicate_object THEN NULL; END $$; - --- Indexes -CREATE INDEX IF NOT EXISTS "AudienceVoter_sessionId_idx" ON "AudienceVoter"("sessionId"); -CREATE INDEX IF NOT EXISTS "AudienceVoter_token_idx" ON "AudienceVoter"("token"); - --- Foreign key: AudienceVoter.sessionId -> LiveVotingSession.id -DO $$ BEGIN - ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_sessionId_fkey" - FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE; -EXCEPTION WHEN duplicate_object THEN NULL; END $$; - --- ============================================================================= --- 4. LiveVote: Foreign key and indexes for audienceVoterId --- ============================================================================= - -CREATE INDEX IF NOT EXISTS "LiveVote_audienceVoterId_idx" ON "LiveVote"("audienceVoterId"); - --- Foreign key: LiveVote.audienceVoterId -> AudienceVoter.id -DO $$ BEGIN - ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_audienceVoterId_fkey" - FOREIGN KEY ("audienceVoterId") REFERENCES "AudienceVoter"("id") ON DELETE CASCADE ON UPDATE CASCADE; -EXCEPTION WHEN duplicate_object THEN NULL; END $$; - --- Unique constraint: sessionId + projectId + audienceVoterId -DO $$ BEGIN - ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_projectId_audienceVoterId_key" - UNIQUE ("sessionId", "projectId", "audienceVoterId"); -EXCEPTION WHEN duplicate_object THEN NULL; END $$; - --- ============================================================================= --- SUMMARY: --- --- LiveVotingSession new columns: --- - votingMode (TEXT, default 'simple') --- - criteriaJson (JSONB, nullable) --- - audienceVotingMode (TEXT, default 'disabled') --- - audienceMaxFavorites (INTEGER, default 3) --- - audienceRequireId (BOOLEAN, default false) --- - audienceVotingDuration (INTEGER, nullable) --- --- LiveVote changes: --- - criterionScoresJson (JSONB, nullable) - new column --- - audienceVoterId (TEXT, nullable) - new column --- - userId changed from NOT NULL to nullable --- - New unique: (sessionId, projectId, audienceVoterId) --- - New index: audienceVoterId --- - New FK: audienceVoterId -> AudienceVoter(id) --- --- New table: AudienceVoter --- - id, sessionId, token (unique), identifier, identifierType, --- ipAddress, userAgent, createdAt --- - FK: sessionId -> LiveVotingSession(id) CASCADE --- ============================================================================= +-- Migration: Add live voting enhancements (criteria voting, audience voting, AudienceVoter) +-- Brings LiveVotingSession, LiveVote, and new AudienceVoter model in sync with schema.prisma +-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution + +-- ============================================================================= +-- 1. LiveVotingSession: Add criteria-based & audience voting columns +-- ============================================================================= + +ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "votingMode" TEXT NOT NULL DEFAULT 'simple'; +ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "criteriaJson" JSONB; +ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingMode" TEXT NOT NULL DEFAULT 'disabled'; +ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceMaxFavorites" INTEGER NOT NULL DEFAULT 3; +ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceRequireId" BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingDuration" INTEGER; + +-- ============================================================================= +-- 2. LiveVote: Add criteria scores, audience voter link, make userId nullable +-- ============================================================================= + +ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "criterionScoresJson" JSONB; +ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "audienceVoterId" TEXT; + +-- Make userId nullable (was NOT NULL in init migration) +ALTER TABLE "LiveVote" ALTER COLUMN "userId" DROP NOT NULL; + +-- ============================================================================= +-- 3. AudienceVoter: New table for audience participation +-- ============================================================================= + +CREATE TABLE IF NOT EXISTS "AudienceVoter" ( + "id" TEXT NOT NULL, + "sessionId" TEXT NOT NULL, + "token" TEXT NOT NULL, + "identifier" TEXT, + "identifierType" TEXT, + "ipAddress" TEXT, + "userAgent" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "AudienceVoter_pkey" PRIMARY KEY ("id") +); + +-- Unique constraint on token +DO $$ BEGIN + ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_token_key" UNIQUE ("token"); +EXCEPTION WHEN duplicate_object THEN NULL; END $$; + +-- Indexes +CREATE INDEX IF NOT EXISTS "AudienceVoter_sessionId_idx" ON "AudienceVoter"("sessionId"); +CREATE INDEX IF NOT EXISTS "AudienceVoter_token_idx" ON "AudienceVoter"("token"); + +-- Foreign key: AudienceVoter.sessionId -> LiveVotingSession.id +DO $$ BEGIN + ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_sessionId_fkey" + FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE; +EXCEPTION WHEN duplicate_object THEN NULL; END $$; + +-- ============================================================================= +-- 4. LiveVote: Foreign key and indexes for audienceVoterId +-- ============================================================================= + +CREATE INDEX IF NOT EXISTS "LiveVote_audienceVoterId_idx" ON "LiveVote"("audienceVoterId"); + +-- Foreign key: LiveVote.audienceVoterId -> AudienceVoter.id +DO $$ BEGIN + ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_audienceVoterId_fkey" + FOREIGN KEY ("audienceVoterId") REFERENCES "AudienceVoter"("id") ON DELETE CASCADE ON UPDATE CASCADE; +EXCEPTION WHEN duplicate_object THEN NULL; END $$; + +-- Unique constraint: sessionId + projectId + audienceVoterId +DO $$ BEGIN + ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_projectId_audienceVoterId_key" + UNIQUE ("sessionId", "projectId", "audienceVoterId"); +EXCEPTION WHEN duplicate_object THEN NULL; END $$; + +-- ============================================================================= +-- SUMMARY: +-- +-- LiveVotingSession new columns: +-- - votingMode (TEXT, default 'simple') +-- - criteriaJson (JSONB, nullable) +-- - audienceVotingMode (TEXT, default 'disabled') +-- - audienceMaxFavorites (INTEGER, default 3) +-- - audienceRequireId (BOOLEAN, default false) +-- - audienceVotingDuration (INTEGER, nullable) +-- +-- LiveVote changes: +-- - criterionScoresJson (JSONB, nullable) - new column +-- - audienceVoterId (TEXT, nullable) - new column +-- - userId changed from NOT NULL to nullable +-- - New unique: (sessionId, projectId, audienceVoterId) +-- - New index: audienceVoterId +-- - New FK: audienceVoterId -> AudienceVoter(id) +-- +-- New table: AudienceVoter +-- - id, sessionId, token (unique), identifier, identifierType, +-- ipAddress, userAgent, createdAt +-- - FK: sessionId -> LiveVotingSession(id) CASCADE +-- ============================================================================= diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index 044d57c..1af22ce 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ -# Please do not edit this file manually -# It should be added in your version-control system (e.g., Git) -provider = "postgresql" +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2e0fa52..a34e1ac 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,2100 +1,2100 @@ -// ============================================================================= -// MOPC Platform - Prisma Schema -// ============================================================================= -// This schema defines the database structure for the Monaco Ocean Protection -// Challenge jury voting platform. - -generator client { - provider = "prisma-client-js" - binaryTargets = ["native", "windows", "linux-musl-openssl-3.0.x"] -} - -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} - -// ============================================================================= -// ENUMS -// ============================================================================= - -enum UserRole { - SUPER_ADMIN - PROGRAM_ADMIN - JURY_MEMBER - MENTOR - OBSERVER - APPLICANT - AWARD_MASTER - AUDIENCE -} - -enum UserStatus { - NONE - INVITED - ACTIVE - SUSPENDED -} - -enum ProgramStatus { - DRAFT - ACTIVE - ARCHIVED -} - -enum ProjectStatus { - SUBMITTED - ELIGIBLE - ASSIGNED - SEMIFINALIST - FINALIST - REJECTED -} - -enum EvaluationStatus { - NOT_STARTED - DRAFT - SUBMITTED - LOCKED -} - -enum AssignmentMethod { - MANUAL - BULK - AI_SUGGESTED - AI_AUTO - ALGORITHM -} - -enum FileType { - EXEC_SUMMARY - PRESENTATION - VIDEO - OTHER - BUSINESS_PLAN - VIDEO_PITCH - SUPPORTING_DOC -} - -enum SubmissionSource { - MANUAL - CSV - NOTION - TYPEFORM - PUBLIC_FORM -} - -enum SettingType { - STRING - NUMBER - BOOLEAN - JSON - SECRET -} - -enum SettingCategory { - AI - BRANDING - EMAIL - STORAGE - SECURITY - DEFAULTS - WHATSAPP - AUDIT_CONFIG - LOCALIZATION - DIGEST - ANALYTICS - INTEGRATIONS - COMMUNICATION -} - -enum NotificationChannel { - EMAIL - WHATSAPP - BOTH - NONE -} - -enum ResourceType { - PDF - VIDEO - DOCUMENT - LINK - OTHER -} - -enum CohortLevel { - ALL - SEMIFINALIST - FINALIST -} - -enum PartnerVisibility { - ADMIN_ONLY - JURY_VISIBLE - PUBLIC -} - -enum PartnerType { - SPONSOR - PARTNER - SUPPORTER - MEDIA - OTHER -} - -// ============================================================================= -// PIPELINE / STAGE ENGINE ENUMS -// ============================================================================= - -enum StageType { - INTAKE - FILTER - EVALUATION - SELECTION - LIVE_FINAL - RESULTS -} - -enum TrackKind { - MAIN - AWARD - SHOWCASE -} - -enum RoutingMode { - PARALLEL - EXCLUSIVE - POST_MAIN -} - -enum StageStatus { - STAGE_DRAFT - STAGE_ACTIVE - STAGE_CLOSED - STAGE_ARCHIVED -} - -enum ProjectStageStateValue { - PENDING - IN_PROGRESS - PASSED - REJECTED - ROUTED - COMPLETED - WITHDRAWN -} - -enum DecisionMode { - JURY_VOTE - AWARD_MASTER_DECISION - ADMIN_DECISION -} - -enum OverrideReasonCode { - DATA_CORRECTION - POLICY_EXCEPTION - JURY_CONFLICT - SPONSOR_DECISION - ADMIN_DISCRETION -} - -// ============================================================================= -// APPLICANT SYSTEM ENUMS -// ============================================================================= - -enum CompetitionCategory { - STARTUP // Existing companies - BUSINESS_CONCEPT // Students/graduates -} - -enum OceanIssue { - POLLUTION_REDUCTION - CLIMATE_MITIGATION - TECHNOLOGY_INNOVATION - SUSTAINABLE_SHIPPING - BLUE_CARBON - HABITAT_RESTORATION - COMMUNITY_CAPACITY - SUSTAINABLE_FISHING - CONSUMER_AWARENESS - OCEAN_ACIDIFICATION - OTHER -} - -enum TeamMemberRole { - LEAD // Primary contact / team lead - MEMBER // Regular team member - ADVISOR // Advisor/mentor from team side -} - -enum MentorAssignmentMethod { - MANUAL - AI_SUGGESTED - AI_AUTO - ALGORITHM -} - -// ============================================================================= -// USERS & AUTHENTICATION -// ============================================================================= - -model User { - id String @id @default(cuid()) - email String @unique - name String? - emailVerified DateTime? // Required by NextAuth Prisma adapter - role UserRole @default(JURY_MEMBER) - status UserStatus @default(INVITED) - expertiseTags String[] @default([]) - maxAssignments Int? // Per-round limit - country String? // User's home country (for mentor matching) - metadataJson Json? @db.JsonB - - // Profile - bio String? // User bio for matching with project descriptions - profileImageKey String? // Storage key (e.g., "avatars/user123/1234567890.jpg") - profileImageProvider String? // Storage provider used: 's3' or 'local' - - // Phone and notification preferences (Phase 2) - phoneNumber String? - phoneNumberVerified Boolean @default(false) - notificationPreference NotificationChannel @default(EMAIL) - whatsappOptIn Boolean @default(false) - - // Onboarding (Phase 2B) - onboardingCompletedAt DateTime? - - // Password authentication (hybrid auth) - passwordHash String? // bcrypt hashed password - passwordSetAt DateTime? // When password was set - mustSetPassword Boolean @default(true) // Force setup on first login - - // Invitation token for one-click invite acceptance - inviteToken String? @unique - inviteTokenExpiresAt DateTime? - - // Digest & availability preferences - digestFrequency String @default("none") // 'none' | 'daily' | 'weekly' - preferredWorkload Int? - availabilityJson Json? @db.JsonB // { startDate?: string, endDate?: string } - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - lastLoginAt DateTime? - - // Relations - assignments Assignment[] - auditLogs AuditLog[] - gracePeriods GracePeriod[] - grantedGracePeriods GracePeriod[] @relation("GrantedBy") - notificationLogs NotificationLog[] - createdResources LearningResource[] @relation("ResourceCreatedBy") - resourceAccess ResourceAccess[] - submittedProjects Project[] @relation("ProjectSubmittedBy") - liveVotes LiveVote[] - - // Team membership & mentorship - teamMemberships TeamMember[] - mentorAssignments MentorAssignment[] @relation("MentorAssignments") - - // Awards - awardJurorships AwardJuror[] - awardVotes AwardVote[] - - // Filtering overrides - filteringOverrides FilteringResult[] @relation("FilteringOverriddenBy") - - // Award overrides - awardEligibilityOverrides AwardEligibility[] @relation("AwardEligibilityOverriddenBy") - awardWinnerOverrides SpecialAward[] @relation("AwardOverriddenBy") - - // In-app notifications - notifications InAppNotification[] @relation("UserNotifications") - notificationSettingsUpdated NotificationEmailSetting[] @relation("NotificationSettingUpdater") - - // Reminder logs - reminderLogs ReminderLog[] - - // Conflict of interest - conflictsOfInterest ConflictOfInterest[] - coiReviews ConflictOfInterest[] @relation("COIReviewedBy") - - // Evaluation summaries - generatedSummaries EvaluationSummary[] @relation("EvaluationSummaryGeneratedBy") - - // Mentor messages - mentorMessages MentorMessage[] @relation("MentorMessageSender") - - // Wizard templates - wizardTemplates WizardTemplate[] @relation("WizardTemplateCreatedBy") - - // Mentor notes - mentorNotes MentorNote[] @relation("MentorNoteAuthor") - - // Milestone completions - milestoneCompletions MentorMilestoneCompletion[] @relation("MilestoneCompletedBy") - - // Evaluation discussions - closedDiscussions EvaluationDiscussion[] @relation("DiscussionClosedBy") - discussionComments DiscussionComment[] @relation("DiscussionCommentAuthor") - - // Messaging - sentMessages Message[] @relation("MessageSender") - receivedMessages MessageRecipient[] @relation("MessageRecipient") - messageTemplates MessageTemplate[] @relation("MessageTemplateCreator") - - // Webhooks - webhooks Webhook[] @relation("WebhookCreator") - - // Digest logs - digestLogs DigestLog[] @relation("DigestLog") - - // NextAuth relations - accounts Account[] - sessions Session[] - - @@index([role]) - @@index([status]) -} - -// NextAuth.js required models -model Account { - id String @id @default(cuid()) - userId String - type String - provider String - providerAccountId String - refresh_token String? @db.Text - access_token String? @db.Text - expires_at Int? - token_type String? - scope String? - id_token String? @db.Text - session_state String? - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([provider, providerAccountId]) - @@index([userId]) -} - -model Session { - id String @id @default(cuid()) - sessionToken String @unique - userId String - expires DateTime - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) -} - -model VerificationToken { - identifier String - token String @unique - expires DateTime - - @@unique([identifier, token]) -} - -// ============================================================================= -// PROGRAMS & ROUNDS -// ============================================================================= - -model Program { - id String @id @default(cuid()) - name String // e.g., "Monaco Ocean Protection Challenge" - slug String? @unique // URL-friendly identifier for edition-wide applications - year Int // e.g., 2026 - status ProgramStatus @default(DRAFT) - description String? - settingsJson Json? @db.JsonB - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - projects Project[] - learningResources LearningResource[] - partners Partner[] - specialAwards SpecialAward[] - taggingJobs TaggingJob[] - wizardTemplates WizardTemplate[] - mentorMilestones MentorMilestone[] - pipelines Pipeline[] - - @@unique([name, year]) - @@index([status]) -} - -model WizardTemplate { - id String @id @default(cuid()) - name String - description String? - config Json @db.JsonB - isGlobal Boolean @default(false) - programId String? - program Program? @relation(fields: [programId], references: [id], onDelete: Cascade) - createdBy String - creator User @relation("WizardTemplateCreatedBy", fields: [createdBy], references: [id]) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@index([programId]) - @@index([isGlobal]) -} - -// Round model RETIRED in Phase 6 — all orchestration now uses Pipeline/Stage. -// roundId columns are preserved as optional raw fields for historical data. - -model EvaluationForm { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - version Int @default(1) - stageId String - - // Form configuration - // criteriaJson: Array of { id, label, description, scale, weight, required } - criteriaJson Json @db.JsonB - // scalesJson: { "1-5": { min, max, labels }, "1-10": { min, max, labels } } - scalesJson Json? @db.JsonB - isActive Boolean @default(false) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - evaluations Evaluation[] - - @@unique([stageId, version]) - @@index([stageId, isActive]) -} - -// ============================================================================= -// PROJECTS -// ============================================================================= - -model Project { - id String @id @default(cuid()) - programId String - roundId String? - status ProjectStatus @default(SUBMITTED) - - // Core fields - title String - teamName String? - description String? @db.Text - - // Competition category - competitionCategory CompetitionCategory? - oceanIssue OceanIssue? - - // Location - country String? - geographicZone String? // "Europe, France" - - // Institution (for students/Business Concepts) - institution String? - - // Mentorship - wantsMentorship Boolean @default(false) - - // Founding date - foundedAt DateTime? // When the project/company was founded - - // Submission links (external, from CSV) - phase1SubmissionUrl String? - phase2SubmissionUrl String? - - // Referral tracking - referralSource String? - - // Internal admin fields - internalComments String? @db.Text - applicationStatus String? // "Received", etc. - - // Submission tracking - submissionSource SubmissionSource @default(MANUAL) - submittedByEmail String? - submittedAt DateTime? - submittedByUserId String? - - // Project branding - logoKey String? // Storage key (e.g., "logos/project456/1234567890.png") - logoProvider String? // Storage provider used: 's3' or 'local' - - // Draft support - isDraft Boolean @default(false) - draftDataJson Json? @db.JsonB // Form data for drafts - draftExpiresAt DateTime? - - // Flexible fields - tags String[] @default([]) // "Ocean Conservation", "Tech", etc. - metadataJson Json? @db.JsonB // Custom fields from Typeform, etc. - externalIdsJson Json? @db.JsonB // Typeform ID, Notion ID, etc. - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - program Program @relation(fields: [programId], references: [id], onDelete: Cascade) - files ProjectFile[] - assignments Assignment[] - submittedBy User? @relation("ProjectSubmittedBy", fields: [submittedByUserId], references: [id], onDelete: SetNull) - teamMembers TeamMember[] - mentorAssignment MentorAssignment? - filteringResults FilteringResult[] - awardEligibilities AwardEligibility[] - awardVotes AwardVote[] - wonAwards SpecialAward[] @relation("AwardWinner") - projectTags ProjectTag[] - statusHistory ProjectStatusHistory[] - mentorMessages MentorMessage[] - evaluationSummaries EvaluationSummary[] - evaluationDiscussions EvaluationDiscussion[] - projectStageStates ProjectStageState[] - cohortProjects CohortProject[] - - @@index([programId]) - @@index([status]) - @@index([tags]) - @@index([submissionSource]) - @@index([submittedByUserId]) - @@index([competitionCategory]) - @@index([oceanIssue]) - @@index([country]) -} - -model FileRequirement { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - name String - description String? - acceptedMimeTypes String[] // e.g. ["application/pdf", "video/*"] - maxSizeMB Int? // Max file size in MB - isRequired Boolean @default(true) - sortOrder Int @default(0) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - files ProjectFile[] - - @@index([stageId]) -} - -model ProjectFile { - id String @id @default(cuid()) - projectId String - roundId String? // Which round this file was submitted for - requirementId String? // FK to FileRequirement (if uploaded against a requirement) - - // File info - fileType FileType - fileName String - mimeType String - size Int // bytes - - // MinIO location - bucket String - objectKey String - - isLate Boolean @default(false) // Uploaded after round deadline - - // Versioning - version Int @default(1) - replacedById String? // FK to the newer file that replaced this one - - createdAt DateTime @default(now()) - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - requirement FileRequirement? @relation(fields: [requirementId], references: [id], onDelete: SetNull) - replacedBy ProjectFile? @relation("FileVersions", fields: [replacedById], references: [id], onDelete: SetNull) - replacements ProjectFile[] @relation("FileVersions") - - @@unique([bucket, objectKey]) - @@index([projectId]) - @@index([fileType]) - @@index([requirementId]) -} - -// ============================================================================= -// ASSIGNMENTS & EVALUATIONS -// ============================================================================= - -model Assignment { - id String @id @default(cuid()) - userId String - projectId String - roundId String? // Legacy — kept for historical data - stageId String - - // Assignment info - method AssignmentMethod @default(MANUAL) - isRequired Boolean @default(true) - isCompleted Boolean @default(false) - - // AI assignment metadata - aiConfidenceScore Float? // 0-1 confidence from AI - expertiseMatchScore Float? // 0-1 match score - aiReasoning String? @db.Text - - createdAt DateTime @default(now()) - createdBy String? // Admin who created the assignment - - // Relations - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - evaluation Evaluation? - conflictOfInterest ConflictOfInterest? - - @@unique([userId, projectId, stageId]) - @@index([stageId]) - @@index([userId]) - @@index([projectId]) - @@index([isCompleted]) - @@index([projectId, userId]) -} - -model Evaluation { - id String @id @default(cuid()) - assignmentId String @unique - formId String - - // Status - status EvaluationStatus @default(NOT_STARTED) - - // Scores - // criterionScoresJson: { "criterion_id": score, ... } - criterionScoresJson Json? @db.JsonB - globalScore Int? // 1-10 - binaryDecision Boolean? // Yes/No for semi-finalist - feedbackText String? @db.Text - - // Versioning (currently unused - evaluations are updated in-place. - // TODO: Implement proper versioning by creating new rows on re-submission - // if version history is needed for audit purposes) - version Int @default(1) - - // Timestamps - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - submittedAt DateTime? - - // Relations - assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade) - form EvaluationForm @relation(fields: [formId], references: [id], onDelete: Cascade) - - @@index([status]) - @@index([submittedAt]) - @@index([formId]) - @@index([status, formId]) -} - -// ============================================================================= -// GRACE PERIODS -// ============================================================================= - -model GracePeriod { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - userId String - projectId String? // Optional: specific project or all projects in stage - - extendedUntil DateTime - reason String? @db.Text - grantedById String - - createdAt DateTime @default(now()) - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - grantedBy User @relation("GrantedBy", fields: [grantedById], references: [id]) - - @@index([stageId]) - @@index([userId]) - @@index([extendedUntil]) - @@index([grantedById]) - @@index([projectId]) - @@index([stageId, userId, extendedUntil]) -} - -// ============================================================================= -// SYSTEM SETTINGS -// ============================================================================= - -model SystemSettings { - id String @id @default(cuid()) - key String @unique - value String @db.Text - type SettingType @default(STRING) - category SettingCategory - - description String? - isSecret Boolean @default(false) // If true, value is encrypted - - updatedAt DateTime @updatedAt - updatedBy String? - - @@index([category]) -} - -// ============================================================================= -// AUDIT LOGGING -// ============================================================================= - -model AuditLog { - id String @id @default(cuid()) - userId String? - - // Event info - action String // "CREATE", "UPDATE", "DELETE", "LOGIN", "EXPORT", etc. - entityType String // "Round", "Project", "Evaluation", etc. - entityId String? - - // Details - detailsJson Json? @db.JsonB // Before/after values, additional context - previousDataJson Json? @db.JsonB // Previous state for tracking changes - - // Request info - ipAddress String? - userAgent String? - sessionId String? - - timestamp DateTime @default(now()) - - // Relations - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - - @@index([userId]) - @@index([action]) - @@index([entityType, entityId]) - @@index([timestamp]) - @@index([entityType, entityId, timestamp]) - @@index([sessionId]) -} - -// ============================================================================= -// AI USAGE TRACKING -// ============================================================================= - -model AIUsageLog { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - - // Who/what triggered it - userId String? - action String // ASSIGNMENT, FILTERING, AWARD_ELIGIBILITY, MENTOR_MATCHING - entityType String? // Round, Project, Award - entityId String? - - // What was used - model String // gpt-4o, gpt-4o-mini, o1, etc. - promptTokens Int - completionTokens Int - totalTokens Int - - // Cost tracking - estimatedCostUsd Decimal? @db.Decimal(10, 6) - - // Request context - batchSize Int? - itemsProcessed Int? - - // Status - status String // SUCCESS, PARTIAL, ERROR - errorMessage String? - - // Detailed data (optional) - detailsJson Json? @db.JsonB - - @@index([userId]) - @@index([action]) - @@index([createdAt]) - @@index([model]) -} - -// ============================================================================= -// NOTIFICATION LOG (Phase 2) -// ============================================================================= - -model NotificationLog { - id String @id @default(cuid()) - userId String - channel NotificationChannel - provider String? // META, TWILIO, SMTP - type String // MAGIC_LINK, REMINDER, ANNOUNCEMENT, JURY_INVITATION - status String // PENDING, SENT, DELIVERED, FAILED - externalId String? // Message ID from provider - errorMsg String? @db.Text - - createdAt DateTime @default(now()) - - // Relations - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([status]) - @@index([createdAt]) -} - -// ============================================================================= -// IN-APP NOTIFICATIONS -// ============================================================================= - -model InAppNotification { - id String @id @default(cuid()) - userId String - type String // FILTERING_COMPLETE, NEW_APPLICATION, ASSIGNED_TO_PROJECT, etc. - priority String @default("normal") // low, normal, high, urgent - icon String? // lucide icon name - title String - message String @db.Text - linkUrl String? // Where to navigate when clicked - linkLabel String? // CTA text - metadata Json? @db.JsonB // Extra context (projectId, roundId, etc.) - groupKey String? // For batching similar notifications - - isRead Boolean @default(false) - readAt DateTime? - expiresAt DateTime? // Auto-dismiss after date - - createdAt DateTime @default(now()) - - // Relations - user User @relation("UserNotifications", fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId, isRead]) - @@index([userId, createdAt]) - @@index([groupKey]) -} - -model NotificationEmailSetting { - id String @id @default(cuid()) - notificationType String @unique // e.g., "ADVANCED_TO_ROUND", "ASSIGNED_TO_PROJECT" - category String // "team", "jury", "mentor", "admin" - label String // Human-readable label for admin UI - description String? // Help text - sendEmail Boolean @default(true) - emailSubject String? // Custom subject template (optional) - emailTemplate String? @db.Text // Custom body template (optional) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - updatedById String? - updatedBy User? @relation("NotificationSettingUpdater", fields: [updatedById], references: [id]) - - @@index([category]) -} - -// ============================================================================= -// LEARNING HUB (Phase 2) -// ============================================================================= - -model LearningResource { - id String @id @default(cuid()) - programId String? // null = global resource - title String - description String? @db.Text - contentJson Json? @db.JsonB // BlockNote document structure - resourceType ResourceType - cohortLevel CohortLevel @default(ALL) - - // File storage (for uploaded resources) - fileName String? - mimeType String? - size Int? - bucket String? - objectKey String? - - // External link - externalUrl String? - - sortOrder Int @default(0) - isPublished Boolean @default(false) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - createdById String - - // Relations - program Program? @relation(fields: [programId], references: [id], onDelete: SetNull) - createdBy User @relation("ResourceCreatedBy", fields: [createdById], references: [id]) - accessLogs ResourceAccess[] - - @@index([programId]) - @@index([cohortLevel]) - @@index([isPublished]) - @@index([sortOrder]) -} - -model ResourceAccess { - id String @id @default(cuid()) - resourceId String - userId String - accessedAt DateTime @default(now()) - ipAddress String? - - // Relations - resource LearningResource @relation(fields: [resourceId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([resourceId]) - @@index([userId]) - @@index([accessedAt]) -} - -// ============================================================================= -// PARTNER MANAGEMENT (Phase 2) -// ============================================================================= - -model Partner { - id String @id @default(cuid()) - programId String? // null = global partner - name String - description String? @db.Text - website String? - partnerType PartnerType @default(PARTNER) - visibility PartnerVisibility @default(ADMIN_ONLY) - - // Logo file - logoFileName String? - logoBucket String? - logoObjectKey String? - - sortOrder Int @default(0) - isActive Boolean @default(true) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - program Program? @relation(fields: [programId], references: [id], onDelete: SetNull) - - @@index([programId]) - @@index([partnerType]) - @@index([visibility]) - @@index([isActive]) - @@index([sortOrder]) -} - -// ============================================================================= -// EXPERTISE TAGS (Phase 2B) -// ============================================================================= - -model ExpertiseTag { - id String @id @default(cuid()) - name String @unique - description String? - category String? // "Marine Science", "Technology", "Policy" - color String? // Hex for badge - isActive Boolean @default(true) - sortOrder Int @default(0) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - projectTags ProjectTag[] - - @@index([category]) - @@index([isActive]) - @@index([sortOrder]) -} - -// Project-Tag relationship for AI tagging -model ProjectTag { - id String @id @default(cuid()) - projectId String - tagId String - confidence Float @default(1.0) // AI confidence score 0-1 - source String @default("AI") // "AI" or "MANUAL" - createdAt DateTime @default(now()) - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - tag ExpertiseTag @relation(fields: [tagId], references: [id], onDelete: Cascade) - - @@unique([projectId, tagId]) - @@index([projectId]) - @@index([tagId]) -} - -// ============================================================================= -// LIVE VOTING (Phase 2B) -// ============================================================================= - -model LiveVotingSession { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String? @unique - status String @default("NOT_STARTED") // NOT_STARTED, IN_PROGRESS, PAUSED, COMPLETED - currentProjectIndex Int @default(0) - currentProjectId String? - votingStartedAt DateTime? - votingEndsAt DateTime? - projectOrderJson Json? @db.JsonB // Array of project IDs in presentation order - - // Criteria-based voting - votingMode String @default("simple") // "simple" (1-10) | "criteria" (per-criterion scores) - criteriaJson Json? @db.JsonB // Array of { id, label, description, scale, weight } - - // Audience & presentation settings - allowAudienceVotes Boolean @default(false) - audienceVoteWeight Float @default(0) // 0.0 to 1.0 - tieBreakerMethod String @default("admin_decides") // 'admin_decides' | 'highest_individual' | 'revote' - presentationSettingsJson Json? @db.JsonB - - // Audience voting configuration - audienceVotingMode String @default("disabled") // "disabled" | "per_project" | "per_category" | "favorites" - audienceMaxFavorites Int @default(3) // For "favorites" mode - audienceRequireId Boolean @default(false) // Require email/phone for audience - audienceVotingDuration Int? // Minutes (null = same as jury) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage? @relation(fields: [stageId], references: [id], onDelete: Cascade) - votes LiveVote[] - audienceVoters AudienceVoter[] - - @@index([status]) -} - -model LiveVote { - id String @id @default(cuid()) - sessionId String - projectId String - userId String? // Nullable for audience voters without accounts - score Int // 1-10 (or weighted score for criteria mode) - isAudienceVote Boolean @default(false) - votedAt DateTime @default(now()) - - // Criteria scores (used when votingMode="criteria") - criterionScoresJson Json? @db.JsonB // { [criterionId]: score } - null for simple mode - - // Audience voter link - audienceVoterId String? - - // Relations - session LiveVotingSession @relation(fields: [sessionId], references: [id], onDelete: Cascade) - user User? @relation(fields: [userId], references: [id], onDelete: Cascade) - audienceVoter AudienceVoter? @relation(fields: [audienceVoterId], references: [id], onDelete: Cascade) - - @@unique([sessionId, projectId, userId]) - @@unique([sessionId, projectId, audienceVoterId]) - @@index([sessionId]) - @@index([projectId]) - @@index([userId]) - @@index([audienceVoterId]) -} - -model AudienceVoter { - id String @id @default(cuid()) - sessionId String - token String @unique // Unique voting token (UUID) - identifier String? // Optional: email, phone, or name - identifierType String? // "email" | "phone" | "name" | "anonymous" - ipAddress String? - userAgent String? - createdAt DateTime @default(now()) - - // Relations - session LiveVotingSession @relation(fields: [sessionId], references: [id], onDelete: Cascade) - votes LiveVote[] - - @@index([sessionId]) - @@index([token]) -} - -// ============================================================================= -// TEAM MEMBERSHIP -// ============================================================================= - -model TeamMember { - id String @id @default(cuid()) - projectId String - userId String - role TeamMemberRole @default(MEMBER) - title String? // "CEO", "CTO", etc. - joinedAt DateTime @default(now()) - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([projectId, userId]) - @@index([projectId]) - @@index([userId]) - @@index([role]) -} - -// ============================================================================= -// MENTOR ASSIGNMENT -// ============================================================================= - -model MentorAssignment { - id String @id @default(cuid()) - projectId String @unique // One mentor per project - mentorId String // User with MENTOR role or expertise - - // Assignment tracking - method MentorAssignmentMethod @default(MANUAL) - assignedAt DateTime @default(now()) - assignedBy String? // Admin who assigned - - // AI assignment metadata - aiConfidenceScore Float? - expertiseMatchScore Float? - aiReasoning String? @db.Text - - // Tracking - completionStatus String @default("in_progress") // 'in_progress' | 'completed' | 'paused' - lastViewedAt DateTime? - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - mentor User @relation("MentorAssignments", fields: [mentorId], references: [id]) - notes MentorNote[] - milestoneCompletions MentorMilestoneCompletion[] - - @@index([mentorId]) - @@index([method]) -} - -// ============================================================================= -// FILTERING ROUND SYSTEM -// ============================================================================= - -enum FilteringOutcome { - PASSED - FILTERED_OUT - FLAGGED -} - -enum FilteringRuleType { - FIELD_BASED - DOCUMENT_CHECK - AI_SCREENING -} - -model FilteringRule { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - name String - ruleType FilteringRuleType - configJson Json @db.JsonB // Conditions, logic, action per rule type - priority Int @default(0) - isActive Boolean @default(true) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@index([stageId]) - @@index([priority]) -} - -model FilteringResult { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - projectId String - outcome FilteringOutcome - ruleResultsJson Json? @db.JsonB // Per-rule results - aiScreeningJson Json? @db.JsonB // AI screening details - - // Admin override - overriddenBy String? - overriddenAt DateTime? - overrideReason String? @db.Text - finalOutcome FilteringOutcome? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - overriddenByUser User? @relation("FilteringOverriddenBy", fields: [overriddenBy], references: [id], onDelete: SetNull) - - @@unique([stageId, projectId]) - @@index([stageId]) - @@index([projectId]) - @@index([outcome]) -} - -// Tracks progress of long-running filtering jobs -model FilteringJob { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - status FilteringJobStatus @default(PENDING) - totalProjects Int @default(0) - totalBatches Int @default(0) - currentBatch Int @default(0) - processedCount Int @default(0) - passedCount Int @default(0) - filteredCount Int @default(0) - flaggedCount Int @default(0) - errorMessage String? @db.Text - startedAt DateTime? - completedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@index([stageId]) - @@index([status]) -} - -enum FilteringJobStatus { - PENDING - RUNNING - COMPLETED - FAILED -} - -// Tracks progress of long-running AI assignment jobs -model AssignmentJob { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - status AssignmentJobStatus @default(PENDING) - totalProjects Int @default(0) - totalBatches Int @default(0) - currentBatch Int @default(0) - processedCount Int @default(0) - suggestionsCount Int @default(0) - suggestionsJson Json? @db.JsonB // Stores the AI-generated suggestions - errorMessage String? @db.Text - startedAt DateTime? - completedAt DateTime? - fallbackUsed Boolean @default(false) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@index([stageId]) - @@index([status]) -} - -enum AssignmentJobStatus { - PENDING - RUNNING - COMPLETED - FAILED -} - -// Tracks progress of long-running AI tagging jobs -model TaggingJob { - id String @id @default(cuid()) - programId String? // If tagging entire program - roundId String? // If tagging single round - status TaggingJobStatus @default(PENDING) - totalProjects Int @default(0) - processedCount Int @default(0) - taggedCount Int @default(0) - skippedCount Int @default(0) - failedCount Int @default(0) - errorMessage String? @db.Text - errorsJson Json? @db.JsonB // Array of error messages - startedAt DateTime? - completedAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations (optional - can tag by program) - program Program? @relation(fields: [programId], references: [id], onDelete: Cascade) - - @@index([programId]) - @@index([status]) -} - -enum TaggingJobStatus { - PENDING - RUNNING - COMPLETED - FAILED -} - -// ============================================================================= -// SPECIAL AWARDS SYSTEM -// ============================================================================= - -enum AwardScoringMode { - PICK_WINNER - RANKED - SCORED -} - -enum AwardStatus { - DRAFT - NOMINATIONS_OPEN - VOTING_OPEN - CLOSED - ARCHIVED -} - -enum EligibilityMethod { - AUTO - MANUAL -} - -model SpecialAward { - id String @id @default(cuid()) - programId String - name String - description String? @db.Text - status AwardStatus @default(DRAFT) - - // Criteria - criteriaText String? @db.Text // Plain-language criteria for AI - autoTagRulesJson Json? @db.JsonB // Deterministic eligibility rules - useAiEligibility Boolean @default(true) // Whether AI evaluates eligibility - - // Scoring - scoringMode AwardScoringMode @default(PICK_WINNER) - maxRankedPicks Int? // For RANKED mode - - // Voting window - votingStartAt DateTime? - votingEndAt DateTime? - - // Evaluation form (for SCORED mode) - evaluationFormId String? - - // Winner - winnerProjectId String? - winnerOverridden Boolean @default(false) - winnerOverriddenBy String? // FK to User who overrode the winner - - sortOrder Int @default(0) - - // Pipeline track link - trackId String? @unique - track Track? @relation(fields: [trackId], references: [id], onDelete: SetNull) - - // Eligibility job tracking - eligibilityJobStatus String? // PENDING, PROCESSING, COMPLETED, FAILED - eligibilityJobTotal Int? // total projects to process - eligibilityJobDone Int? // completed so far - eligibilityJobError String? @db.Text // error message if failed - eligibilityJobStarted DateTime? // when job started - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - program Program @relation(fields: [programId], references: [id], onDelete: Cascade) - winnerProject Project? @relation("AwardWinner", fields: [winnerProjectId], references: [id], onDelete: SetNull) - overriddenByUser User? @relation("AwardOverriddenBy", fields: [winnerOverriddenBy], references: [id], onDelete: SetNull) - eligibilities AwardEligibility[] - jurors AwardJuror[] - votes AwardVote[] - - @@index([programId]) - @@index([status]) - @@index([sortOrder]) -} - -model AwardEligibility { - id String @id @default(cuid()) - awardId String - projectId String - method EligibilityMethod @default(AUTO) - eligible Boolean @default(false) - aiReasoningJson Json? @db.JsonB - - // Admin override - overriddenBy String? - overriddenAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - award SpecialAward @relation(fields: [awardId], references: [id], onDelete: Cascade) - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - overriddenByUser User? @relation("AwardEligibilityOverriddenBy", fields: [overriddenBy], references: [id], onDelete: SetNull) - - @@unique([awardId, projectId]) - @@index([awardId]) - @@index([projectId]) - @@index([eligible]) - @@index([awardId, eligible]) -} - -model AwardJuror { - id String @id @default(cuid()) - awardId String - userId String - - createdAt DateTime @default(now()) - - // Relations - award SpecialAward @relation(fields: [awardId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([awardId, userId]) - @@index([awardId]) - @@index([userId]) -} - -model AwardVote { - id String @id @default(cuid()) - awardId String - userId String - projectId String - rank Int? // For RANKED mode - votedAt DateTime @default(now()) - - // Relations - award SpecialAward @relation(fields: [awardId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - - @@unique([awardId, userId, projectId]) - @@index([awardId]) - @@index([userId]) - @@index([projectId]) - @@index([awardId, userId]) -} - -// ============================================================================= -// REMINDER LOG (Evaluation Deadline Reminders) -// ============================================================================= - -model ReminderLog { - id String @id @default(cuid()) - roundId String? // Legacy — kept for historical data - stageId String - userId String - type String // "3_DAYS", "24H", "1H" - sentAt DateTime @default(now()) - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([stageId, userId, type]) - @@index([stageId]) -} - -// ============================================================================= -// CONFLICT OF INTEREST -// ============================================================================= - -model ConflictOfInterest { - id String @id @default(cuid()) - assignmentId String @unique - userId String - projectId String - roundId String? // Legacy — kept for historical data - hasConflict Boolean @default(false) - conflictType String? // "financial", "personal", "organizational", "other" - description String? @db.Text - declaredAt DateTime @default(now()) - - // Admin review - reviewedById String? - reviewedAt DateTime? - reviewAction String? // "cleared", "reassigned", "noted" - - // Relations - assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id]) - reviewedBy User? @relation("COIReviewedBy", fields: [reviewedById], references: [id]) - - @@index([userId]) - @@index([hasConflict]) -} - -// ============================================================================= -// AI EVALUATION SUMMARY -// ============================================================================= - -model EvaluationSummary { - id String @id @default(cuid()) - projectId String - roundId String? // Legacy — kept for historical data - stageId String - summaryJson Json @db.JsonB - generatedAt DateTime @default(now()) - generatedById String - model String - tokensUsed Int - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - generatedBy User @relation("EvaluationSummaryGeneratedBy", fields: [generatedById], references: [id]) - - @@unique([projectId, stageId]) - @@index([stageId]) -} - -// ============================================================================= -// PROJECT STATUS HISTORY -// ============================================================================= - -model ProjectStatusHistory { - id String @id @default(cuid()) - projectId String - status ProjectStatus - changedAt DateTime @default(now()) - changedBy String? - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - - @@index([projectId, changedAt]) -} - -// ============================================================================= -// MENTOR MESSAGES -// ============================================================================= - -model MentorMessage { - id String @id @default(cuid()) - projectId String - senderId String - message String @db.Text - isRead Boolean @default(false) - createdAt DateTime @default(now()) - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - sender User @relation("MentorMessageSender", fields: [senderId], references: [id]) - - @@index([projectId, createdAt]) -} - -// RoundTemplate model RETIRED in Phase 6 — replaced by WizardTemplate for pipelines. - -// ============================================================================= -// MENTOR NOTES & MILESTONES -// ============================================================================= - -model MentorNote { - id String @id @default(cuid()) - mentorAssignmentId String - authorId String - content String @db.Text - isVisibleToAdmin Boolean @default(true) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - mentorAssignment MentorAssignment @relation(fields: [mentorAssignmentId], references: [id], onDelete: Cascade) - author User @relation("MentorNoteAuthor", fields: [authorId], references: [id]) - - @@index([mentorAssignmentId]) - @@index([authorId]) -} - -model MentorMilestone { - id String @id @default(cuid()) - programId String - name String - description String? @db.Text - isRequired Boolean @default(false) - deadlineOffsetDays Int? - sortOrder Int @default(0) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - program Program @relation(fields: [programId], references: [id], onDelete: Cascade) - completions MentorMilestoneCompletion[] - - @@index([programId]) - @@index([sortOrder]) -} - -model MentorMilestoneCompletion { - id String @id @default(cuid()) - milestoneId String - mentorAssignmentId String - completedById String - completedAt DateTime @default(now()) - - // Relations - milestone MentorMilestone @relation(fields: [milestoneId], references: [id], onDelete: Cascade) - mentorAssignment MentorAssignment @relation(fields: [mentorAssignmentId], references: [id], onDelete: Cascade) - completedBy User @relation("MilestoneCompletedBy", fields: [completedById], references: [id]) - - @@unique([milestoneId, mentorAssignmentId]) - @@index([mentorAssignmentId]) - @@index([completedById]) -} - -// ============================================================================= -// EVALUATION DISCUSSIONS -// ============================================================================= - -model EvaluationDiscussion { - id String @id @default(cuid()) - projectId String - roundId String? // Legacy — kept for historical data - stageId String - status String @default("open") // 'open' | 'closed' - createdAt DateTime @default(now()) - closedAt DateTime? - closedById String? - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - closedBy User? @relation("DiscussionClosedBy", fields: [closedById], references: [id], onDelete: SetNull) - comments DiscussionComment[] - - @@unique([projectId, stageId]) - @@index([stageId]) - @@index([closedById]) -} - -model DiscussionComment { - id String @id @default(cuid()) - discussionId String - userId String - content String @db.Text - - createdAt DateTime @default(now()) - - // Relations - discussion EvaluationDiscussion @relation(fields: [discussionId], references: [id], onDelete: Cascade) - user User @relation("DiscussionCommentAuthor", fields: [userId], references: [id]) - - @@index([discussionId]) - @@index([userId]) -} - -// ============================================================================= -// MESSAGING SYSTEM -// ============================================================================= - -model Message { - id String @id @default(cuid()) - senderId String - recipientType String // 'USER', 'ROLE', 'ROUND_JURY', 'PROGRAM_TEAM', 'ALL' - recipientFilter Json? @db.JsonB - roundId String? - stageId String? - templateId String? - subject String - body String @db.Text - deliveryChannels String[] - - scheduledAt DateTime? - sentAt DateTime? - metadata Json? @db.JsonB - - createdAt DateTime @default(now()) - - // Relations - sender User @relation("MessageSender", fields: [senderId], references: [id]) - stage Stage? @relation(fields: [stageId], references: [id], onDelete: SetNull) - template MessageTemplate? @relation(fields: [templateId], references: [id], onDelete: SetNull) - recipients MessageRecipient[] - - @@index([senderId]) - @@index([stageId]) - @@index([sentAt]) -} - -model MessageRecipient { - id String @id @default(cuid()) - messageId String - userId String - channel String // 'EMAIL', 'IN_APP', etc. - isRead Boolean @default(false) - readAt DateTime? - deliveredAt DateTime? - - // Relations - message Message @relation(fields: [messageId], references: [id], onDelete: Cascade) - user User @relation("MessageRecipient", fields: [userId], references: [id], onDelete: Cascade) - - @@unique([messageId, userId, channel]) - @@index([userId]) -} - -model MessageTemplate { - id String @id @default(cuid()) - name String - category String // 'SYSTEM', 'EVALUATION', 'ASSIGNMENT' - subject String - body String @db.Text - variables Json? @db.JsonB - isActive Boolean @default(true) - createdBy String - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - creator User @relation("MessageTemplateCreator", fields: [createdBy], references: [id]) - messages Message[] - - @@index([category]) - @@index([isActive]) -} - -// ============================================================================= -// WEBHOOKS -// ============================================================================= - -model Webhook { - id String @id @default(cuid()) - name String - url String - secret String - events String[] - headers Json? @db.JsonB - maxRetries Int @default(3) - isActive Boolean @default(true) - createdById String - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - createdBy User @relation("WebhookCreator", fields: [createdById], references: [id]) - deliveries WebhookDelivery[] - - @@index([isActive]) - @@index([createdById]) -} - -model WebhookDelivery { - id String @id @default(cuid()) - webhookId String - event String - payload Json @db.JsonB - status String @default("PENDING") // 'PENDING', 'DELIVERED', 'FAILED' - responseStatus Int? - responseBody String? @db.Text - attempts Int @default(0) - lastAttemptAt DateTime? - - createdAt DateTime @default(now()) - - // Relations - webhook Webhook @relation(fields: [webhookId], references: [id], onDelete: Cascade) - - @@index([webhookId]) - @@index([status]) - @@index([event]) -} - -// ============================================================================= -// DIGEST LOGS -// ============================================================================= - -model DigestLog { - id String @id @default(cuid()) - userId String - digestType String // 'daily' | 'weekly' - contentJson Json @db.JsonB - sentAt DateTime @default(now()) - - // Relations - user User @relation("DigestLog", fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([sentAt]) -} - -// ============================================================================= -// PIPELINE / TRACK / STAGE ENGINE -// ============================================================================= - -model Pipeline { - id String @id @default(cuid()) - programId String - name String - slug String @unique - status String @default("DRAFT") // DRAFT, ACTIVE, ARCHIVED - settingsJson Json? @db.JsonB - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - program Program @relation(fields: [programId], references: [id], onDelete: Cascade) - tracks Track[] - routingRules RoutingRule[] - - @@index([programId]) - @@index([status]) -} - -model Track { - id String @id @default(cuid()) - pipelineId String - name String - slug String - kind TrackKind @default(MAIN) - routingMode RoutingMode? - decisionMode DecisionMode? - sortOrder Int @default(0) - settingsJson Json? @db.JsonB - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) - stages Stage[] - projectStageStates ProjectStageState[] - specialAward SpecialAward? - routingRulesAsSource RoutingRule[] @relation("RoutingSourceTrack") - routingRulesAsDestination RoutingRule[] @relation("RoutingDestinationTrack") - - @@unique([pipelineId, slug]) - @@unique([pipelineId, sortOrder]) - @@index([pipelineId]) - @@index([kind]) -} - -model Stage { - id String @id @default(cuid()) - trackId String - stageType StageType - name String - slug String - status StageStatus @default(STAGE_DRAFT) - sortOrder Int @default(0) - configJson Json? @db.JsonB - windowOpenAt DateTime? - windowCloseAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) - projectStageStates ProjectStageState[] - transitionsFrom StageTransition[] @relation("TransitionFrom") - transitionsTo StageTransition[] @relation("TransitionTo") - cohorts Cohort[] - liveCursor LiveProgressCursor? - liveVotingSession LiveVotingSession? - - // Reverse relations from existing models - evaluationForms EvaluationForm[] - assignments Assignment[] - fileRequirements FileRequirement[] - filteringRules FilteringRule[] - filteringResults FilteringResult[] - filteringJobs FilteringJob[] - assignmentJobs AssignmentJob[] - gracePeriods GracePeriod[] - reminderLogs ReminderLog[] - evaluationSummaries EvaluationSummary[] - evaluationDiscussions EvaluationDiscussion[] - messages Message[] - - @@unique([trackId, slug]) - @@unique([trackId, sortOrder]) - @@index([trackId]) - @@index([stageType]) - @@index([status]) -} - -model StageTransition { - id String @id @default(cuid()) - fromStageId String - toStageId String - isDefault Boolean @default(false) - guardJson Json? @db.JsonB // Conditions that must be met - - createdAt DateTime @default(now()) - - // Relations - fromStage Stage @relation("TransitionFrom", fields: [fromStageId], references: [id], onDelete: Cascade) - toStage Stage @relation("TransitionTo", fields: [toStageId], references: [id], onDelete: Cascade) - - @@unique([fromStageId, toStageId]) - @@index([fromStageId]) - @@index([toStageId]) -} - -model ProjectStageState { - id String @id @default(cuid()) - projectId String - trackId String - stageId String - state ProjectStageStateValue @default(PENDING) - enteredAt DateTime @default(now()) - exitedAt DateTime? - metadataJson Json? @db.JsonB - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@unique([projectId, trackId, stageId]) - @@index([projectId]) - @@index([trackId]) - @@index([stageId]) - @@index([state]) - @@index([projectId, trackId]) -} - -model RoutingRule { - id String @id @default(cuid()) - pipelineId String - name String - scope String @default("global") // global, track, stage - sourceTrackId String? - destinationTrackId String - destinationStageId String? - predicateJson Json @db.JsonB // { field, operator, value } or compound - priority Int @default(0) - isActive Boolean @default(true) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) - sourceTrack Track? @relation("RoutingSourceTrack", fields: [sourceTrackId], references: [id], onDelete: SetNull) - destinationTrack Track @relation("RoutingDestinationTrack", fields: [destinationTrackId], references: [id], onDelete: Cascade) - - @@index([pipelineId]) - @@index([priority]) - @@index([isActive]) -} - -model Cohort { - id String @id @default(cuid()) - stageId String - name String - votingMode String @default("simple") // simple, criteria, ranked - isOpen Boolean @default(false) - windowOpenAt DateTime? - windowCloseAt DateTime? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - projects CohortProject[] - - @@index([stageId]) - @@index([isOpen]) -} - -model CohortProject { - id String @id @default(cuid()) - cohortId String - projectId String - sortOrder Int @default(0) - - createdAt DateTime @default(now()) - - // Relations - cohort Cohort @relation(fields: [cohortId], references: [id], onDelete: Cascade) - project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) - - @@unique([cohortId, projectId]) - @@index([cohortId]) - @@index([projectId]) - @@index([sortOrder]) -} - -model LiveProgressCursor { - id String @id @default(cuid()) - stageId String @unique - sessionId String @unique @default(cuid()) - activeProjectId String? - activeOrderIndex Int @default(0) - isPaused Boolean @default(false) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - // Relations - stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) - - @@index([sessionId]) -} - -model OverrideAction { - id String @id @default(cuid()) - entityType String // ProjectStageState, FilteringResult, AwardEligibility, etc. - entityId String - previousValue Json? @db.JsonB - newValueJson Json @db.JsonB - reasonCode OverrideReasonCode - reasonText String? @db.Text - actorId String - - createdAt DateTime @default(now()) - - @@index([entityType, entityId]) - @@index([actorId]) - @@index([reasonCode]) - @@index([createdAt]) -} - -model DecisionAuditLog { - id String @id @default(cuid()) - eventType String // stage.transitioned, routing.executed, filtering.completed, etc. - entityType String - entityId String - actorId String? - detailsJson Json? @db.JsonB - snapshotJson Json? @db.JsonB // State at time of decision - - createdAt DateTime @default(now()) - - @@index([eventType]) - @@index([entityType, entityId]) - @@index([actorId]) - @@index([createdAt]) -} - -model NotificationPolicy { - id String @id @default(cuid()) - eventType String @unique // stage.transitioned, filtering.completed, etc. - channel String @default("EMAIL") // EMAIL, IN_APP, BOTH, NONE - templateId String? // Optional reference to MessageTemplate - isActive Boolean @default(true) - configJson Json? @db.JsonB // Additional config (delay, batch, etc.) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@index([eventType]) - @@index([isActive]) -} +// ============================================================================= +// MOPC Platform - Prisma Schema +// ============================================================================= +// This schema defines the database structure for the Monaco Ocean Protection +// Challenge jury voting platform. + +generator client { + provider = "prisma-client-js" + binaryTargets = ["native", "windows", "linux-musl-openssl-3.0.x"] +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +// ============================================================================= +// ENUMS +// ============================================================================= + +enum UserRole { + SUPER_ADMIN + PROGRAM_ADMIN + JURY_MEMBER + MENTOR + OBSERVER + APPLICANT + AWARD_MASTER + AUDIENCE +} + +enum UserStatus { + NONE + INVITED + ACTIVE + SUSPENDED +} + +enum ProgramStatus { + DRAFT + ACTIVE + ARCHIVED +} + +enum ProjectStatus { + SUBMITTED + ELIGIBLE + ASSIGNED + SEMIFINALIST + FINALIST + REJECTED +} + +enum EvaluationStatus { + NOT_STARTED + DRAFT + SUBMITTED + LOCKED +} + +enum AssignmentMethod { + MANUAL + BULK + AI_SUGGESTED + AI_AUTO + ALGORITHM +} + +enum FileType { + EXEC_SUMMARY + PRESENTATION + VIDEO + OTHER + BUSINESS_PLAN + VIDEO_PITCH + SUPPORTING_DOC +} + +enum SubmissionSource { + MANUAL + CSV + NOTION + TYPEFORM + PUBLIC_FORM +} + +enum SettingType { + STRING + NUMBER + BOOLEAN + JSON + SECRET +} + +enum SettingCategory { + AI + BRANDING + EMAIL + STORAGE + SECURITY + DEFAULTS + WHATSAPP + AUDIT_CONFIG + LOCALIZATION + DIGEST + ANALYTICS + INTEGRATIONS + COMMUNICATION +} + +enum NotificationChannel { + EMAIL + WHATSAPP + BOTH + NONE +} + +enum ResourceType { + PDF + VIDEO + DOCUMENT + LINK + OTHER +} + +enum CohortLevel { + ALL + SEMIFINALIST + FINALIST +} + +enum PartnerVisibility { + ADMIN_ONLY + JURY_VISIBLE + PUBLIC +} + +enum PartnerType { + SPONSOR + PARTNER + SUPPORTER + MEDIA + OTHER +} + +// ============================================================================= +// PIPELINE / STAGE ENGINE ENUMS +// ============================================================================= + +enum StageType { + INTAKE + FILTER + EVALUATION + SELECTION + LIVE_FINAL + RESULTS +} + +enum TrackKind { + MAIN + AWARD + SHOWCASE +} + +enum RoutingMode { + PARALLEL + EXCLUSIVE + POST_MAIN +} + +enum StageStatus { + STAGE_DRAFT + STAGE_ACTIVE + STAGE_CLOSED + STAGE_ARCHIVED +} + +enum ProjectStageStateValue { + PENDING + IN_PROGRESS + PASSED + REJECTED + ROUTED + COMPLETED + WITHDRAWN +} + +enum DecisionMode { + JURY_VOTE + AWARD_MASTER_DECISION + ADMIN_DECISION +} + +enum OverrideReasonCode { + DATA_CORRECTION + POLICY_EXCEPTION + JURY_CONFLICT + SPONSOR_DECISION + ADMIN_DISCRETION +} + +// ============================================================================= +// APPLICANT SYSTEM ENUMS +// ============================================================================= + +enum CompetitionCategory { + STARTUP // Existing companies + BUSINESS_CONCEPT // Students/graduates +} + +enum OceanIssue { + POLLUTION_REDUCTION + CLIMATE_MITIGATION + TECHNOLOGY_INNOVATION + SUSTAINABLE_SHIPPING + BLUE_CARBON + HABITAT_RESTORATION + COMMUNITY_CAPACITY + SUSTAINABLE_FISHING + CONSUMER_AWARENESS + OCEAN_ACIDIFICATION + OTHER +} + +enum TeamMemberRole { + LEAD // Primary contact / team lead + MEMBER // Regular team member + ADVISOR // Advisor/mentor from team side +} + +enum MentorAssignmentMethod { + MANUAL + AI_SUGGESTED + AI_AUTO + ALGORITHM +} + +// ============================================================================= +// USERS & AUTHENTICATION +// ============================================================================= + +model User { + id String @id @default(cuid()) + email String @unique + name String? + emailVerified DateTime? // Required by NextAuth Prisma adapter + role UserRole @default(JURY_MEMBER) + status UserStatus @default(INVITED) + expertiseTags String[] @default([]) + maxAssignments Int? // Per-round limit + country String? // User's home country (for mentor matching) + metadataJson Json? @db.JsonB + + // Profile + bio String? // User bio for matching with project descriptions + profileImageKey String? // Storage key (e.g., "avatars/user123/1234567890.jpg") + profileImageProvider String? // Storage provider used: 's3' or 'local' + + // Phone and notification preferences (Phase 2) + phoneNumber String? + phoneNumberVerified Boolean @default(false) + notificationPreference NotificationChannel @default(EMAIL) + whatsappOptIn Boolean @default(false) + + // Onboarding (Phase 2B) + onboardingCompletedAt DateTime? + + // Password authentication (hybrid auth) + passwordHash String? // bcrypt hashed password + passwordSetAt DateTime? // When password was set + mustSetPassword Boolean @default(true) // Force setup on first login + + // Invitation token for one-click invite acceptance + inviteToken String? @unique + inviteTokenExpiresAt DateTime? + + // Digest & availability preferences + digestFrequency String @default("none") // 'none' | 'daily' | 'weekly' + preferredWorkload Int? + availabilityJson Json? @db.JsonB // { startDate?: string, endDate?: string } + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + lastLoginAt DateTime? + + // Relations + assignments Assignment[] + auditLogs AuditLog[] + gracePeriods GracePeriod[] + grantedGracePeriods GracePeriod[] @relation("GrantedBy") + notificationLogs NotificationLog[] + createdResources LearningResource[] @relation("ResourceCreatedBy") + resourceAccess ResourceAccess[] + submittedProjects Project[] @relation("ProjectSubmittedBy") + liveVotes LiveVote[] + + // Team membership & mentorship + teamMemberships TeamMember[] + mentorAssignments MentorAssignment[] @relation("MentorAssignments") + + // Awards + awardJurorships AwardJuror[] + awardVotes AwardVote[] + + // Filtering overrides + filteringOverrides FilteringResult[] @relation("FilteringOverriddenBy") + + // Award overrides + awardEligibilityOverrides AwardEligibility[] @relation("AwardEligibilityOverriddenBy") + awardWinnerOverrides SpecialAward[] @relation("AwardOverriddenBy") + + // In-app notifications + notifications InAppNotification[] @relation("UserNotifications") + notificationSettingsUpdated NotificationEmailSetting[] @relation("NotificationSettingUpdater") + + // Reminder logs + reminderLogs ReminderLog[] + + // Conflict of interest + conflictsOfInterest ConflictOfInterest[] + coiReviews ConflictOfInterest[] @relation("COIReviewedBy") + + // Evaluation summaries + generatedSummaries EvaluationSummary[] @relation("EvaluationSummaryGeneratedBy") + + // Mentor messages + mentorMessages MentorMessage[] @relation("MentorMessageSender") + + // Wizard templates + wizardTemplates WizardTemplate[] @relation("WizardTemplateCreatedBy") + + // Mentor notes + mentorNotes MentorNote[] @relation("MentorNoteAuthor") + + // Milestone completions + milestoneCompletions MentorMilestoneCompletion[] @relation("MilestoneCompletedBy") + + // Evaluation discussions + closedDiscussions EvaluationDiscussion[] @relation("DiscussionClosedBy") + discussionComments DiscussionComment[] @relation("DiscussionCommentAuthor") + + // Messaging + sentMessages Message[] @relation("MessageSender") + receivedMessages MessageRecipient[] @relation("MessageRecipient") + messageTemplates MessageTemplate[] @relation("MessageTemplateCreator") + + // Webhooks + webhooks Webhook[] @relation("WebhookCreator") + + // Digest logs + digestLogs DigestLog[] @relation("DigestLog") + + // NextAuth relations + accounts Account[] + sessions Session[] + + @@index([role]) + @@index([status]) +} + +// NextAuth.js required models +model Account { + id String @id @default(cuid()) + userId String + type String + provider String + providerAccountId String + refresh_token String? @db.Text + access_token String? @db.Text + expires_at Int? + token_type String? + scope String? + id_token String? @db.Text + session_state String? + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([provider, providerAccountId]) + @@index([userId]) +} + +model Session { + id String @id @default(cuid()) + sessionToken String @unique + userId String + expires DateTime + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) +} + +model VerificationToken { + identifier String + token String @unique + expires DateTime + + @@unique([identifier, token]) +} + +// ============================================================================= +// PROGRAMS & ROUNDS +// ============================================================================= + +model Program { + id String @id @default(cuid()) + name String // e.g., "Monaco Ocean Protection Challenge" + slug String? @unique // URL-friendly identifier for edition-wide applications + year Int // e.g., 2026 + status ProgramStatus @default(DRAFT) + description String? + settingsJson Json? @db.JsonB + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + projects Project[] + learningResources LearningResource[] + partners Partner[] + specialAwards SpecialAward[] + taggingJobs TaggingJob[] + wizardTemplates WizardTemplate[] + mentorMilestones MentorMilestone[] + pipelines Pipeline[] + + @@unique([name, year]) + @@index([status]) +} + +model WizardTemplate { + id String @id @default(cuid()) + name String + description String? + config Json @db.JsonB + isGlobal Boolean @default(false) + programId String? + program Program? @relation(fields: [programId], references: [id], onDelete: Cascade) + createdBy String + creator User @relation("WizardTemplateCreatedBy", fields: [createdBy], references: [id]) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([programId]) + @@index([isGlobal]) +} + +// Round model RETIRED in Phase 6 — all orchestration now uses Pipeline/Stage. +// roundId columns are preserved as optional raw fields for historical data. + +model EvaluationForm { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + version Int @default(1) + stageId String + + // Form configuration + // criteriaJson: Array of { id, label, description, scale, weight, required } + criteriaJson Json @db.JsonB + // scalesJson: { "1-5": { min, max, labels }, "1-10": { min, max, labels } } + scalesJson Json? @db.JsonB + isActive Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + evaluations Evaluation[] + + @@unique([stageId, version]) + @@index([stageId, isActive]) +} + +// ============================================================================= +// PROJECTS +// ============================================================================= + +model Project { + id String @id @default(cuid()) + programId String + roundId String? + status ProjectStatus @default(SUBMITTED) + + // Core fields + title String + teamName String? + description String? @db.Text + + // Competition category + competitionCategory CompetitionCategory? + oceanIssue OceanIssue? + + // Location + country String? + geographicZone String? // "Europe, France" + + // Institution (for students/Business Concepts) + institution String? + + // Mentorship + wantsMentorship Boolean @default(false) + + // Founding date + foundedAt DateTime? // When the project/company was founded + + // Submission links (external, from CSV) + phase1SubmissionUrl String? + phase2SubmissionUrl String? + + // Referral tracking + referralSource String? + + // Internal admin fields + internalComments String? @db.Text + applicationStatus String? // "Received", etc. + + // Submission tracking + submissionSource SubmissionSource @default(MANUAL) + submittedByEmail String? + submittedAt DateTime? + submittedByUserId String? + + // Project branding + logoKey String? // Storage key (e.g., "logos/project456/1234567890.png") + logoProvider String? // Storage provider used: 's3' or 'local' + + // Draft support + isDraft Boolean @default(false) + draftDataJson Json? @db.JsonB // Form data for drafts + draftExpiresAt DateTime? + + // Flexible fields + tags String[] @default([]) // "Ocean Conservation", "Tech", etc. + metadataJson Json? @db.JsonB // Custom fields from Typeform, etc. + externalIdsJson Json? @db.JsonB // Typeform ID, Notion ID, etc. + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + program Program @relation(fields: [programId], references: [id], onDelete: Cascade) + files ProjectFile[] + assignments Assignment[] + submittedBy User? @relation("ProjectSubmittedBy", fields: [submittedByUserId], references: [id], onDelete: SetNull) + teamMembers TeamMember[] + mentorAssignment MentorAssignment? + filteringResults FilteringResult[] + awardEligibilities AwardEligibility[] + awardVotes AwardVote[] + wonAwards SpecialAward[] @relation("AwardWinner") + projectTags ProjectTag[] + statusHistory ProjectStatusHistory[] + mentorMessages MentorMessage[] + evaluationSummaries EvaluationSummary[] + evaluationDiscussions EvaluationDiscussion[] + projectStageStates ProjectStageState[] + cohortProjects CohortProject[] + + @@index([programId]) + @@index([status]) + @@index([tags]) + @@index([submissionSource]) + @@index([submittedByUserId]) + @@index([competitionCategory]) + @@index([oceanIssue]) + @@index([country]) +} + +model FileRequirement { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + name String + description String? + acceptedMimeTypes String[] // e.g. ["application/pdf", "video/*"] + maxSizeMB Int? // Max file size in MB + isRequired Boolean @default(true) + sortOrder Int @default(0) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + files ProjectFile[] + + @@index([stageId]) +} + +model ProjectFile { + id String @id @default(cuid()) + projectId String + roundId String? // Which round this file was submitted for + requirementId String? // FK to FileRequirement (if uploaded against a requirement) + + // File info + fileType FileType + fileName String + mimeType String + size Int // bytes + + // MinIO location + bucket String + objectKey String + + isLate Boolean @default(false) // Uploaded after round deadline + + // Versioning + version Int @default(1) + replacedById String? // FK to the newer file that replaced this one + + createdAt DateTime @default(now()) + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + requirement FileRequirement? @relation(fields: [requirementId], references: [id], onDelete: SetNull) + replacedBy ProjectFile? @relation("FileVersions", fields: [replacedById], references: [id], onDelete: SetNull) + replacements ProjectFile[] @relation("FileVersions") + + @@unique([bucket, objectKey]) + @@index([projectId]) + @@index([fileType]) + @@index([requirementId]) +} + +// ============================================================================= +// ASSIGNMENTS & EVALUATIONS +// ============================================================================= + +model Assignment { + id String @id @default(cuid()) + userId String + projectId String + roundId String? // Legacy — kept for historical data + stageId String + + // Assignment info + method AssignmentMethod @default(MANUAL) + isRequired Boolean @default(true) + isCompleted Boolean @default(false) + + // AI assignment metadata + aiConfidenceScore Float? // 0-1 confidence from AI + expertiseMatchScore Float? // 0-1 match score + aiReasoning String? @db.Text + + createdAt DateTime @default(now()) + createdBy String? // Admin who created the assignment + + // Relations + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + evaluation Evaluation? + conflictOfInterest ConflictOfInterest? + + @@unique([userId, projectId, stageId]) + @@index([stageId]) + @@index([userId]) + @@index([projectId]) + @@index([isCompleted]) + @@index([projectId, userId]) +} + +model Evaluation { + id String @id @default(cuid()) + assignmentId String @unique + formId String + + // Status + status EvaluationStatus @default(NOT_STARTED) + + // Scores + // criterionScoresJson: { "criterion_id": score, ... } + criterionScoresJson Json? @db.JsonB + globalScore Int? // 1-10 + binaryDecision Boolean? // Yes/No for semi-finalist + feedbackText String? @db.Text + + // Versioning (currently unused - evaluations are updated in-place. + // TODO: Implement proper versioning by creating new rows on re-submission + // if version history is needed for audit purposes) + version Int @default(1) + + // Timestamps + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + submittedAt DateTime? + + // Relations + assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade) + form EvaluationForm @relation(fields: [formId], references: [id], onDelete: Cascade) + + @@index([status]) + @@index([submittedAt]) + @@index([formId]) + @@index([status, formId]) +} + +// ============================================================================= +// GRACE PERIODS +// ============================================================================= + +model GracePeriod { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + userId String + projectId String? // Optional: specific project or all projects in stage + + extendedUntil DateTime + reason String? @db.Text + grantedById String + + createdAt DateTime @default(now()) + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + grantedBy User @relation("GrantedBy", fields: [grantedById], references: [id]) + + @@index([stageId]) + @@index([userId]) + @@index([extendedUntil]) + @@index([grantedById]) + @@index([projectId]) + @@index([stageId, userId, extendedUntil]) +} + +// ============================================================================= +// SYSTEM SETTINGS +// ============================================================================= + +model SystemSettings { + id String @id @default(cuid()) + key String @unique + value String @db.Text + type SettingType @default(STRING) + category SettingCategory + + description String? + isSecret Boolean @default(false) // If true, value is encrypted + + updatedAt DateTime @updatedAt + updatedBy String? + + @@index([category]) +} + +// ============================================================================= +// AUDIT LOGGING +// ============================================================================= + +model AuditLog { + id String @id @default(cuid()) + userId String? + + // Event info + action String // "CREATE", "UPDATE", "DELETE", "LOGIN", "EXPORT", etc. + entityType String // "Round", "Project", "Evaluation", etc. + entityId String? + + // Details + detailsJson Json? @db.JsonB // Before/after values, additional context + previousDataJson Json? @db.JsonB // Previous state for tracking changes + + // Request info + ipAddress String? + userAgent String? + sessionId String? + + timestamp DateTime @default(now()) + + // Relations + user User? @relation(fields: [userId], references: [id], onDelete: SetNull) + + @@index([userId]) + @@index([action]) + @@index([entityType, entityId]) + @@index([timestamp]) + @@index([entityType, entityId, timestamp]) + @@index([sessionId]) +} + +// ============================================================================= +// AI USAGE TRACKING +// ============================================================================= + +model AIUsageLog { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + + // Who/what triggered it + userId String? + action String // ASSIGNMENT, FILTERING, AWARD_ELIGIBILITY, MENTOR_MATCHING + entityType String? // Round, Project, Award + entityId String? + + // What was used + model String // gpt-4o, gpt-4o-mini, o1, etc. + promptTokens Int + completionTokens Int + totalTokens Int + + // Cost tracking + estimatedCostUsd Decimal? @db.Decimal(10, 6) + + // Request context + batchSize Int? + itemsProcessed Int? + + // Status + status String // SUCCESS, PARTIAL, ERROR + errorMessage String? + + // Detailed data (optional) + detailsJson Json? @db.JsonB + + @@index([userId]) + @@index([action]) + @@index([createdAt]) + @@index([model]) +} + +// ============================================================================= +// NOTIFICATION LOG (Phase 2) +// ============================================================================= + +model NotificationLog { + id String @id @default(cuid()) + userId String + channel NotificationChannel + provider String? // META, TWILIO, SMTP + type String // MAGIC_LINK, REMINDER, ANNOUNCEMENT, JURY_INVITATION + status String // PENDING, SENT, DELIVERED, FAILED + externalId String? // Message ID from provider + errorMsg String? @db.Text + + createdAt DateTime @default(now()) + + // Relations + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) + @@index([status]) + @@index([createdAt]) +} + +// ============================================================================= +// IN-APP NOTIFICATIONS +// ============================================================================= + +model InAppNotification { + id String @id @default(cuid()) + userId String + type String // FILTERING_COMPLETE, NEW_APPLICATION, ASSIGNED_TO_PROJECT, etc. + priority String @default("normal") // low, normal, high, urgent + icon String? // lucide icon name + title String + message String @db.Text + linkUrl String? // Where to navigate when clicked + linkLabel String? // CTA text + metadata Json? @db.JsonB // Extra context (projectId, roundId, etc.) + groupKey String? // For batching similar notifications + + isRead Boolean @default(false) + readAt DateTime? + expiresAt DateTime? // Auto-dismiss after date + + createdAt DateTime @default(now()) + + // Relations + user User @relation("UserNotifications", fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId, isRead]) + @@index([userId, createdAt]) + @@index([groupKey]) +} + +model NotificationEmailSetting { + id String @id @default(cuid()) + notificationType String @unique // e.g., "ADVANCED_TO_ROUND", "ASSIGNED_TO_PROJECT" + category String // "team", "jury", "mentor", "admin" + label String // Human-readable label for admin UI + description String? // Help text + sendEmail Boolean @default(true) + emailSubject String? // Custom subject template (optional) + emailTemplate String? @db.Text // Custom body template (optional) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + updatedById String? + updatedBy User? @relation("NotificationSettingUpdater", fields: [updatedById], references: [id]) + + @@index([category]) +} + +// ============================================================================= +// LEARNING HUB (Phase 2) +// ============================================================================= + +model LearningResource { + id String @id @default(cuid()) + programId String? // null = global resource + title String + description String? @db.Text + contentJson Json? @db.JsonB // BlockNote document structure + resourceType ResourceType + cohortLevel CohortLevel @default(ALL) + + // File storage (for uploaded resources) + fileName String? + mimeType String? + size Int? + bucket String? + objectKey String? + + // External link + externalUrl String? + + sortOrder Int @default(0) + isPublished Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdById String + + // Relations + program Program? @relation(fields: [programId], references: [id], onDelete: SetNull) + createdBy User @relation("ResourceCreatedBy", fields: [createdById], references: [id]) + accessLogs ResourceAccess[] + + @@index([programId]) + @@index([cohortLevel]) + @@index([isPublished]) + @@index([sortOrder]) +} + +model ResourceAccess { + id String @id @default(cuid()) + resourceId String + userId String + accessedAt DateTime @default(now()) + ipAddress String? + + // Relations + resource LearningResource @relation(fields: [resourceId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([resourceId]) + @@index([userId]) + @@index([accessedAt]) +} + +// ============================================================================= +// PARTNER MANAGEMENT (Phase 2) +// ============================================================================= + +model Partner { + id String @id @default(cuid()) + programId String? // null = global partner + name String + description String? @db.Text + website String? + partnerType PartnerType @default(PARTNER) + visibility PartnerVisibility @default(ADMIN_ONLY) + + // Logo file + logoFileName String? + logoBucket String? + logoObjectKey String? + + sortOrder Int @default(0) + isActive Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + program Program? @relation(fields: [programId], references: [id], onDelete: SetNull) + + @@index([programId]) + @@index([partnerType]) + @@index([visibility]) + @@index([isActive]) + @@index([sortOrder]) +} + +// ============================================================================= +// EXPERTISE TAGS (Phase 2B) +// ============================================================================= + +model ExpertiseTag { + id String @id @default(cuid()) + name String @unique + description String? + category String? // "Marine Science", "Technology", "Policy" + color String? // Hex for badge + isActive Boolean @default(true) + sortOrder Int @default(0) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + projectTags ProjectTag[] + + @@index([category]) + @@index([isActive]) + @@index([sortOrder]) +} + +// Project-Tag relationship for AI tagging +model ProjectTag { + id String @id @default(cuid()) + projectId String + tagId String + confidence Float @default(1.0) // AI confidence score 0-1 + source String @default("AI") // "AI" or "MANUAL" + createdAt DateTime @default(now()) + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + tag ExpertiseTag @relation(fields: [tagId], references: [id], onDelete: Cascade) + + @@unique([projectId, tagId]) + @@index([projectId]) + @@index([tagId]) +} + +// ============================================================================= +// LIVE VOTING (Phase 2B) +// ============================================================================= + +model LiveVotingSession { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String? @unique + status String @default("NOT_STARTED") // NOT_STARTED, IN_PROGRESS, PAUSED, COMPLETED + currentProjectIndex Int @default(0) + currentProjectId String? + votingStartedAt DateTime? + votingEndsAt DateTime? + projectOrderJson Json? @db.JsonB // Array of project IDs in presentation order + + // Criteria-based voting + votingMode String @default("simple") // "simple" (1-10) | "criteria" (per-criterion scores) + criteriaJson Json? @db.JsonB // Array of { id, label, description, scale, weight } + + // Audience & presentation settings + allowAudienceVotes Boolean @default(false) + audienceVoteWeight Float @default(0) // 0.0 to 1.0 + tieBreakerMethod String @default("admin_decides") // 'admin_decides' | 'highest_individual' | 'revote' + presentationSettingsJson Json? @db.JsonB + + // Audience voting configuration + audienceVotingMode String @default("disabled") // "disabled" | "per_project" | "per_category" | "favorites" + audienceMaxFavorites Int @default(3) // For "favorites" mode + audienceRequireId Boolean @default(false) // Require email/phone for audience + audienceVotingDuration Int? // Minutes (null = same as jury) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage? @relation(fields: [stageId], references: [id], onDelete: Cascade) + votes LiveVote[] + audienceVoters AudienceVoter[] + + @@index([status]) +} + +model LiveVote { + id String @id @default(cuid()) + sessionId String + projectId String + userId String? // Nullable for audience voters without accounts + score Int // 1-10 (or weighted score for criteria mode) + isAudienceVote Boolean @default(false) + votedAt DateTime @default(now()) + + // Criteria scores (used when votingMode="criteria") + criterionScoresJson Json? @db.JsonB // { [criterionId]: score } - null for simple mode + + // Audience voter link + audienceVoterId String? + + // Relations + session LiveVotingSession @relation(fields: [sessionId], references: [id], onDelete: Cascade) + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + audienceVoter AudienceVoter? @relation(fields: [audienceVoterId], references: [id], onDelete: Cascade) + + @@unique([sessionId, projectId, userId]) + @@unique([sessionId, projectId, audienceVoterId]) + @@index([sessionId]) + @@index([projectId]) + @@index([userId]) + @@index([audienceVoterId]) +} + +model AudienceVoter { + id String @id @default(cuid()) + sessionId String + token String @unique // Unique voting token (UUID) + identifier String? // Optional: email, phone, or name + identifierType String? // "email" | "phone" | "name" | "anonymous" + ipAddress String? + userAgent String? + createdAt DateTime @default(now()) + + // Relations + session LiveVotingSession @relation(fields: [sessionId], references: [id], onDelete: Cascade) + votes LiveVote[] + + @@index([sessionId]) + @@index([token]) +} + +// ============================================================================= +// TEAM MEMBERSHIP +// ============================================================================= + +model TeamMember { + id String @id @default(cuid()) + projectId String + userId String + role TeamMemberRole @default(MEMBER) + title String? // "CEO", "CTO", etc. + joinedAt DateTime @default(now()) + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([projectId, userId]) + @@index([projectId]) + @@index([userId]) + @@index([role]) +} + +// ============================================================================= +// MENTOR ASSIGNMENT +// ============================================================================= + +model MentorAssignment { + id String @id @default(cuid()) + projectId String @unique // One mentor per project + mentorId String // User with MENTOR role or expertise + + // Assignment tracking + method MentorAssignmentMethod @default(MANUAL) + assignedAt DateTime @default(now()) + assignedBy String? // Admin who assigned + + // AI assignment metadata + aiConfidenceScore Float? + expertiseMatchScore Float? + aiReasoning String? @db.Text + + // Tracking + completionStatus String @default("in_progress") // 'in_progress' | 'completed' | 'paused' + lastViewedAt DateTime? + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + mentor User @relation("MentorAssignments", fields: [mentorId], references: [id]) + notes MentorNote[] + milestoneCompletions MentorMilestoneCompletion[] + + @@index([mentorId]) + @@index([method]) +} + +// ============================================================================= +// FILTERING ROUND SYSTEM +// ============================================================================= + +enum FilteringOutcome { + PASSED + FILTERED_OUT + FLAGGED +} + +enum FilteringRuleType { + FIELD_BASED + DOCUMENT_CHECK + AI_SCREENING +} + +model FilteringRule { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + name String + ruleType FilteringRuleType + configJson Json @db.JsonB // Conditions, logic, action per rule type + priority Int @default(0) + isActive Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@index([stageId]) + @@index([priority]) +} + +model FilteringResult { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + projectId String + outcome FilteringOutcome + ruleResultsJson Json? @db.JsonB // Per-rule results + aiScreeningJson Json? @db.JsonB // AI screening details + + // Admin override + overriddenBy String? + overriddenAt DateTime? + overrideReason String? @db.Text + finalOutcome FilteringOutcome? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + overriddenByUser User? @relation("FilteringOverriddenBy", fields: [overriddenBy], references: [id], onDelete: SetNull) + + @@unique([stageId, projectId]) + @@index([stageId]) + @@index([projectId]) + @@index([outcome]) +} + +// Tracks progress of long-running filtering jobs +model FilteringJob { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + status FilteringJobStatus @default(PENDING) + totalProjects Int @default(0) + totalBatches Int @default(0) + currentBatch Int @default(0) + processedCount Int @default(0) + passedCount Int @default(0) + filteredCount Int @default(0) + flaggedCount Int @default(0) + errorMessage String? @db.Text + startedAt DateTime? + completedAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@index([stageId]) + @@index([status]) +} + +enum FilteringJobStatus { + PENDING + RUNNING + COMPLETED + FAILED +} + +// Tracks progress of long-running AI assignment jobs +model AssignmentJob { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + status AssignmentJobStatus @default(PENDING) + totalProjects Int @default(0) + totalBatches Int @default(0) + currentBatch Int @default(0) + processedCount Int @default(0) + suggestionsCount Int @default(0) + suggestionsJson Json? @db.JsonB // Stores the AI-generated suggestions + errorMessage String? @db.Text + startedAt DateTime? + completedAt DateTime? + fallbackUsed Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@index([stageId]) + @@index([status]) +} + +enum AssignmentJobStatus { + PENDING + RUNNING + COMPLETED + FAILED +} + +// Tracks progress of long-running AI tagging jobs +model TaggingJob { + id String @id @default(cuid()) + programId String? // If tagging entire program + roundId String? // If tagging single round + status TaggingJobStatus @default(PENDING) + totalProjects Int @default(0) + processedCount Int @default(0) + taggedCount Int @default(0) + skippedCount Int @default(0) + failedCount Int @default(0) + errorMessage String? @db.Text + errorsJson Json? @db.JsonB // Array of error messages + startedAt DateTime? + completedAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations (optional - can tag by program) + program Program? @relation(fields: [programId], references: [id], onDelete: Cascade) + + @@index([programId]) + @@index([status]) +} + +enum TaggingJobStatus { + PENDING + RUNNING + COMPLETED + FAILED +} + +// ============================================================================= +// SPECIAL AWARDS SYSTEM +// ============================================================================= + +enum AwardScoringMode { + PICK_WINNER + RANKED + SCORED +} + +enum AwardStatus { + DRAFT + NOMINATIONS_OPEN + VOTING_OPEN + CLOSED + ARCHIVED +} + +enum EligibilityMethod { + AUTO + MANUAL +} + +model SpecialAward { + id String @id @default(cuid()) + programId String + name String + description String? @db.Text + status AwardStatus @default(DRAFT) + + // Criteria + criteriaText String? @db.Text // Plain-language criteria for AI + autoTagRulesJson Json? @db.JsonB // Deterministic eligibility rules + useAiEligibility Boolean @default(true) // Whether AI evaluates eligibility + + // Scoring + scoringMode AwardScoringMode @default(PICK_WINNER) + maxRankedPicks Int? // For RANKED mode + + // Voting window + votingStartAt DateTime? + votingEndAt DateTime? + + // Evaluation form (for SCORED mode) + evaluationFormId String? + + // Winner + winnerProjectId String? + winnerOverridden Boolean @default(false) + winnerOverriddenBy String? // FK to User who overrode the winner + + sortOrder Int @default(0) + + // Pipeline track link + trackId String? @unique + track Track? @relation(fields: [trackId], references: [id], onDelete: SetNull) + + // Eligibility job tracking + eligibilityJobStatus String? // PENDING, PROCESSING, COMPLETED, FAILED + eligibilityJobTotal Int? // total projects to process + eligibilityJobDone Int? // completed so far + eligibilityJobError String? @db.Text // error message if failed + eligibilityJobStarted DateTime? // when job started + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + program Program @relation(fields: [programId], references: [id], onDelete: Cascade) + winnerProject Project? @relation("AwardWinner", fields: [winnerProjectId], references: [id], onDelete: SetNull) + overriddenByUser User? @relation("AwardOverriddenBy", fields: [winnerOverriddenBy], references: [id], onDelete: SetNull) + eligibilities AwardEligibility[] + jurors AwardJuror[] + votes AwardVote[] + + @@index([programId]) + @@index([status]) + @@index([sortOrder]) +} + +model AwardEligibility { + id String @id @default(cuid()) + awardId String + projectId String + method EligibilityMethod @default(AUTO) + eligible Boolean @default(false) + aiReasoningJson Json? @db.JsonB + + // Admin override + overriddenBy String? + overriddenAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + award SpecialAward @relation(fields: [awardId], references: [id], onDelete: Cascade) + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + overriddenByUser User? @relation("AwardEligibilityOverriddenBy", fields: [overriddenBy], references: [id], onDelete: SetNull) + + @@unique([awardId, projectId]) + @@index([awardId]) + @@index([projectId]) + @@index([eligible]) + @@index([awardId, eligible]) +} + +model AwardJuror { + id String @id @default(cuid()) + awardId String + userId String + + createdAt DateTime @default(now()) + + // Relations + award SpecialAward @relation(fields: [awardId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([awardId, userId]) + @@index([awardId]) + @@index([userId]) +} + +model AwardVote { + id String @id @default(cuid()) + awardId String + userId String + projectId String + rank Int? // For RANKED mode + votedAt DateTime @default(now()) + + // Relations + award SpecialAward @relation(fields: [awardId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + + @@unique([awardId, userId, projectId]) + @@index([awardId]) + @@index([userId]) + @@index([projectId]) + @@index([awardId, userId]) +} + +// ============================================================================= +// REMINDER LOG (Evaluation Deadline Reminders) +// ============================================================================= + +model ReminderLog { + id String @id @default(cuid()) + roundId String? // Legacy — kept for historical data + stageId String + userId String + type String // "3_DAYS", "24H", "1H" + sentAt DateTime @default(now()) + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([stageId, userId, type]) + @@index([stageId]) +} + +// ============================================================================= +// CONFLICT OF INTEREST +// ============================================================================= + +model ConflictOfInterest { + id String @id @default(cuid()) + assignmentId String @unique + userId String + projectId String + roundId String? // Legacy — kept for historical data + hasConflict Boolean @default(false) + conflictType String? // "financial", "personal", "organizational", "other" + description String? @db.Text + declaredAt DateTime @default(now()) + + // Admin review + reviewedById String? + reviewedAt DateTime? + reviewAction String? // "cleared", "reassigned", "noted" + + // Relations + assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id]) + reviewedBy User? @relation("COIReviewedBy", fields: [reviewedById], references: [id]) + + @@index([userId]) + @@index([hasConflict]) +} + +// ============================================================================= +// AI EVALUATION SUMMARY +// ============================================================================= + +model EvaluationSummary { + id String @id @default(cuid()) + projectId String + roundId String? // Legacy — kept for historical data + stageId String + summaryJson Json @db.JsonB + generatedAt DateTime @default(now()) + generatedById String + model String + tokensUsed Int + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + generatedBy User @relation("EvaluationSummaryGeneratedBy", fields: [generatedById], references: [id]) + + @@unique([projectId, stageId]) + @@index([stageId]) +} + +// ============================================================================= +// PROJECT STATUS HISTORY +// ============================================================================= + +model ProjectStatusHistory { + id String @id @default(cuid()) + projectId String + status ProjectStatus + changedAt DateTime @default(now()) + changedBy String? + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + + @@index([projectId, changedAt]) +} + +// ============================================================================= +// MENTOR MESSAGES +// ============================================================================= + +model MentorMessage { + id String @id @default(cuid()) + projectId String + senderId String + message String @db.Text + isRead Boolean @default(false) + createdAt DateTime @default(now()) + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + sender User @relation("MentorMessageSender", fields: [senderId], references: [id]) + + @@index([projectId, createdAt]) +} + +// RoundTemplate model RETIRED in Phase 6 — replaced by WizardTemplate for pipelines. + +// ============================================================================= +// MENTOR NOTES & MILESTONES +// ============================================================================= + +model MentorNote { + id String @id @default(cuid()) + mentorAssignmentId String + authorId String + content String @db.Text + isVisibleToAdmin Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + mentorAssignment MentorAssignment @relation(fields: [mentorAssignmentId], references: [id], onDelete: Cascade) + author User @relation("MentorNoteAuthor", fields: [authorId], references: [id]) + + @@index([mentorAssignmentId]) + @@index([authorId]) +} + +model MentorMilestone { + id String @id @default(cuid()) + programId String + name String + description String? @db.Text + isRequired Boolean @default(false) + deadlineOffsetDays Int? + sortOrder Int @default(0) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + program Program @relation(fields: [programId], references: [id], onDelete: Cascade) + completions MentorMilestoneCompletion[] + + @@index([programId]) + @@index([sortOrder]) +} + +model MentorMilestoneCompletion { + id String @id @default(cuid()) + milestoneId String + mentorAssignmentId String + completedById String + completedAt DateTime @default(now()) + + // Relations + milestone MentorMilestone @relation(fields: [milestoneId], references: [id], onDelete: Cascade) + mentorAssignment MentorAssignment @relation(fields: [mentorAssignmentId], references: [id], onDelete: Cascade) + completedBy User @relation("MilestoneCompletedBy", fields: [completedById], references: [id]) + + @@unique([milestoneId, mentorAssignmentId]) + @@index([mentorAssignmentId]) + @@index([completedById]) +} + +// ============================================================================= +// EVALUATION DISCUSSIONS +// ============================================================================= + +model EvaluationDiscussion { + id String @id @default(cuid()) + projectId String + roundId String? // Legacy — kept for historical data + stageId String + status String @default("open") // 'open' | 'closed' + createdAt DateTime @default(now()) + closedAt DateTime? + closedById String? + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + closedBy User? @relation("DiscussionClosedBy", fields: [closedById], references: [id], onDelete: SetNull) + comments DiscussionComment[] + + @@unique([projectId, stageId]) + @@index([stageId]) + @@index([closedById]) +} + +model DiscussionComment { + id String @id @default(cuid()) + discussionId String + userId String + content String @db.Text + + createdAt DateTime @default(now()) + + // Relations + discussion EvaluationDiscussion @relation(fields: [discussionId], references: [id], onDelete: Cascade) + user User @relation("DiscussionCommentAuthor", fields: [userId], references: [id]) + + @@index([discussionId]) + @@index([userId]) +} + +// ============================================================================= +// MESSAGING SYSTEM +// ============================================================================= + +model Message { + id String @id @default(cuid()) + senderId String + recipientType String // 'USER', 'ROLE', 'ROUND_JURY', 'PROGRAM_TEAM', 'ALL' + recipientFilter Json? @db.JsonB + roundId String? + stageId String? + templateId String? + subject String + body String @db.Text + deliveryChannels String[] + + scheduledAt DateTime? + sentAt DateTime? + metadata Json? @db.JsonB + + createdAt DateTime @default(now()) + + // Relations + sender User @relation("MessageSender", fields: [senderId], references: [id]) + stage Stage? @relation(fields: [stageId], references: [id], onDelete: SetNull) + template MessageTemplate? @relation(fields: [templateId], references: [id], onDelete: SetNull) + recipients MessageRecipient[] + + @@index([senderId]) + @@index([stageId]) + @@index([sentAt]) +} + +model MessageRecipient { + id String @id @default(cuid()) + messageId String + userId String + channel String // 'EMAIL', 'IN_APP', etc. + isRead Boolean @default(false) + readAt DateTime? + deliveredAt DateTime? + + // Relations + message Message @relation(fields: [messageId], references: [id], onDelete: Cascade) + user User @relation("MessageRecipient", fields: [userId], references: [id], onDelete: Cascade) + + @@unique([messageId, userId, channel]) + @@index([userId]) +} + +model MessageTemplate { + id String @id @default(cuid()) + name String + category String // 'SYSTEM', 'EVALUATION', 'ASSIGNMENT' + subject String + body String @db.Text + variables Json? @db.JsonB + isActive Boolean @default(true) + createdBy String + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + creator User @relation("MessageTemplateCreator", fields: [createdBy], references: [id]) + messages Message[] + + @@index([category]) + @@index([isActive]) +} + +// ============================================================================= +// WEBHOOKS +// ============================================================================= + +model Webhook { + id String @id @default(cuid()) + name String + url String + secret String + events String[] + headers Json? @db.JsonB + maxRetries Int @default(3) + isActive Boolean @default(true) + createdById String + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + createdBy User @relation("WebhookCreator", fields: [createdById], references: [id]) + deliveries WebhookDelivery[] + + @@index([isActive]) + @@index([createdById]) +} + +model WebhookDelivery { + id String @id @default(cuid()) + webhookId String + event String + payload Json @db.JsonB + status String @default("PENDING") // 'PENDING', 'DELIVERED', 'FAILED' + responseStatus Int? + responseBody String? @db.Text + attempts Int @default(0) + lastAttemptAt DateTime? + + createdAt DateTime @default(now()) + + // Relations + webhook Webhook @relation(fields: [webhookId], references: [id], onDelete: Cascade) + + @@index([webhookId]) + @@index([status]) + @@index([event]) +} + +// ============================================================================= +// DIGEST LOGS +// ============================================================================= + +model DigestLog { + id String @id @default(cuid()) + userId String + digestType String // 'daily' | 'weekly' + contentJson Json @db.JsonB + sentAt DateTime @default(now()) + + // Relations + user User @relation("DigestLog", fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) + @@index([sentAt]) +} + +// ============================================================================= +// PIPELINE / TRACK / STAGE ENGINE +// ============================================================================= + +model Pipeline { + id String @id @default(cuid()) + programId String + name String + slug String @unique + status String @default("DRAFT") // DRAFT, ACTIVE, ARCHIVED + settingsJson Json? @db.JsonB + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + program Program @relation(fields: [programId], references: [id], onDelete: Cascade) + tracks Track[] + routingRules RoutingRule[] + + @@index([programId]) + @@index([status]) +} + +model Track { + id String @id @default(cuid()) + pipelineId String + name String + slug String + kind TrackKind @default(MAIN) + routingMode RoutingMode? + decisionMode DecisionMode? + sortOrder Int @default(0) + settingsJson Json? @db.JsonB + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) + stages Stage[] + projectStageStates ProjectStageState[] + specialAward SpecialAward? + routingRulesAsSource RoutingRule[] @relation("RoutingSourceTrack") + routingRulesAsDestination RoutingRule[] @relation("RoutingDestinationTrack") + + @@unique([pipelineId, slug]) + @@unique([pipelineId, sortOrder]) + @@index([pipelineId]) + @@index([kind]) +} + +model Stage { + id String @id @default(cuid()) + trackId String + stageType StageType + name String + slug String + status StageStatus @default(STAGE_DRAFT) + sortOrder Int @default(0) + configJson Json? @db.JsonB + windowOpenAt DateTime? + windowCloseAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) + projectStageStates ProjectStageState[] + transitionsFrom StageTransition[] @relation("TransitionFrom") + transitionsTo StageTransition[] @relation("TransitionTo") + cohorts Cohort[] + liveCursor LiveProgressCursor? + liveVotingSession LiveVotingSession? + + // Reverse relations from existing models + evaluationForms EvaluationForm[] + assignments Assignment[] + fileRequirements FileRequirement[] + filteringRules FilteringRule[] + filteringResults FilteringResult[] + filteringJobs FilteringJob[] + assignmentJobs AssignmentJob[] + gracePeriods GracePeriod[] + reminderLogs ReminderLog[] + evaluationSummaries EvaluationSummary[] + evaluationDiscussions EvaluationDiscussion[] + messages Message[] + + @@unique([trackId, slug]) + @@unique([trackId, sortOrder]) + @@index([trackId]) + @@index([stageType]) + @@index([status]) +} + +model StageTransition { + id String @id @default(cuid()) + fromStageId String + toStageId String + isDefault Boolean @default(false) + guardJson Json? @db.JsonB // Conditions that must be met + + createdAt DateTime @default(now()) + + // Relations + fromStage Stage @relation("TransitionFrom", fields: [fromStageId], references: [id], onDelete: Cascade) + toStage Stage @relation("TransitionTo", fields: [toStageId], references: [id], onDelete: Cascade) + + @@unique([fromStageId, toStageId]) + @@index([fromStageId]) + @@index([toStageId]) +} + +model ProjectStageState { + id String @id @default(cuid()) + projectId String + trackId String + stageId String + state ProjectStageStateValue @default(PENDING) + enteredAt DateTime @default(now()) + exitedAt DateTime? + metadataJson Json? @db.JsonB + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@unique([projectId, trackId, stageId]) + @@index([projectId]) + @@index([trackId]) + @@index([stageId]) + @@index([state]) + @@index([projectId, trackId]) +} + +model RoutingRule { + id String @id @default(cuid()) + pipelineId String + name String + scope String @default("global") // global, track, stage + sourceTrackId String? + destinationTrackId String + destinationStageId String? + predicateJson Json @db.JsonB // { field, operator, value } or compound + priority Int @default(0) + isActive Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade) + sourceTrack Track? @relation("RoutingSourceTrack", fields: [sourceTrackId], references: [id], onDelete: SetNull) + destinationTrack Track @relation("RoutingDestinationTrack", fields: [destinationTrackId], references: [id], onDelete: Cascade) + + @@index([pipelineId]) + @@index([priority]) + @@index([isActive]) +} + +model Cohort { + id String @id @default(cuid()) + stageId String + name String + votingMode String @default("simple") // simple, criteria, ranked + isOpen Boolean @default(false) + windowOpenAt DateTime? + windowCloseAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + projects CohortProject[] + + @@index([stageId]) + @@index([isOpen]) +} + +model CohortProject { + id String @id @default(cuid()) + cohortId String + projectId String + sortOrder Int @default(0) + + createdAt DateTime @default(now()) + + // Relations + cohort Cohort @relation(fields: [cohortId], references: [id], onDelete: Cascade) + project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) + + @@unique([cohortId, projectId]) + @@index([cohortId]) + @@index([projectId]) + @@index([sortOrder]) +} + +model LiveProgressCursor { + id String @id @default(cuid()) + stageId String @unique + sessionId String @unique @default(cuid()) + activeProjectId String? + activeOrderIndex Int @default(0) + isPaused Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + stage Stage @relation(fields: [stageId], references: [id], onDelete: Cascade) + + @@index([sessionId]) +} + +model OverrideAction { + id String @id @default(cuid()) + entityType String // ProjectStageState, FilteringResult, AwardEligibility, etc. + entityId String + previousValue Json? @db.JsonB + newValueJson Json @db.JsonB + reasonCode OverrideReasonCode + reasonText String? @db.Text + actorId String + + createdAt DateTime @default(now()) + + @@index([entityType, entityId]) + @@index([actorId]) + @@index([reasonCode]) + @@index([createdAt]) +} + +model DecisionAuditLog { + id String @id @default(cuid()) + eventType String // stage.transitioned, routing.executed, filtering.completed, etc. + entityType String + entityId String + actorId String? + detailsJson Json? @db.JsonB + snapshotJson Json? @db.JsonB // State at time of decision + + createdAt DateTime @default(now()) + + @@index([eventType]) + @@index([entityType, entityId]) + @@index([actorId]) + @@index([createdAt]) +} + +model NotificationPolicy { + id String @id @default(cuid()) + eventType String @unique // stage.transitioned, filtering.completed, etc. + channel String @default("EMAIL") // EMAIL, IN_APP, BOTH, NONE + templateId String? // Optional reference to MessageTemplate + isActive Boolean @default(true) + configJson Json? @db.JsonB // Additional config (delay, batch, etc.) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([eventType]) + @@index([isActive]) +} diff --git a/prisma/seed.ts b/prisma/seed.ts index 600344f..99b81bd 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,938 +1,1137 @@ -import { - PrismaClient, - UserRole, - UserStatus, - ProgramStatus, - SettingType, - SettingCategory, - CompetitionCategory, - OceanIssue, - StageType, - TrackKind, - RoutingMode, - DecisionMode, - StageStatus, - ProjectStageStateValue, - ProjectStatus, - SubmissionSource, -} from '@prisma/client' -import bcrypt from 'bcryptjs' -import { readFileSync } from 'fs' -import { parse } from 'csv-parse/sync' -import { join, dirname } from 'path' -import { fileURLToPath } from 'url' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - -const prisma = new PrismaClient() - -// ============================================================================= -// CSV Column Mapping Helpers -// ============================================================================= - -const categoryMap: Record = { - 'the « Start-ups » category': CompetitionCategory.STARTUP, - 'the « Business concepts » category': CompetitionCategory.BUSINESS_CONCEPT, -} - -const issueMap: Record = { - 'Reduction of pollution': OceanIssue.POLLUTION_REDUCTION, - 'Mitigation of climate change': OceanIssue.CLIMATE_MITIGATION, - 'Technology & innovations': OceanIssue.TECHNOLOGY_INNOVATION, - 'Sustainable shipping': OceanIssue.SUSTAINABLE_SHIPPING, - 'Blue Carbon': OceanIssue.BLUE_CARBON, - 'Restoration of marine': OceanIssue.HABITAT_RESTORATION, - 'Capacity building': OceanIssue.COMMUNITY_CAPACITY, - 'Sustainable fishing': OceanIssue.SUSTAINABLE_FISHING, - 'Consumer awareness': OceanIssue.CONSUMER_AWARENESS, - 'Mitigation of ocean acidification': OceanIssue.OCEAN_ACIDIFICATION, - 'Other': OceanIssue.OTHER, -} - -function mapCategory(raw: string | undefined): CompetitionCategory | null { - if (!raw) return null - const trimmed = raw.trim() - for (const [prefix, value] of Object.entries(categoryMap)) { - if (trimmed.startsWith(prefix)) return value - } - return null -} - -function mapIssue(raw: string | undefined): OceanIssue | null { - if (!raw) return null - const trimmed = raw.trim() - for (const [prefix, value] of Object.entries(issueMap)) { - if (trimmed.startsWith(prefix)) return value - } - return OceanIssue.OTHER -} - -function parseFoundedDate(raw: string | undefined): Date | null { - if (!raw) return null - const trimmed = raw.trim() - if (!trimmed) return null - const d = new Date(trimmed) - return isNaN(d.getTime()) ? null : d -} - -function isValidEntry(row: Record): boolean { - const status = (row['Application status'] || '').trim().toLowerCase() - if (status === 'ignore' || status === 'doublon') return false - - const name = (row['Full name'] || '').trim() - if (name.length <= 2) return false // skip test entries - - const email = (row['E-mail'] || '').trim() - if (!email || !email.includes('@')) return false - - return true -} - -// ============================================================================= -// Main Seed Function -// ============================================================================= - -async function main() { - console.log('🌱 Seeding database with MOPC 2026 real data...\n') - - // ========================================================================== - // 1. System Settings - // ========================================================================== - console.log('📋 Creating system settings...') - - const settings = [ - { key: 'ai_enabled', value: 'false', type: SettingType.BOOLEAN, category: SettingCategory.AI, description: 'Enable AI-powered jury assignment suggestions' }, - { key: 'ai_provider', value: 'openai', type: SettingType.STRING, category: SettingCategory.AI, description: 'AI provider for smart assignment (openai)' }, - { key: 'ai_model', value: 'gpt-4o', type: SettingType.STRING, category: SettingCategory.AI, description: 'OpenAI model to use for suggestions' }, - { key: 'ai_send_descriptions', value: 'false', type: SettingType.BOOLEAN, category: SettingCategory.AI, description: 'Send anonymized project descriptions to AI' }, - { key: 'platform_name', value: 'Monaco Ocean Protection Challenge', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Platform display name' }, - { key: 'primary_color', value: '#de0f1e', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Primary brand color (hex)' }, - { key: 'secondary_color', value: '#053d57', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Secondary brand color (hex)' }, - { key: 'accent_color', value: '#557f8c', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Accent color (hex)' }, - { key: 'session_duration_hours', value: '24', type: SettingType.NUMBER, category: SettingCategory.SECURITY, description: 'Session duration in hours' }, - { key: 'magic_link_expiry_minutes', value: '15', type: SettingType.NUMBER, category: SettingCategory.SECURITY, description: 'Magic link expiry time in minutes' }, - { key: 'rate_limit_requests_per_minute', value: '60', type: SettingType.NUMBER, category: SettingCategory.SECURITY, description: 'API rate limit per minute' }, - { key: 'storage_provider', value: 's3', type: SettingType.STRING, category: SettingCategory.STORAGE, description: 'Storage provider: s3 (MinIO) or local (filesystem)' }, - { key: 'local_storage_path', value: './uploads', type: SettingType.STRING, category: SettingCategory.STORAGE, description: 'Base path for local file storage' }, - { key: 'max_file_size_mb', value: '500', type: SettingType.NUMBER, category: SettingCategory.STORAGE, description: 'Maximum file upload size in MB' }, - { key: 'avatar_max_size_mb', value: '5', type: SettingType.NUMBER, category: SettingCategory.STORAGE, description: 'Maximum avatar image size in MB' }, - { key: 'allowed_file_types', value: JSON.stringify(['application/pdf', 'video/mp4', 'video/quicktime', 'image/png', 'image/jpeg']), type: SettingType.JSON, category: SettingCategory.STORAGE, description: 'Allowed MIME types for file uploads' }, - { key: 'allowed_image_types', value: JSON.stringify(['image/png', 'image/jpeg', 'image/webp']), type: SettingType.JSON, category: SettingCategory.STORAGE, description: 'Allowed MIME types for avatar/logo uploads' }, - { key: 'default_timezone', value: 'Europe/Monaco', type: SettingType.STRING, category: SettingCategory.DEFAULTS, description: 'Default timezone for date displays' }, - { key: 'default_page_size', value: '20', type: SettingType.NUMBER, category: SettingCategory.DEFAULTS, description: 'Default pagination size' }, - { key: 'autosave_interval_seconds', value: '30', type: SettingType.NUMBER, category: SettingCategory.DEFAULTS, description: 'Autosave interval for evaluation forms' }, - { key: 'whatsapp_enabled', value: 'false', type: SettingType.BOOLEAN, category: SettingCategory.WHATSAPP, description: 'Enable WhatsApp notifications' }, - { key: 'whatsapp_provider', value: 'META', type: SettingType.STRING, category: SettingCategory.WHATSAPP, description: 'WhatsApp provider (META or TWILIO)' }, - { key: 'openai_api_key', value: '', type: SettingType.SECRET, category: SettingCategory.AI, description: 'OpenAI API Key for AI-powered features', isSecret: true }, - ] - - for (const setting of settings) { - await prisma.systemSettings.upsert({ - where: { key: setting.key }, - update: {}, - create: setting, - }) - } - console.log(` Created ${settings.length} settings`) - - // ========================================================================== - // 1b. Expertise Tags - // ========================================================================== - console.log('\n🏷️ Creating expertise tags...') - - const expertiseTags = [ - // Pollution & Waste — aligned with MOPC OceanIssue: POLLUTION_REDUCTION - { name: 'Plastic Pollution Solutions', description: 'Technologies and methods to reduce marine plastic debris, microplastics, and single-use packaging', category: 'Pollution & Waste', color: '#dc2626', sortOrder: 0 }, - { name: 'Oil Spill Prevention & Response', description: 'Tools and systems for preventing and cleaning up oil and chemical spills at sea', category: 'Pollution & Waste', color: '#dc2626', sortOrder: 1 }, - { name: 'Wastewater & Runoff Treatment', description: 'Filtering agricultural runoff, industrial discharge, and urban wastewater before it reaches the ocean', category: 'Pollution & Waste', color: '#dc2626', sortOrder: 2 }, - { name: 'Marine Debris Cleanup', description: 'Ocean and coastal cleanup technologies, collection vessels, and waste recovery systems', category: 'Pollution & Waste', color: '#dc2626', sortOrder: 3 }, - { name: 'Circular Economy & Recycling', description: 'Upcycling ocean waste, circular packaging, and zero-waste supply chains for coastal industries', category: 'Pollution & Waste', color: '#dc2626', sortOrder: 4 }, - - // Climate & Carbon — aligned with MOPC OceanIssue: CLIMATE_MITIGATION, BLUE_CARBON, OCEAN_ACIDIFICATION - { name: 'Blue Carbon Ecosystems', description: 'Conservation and restoration of mangroves, seagrass beds, and salt marshes for carbon sequestration', category: 'Climate & Carbon', color: '#0284c7', sortOrder: 10 }, - { name: 'Ocean Acidification Mitigation', description: 'Solutions addressing declining ocean pH, alkalinity enhancement, and impacts on calcifying organisms', category: 'Climate & Carbon', color: '#0284c7', sortOrder: 11 }, - { name: 'Climate Adaptation for Coasts', description: 'Nature-based solutions and infrastructure protecting coastal communities from rising seas and storms', category: 'Climate & Carbon', color: '#0284c7', sortOrder: 12 }, - { name: 'Renewable Ocean Energy', description: 'Wave, tidal, offshore wind, and ocean thermal energy conversion technologies', category: 'Climate & Carbon', color: '#0284c7', sortOrder: 13 }, - { name: 'Carbon Capture & Sequestration', description: 'Marine-based carbon dioxide removal technologies including algae, mineralization, and ocean fertilization', category: 'Climate & Carbon', color: '#0284c7', sortOrder: 14 }, - - // Sustainable Seafood & Aquaculture — aligned with MOPC OceanIssue: SUSTAINABLE_FISHING - { name: 'Sustainable Aquaculture', description: 'Low-impact fish and shellfish farming, alternative feeds (e.g., seaweed, insect-based), and recirculating systems', category: 'Seafood & Aquaculture', color: '#059669', sortOrder: 20 }, - { name: 'Overfishing Prevention', description: 'Monitoring, traceability, and enforcement tools to combat illegal and unsustainable fishing', category: 'Seafood & Aquaculture', color: '#059669', sortOrder: 21 }, - { name: 'Seafood Traceability & Supply Chain', description: 'Blockchain, IoT, and certification systems ensuring sustainable and ethical seafood sourcing', category: 'Seafood & Aquaculture', color: '#059669', sortOrder: 22 }, - { name: 'Algae & Seaweed Innovation', description: 'Cultivation, processing, and applications of macroalgae and microalgae for food, feed, biomaterials, and biofuels', category: 'Seafood & Aquaculture', color: '#059669', sortOrder: 23 }, - { name: 'Small-Scale Fisheries & Hatcheries', description: 'Support for artisanal fishing communities, small-scale hatchery technology, and local fisheries management', category: 'Seafood & Aquaculture', color: '#059669', sortOrder: 24 }, - - // Marine Biodiversity & Habitat — aligned with MOPC OceanIssue: HABITAT_RESTORATION - { name: 'Coral Reef Restoration', description: 'Technologies for coral propagation, transplantation, reef structure creation, and resilience monitoring', category: 'Biodiversity & Habitat', color: '#7c3aed', sortOrder: 30 }, - { name: 'Marine Protected Areas', description: 'Design, monitoring, and management of MPAs and marine spatial planning', category: 'Biodiversity & Habitat', color: '#7c3aed', sortOrder: 31 }, - { name: 'Endangered Species Conservation', description: 'Protection programs for marine mammals, sea turtles, sharks, and other threatened species', category: 'Biodiversity & Habitat', color: '#7c3aed', sortOrder: 32 }, - { name: 'Coastal & Wetland Restoration', description: 'Restoring marshes, estuaries, dunes, and other coastal habitats for biodiversity and resilience', category: 'Biodiversity & Habitat', color: '#7c3aed', sortOrder: 33 }, - { name: 'Invasive Species Management', description: 'Detection, monitoring, and control of invasive marine organisms and ballast water management', category: 'Biodiversity & Habitat', color: '#7c3aed', sortOrder: 34 }, - - // Ocean Technology & Innovation — aligned with MOPC OceanIssue: TECHNOLOGY_INNOVATION - { name: 'Ocean Monitoring & Sensors', description: 'IoT sensors, buoys, and autonomous platforms for real-time ocean data collection', category: 'Ocean Technology', color: '#7c3aed', sortOrder: 40 }, - { name: 'Underwater Robotics & AUVs', description: 'Autonomous underwater vehicles, ROVs, and marine drones for exploration and monitoring', category: 'Ocean Technology', color: '#7c3aed', sortOrder: 41 }, - { name: 'AI & Data Analytics for Oceans', description: 'Machine learning and big data applications for ocean health prediction, species identification, and pattern detection', category: 'Ocean Technology', color: '#7c3aed', sortOrder: 42 }, - { name: 'Satellite & Remote Sensing', description: 'Earth observation, hyperspectral imaging, and satellite-based ocean monitoring', category: 'Ocean Technology', color: '#7c3aed', sortOrder: 43 }, - { name: 'Marine Biotechnology', description: 'Bio-inspired materials, biomimicry, marine-derived pharmaceuticals, and bioplastics from ocean organisms', category: 'Ocean Technology', color: '#7c3aed', sortOrder: 44 }, - { name: 'Desalination & Water Purification', description: 'Energy-efficient desalination, membrane technology, and portable water purification systems', category: 'Ocean Technology', color: '#7c3aed', sortOrder: 45 }, - - // Sustainable Shipping & Ports — aligned with MOPC OceanIssue: SUSTAINABLE_SHIPPING - { name: 'Green Shipping & Fuels', description: 'Alternative marine fuels (hydrogen, ammonia, LNG), electric vessels, and emission reduction', category: 'Shipping & Ports', color: '#053d57', sortOrder: 50 }, - { name: 'Port Sustainability', description: 'Shore power, smart port logistics, and environmental impact reduction in harbors', category: 'Shipping & Ports', color: '#053d57', sortOrder: 51 }, - { name: 'Anti-fouling & Hull Technology', description: 'Non-toxic anti-fouling coatings, hull cleaning, and drag reduction for vessels', category: 'Shipping & Ports', color: '#053d57', sortOrder: 52 }, - { name: 'Underwater Noise Reduction', description: 'Technologies and practices to reduce vessel noise impact on marine life', category: 'Shipping & Ports', color: '#053d57', sortOrder: 53 }, - - // Community & Education — aligned with MOPC OceanIssue: COMMUNITY_CAPACITY, CONSUMER_AWARENESS - { name: 'Coastal Community Development', description: 'Livelihood programs, capacity building, and economic alternatives for fishing-dependent communities', category: 'Community & Education', color: '#ea580c', sortOrder: 60 }, - { name: 'Ocean Literacy & Education', description: 'Educational programs, curricula, and outreach to increase public ocean awareness', category: 'Community & Education', color: '#ea580c', sortOrder: 61 }, - { name: 'Citizen Science & Engagement', description: 'Public participation platforms for ocean data collection, species reporting, and conservation', category: 'Community & Education', color: '#ea580c', sortOrder: 62 }, - { name: 'Ecotourism & Responsible Tourism', description: 'Sustainable marine tourism models that support conservation and local economies', category: 'Community & Education', color: '#ea580c', sortOrder: 63 }, - { name: 'Consumer Awareness & Labeling', description: 'Eco-labels, consumer apps, and awareness campaigns for sustainable ocean products', category: 'Community & Education', color: '#ea580c', sortOrder: 64 }, - - // Business & Investment — aligned with MOPC competition structure (Startup / Business Concept) - { name: 'Blue Economy & Finance', description: 'Sustainable ocean economy models, blue bonds, and financial mechanisms for ocean projects', category: 'Business & Investment', color: '#557f8c', sortOrder: 70 }, - { name: 'Impact Investing & ESG', description: 'Ocean-focused impact funds, ESG frameworks, and blended finance for marine conservation', category: 'Business & Investment', color: '#557f8c', sortOrder: 71 }, - { name: 'Startup Acceleration', description: 'Scaling early-stage ocean startups, go-to-market strategy, and business model validation', category: 'Business & Investment', color: '#557f8c', sortOrder: 72 }, - { name: 'Ocean Policy & Governance', description: 'International maritime law, regulatory frameworks, and ocean governance institutions', category: 'Business & Investment', color: '#557f8c', sortOrder: 73 }, - { name: 'Mediterranean & Small Seas', description: 'Conservation and sustainable development specific to enclosed and semi-enclosed seas like the Mediterranean', category: 'Business & Investment', color: '#557f8c', sortOrder: 74 }, - ] - - for (const tag of expertiseTags) { - await prisma.expertiseTag.upsert({ - where: { name: tag.name }, - update: {}, - create: { - name: tag.name, - description: tag.description, - category: tag.category, - color: tag.color, - sortOrder: tag.sortOrder, - isActive: true, - }, - }) - } - console.log(` Created ${expertiseTags.length} expertise tags across ${new Set(expertiseTags.map(t => t.category)).size} categories`) - - // ========================================================================== - // 2. Admin/Staff Users - // ========================================================================== - console.log('\n👤 Creating admin & staff users...') - - const staffAccounts = [ - { email: 'matt@monaco-opc.com', name: 'Matt', role: UserRole.SUPER_ADMIN, password: '195260Mp!' }, - { email: 'admin@monaco-opc.com', name: 'Admin', role: UserRole.PROGRAM_ADMIN, password: 'Admin123!' }, - { email: 'awards@monaco-opc.com', name: 'Award Director', role: UserRole.AWARD_MASTER, password: 'Awards123!' }, - ] - - const staffUsers: Record = {} - for (const account of staffAccounts) { - const passwordHash = await bcrypt.hash(account.password, 12) - const user = await prisma.user.upsert({ - where: { email: account.email }, - update: { passwordHash }, - create: { - email: account.email, - name: account.name, - role: account.role, - status: UserStatus.ACTIVE, - passwordHash, - mustSetPassword: false, - passwordSetAt: new Date(), - onboardingCompletedAt: new Date(), - }, - }) - staffUsers[account.email] = user.id - console.log(` ✓ ${account.role}: ${account.email}`) - } - - // ========================================================================== - // 3. Jury Members (8 fictional) - // ========================================================================== - console.log('\n⚖️ Creating jury members...') - - const juryMembers = [ - { email: 'jury1@monaco-opc.com', name: 'Dr. Sophie Laurent', country: 'France', tags: ['marine-biology', 'coral-restoration', 'biodiversity'] }, - { email: 'jury2@monaco-opc.com', name: 'Prof. Marco Bianchi', country: 'Italy', tags: ['ocean-engineering', 'renewable-energy', 'desalination'] }, - { email: 'jury3@monaco-opc.com', name: 'Dr. Aisha Patel', country: 'United Kingdom', tags: ['sustainability', 'circular-economy', 'waste-management'] }, - { email: 'jury4@monaco-opc.com', name: 'Dr. Kenji Tanaka', country: 'Japan', tags: ['aquaculture', 'sustainable-fishing', 'marine-technology'] }, - { email: 'jury5@monaco-opc.com', name: 'Prof. Elena Volkov', country: 'Germany', tags: ['climate-science', 'ocean-acidification', 'blue-carbon'] }, - { email: 'jury6@monaco-opc.com', name: 'Dr. Amara Diallo', country: 'Senegal', tags: ['community-development', 'capacity-building', 'coastal-management'] }, - { email: 'jury7@monaco-opc.com', name: 'Dr. Carlos Rivera', country: 'Spain', tags: ['blue-economy', 'maritime-policy', 'shipping'] }, - { email: 'jury8@monaco-opc.com', name: 'Prof. Lin Wei', country: 'Singapore', tags: ['marine-biotech', 'pollution-monitoring', 'AI-ocean'] }, - ] - - const juryUserIds: string[] = [] - for (const j of juryMembers) { - const user = await prisma.user.upsert({ - where: { email: j.email }, - update: {}, - create: { - email: j.email, - name: j.name, - role: UserRole.JURY_MEMBER, - status: UserStatus.NONE, - country: j.country, - expertiseTags: j.tags, - bio: `Expert in ${j.tags.join(', ')}`, - }, - }) - juryUserIds.push(user.id) - console.log(` ✓ Jury: ${j.name} (${j.country})`) - } - - // ========================================================================== - // 4. Mentors (3 fictional) - // ========================================================================== - console.log('\n🧑‍🏫 Creating mentors...') - - const mentors = [ - { email: 'mentor1@monaco-opc.com', name: 'Marie Dubois', country: 'Monaco', tags: ['startup-coaching', 'ocean-conservation'] }, - { email: 'mentor2@monaco-opc.com', name: 'James Cooper', country: 'United States', tags: ['venture-capital', 'cleantech'] }, - { email: 'mentor3@monaco-opc.com', name: 'Fatima Al-Rashid', country: 'UAE', tags: ['impact-investing', 'sustainability-strategy'] }, - ] - - for (const m of mentors) { - await prisma.user.upsert({ - where: { email: m.email }, - update: {}, - create: { - email: m.email, - name: m.name, - role: UserRole.MENTOR, - status: UserStatus.NONE, - country: m.country, - expertiseTags: m.tags, - }, - }) - console.log(` ✓ Mentor: ${m.name}`) - } - - // ========================================================================== - // 5. Observers (2 fictional) - // ========================================================================== - console.log('\n👁️ Creating observers...') - - const observers = [ - { email: 'observer1@monaco-opc.com', name: 'Pierre Martin', country: 'Monaco' }, - { email: 'observer2@monaco-opc.com', name: 'Sarah Chen', country: 'Canada' }, - ] - - for (const o of observers) { - await prisma.user.upsert({ - where: { email: o.email }, - update: {}, - create: { - email: o.email, - name: o.name, - role: UserRole.OBSERVER, - status: UserStatus.NONE, - country: o.country, - }, - }) - console.log(` ✓ Observer: ${o.name}`) - } - - // ========================================================================== - // 6. Program - // ========================================================================== - console.log('\n📁 Creating program...') - - const program = await prisma.program.upsert({ - where: { name_year: { name: 'Monaco Ocean Protection Challenge', year: 2026 } }, - update: {}, - create: { - name: 'Monaco Ocean Protection Challenge', - year: 2026, - status: ProgramStatus.ACTIVE, - description: 'Annual ocean conservation startup competition supporting innovative solutions for ocean protection.', - }, - }) - console.log(` ✓ Program: ${program.name} ${program.year}`) - - // ========================================================================== - // 7. Pipeline - // ========================================================================== - console.log('\n🔗 Creating pipeline...') - - const pipeline = await prisma.pipeline.create({ - data: { - programId: program.id, - name: 'MOPC 2026 Main Pipeline', - slug: 'mopc-2026', - status: 'ACTIVE', - settingsJson: { - description: 'Main pipeline for MOPC 2026 competition', - allowParallelTracks: true, - autoAdvanceOnClose: false, - }, - }, - }) - console.log(` ✓ Pipeline: ${pipeline.name}`) - - // ========================================================================== - // 8. Tracks (4) - // ========================================================================== - console.log('\n🛤️ Creating tracks...') - - const mainTrack = await prisma.track.create({ - data: { - pipelineId: pipeline.id, - name: 'Main Competition', - slug: 'main', - kind: TrackKind.MAIN, - sortOrder: 0, - settingsJson: { description: 'Primary competition track for all applicants' }, - }, - }) - - const innovationTrack = await prisma.track.create({ - data: { - pipelineId: pipeline.id, - name: 'Ocean Innovation Award', - slug: 'innovation-award', - kind: TrackKind.AWARD, - routingMode: RoutingMode.PARALLEL, - decisionMode: DecisionMode.JURY_VOTE, - sortOrder: 1, - settingsJson: { description: 'Award for most innovative ocean technology' }, - }, - }) - - const impactTrack = await prisma.track.create({ - data: { - pipelineId: pipeline.id, - name: 'Ocean Impact Award', - slug: 'impact-award', - kind: TrackKind.AWARD, - routingMode: RoutingMode.EXCLUSIVE, - decisionMode: DecisionMode.AWARD_MASTER_DECISION, - sortOrder: 2, - settingsJson: { description: 'Award for highest community impact on ocean health' }, - }, - }) - - const peoplesTrack = await prisma.track.create({ - data: { - pipelineId: pipeline.id, - name: "People's Choice", - slug: 'peoples-choice', - kind: TrackKind.SHOWCASE, - routingMode: RoutingMode.POST_MAIN, - sortOrder: 3, - settingsJson: { description: 'Public audience voting for fan favorite' }, - }, - }) - - console.log(` ✓ Main Competition (MAIN)`) - console.log(` ✓ Ocean Innovation Award (AWARD, PARALLEL)`) - console.log(` ✓ Ocean Impact Award (AWARD, EXCLUSIVE)`) - console.log(` ✓ People's Choice (SHOWCASE, POST_MAIN)`) - - // ========================================================================== - // 9. Stages - // ========================================================================== - console.log('\n📊 Creating stages...') - - // --- Main track stages --- - const mainStages = await Promise.all([ - prisma.stage.create({ - data: { - trackId: mainTrack.id, - stageType: StageType.INTAKE, - name: 'Application Intake', - slug: 'intake', - status: StageStatus.STAGE_CLOSED, - sortOrder: 0, - configJson: { - fileRequirements: [ - { name: 'Executive Summary', type: 'PDF', maxSizeMB: 50, required: true }, - { name: 'Video Pitch', type: 'VIDEO', maxSizeMB: 500, required: false }, - ], - deadline: '2026-01-31T23:59:00Z', - maxSubmissions: 1, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: mainTrack.id, - stageType: StageType.FILTER, - name: 'AI Screening', - slug: 'screening', - status: StageStatus.STAGE_ACTIVE, - sortOrder: 1, - configJson: { - deterministic: { - rules: [ - { field: 'competitionCategory', operator: 'is_not_null', label: 'Has category' }, - { field: 'description', operator: 'min_length', value: 50, label: 'Description >= 50 chars' }, - ], - }, - ai: { rubricVersion: '2026-v1', model: 'gpt-4o' }, - confidenceBands: { - high: { threshold: 0.8, action: 'auto_pass' }, - medium: { threshold: 0.5, action: 'manual_review' }, - low: { threshold: 0, action: 'auto_reject' }, - }, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: mainTrack.id, - stageType: StageType.EVALUATION, - name: 'Expert Evaluation', - slug: 'evaluation', - status: StageStatus.STAGE_DRAFT, - sortOrder: 2, - configJson: { - criteriaVersion: '2026-v1', - assignmentStrategy: 'smart', - requiredReviews: 3, - minAssignmentsPerJuror: 5, - maxAssignmentsPerJuror: 20, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: mainTrack.id, - stageType: StageType.SELECTION, - name: 'Semi-Final Selection', - slug: 'selection', - status: StageStatus.STAGE_DRAFT, - sortOrder: 3, - configJson: { - rankingSource: 'evaluation_scores', - finalistTarget: 6, - selectionMethod: 'top_n_with_admin_override', - }, - }, - }), - prisma.stage.create({ - data: { - trackId: mainTrack.id, - stageType: StageType.LIVE_FINAL, - name: 'Grand Final', - slug: 'grand-final', - status: StageStatus.STAGE_DRAFT, - sortOrder: 4, - configJson: { - sessionMode: 'cohort', - votingEnabled: true, - audienceVoting: true, - audienceVoteWeight: 0.2, - presentationDurationMinutes: 10, - qaDurationMinutes: 5, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: mainTrack.id, - stageType: StageType.RESULTS, - name: 'Results & Awards', - slug: 'results', - status: StageStatus.STAGE_DRAFT, - sortOrder: 5, - configJson: { - rankingWeights: { juryScore: 0.8, audienceScore: 0.2 }, - publicationPolicy: 'after_ceremony', - announcementDate: '2026-06-15', - }, - }, - }), - ]) - - // --- Innovation Award track stages --- - const innovationStages = await Promise.all([ - prisma.stage.create({ - data: { - trackId: innovationTrack.id, - stageType: StageType.EVALUATION, - name: 'Innovation Jury Review', - slug: 'innovation-review', - status: StageStatus.STAGE_DRAFT, - sortOrder: 0, - configJson: { - criteriaVersion: 'innovation-2026-v1', - assignmentStrategy: 'manual', - requiredReviews: 2, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: innovationTrack.id, - stageType: StageType.RESULTS, - name: 'Innovation Results', - slug: 'innovation-results', - status: StageStatus.STAGE_DRAFT, - sortOrder: 1, - configJson: { publicationPolicy: 'after_ceremony' }, - }, - }), - ]) - - // --- Impact Award track stages --- - const impactStages = await Promise.all([ - prisma.stage.create({ - data: { - trackId: impactTrack.id, - stageType: StageType.EVALUATION, - name: 'Impact Assessment', - slug: 'impact-review', - status: StageStatus.STAGE_DRAFT, - sortOrder: 0, - configJson: { - criteriaVersion: 'impact-2026-v1', - assignmentStrategy: 'award_master', - requiredReviews: 1, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: impactTrack.id, - stageType: StageType.RESULTS, - name: 'Impact Results', - slug: 'impact-results', - status: StageStatus.STAGE_DRAFT, - sortOrder: 1, - configJson: { publicationPolicy: 'after_ceremony' }, - }, - }), - ]) - - // --- People's Choice track stages --- - const peoplesStages = await Promise.all([ - prisma.stage.create({ - data: { - trackId: peoplesTrack.id, - stageType: StageType.LIVE_FINAL, - name: 'Public Voting', - slug: 'public-vote', - status: StageStatus.STAGE_DRAFT, - sortOrder: 0, - configJson: { - votingMode: 'favorites', - maxFavorites: 3, - requireIdentification: false, - votingDurationMinutes: 30, - }, - }, - }), - prisma.stage.create({ - data: { - trackId: peoplesTrack.id, - stageType: StageType.RESULTS, - name: "People's Choice Results", - slug: 'peoples-results', - status: StageStatus.STAGE_DRAFT, - sortOrder: 1, - configJson: { publicationPolicy: 'after_ceremony' }, - }, - }), - ]) - - const allStages = [...mainStages, ...innovationStages, ...impactStages, ...peoplesStages] - console.log(` ✓ Created ${allStages.length} stages across 4 tracks`) - - // ========================================================================== - // 10. Stage Transitions (linear within each track) - // ========================================================================== - console.log('\n🔀 Creating stage transitions...') - - const trackStageGroups = [ - { name: 'Main', stages: mainStages }, - { name: 'Innovation', stages: innovationStages }, - { name: 'Impact', stages: impactStages }, - { name: "People's", stages: peoplesStages }, - ] - - let transitionCount = 0 - for (const group of trackStageGroups) { - for (let i = 0; i < group.stages.length - 1; i++) { - await prisma.stageTransition.create({ - data: { - fromStageId: group.stages[i].id, - toStageId: group.stages[i + 1].id, - isDefault: true, - }, - }) - transitionCount++ - } - } - console.log(` ✓ Created ${transitionCount} transitions`) - - // ========================================================================== - // 11. Parse CSV & Create Applicants + Projects - // ========================================================================== - console.log('\n📄 Parsing Candidatures2026.csv...') - - const csvPath = join(__dirname, '..', 'docs', 'Candidatures2026.csv') - const csvContent = readFileSync(csvPath, 'utf-8') - - // Remove BOM if present - const cleanContent = csvContent.replace(/^\uFEFF/, '') - - const records: Record[] = parse(cleanContent, { - columns: true, - skip_empty_lines: true, - relax_column_count: true, - trim: true, - }) - - console.log(` Raw CSV rows: ${records.length}`) - - // Filter and deduplicate - const seenEmails = new Set() - const validRecords: Record[] = [] - - for (const row of records) { - if (!isValidEntry(row)) continue - - const email = (row['E-mail'] || '').trim().toLowerCase() - if (seenEmails.has(email)) continue - - seenEmails.add(email) - validRecords.push(row) - } - - console.log(` Valid entries after filtering: ${validRecords.length}`) - - // Create applicant users and projects - console.log('\n🚀 Creating applicant users and projects...') - - const intakeStage = mainStages[0] // INTAKE - CLOSED - const filterStage = mainStages[1] // FILTER - ACTIVE - - let projectCount = 0 - for (const row of validRecords) { - const email = (row['E-mail'] || '').trim().toLowerCase() - const name = (row['Full name'] || '').trim() - const phone = (row['Téléphone'] || '').trim() || null - const country = (row['Country'] || '').trim() || null - const zone = (row['Tri par zone'] || '').trim() || null - const university = (row['University'] || '').trim() || null - const projectName = (row["Project's name"] || '').trim() - const teamMembers = (row['Team members'] || '').trim() || null - const category = mapCategory(row['Category']) - const issue = mapIssue(row['Issue']) - const comment = (row['Comment'] || row['Comment '] || '').trim() || null - const mentorship = (row['Mentorship'] || '').trim().toLowerCase() === 'true' - const referral = (row['How did you hear about MOPC?'] || '').trim() || null - const appStatus = (row['Application status'] || '').trim() || null - const phase1Url = (row['PHASE 1 - Submission'] || '').trim() || null - const phase2Url = (row['PHASE 2 - Submission'] || '').trim() || null - const foundedAt = parseFoundedDate(row['Date of creation']) - - // Create or get applicant user - const user = await prisma.user.upsert({ - where: { email }, - update: {}, - create: { - email, - name, - role: UserRole.APPLICANT, - status: UserStatus.ACTIVE, - phoneNumber: phone, - country, - metadataJson: university ? { institution: university } : undefined, - mustSetPassword: true, - }, - }) - - // Create project - const project = await prisma.project.create({ - data: { - programId: program.id, - title: projectName || `Project by ${name}`, - description: comment, - competitionCategory: category, - oceanIssue: issue, - country, - geographicZone: zone, - institution: university, - wantsMentorship: mentorship, - foundedAt, - phase1SubmissionUrl: phase1Url, - phase2SubmissionUrl: phase2Url, - referralSource: referral, - applicationStatus: appStatus, - submissionSource: SubmissionSource.CSV, - submittedByUserId: user.id, - submittedByEmail: email, - submittedAt: new Date(), - status: ProjectStatus.SUBMITTED, - metadataJson: teamMembers ? { teamMembers } : undefined, - }, - }) - - // Create ProjectStageState: INTAKE stage = PASSED (intake closed) - await prisma.projectStageState.create({ - data: { - projectId: project.id, - trackId: mainTrack.id, - stageId: intakeStage.id, - state: ProjectStageStateValue.PASSED, - enteredAt: new Date('2026-01-15'), - exitedAt: new Date('2026-01-31'), - }, - }) - - // Create ProjectStageState: FILTER stage = PENDING (current active stage) - await prisma.projectStageState.create({ - data: { - projectId: project.id, - trackId: mainTrack.id, - stageId: filterStage.id, - state: ProjectStageStateValue.PENDING, - enteredAt: new Date('2026-02-01'), - }, - }) - - projectCount++ - if (projectCount % 50 === 0) { - console.log(` ... ${projectCount} projects created`) - } - } - - console.log(` ✓ Created ${projectCount} projects with stage states`) - - // ========================================================================== - // 12. Evaluation Form (for Expert Evaluation stage) - // ========================================================================== - console.log('\n📝 Creating evaluation form...') - - const evaluationStage = mainStages[2] // EVALUATION stage - await prisma.evaluationForm.upsert({ - where: { stageId_version: { stageId: evaluationStage.id, version: 1 } }, - update: {}, - create: { - stageId: evaluationStage.id, - version: 1, - isActive: true, - criteriaJson: [ - { id: 'need_clarity', label: 'Need Clarity', description: 'How clearly is the problem/need articulated?', scale: '1-5', weight: 20, type: 'numeric', required: true }, - { id: 'solution_relevance', label: 'Solution Relevance', description: 'How relevant and innovative is the proposed solution?', scale: '1-5', weight: 25, type: 'numeric', required: true }, - { id: 'ocean_impact', label: 'Ocean Impact', description: 'What is the potential positive impact on ocean conservation?', scale: '1-5', weight: 25, type: 'numeric', required: true }, - { id: 'feasibility', label: 'Feasibility & Scalability', description: 'How feasible and scalable is the project?', scale: '1-5', weight: 20, type: 'numeric', required: true }, - { id: 'team_strength', label: 'Team Strength', description: 'How strong and capable is the team?', scale: '1-5', weight: 10, type: 'numeric', required: true }, - ], - scalesJson: { - '1-5': { min: 1, max: 5, labels: { 1: 'Poor', 2: 'Below Average', 3: 'Average', 4: 'Good', 5: 'Excellent' } }, - }, - }, - }) - console.log(' ✓ Evaluation form created (5 criteria)') - - // ========================================================================== - // 13. Special Awards - // ========================================================================== - console.log('\n🏆 Creating special awards...') - - await prisma.specialAward.create({ - data: { - programId: program.id, - name: 'Ocean Innovation Award', - description: 'Recognizes the most innovative technology solution for ocean protection', - status: 'DRAFT', - trackId: innovationTrack.id, - scoringMode: 'PICK_WINNER', - useAiEligibility: true, - criteriaText: 'Projects demonstrating breakthrough technological innovation for ocean conservation', - }, - }) - - await prisma.specialAward.create({ - data: { - programId: program.id, - name: 'Ocean Impact Award', - description: 'Recognizes the project with highest community and environmental impact', - status: 'DRAFT', - trackId: impactTrack.id, - scoringMode: 'PICK_WINNER', - useAiEligibility: false, - criteriaText: 'Projects with measurable, significant impact on ocean health and coastal communities', - }, - }) - - console.log(' ✓ Ocean Innovation Award → innovation-award track') - console.log(' ✓ Ocean Impact Award → impact-award track') - - // ========================================================================== - // 14. Routing Rules - // ========================================================================== - console.log('\n🔀 Creating routing rules...') - - await prisma.routingRule.create({ - data: { - pipelineId: pipeline.id, - name: 'Route Tech Innovation to Innovation Award', - scope: 'global', - destinationTrackId: innovationTrack.id, - predicateJson: { - field: 'oceanIssue', - operator: 'eq', - value: 'TECHNOLOGY_INNOVATION', - }, - priority: 10, - isActive: true, - }, - }) - - await prisma.routingRule.create({ - data: { - pipelineId: pipeline.id, - name: 'Route Community Impact to Impact Award', - scope: 'global', - destinationTrackId: impactTrack.id, - predicateJson: { - or: [ - { field: 'oceanIssue', operator: 'eq', value: 'COMMUNITY_CAPACITY' }, - { field: 'oceanIssue', operator: 'eq', value: 'HABITAT_RESTORATION' }, - ], - }, - priority: 5, - isActive: true, - }, - }) - - console.log(' ✓ Tech Innovation → Innovation Award (PARALLEL)') - console.log(' ✓ Community Impact → Impact Award (EXCLUSIVE)') - - // ========================================================================== - // 15. Summary - // ========================================================================== - console.log('\n' + '='.repeat(60)) - console.log('✅ SEEDING COMPLETE') - console.log('='.repeat(60)) - console.log(` - Program: ${program.name} ${program.year} - Pipeline: ${pipeline.name} (${pipeline.slug}) - Tracks: 4 (Main, Innovation Award, Impact Award, People's Choice) - Stages: ${allStages.length} total - Transitions: ${transitionCount} - Projects: ${projectCount} (from CSV) - Users: ${3 + juryMembers.length + mentors.length + observers.length + projectCount} total - - Admin/Staff: 3 - - Jury: ${juryMembers.length} - - Mentors: ${mentors.length} - - Observers: ${observers.length} - - Applicants: ${projectCount} - - Login: matt@monaco-opc.com / 195260Mp! - `) -} - -main() - .catch((e) => { - console.error('❌ Seeding failed:', e) - process.exit(1) - }) - .finally(async () => { - await prisma.$disconnect() - }) +import { + PrismaClient, + UserRole, + UserStatus, + ProgramStatus, + SettingType, + SettingCategory, + CompetitionCategory, + OceanIssue, + StageType, + TrackKind, + RoutingMode, + DecisionMode, + StageStatus, + ProjectStageStateValue, + ProjectStatus, + SubmissionSource, +} from '@prisma/client' +import bcrypt from 'bcryptjs' +import { readFileSync } from 'fs' +import { parse } from 'csv-parse/sync' +import { join, dirname } from 'path' +import { fileURLToPath } from 'url' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +const prisma = new PrismaClient() + +// ============================================================================= +// CSV Column Mapping Helpers +// ============================================================================= + +const categoryMap: Record = { + 'the « Start-ups » category': CompetitionCategory.STARTUP, + 'the « Business concepts » category': CompetitionCategory.BUSINESS_CONCEPT, +} + +const issueMap: Record = { + 'Reduction of pollution': OceanIssue.POLLUTION_REDUCTION, + 'Mitigation of climate change': OceanIssue.CLIMATE_MITIGATION, + 'Technology & innovations': OceanIssue.TECHNOLOGY_INNOVATION, + 'Sustainable shipping': OceanIssue.SUSTAINABLE_SHIPPING, + 'Blue Carbon': OceanIssue.BLUE_CARBON, + 'Restoration of marine': OceanIssue.HABITAT_RESTORATION, + 'Capacity building': OceanIssue.COMMUNITY_CAPACITY, + 'Sustainable fishing': OceanIssue.SUSTAINABLE_FISHING, + 'Consumer awareness': OceanIssue.CONSUMER_AWARENESS, + 'Mitigation of ocean acidification': OceanIssue.OCEAN_ACIDIFICATION, + 'Other': OceanIssue.OTHER, +} + +function mapCategory(raw: string | undefined): CompetitionCategory | null { + if (!raw) return null + const trimmed = raw.trim() + for (const [prefix, value] of Object.entries(categoryMap)) { + if (trimmed.startsWith(prefix)) return value + } + return null +} + +function mapIssue(raw: string | undefined): OceanIssue | null { + if (!raw) return null + const trimmed = raw.trim() + for (const [prefix, value] of Object.entries(issueMap)) { + if (trimmed.startsWith(prefix)) return value + } + return OceanIssue.OTHER +} + +function parseFoundedDate(raw: string | undefined): Date | null { + if (!raw) return null + const trimmed = raw.trim() + if (!trimmed) return null + const d = new Date(trimmed) + return isNaN(d.getTime()) ? null : d +} + +function isValidEntry(row: Record): boolean { + const status = (row['Application status'] || '').trim().toLowerCase() + if (status === 'ignore' || status === 'doublon') return false + + const name = (row['Full name'] || '').trim() + if (name.length <= 2) return false // skip test entries + + const email = (row['E-mail'] || '').trim() + if (!email || !email.includes('@')) return false + + return true +} + +// ============================================================================= +// Main Seed Function +// ============================================================================= + +async function main() { + console.log('🌱 Seeding database with MOPC 2026 real data...\n') + + // ========================================================================== + // 1. System Settings + // ========================================================================== + console.log('📋 Creating system settings...') + + const settings = [ + { key: 'ai_enabled', value: 'false', type: SettingType.BOOLEAN, category: SettingCategory.AI, description: 'Enable AI-powered jury assignment suggestions' }, + { key: 'ai_provider', value: 'openai', type: SettingType.STRING, category: SettingCategory.AI, description: 'AI provider for smart assignment (openai)' }, + { key: 'ai_model', value: 'gpt-4o', type: SettingType.STRING, category: SettingCategory.AI, description: 'OpenAI model to use for suggestions' }, + { key: 'ai_send_descriptions', value: 'false', type: SettingType.BOOLEAN, category: SettingCategory.AI, description: 'Send anonymized project descriptions to AI' }, + { key: 'platform_name', value: 'Monaco Ocean Protection Challenge', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Platform display name' }, + { key: 'primary_color', value: '#de0f1e', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Primary brand color (hex)' }, + { key: 'secondary_color', value: '#053d57', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Secondary brand color (hex)' }, + { key: 'accent_color', value: '#557f8c', type: SettingType.STRING, category: SettingCategory.BRANDING, description: 'Accent color (hex)' }, + { key: 'session_duration_hours', value: '24', type: SettingType.NUMBER, category: SettingCategory.SECURITY, description: 'Session duration in hours' }, + { key: 'magic_link_expiry_minutes', value: '15', type: SettingType.NUMBER, category: SettingCategory.SECURITY, description: 'Magic link expiry time in minutes' }, + { key: 'rate_limit_requests_per_minute', value: '60', type: SettingType.NUMBER, category: SettingCategory.SECURITY, description: 'API rate limit per minute' }, + { key: 'storage_provider', value: 's3', type: SettingType.STRING, category: SettingCategory.STORAGE, description: 'Storage provider: s3 (MinIO) or local (filesystem)' }, + { key: 'local_storage_path', value: './uploads', type: SettingType.STRING, category: SettingCategory.STORAGE, description: 'Base path for local file storage' }, + { key: 'max_file_size_mb', value: '500', type: SettingType.NUMBER, category: SettingCategory.STORAGE, description: 'Maximum file upload size in MB' }, + { key: 'avatar_max_size_mb', value: '5', type: SettingType.NUMBER, category: SettingCategory.STORAGE, description: 'Maximum avatar image size in MB' }, + { key: 'allowed_file_types', value: JSON.stringify(['application/pdf', 'video/mp4', 'video/quicktime', 'image/png', 'image/jpeg']), type: SettingType.JSON, category: SettingCategory.STORAGE, description: 'Allowed MIME types for file uploads' }, + { key: 'allowed_image_types', value: JSON.stringify(['image/png', 'image/jpeg', 'image/webp']), type: SettingType.JSON, category: SettingCategory.STORAGE, description: 'Allowed MIME types for avatar/logo uploads' }, + { key: 'default_timezone', value: 'Europe/Monaco', type: SettingType.STRING, category: SettingCategory.DEFAULTS, description: 'Default timezone for date displays' }, + { key: 'default_page_size', value: '20', type: SettingType.NUMBER, category: SettingCategory.DEFAULTS, description: 'Default pagination size' }, + { key: 'autosave_interval_seconds', value: '30', type: SettingType.NUMBER, category: SettingCategory.DEFAULTS, description: 'Autosave interval for evaluation forms' }, + { key: 'whatsapp_enabled', value: 'false', type: SettingType.BOOLEAN, category: SettingCategory.WHATSAPP, description: 'Enable WhatsApp notifications' }, + { key: 'whatsapp_provider', value: 'META', type: SettingType.STRING, category: SettingCategory.WHATSAPP, description: 'WhatsApp provider (META or TWILIO)' }, + { key: 'openai_api_key', value: '', type: SettingType.SECRET, category: SettingCategory.AI, description: 'OpenAI API Key for AI-powered features', isSecret: true }, + ] + + for (const setting of settings) { + await prisma.systemSettings.upsert({ + where: { key: setting.key }, + update: {}, + create: setting, + }) + } + console.log(` Created ${settings.length} settings`) + + // ========================================================================== + // 1b. Expertise Tags + // ========================================================================== + console.log('\n🏷️ Creating expertise tags...') + + const tagGroups = [ + { + category: 'Pollution Reduction', + color: '#dc2626', + tags: [ + { name: 'Marine Plastic & Ghost Gear Cleanup', description: 'Collection and processing of plastic waste, fishing nets, and marine debris from coastal and ocean environments' }, + { name: 'Industrial & Wastewater Marine Protection', description: 'Systems reducing chemical discharge, nutrient runoff, and wastewater pollution before ocean impact' }, + { name: 'Circular Materials from Marine Waste', description: 'Transformation of algae, fishery byproducts, and recovered ocean waste into useful products' }, + ], + }, + { + category: 'Climate Mitigation', + color: '#0284c7', + tags: [ + { name: 'Low-Carbon Blue Supply Chains', description: 'Solutions reducing emissions in seafood logistics, cooling, and marine value chains' }, + { name: 'Ocean Renewable Energy', description: 'Wave, tidal, offshore, and hybrid marine energy technologies' }, + { name: 'Marine Carbon Removal & Sequestration', description: 'Approaches that remove and store carbon through ocean-linked biological or mineral pathways' }, + ], + }, + { + category: 'Technology & Innovation', + color: '#7c3aed', + tags: [ + { name: 'Marine Robotics & Autonomous Systems', description: 'ROVs, AUVs, and marine drones used for restoration, monitoring, and intervention' }, + { name: 'AI Ocean Intelligence', description: 'Machine learning and advanced analytics for ocean health, biodiversity, or operations optimization' }, + { name: 'Marine Ecotoxicology & Environmental Testing', description: 'Testing platforms that evaluate product or discharge impacts on marine ecosystems' }, + ], + }, + { + category: 'Sustainable Shipping', + color: '#053d57', + tags: [ + { name: 'Cleaner Maritime Operations', description: 'Operational innovations that reduce emissions, waste, and fuel intensity in maritime transport' }, + { name: 'Port Environmental Performance', description: 'Technologies and practices that improve sustainability outcomes in ports and harbors' }, + { name: 'Marine Noise & Vessel Impact Reduction', description: 'Solutions that mitigate underwater noise and ecological disturbance from vessel activity' }, + ], + }, + { + category: 'Blue Carbon', + color: '#0ea5a4', + tags: [ + { name: 'Seagrass & Mangrove Carbon Projects', description: 'Restoration and protection programs for key blue carbon habitats' }, + { name: 'Blue Carbon Measurement & Verification', description: 'Monitoring and MRV tools for quantifying carbon outcomes in marine ecosystems' }, + { name: 'Financing Blue Carbon Conservation', description: 'Financial models enabling scalable protection and restoration of blue carbon assets' }, + ], + }, + { + category: 'Habitat Restoration', + color: '#16a34a', + tags: [ + { name: 'Coral Restoration & Reef Resilience', description: 'Propagation, outplanting, and resilience strategies for coral ecosystems' }, + { name: 'Coastal Habitat Regeneration', description: 'Recovery of dunes, wetlands, estuaries, and nearshore biodiversity hotspots' }, + { name: 'Biodiversity Threat Mitigation', description: 'Targeted interventions for invasive species, habitat degradation, and species decline' }, + ], + }, + { + category: 'Community Capacity', + color: '#ea580c', + tags: [ + { name: 'Coastal Livelihood & Inclusion Models', description: 'Community-led business models that improve income while protecting marine ecosystems' }, + { name: 'Women-Led Blue Economy Initiatives', description: 'Programs that strengthen women leadership and participation in sustainable marine enterprises' }, + { name: 'Ocean Skills & Entrepreneurship Training', description: 'Capacity-building and startup enablement for students and coastal entrepreneurs' }, + ], + }, + { + category: 'Sustainable Fishing', + color: '#059669', + tags: [ + { name: 'Regenerative Aquaculture', description: 'Aquaculture systems integrating ecological restoration, animal welfare, and reduced environmental pressure' }, + { name: 'Seaweed & Algae Value Chains', description: 'Cultivation and commercialization of algae or seaweed for food, feed, and biomaterials' }, + { name: 'Cold Chain & Post-Harvest Seafood Efficiency', description: 'Technologies reducing fish loss and waste through sustainable preservation and handling' }, + ], + }, + { + category: 'Consumer Awareness', + color: '#f59e0b', + tags: [ + { name: 'Ocean Literacy Platforms', description: 'Digital or physical tools that increase public understanding of ocean health issues' }, + { name: 'Behavior Change for Ocean Protection', description: 'Campaigns and products that help consumers reduce harmful marine impact' }, + { name: 'Traceability & Sustainable Choice Tools', description: 'Interfaces helping buyers identify responsible seafood and ocean-positive products' }, + ], + }, + { + category: 'Ocean Acidification', + color: '#2563eb', + tags: [ + { name: 'Acidification Monitoring & Forecasting', description: 'Sensors and models tracking pH dynamics and acidification risk in marine environments' }, + { name: 'Alkalinity & Buffering Interventions', description: 'Interventions designed to reduce acidification pressure on vulnerable marine systems' }, + { name: 'Acidification-Resilient Aquaculture', description: 'Farming approaches and species strategies resilient to changing ocean chemistry' }, + ], + }, + ] as const + + const expertiseTags = tagGroups.flatMap((group, groupIndex) => + group.tags.map((tag, tagIndex) => ({ + name: tag.name, + description: tag.description, + category: group.category, + color: group.color, + sortOrder: groupIndex * 10 + tagIndex, + })) + ) + + for (const tag of expertiseTags) { + await prisma.expertiseTag.upsert({ + where: { name: tag.name }, + update: { + description: tag.description, + category: tag.category, + color: tag.color, + sortOrder: tag.sortOrder, + isActive: true, + }, + create: { + name: tag.name, + description: tag.description, + category: tag.category, + color: tag.color, + sortOrder: tag.sortOrder, + isActive: true, + }, + }) + } + console.log(` Created ${expertiseTags.length} expertise tags across ${new Set(expertiseTags.map(t => t.category)).size} categories`) + + // ========================================================================== + // 2. Admin/Staff Users + // ========================================================================== + console.log('\n👤 Creating admin & staff users...') + + const staffAccounts = [ + { email: 'matt@monaco-opc.com', name: 'Matt', role: UserRole.SUPER_ADMIN, password: '195260Mp!' }, + { email: 'admin@monaco-opc.com', name: 'Admin', role: UserRole.PROGRAM_ADMIN, password: 'Admin123!' }, + { email: 'awards@monaco-opc.com', name: 'Award Director', role: UserRole.AWARD_MASTER, password: 'Awards123!' }, + ] + + const staffUsers: Record = {} + for (const account of staffAccounts) { + const passwordHash = await bcrypt.hash(account.password, 12) + const isSuperAdmin = account.role === UserRole.SUPER_ADMIN + const user = await prisma.user.upsert({ + where: { email: account.email }, + update: isSuperAdmin + ? { + status: UserStatus.ACTIVE, + passwordHash, + mustSetPassword: false, + passwordSetAt: new Date(), + onboardingCompletedAt: new Date(), + } + : { + status: UserStatus.NONE, + passwordHash: null, + mustSetPassword: true, + passwordSetAt: null, + onboardingCompletedAt: null, + inviteToken: null, + inviteTokenExpiresAt: null, + }, + create: { + email: account.email, + name: account.name, + role: account.role, + status: isSuperAdmin ? UserStatus.ACTIVE : UserStatus.NONE, + passwordHash: isSuperAdmin ? passwordHash : null, + mustSetPassword: !isSuperAdmin, + passwordSetAt: isSuperAdmin ? new Date() : null, + onboardingCompletedAt: isSuperAdmin ? new Date() : null, + }, + }) + staffUsers[account.email] = user.id + console.log(` ✓ ${account.role}: ${account.email}`) + } + + // ========================================================================== + // 3. Jury Members (8 fictional) + // ========================================================================== + console.log('\n⚖️ Creating jury members...') + + const juryMembers = [ + { email: 'jury1@monaco-opc.com', name: 'Dr. Sophie Laurent', country: 'France', tags: ['marine-biology', 'coral-restoration', 'biodiversity'] }, + { email: 'jury2@monaco-opc.com', name: 'Prof. Marco Bianchi', country: 'Italy', tags: ['ocean-engineering', 'renewable-energy', 'desalination'] }, + { email: 'jury3@monaco-opc.com', name: 'Dr. Aisha Patel', country: 'United Kingdom', tags: ['sustainability', 'circular-economy', 'waste-management'] }, + { email: 'jury4@monaco-opc.com', name: 'Dr. Kenji Tanaka', country: 'Japan', tags: ['aquaculture', 'sustainable-fishing', 'marine-technology'] }, + { email: 'jury5@monaco-opc.com', name: 'Prof. Elena Volkov', country: 'Germany', tags: ['climate-science', 'ocean-acidification', 'blue-carbon'] }, + { email: 'jury6@monaco-opc.com', name: 'Dr. Amara Diallo', country: 'Senegal', tags: ['community-development', 'capacity-building', 'coastal-management'] }, + { email: 'jury7@monaco-opc.com', name: 'Dr. Carlos Rivera', country: 'Spain', tags: ['blue-economy', 'maritime-policy', 'shipping'] }, + { email: 'jury8@monaco-opc.com', name: 'Prof. Lin Wei', country: 'Singapore', tags: ['marine-biotech', 'pollution-monitoring', 'AI-ocean'] }, + ] + + const juryUserIds: string[] = [] + for (const j of juryMembers) { + const user = await prisma.user.upsert({ + where: { email: j.email }, + update: { + status: UserStatus.NONE, + }, + create: { + email: j.email, + name: j.name, + role: UserRole.JURY_MEMBER, + status: UserStatus.NONE, + country: j.country, + expertiseTags: j.tags, + bio: `Expert in ${j.tags.join(', ')}`, + }, + }) + juryUserIds.push(user.id) + console.log(` ✓ Jury: ${j.name} (${j.country})`) + } + + // ========================================================================== + // 4. Mentors (3 fictional) + // ========================================================================== + console.log('\n🧑‍🏫 Creating mentors...') + + const mentors = [ + { email: 'mentor1@monaco-opc.com', name: 'Marie Dubois', country: 'Monaco', tags: ['startup-coaching', 'ocean-conservation'] }, + { email: 'mentor2@monaco-opc.com', name: 'James Cooper', country: 'United States', tags: ['venture-capital', 'cleantech'] }, + { email: 'mentor3@monaco-opc.com', name: 'Fatima Al-Rashid', country: 'UAE', tags: ['impact-investing', 'sustainability-strategy'] }, + ] + + for (const m of mentors) { + await prisma.user.upsert({ + where: { email: m.email }, + update: { + status: UserStatus.NONE, + }, + create: { + email: m.email, + name: m.name, + role: UserRole.MENTOR, + status: UserStatus.NONE, + country: m.country, + expertiseTags: m.tags, + }, + }) + console.log(` ✓ Mentor: ${m.name}`) + } + + // ========================================================================== + // 5. Observers (2 fictional) + // ========================================================================== + console.log('\n👁️ Creating observers...') + + const observers = [ + { email: 'observer1@monaco-opc.com', name: 'Pierre Martin', country: 'Monaco' }, + { email: 'observer2@monaco-opc.com', name: 'Sarah Chen', country: 'Canada' }, + ] + + for (const o of observers) { + await prisma.user.upsert({ + where: { email: o.email }, + update: { + status: UserStatus.NONE, + }, + create: { + email: o.email, + name: o.name, + role: UserRole.OBSERVER, + status: UserStatus.NONE, + country: o.country, + }, + }) + console.log(` ✓ Observer: ${o.name}`) + } + + // ========================================================================== + // 6. Program + // ========================================================================== + console.log('\n📁 Creating program...') + + const program = await prisma.program.upsert({ + where: { name_year: { name: 'Monaco Ocean Protection Challenge', year: 2026 } }, + update: {}, + create: { + name: 'Monaco Ocean Protection Challenge', + year: 2026, + status: ProgramStatus.ACTIVE, + description: 'Annual ocean conservation startup competition supporting innovative solutions for ocean protection.', + }, + }) + console.log(` ✓ Program: ${program.name} ${program.year}`) + + // ========================================================================== + // 7. Pipeline + // ========================================================================== + console.log('\n🔗 Creating pipeline...') + + const pipeline = await prisma.pipeline.upsert({ + where: { slug: 'mopc-2026' }, + update: { + name: 'MOPC 2026 Main Pipeline', + status: 'ACTIVE', + }, + create: { + programId: program.id, + name: 'MOPC 2026 Main Pipeline', + slug: 'mopc-2026', + status: 'ACTIVE', + settingsJson: { + description: 'Main pipeline for MOPC 2026 competition', + allowParallelTracks: true, + autoAdvanceOnClose: false, + }, + }, + }) + console.log(` ✓ Pipeline: ${pipeline.name}`) + + // ========================================================================== + // 8. Tracks (4) + // ========================================================================== + console.log('\n🛤️ Creating tracks...') + + const mainTrack = await prisma.track.upsert({ + where: { pipelineId_slug: { pipelineId: pipeline.id, slug: 'main' } }, + update: { name: 'Main Competition' }, + create: { + pipelineId: pipeline.id, + name: 'Main Competition', + slug: 'main', + kind: TrackKind.MAIN, + sortOrder: 0, + settingsJson: { description: 'Primary competition track for all applicants' }, + }, + }) + + const innovationTrack = await prisma.track.upsert({ + where: { pipelineId_slug: { pipelineId: pipeline.id, slug: 'innovation-award' } }, + update: { name: 'Ocean Innovation Award' }, + create: { + pipelineId: pipeline.id, + name: 'Ocean Innovation Award', + slug: 'innovation-award', + kind: TrackKind.AWARD, + routingMode: RoutingMode.PARALLEL, + decisionMode: DecisionMode.JURY_VOTE, + sortOrder: 1, + settingsJson: { description: 'Award for most innovative ocean technology' }, + }, + }) + + const impactTrack = await prisma.track.upsert({ + where: { pipelineId_slug: { pipelineId: pipeline.id, slug: 'impact-award' } }, + update: { name: 'Ocean Impact Award' }, + create: { + pipelineId: pipeline.id, + name: 'Ocean Impact Award', + slug: 'impact-award', + kind: TrackKind.AWARD, + routingMode: RoutingMode.EXCLUSIVE, + decisionMode: DecisionMode.AWARD_MASTER_DECISION, + sortOrder: 2, + settingsJson: { description: 'Award for highest community impact on ocean health' }, + }, + }) + + const peoplesTrack = await prisma.track.upsert({ + where: { pipelineId_slug: { pipelineId: pipeline.id, slug: 'peoples-choice' } }, + update: { name: "People's Choice" }, + create: { + pipelineId: pipeline.id, + name: "People's Choice", + slug: 'peoples-choice', + kind: TrackKind.SHOWCASE, + routingMode: RoutingMode.POST_MAIN, + sortOrder: 3, + settingsJson: { description: 'Public audience voting for fan favorite' }, + }, + }) + + console.log(` ✓ Main Competition (MAIN)`) + console.log(` ✓ Ocean Innovation Award (AWARD, PARALLEL)`) + console.log(` ✓ Ocean Impact Award (AWARD, EXCLUSIVE)`) + console.log(` ✓ People's Choice (SHOWCASE, POST_MAIN)`) + + // ========================================================================== + // 9. Stages + // ========================================================================== + console.log('\n📊 Creating stages...') + + // --- Main track stages --- + const mainStages = await Promise.all([ + prisma.stage.upsert({ + where: { trackId_slug: { trackId: mainTrack.id, slug: 'intake' } }, + update: {}, + create: { + trackId: mainTrack.id, + stageType: StageType.INTAKE, + name: 'Application Intake', + slug: 'intake', + status: StageStatus.STAGE_CLOSED, + sortOrder: 0, + configJson: { + fileRequirements: [ + { name: 'Executive Summary', type: 'PDF', maxSizeMB: 50, required: true }, + { name: 'Video Pitch', type: 'VIDEO', maxSizeMB: 500, required: false }, + ], + deadline: '2026-01-31T23:59:00Z', + maxSubmissions: 1, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: mainTrack.id, slug: 'screening' } }, + update: {}, + create: { + trackId: mainTrack.id, + stageType: StageType.FILTER, + name: 'AI Screening', + slug: 'screening', + status: StageStatus.STAGE_ACTIVE, + sortOrder: 1, + configJson: { + deterministic: { + rules: [ + { field: 'competitionCategory', operator: 'is_not_null', label: 'Has category' }, + { field: 'description', operator: 'min_length', value: 50, label: 'Description >= 50 chars' }, + ], + }, + ai: { rubricVersion: '2026-v1', model: 'gpt-4o' }, + confidenceBands: { + high: { threshold: 0.8, action: 'auto_pass' }, + medium: { threshold: 0.5, action: 'manual_review' }, + low: { threshold: 0, action: 'auto_reject' }, + }, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: mainTrack.id, slug: 'evaluation' } }, + update: {}, + create: { + trackId: mainTrack.id, + stageType: StageType.EVALUATION, + name: 'Expert Evaluation', + slug: 'evaluation', + status: StageStatus.STAGE_DRAFT, + sortOrder: 2, + configJson: { + criteriaVersion: '2026-v1', + assignmentStrategy: 'smart', + requiredReviews: 3, + minAssignmentsPerJuror: 5, + maxAssignmentsPerJuror: 20, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: mainTrack.id, slug: 'selection' } }, + update: {}, + create: { + trackId: mainTrack.id, + stageType: StageType.SELECTION, + name: 'Semi-Final Selection', + slug: 'selection', + status: StageStatus.STAGE_DRAFT, + sortOrder: 3, + configJson: { + rankingSource: 'evaluation_scores', + finalistTarget: 6, + selectionMethod: 'top_n_with_admin_override', + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: mainTrack.id, slug: 'grand-final' } }, + update: {}, + create: { + trackId: mainTrack.id, + stageType: StageType.LIVE_FINAL, + name: 'Grand Final', + slug: 'grand-final', + status: StageStatus.STAGE_DRAFT, + sortOrder: 4, + configJson: { + sessionMode: 'cohort', + votingEnabled: true, + audienceVoting: true, + audienceVoteWeight: 0.2, + presentationDurationMinutes: 10, + qaDurationMinutes: 5, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: mainTrack.id, slug: 'results' } }, + update: {}, + create: { + trackId: mainTrack.id, + stageType: StageType.RESULTS, + name: 'Results & Awards', + slug: 'results', + status: StageStatus.STAGE_DRAFT, + sortOrder: 5, + configJson: { + rankingWeights: { juryScore: 0.8, audienceScore: 0.2 }, + publicationPolicy: 'after_ceremony', + announcementDate: '2026-06-15', + }, + }, + }), + ]) + + // --- Innovation Award track stages --- + const innovationStages = await Promise.all([ + prisma.stage.upsert({ + where: { trackId_slug: { trackId: innovationTrack.id, slug: 'innovation-review' } }, + update: {}, + create: { + trackId: innovationTrack.id, + stageType: StageType.EVALUATION, + name: 'Innovation Jury Review', + slug: 'innovation-review', + status: StageStatus.STAGE_DRAFT, + sortOrder: 0, + configJson: { + criteriaVersion: 'innovation-2026-v1', + assignmentStrategy: 'manual', + requiredReviews: 2, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: innovationTrack.id, slug: 'innovation-results' } }, + update: {}, + create: { + trackId: innovationTrack.id, + stageType: StageType.RESULTS, + name: 'Innovation Results', + slug: 'innovation-results', + status: StageStatus.STAGE_DRAFT, + sortOrder: 1, + configJson: { publicationPolicy: 'after_ceremony' }, + }, + }), + ]) + + // --- Impact Award track stages --- + const impactStages = await Promise.all([ + prisma.stage.upsert({ + where: { trackId_slug: { trackId: impactTrack.id, slug: 'impact-review' } }, + update: {}, + create: { + trackId: impactTrack.id, + stageType: StageType.EVALUATION, + name: 'Impact Assessment', + slug: 'impact-review', + status: StageStatus.STAGE_DRAFT, + sortOrder: 0, + configJson: { + criteriaVersion: 'impact-2026-v1', + assignmentStrategy: 'award_master', + requiredReviews: 1, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: impactTrack.id, slug: 'impact-results' } }, + update: {}, + create: { + trackId: impactTrack.id, + stageType: StageType.RESULTS, + name: 'Impact Results', + slug: 'impact-results', + status: StageStatus.STAGE_DRAFT, + sortOrder: 1, + configJson: { publicationPolicy: 'after_ceremony' }, + }, + }), + ]) + + // --- People's Choice track stages --- + const peoplesStages = await Promise.all([ + prisma.stage.upsert({ + where: { trackId_slug: { trackId: peoplesTrack.id, slug: 'public-vote' } }, + update: {}, + create: { + trackId: peoplesTrack.id, + stageType: StageType.LIVE_FINAL, + name: 'Public Voting', + slug: 'public-vote', + status: StageStatus.STAGE_DRAFT, + sortOrder: 0, + configJson: { + votingMode: 'favorites', + maxFavorites: 3, + requireIdentification: false, + votingDurationMinutes: 30, + }, + }, + }), + prisma.stage.upsert({ + where: { trackId_slug: { trackId: peoplesTrack.id, slug: 'peoples-results' } }, + update: {}, + create: { + trackId: peoplesTrack.id, + stageType: StageType.RESULTS, + name: "People's Choice Results", + slug: 'peoples-results', + status: StageStatus.STAGE_DRAFT, + sortOrder: 1, + configJson: { publicationPolicy: 'after_ceremony' }, + }, + }), + ]) + + const allStages = [...mainStages, ...innovationStages, ...impactStages, ...peoplesStages] + console.log(` ✓ Created ${allStages.length} stages across 4 tracks`) + + // ========================================================================== + // 10. Stage Transitions (linear within each track) + // ========================================================================== + console.log('\n🔀 Creating stage transitions...') + + const trackStageGroups = [ + { name: 'Main', stages: mainStages }, + { name: 'Innovation', stages: innovationStages }, + { name: 'Impact', stages: impactStages }, + { name: "People's", stages: peoplesStages }, + ] + + let transitionCount = 0 + for (const group of trackStageGroups) { + for (let i = 0; i < group.stages.length - 1; i++) { + await prisma.stageTransition.upsert({ + where: { + fromStageId_toStageId: { + fromStageId: group.stages[i].id, + toStageId: group.stages[i + 1].id, + }, + }, + update: {}, + create: { + fromStageId: group.stages[i].id, + toStageId: group.stages[i + 1].id, + isDefault: true, + }, + }) + transitionCount++ + } + } + console.log(` ✓ Created ${transitionCount} transitions`) + + // ========================================================================== + // 11. Parse CSV & Create Applicants + Projects + // ========================================================================== + console.log('\n📄 Checking for existing projects...') + + const existingProjectCount = await prisma.project.count({ where: { programId: program.id } }) + let projectCount = 0 + + if (existingProjectCount > 0) { + projectCount = existingProjectCount + console.log(` ⏭️ ${existingProjectCount} projects already exist, skipping CSV import`) + } else { + console.log(' Parsing Candidatures2026.csv...') + + const csvPath = join(__dirname, '..', 'docs', 'Candidatures2026.csv') + const csvContent = readFileSync(csvPath, 'utf-8') + + // Remove BOM if present + const cleanContent = csvContent.replace(/^\uFEFF/, '') + + const records: Record[] = parse(cleanContent, { + columns: true, + skip_empty_lines: true, + relax_column_count: true, + trim: true, + }) + + console.log(` Raw CSV rows: ${records.length}`) + + // Filter and deduplicate + const seenEmails = new Set() + const validRecords: Record[] = [] + + for (const row of records) { + if (!isValidEntry(row)) continue + + const email = (row['E-mail'] || '').trim().toLowerCase() + if (seenEmails.has(email)) continue + + seenEmails.add(email) + validRecords.push(row) + } + + console.log(` Valid entries after filtering: ${validRecords.length}`) + + // Create applicant users and projects + console.log('\n🚀 Creating applicant users and projects...') + + const intakeStage = mainStages[0] // INTAKE - CLOSED + const filterStage = mainStages[1] // FILTER - ACTIVE + + for (const row of validRecords) { + const email = (row['E-mail'] || '').trim().toLowerCase() + const name = (row['Full name'] || '').trim() + const phone = (row['Téléphone'] || '').trim() || null + const country = (row['Country'] || '').trim() || null + const zone = (row['Tri par zone'] || '').trim() || null + const university = (row['University'] || '').trim() || null + const projectName = (row["Project's name"] || '').trim() + const teamMembers = (row['Team members'] || '').trim() || null + const category = mapCategory(row['Category']) + const issue = mapIssue(row['Issue']) + const comment = (row['Comment'] || row['Comment '] || '').trim() || null + const mentorship = (row['Mentorship'] || '').trim().toLowerCase() === 'true' + const referral = (row['How did you hear about MOPC?'] || '').trim() || null + const appStatus = (row['Application status'] || '').trim() || null + const phase1Url = (row['PHASE 1 - Submission'] || '').trim() || null + const phase2Url = (row['PHASE 2 - Submission'] || '').trim() || null + const foundedAt = parseFoundedDate(row['Date of creation']) + + // Create or get applicant user + const user = await prisma.user.upsert({ + where: { email }, + update: { + status: UserStatus.NONE, + mustSetPassword: true, + }, + create: { + email, + name, + role: UserRole.APPLICANT, + status: UserStatus.NONE, + phoneNumber: phone, + country, + metadataJson: university ? { institution: university } : undefined, + mustSetPassword: true, + }, + }) + + // Create project + const project = await prisma.project.create({ + data: { + programId: program.id, + title: projectName || `Project by ${name}`, + description: comment, + competitionCategory: category, + oceanIssue: issue, + country, + geographicZone: zone, + institution: university, + wantsMentorship: mentorship, + foundedAt, + phase1SubmissionUrl: phase1Url, + phase2SubmissionUrl: phase2Url, + referralSource: referral, + applicationStatus: appStatus, + submissionSource: SubmissionSource.CSV, + submittedByUserId: user.id, + submittedByEmail: email, + submittedAt: new Date(), + status: ProjectStatus.SUBMITTED, + metadataJson: teamMembers ? { teamMembers } : undefined, + }, + }) + + // Create ProjectStageState: INTAKE stage = PASSED (intake closed) + await prisma.projectStageState.create({ + data: { + projectId: project.id, + trackId: mainTrack.id, + stageId: intakeStage.id, + state: ProjectStageStateValue.PASSED, + enteredAt: new Date('2026-01-15'), + exitedAt: new Date('2026-01-31'), + }, + }) + + // Create ProjectStageState: FILTER stage = PENDING (current active stage) + await prisma.projectStageState.create({ + data: { + projectId: project.id, + trackId: mainTrack.id, + stageId: filterStage.id, + state: ProjectStageStateValue.PENDING, + enteredAt: new Date('2026-02-01'), + }, + }) + + projectCount++ + if (projectCount % 50 === 0) { + console.log(` ... ${projectCount} projects created`) + } + } + + console.log(` ✓ Created ${projectCount} projects with stage states`) + } + + // ========================================================================== + // 12. Evaluation Form (for Expert Evaluation stage) + // ========================================================================== + console.log('\n📝 Creating evaluation form...') + + const evaluationStage = mainStages[2] // EVALUATION stage + await prisma.evaluationForm.upsert({ + where: { stageId_version: { stageId: evaluationStage.id, version: 1 } }, + update: {}, + create: { + stageId: evaluationStage.id, + version: 1, + isActive: true, + criteriaJson: [ + { id: 'need_clarity', label: 'Need Clarity', description: 'How clearly is the problem/need articulated?', scale: '1-5', weight: 20, type: 'numeric', required: true }, + { id: 'solution_relevance', label: 'Solution Relevance', description: 'How relevant and innovative is the proposed solution?', scale: '1-5', weight: 25, type: 'numeric', required: true }, + { id: 'ocean_impact', label: 'Ocean Impact', description: 'What is the potential positive impact on ocean conservation?', scale: '1-5', weight: 25, type: 'numeric', required: true }, + { id: 'feasibility', label: 'Feasibility & Scalability', description: 'How feasible and scalable is the project?', scale: '1-5', weight: 20, type: 'numeric', required: true }, + { id: 'team_strength', label: 'Team Strength', description: 'How strong and capable is the team?', scale: '1-5', weight: 10, type: 'numeric', required: true }, + ], + scalesJson: { + '1-5': { min: 1, max: 5, labels: { 1: 'Poor', 2: 'Below Average', 3: 'Average', 4: 'Good', 5: 'Excellent' } }, + }, + }, + }) + console.log(' ✓ Evaluation form created (5 criteria)') + + // ========================================================================== + // 13. Special Awards + // ========================================================================== + console.log('\n🏆 Creating special awards...') + + await prisma.specialAward.upsert({ + where: { trackId: innovationTrack.id }, + update: {}, + create: { + programId: program.id, + name: 'Ocean Innovation Award', + description: 'Recognizes the most innovative technology solution for ocean protection', + status: 'DRAFT', + trackId: innovationTrack.id, + scoringMode: 'PICK_WINNER', + useAiEligibility: true, + criteriaText: 'Projects demonstrating breakthrough technological innovation for ocean conservation', + }, + }) + + await prisma.specialAward.upsert({ + where: { trackId: impactTrack.id }, + update: {}, + create: { + programId: program.id, + name: 'Ocean Impact Award', + description: 'Recognizes the project with highest community and environmental impact', + status: 'DRAFT', + trackId: impactTrack.id, + scoringMode: 'PICK_WINNER', + useAiEligibility: false, + criteriaText: 'Projects with measurable, significant impact on ocean health and coastal communities', + }, + }) + + console.log(' ✓ Ocean Innovation Award → innovation-award track') + console.log(' ✓ Ocean Impact Award → impact-award track') + + // ========================================================================== + // 14. Routing Rules + // ========================================================================== + console.log('\n🔀 Creating routing rules...') + + const existingTechRule = await prisma.routingRule.findFirst({ + where: { pipelineId: pipeline.id, name: 'Route Tech Innovation to Innovation Award' }, + }) + if (!existingTechRule) { + await prisma.routingRule.create({ + data: { + pipelineId: pipeline.id, + name: 'Route Tech Innovation to Innovation Award', + scope: 'global', + destinationTrackId: innovationTrack.id, + predicateJson: { + field: 'oceanIssue', + operator: 'eq', + value: 'TECHNOLOGY_INNOVATION', + }, + priority: 10, + isActive: true, + }, + }) + } + + const existingImpactRule = await prisma.routingRule.findFirst({ + where: { pipelineId: pipeline.id, name: 'Route Community Impact to Impact Award' }, + }) + if (!existingImpactRule) { + await prisma.routingRule.create({ + data: { + pipelineId: pipeline.id, + name: 'Route Community Impact to Impact Award', + scope: 'global', + destinationTrackId: impactTrack.id, + predicateJson: { + or: [ + { field: 'oceanIssue', operator: 'eq', value: 'COMMUNITY_CAPACITY' }, + { field: 'oceanIssue', operator: 'eq', value: 'HABITAT_RESTORATION' }, + ], + }, + priority: 5, + isActive: true, + }, + }) + } + + console.log(' ✓ Tech Innovation → Innovation Award (PARALLEL)') + console.log(' ✓ Community Impact → Impact Award (EXCLUSIVE)') + + // ========================================================================== + // 15. Notification Email Settings + // ========================================================================== + console.log('\n🔔 Creating notification email settings...') + + const notificationSettings = [ + // Team / Applicant notifications + { notificationType: 'APPLICATION_SUBMITTED', category: 'team', label: 'Application Submitted', description: 'When a team submits their application', sendEmail: true }, + { notificationType: 'TEAM_INVITE_RECEIVED', category: 'team', label: 'Team Invitation Received', description: 'When someone is invited to join a team', sendEmail: true }, + { notificationType: 'TEAM_MEMBER_JOINED', category: 'team', label: 'Team Member Joined', description: 'When a new member joins the team', sendEmail: false }, + { notificationType: 'ADVANCED_SEMIFINAL', category: 'team', label: 'Advanced to Semi-Finals', description: 'When a project advances to semi-finals', sendEmail: true }, + { notificationType: 'ADVANCED_FINAL', category: 'team', label: 'Selected as Finalist', description: 'When a project is selected as a finalist', sendEmail: true }, + { notificationType: 'MENTOR_ASSIGNED', category: 'team', label: 'Mentor Assigned', description: 'When a mentor is assigned to the team', sendEmail: true }, + { notificationType: 'NOT_SELECTED', category: 'team', label: 'Not Selected', description: 'When a project is not selected for the next round', sendEmail: true }, + { notificationType: 'FEEDBACK_AVAILABLE', category: 'team', label: 'Feedback Available', description: 'When jury feedback becomes available', sendEmail: true }, + { notificationType: 'WINNER_ANNOUNCEMENT', category: 'team', label: 'Winner Announcement', description: 'When a project wins an award', sendEmail: true }, + // Jury notifications + { notificationType: 'ASSIGNED_TO_PROJECT', category: 'jury', label: 'Assigned to Project', description: 'When a jury member is assigned to a project', sendEmail: true }, + { notificationType: 'BATCH_ASSIGNED', category: 'jury', label: 'Batch Assignment', description: 'When multiple projects are assigned at once', sendEmail: true }, + { notificationType: 'ROUND_NOW_OPEN', category: 'jury', label: 'Round Now Open', description: 'When a round opens for evaluation', sendEmail: true }, + { notificationType: 'REMINDER_24H', category: 'jury', label: 'Reminder (24h)', description: 'Reminder 24 hours before deadline', sendEmail: true }, + { notificationType: 'REMINDER_1H', category: 'jury', label: 'Reminder (1h)', description: 'Urgent reminder 1 hour before deadline', sendEmail: true }, + { notificationType: 'ROUND_CLOSED', category: 'jury', label: 'Round Closed', description: 'When a round closes', sendEmail: false }, + { notificationType: 'AWARD_VOTING_OPEN', category: 'jury', label: 'Award Voting Open', description: 'When special award voting opens', sendEmail: true }, + // Mentor notifications + { notificationType: 'MENTEE_ASSIGNED', category: 'mentor', label: 'Mentee Assigned', description: 'When assigned as mentor to a project', sendEmail: true }, + { notificationType: 'MENTEE_UPLOADED_DOCS', category: 'mentor', label: 'Mentee Documents Updated', description: 'When a mentee uploads new documents', sendEmail: false }, + { notificationType: 'MENTEE_ADVANCED', category: 'mentor', label: 'Mentee Advanced', description: 'When a mentee advances to the next round', sendEmail: true }, + { notificationType: 'MENTEE_FINALIST', category: 'mentor', label: 'Mentee is Finalist', description: 'When a mentee is selected as finalist', sendEmail: true }, + { notificationType: 'MENTEE_WON', category: 'mentor', label: 'Mentee Won', description: 'When a mentee wins an award', sendEmail: true }, + // Observer notifications + { notificationType: 'ROUND_STARTED', category: 'observer', label: 'Round Started', description: 'When a new round begins', sendEmail: false }, + { notificationType: 'ROUND_COMPLETED', category: 'observer', label: 'Round Completed', description: 'When a round is completed', sendEmail: true }, + { notificationType: 'FINALISTS_ANNOUNCED', category: 'observer', label: 'Finalists Announced', description: 'When finalists are announced', sendEmail: true }, + { notificationType: 'WINNERS_ANNOUNCED', category: 'observer', label: 'Winners Announced', description: 'When winners are announced', sendEmail: true }, + // Admin notifications + { notificationType: 'FILTERING_COMPLETE', category: 'admin', label: 'AI Filtering Complete', description: 'When AI filtering job completes', sendEmail: false }, + { notificationType: 'FILTERING_FAILED', category: 'admin', label: 'AI Filtering Failed', description: 'When AI filtering job fails', sendEmail: true }, + { notificationType: 'NEW_APPLICATION', category: 'admin', label: 'New Application', description: 'When a new application is received', sendEmail: false }, + { notificationType: 'SYSTEM_ERROR', category: 'admin', label: 'System Error', description: 'When a system error occurs', sendEmail: true }, + ] + + for (const setting of notificationSettings) { + await prisma.notificationEmailSetting.upsert({ + where: { notificationType: setting.notificationType }, + update: { + category: setting.category, + label: setting.label, + description: setting.description, + }, + create: setting, + }) + } + console.log(` ✓ Created ${notificationSettings.length} notification email settings`) + + // ========================================================================== + // 16. Summary + // ========================================================================== + console.log('\n' + '='.repeat(60)) + console.log('✅ SEEDING COMPLETE') + console.log('='.repeat(60)) + console.log(` + Program: ${program.name} ${program.year} + Pipeline: ${pipeline.name} (${pipeline.slug}) + Tracks: 4 (Main, Innovation Award, Impact Award, People's Choice) + Stages: ${allStages.length} total + Transitions: ${transitionCount} + Projects: ${projectCount} (from CSV) + Users: ${3 + juryMembers.length + mentors.length + observers.length + projectCount} total + - Admin/Staff: 3 + - Jury: ${juryMembers.length} + - Mentors: ${mentors.length} + - Observers: ${observers.length} + - Applicants: ${projectCount} + + Login: matt@monaco-opc.com / 195260Mp! + `) +} + +main() + .catch((e) => { + console.error('❌ Seeding failed:', e) + process.exit(1) + }) + .finally(async () => { + await prisma.$disconnect() + }) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index b4d2c53..61562f8 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,100 +1,100 @@ -#!/bin/bash -# ============================================================================= -# MOPC Platform - First-Time Deployment Script -# ============================================================================= -# Usage: ./scripts/deploy.sh -# Run this once on the Linux VPS to set up the platform. -# The Docker image is built by Gitea CI and pulled from the registry. - -set -e - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PROJECT_DIR="$(dirname "$SCRIPT_DIR")" -DOCKER_DIR="$PROJECT_DIR/docker" - -echo "============================================" -echo " MOPC Platform - Deployment" -echo "============================================" -echo "" - -# 1. Check Docker is available -if ! command -v docker &> /dev/null; then - echo "ERROR: Docker is not installed." - exit 1 -fi - -if ! docker compose version &> /dev/null; then - echo "ERROR: Docker Compose v2 is not available." - exit 1 -fi - -# 2. Check environment file -if [ ! -f "$DOCKER_DIR/.env" ]; then - echo "No .env file found in docker/." - echo "Copying template..." - cp "$DOCKER_DIR/.env.production" "$DOCKER_DIR/.env" - echo "" - echo "IMPORTANT: Edit docker/.env with your production values before continuing." - echo " nano $DOCKER_DIR/.env" - echo "" - exit 1 -fi - -# 3. Load registry URL from env -source "$DOCKER_DIR/.env" -if [ -z "$REGISTRY_URL" ] || [ "$REGISTRY_URL" = "CHANGE_ME" ]; then - echo "ERROR: REGISTRY_URL is not set in docker/.env" - echo "Set it to your Gitea registry URL (e.g. gitea.example.com/your-org)" - exit 1 -fi - -# 4. Log in to container registry -echo "==> Logging in to container registry ($REGISTRY_URL)..." -docker login "$REGISTRY_URL" - -# 5. Create data directories -echo "==> Creating data directories..." -sudo mkdir -p /data/mopc/postgres -sudo chown -R 1000:1000 /data/mopc - -# 6. Pull and start -echo "==> Pulling latest images and starting services..." -cd "$DOCKER_DIR" -docker compose up -d --pull always - -# 7. Wait for health check -echo "==> Waiting for application to start..." -MAX_WAIT=120 -WAITED=0 -while [ $WAITED -lt $MAX_WAIT ]; do - if curl -sf http://localhost:7600/api/health > /dev/null 2>&1; then - echo "" - echo "============================================" - echo " Application is running!" - echo "============================================" - echo "" - echo " URL: http://localhost:7600" - echo " Health: http://localhost:7600/api/health" - echo "" - echo " NEXT STEPS:" - echo " 1. Run the one-time database seed:" - echo " ./scripts/seed.sh" - echo "" - echo " 2. Set up Nginx reverse proxy:" - echo " sudo ln -s $DOCKER_DIR/nginx/mopc-platform.conf /etc/nginx/sites-enabled/" - echo " sudo nginx -t && sudo systemctl reload nginx" - echo "" - echo " 3. Set up SSL:" - echo " sudo certbot --nginx -d portal.monaco-opc.com" - echo "" - exit 0 - fi - sleep 2 - WAITED=$((WAITED + 2)) - printf "." -done - -echo "" -echo "WARNING: Application did not become healthy within ${MAX_WAIT}s." -echo "Check logs: cd $DOCKER_DIR && docker compose logs -f app" -exit 1 +#!/bin/bash +# ============================================================================= +# MOPC Platform - First-Time Deployment Script +# ============================================================================= +# Usage: ./scripts/deploy.sh +# Run this once on the Linux VPS to set up the platform. +# The Docker image is built by Gitea CI and pulled from the registry. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +DOCKER_DIR="$PROJECT_DIR/docker" + +echo "============================================" +echo " MOPC Platform - Deployment" +echo "============================================" +echo "" + +# 1. Check Docker is available +if ! command -v docker &> /dev/null; then + echo "ERROR: Docker is not installed." + exit 1 +fi + +if ! docker compose version &> /dev/null; then + echo "ERROR: Docker Compose v2 is not available." + exit 1 +fi + +# 2. Check environment file +if [ ! -f "$DOCKER_DIR/.env" ]; then + echo "No .env file found in docker/." + echo "Copying template..." + cp "$DOCKER_DIR/.env.production" "$DOCKER_DIR/.env" + echo "" + echo "IMPORTANT: Edit docker/.env with your production values before continuing." + echo " nano $DOCKER_DIR/.env" + echo "" + exit 1 +fi + +# 3. Load registry URL from env +source "$DOCKER_DIR/.env" +if [ -z "$REGISTRY_URL" ] || [ "$REGISTRY_URL" = "CHANGE_ME" ]; then + echo "ERROR: REGISTRY_URL is not set in docker/.env" + echo "Set it to your Gitea registry URL (e.g. gitea.example.com/your-org)" + exit 1 +fi + +# 4. Log in to container registry +echo "==> Logging in to container registry ($REGISTRY_URL)..." +docker login "$REGISTRY_URL" + +# 5. Create data directories +echo "==> Creating data directories..." +sudo mkdir -p /data/mopc/postgres +sudo chown -R 1000:1000 /data/mopc + +# 6. Pull and start +echo "==> Pulling latest images and starting services..." +cd "$DOCKER_DIR" +docker compose up -d --pull always + +# 7. Wait for health check +echo "==> Waiting for application to start..." +MAX_WAIT=120 +WAITED=0 +while [ $WAITED -lt $MAX_WAIT ]; do + if curl -sf http://localhost:7600/api/health > /dev/null 2>&1; then + echo "" + echo "============================================" + echo " Application is running!" + echo "============================================" + echo "" + echo " URL: http://localhost:7600" + echo " Health: http://localhost:7600/api/health" + echo "" + echo " NEXT STEPS:" + echo " 1. Run the one-time database seed:" + echo " ./scripts/seed.sh" + echo "" + echo " 2. Set up Nginx reverse proxy:" + echo " sudo ln -s $DOCKER_DIR/nginx/mopc-platform.conf /etc/nginx/sites-enabled/" + echo " sudo nginx -t && sudo systemctl reload nginx" + echo "" + echo " 3. Set up SSL:" + echo " sudo certbot --nginx -d portal.monaco-opc.com" + echo "" + exit 0 + fi + sleep 2 + WAITED=$((WAITED + 2)) + printf "." +done + +echo "" +echo "WARNING: Application did not become healthy within ${MAX_WAIT}s." +echo "Check logs: cd $DOCKER_DIR && docker compose logs -f app" +exit 1 diff --git a/scripts/update.sh b/scripts/update.sh index 09bc751..ea27820 100644 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -1,45 +1,45 @@ -#!/bin/bash -# ============================================================================= -# MOPC Platform - Update / Redeploy Script -# ============================================================================= -# Usage: ./scripts/update.sh -# Pulls the latest image from the registry and restarts the app. -# PostgreSQL is NOT restarted. - -set -e - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PROJECT_DIR="$(dirname "$SCRIPT_DIR")" -DOCKER_DIR="$PROJECT_DIR/docker" - -echo "============================================" -echo " MOPC Platform - Update" -echo "============================================" -echo "" - -# 1. Pull and recreate app only (postgres stays running) -echo "==> Pulling latest image and recreating app..." -cd "$DOCKER_DIR" -docker compose up -d --pull always --force-recreate app - -# 2. Wait for health check -echo "==> Waiting for application to start..." -MAX_WAIT=120 -WAITED=0 -while [ $WAITED -lt $MAX_WAIT ]; do - if curl -sf http://localhost:7600/api/health > /dev/null 2>&1; then - echo "" - echo "============================================" - echo " Update complete! App is healthy." - echo "============================================" - exit 0 - fi - sleep 2 - WAITED=$((WAITED + 2)) - printf "." -done - -echo "" -echo "WARNING: Application did not become healthy within ${MAX_WAIT}s." -echo "Check logs: cd $DOCKER_DIR && docker compose logs -f app" -exit 1 +#!/bin/bash +# ============================================================================= +# MOPC Platform - Update / Redeploy Script +# ============================================================================= +# Usage: ./scripts/update.sh +# Pulls the latest image from the registry and restarts the app. +# PostgreSQL is NOT restarted. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +DOCKER_DIR="$PROJECT_DIR/docker" + +echo "============================================" +echo " MOPC Platform - Update" +echo "============================================" +echo "" + +# 1. Pull and recreate app only (postgres stays running) +echo "==> Pulling latest image and recreating app..." +cd "$DOCKER_DIR" +docker compose up -d --pull always --force-recreate app + +# 2. Wait for health check +echo "==> Waiting for application to start..." +MAX_WAIT=120 +WAITED=0 +while [ $WAITED -lt $MAX_WAIT ]; do + if curl -sf http://localhost:7600/api/health > /dev/null 2>&1; then + echo "" + echo "============================================" + echo " Update complete! App is healthy." + echo "============================================" + exit 0 + fi + sleep 2 + WAITED=$((WAITED + 2)) + printf "." +done + +echo "" +echo "WARNING: Application did not become healthy within ${MAX_WAIT}s." +echo "Check logs: cd $DOCKER_DIR && docker compose logs -f app" +exit 1 diff --git a/src/app/(admin)/admin/audit/page.tsx b/src/app/(admin)/admin/audit/page.tsx index c4d9045..2d3faab 100644 --- a/src/app/(admin)/admin/audit/page.tsx +++ b/src/app/(admin)/admin/audit/page.tsx @@ -1,750 +1,750 @@ -'use client' - -import { useState, useMemo, useCallback } from 'react' -import { trpc } from '@/lib/trpc/client' -import { Button } from '@/components/ui/button' -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from '@/components/ui/card' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { Badge } from '@/components/ui/badge' -import { Skeleton } from '@/components/ui/skeleton' -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select' -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from '@/components/ui/table' -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from '@/components/ui/collapsible' -import { - Download, - Filter, - ChevronDown, - ChevronUp, - Clock, - User, - Activity, - Database, - Globe, - ChevronLeft, - ChevronRight, - RefreshCw, - RotateCcw, - AlertTriangle, - Layers, - ArrowLeftRight, -} from 'lucide-react' -import { Switch } from '@/components/ui/switch' -import { CsvExportDialog } from '@/components/shared/csv-export-dialog' -import { formatDate } from '@/lib/utils' -import { cn } from '@/lib/utils' - -// Action type options -const ACTION_TYPES = [ - 'CREATE', - 'UPDATE', - 'DELETE', - 'IMPORT', - 'EXPORT', - 'LOGIN', - 'LOGIN_SUCCESS', - 'LOGIN_FAILED', - 'INVITATION_ACCEPTED', - 'SUBMIT_EVALUATION', - 'EVALUATION_SUBMITTED', - 'UPDATE_STATUS', - 'ROUND_ACTIVATED', - 'ROUND_CLOSED', - 'ROUND_ARCHIVED', - 'UPLOAD_FILE', - 'DELETE_FILE', - 'FILE_DOWNLOADED', - 'BULK_CREATE', - 'BULK_UPDATE_STATUS', - 'UPDATE_EVALUATION_FORM', - 'ROLE_CHANGED', - 'PASSWORD_SET', - 'PASSWORD_CHANGED', -] - -// Entity type options -const ENTITY_TYPES = [ - 'User', - 'Program', - 'Round', - 'Project', - 'Assignment', - 'Evaluation', - 'EvaluationForm', - 'ProjectFile', - 'GracePeriod', -] - -// Color map for action types -const actionColors: Record = { - CREATE: 'default', - UPDATE: 'secondary', - DELETE: 'destructive', - IMPORT: 'default', - EXPORT: 'outline', - LOGIN: 'outline', - LOGIN_SUCCESS: 'outline', - LOGIN_FAILED: 'destructive', - INVITATION_ACCEPTED: 'default', - SUBMIT_EVALUATION: 'default', - EVALUATION_SUBMITTED: 'default', - ROUND_ACTIVATED: 'default', - ROUND_CLOSED: 'secondary', - ROUND_ARCHIVED: 'secondary', - FILE_DOWNLOADED: 'outline', - ROLE_CHANGED: 'secondary', - PASSWORD_SET: 'outline', - PASSWORD_CHANGED: 'outline', -} - -export default function AuditLogPage() { - // Filter state - const [filters, setFilters] = useState({ - userId: '', - action: '', - entityType: '', - startDate: '', - endDate: '', - }) - const [page, setPage] = useState(1) - const [expandedRows, setExpandedRows] = useState>(new Set()) - const [showFilters, setShowFilters] = useState(true) - const [groupBySession, setGroupBySession] = useState(false) - - // Build query input - const queryInput = useMemo( - () => ({ - userId: filters.userId || undefined, - action: filters.action || undefined, - entityType: filters.entityType || undefined, - startDate: filters.startDate ? new Date(filters.startDate) : undefined, - endDate: filters.endDate - ? new Date(filters.endDate + 'T23:59:59') - : undefined, - page, - perPage: 50, - }), - [filters, page] - ) - - // Fetch audit logs - const { data, isLoading, refetch } = trpc.audit.list.useQuery(queryInput) - - // Fetch users for filter dropdown - const { data: usersData } = trpc.user.list.useQuery({ - page: 1, - perPage: 100, - }) - - // Fetch anomalies - const { data: anomalyData } = trpc.audit.getAnomalies.useQuery({}, { - retry: false, - }) - - // Export query - const exportLogs = trpc.export.auditLogs.useQuery( - { - userId: filters.userId || undefined, - action: filters.action || undefined, - entityType: filters.entityType || undefined, - startDate: filters.startDate ? new Date(filters.startDate) : undefined, - endDate: filters.endDate - ? new Date(filters.endDate + 'T23:59:59') - : undefined, - }, - { enabled: false } - ) - const [showExportDialog, setShowExportDialog] = useState(false) - - // Handle export - const handleExport = () => { - setShowExportDialog(true) - } - - const handleRequestExportData = useCallback(async () => { - const result = await exportLogs.refetch() - return result.data ?? undefined - }, [exportLogs]) - - // Reset filters - const resetFilters = () => { - setFilters({ - userId: '', - action: '', - entityType: '', - startDate: '', - endDate: '', - }) - setPage(1) - } - - // Toggle row expansion - const toggleRow = (id: string) => { - const newExpanded = new Set(expandedRows) - if (newExpanded.has(id)) { - newExpanded.delete(id) - } else { - newExpanded.add(id) - } - setExpandedRows(newExpanded) - } - - const hasFilters = Object.values(filters).some((v) => v !== '') - - return ( -
- {/* Header */} -
-
-

Audit Logs

-

- View system activity and user actions -

-
-
- - -
-
- - {/* Filters */} - - - - -
-
- - Filters - {hasFilters && ( - - Active - - )} -
- {showFilters ? ( - - ) : ( - - )} -
-
-
- - -
- {/* User Filter */} -
- - -
- - {/* Action Filter */} -
- - -
- - {/* Entity Type Filter */} -
- - -
- - {/* Start Date */} -
- - - setFilters({ ...filters, startDate: e.target.value }) - } - /> -
- - {/* End Date */} -
- - - setFilters({ ...filters, endDate: e.target.value }) - } - /> -
-
- - {hasFilters && ( -
- -
- )} -
-
-
-
- - {/* Anomaly Alerts */} - {anomalyData && anomalyData.anomalies.length > 0 && ( - - - - - Anomaly Alerts ({anomalyData.anomalies.length}) - - - -
- {anomalyData.anomalies.slice(0, 5).map((anomaly, i) => ( -
- -
-

{anomaly.isRapid ? 'Rapid Activity' : 'Bulk Operations'}

-

{String(anomaly.actionCount)} actions in {String(anomaly.timeWindowMinutes)} min ({anomaly.actionsPerMinute.toFixed(1)}/min)

- {anomaly.userId && ( -

- User: {String(anomaly.user?.name || anomaly.userId)} -

- )} -
- - {String(anomaly.actionCount)} actions - -
- ))} -
-
-
- )} - - {/* Session Grouping Toggle */} -
-
- - -
-
- - {/* Results */} - {isLoading ? ( - - ) : data && data.logs.length > 0 ? ( - <> - {/* Desktop Table View */} - - - - - Timestamp - User - Action - Entity - IP Address - - - - - {data.logs.map((log) => { - const isExpanded = expandedRows.has(log.id) - return ( - <> - toggleRow(log.id)} - > - - {formatDate(log.timestamp)} - - -
-

- {log.user?.name || 'System'} -

-

- {log.user?.email} -

-
-
- - - {log.action.replace(/_/g, ' ')} - - - -
-

{log.entityType}

- {log.entityId && ( -

- {log.entityId.slice(0, 8)}... -

- )} -
-
- - {log.ipAddress || '-'} - - - {isExpanded ? ( - - ) : ( - - )} - -
- {isExpanded && ( - - -
-
-
-

- Entity ID -

-

- {log.entityId || 'N/A'} -

-
-
-

- User Agent -

-

- {log.userAgent || 'N/A'} -

-
-
- {log.detailsJson && ( -
-

- Details -

-
-                                    {JSON.stringify(log.detailsJson, null, 2)}
-                                  
-
- )} - {!!(log as Record).previousDataJson && ( -
-

- - Changes (Before / After) -

- ).previousDataJson} - after={log.detailsJson} - /> -
- )} - {groupBySession && !!(log as Record).sessionId && ( -
-

- Session ID -

-

- {String((log as Record).sessionId)} -

-
- )} -
-
-
- )} - - ) - })} -
-
-
- - {/* Mobile Card View */} -
- {data.logs.map((log) => { - const isExpanded = expandedRows.has(log.id) - return ( - toggleRow(log.id)} - > - -
-
- - {log.action.replace(/_/g, ' ')} - - - {log.entityType} - -
- {isExpanded ? ( - - ) : ( - - )} -
-
- -
-
- - - {formatDate(log.timestamp)} - -
-
- - - {log.user?.name || 'System'} - -
-
- - {isExpanded && ( -
-
-

- Entity ID -

-

- {log.entityId || 'N/A'} -

-
-
-

- IP Address -

-

- {log.ipAddress || 'N/A'} -

-
- {log.detailsJson && ( -
-

- Details -

-
-                              {JSON.stringify(log.detailsJson, null, 2)}
-                            
-
- )} -
- )} -
-
- ) - })} -
- - {/* Pagination */} -
-

- Showing {(page - 1) * 50 + 1} to{' '} - {Math.min(page * 50, data.total)} of {data.total} results -

-
- - - Page {page} of {data.totalPages} - - -
-
- - ) : ( - - - -

No audit logs found

-

- {hasFilters - ? 'Try adjusting your filters' - : 'Activity will appear here as users interact with the system'} -

-
-
- )} - - {/* CSV Export Dialog with Column Selection */} - -
- ) -} - -function DiffViewer({ before, after }: { before: unknown; after: unknown }) { - const beforeObj = typeof before === 'object' && before !== null ? before as Record : {} - const afterObj = typeof after === 'object' && after !== null ? after as Record : {} - const allKeys = Array.from(new Set([...Object.keys(beforeObj), ...Object.keys(afterObj)])) - const changedKeys = allKeys.filter( - (key) => JSON.stringify(beforeObj[key]) !== JSON.stringify(afterObj[key]) - ) - - if (changedKeys.length === 0) { - return ( -

No differences detected

- ) - } - - return ( -
-
- Field - Before - After -
- {changedKeys.map((key) => ( -
- {key} - - {beforeObj[key] !== undefined ? JSON.stringify(beforeObj[key]) : '--'} - - - {afterObj[key] !== undefined ? JSON.stringify(afterObj[key]) : '--'} - -
- ))} -
- ) -} - -function AuditLogSkeleton() { - return ( - - -
- {[...Array(10)].map((_, i) => ( -
- - - - - -
- ))} -
-
-
- ) -} +'use client' + +import { useState, useMemo, useCallback } from 'react' +import { trpc } from '@/lib/trpc/client' +import { Button } from '@/components/ui/button' +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { Badge } from '@/components/ui/badge' +import { Skeleton } from '@/components/ui/skeleton' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table' +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from '@/components/ui/collapsible' +import { + Download, + Filter, + ChevronDown, + ChevronUp, + Clock, + User, + Activity, + Database, + Globe, + ChevronLeft, + ChevronRight, + RefreshCw, + RotateCcw, + AlertTriangle, + Layers, + ArrowLeftRight, +} from 'lucide-react' +import { Switch } from '@/components/ui/switch' +import { CsvExportDialog } from '@/components/shared/csv-export-dialog' +import { formatDate } from '@/lib/utils' +import { cn } from '@/lib/utils' + +// Action type options +const ACTION_TYPES = [ + 'CREATE', + 'UPDATE', + 'DELETE', + 'IMPORT', + 'EXPORT', + 'LOGIN', + 'LOGIN_SUCCESS', + 'LOGIN_FAILED', + 'INVITATION_ACCEPTED', + 'SUBMIT_EVALUATION', + 'EVALUATION_SUBMITTED', + 'UPDATE_STATUS', + 'ROUND_ACTIVATED', + 'ROUND_CLOSED', + 'ROUND_ARCHIVED', + 'UPLOAD_FILE', + 'DELETE_FILE', + 'FILE_DOWNLOADED', + 'BULK_CREATE', + 'BULK_UPDATE_STATUS', + 'UPDATE_EVALUATION_FORM', + 'ROLE_CHANGED', + 'PASSWORD_SET', + 'PASSWORD_CHANGED', +] + +// Entity type options +const ENTITY_TYPES = [ + 'User', + 'Program', + 'Round', + 'Project', + 'Assignment', + 'Evaluation', + 'EvaluationForm', + 'ProjectFile', + 'GracePeriod', +] + +// Color map for action types +const actionColors: Record = { + CREATE: 'default', + UPDATE: 'secondary', + DELETE: 'destructive', + IMPORT: 'default', + EXPORT: 'outline', + LOGIN: 'outline', + LOGIN_SUCCESS: 'outline', + LOGIN_FAILED: 'destructive', + INVITATION_ACCEPTED: 'default', + SUBMIT_EVALUATION: 'default', + EVALUATION_SUBMITTED: 'default', + ROUND_ACTIVATED: 'default', + ROUND_CLOSED: 'secondary', + ROUND_ARCHIVED: 'secondary', + FILE_DOWNLOADED: 'outline', + ROLE_CHANGED: 'secondary', + PASSWORD_SET: 'outline', + PASSWORD_CHANGED: 'outline', +} + +export default function AuditLogPage() { + // Filter state + const [filters, setFilters] = useState({ + userId: '', + action: '', + entityType: '', + startDate: '', + endDate: '', + }) + const [page, setPage] = useState(1) + const [expandedRows, setExpandedRows] = useState>(new Set()) + const [showFilters, setShowFilters] = useState(true) + const [groupBySession, setGroupBySession] = useState(false) + + // Build query input + const queryInput = useMemo( + () => ({ + userId: filters.userId || undefined, + action: filters.action || undefined, + entityType: filters.entityType || undefined, + startDate: filters.startDate ? new Date(filters.startDate) : undefined, + endDate: filters.endDate + ? new Date(filters.endDate + 'T23:59:59') + : undefined, + page, + perPage: 50, + }), + [filters, page] + ) + + // Fetch audit logs + const { data, isLoading, refetch } = trpc.audit.list.useQuery(queryInput) + + // Fetch users for filter dropdown + const { data: usersData } = trpc.user.list.useQuery({ + page: 1, + perPage: 100, + }) + + // Fetch anomalies + const { data: anomalyData } = trpc.audit.getAnomalies.useQuery({}, { + retry: false, + }) + + // Export query + const exportLogs = trpc.export.auditLogs.useQuery( + { + userId: filters.userId || undefined, + action: filters.action || undefined, + entityType: filters.entityType || undefined, + startDate: filters.startDate ? new Date(filters.startDate) : undefined, + endDate: filters.endDate + ? new Date(filters.endDate + 'T23:59:59') + : undefined, + }, + { enabled: false } + ) + const [showExportDialog, setShowExportDialog] = useState(false) + + // Handle export + const handleExport = () => { + setShowExportDialog(true) + } + + const handleRequestExportData = useCallback(async () => { + const result = await exportLogs.refetch() + return result.data ?? undefined + }, [exportLogs]) + + // Reset filters + const resetFilters = () => { + setFilters({ + userId: '', + action: '', + entityType: '', + startDate: '', + endDate: '', + }) + setPage(1) + } + + // Toggle row expansion + const toggleRow = (id: string) => { + const newExpanded = new Set(expandedRows) + if (newExpanded.has(id)) { + newExpanded.delete(id) + } else { + newExpanded.add(id) + } + setExpandedRows(newExpanded) + } + + const hasFilters = Object.values(filters).some((v) => v !== '') + + return ( +
+ {/* Header */} +
+
+

Audit Logs

+

+ View system activity and user actions +

+
+
+ + +
+
+ + {/* Filters */} + + + + +
+
+ + Filters + {hasFilters && ( + + Active + + )} +
+ {showFilters ? ( + + ) : ( + + )} +
+
+
+ + +
+ {/* User Filter */} +
+ + +
+ + {/* Action Filter */} +
+ + +
+ + {/* Entity Type Filter */} +
+ + +
+ + {/* Start Date */} +
+ + + setFilters({ ...filters, startDate: e.target.value }) + } + /> +
+ + {/* End Date */} +
+ + + setFilters({ ...filters, endDate: e.target.value }) + } + /> +
+
+ + {hasFilters && ( +
+ +
+ )} +
+
+
+
+ + {/* Anomaly Alerts */} + {anomalyData && anomalyData.anomalies.length > 0 && ( + + + + + Anomaly Alerts ({anomalyData.anomalies.length}) + + + +
+ {anomalyData.anomalies.slice(0, 5).map((anomaly, i) => ( +
+ +
+

{anomaly.isRapid ? 'Rapid Activity' : 'Bulk Operations'}

+

{String(anomaly.actionCount)} actions in {String(anomaly.timeWindowMinutes)} min ({anomaly.actionsPerMinute.toFixed(1)}/min)

+ {anomaly.userId && ( +

+ User: {String(anomaly.user?.name || anomaly.userId)} +

+ )} +
+ + {String(anomaly.actionCount)} actions + +
+ ))} +
+
+
+ )} + + {/* Session Grouping Toggle */} +
+
+ + +
+
+ + {/* Results */} + {isLoading ? ( + + ) : data && data.logs.length > 0 ? ( + <> + {/* Desktop Table View */} + + + + + Timestamp + User + Action + Entity + IP Address + + + + + {data.logs.map((log) => { + const isExpanded = expandedRows.has(log.id) + return ( + <> + toggleRow(log.id)} + > + + {formatDate(log.timestamp)} + + +
+

+ {log.user?.name || 'System'} +

+

+ {log.user?.email} +

+
+
+ + + {log.action.replace(/_/g, ' ')} + + + +
+

{log.entityType}

+ {log.entityId && ( +

+ {log.entityId.slice(0, 8)}... +

+ )} +
+
+ + {log.ipAddress || '-'} + + + {isExpanded ? ( + + ) : ( + + )} + +
+ {isExpanded && ( + + +
+
+
+

+ Entity ID +

+

+ {log.entityId || 'N/A'} +

+
+
+

+ User Agent +

+

+ {log.userAgent || 'N/A'} +

+
+
+ {log.detailsJson && ( +
+

+ Details +

+
+                                    {JSON.stringify(log.detailsJson, null, 2)}
+                                  
+
+ )} + {!!(log as Record).previousDataJson && ( +
+

+ + Changes (Before / After) +

+ ).previousDataJson} + after={log.detailsJson} + /> +
+ )} + {groupBySession && !!(log as Record).sessionId && ( +
+

+ Session ID +

+

+ {String((log as Record).sessionId)} +

+
+ )} +
+
+
+ )} + + ) + })} +
+
+
+ + {/* Mobile Card View */} +
+ {data.logs.map((log) => { + const isExpanded = expandedRows.has(log.id) + return ( + toggleRow(log.id)} + > + +
+
+ + {log.action.replace(/_/g, ' ')} + + + {log.entityType} + +
+ {isExpanded ? ( + + ) : ( + + )} +
+
+ +
+
+ + + {formatDate(log.timestamp)} + +
+
+ + + {log.user?.name || 'System'} + +
+
+ + {isExpanded && ( +
+
+

+ Entity ID +

+

+ {log.entityId || 'N/A'} +

+
+
+

+ IP Address +

+

+ {log.ipAddress || 'N/A'} +

+
+ {log.detailsJson && ( +
+

+ Details +

+
+                              {JSON.stringify(log.detailsJson, null, 2)}
+                            
+
+ )} +
+ )} +
+
+ ) + })} +
+ + {/* Pagination */} +
+

+ Showing {(page - 1) * 50 + 1} to{' '} + {Math.min(page * 50, data.total)} of {data.total} results +

+
+ + + Page {page} of {data.totalPages} + + +
+
+ + ) : ( + + + +

No audit logs found

+

+ {hasFilters + ? 'Try adjusting your filters' + : 'Activity will appear here as users interact with the system'} +

+
+
+ )} + + {/* CSV Export Dialog with Column Selection */} + +
+ ) +} + +function DiffViewer({ before, after }: { before: unknown; after: unknown }) { + const beforeObj = typeof before === 'object' && before !== null ? before as Record : {} + const afterObj = typeof after === 'object' && after !== null ? after as Record : {} + const allKeys = Array.from(new Set([...Object.keys(beforeObj), ...Object.keys(afterObj)])) + const changedKeys = allKeys.filter( + (key) => JSON.stringify(beforeObj[key]) !== JSON.stringify(afterObj[key]) + ) + + if (changedKeys.length === 0) { + return ( +

No differences detected

+ ) + } + + return ( +
+
+ Field + Before + After +
+ {changedKeys.map((key) => ( +
+ {key} + + {beforeObj[key] !== undefined ? JSON.stringify(beforeObj[key]) : '--'} + + + {afterObj[key] !== undefined ? JSON.stringify(afterObj[key]) : '--'} + +
+ ))} +
+ ) +} + +function AuditLogSkeleton() { + return ( + + +
+ {[...Array(10)].map((_, i) => ( +
+ + + + + +
+ ))} +
+
+
+ ) +} diff --git a/src/app/(admin)/admin/awards/[id]/edit/page.tsx b/src/app/(admin)/admin/awards/[id]/edit/page.tsx index 5826cb0..207d5cd 100644 --- a/src/app/(admin)/admin/awards/[id]/edit/page.tsx +++ b/src/app/(admin)/admin/awards/[id]/edit/page.tsx @@ -1,291 +1,291 @@ -'use client' - -import { use, useState, useEffect } from 'react' -import Link from 'next/link' -import { useRouter } from 'next/navigation' -import { trpc } from '@/lib/trpc/client' -import { Button } from '@/components/ui/button' -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from '@/components/ui/card' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { Textarea } from '@/components/ui/textarea' -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select' -import { Switch } from '@/components/ui/switch' -import { Skeleton } from '@/components/ui/skeleton' -import { toast } from 'sonner' -import { ArrowLeft, Save, Loader2 } from 'lucide-react' - -export default function EditAwardPage({ - params, -}: { - params: Promise<{ id: string }> -}) { - const { id: awardId } = use(params) - const router = useRouter() - - const utils = trpc.useUtils() - const { data: award, isLoading } = trpc.specialAward.get.useQuery({ id: awardId }) - const updateAward = trpc.specialAward.update.useMutation({ - onSuccess: () => { - utils.specialAward.get.invalidate({ id: awardId }) - utils.specialAward.list.invalidate() - }, - }) - - const [name, setName] = useState('') - const [description, setDescription] = useState('') - const [criteriaText, setCriteriaText] = useState('') - const [scoringMode, setScoringMode] = useState<'PICK_WINNER' | 'RANKED' | 'SCORED'>('PICK_WINNER') - const [useAiEligibility, setUseAiEligibility] = useState(true) - const [maxRankedPicks, setMaxRankedPicks] = useState('3') - const [votingStartAt, setVotingStartAt] = useState('') - const [votingEndAt, setVotingEndAt] = useState('') - - // Helper to format date for datetime-local input - const formatDateForInput = (date: Date | string | null | undefined): string => { - if (!date) return '' - const d = new Date(date) - // Format: YYYY-MM-DDTHH:mm - return d.toISOString().slice(0, 16) - } - - // Load existing values when award data arrives - useEffect(() => { - if (award) { - setName(award.name) - setDescription(award.description || '') - setCriteriaText(award.criteriaText || '') - setScoringMode(award.scoringMode as 'PICK_WINNER' | 'RANKED' | 'SCORED') - setUseAiEligibility(award.useAiEligibility) - setMaxRankedPicks(String(award.maxRankedPicks || 3)) - setVotingStartAt(formatDateForInput(award.votingStartAt)) - setVotingEndAt(formatDateForInput(award.votingEndAt)) - } - }, [award]) - - const handleSubmit = async () => { - if (!name.trim()) return - try { - await updateAward.mutateAsync({ - id: awardId, - name: name.trim(), - description: description.trim() || undefined, - criteriaText: criteriaText.trim() || undefined, - useAiEligibility, - scoringMode, - maxRankedPicks: scoringMode === 'RANKED' ? parseInt(maxRankedPicks) : undefined, - votingStartAt: votingStartAt ? new Date(votingStartAt) : undefined, - votingEndAt: votingEndAt ? new Date(votingEndAt) : undefined, - }) - toast.success('Award updated') - router.push(`/admin/awards/${awardId}`) - } catch (error) { - toast.error( - error instanceof Error ? error.message : 'Failed to update award' - ) - } - } - - if (isLoading) { - return ( -
- - -
- ) - } - - if (!award) return null - - return ( -
-
- -
- -
-

- Edit Award -

-

- Update award settings and eligibility criteria -

-
- - - - Award Details - - Configure the award name, criteria, and scoring mode - - - -
- - setName(e.target.value)} - placeholder="e.g., Mediterranean Entrepreneurship Award" - /> -
- -
- -