From 7dc7cffa2bc7b53663e03f4f33a3effef0cfd78b Mon Sep 17 00:00:00 2001 From: evenif99 Date: Wed, 10 Jun 2026 12:40:37 +0900 Subject: [PATCH 01/12] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 98e88e9..ef77b3f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ -# FRONTEND +# AI-CONFLICT-JUDGE + 추후 수정 From 7a00e9e498a03aaac66b137930ea7032706f84c1 Mon Sep 17 00:00:00 2001 From: evenif99 Date: Mon, 15 Jun 2026 13:13:34 +0900 Subject: [PATCH 02/12] =?UTF-8?q?fix:=20update=20README=20to=20match=20pro?= =?UTF-8?q?ject=20(=EB=A7=90=ED=95=B4=EB=B6=80=EC=97=89)=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ef77b3f..896f916 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,39 @@ -# AI-CONFLICT-JUDGE +# 말해부엉 -추후 수정 +AI 갈등 조정 판결 서비스 + +## 기술 스택 + +- Next.js 15, React 19, TypeScript +- Prisma + PostgreSQL +- Google Gemini API +- NextAuth (Kakao OAuth) +- Zustand, TanStack Query, React Hook Form, Zod +- SCSS Module, Recharts, html-to-image + +## 로컬 실행 + +```bash +# 의존성 설치 +npm install + +# 개발 서버 실행 (port 3030) +npm run dev + +# Mock 서버 실행 (port 8081) +npm run mock +``` + +## 환경변수 + +환경변수 key는 `.env.example`을 기준으로 확인합니다. + +실제 값은 Git에 커밋하지 않습니다. + +배포 환경변수는 Vercel Dashboard의 Project Settings > Environment Variables에서 관리합니다. + +GitHub Actions로 Vercel CLI 배포를 사용하는 경우, `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`는 GitHub Repository Secrets에 등록합니다. + +`.env.local`은 로컬에서만 사용하며 Git에 포함하지 않습니다. + +상세 내용은 [`docs/guides/ENV_GUIDE.md`](docs/guides/ENV_GUIDE.md) 및 [`docs/guides/VERCEL_DEPLOYMENT_GUIDE.md`](docs/guides/VERCEL_DEPLOYMENT_GUIDE.md)를 참고하세요. From ee3297f72a7048cead946a552e98bfc02aab2846 Mon Sep 17 00:00:00 2001 From: evenif99 Date: Mon, 15 Jun 2026 13:16:19 +0900 Subject: [PATCH 03/12] =?UTF-8?q?[Release]=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85=20=EB=B0=8F=20=EB=AC=B8=EC=84=9C=ED=99=94=20?= =?UTF-8?q?dev=20=E2=86=92=20main=20(#19)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: initialize project folder structure (#1) * chore: initialize project folder structure - Add base directory layout for Next.js + domain-driven architecture - Add .gitkeep to track empty directories in git - Exclude MVP out-of-scope domains (shop, points, user-items) - No implementation files included, structure only Co-Authored-By: Claude Sonnet 4.6 * Update README.md --------- Co-authored-by: Claude Sonnet 4.6 * docs: add CLAUDE.md with project rules and work guidelines (#2) - Add project overview and MVP scope definition - Add fixed product rules (categories, AI chat policy, judgement output) - Add architecture, domain scope, and state transition rules - Add auth/security, DB, frontend state, API, logging rules - Add Git workflow, Claude work process, STOP conditions - Add approval-required list and required reference documents Co-authored-by: Claude Sonnet 4.6 * infra: setup project config and install dependencies (#3) - Add package.json with Next.js 15, React 19, TypeScript stack - Add next.config.ts (minimal Next.js 15 config) - Add tsconfig.json (strict mode, @/* path alias) - Add eslint.config.mjs (next/core-web-vitals + next/typescript) - Add .prettierrc and .prettierignore - Add .gitignore (node_modules, .next, .env.local, etc.) - Add .env.example (key names only, no real values) - Add prisma/schema.prisma (generator + datasource only) - Add data/mock/db.json (health check stub for json-server) - Add docs/TECH_STACK.md (package list and selection rationale) - Update README.md with run commands and env guide Co-authored-by: Claude Sonnet 4.6 * docs: add base documentation structure (#4) - Add PROJECT_DECISIONS.md (MVP scope, architecture, security principles) - Add guides/CLAUDE_WORKFLOW.md (work process, STOP conditions, approval rules) - Add guides/GIT_WORKFLOW.md (branch naming, commit convention, workflow) - Add guides/PR_RULES.md (PR target, title rules, review criteria) - Add guides/ENV_GUIDE.md (Vercel env pull, .env.example management) - Add guides/CODING_CONVENTION.md (naming, state management, folder rules) - Add db/STATUS_TRANSITION.md (room_mode, dispute_status transitions) - Add db/PRISMA_MAPPING.md (snake_case/camelCase mapping rules) - Add db/MASTER_DATA.md (categories, result types, DB master principles) - Add domains/README.md (domain list, MVP scope, writing guidelines) - Add domains/_DOMAIN_TEMPLATE.md (template for domain docs) Co-authored-by: Claude Sonnet 4.6 * docs: add domain document drafts for all MVP domains (#5) - Add AUTH.md (kakao login, terms, session management) - Add COMMON.md (error handling, logging, common response) - Add ROOM.md (AI chat room, invite link, room_mode transitions) - Add PERSONAL_ANALYSIS.md (AI-based personal conflict analysis) - Add DISPUTE.md (1:1 mediation, roles, statements, dispute_status) - Add JUDGEMENT.md (AI judgement, Gemini API, result card) - Add GIFT.md (gift recommendation after judgement) - Add USER.md (mypage, profile, bottom tab) - Add CALENDAR.md (date-based record marking, monthly summary) - Add DIARY.md (emotion diary, author-only access, content protection) - Add STATISTICS.md (anonymous aggregation, summary components) - Add SHOP_FUTURE.md (v2.0 planned, MVP excluded) - Add POINTS_FUTURE.md (v2.0 planned, MVP excluded) - Add USER_ITEMS_FUTURE.md (v2.0 planned, MVP excluded) All documents are draft templates with TODO markers for assignees. No implementation, no API routes, no schema changes. Co-authored-by: Claude Sonnet 4.6 * infra: add Next.js App Router entry files and SCSS base structure (#6) - Add src/app/layout.tsx (root layout with metadata and globals.scss import) - Add src/app/page.tsx (minimal root page for build verification) - Add src/app/globals.scss (imports src/styles/main.scss) - Add src/app/error.tsx (minimal error boundary with reset) - Add src/app/not-found.tsx (minimal 404 page) - Add src/app/loading.tsx (minimal loading page) - Add src/styles/main.scss (ordered SCSS entry point) - Add src/styles/abstracts/_variables.scss (color, typography, spacing tokens) - Add src/styles/abstracts/_mixins.scss (flex-center, respond-to breakpoints) - Add src/styles/base/_reset.scss (box-sizing, margin, button, img reset) - Add src/styles/base/_global.scss (body font, background, color defaults) - Add src/styles/layout/_page.scss (placeholder for page layout) Verified: type-check, lint, build all pass Co-authored-by: Claude Sonnet 4.6 * Infra/init next setup (#7) * infra: add Next.js App Router entry files and SCSS base structure - Add src/app/layout.tsx (root layout with metadata and globals.scss import) - Add src/app/page.tsx (minimal root page for build verification) - Add src/app/globals.scss (imports src/styles/main.scss) - Add src/app/error.tsx (minimal error boundary with reset) - Add src/app/not-found.tsx (minimal 404 page) - Add src/app/loading.tsx (minimal loading page) - Add src/styles/main.scss (ordered SCSS entry point) - Add src/styles/abstracts/_variables.scss (color, typography, spacing tokens) - Add src/styles/abstracts/_mixins.scss (flex-center, respond-to breakpoints) - Add src/styles/base/_reset.scss (box-sizing, margin, button, img reset) - Add src/styles/base/_global.scss (body font, background, color defaults) - Add src/styles/layout/_page.scss (placeholder for page layout) Verified: type-check, lint, build all pass Co-Authored-By: Claude Sonnet 4.6 * fix: resolve ESLint and TypeScript config warnings - eslint.config.mjs: ignore next-env.d.ts and .next/** (auto-generated by Next.js, triple-slash reference false positive) - tsconfig.json: remove deprecated baseUrl option (TypeScript 5.x+, paths works without baseUrl) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * Update README.md (#8) * docs(infra): confirm Supabase as project infrastructure (#9) * chore(github): add collaboration templates and policy (#10) * docs(env): document environment variable management (#11) * docs(calendar): confirm MUI date picker usage (#12) 달력 UI 라이브러리로 MUI X Date Pickers + Day.js 사용을 확정하고 관련 문서(TECH_STACK, PROJECT_DECISIONS, CODING_CONVENTION, CALENDAR, DIARY, CLAUDE.md)에 반영한다. * chore(deps): install MUI X Date Pickers and peer dependencies (#13) 달력 UI 구현을 위해 MUI X Date Pickers 및 필수 peer dependency를 설치한다. @mui/material@9.1.1, @emotion/react@11.14.0, @emotion/styled@11.14.1, @mui/x-date-pickers@9.5.0, dayjs@1.11.21 * Update README.md (#15) --------- Co-authored-by: Claude Sonnet 4.6 --- .env.example | 30 + .github/.gitkeep | 0 .github/ISSUE_TEMPLATE/.gitkeep | 0 .github/ISSUE_TEMPLATE/bug.md | 69 + .github/ISSUE_TEMPLATE/config.yml | 2 + .github/ISSUE_TEMPLATE/docs.md | 36 + .github/ISSUE_TEMPLATE/feature.md | 57 + .github/pull_request_template.md | 78 + .gitignore | 32 + .prettierignore | 7 + .prettierrc | 7 + CLAUDE.md | 540 ++ data/.gitkeep | 0 data/mock/.gitkeep | 0 data/mock/db.json | 8 + docs/.gitkeep | 0 docs/INFRA.md | 185 + docs/PROJECT_DECISIONS.md | 232 + docs/TECH_STACK.md | 161 + docs/db/.gitkeep | 0 docs/db/MASTER_DATA.md | 70 + docs/db/PRISMA_MAPPING.md | 73 + docs/db/STATUS_TRANSITION.md | 97 + docs/domains/.gitkeep | 0 docs/domains/AUTH.md | 144 + docs/domains/CALENDAR.md | 162 + docs/domains/COMMON.md | 141 + docs/domains/DIARY.md | 143 + docs/domains/DISPUTE.md | 186 + docs/domains/GIFT.md | 130 + docs/domains/JUDGEMENT.md | 179 + docs/domains/PERSONAL_ANALYSIS.md | 126 + docs/domains/POINTS_FUTURE.md | 39 + docs/domains/README.md | 69 + docs/domains/ROOM.md | 164 + docs/domains/SHOP_FUTURE.md | 39 + docs/domains/STATISTICS.md | 142 + docs/domains/USER.md | 137 + docs/domains/USER_ITEMS_FUTURE.md | 38 + docs/domains/_DOMAIN_TEMPLATE.md | 140 + docs/guides/.gitkeep | 0 docs/guides/CLAUDE_WORKFLOW.md | 99 + docs/guides/CODING_CONVENTION.md | 120 + docs/guides/ENV_GUIDE.md | 219 + docs/guides/GITHUB_COLLABORATION_POLICY.md | 466 + docs/guides/GIT_WORKFLOW.md | 141 + docs/guides/PR_RULES.md | 117 + docs/guides/VERCEL_DEPLOYMENT_GUIDE.md | 278 + eslint.config.mjs | 17 + next-env.d.ts | 6 + next.config.ts | 5 + package-lock.json | 9102 ++++++++++++++++++ package.json | 50 + prisma/.gitkeep | 0 prisma/schema.prisma | 8 + public/.gitkeep | 0 public/images/.gitkeep | 0 public/images/backgrounds/.gitkeep | 0 public/images/characters/.gitkeep | 0 public/images/icons/.gitkeep | 0 public/images/result-card-templates/.gitkeep | 0 src/.gitkeep | 0 src/app/.gitkeep | 0 src/app/api/.gitkeep | 0 src/app/api/auth/.gitkeep | 0 src/app/api/v1/.gitkeep | 0 src/app/error.tsx | 15 + src/app/globals.scss | 1 + src/app/layout.tsx | 19 + src/app/loading.tsx | 7 + src/app/not-found.tsx | 7 + src/app/page.tsx | 8 + src/app/page/.gitkeep | 0 src/app/page/calendar/.gitkeep | 0 src/app/page/diary/.gitkeep | 0 src/app/page/disputes/.gitkeep | 0 src/app/page/home/.gitkeep | 0 src/app/page/join/.gitkeep | 0 src/app/page/landing/.gitkeep | 0 src/app/page/login/.gitkeep | 0 src/app/page/mypage/.gitkeep | 0 src/app/page/personal-analyses/.gitkeep | 0 src/app/page/rooms/.gitkeep | 0 src/app/page/terms/.gitkeep | 0 src/components/.gitkeep | 0 src/components/feedback/.gitkeep | 0 src/components/layout/.gitkeep | 0 src/components/ui/.gitkeep | 0 src/domains/.gitkeep | 0 src/domains/auth/.gitkeep | 0 src/domains/calendar/.gitkeep | 0 src/domains/common/.gitkeep | 0 src/domains/diary/.gitkeep | 0 src/domains/dispute/.gitkeep | 0 src/domains/gift/.gitkeep | 0 src/domains/judgement/.gitkeep | 0 src/domains/personal-analysis/.gitkeep | 0 src/domains/room/.gitkeep | 0 src/domains/statistics/.gitkeep | 0 src/domains/user/.gitkeep | 0 src/lib/.gitkeep | 0 src/lib/ai/.gitkeep | 0 src/lib/api/.gitkeep | 0 src/lib/auth/.gitkeep | 0 src/lib/constants/.gitkeep | 0 src/lib/db/.gitkeep | 0 src/lib/security/.gitkeep | 0 src/lib/utils/.gitkeep | 0 src/lib/validators/.gitkeep | 0 src/stores/.gitkeep | 0 src/styles/.gitkeep | 0 src/styles/abstracts/.gitkeep | 0 src/styles/abstracts/_mixins.scss | 17 + src/styles/abstracts/_variables.scss | 10 + src/styles/base/.gitkeep | 0 src/styles/base/_global.scss | 10 + src/styles/base/_reset.scss | 28 + src/styles/layout/.gitkeep | 0 src/styles/layout/_page.scss | 2 + src/styles/main.scss | 5 + src/types/.gitkeep | 0 tsconfig.json | 27 + 122 files changed, 14447 insertions(+) create mode 100644 .env.example create mode 100644 .github/.gitkeep create mode 100644 .github/ISSUE_TEMPLATE/.gitkeep create mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/docs.md create mode 100644 .github/ISSUE_TEMPLATE/feature.md create mode 100644 .github/pull_request_template.md create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 CLAUDE.md create mode 100644 data/.gitkeep create mode 100644 data/mock/.gitkeep create mode 100644 data/mock/db.json create mode 100644 docs/.gitkeep create mode 100644 docs/INFRA.md create mode 100644 docs/PROJECT_DECISIONS.md create mode 100644 docs/TECH_STACK.md create mode 100644 docs/db/.gitkeep create mode 100644 docs/db/MASTER_DATA.md create mode 100644 docs/db/PRISMA_MAPPING.md create mode 100644 docs/db/STATUS_TRANSITION.md create mode 100644 docs/domains/.gitkeep create mode 100644 docs/domains/AUTH.md create mode 100644 docs/domains/CALENDAR.md create mode 100644 docs/domains/COMMON.md create mode 100644 docs/domains/DIARY.md create mode 100644 docs/domains/DISPUTE.md create mode 100644 docs/domains/GIFT.md create mode 100644 docs/domains/JUDGEMENT.md create mode 100644 docs/domains/PERSONAL_ANALYSIS.md create mode 100644 docs/domains/POINTS_FUTURE.md create mode 100644 docs/domains/README.md create mode 100644 docs/domains/ROOM.md create mode 100644 docs/domains/SHOP_FUTURE.md create mode 100644 docs/domains/STATISTICS.md create mode 100644 docs/domains/USER.md create mode 100644 docs/domains/USER_ITEMS_FUTURE.md create mode 100644 docs/domains/_DOMAIN_TEMPLATE.md create mode 100644 docs/guides/.gitkeep create mode 100644 docs/guides/CLAUDE_WORKFLOW.md create mode 100644 docs/guides/CODING_CONVENTION.md create mode 100644 docs/guides/ENV_GUIDE.md create mode 100644 docs/guides/GITHUB_COLLABORATION_POLICY.md create mode 100644 docs/guides/GIT_WORKFLOW.md create mode 100644 docs/guides/PR_RULES.md create mode 100644 docs/guides/VERCEL_DEPLOYMENT_GUIDE.md create mode 100644 eslint.config.mjs create mode 100644 next-env.d.ts create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 prisma/.gitkeep create mode 100644 prisma/schema.prisma create mode 100644 public/.gitkeep create mode 100644 public/images/.gitkeep create mode 100644 public/images/backgrounds/.gitkeep create mode 100644 public/images/characters/.gitkeep create mode 100644 public/images/icons/.gitkeep create mode 100644 public/images/result-card-templates/.gitkeep create mode 100644 src/.gitkeep create mode 100644 src/app/.gitkeep create mode 100644 src/app/api/.gitkeep create mode 100644 src/app/api/auth/.gitkeep create mode 100644 src/app/api/v1/.gitkeep create mode 100644 src/app/error.tsx create mode 100644 src/app/globals.scss create mode 100644 src/app/layout.tsx create mode 100644 src/app/loading.tsx create mode 100644 src/app/not-found.tsx create mode 100644 src/app/page.tsx create mode 100644 src/app/page/.gitkeep create mode 100644 src/app/page/calendar/.gitkeep create mode 100644 src/app/page/diary/.gitkeep create mode 100644 src/app/page/disputes/.gitkeep create mode 100644 src/app/page/home/.gitkeep create mode 100644 src/app/page/join/.gitkeep create mode 100644 src/app/page/landing/.gitkeep create mode 100644 src/app/page/login/.gitkeep create mode 100644 src/app/page/mypage/.gitkeep create mode 100644 src/app/page/personal-analyses/.gitkeep create mode 100644 src/app/page/rooms/.gitkeep create mode 100644 src/app/page/terms/.gitkeep create mode 100644 src/components/.gitkeep create mode 100644 src/components/feedback/.gitkeep create mode 100644 src/components/layout/.gitkeep create mode 100644 src/components/ui/.gitkeep create mode 100644 src/domains/.gitkeep create mode 100644 src/domains/auth/.gitkeep create mode 100644 src/domains/calendar/.gitkeep create mode 100644 src/domains/common/.gitkeep create mode 100644 src/domains/diary/.gitkeep create mode 100644 src/domains/dispute/.gitkeep create mode 100644 src/domains/gift/.gitkeep create mode 100644 src/domains/judgement/.gitkeep create mode 100644 src/domains/personal-analysis/.gitkeep create mode 100644 src/domains/room/.gitkeep create mode 100644 src/domains/statistics/.gitkeep create mode 100644 src/domains/user/.gitkeep create mode 100644 src/lib/.gitkeep create mode 100644 src/lib/ai/.gitkeep create mode 100644 src/lib/api/.gitkeep create mode 100644 src/lib/auth/.gitkeep create mode 100644 src/lib/constants/.gitkeep create mode 100644 src/lib/db/.gitkeep create mode 100644 src/lib/security/.gitkeep create mode 100644 src/lib/utils/.gitkeep create mode 100644 src/lib/validators/.gitkeep create mode 100644 src/stores/.gitkeep create mode 100644 src/styles/.gitkeep create mode 100644 src/styles/abstracts/.gitkeep create mode 100644 src/styles/abstracts/_mixins.scss create mode 100644 src/styles/abstracts/_variables.scss create mode 100644 src/styles/base/.gitkeep create mode 100644 src/styles/base/_global.scss create mode 100644 src/styles/base/_reset.scss create mode 100644 src/styles/layout/.gitkeep create mode 100644 src/styles/layout/_page.scss create mode 100644 src/styles/main.scss create mode 100644 src/types/.gitkeep create mode 100644 tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..aa938cc --- /dev/null +++ b/.env.example @@ -0,0 +1,30 @@ +# App +NEXT_PUBLIC_APP_URL= +NEXT_PUBLIC_SITE_NAME= + +# NextAuth +NEXTAUTH_URL= +NEXTAUTH_SECRET= + +# Kakao OAuth +KAKAO_CLIENT_ID= +KAKAO_CLIENT_SECRET= + +# Database (Supabase Postgres) +DATABASE_URL= + +# Supabase +SUPABASE_URL= +SUPABASE_ANON_KEY= +SUPABASE_SERVICE_ROLE_KEY= +SUPABASE_STORAGE_BUCKET_RESULT_CARDS= + +# Gemini +GEMINI_API_KEY= + +# Security +ROOM_TOKEN_SECRET= +CRON_SECRET= + +# Mock Server +NEXT_PUBLIC_MOCK_API_URL= diff --git a/.github/.gitkeep b/.github/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.github/ISSUE_TEMPLATE/.gitkeep b/.github/ISSUE_TEMPLATE/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..4c28dfd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,69 @@ +--- +name: "[Bug] 버그 수정" +about: 버그 수정 Issue +title: "[Bug] " +labels: fix +assignees: "" +--- + +## 1. 발생 위치 + +- + +## 2. 발생 상황 + +- + +## 3. 재현 방법 + +1. +2. +3. + +## 4. 기대 동작 + +- + +## 5. 실제 동작 + +- + +## 6. 관련 작업 영역 + +- [ ] identity-access +- [ ] room-ai-chat +- [ ] personal-analysis +- [ ] invite-participation +- [ ] statement +- [ ] judgement-result +- [ ] result-card-media +- [ ] records-lifecycle +- [ ] calendar-diary +- [ ] statistics +- [ ] gift-recommendation +- [ ] profile-mypage +- [ ] ops-common + +## 7. 관련 NFR + +- [ ] security +- [ ] privacy +- [ ] performance +- [ ] reliability +- [ ] usability +- [ ] accessibility +- [ ] compatibility +- [ ] ai-safety +- [ ] data +- [ ] ops + +## 8. 스크린샷 / 로그 + +- + +## 9. 완료 기준 + +- [ ] 원인 파악 +- [ ] 수정 완료 +- [ ] 재현 케이스 확인 +- [ ] 회귀 테스트 확인 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..64eb98d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,2 @@ +blank_issues_enabled: true +contact_links: [] diff --git a/.github/ISSUE_TEMPLATE/docs.md b/.github/ISSUE_TEMPLATE/docs.md new file mode 100644 index 0000000..08afe99 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs.md @@ -0,0 +1,36 @@ +--- +name: "[Docs] 문서 작업" +about: 문서 추가 및 수정 Issue +title: "[Docs] " +labels: docs +assignees: "" +--- + +## 1. 수정 문서 + +- [ ] PRD +- [ ] 기능 요구사항 +- [ ] 비기능 요구사항 +- [ ] ERD +- [ ] API 명세서 +- [ ] Architecture +- [ ] 기술스택 정의서 +- [ ] Git 협업 정책 +- [ ] 인프라 문서 +- [ ] 도메인 문서 +- [ ] 와이어프레임/디자인 문서 + +## 2. 작업 내용 + +- + +## 3. 수정 사유 + +- + +## 4. 완료 기준 + +- [ ] 문서 수정 완료 +- [ ] 최신 정책과 일치 확인 +- [ ] 관련 문서 간 충돌 없음 +- [ ] Notion 반영 필요 여부 확인 diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 0000000..a99adc6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,57 @@ +--- +name: "[Feat] 기능 구현" +about: 새 기능 구현 Issue +title: "[Feat] " +labels: feat +assignees: "" +--- + +## 1. 작업 영역 + +- [ ] identity-access +- [ ] room-ai-chat +- [ ] personal-analysis +- [ ] invite-participation +- [ ] statement +- [ ] judgement-result +- [ ] result-card-media +- [ ] records-lifecycle +- [ ] calendar-diary +- [ ] statistics +- [ ] gift-recommendation +- [ ] profile-mypage +- [ ] ops-common + +## 2. 작업 내용 + +- + +## 3. 관련 기능 요구사항 + +- FR- + +## 4. 관련 비기능 요구사항 + +- NFR- + +## 5. 완료 기준 + +- [ ] 기능 구현 완료 +- [ ] 로딩 상태 처리 +- [ ] 에러 상태 처리 +- [ ] 권한 검증 적용 +- [ ] 모바일 화면 확인 +- [ ] 로컬 테스트 완료 +- [ ] 관련 문서 수정 필요 여부 확인 + +## 6. 참고 문서 + +- PRD: +- ERD: +- API: +- Architecture: +- Design: + +## 7. 추가 참고 사항 + +- diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..36ac97b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,78 @@ +## 1. 작업 내용 + +- + +## 2. 담당 작업 영역 + +- [ ] identity-access +- [ ] room-ai-chat +- [ ] personal-analysis +- [ ] invite-participation +- [ ] statement +- [ ] judgement-result +- [ ] result-card-media +- [ ] records-lifecycle +- [ ] calendar-diary +- [ ] statistics +- [ ] gift-recommendation +- [ ] profile-mypage +- [ ] ops-common + +## 3. 관련 Issue + +- close # + +## 4. 관련 기능 요구사항 + +- FR- + +## 5. 관련 비기능 요구사항 + +- NFR- + +## 6. 변경 사항 + +- + +## 7. 테스트 결과 + +- [ ] 로컬 실행 확인 +- [ ] 기능 동작 확인 +- [ ] 에러 케이스 확인 +- [ ] 모바일 화면 확인 +- [ ] 빌드 확인 +- [ ] lint 확인 +- [ ] type-check 확인 + +## 8. 작업 범위 확인 + +- [ ] Issue에 정의된 작업 범위 안에서 수정함 +- [ ] 다른 팀원 담당 영역을 불필요하게 수정하지 않음 +- [ ] 공통 파일 변경 시 팀에 공유함 +- [ ] 관련 문서 수정 필요 여부를 확인함 + +## 9. 보안 / 개인정보 확인 + +- [ ] 환경변수 노출 없음 +- [ ] API Key 노출 없음 +- [ ] Supabase Service Role Key 클라이언트 노출 없음 +- [ ] 권한 검증 적용 +- [ ] 개인정보/진술/감정일기 원문 로그 저장 없음 +- [ ] 공유 이미지에 민감정보 포함 없음 + +## 10. DB/API/Storage 변경 여부 + +- [ ] DB 변경 없음 +- [ ] DB 변경 있음 → migration 포함 +- [ ] API 변경 없음 +- [ ] API 변경 있음 → API 문서 반영 +- [ ] Storage 변경 없음 +- [ ] Storage 변경 있음 → Supabase Storage 정책 확인 + +## 11. 스크린샷 + +필요 시 첨부 + +## 12. 추가 공유 사항 + +- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5131f90 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Dependencies +node_modules + +# Next.js +.next +out + +# Build +dist +build +coverage + +# Environment variables +.env +.env.local +.env.*.local + +# Vercel +.vercel + +# OS +.DS_Store + +# TypeScript +tsconfig.tsbuildinfo + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..55b1fc3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +.next +out +dist +build +node_modules +coverage +*.log diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..4cbc711 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2 +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..60d9af2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,540 @@ +# CLAUDE.md + +## 1. Project Overview + +이 프로젝트는 **AI 갈등 조정 판결 서비스**이다. + +사용자가 갈등 상황을 AI와 먼저 정리한 뒤, 필요 시 상대방을 초대하여 1:1 조정 상태로 전환하고, 양측 진술을 기반으로 AI 판결과 관계 회복 제안을 제공한다. + +### 핵심 서비스 흐름 + +```txt +AI 대화방 생성 +→ AI 대화 +→ 초대 링크 발급 +→ 상대방 참여 +→ 1:1 조정 전환 +→ 양측 진술 작성 +→ AI 판결 생성 +→ 판결 결과 확인 +→ 선물추천 +``` + +--- + +## 2. MVP Scope + +### MVP 포함 + +```txt +- 카카오 로그인 +- 약관 동의 +- AI 대화방 생성 +- AI와 갈등 상황 정리 +- 초대 링크 발급 +- 상대방 참여 +- 1:1 조정 전환 +- 양측 진술 작성 +- AI 판결 생성 +- 판결 결과 확인 +- 판결 결과 카드 +- 사건기록 +- 달력 +- 감정일기 +- 마이페이지 +- 하단 탭 +- 선물추천 +- 통계 API +- 홈/마이페이지 내 요약 통계 컴포넌트 +``` + +### MVP 제외 + +```txt +- 상대방 없는 단독 판결 +- shop +- points +- user-items +- 내부 결제 +- 카카오톡 선물하기 직접 연동 +- 외부 상품 API 직접 연동 +- statistics 독립 화면 +- 관리자 페이지 +- 푸시 알림 +``` + +MVP 제외 기능은 구현하지 않는다. +필요한 경우 `docs/domains/*_FUTURE.md` 문서에만 정리한다. + +--- + +## 3. Fixed Product Rules + +### 작성 카테고리 + +작성 카테고리는 아래 4개만 사용한다. + +```txt +연애 +가족 +친구 +직장 +``` + +아래 6개 카테고리 기준은 사용하지 않는다. + +```txt +관계 +금전 +공간 +시간 +가치관 +역할 +``` + +### AI 대화방 정책 + +```txt +- 모든 방은 먼저 AI 대화방으로 생성한다. +- AI 대화방 단계에서는 갈등 정리, 감정 정리, 대화 방향 조언만 제공한다. +- AI 대화방 단계에서는 판결 점수를 생성하지 않는다. +- 상대방 참여 후 1:1 조정 상태로 전환된 뒤에만 AI 판결을 생성할 수 있다. +``` + +### AI 판결 결과 + +AI 판결 결과에는 아래 항목을 중심으로 제공한다. + +```txt +- A/B 판결 점수 +- 핵심 쟁점 요약 +- 판결 근거 +- 화해 제안 +- 화해 메시지 +- 선물추천 문구 +- 16가지 세부 결과 유형 중 AI 도출 유형 +``` + +아래 항목은 구현하지 않는다. + +```txt +- A/B 공감 지수 +- A/B 소통 태도 점수 +``` + +### 결과 유형 관리 + +결과 유형은 코드 Enum 하드코딩을 금지한다. +상위 결과 그룹과 세부 결과 유형은 DB 마스터 데이터 기준으로 관리한다. + +--- + +## 4. Architecture Rules + +이 프로젝트는 **DDD 중심 + 공통 UI 분리 보조 구조**를 따른다. + +### 기본 구조 원칙 + +```txt +src/app/page → 화면 라우트 +src/app/api → API Route Handler +src/domains → 도메인별 비즈니스 로직, API client, hooks, constants +src/components → 공통 UI / 레이아웃 / 피드백 컴포넌트 +src/stores → Zustand 기반 UI 상태 +src/types → 전역 타입 +src/lib → 공통 유틸, auth, api, db, ai, security, validators, constants +src/styles → 전역 스타일, SCSS 변수, mixin +``` + +### 금지 구조 + +```txt +src/features +src/server +src/lib/types +src/lib/stores +src/domains/*/types +src/domains/*/stores +src/app/page/*/*.type.ts +src/app/page/*/*.store.ts +``` + +`features` 폴더는 사용하지 않는다. + +### Calendar UI Rules + +```txt +- 달력 UI는 MUI X Date Pickers 기반으로 구현한다. +- MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다. 전체 디자인 시스템에 적용하지 않는다. +- 전체 스타일 기준은 SCSS / SCSS Module을 유지한다. +- MUI 컴포넌트는 src/components/calendar/ 내 래핑 컴포넌트를 통해서만 사용한다. +- 여러 페이지 / 도메인에서 MUI 컴포넌트를 직접 import하지 않는다. +- 아이콘은 기존 lucide-react를 우선 사용한다. +- 달력 라이브러리는 래핑 컴포넌트 구조로 교체 가능성을 확보한다. +``` + +--- + +## 5. Domain Scope + +### MVP 도메인 + +```txt +auth +common +room +personal-analysis +dispute +judgement +gift +user +calendar +diary +statistics +``` + +`statistics`는 독립 화면을 의미하지 않는다. +MVP에서는 홈/마이페이지 요약 통계 컴포넌트와 API 중심으로만 사용한다. + +### v2.0 확장 예정 도메인 + +```txt +shop +points +user-items +``` + +v2.0 확장 예정 도메인은 MVP 구현 폴더를 만들지 않는다. + +```txt +src/domains/shop 생성 금지 +src/domains/points 생성 금지 +src/domains/user-items 생성 금지 +``` + +--- + +## 6. State Transition Rules + +상태 전이는 임의로 변경하지 않는다. +변경이 필요하면 반드시 문서 수정과 팀 승인을 먼저 진행한다. + +### room_mode + +```txt +ai_chat +→ invite_ready +→ one_to_one +→ closed / expired / deleted +``` + +### dispute_status + +```txt +draft +→ waiting_opponent +→ opponent_joined +→ both_submitted +→ judging +→ judged +→ closed / expired / deleted +``` + +`jailed` 상태명은 사용하지 않는다. + +--- + +## 7. Auth & Security Rules + +### 권한 기준 + +```txt +AI 대화방 조회: +creator_user_id 기준 + +1:1 사건 조회: +dispute_participants.user_id 기준 + +감정일기 조회: +emotion_diaries.user_id 기준 + +판결 결과 조회: +해당 dispute 참여자만 가능 +``` + +### 초대 링크 보안 + +```txt +- room_token 원문은 DB에 저장하지 않는다. +- room_token_hash만 저장한다. +- 만료된 초대 링크 접근은 차단한다. +- 삭제된 방/사건 접근은 차단한다. +- 생성자 본인이 본인 초대 링크로 role_b 참여하는 것을 차단한다. +- 이미 role_b가 존재하는 방에는 추가 참여를 차단한다. +``` + +### 민감 정보 보호 + +```txt +- 공유 이미지에 사건 원문을 포함하지 않는다. +- 결과 카드에 개인정보를 포함하지 않는다. +- 감정일기 원문은 통계, 공유 이미지, 외부 추천 기능에 노출하지 않는다. +- 로그에는 불필요한 원문과 민감 정보를 저장하지 않는다. +``` + +### 인증 방식 + +```txt +- 인증은 NextAuth + Kakao OAuth를 사용한다. +- Supabase Auth는 사용하지 않는다. +``` + +--- + +## 8. Data & DB Rules + +### DB 네이밍 + +```txt +DB column: snake_case +Prisma field: camelCase +Prisma mapping: @map 사용 +``` + +### 정합성 규칙 + +```txt +- AI 대화방 단계에서는 role_a / role_b를 확정하지 않는다. +- 1:1 조정 전환 시 생성자를 role_a로 확정한다. +- 상대방 참여 시 role_b로 확정한다. +- 하나의 dispute에는 role_a 1명, role_b 1명만 존재할 수 있다. +- 하나의 role은 하나의 진술만 작성할 수 있다. +- 동일 사용자가 role_a와 role_b를 동시에 가질 수 없다. +``` + +### DB 인프라 + +```txt +- DB는 Supabase Postgres를 사용한다. +- Prisma는 Supabase Postgres의 DATABASE_URL을 통해 연결한다. +``` + +### Storage 인프라 + +```txt +- Storage는 Supabase Storage를 사용한다. +- MVP Storage 사용 범위는 result-cards bucket으로 제한한다. +- 결과 카드 이미지 저장에 사용한다. +- SUPABASE_SERVICE_ROLE_KEY는 서버에서만 사용하며 클라이언트에 노출하지 않는다. +- 민감 원문(진술, 감정일기, AI 대화)은 Storage에 저장하지 않는다. +- 정적 에셋(캐릭터, 아이콘, 결과카드 템플릿 등)은 public/images에서 관리한다. +``` + +### 멱등성 / 중복 요청 방지 + +MVP에서 중복 요청 방지를 적용해야 하는 대상: + +```txt +- AI 판결 생성 요청 +- 진술 종료 요청 +- 초대 참여 요청 +- 삭제 / 비식별 처리 요청 +``` + +포인트, 상품 구매, 결제 관련 멱등성은 v2.0 확장 문서에서 관리한다. + +--- + +## 9. Frontend State Rules + +### Zustand 사용 범위 + +Zustand는 UI 상태에만 사용한다. + +```txt +- 모달 +- 바텀시트 +- 플로팅 메뉴 +- 선택 날짜 +- 로딩 UI +- 결과 카드 생성 중 상태 +``` + +아래 데이터는 Zustand에 저장하지 않는다. + +```txt +- 서버에서 조회한 도메인 데이터 +- 사건 상세 데이터 +- 판결 결과 데이터 +- 감정일기 목록 +- 통계 데이터 +``` + +서버 데이터는 TanStack Query와 API 응답 기준으로 관리한다. + +--- + +## 10. API / Server Rules + +```txt +- API 응답은 공통 응답 구조를 따른다. +- API Route와 Server Service에는 try-catch 기반 예외 처리를 적용한다. +- Gemini API 실패, JSON 파싱 실패, timeout은 구분해서 처리한다. +- 권한 검증은 프론트가 아니라 서버에서 최종 수행한다. +- API 로직 구현 전 API 명세서를 확인한다. +``` + +--- + +## 11. Logging & Ops Rules + +MVP에서는 Sentry 없이 아래 기준으로 시작한다. + +```txt +- try-catch 기반 공통 에러 핸들러 +- 공통 에러 응답 +- DB 실패 로그 +- Vercel Logs +``` + +로그 대상: + +```txt +- API 오류 +- AI 요청 실패 +- 욕설/부적절 표현 필터링 결과 +- 삭제 / 비식별 처리 +- 초대 링크 오류 +- 권한 오류 +``` + +로그에는 불필요한 사건 원문, 감정일기 원문, 개인정보를 저장하지 않는다. + +--- + +## 12. Git Workflow + +현재 GitHub Organization 기반 팀 프로젝트로 진행한다. + +### 기본 브랜치 + +```txt +main +dev +``` + +### 작업 브랜치 + +모든 작업은 `dev`에서 분기한다. + +```txt +feature/* +fix/* +refactor/* +docs/* +infra/* +``` + +### PR 규칙 + +```txt +- main 직접 push 금지 +- dev 직접 push 금지 +- 작업 브랜치는 dev에서 생성 +- PR 대상은 기본적으로 dev +- main 병합은 최종 배포 시에만 진행 +- PR 전 로컬 실행 / 빌드 / 린트 확인 +``` + +--- + +## 13. Claude Work Process + +Claude는 작업 시 아래 순서를 따른다. + +```txt +1. 관련 문서 확인 +2. 작업 계획 제시 +3. 사용자 승인 대기 +4. 구현 +5. 검증 +6. 변경 파일 요약 +7. 커밋 / PR 안내 +``` + +문서가 없거나 문서 간 충돌이 있으면 구현하지 말고 질문한다. + +--- + +## 14. STOP Conditions + +아래 상황에서는 작업을 즉시 중단하고 사용자에게 확인한다. + +```txt +- ERD 없이 Prisma schema 변경이 필요한 경우 +- 상태 전이 규칙 변경이 필요한 경우 +- 권한 쿼리 변경이 필요한 경우 +- API 응답 구조 변경이 필요한 경우 +- MVP 제외 기능 구현 요청이 발생한 경우 +- shop / points / user-items 구현이 필요한 경우 +- 6개 카테고리 기준 구현이 필요한 경우 +- 공감 지수 / 소통 태도 점수 구현이 필요한 경우 +- AI 대화방 없이 바로 1:1 사건 생성 흐름이 필요한 경우 +- statistics 독립 화면 생성이 필요한 경우 +- 결과 유형을 Enum으로 하드코딩하려는 경우 +- 브랜치 없이 작업 중인 경우 +- 도메인별 문서가 없는데 임의로 도메인 로직을 구현하려는 경우 +``` + +--- + +## 15. Approval Required + +아래 작업은 반드시 사용자 또는 팀 승인 후 진행한다. + +```txt +- Prisma schema 변경 +- DB relation 변경 +- 상태 전이 규칙 변경 +- 권한 검증 로직 변경 +- API endpoint 추가 / 삭제 / 구조 변경 +- 카카오 OAuth 설정 변경 +- Gemini API 프롬프트 구조 변경 +- 환경변수 추가 / 삭제 +- 공통 폴더 구조 변경 +- MVP 제외 기능을 구현 범위로 올리는 작업 +``` + +--- + +## 16. Required Reference Documents + +작업 전 필요한 문서를 확인한다. + +```txt +docs/PROJECT_DECISIONS.md +docs/PRD.md +docs/FUNCTIONAL_REQUIREMENTS.xlsx +docs/NON_FUNCTIONAL_REQUIREMENTS.xlsx +docs/TASK_ASSIGNMENT.xlsx +docs/TECH_STACK.md +docs/ERD.md +docs/API_SPEC.md +docs/ARCHITECTURE.md +docs/INFRA.md +docs/guides/CLAUDE_WORKFLOW.md +docs/guides/GIT_WORKFLOW.md +docs/guides/PR_RULES.md +docs/guides/ENV_GUIDE.md +docs/guides/CODING_CONVENTION.md +docs/db/PRISMA_MAPPING.md +docs/db/MASTER_DATA.md +docs/db/STATUS_TRANSITION.md +docs/domains/*.md +``` + +도메인 상세 설계는 루트 `CLAUDE.md`에 작성하지 않는다. +도메인별 상세 내용은 `docs/domains/*.md`에서 관리한다. + +도메인별 문서가 아직 없으면 임의 구현하지 않는다. +필요한 경우 담당자에게 문서 작성 또는 기준 확정을 요청한다. diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/mock/.gitkeep b/data/mock/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/mock/db.json b/data/mock/db.json new file mode 100644 index 0000000..f49e711 --- /dev/null +++ b/data/mock/db.json @@ -0,0 +1,8 @@ +{ + "health": [ + { + "id": 1, + "status": "ok" + } + ] +} diff --git a/docs/.gitkeep b/docs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/INFRA.md b/docs/INFRA.md new file mode 100644 index 0000000..a85daf6 --- /dev/null +++ b/docs/INFRA.md @@ -0,0 +1,185 @@ +# INFRA.md + +TALKY-OWL 인프라 구성 문서 + +--- + +## 1. 인프라 개요 + +| 분류 | 기술 | 비고 | +|------|------|------| +| Hosting | Vercel Hobby | Vercel Team 미사용 | +| Database | Supabase Postgres | Prisma ORM 연결 | +| Storage | Supabase Storage | result-cards bucket (MVP 범위) | +| Auth | NextAuth + Kakao OAuth | Supabase Auth 미사용 | +| AI | Google Gemini API | 서버 API Route에서만 사용 | +| CI/CD | GitHub Actions + Vercel CLI | 별도 작업에서 workflow 구성 | + +--- + +## 2. Hosting + +```txt +플랫폼: Vercel Hobby +계정: 배포 전용 Google 계정 1개 +팀 구성: Vercel Team 미사용 +팀원: Vercel Team에 초대하지 않음 +배포 방식: GitHub Actions + Vercel CLI +``` + +Vercel Team을 사용하지 않기 때문에, GitHub Organization repo와의 연동은 GitHub Actions + Vercel CLI 방식으로 구성한다. + +--- + +## 3. Deployment + +### 배포 흐름 + +```txt +GitHub Organization (I5-Project/TALKY-OWL) +→ dev 브랜치 PR 병합 +→ GitHub Actions에서 Vercel CLI 배포 +→ 개인 Vercel Hobby 프로젝트로 배포 +``` + +### 브랜치 기준 + +```txt +dev: 개발 통합 브랜치. 배포 대상 브랜치 +main: 최종 배포 기준 브랜치 (보존용) +``` + +### 필요한 GitHub Actions Secrets + +```txt +VERCEL_TOKEN +VERCEL_ORG_ID +VERCEL_PROJECT_ID +``` + +실제 workflow 파일은 별도 작업 브랜치에서 생성한다. + +--- + +## 4. Database + +```txt +플랫폼: Supabase Postgres +ORM: Prisma +연결 방식: DATABASE_URL 환경변수를 통해 Prisma와 연결 +``` + +```txt +DATABASE_URL: Supabase Postgres 연결 문자열 + Supabase Dashboard > Project Settings > Database > Connection String (URI) +``` + +--- + +## 5. Storage + +```txt +플랫폼: Supabase Storage +MVP 범위: result-cards bucket 중심 +용도: 판결 결과 카드 이미지 저장 +``` + +버킷 구분: + +```txt +result-cards 판결 결과 카드 이미지 (MVP 사용 대상) +``` + +```txt +정적 에셋 (캐릭터, 아이콘, 결과카드 템플릿 등)은 public/images에서 관리한다. +Supabase Storage는 서비스 실행 중 생성되는 결과 카드 이미지 저장에 사용한다. +``` + +MVP 제외 범위: + +```txt +- 진술 원문 이미지 저장 +- 감정일기 원문 이미지 저장 +- AI 대화 원문 캡처 저장 +- 사용자 첨부파일 저장 +- 프로필 이미지 업로드 (추후 확장 검토) +``` + +접근 원칙: + +```txt +- SUPABASE_SERVICE_ROLE_KEY는 서버에서만 사용한다. +- 클라이언트에서 Service Role Key 사용 금지. +- 업로드/삭제/비공개 접근은 Next.js API Route를 통해 서버에서 처리한다. +``` + +--- + +## 6. Auth + +```txt +방식: NextAuth + Kakao OAuth +라이브러리: next-auth v4 +``` + +```txt +Supabase Auth는 사용하지 않는다. +인증은 NextAuth + Kakao OAuth를 유지한다. +``` + +Kakao Redirect URI: + +```txt +로컬: http://localhost:3030/api/auth/callback/kakao +Production: https://[프로덕션도메인]/api/auth/callback/kakao +``` + +--- + +## 7. AI + +```txt +플랫폼: Google Gemini API +SDK: @google/generative-ai +사용 범위: 서버 API Route에서만 사용 +``` + +```txt +GEMINI_API_KEY는 클라이언트에 노출하지 않는다. +NEXT_PUBLIC_ prefix 사용 금지. +``` + +--- + +## 8. 환경변수 관리 + +```txt +- .env.example에는 key 이름만 관리한다. +- 실제 값은 Vercel Dashboard Environment Variables에 등록한다. +- GitHub Actions 배포용 Secrets는 GitHub Repository Secrets에 별도 등록한다. +- .env.local은 Git에 커밋하지 않는다. +``` + +상세 내용은 아래 문서를 참고한다: + +```txt +docs/guides/ENV_GUIDE.md +docs/guides/VERCEL_DEPLOYMENT_GUIDE.md +``` + +--- + +## 9. 수동 설정 필요 항목 + +아래 항목은 배포 담당자가 직접 설정한다. + +```txt +- Vercel 프로젝트 생성 (배포 전용 계정) +- Vercel Environment Variables 등록 +- GitHub Repository Secrets 등록 (VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID) +- Supabase 프로젝트 생성 +- Supabase result-cards bucket 생성 +- Kakao Developers Redirect URI 등록 +- GitHub Actions workflow 생성 (별도 작업 브랜치) +- main / dev Branch Protection 설정 +``` diff --git a/docs/PROJECT_DECISIONS.md b/docs/PROJECT_DECISIONS.md new file mode 100644 index 0000000..11afe6c --- /dev/null +++ b/docs/PROJECT_DECISIONS.md @@ -0,0 +1,232 @@ +# PROJECT_DECISIONS.md + +TALKY-OWL 프로젝트 최종 합의사항 정리 + +--- + +## 1. 프로젝트 핵심 방향 + +AI 갈등 조정 판결 서비스. +사용자가 갈등 상황을 AI와 먼저 정리하고, 상대방을 초대해 1:1 조정 후 AI 판결과 관계 회복 제안을 받는다. + +--- + +## 2. 핵심 서비스 흐름 + +```txt +AI 대화방 생성 +→ AI 대화 +→ 초대 링크 발급 +→ 상대방 참여 +→ 1:1 조정 전환 +→ 양측 진술 작성 +→ AI 판결 생성 +→ 판결 결과 확인 +→ 선물추천 +``` + +--- + +## 3. MVP 포함 범위 + +```txt +카카오 로그인 / 약관 동의 +AI 대화방 생성 / AI와 갈등 상황 정리 +초대 링크 발급 / 상대방 참여 / 1:1 조정 전환 +양측 진술 작성 / AI 판결 생성 +판결 결과 확인 / 판결 결과 카드 +사건기록 / 달력 / 감정일기 +마이페이지 / 하단 탭 +선물추천 +통계 API / 홈·마이페이지 내 요약 통계 컴포넌트 +``` + +--- + +## 4. MVP 제외 범위 + +```txt +상대방 없는 단독 판결 +shop / points / user-items +내부 결제 +카카오톡 선물하기 직접 연동 +외부 상품 API 직접 연동 +statistics 독립 화면 +관리자 페이지 +푸시 알림 +``` + +MVP 제외 항목은 구현하지 않는다. 필요 시 `docs/domains/*_FUTURE.md`에 정리한다. + +--- + +## 5. 작성 카테고리 + +아래 4개만 사용한다. + +```txt +연애 / 가족 / 친구 / 직장 +``` + +아래 6개 구버전 카테고리는 사용하지 않는다. + +```txt +관계 / 금전 / 공간 / 시간 / 가치관 / 역할 +``` + +--- + +## 6. AI 판결 결과 기준 + +**포함:** + +```txt +A/B 판결 점수 +핵심 쟁점 요약 +판결 근거 +화해 제안 +화해 메시지 +선물추천 문구 +16가지 세부 결과 유형 중 AI 도출 유형 +``` + +**제외 (구현 금지):** + +```txt +A/B 공감 지수 +A/B 소통 태도 점수 +``` + +결과 유형은 코드 Enum 하드코딩을 금지하고 DB 마스터 데이터 기준으로 관리한다. + +--- + +## 7. 아키텍처 원칙 + +```txt +src/app/page → 화면 라우트 +src/app/api → API Route Handler +src/domains → 도메인별 비즈니스 로직, API client, hooks, constants +src/components → 공통 UI / 레이아웃 / 피드백 컴포넌트 +src/stores → Zustand 기반 UI 상태 +src/types → 전역 타입 +src/lib → 공통 유틸, auth, api, db, ai, security, validators, constants +src/styles → 전역 스타일, SCSS 변수, mixin +``` + +`features` 폴더는 사용하지 않는다. + +--- + +## 8. 상태 전이 요약 + +### room_mode + +```txt +ai_chat → invite_ready → one_to_one → closed / expired / deleted +``` + +### dispute_status + +```txt +draft → waiting_opponent → opponent_joined → both_submitted → judging → judged → closed / expired / deleted +``` + +`jailed` 상태명은 사용하지 않는다. 상세 내용은 `docs/db/STATUS_TRANSITION.md` 참고. + +--- + +## 9. 권한/보안 원칙 + +```txt +AI 대화방 조회: creator_user_id 기준 +1:1 사건 조회: dispute_participants.user_id 기준 +감정일기 조회: emotion_diaries.user_id 기준 +판결 결과 조회: 해당 dispute 참여자만 가능 +``` + +```txt +room_token 원문은 DB 저장 금지 → room_token_hash만 저장 +공유 이미지에 사건 원문 포함 금지 +결과 카드에 개인정보 포함 금지 +로그에 원문·개인정보 저장 금지 +``` + +--- + +## 10. Supabase 인프라 확정 + +Supabase를 실제 사용 인프라로 확정한다. + +**DB:** + +```txt +Supabase Postgres 사용 +Prisma는 Supabase Postgres의 DATABASE_URL을 통해 연결 +``` + +**Storage:** + +```txt +Supabase Storage 사용 +MVP Storage 사용 범위는 result-cards bucket으로 제한 +결과 카드 이미지 저장에 사용 +정적 에셋(캐릭터, 아이콘, 결과카드 템플릿 등)은 public/images에서 관리 +``` + +**Auth:** + +```txt +Supabase Auth는 사용하지 않음 +인증은 NextAuth + Kakao OAuth 유지 +``` + +**보안:** + +```txt +SUPABASE_SERVICE_ROLE_KEY는 서버 전용 +클라이언트에서 Service Role Key 사용 금지 +민감 원문(진술, 감정일기, AI 대화)은 Storage에 저장하지 않음 +``` + +--- + +## 11. 문서 관리 원칙 + +```txt +도메인 상세 설계는 docs/domains/*.md에서 관리 +루트 CLAUDE.md에는 상세 설계를 넣지 않음 +도메인별 문서가 없으면 임의 구현하지 않음 +``` + +--- + +## 12. Calendar UI 결정사항 + +**결정:** 달력 UI는 MUI X Date Pickers + Day.js 기반으로 구현한다. + +**배경:** + +```txt +- 날짜 선택 / 달력 마킹 UI를 자체 구현하면 복잡도가 높아진다. +- MUI X Date Pickers는 React + TypeScript 환경에서 안정적인 달력 UI를 제공한다. +- Day.js는 번들 크기가 작고 @mui/x-date-pickers 어댑터와 호환된다. +``` + +**적용 범위:** + +```txt +- 달력 UI +- 날짜 선택 UI +- 날짜 기반 감정일기 / 사건기록 조회 UI +``` + +**제약:** + +```txt +- 전체 디자인 시스템은 SCSS / SCSS Module을 유지한다. +- MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다. +- MUI 컴포넌트는 src/components/calendar/ 내 래핑 컴포넌트를 통해서만 사용한다. +- 아이콘은 기존 lucide-react를 우선 사용한다. +- 달력 라이브러리는 래핑 컴포넌트 구조로 교체 가능성을 확보한다. +``` diff --git a/docs/TECH_STACK.md b/docs/TECH_STACK.md new file mode 100644 index 0000000..cc4a7b7 --- /dev/null +++ b/docs/TECH_STACK.md @@ -0,0 +1,161 @@ +# TECH STACK + +TALKY-OWL 프로젝트 기술 스택 및 설치 패키지 정의서 + +--- + +## 인프라 + +| 분류 | 기술 | 비고 | +|------|------|------| +| Database | Supabase Postgres | Prisma ORM을 통해 연결 | +| Storage | Supabase Storage | result-cards bucket (MVP 범위) | +| Auth | NextAuth + Kakao OAuth | Supabase Auth 미사용 | +| 배포 | Vercel | 환경변수는 Vercel에서 관리 | + +--- + +## Calendar UI + +달력 UI는 MUI X Date Pickers 기반으로 구현한다. + +설치 예정 패키지: + +```txt +@mui/material +@emotion/react +@emotion/styled +@mui/x-date-pickers +dayjs +``` + +사용 범위: + +- 달력 UI +- 날짜 선택 UI +- 날짜 기반 감정일기/사건기록 조회 UI + +주의사항: + +- 전체 디자인 시스템을 MUI 기반으로 전환하지 않는다. +- 기존 스타일 기준은 SCSS / SCSS Module을 유지한다. +- 아이콘은 기존 `lucide-react` 사용을 우선한다. +- `@mui/icons-material`은 현재 필수 설치 대상이 아니다. +- 달력 라이브러리는 추후 변경 가능하다. 변경 가능성을 확보하기 위해 MUI 의존성은 Calendar 전용 컴포넌트와 날짜 유틸 영역에만 제한한다. + +--- + +## 패키지 매니저 + +```txt +npm +``` + +--- + +## 설치 명령어 + +```bash +npm install +``` + +--- + +## Dependencies + +| 패키지 | 버전 | 용도 | +|--------|------|------| +| `next` | ^15.0.0 | Next.js 15 App Router 프레임워크 | +| `react` | ^19.0.0 | UI 라이브러리 | +| `react-dom` | ^19.0.0 | React DOM 렌더링 | +| `next-auth` | ^4.24.11 | 카카오 OAuth 인증 (NextAuth v4) | +| `@prisma/client` | ^6.0.0 | Prisma ORM 클라이언트 | +| `@google/generative-ai` | ^0.21.0 | Google Gemini API SDK | +| `zustand` | ^5.0.2 | UI 상태 관리 (모달, 바텀시트 등) | +| `@tanstack/react-query` | ^5.62.0 | 서버 데이터 패칭 및 캐싱 | +| `react-hook-form` | ^7.54.1 | 폼 상태 관리 | +| `@hookform/resolvers` | ^3.9.1 | React Hook Form + Zod 연동 | +| `zod` | ^3.23.8 | 스키마 유효성 검사 | +| `lucide-react` | ^0.468.0 | 아이콘 라이브러리 | +| `recharts` | ^3.0.0 | 차트 라이브러리 (통계 시각화) | +| `html-to-image` | ^1.11.11 | 판결 결과 카드 이미지 추출 | +| `sass` | ^1.83.0 | SCSS / SCSS Module 스타일링 | + +--- + +## DevDependencies + +| 패키지 | 버전 | 용도 | +|--------|------|------| +| `typescript` | ^5.7.2 | TypeScript 컴파일러 | +| `@types/node` | ^22.0.0 | Node.js 타입 정의 | +| `@types/react` | ^19.0.0 | React 타입 정의 | +| `@types/react-dom` | ^19.0.0 | React DOM 타입 정의 | +| `eslint` | ^9.0.0 | 코드 린터 | +| `eslint-config-next` | ^15.0.0 | Next.js ESLint 규칙 프리셋 | +| `prettier` | ^3.4.2 | 코드 포맷터 | +| `prisma` | ^6.0.0 | Prisma CLI (마이그레이션, 스키마 관리) | +| `json-server` | ^0.17.4 | Mock API 서버 | + +--- + +## 주요 선택 이유 + +### Gemini SDK — `@google/generative-ai` + +Google 공식 Node.js SDK. Next.js App Router Server Actions 및 API Route와 호환되며, GCP 인프라 의존 없이 API 키만으로 사용 가능. (`@google-cloud/vertexai`는 GCP 환경 전용이므로 제외) + +### 상태 관리 분리 전략 + +- **Zustand** → 모달, 바텀시트, 로딩 UI 등 순수 UI 상태만 담당 +- **TanStack Query** → 서버 데이터 패칭, 캐싱, 동기화 담당 +- 서버 데이터(사건, 판결, 일기 등)는 Zustand에 저장하지 않음 + +### recharts v3 + +v2.x는 deprecated 상태. v3로 업그레이드하여 최신 유지. + +### next-auth v4 + +v5(beta)는 아직 프로덕션 안정성 미검증. 카카오 OAuth 연동이 v4에서 안정적으로 지원되므로 v4 사용. + +--- + +## npm scripts + +| 명령어 | 설명 | +|--------|------| +| `npm run dev` | 개발 서버 실행 (port 3030) | +| `npm run build` | 프로덕션 빌드 | +| `npm run start` | 프로덕션 서버 실행 (port 3030) | +| `npm run lint` | ESLint 검사 | +| `npm run type-check` | TypeScript 타입 검사 | +| `npm run format` | Prettier 포맷 적용 | +| `npm run format:check` | Prettier 포맷 검사 | +| `npm run mock` | Mock 서버 실행 (port 8081) | +| `npm run prisma:generate` | Prisma 클라이언트 생성 | +| `npm run prisma:migrate` | Prisma 마이그레이션 실행 | + +--- + +## 환경변수 + +`.env.example` 파일을 참고하세요. + +실제 `.env.local`은 팀 내부에서 공유하지 않습니다. +Vercel에 등록된 환경변수를 아래 명령어로 로컬에 가져올 수 있습니다. + +```bash +vercel env pull .env.local +``` + +--- + +## 버전 고정 기준 + +`package-lock.json`을 Git에 포함하여 팀원 전체가 동일한 버전으로 설치합니다. + +```bash +# 신규 팀원 환경 세팅 +npm ci +``` diff --git a/docs/db/.gitkeep b/docs/db/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/db/MASTER_DATA.md b/docs/db/MASTER_DATA.md new file mode 100644 index 0000000..4cc81ee --- /dev/null +++ b/docs/db/MASTER_DATA.md @@ -0,0 +1,70 @@ +# MASTER_DATA.md + +마스터 데이터 관리 문서 + +--- + +## 1. 마스터 데이터 관리 원칙 + +```txt +결과 유형은 코드 Enum으로 하드코딩하지 않는다. +상위 결과 그룹과 세부 결과 유형은 DB 마스터 테이블로 관리한다. +카테고리도 DB 마스터 기준으로 관리한다. +``` + +--- + +## 2. 작성 카테고리 + +MVP에서 사용하는 카테고리는 아래 4개다. + +```txt +연애 +가족 +친구 +직장 +``` + +아래 6개 구버전 카테고리는 사용하지 않는다. + +```txt +관계 / 금전 / 공간 / 시간 / 가치관 / 역할 +``` + +--- + +## 3. 결과 유형 + +AI 판결 결과 유형은 상위 결과 그룹과 16가지 세부 유형으로 구성된다. +세부 유형은 DB 마스터 데이터 기준으로 관리하며, AI가 최종 유형을 도출한다. + +```txt +상위 결과 그룹 N개 (확정 필요) +세부 결과 유형 16개 (확정 필요) +``` + +상세 유형 목록은 ERD / 기획 확정 후 이 문서에 추가한다. + +--- + +## 4. 금지사항 + +```txt +결과 유형을 코드 Enum으로 고정하지 않는다. +카테고리를 구버전 6개 기준으로 구현하지 않는다. +마스터 데이터를 하드코딩으로 관리하지 않는다. +``` + +--- + +## 5. 향후 관리 방식 + +seed 또는 migration 방식은 ERD 확정 후 결정한다. + +```txt +예시: +- prisma/seed.ts 방식 +- 초기 migration SQL 방식 +``` + +확정 후 이 문서에 추가한다. diff --git a/docs/db/PRISMA_MAPPING.md b/docs/db/PRISMA_MAPPING.md new file mode 100644 index 0000000..29c2275 --- /dev/null +++ b/docs/db/PRISMA_MAPPING.md @@ -0,0 +1,73 @@ +# PRISMA_MAPPING.md + +Prisma 매핑 기준 문서 + +--- + +## 1. 기본 원칙 + +```txt +DB column 네이밍: snake_case +Prisma field 네이밍: camelCase +매핑: @map() 필수 사용 +테이블 매핑: @@map() 필수 사용 +``` + +--- + +## 2. 작성 예시 + +```prisma +model DisputeRoom { + id Int @id @default(autoincrement()) + creatorUserId Int @map("creator_user_id") + roomMode String @map("room_mode") + createdAt DateTime @default(now()) @map("created_at") + + @@map("dispute_rooms") +} +``` + +--- + +## 3. 금지사항 + +```txt +ERD 확정 없이 모델 상세 작성 금지 +DB relation 임의 작성 금지 +결과 유형을 Prisma Enum으로 하드코딩 금지 +shop / points / user-items 모델 작성 금지 +``` + +--- + +## 4. 향후 작성 대상 + +ERD 및 `docs/db/MASTER_DATA.md` 확정 후 아래 모델을 순서대로 작성한다. + +```txt +users +dispute_rooms +disputes +dispute_participants +dispute_statements +judgements +judgement_result_types ← Enum 대신 마스터 테이블로 관리 +gift_recommendations +emotion_diaries +calendar_events +``` + +상세 매핑은 ERD와 `docs/db/PRISMA_MAPPING.md`를 기준으로 작성한다. + +--- + +## 5. Prisma 관련 명령어 + +```bash +# 클라이언트 생성 +npm run prisma:generate + +# 마이그레이션 실행 +npm run prisma:migrate +``` diff --git a/docs/db/STATUS_TRANSITION.md b/docs/db/STATUS_TRANSITION.md new file mode 100644 index 0000000..ff9abb0 --- /dev/null +++ b/docs/db/STATUS_TRANSITION.md @@ -0,0 +1,97 @@ +# STATUS_TRANSITION.md + +상태 전이 정의 문서 + +--- + +## 1. room_mode + +AI 대화방의 현재 모드를 나타낸다. + +```txt +ai_chat + │ 초대 링크 발급 + ▼ +invite_ready + │ 상대방 참여 + ▼ +one_to_one + │ 종료 / 만료 / 삭제 + ▼ +closed / expired / deleted +``` + +| 상태 | 설명 | +|------|------| +| `ai_chat` | AI와 갈등 정리 단계. 판결 점수 생성 금지 | +| `invite_ready` | 초대 링크 발급 완료. 상대방 참여 대기 중 | +| `one_to_one` | 상대방 참여 완료. 양측 진술 작성 및 AI 판결 가능 | +| `closed` | 정상 종료 | +| `expired` | 만료 처리 | +| `deleted` | 삭제 처리 | + +--- + +## 2. dispute_status + +1:1 조정 사건의 진행 상태를 나타낸다. + +```txt +draft + │ 생성자 진술 준비 + ▼ +waiting_opponent + │ 상대방 참여 + ▼ +opponent_joined + │ 양측 진술 완료 + ▼ +both_submitted + │ AI 판결 요청 + ▼ +judging + │ AI 판결 완료 + ▼ +judged + │ 종료 / 만료 / 삭제 + ▼ +closed / expired / deleted +``` + +| 상태 | 설명 | +|------|------| +| `draft` | 진술 초안 작성 단계 | +| `waiting_opponent` | 상대방 참여 대기 | +| `opponent_joined` | 상대방 참여 완료, 진술 작성 가능 | +| `both_submitted` | 양측 진술 완료, AI 판결 요청 가능 | +| `judging` | AI 판결 처리 중 | +| `judged` | AI 판결 완료 | +| `closed` | 정상 종료 | +| `expired` | 만료 처리 | +| `deleted` | 삭제 처리 | + +--- + +## 3. 상태 변경 원칙 + +```txt +상태 변경은 서버에서 최종 검증한다. +클라이언트에서 임의로 상태를 변경하지 않는다. +임의 상태 점프 금지 (예: ai_chat → one_to_one 직접 전환 불가) +상태 변경 시 권한 검증 필수 +``` + +--- + +## 4. 금지 상태명 + +```txt +jailed — 사용하지 않는다. +``` + +--- + +## 5. 상태 전이 변경 기준 + +상태 전이 규칙 변경이 필요한 경우 반드시 팀 승인 후 진행한다. +임의로 변경하지 않는다. diff --git a/docs/domains/.gitkeep b/docs/domains/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/domains/AUTH.md b/docs/domains/AUTH.md new file mode 100644 index 0000000..ef529ac --- /dev/null +++ b/docs/domains/AUTH.md @@ -0,0 +1,144 @@ +# AUTH Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +카카오 소셜 로그인, 약관 동의, 로그아웃, 회원탈퇴, 인증 상태 관리를 담당한다. +NextAuth 기반으로 카카오 OAuth를 처리하며, 세션 상태를 앱 전반에 제공한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-AUTH-001 +FR-AUTH-002 +FR-AUTH-003 +FR-AUTH-005 +FR-AUTH-006 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 카카오 소셜 로그인 +- 최초 로그인 시 약관 동의 +- 로그아웃 +- 로그인 상태 확인 +- 회원탈퇴 +``` + +--- + +## 6. 제외 기능 + +```txt +- 이메일 / 일반 로그인 +- 카카오 외 다른 OAuth 제공자 +- 관리자 로그인 +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/login/ +src/app/page/terms/ +``` + +--- + +## 8. 관련 API + +```txt +GET /api/auth/[...nextauth] NextAuth 핸들러 +POST /api/v1/auth/withdraw 회원탈퇴 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +users 사용자 정보 +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +인증 상태는 NextAuth 세션 기준으로 관리한다. + +```txt +비로그인 → 카카오 OAuth → 약관 동의 → 로그인 완료 +로그인 완료 → 로그아웃 → 비로그인 +로그인 완료 → 회원탈퇴 → 비식별 처리 +``` + +--- + +## 11. 권한 규칙 + +```txt +로그인 페이지: 비인증 사용자만 접근 +약관 동의 페이지: 최초 로그인 사용자만 접근 +회원탈퇴: 본인만 가능 +``` + +--- + +## 12. UI 연결 지점 + +```txt +세션 확인: src/lib/auth/ +카카오 OAuth 설정: src/lib/auth/ +``` + +--- + +## 13. 예외 상황 + +```txt +- 카카오 OAuth 실패 시 로그인 페이지로 리다이렉트 +- 약관 미동의 상태로 접근 시 약관 동의 페이지로 강제 이동 +- 탈퇴 처리 중 오류 시 롤백 처리 기준 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- 실제 KAKAO_CLIENT_ID / KAKAO_CLIENT_SECRET 값 코드에 포함 금지 +- NextAuth 상세 콜백 구현은 API_SPEC 확정 후 진행 +- 환경변수는 docs/guides/ENV_GUIDE.md 기준 참조 +- 카카오 OAuth 설정 변경은 팀 승인 필요 (CLAUDE.md 15항 참고) +``` diff --git a/docs/domains/CALENDAR.md b/docs/domains/CALENDAR.md new file mode 100644 index 0000000..fea65d7 --- /dev/null +++ b/docs/domains/CALENDAR.md @@ -0,0 +1,162 @@ +# CALENDAR Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +달력 화면에서 날짜별 사건 기록, 감정 기록 마킹, 월별 요약을 담당한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-CALENDAR-001 +FR-CALENDAR-002 +FR-CALENDAR-003 +FR-CALENDAR-004 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 하단 탭 달력 접근 +- 판결 기록 날짜 마킹 +- 감정일기 작성 여부 마킹 +- 월별 다툼 횟수 요약 +``` + +--- + +## 6. 제외 기능 + +```txt +- 외부 캘린더 연동 +- 이벤트 알림 / 푸시 알림 (MVP 제외) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/calendar/ +``` + +--- + +## 8. 관련 API + +```txt +GET /api/v1/calendar?year=&month= 월별 기록 조회 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +disputes 판결 기록 날짜 참조 +emotion_diaries 감정일기 작성 여부 참조 +``` + +상세 구조는 `docs/ERD.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +별도 상태 전이 없음. + +--- + +## 11. 권한 규칙 + +```txt +달력 조회: 본인 데이터만 조회 +타인 기록 접근 금지 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/calendar/ +달력 화면: src/app/page/calendar/ +``` + +--- + +## 13. 예외 상황 + +```txt +- 감정일기 미작성 날짜 마킹 기준 확인 필요 +- 해결 여부 필드 MVP 필수 여부 담당자 확인 필요 +``` + +--- + +## 14. Calendar UI Library + +달력 UI는 MUI X Date Pickers 기반으로 구현한다. + +```txt +라이브러리: @mui/x-date-pickers +날짜 어댑터: dayjs (@mui/x-date-pickers/AdapterDayjs) +``` + +사용 범위: + +```txt +- 달력 UI +- 날짜 선택 UI +- 날짜 기반 감정일기 / 사건기록 조회 UI +``` + +구현 원칙: + +```txt +- MUI 컴포넌트는 src/components/calendar/ 내 래핑 컴포넌트를 통해서만 사용한다. +- 여러 페이지 / 도메인에서 MUI 컴포넌트를 직접 import하지 않는다. +- 달력 마킹 데이터는 TanStack Query로 조회한다. +- 선택 날짜 상태는 Zustand로 관리한다. +- 전체 스타일 기준은 SCSS / SCSS Module을 유지한다. +- MUI는 달력 / 날짜 선택 UI 전용으로만 사용하며 전체 디자인 시스템에 적용하지 않는다. +``` + +--- + +## 15. Claude 작업 시 주의사항 + +```txt +- 감정일기는 사건과 직접 연결하지 않고 달력에서 독립 작성 +- 외부 캘린더 연동 구현 금지 +- 해결 여부 필드 MVP 필수 항목 여부 담당자 확인 필요 +- MUI 컴포넌트를 달력 / 날짜 선택 이외 용도로 사용하지 않는다 +- MUI 컴포넌트는 래핑 없이 페이지에서 직접 사용하지 않는다 +``` diff --git a/docs/domains/COMMON.md b/docs/domains/COMMON.md new file mode 100644 index 0000000..c5c0f27 --- /dev/null +++ b/docs/domains/COMMON.md @@ -0,0 +1,141 @@ +# COMMON Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +앱 전반에서 공유하는 공통 기능을 담당한다. +에러 처리, 공통 응답 구조, 로그 기준, 삭제/비식별 처리, 네비게이션, 보안 유틸을 포함한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-COM-001 +FR-COM-002 +FR-COM-003 +FR-COM-004 +FR-COM-005 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 뒤로가기 +- 메인 이동 +- 앱 내 배너 이동 +- Footer 약관 링크 +- 로그인 실패 및 returnUrl 처리 +- 공통 에러 처리 (try-catch 기반) +- 공통 API 응답 구조 +- 공통 로그 기준 +- 삭제 / 비식별 처리 +``` + +--- + +## 6. 제외 기능 + +```txt +- 도메인별 개별 비즈니스 로직 +- Sentry 연동 (MVP 제외, Vercel Logs 기준 운영) +- 푸시 알림 +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/landing/ +src/components/layout/ +src/components/feedback/ +``` + +--- + +## 8. 관련 API + +```txt +공통 응답 구조는 모든 /api/v1/* 에 적용 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +TODO: ERD 확정 후 작성 +``` + +--- + +## 10. 상태 전이 + +공통 도메인에 별도 상태 전이 없음. + +--- + +## 11. 권한 규칙 + +```txt +공통 에러 응답: 권한 없는 접근 시 401 / 403 반환 +삭제/비식별 처리: 본인 또는 관리자 권한 기준 (추후 확정) +``` + +--- + +## 12. UI 연결 지점 + +```txt +공통 에러 처리: src/lib/api/ +공통 유틸: src/lib/utils/ +보안 유틸: src/lib/security/ +공통 레이아웃: src/components/layout/ +공통 피드백 UI: src/components/feedback/ +``` + +--- + +## 13. 예외 상황 + +```txt +- API 오류 시 공통 에러 응답 구조 반환 +- DB 실패 시 로그 기록 (원문 포함 금지) +- 삭제/비식별 처리 중 오류 시 롤백 기준 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- 민감 정보(사건 원문, 감정일기 원문, 개인정보)를 로그에 저장하지 않음 +- 공통 로직을 도메인 내부에 중복 구현하지 않음 +- 공통 폴더 구조 변경은 팀 승인 필요 (CLAUDE.md 15항 참고) +``` diff --git a/docs/domains/DIARY.md b/docs/domains/DIARY.md new file mode 100644 index 0000000..bc09fc7 --- /dev/null +++ b/docs/domains/DIARY.md @@ -0,0 +1,143 @@ +# DIARY Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +감정일기 작성, 조회, 원문 보호를 담당한다. +작성자 본인만 조회 가능하며, 원문은 외부에 노출하지 않는다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-DIARY-001 +FR-DIARY-002 +FR-DIARY-003 +FR-DIARY-004 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 날짜 기준 감정일기 작성 +- 감정일기 조회 (본인만) +- 감정 키워드 / 감정 상태 (확장 가능성 확인 필요) +- 원문 보호 +``` + +--- + +## 6. 제외 기능 + +```txt +- 감정일기 통계 화면 독립 노출 (MVP 제외) +- 감정일기 공유 이미지 생성 (금지) +- 외부 추천 기능에 원문 전달 (금지) +- 감정일기 원문 및 첨부 이미지 Supabase Storage 저장 (MVP 제외 — 추후 확장 시 별도 보안 정책 필요) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/diary/ +src/app/page/calendar/ 달력에서 일기 마킹 연계 +``` + +--- + +## 8. 관련 API + +```txt +POST /api/v1/diaries 일기 작성 +GET /api/v1/diaries 일기 목록 조회 +GET /api/v1/diaries/:id 일기 상세 조회 +PATCH /api/v1/diaries/:id 일기 수정 +DELETE /api/v1/diaries/:id 일기 삭제 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +emotion_diaries 감정일기 원문 및 감정 정보 +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +별도 상태 전이 없음. + +--- + +## 11. 권한 규칙 + +```txt +감정일기 조회: emotion_diaries.user_id 기준 +본인 일기만 접근 가능 +타인 일기 접근 금지 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/diary/ +일기 화면: src/app/page/diary/ +달력 연계: src/domains/calendar/ 와 마킹 연결 +날짜 선택: 달력 날짜 선택 UI는 MUI X Date Pickers 기반 래핑 컴포넌트(src/components/calendar/)를 사용한다 +``` + +--- + +## 13. 예외 상황 + +```txt +- 같은 날짜에 중복 작성 가능 여부 확인 필요 +- 감정 키워드 목록 마스터 데이터 관리 방식 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- 감정일기 원문을 통계에 노출하지 않음 +- 공유 이미지에 원문 포함 금지 +- 외부 추천 기능에 원문 전달 금지 +- 로그에 원문 저장 금지 +- 감정일기 원문 및 첨부 이미지는 MVP에서 Supabase Storage 저장 대상이 아님 +- 추후 첨부 이미지 기능 추가 시 별도 보안 정책(접근 권한, signed URL 등) 수립 필요 +``` diff --git a/docs/domains/DISPUTE.md b/docs/domains/DISPUTE.md new file mode 100644 index 0000000..80426e5 --- /dev/null +++ b/docs/domains/DISPUTE.md @@ -0,0 +1,186 @@ +# DISPUTE Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +1:1 조정 전환, 참여자(role_a / role_b), 양측 진술 작성, dispute_status 상태 관리를 담당한다. +상대방 참여 후 사건이 생성되며, 양측 진술 완료 후 AI 판결로 이어진다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-INVITE-001 +FR-INVITE-002 +FR-INVITE-003 +FR-INVITE-004 +FR-INVITE-005 +FR-INVITE-006 +FR-STATEMENT-001 +FR-STATEMENT-002 +FR-STATEMENT-003 +FR-STATEMENT-004 +FR-STATEMENT-005 +FR-CLOSE-001 +FR-CLOSE-002 +FR-DELETE-001 +FR-DELETE-002 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 상대방 참여 (초대 링크 기반) +- 1:1 조정 전환 (role_a / role_b 확정) +- 양측 진술 작성 +- 진술 종료 +- dispute_status 상태 관리 +- 사건 종료 / 만료 / 삭제 +- 비식별 처리 +``` + +--- + +## 6. 제외 기능 + +```txt +- AI 대화방 없이 바로 1:1 사건 생성 (금지) +- 단독 판결 (MVP 제외) +- 동일 사용자의 role_a / role_b 동시 보유 (금지) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/disputes/ +src/app/page/join/ +``` + +--- + +## 8. 관련 API + +```txt +POST /api/v1/disputes 사건 생성 (1:1 전환) +GET /api/v1/disputes/:id 사건 상세 조회 +POST /api/v1/disputes/:id/statements 진술 작성 +POST /api/v1/disputes/:id/statements/submit 진술 종료 +POST /api/v1/disputes/:id/close 사건 종료 +DELETE /api/v1/disputes/:id 사건 삭제 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +disputes 사건 정보, dispute_status +dispute_participants 참여자 (role_a / role_b) +dispute_statements 양측 진술 +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +기준: `docs/db/STATUS_TRANSITION.md` + +```txt +draft + │ 상대방 참여 대기 + ▼ +waiting_opponent + │ 상대방 참여 + ▼ +opponent_joined + │ 양측 진술 완료 + ▼ +both_submitted + │ AI 판결 요청 + ▼ +judging + │ AI 판결 완료 + ▼ +judged + │ 종료 / 만료 / 삭제 + ▼ +closed / expired / deleted +``` + +--- + +## 11. 권한 규칙 + +```txt +사건 조회: dispute_participants.user_id 기준 +진술 작성: 본인 role 기준 (role_a 또는 role_b) +진술 종료: 본인 role 기준 +사건 삭제: TODO: 권한 기준 확정 필요 +비식별 처리: TODO: 권한 기준 확정 필요 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/dispute/ +참여 페이지: src/app/page/join/ +사건 페이지: src/app/page/disputes/ +``` + +--- + +## 13. 예외 상황 + +```txt +- 생성자 본인이 role_b로 참여 시도 → 차단 +- 이미 role_b가 존재하는 방에 추가 참여 → 차단 +- 만료된 초대 링크 접근 → 차단 +- 진술 종료 중복 요청 → 멱등성 처리 필요 +- AI 판결 생성 중복 요청 → 멱등성 처리 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- AI 대화방 단계에서는 role_a / role_b 확정 로직 구현 금지 +- 1:1 전환 시 생성자를 role_a로 확정, 상대방을 role_b로 확정 +- 동일 사용자가 role_a / role_b 동시 보유하는 로직 구현 금지 +- 하나의 role에 진술 1개만 허용 +- 진술 종료 / 초대 참여 / 삭제 요청은 중복 방지 처리 필요 +- jailed 상태명 사용 금지 +- 상태 전이 임의 변경 금지 (팀 승인 필요) +``` diff --git a/docs/domains/GIFT.md b/docs/domains/GIFT.md new file mode 100644 index 0000000..447420c --- /dev/null +++ b/docs/domains/GIFT.md @@ -0,0 +1,130 @@ +# GIFT Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +판결 완료 후 선물추천 기능을 담당한다. +더 잘못한 쪽에게 선물을 추천하며, 최소한의 정보만 수집하여 추천 목록을 제공한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-GIFT-001 +FR-GIFT-002 +FR-GIFT-003 +FR-GIFT-004 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 판결 이후 선물추천 스티커 또는 버튼 제공 +- 나이대 / 성별 등 최소 정보 수집 +- 1~3개 수준의 추천 목록 제공 +- 선물추천 문구 (AI 판결 결과에 포함) +``` + +--- + +## 6. 제외 기능 + +```txt +- 내부 결제 (MVP 제외) +- 카카오톡 선물하기 직접 연동 (MVP 제외) +- 외부 상품 API 직접 연동 (MVP 제외) +- 포인트 기반 구매 (MVP 제외) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/disputes/ 판결 결과 페이지 내 선물추천 진입점 +``` + +--- + +## 8. 관련 API + +```txt +TODO: API 명세서 확정 후 작성 +``` + +--- + +## 9. 관련 테이블 + +```txt +gift_recommendations 추천 정보 (TODO: ERD 확정 후 작성) +``` + +--- + +## 10. 상태 전이 + +판결 완료(dispute_status = judged) 이후 접근 가능. +별도 상태 전이 없음. + +--- + +## 11. 권한 규칙 + +```txt +선물추천 접근: 해당 dispute 참여자만 가능 +타인 선물추천 결과 접근 금지 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/gift/ +판결 결과 페이지 내 연결 +``` + +--- + +## 13. 예외 상황 + +```txt +- 판결 미완료 상태에서 선물추천 접근 → 차단 +- 추천 API 실패 시 처리 기준 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- 갈등 원문을 외부 선물추천 API에 전달 금지 +- 내부 결제 / 카카오톡 선물하기 / 외부 상품 API 연동 구현 금지 +- 포인트 기반 구매 로직 구현 금지 +- 상세 추천 로직은 API_SPEC 확정 후 담당자가 구현 +``` diff --git a/docs/domains/JUDGEMENT.md b/docs/domains/JUDGEMENT.md new file mode 100644 index 0000000..51e470d --- /dev/null +++ b/docs/domains/JUDGEMENT.md @@ -0,0 +1,179 @@ +# JUDGEMENT Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +AI 판결 생성, Gemini API 연동, 판결 결과 저장 및 조회를 담당한다. +양측 진술 완료 후 AI 판결을 생성하고, 결과를 카드 형태로 제공한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-AI-001 +FR-AI-002 +FR-AI-003 +FR-AI-004 +FR-AI-005 +FR-RESULT-001 +FR-RESULT-002 +FR-RESULT-003 +FR-RESULT-004 +FR-CARD-001 +FR-CARD-002 +FR-CARD-003 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- AI 판결 생성 요청 (Gemini API) +- 판결 결과 저장 +- 판결 결과 조회 +- 판결 결과 카드 생성 +- 결과 카드 이미지 추출 (html-to-image) +- 결과 카드 이미지 저장 (Supabase Storage result-cards bucket) +- 16가지 세부 결과 유형 중 AI 도출 유형 표시 +``` + +판결 결과 포함 항목: + +```txt +- A/B 판결 점수 +- 핵심 쟁점 요약 +- 판결 근거 +- 화해 제안 +- 화해 메시지 +- 결과 카드용 요약 +- 선물추천 문구 +- 세부 결과 유형 (DB 마스터 기준) +``` + +--- + +## 6. 제외 기능 + +```txt +- A/B 공감 지수 (구현 금지) +- A/B 소통 태도 점수 (구현 금지) +- 결과 유형 Enum 하드코딩 (구현 금지) +- 공유 이미지에 사건 원문 포함 (금지) +- 결과 카드에 개인정보 포함 (금지) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/disputes/ 판결 결과 확인 +``` + +--- + +## 8. 관련 API + +```txt +POST /api/v1/disputes/:id/judge AI 판결 요청 +GET /api/v1/disputes/:id/result 판결 결과 조회 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +judgements 판결 결과 +judgement_result_types 결과 유형 마스터 (Enum 대신 DB 관리) +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +dispute_status = judging → judged 로 전환. +기준: `docs/db/STATUS_TRANSITION.md` + +--- + +## 11. 권한 규칙 + +```txt +판결 결과 조회: 해당 dispute의 참여자(role_a / role_b)만 가능 +타인 판결 결과 접근 금지 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/judgement/ +AI 연동: src/lib/ai/ +결과 카드 추출: html-to-image 활용 +결과 카드 저장: Supabase Storage result-cards bucket (서버 API Route를 통해 업로드) +``` + +### Storage 접근 원칙 + +```txt +- 결과 카드 이미지 업로드는 Next.js API Route를 통해 서버에서 처리한다. +- 클라이언트에서 SUPABASE_SERVICE_ROLE_KEY를 직접 사용하지 않는다. +- 공개 가능한 결과 카드는 public URL 또는 signed URL 정책을 구현 단계에서 확정한다. +- 결과 카드에 개인정보 및 사건 원문을 포함하지 않는다. +``` + +--- + +## 13. 예외 상황 + +```txt +- Gemini API 실패 → 구분 처리 필요 (API 오류 / JSON 파싱 실패 / timeout) +- AI 판결 생성 중복 요청 → 멱등성 처리 필요 +- 판결 생성 중 상태(judging)에서 추가 요청 → 차단 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- A/B 공감 지수 / 소통 태도 점수 구현 절대 금지 +- 결과 유형 Enum 하드코딩 금지. DB 마스터 기준으로 관리 (docs/db/MASTER_DATA.md 참고) +- Gemini API 실패 / JSON 파싱 실패 / timeout 각각 구분 처리 +- 공유 이미지에 사건 원문 포함 금지 +- 결과 카드에 개인정보 포함 금지 +- AI 판결 생성 요청 중복 방지 처리 필요 +- Gemini API 프롬프트 구조 변경은 팀 승인 필요 (CLAUDE.md 15항 참고) +- 결과 카드 이미지 저장은 Supabase Storage result-cards bucket 사용 +- Storage 업로드는 반드시 서버(API Route)를 통해 처리하며 클라이언트에서 직접 업로드 금지 +- src/lib/supabase 또는 src/lib/storage 폴더 생성은 실제 구현 단계에서 진행 +``` diff --git a/docs/domains/PERSONAL_ANALYSIS.md b/docs/domains/PERSONAL_ANALYSIS.md new file mode 100644 index 0000000..12bea0f --- /dev/null +++ b/docs/domains/PERSONAL_ANALYSIS.md @@ -0,0 +1,126 @@ +# PERSONAL_ANALYSIS Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +AI 대화 기반 개인 갈등 분석 흐름을 담당한다. +상대방 참여 전 단계에서 AI와의 대화를 통해 갈등 정리, 감정 정리, 대화 방향 조언을 제공한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +TODO: 기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- AI와 갈등 상황 정리 대화 +- 감정 정리 지원 +- 대화 방향 조언 제공 +- 개인 분석 결과 조회 (담당자 확인 필요) +``` + +--- + +## 6. 제외 기능 + +```txt +- 상대방 없는 단독 판결 (MVP 제외) +- AI 대화방 단계에서 판결 점수 생성 (금지) +- A/B 공감 지수 (구현 금지) +- A/B 소통 태도 점수 (구현 금지) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/personal-analyses/ +``` + +--- + +## 8. 관련 API + +```txt +TODO: API 명세서 확정 후 작성 +``` + +--- + +## 9. 관련 테이블 + +```txt +TODO: ERD / PRISMA_MAPPING 확정 후 작성 +``` + +--- + +## 10. 상태 전이 + +개인 분석 단계는 room_mode = ai_chat 상태에서 이루어진다. +별도 상태 전이 없음. 기준: `docs/db/STATUS_TRANSITION.md` + +--- + +## 11. 권한 규칙 + +```txt +개인 분석 조회: creator_user_id 기준 +타인 데이터 접근 금지 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/personal-analysis/ +AI 대화: ROOM 도메인과 연계 +``` + +--- + +## 13. 예외 상황 + +```txt +- Gemini API 실패 시 재시도 / 오류 안내 +- 대화 중 연결 끊김 처리 기준 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- 상대방 없는 단독 판결 구현 금지 (MVP 제외) +- AI 대화방 단계에서 판결 점수 생성 로직 구현 금지 +- 이 도메인 상세 설계는 기능 요구사항 정의서 확인 후 담당자가 보강 +``` diff --git a/docs/domains/POINTS_FUTURE.md b/docs/domains/POINTS_FUTURE.md new file mode 100644 index 0000000..2fccccc --- /dev/null +++ b/docs/domains/POINTS_FUTURE.md @@ -0,0 +1,39 @@ +# POINTS — v2.0 확장 예정 + +> 이 문서는 구현 문서가 아닙니다. +> points 도메인은 MVP 제외이며 v2.0 확장 예정입니다. + +--- + +## MVP 상태 + +```txt +- MVP에서 구현하지 않음 +- src/domains/points 생성 금지 +- 판결 완료 포인트 지급 로직 구현 금지 +- 포인트 조회 / 적립 / 사용 API 구현 금지 +``` + +--- + +## MVP 제외 이유 + +```txt +- 포인트 거래 정합성 설계 복잡도 +- 멱등성 / 중복 지급 방지 설계 미확정 +- shop / user-items 도메인과 함께 재설계 필요 +- MVP 핵심 흐름(갈등 조정 판결)에 포함되지 않음 +``` + +--- + +## v2.0 확장 시 검토 항목 + +```txt +- 포인트 적립 기준 (판결 완료 / 일기 작성 등) +- 포인트 사용처 (shop 연동) +- 포인트 거래 정합성 및 멱등성 설계 +- shop / user-items 도메인과 함께 재설계 +``` + +상세 요구사항은 v2.0 기획 확정 후 별도 문서에 작성한다. diff --git a/docs/domains/README.md b/docs/domains/README.md new file mode 100644 index 0000000..942409d --- /dev/null +++ b/docs/domains/README.md @@ -0,0 +1,69 @@ +# domains/README.md + +도메인 문서 관리 안내 + +--- + +## 1. 목적 + +도메인별 상세 설계 문서를 관리한다. +루트 `CLAUDE.md`에는 도메인 상세 설계를 넣지 않는다. +Claude Code는 작업 전 해당 도메인 문서를 반드시 확인한다. + +--- + +## 2. MVP 도메인 + +| 도메인 | 설명 | +|--------|------| +| `auth` | 카카오 로그인, 약관 동의 | +| `common` | 공통 유틸, 공유 컴포넌트 기반 | +| `room` | AI 대화방 생성, 초대 링크 | +| `personal-analysis` | 개인 갈등 분석 | +| `dispute` | 1:1 조정 사건 | +| `judgement` | AI 판결 생성 및 결과 | +| `gift` | 선물 추천 | +| `user` | 마이페이지, 사용자 정보 | +| `calendar` | 달력 | +| `diary` | 감정일기 | +| `statistics` | 요약 통계 API, 홈·마이페이지 통계 컴포넌트 | + +`statistics`는 독립 화면이 아니다. MVP에서는 API 및 컴포넌트 중심으로만 사용한다. + +--- + +## 3. v2.0 확장 예정 도메인 + +```txt +shop +points +user-items +``` + +MVP에서 구현하지 않는다. +필요 시 `docs/domains/*_FUTURE.md`에 정리한다. + +--- + +## 4. 작성 원칙 + +```txt +각 담당자가 _DOMAIN_TEMPLATE.md를 기반으로 도메인 문서를 작성한다. +업무 분배표와 기능 요구사항 ID를 확인 후 작성한다. +도메인 문서가 없으면 Claude Code는 해당 도메인 로직을 임의 구현하지 않는다. +``` + +--- + +## 5. 파일 네이밍 + +```txt +docs/domains/ROOM.md +docs/domains/DISPUTE.md +docs/domains/JUDGEMENT.md +docs/domains/GIFT.md +docs/domains/USER.md +docs/domains/CALENDAR.md +docs/domains/DIARY.md +docs/domains/STATISTICS.md +``` diff --git a/docs/domains/ROOM.md b/docs/domains/ROOM.md new file mode 100644 index 0000000..b196d51 --- /dev/null +++ b/docs/domains/ROOM.md @@ -0,0 +1,164 @@ +# ROOM Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +AI 대화방 생성, AI 대화, 초대 링크 발급, room_mode 상태 관리를 담당한다. +모든 갈등 조정은 AI 대화방에서 시작하며, 상대방 초대 전까지 AI와의 갈등 정리 단계를 유지한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-ROOM-001 +FR-ROOM-002 +FR-ROOM-003 +FR-ROOM-004 +FR-ROOM-005 +FR-ROOM-006 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- AI 대화방 생성 (카테고리 선택 포함) +- AI와 갈등 상황 정리 대화 +- 초대 링크 발급 +- room_mode 상태 관리 +- 방 목록 / 사건기록 조회 +- 방 종료 / 만료 / 삭제 처리 +``` + +--- + +## 6. 제외 기능 + +```txt +- AI 대화방 없이 바로 1:1 사건 생성 (금지) +- AI 대화방 단계의 판결 점수 생성 (금지) +- 상대방 없는 단독 판결 (MVP 제외) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/home/ +src/app/page/rooms/ +src/app/page/join/ +``` + +--- + +## 8. 관련 API + +```txt +POST /api/v1/rooms 방 생성 +GET /api/v1/rooms 방 목록 조회 +GET /api/v1/rooms/:id 방 상세 조회 +POST /api/v1/rooms/:id/invite 초대 링크 발급 +POST /api/v1/rooms/:id/close 방 종료 +DELETE /api/v1/rooms/:id 방 삭제 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +dispute_rooms 방 정보, room_mode, room_token_hash +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +기준: `docs/db/STATUS_TRANSITION.md` + +```txt +ai_chat + │ 초대 링크 발급 + ▼ +invite_ready + │ 상대방 참여 + ▼ +one_to_one + │ 종료 / 만료 / 삭제 + ▼ +closed / expired / deleted +``` + +--- + +## 11. 권한 규칙 + +```txt +방 조회: creator_user_id 기준 (ai_chat / invite_ready 단계) +1:1 이후 조회: dispute_participants.user_id 기준 +초대 링크 접근: 만료 / 삭제 방 차단 +생성자 본인 초대 링크 참여: 차단 +이미 role_b 존재 시 추가 참여: 차단 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/room/ +AI 대화 UI: src/app/page/rooms/ +초대 참여: src/app/page/join/ +``` + +--- + +## 13. 예외 상황 + +```txt +- 만료된 초대 링크 접근 → 차단 및 안내 메시지 +- 삭제된 방 접근 → 차단 +- 생성자 본인이 초대 링크로 role_b 참여 시도 → 차단 +- 이미 role_b가 존재하는 방에 추가 참여 시도 → 차단 +- AI 대화 중 Gemini API 실패 → 재시도 / 오류 안내 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- room_token 원문은 DB에 저장하지 않음. room_token_hash만 저장 +- AI 대화방 단계에서 판결 점수 생성 로직 구현 금지 +- AI 대화방 없이 바로 1:1 사건 생성 흐름 구현 금지 +- 카테고리는 연애/가족/친구/직장 4개만 사용 (6개 구버전 금지) +- 상태 전이 임의 변경 금지 (팀 승인 필요) +``` diff --git a/docs/domains/SHOP_FUTURE.md b/docs/domains/SHOP_FUTURE.md new file mode 100644 index 0000000..5056e2b --- /dev/null +++ b/docs/domains/SHOP_FUTURE.md @@ -0,0 +1,39 @@ +# SHOP — v2.0 확장 예정 + +> 이 문서는 구현 문서가 아닙니다. +> shop 도메인은 MVP 제외이며 v2.0 확장 예정입니다. + +--- + +## MVP 상태 + +```txt +- MVP에서 구현하지 않음 +- src/domains/shop 생성 금지 +- shop 관련 API 구현 금지 +- shop 관련 화면 구현 금지 +``` + +--- + +## MVP 제외 이유 + +```txt +- 내부 결제 연동 복잡도 +- 카카오톡 선물하기 직접 연동 정책 미확정 +- 외부 상품 API 직접 연동 정책 미확정 +- MVP 핵심 흐름(갈등 조정 판결)에 포함되지 않음 +``` + +--- + +## v2.0 확장 시 검토 항목 + +```txt +- 내부 결제 연동 방식 결정 +- 카카오톡 선물하기 연동 가능 여부 재검토 +- 외부 상품 API 파트너십 검토 +- points / user-items 도메인과 함께 재설계 +``` + +상세 요구사항은 v2.0 기획 확정 후 별도 문서에 작성한다. diff --git a/docs/domains/STATISTICS.md b/docs/domains/STATISTICS.md new file mode 100644 index 0000000..c7970bd --- /dev/null +++ b/docs/domains/STATISTICS.md @@ -0,0 +1,142 @@ +# STATISTICS Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +전체 사용자 갈등 데이터 익명 집계, 통계 API, 홈/마이페이지 요약 통계 컴포넌트를 담당한다. +독립 화면은 MVP 제외이며, API와 컴포넌트 중심으로만 운영한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-STATS-001 +FR-STATS-002 +FR-STATS-003 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 전체 사용자 갈등 데이터 익명화 집계 +- 결과 유형 Top5 집계 +- 홈 화면 내 요약 통계 컴포넌트 +- 마이페이지 내 요약 통계 컴포넌트 +- 통계 API +``` + +--- + +## 6. 제외 기능 + +```txt +- statistics 독립 화면 (MVP 제외) +- 개인 식별 정보 포함 통계 +- 진술 원문 포함 통계 +- 감정일기 원문 포함 통계 +- Supabase Storage URL 포함 통계 (개인 식별 가능 정보로 간주) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/home/ 홈 내 요약 통계 컴포넌트 +src/app/page/mypage/ 마이페이지 내 요약 통계 컴포넌트 +``` + +독립 statistics 화면은 생성하지 않는다. + +--- + +## 8. 관련 API + +```txt +GET /api/v1/statistics/summary 요약 통계 조회 +GET /api/v1/statistics/top-types 결과 유형 Top5 조회 +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +judgements 판결 집계 기준 +judgement_result_types 결과 유형 마스터 +``` + +상세 구조는 `docs/ERD.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +별도 상태 전이 없음. + +--- + +## 11. 권한 규칙 + +```txt +통계 API: 로그인 사용자 접근 가능 +개인 식별 정보 없이 익명 집계만 제공 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/statistics/ +홈 컴포넌트: src/components/ 또는 src/app/page/home/ +마이페이지 컴포넌트: src/app/page/mypage/ +차트: recharts 활용 +``` + +--- + +## 13. 예외 상황 + +```txt +- 집계 데이터 없을 경우 빈 상태 UI 처리 필요 +- 통계 집계 쿼리 성능 기준 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- statistics 독립 화면 생성 금지 +- 통계 데이터에 개인 식별 정보 포함 금지 +- 진술 원문 / 감정일기 원문 통계에 저장 금지 +- 결과 유형은 DB 마스터 기준으로 집계 (Enum 하드코딩 금지) +- Storage URL / 진술 원문 / 감정일기 원문 등 개인 식별 가능 정보 포함 금지 +``` diff --git a/docs/domains/USER.md b/docs/domains/USER.md new file mode 100644 index 0000000..858b6d3 --- /dev/null +++ b/docs/domains/USER.md @@ -0,0 +1,137 @@ +# USER Domain Document + +> 작성자: TODO: 담당자 확인 필요 +> 최종 수정일: 2026-06-15 + +--- + +## 1. 도메인 목적 + +사용자 정보, 마이페이지, 프로필 관리, 하단 탭 접근, 회원탈퇴 연결을 담당한다. + +--- + +## 2. 담당자 + +```txt +FE: TODO: 담당자 확인 필요 +BE: TODO: 담당자 확인 필요 +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-MYPAGE-001 +FR-MYPAGE-002 +FR-NAV-001 +FR-NAV-002 +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +TODO: 비기능 요구사항 정의서 확인 후 작성 +``` + +--- + +## 5. 포함 기능 + +```txt +- 마이페이지 조회 +- 프로필 수정 +- MBTI 선택 / 수정 +- 하단 탭 접근 +- 회원탈퇴 진입 (처리는 AUTH 도메인) +- 홈/마이페이지 내 요약 통계 컴포넌트 연결 +``` + +--- + +## 6. 제외 기능 + +```txt +- 관리자 페이지 (MVP 제외) +- 푸시 알림 설정 (MVP 제외) +- 포인트 / 아이템 관리 (MVP 제외) +- 프로필 이미지 업로드 (MVP 필수 아님 — 추후 Supabase Storage 확장 대상으로 검토) +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/mypage/ +src/app/page/home/ +``` + +--- + +## 8. 관련 API + +```txt +GET /api/v1/users/me 내 정보 조회 +PATCH /api/v1/users/me 프로필 수정 +DELETE /api/v1/users/me 회원탈퇴 (AUTH 도메인과 연계) +``` + +상세 스펙은 `docs/API_SPEC.md` 확정 후 작성. + +--- + +## 9. 관련 테이블 + +```txt +users 사용자 정보 +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 확정 후 작성. + +--- + +## 10. 상태 전이 + +별도 상태 전이 없음. + +--- + +## 11. 권한 규칙 + +```txt +내 정보 조회/수정: 본인만 가능 +타인 정보 접근 금지 +``` + +--- + +## 12. UI 연결 지점 + +```txt +도메인 훅: src/domains/user/ +마이페이지: src/app/page/mypage/ +요약 통계 컴포넌트: src/components/ (STATISTICS 도메인 연계) +``` + +--- + +## 13. 예외 상황 + +```txt +- 프로필 이미지 업로드는 MVP 필수 아님. 추후 Supabase Storage 확장 시 별도 정책 수립 필요 +- 회원탈퇴 처리 중 오류 시 롤백 기준 확인 필요 +``` + +--- + +## 14. Claude 작업 시 주의사항 + +```txt +- 사용자 민감정보 최소 수집 +- 프로필 이미지 업로드는 MVP 구현 금지. 추후 Supabase Storage 확장 단계에서 별도 브랜치로 진행 +- 포인트 / 아이템 관련 로직 구현 금지 +``` diff --git a/docs/domains/USER_ITEMS_FUTURE.md b/docs/domains/USER_ITEMS_FUTURE.md new file mode 100644 index 0000000..d6cfa9d --- /dev/null +++ b/docs/domains/USER_ITEMS_FUTURE.md @@ -0,0 +1,38 @@ +# USER_ITEMS — v2.0 확장 예정 + +> 이 문서는 구현 문서가 아닙니다. +> user-items 도메인은 MVP 제외이며 v2.0 확장 예정입니다. + +--- + +## MVP 상태 + +```txt +- MVP에서 구현하지 않음 +- src/domains/user-items 생성 금지 +- 테마 / 프로필 꾸미기 아이템 적용 로직 구현 금지 +- 아이템 보유 조회 / 적용 API 구현 금지 +``` + +--- + +## MVP 제외 이유 + +```txt +- shop / points 도메인과 함께 재설계 필요 +- 아이템 적용 UX 정책 미확정 +- MVP 핵심 흐름(갈등 조정 판결)에 포함되지 않음 +``` + +--- + +## v2.0 확장 시 검토 항목 + +```txt +- 아이템 종류 (테마, 프로필 꾸미기 등) +- 아이템 획득 방식 (shop 구매 / 포인트 교환 등) +- 아이템 적용 UX 및 저장 방식 +- shop / points 도메인과 함께 재설계 +``` + +상세 요구사항은 v2.0 기획 확정 후 별도 문서에 작성한다. diff --git a/docs/domains/_DOMAIN_TEMPLATE.md b/docs/domains/_DOMAIN_TEMPLATE.md new file mode 100644 index 0000000..0d0c283 --- /dev/null +++ b/docs/domains/_DOMAIN_TEMPLATE.md @@ -0,0 +1,140 @@ +# [도메인명] Domain Document + +> 작성자: +> 최종 수정일: + +--- + +## 1. 도메인 목적 + +이 도메인이 담당하는 책임과 범위를 한 문단으로 요약한다. + +--- + +## 2. 담당자 + +```txt +FE: +BE: +``` + +--- + +## 3. 관련 기능 요구사항 ID + +```txt +FR-xxx +FR-xxx +``` + +--- + +## 4. 관련 비기능 요구사항 ID + +```txt +NFR-xxx +``` + +--- + +## 5. 포함 기능 + +이 도메인에서 구현하는 기능 목록. + +```txt +- +- +``` + +--- + +## 6. 제외 기능 + +MVP 제외이거나 이 도메인 범위 밖인 기능. + +```txt +- +- +``` + +--- + +## 7. 관련 화면 + +```txt +src/app/page/[경로] +``` + +--- + +## 8. 관련 API + +```txt +GET /api/v1/[경로] +POST /api/v1/[경로] +``` + +상세 스펙은 `docs/API_SPEC.md` 참고. + +--- + +## 9. 관련 테이블 + +```txt +테이블명 — 용도 +``` + +상세 구조는 `docs/ERD.md` 및 `docs/db/PRISMA_MAPPING.md` 참고. + +--- + +## 10. 상태 전이 + +해당 도메인에 상태 전이가 있는 경우 작성. 없으면 생략. + +```txt +상태A → 상태B → 상태C +``` + +기준: `docs/db/STATUS_TRANSITION.md` + +--- + +## 11. 권한 규칙 + +```txt +조회: +수정: +삭제: +``` + +--- + +## 12. UI 연결 지점 + +```txt +공통 컴포넌트 사용: src/components/... +도메인 훅: src/domains/[도메인]/hooks/... +``` + +--- + +## 13. 예외 상황 + +처리해야 할 예외 케이스 목록. + +```txt +- +- +``` + +--- + +## 14. Claude 작업 시 주의사항 + +이 도메인 작업 시 Claude Code가 반드시 확인해야 할 사항. + +```txt +- +- +``` diff --git a/docs/guides/.gitkeep b/docs/guides/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/guides/CLAUDE_WORKFLOW.md b/docs/guides/CLAUDE_WORKFLOW.md new file mode 100644 index 0000000..13e6e02 --- /dev/null +++ b/docs/guides/CLAUDE_WORKFLOW.md @@ -0,0 +1,99 @@ +# CLAUDE_WORKFLOW.md + +Claude Code 작업 절차 가이드 + +> 기준 문서: `CLAUDE.md` (섹션 13–15) + +--- + +## 1. 기본 작업 절차 + +```txt +1. 관련 문서 확인 + CLAUDE.md / PROJECT_DECISIONS.md / 해당 도메인 docs/domains/*.md + +2. 작업 계획 제시 + 변경 파일 목록, 예상 범위, 주의사항 포함 + +3. 사용자 승인 대기 + 계획 확인 전 구현 금지 + +4. 구현 + +5. 검증 + lint / type-check / 기능 확인 + +6. 변경 파일 요약 + +7. 커밋 / PR 안내 +``` + +문서가 없거나 문서 간 충돌이 있으면 구현하지 말고 질문한다. + +--- + +## 2. 작업 전 확인 문서 + +```txt +CLAUDE.md +docs/PROJECT_DECISIONS.md +docs/guides/GIT_WORKFLOW.md +docs/db/STATUS_TRANSITION.md +docs/domains/[해당 도메인].md +``` + +도메인 문서가 없으면 담당자에게 문서 작성을 요청한다. + +--- + +## 3. STOP 조건 + +아래 상황에서 즉시 중단하고 사용자에게 확인한다. + +```txt +ERD 없이 Prisma schema 변경이 필요한 경우 +상태 전이 규칙 변경이 필요한 경우 +권한 쿼리 변경이 필요한 경우 +API 응답 구조 변경이 필요한 경우 +MVP 제외 기능 구현 요청이 발생한 경우 +shop / points / user-items 구현이 필요한 경우 +6개 카테고리 기준 구현이 필요한 경우 +공감 지수 / 소통 태도 점수 구현이 필요한 경우 +AI 대화방 없이 바로 1:1 사건 생성 흐름이 필요한 경우 +statistics 독립 화면 생성이 필요한 경우 +결과 유형을 Enum으로 하드코딩하려는 경우 +브랜치 없이 작업 중인 경우 +도메인별 문서가 없는데 임의로 도메인 로직을 구현하려는 경우 +``` + +--- + +## 4. 승인 필요 조건 + +아래 작업은 반드시 사용자 또는 팀 승인 후 진행한다. + +```txt +Prisma schema 변경 +DB relation 변경 +상태 전이 규칙 변경 +권한 검증 로직 변경 +API endpoint 추가 / 삭제 / 구조 변경 +카카오 OAuth 설정 변경 +Gemini API 프롬프트 구조 변경 +환경변수 추가 / 삭제 +공통 폴더 구조 변경 +MVP 제외 기능을 구현 범위로 올리는 작업 +``` + +--- + +## 5. 금지사항 + +```txt +기능 범위 임의 확장 +문서 간 충돌 무시하고 구현 +브랜치 없이 작업 +shop / points / user-items 구현 폴더 생성 +features 폴더 생성 +실제 환경변수 값 코드에 포함 +``` diff --git a/docs/guides/CODING_CONVENTION.md b/docs/guides/CODING_CONVENTION.md new file mode 100644 index 0000000..26e7614 --- /dev/null +++ b/docs/guides/CODING_CONVENTION.md @@ -0,0 +1,120 @@ +# CODING_CONVENTION.md + +코딩 컨벤션 가이드 + +--- + +## 1. 언어 및 스타일 + +```txt +언어: TypeScript (strict 모드) +스타일: SCSS Module (전역 스타일은 src/styles/) +포맷: Prettier (.prettierrc 기준) +린트: ESLint (eslint.config.mjs 기준) +``` + +--- + +## 2. 네이밍 규칙 + +| 대상 | 규칙 | 예시 | +|------|------|------| +| React 컴포넌트 | PascalCase | `RoomCard.tsx` | +| 함수 / 변수 | camelCase | `getRoomById`, `isLoading` | +| 파일명 (컴포넌트 외) | kebab-case | `room-service.ts`, `use-room.ts` | +| 상수 | UPPER_SNAKE_CASE | `MAX_ROOM_COUNT` | +| DB column | snake_case | `creator_user_id` | +| Prisma field | camelCase | `creatorUserId` | +| CSS class | kebab-case | `.room-card__title` | + +--- + +## 3. 상태 관리 기준 + +**Zustand** — UI 상태만 담당 + +```txt +모달 / 바텀시트 / 플로팅 메뉴 +선택 날짜 / 로딩 UI / 결과 카드 생성 중 상태 +``` + +**TanStack Query** — 서버 데이터 담당 + +```txt +서버 조회 데이터 / 사건 상세 / 판결 결과 +감정일기 목록 / 통계 데이터 +``` + +서버 데이터는 Zustand에 저장하지 않는다. + +--- + +## 4. 폴더 사용 기준 + +```txt +src/domains/* 도메인별 비즈니스 로직, API client, hooks, constants +src/components 공통 UI (ui / layout / feedback) +src/lib 공통 유틸, auth, api, db, ai, security, validators, constants +src/stores Zustand UI 상태 +src/types 전역 타입 +src/styles 전역 SCSS 변수, mixin, base +``` + +--- + +## 5. 금지 구조 + +```txt +src/features +src/server +src/lib/types +src/lib/stores +src/domains/*/types +src/domains/*/stores +src/app/page/*/*.type.ts +src/app/page/*/*.store.ts +``` + +--- + +## 6. 보안 주의사항 + +```txt +console.log에 사건 원문 / 개인정보 출력 금지 +API 응답에 불필요한 민감 정보 포함 금지 +권한 검증은 반드시 서버에서 수행 +클라이언트 단독 권한 검증 금지 +``` + +--- + +## 7. MUI 사용 기준 + +MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다. + +```txt +허용 범위: + src/components/calendar/ 내 래핑 컴포넌트에서만 MUI import 허용 + +금지 사항: + - 전체 디자인 시스템을 MUI 기반으로 전환하지 않는다 + - 여러 페이지 / 도메인에서 MUI 컴포넌트를 직접 import하지 않는다 + - @mui/icons-material 사용 금지 (아이콘은 lucide-react 사용) + - MUI ThemeProvider를 앱 전역에 적용하지 않는다 +``` + +스타일 기준: + +```txt +- SCSS / SCSS Module 원칙을 유지한다 +- MUI의 sx prop, styled() 사용은 래핑 컴포넌트 내부로 제한한다 +- 전역 스타일에 MUI 의존 스타일을 추가하지 않는다 +``` + +래핑 컴포넌트 원칙: + +```txt +- 달력 UI는 src/components/calendar/ 내 래핑 컴포넌트로 제공한다 +- 래핑 컴포넌트를 통해 라이브러리 교체 가능성을 유지한다 +- 래핑 컴포넌트 외부에서는 MUI 직접 의존을 갖지 않는다 +``` diff --git a/docs/guides/ENV_GUIDE.md b/docs/guides/ENV_GUIDE.md new file mode 100644 index 0000000..705331c --- /dev/null +++ b/docs/guides/ENV_GUIDE.md @@ -0,0 +1,219 @@ +# ENV_GUIDE.md + +환경변수 운영 가이드 + +--- + +## 1. 문서 목적 + +이 문서는 TALKY-OWL 프로젝트의 환경변수 관리 기준을 정의한다. + +모든 팀원은 이 문서를 기준으로 로컬 환경을 세팅하고, 환경변수를 다룰 때 반드시 준수한다. + +--- + +## 2. 환경변수 관리 원칙 + +```txt +- .env.example에는 key 이름만 작성한다. 실제 값은 작성하지 않는다. +- .env.local은 Git에 커밋하지 않는다. +- .env.local은 Claude Code가 생성하거나 읽지 않는다. +- 실제 secret 값은 메신저, PR, GitHub, Notion, 문서에 포함하지 않는다. +- Vercel Environment Variables 등록/수정은 배포 담당자 또는 PM이 수행한다. +- 팀원은 Vercel Team에 초대하지 않는다. +``` + +--- + +## 3. .env.example 관리 기준 + +`.env.example`은 Git에 포함한다. + +```txt +- key 이름만 작성하고 실제 값은 비워둔다. +- 새 환경변수가 생기면 .env.example에 key만 추가하고 PR에 포함한다. +- Vercel에는 배포 담당자가 실제 값을 별도로 등록한다. +``` + +추가 순서: + +```txt +1. .env.example에 key만 추가 +2. Vercel Dashboard > Project Settings > Environment Variables에 실제 값 등록 +3. PR에 .env.example 변경사항 포함 +4. 팀원에게 새 환경변수 추가 사실 공유 +``` + +--- + +## 4. .env.local 관리 기준 + +```txt +- .env.local은 Git에 커밋하지 않는다. +- .gitignore에 .env.local이 포함되어 있는지 확인한다. +- 로컬에서만 사용하며 팀원 간 공유하지 않는다. +- Claude Code는 .env.local을 생성하거나 읽지 않는다. +``` + +팀원 로컬 세팅 방식은 아래 섹션을 참고한다. + +--- + +## 5. Vercel Environment Variables 관리 기준 + +```txt +- Vercel Team은 사용하지 않는다. +- 배포 전용 Google 계정 1개로 Vercel Hobby 프로젝트를 운영한다. +- 팀원은 Vercel Team에 초대하지 않는다. +- Vercel Environment Variables 등록/수정은 배포 담당자 또는 PM이 수행한다. +``` + +등록 경로: + +```txt +Vercel Dashboard > 프로젝트 선택 > Settings > Environment Variables +``` + +등록 기준: + +```txt +- Production: 프로덕션 배포에 사용되는 값 +- Preview: PR Preview 배포에 사용되는 값 (필요 시) +- Development: 개발 환경 값 (필요 시) +``` + +--- + +## 6. GitHub Actions Secrets 관리 기준 + +GitHub Actions로 Vercel CLI 배포를 구성할 경우, 아래 값을 GitHub Repository Secrets에 등록한다. + +```txt +GitHub Repository > Settings > Secrets and variables > Actions +``` + +필요한 Secrets: + +```txt +VERCEL_TOKEN Vercel Personal Access Token +VERCEL_ORG_ID Vercel 프로젝트의 orgId (vercel.json 또는 .vercel/project.json 확인) +VERCEL_PROJECT_ID Vercel 프로젝트 ID +``` + +주의: + +```txt +- 위 값들은 .env.example에 포함하지 않는다. +- 실제 값은 문서에 작성하지 않는다. +- GitHub Actions workflow 파일은 별도 작업에서 생성한다. +``` + +--- + +## 7. Supabase 환경변수 + +| 키 | 용도 | 서버 전용 여부 | +|----|------|--------------| +| `DATABASE_URL` | Supabase Postgres 연결 문자열. Prisma 연결에 사용 | 서버 전용 | +| `SUPABASE_URL` | Supabase 프로젝트 URL | 공개 가능 | +| `SUPABASE_ANON_KEY` | 클라이언트 공개 범위 anon key | 공개 가능 (제한적) | +| `SUPABASE_SERVICE_ROLE_KEY` | 서버 전용 관리 key. 클라이언트 절대 노출 금지 | **서버 전용** | +| `SUPABASE_STORAGE_BUCKET_RESULT_CARDS` | 결과 카드 이미지 저장용 bucket 이름. 권장 값: `result-cards` | 서버 전용 | + +**SUPABASE_SERVICE_ROLE_KEY 주의사항:** + +```txt +- 클라이언트(브라우저) 코드에서 절대 사용하지 않는다. +- NEXT_PUBLIC_ prefix를 사용하지 않는다. +- 업로드, 삭제, 비공개 파일 접근은 Next.js API Route를 통해 서버에서만 처리한다. +``` + +--- + +## 8. NextAuth / Kakao OAuth 환경변수 + +| 키 | 용도 | +|----|------| +| `NEXTAUTH_URL` | NextAuth 콜백 URL. 로컬: `http://localhost:3030`, 프로덕션: 실제 도메인 | +| `NEXTAUTH_SECRET` | NextAuth 세션 서명 key. 서버 전용 | +| `KAKAO_CLIENT_ID` | Kakao Developers REST API Key | +| `KAKAO_CLIENT_SECRET` | Kakao OAuth Client Secret. 클라이언트 노출 금지 | + +**Kakao Redirect URI 등록 기준:** + +```txt +로컬: +http://localhost:3030/api/auth/callback/kakao + +Vercel Production: +https://[프로덕션도메인]/api/auth/callback/kakao + +Vercel Preview (필요 시): +Preview URL 기준으로 별도 등록 +``` + +Redirect URI는 Kakao Developers > 앱 > 카카오 로그인 > Redirect URI에서 등록한다. + +--- + +## 9. Gemini 환경변수 + +| 키 | 용도 | +|----|------| +| `GEMINI_API_KEY` | Google Gemini API 호출용 key | + +```txt +- 서버 API Route에서만 사용한다. +- 클라이언트 코드에서 노출 금지. +- NEXT_PUBLIC_ prefix 사용 금지. +``` + +--- + +## 10. Security 환경변수 + +| 키 | 용도 | +|----|------| +| `ROOM_TOKEN_SECRET` | 초대 링크 토큰 생성/검증 및 hash 처리에 사용하는 서버 전용 secret | +| `CRON_SECRET` | Vercel Cron 또는 서버 cron API 보호용 secret | + +--- + +## 11. 팀원 로컬 환경 세팅 방식 + +현재 프로젝트는 Vercel Team을 사용하지 않으므로, 팀원이 `vercel env pull`을 직접 사용하기 어렵다. + +**권장 방식:** + +```txt +1. 배포 담당자 또는 PM이 .env.example 기준으로 각 key의 실제 값을 별도 채널로 전달한다. + (단, 전달 방식은 보안 채널을 사용하며 PR, GitHub, 공개 문서에 작성하지 않는다.) + +2. 팀원은 전달받은 값을 바탕으로 로컬에 .env.local 파일을 직접 생성한다. + +3. .env.local은 Git에 커밋하지 않는다. +``` + +**.env.local 작성 기준:** + +```txt +.env.example의 key를 기준으로 값을 채워 넣는다. +NEXT_PUBLIC_ prefix 없는 key는 서버 전용으로 취급한다. +SUPABASE_SERVICE_ROLE_KEY, GEMINI_API_KEY, KAKAO_CLIENT_SECRET, NEXTAUTH_SECRET, ROOM_TOKEN_SECRET, CRON_SECRET는 클라이언트에 노출하지 않는다. +``` + +--- + +## 12. 금지 사항 + +```txt +- 실제 secret 값을 메신저, PR, 코드, 문서에 포함 금지 +- .env.local을 Git에 커밋 금지 +- .env.local을 Claude Code가 생성/읽는 것 금지 +- NEXT_PUBLIC_ prefix를 secret key에 사용 금지 +- SUPABASE_SERVICE_ROLE_KEY를 클라이언트 코드에서 사용 금지 +- GEMINI_API_KEY를 클라이언트 코드에서 사용 금지 +- KAKAO_CLIENT_SECRET를 클라이언트 코드에서 사용 금지 +- VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID를 .env.example에 포함 금지 +- 환경변수 값을 GitHub Issues, PR, Notion에 작성 금지 +``` diff --git a/docs/guides/GITHUB_COLLABORATION_POLICY.md b/docs/guides/GITHUB_COLLABORATION_POLICY.md new file mode 100644 index 0000000..28dd5ba --- /dev/null +++ b/docs/guides/GITHUB_COLLABORATION_POLICY.md @@ -0,0 +1,466 @@ +# GitHub 협업 정책 + +TALKY-OWL 프로젝트 GitHub 협업 정책 문서 + +--- + +## 1. 문서 목적 + +이 문서는 TALKY-OWL 팀의 GitHub 협업 기준을 정의한다. +모든 팀원은 이 문서를 숙지하고 작업 전에 참고한다. + +--- + +## 2. Repository 운영 원칙 + +```txt +Repository: https://github.com/I5-Project/TALKY-OWL +기본 브랜치: main (최종 배포), dev (개발 통합) +PR 대상: 기본 dev +main 직접 push 금지 +dev 직접 push 금지 +``` + +모든 작업은 Issue 생성 → 작업 브랜치 생성 → PR → 리뷰 → Merge 순서로 진행한다. + +--- + +## 3. Issue 운영 방식 + +```txt +- 작업 전 반드시 Issue를 먼저 생성한다. +- Issue 제목은 [Feat], [Fix], [Docs], [Chore], [Refactor], [Infra] prefix를 붙인다. +- Issue에는 작업 영역, 작업 내용, 완료 기준을 명시한다. +- 작업 브랜치 이름에 Issue 번호를 포함하는 것을 권장한다. +- PR 병합 시 Issue를 close 키워드로 연결하여 자동 종료한다. +``` + +--- + +## 4. Issue Label 정책 + +아래 Label을 사용한다. GitHub Settings > Labels에서 직접 생성한다. + +### 타입 Label + +| Label | 용도 | +|-------|------| +| `feat` | 새 기능 구현 | +| `fix` | 버그 수정 | +| `docs` | 문서 작업 | +| `refactor` | 리팩토링 | +| `chore` | 패키지, 설정, 기타 | +| `infra` | 환경설정, 인프라 | + +### 작업 영역 Label + +| Label | 용도 | +|-------|------| +| `identity-access` | 카카오 로그인, 약관, 인증 | +| `room-ai-chat` | AI 대화방 생성, AI 대화 | +| `personal-analysis` | 개인 분석 | +| `invite-participation` | 초대 링크, 상대방 참여 | +| `statement` | 진술 작성 | +| `judgement-result` | AI 판결 생성, 결과 조회 | +| `result-card-media` | 판결 결과 카드, Supabase Storage | +| `records-lifecycle` | 사건기록, 삭제, 비식별 | +| `calendar-diary` | 달력, 감정일기 | +| `statistics` | 통계 API, 통계 컴포넌트 | +| `gift-recommendation` | 선물추천 | +| `profile-mypage` | 마이페이지, 프로필 | +| `ops-common` | 공통 유틸, 에러 핸들링, Ops | + +### 상태 Label + +| Label | 용도 | +|-------|------| +| `in-progress` | 작업 중 | +| `needs-review` | 리뷰 요청 | +| `blocked` | 블로킹 이슈 존재 | +| `wontfix` | 수정하지 않음 | + +--- + +## 5. Milestone / Project Board 정책 + +```txt +Milestone: GitHub Settings > Milestones에서 직접 생성 +Project Board: GitHub Projects에서 직접 생성 +``` + +기준: + +```txt +- MVP 단계별 Milestone을 생성하여 Issue를 연결한다. +- Project Board는 Todo / In Progress / Done 컬럼 기준으로 운영한다. +- 팀원 간 작업 중복 방지를 위해 담당자(Assignee)를 반드시 지정한다. +``` + +--- + +## 6. Branch 전략 + +```txt +main ← 최종 배포 브랜치 (직접 push 금지) + └─ dev ← 개발 통합 브랜치 (직접 push 금지) + ├─ feature/* + ├─ fix/* + ├─ refactor/* + ├─ docs/* + ├─ chore/* + └─ infra/* +``` + +hotfix는 `main`에 직접 PR 후 `dev`에도 반영한다. + +```txt +hotfix/* → main → dev 반영 +``` + +--- + +## 7. Branch Naming Convention + +```txt +feature/{작업영역}-{내용} +fix/{작업영역}-{내용} +refactor/{작업영역}-{내용} +docs/{내용} +chore/{내용} +infra/{내용} +hotfix/{내용} +``` + +예시: + +```txt +feature/auth-kakao-login +feature/room-ai-chat-create-room +fix/judgement-duplicate-request +refactor/diary-query-optimization +docs/add-user-domain-spec +chore/setup-github-templates +infra/setup-eslint-config +``` + +--- + +## 8. Commit Message Convention + +```txt +feat: 새 기능 추가 +fix: 버그 수정 +docs: 문서 변경 +refactor: 리팩토링 +chore: 패키지, 설정, 기타 +infra: 환경설정, 인프라 +``` + +예시: + +```txt +feat(auth): add kakao oauth login +fix(room): resolve token expiry validation +docs(infra): confirm Supabase as project infrastructure +chore(github): add collaboration templates and policy +``` + +--- + +## 9. Pull Request 정책 + +```txt +- 작업 완료 후 dev를 대상으로 PR을 생성한다. +- PR 제목은 [Feat], [Fix], [Docs], [Chore], [Refactor], [Infra] prefix를 붙인다. +- PR Template을 반드시 작성한다. +- 리뷰어를 1명 이상 지정한다. +- 셀프 Merge 금지 (긴급 hotfix 제외). +``` + +--- + +## 10. PR과 Issue 연결 방법 + +PR 본문에 아래 키워드를 사용하면 PR Merge 시 Issue가 자동으로 닫힌다. + +```txt +close #[Issue번호] +closes #[Issue번호] +fix #[Issue번호] +resolve #[Issue번호] +``` + +예시: + +```txt +close #12 +``` + +--- + +## 11. Code Review 정책 + +```txt +- 리뷰어는 기능 범위, 문서 기준, 폴더 구조, 보안, 환경변수를 확인한다. +- 리뷰 승인(Approve) 1명 이상 필요. +- Request Changes가 있으면 수정 후 재요청한다. +- 코드 스타일 지적은 Nit: 접두사를 사용한다. +``` + +리뷰 체크 항목: + +```txt +기능 범위: MVP 외 기능 구현 여부 확인 +문서 기준: CLAUDE.md / 도메인 문서와 일치 여부 +폴더 구조: features 폴더, 금지 구조 사용 여부 +보안: 권한 검증 서버 수행 여부, 민감 정보 노출 여부 +환경변수: .env.local, secret 값 커밋 여부 +상태 전이: 임의 상태 점프 여부 +Supabase: Service Role Key 클라이언트 노출 여부 +``` + +--- + +## 12. Merge 정책 + +```txt +Merge 방식: Squash Merge 권장 +이유: 작업 브랜치의 커밋 이력을 하나로 합쳐 dev 히스토리를 간결하게 유지 +``` + +Squash Merge 기본 설정은 GitHub Settings > General > Pull Requests에서 직접 설정한다. + +Merge 조건: + +```txt +- 리뷰 승인 1명 이상 +- 충돌(Conflict) 없음 +- 빌드 성공 (로컬 확인) +- 환경변수 노출 없음 +``` + +--- + +## 13. Branch Protection 정책 + +GitHub Settings > Branches에서 아래 설정을 직접 적용한다. + +### main 보호 규칙 + +```txt +- Require a pull request before merging: ON +- Require approvals: 1명 이상 +- Dismiss stale pull request approvals: ON +- Require status checks to pass: 필요 시 설정 +- Include administrators: ON +``` + +### dev 보호 규칙 + +```txt +- Require a pull request before merging: ON +- Require approvals: 1명 이상 +- Include administrators: ON +``` + +--- + +## 14. Conflict 해결 정책 + +```bash +# 1. dev 최신화 +git checkout dev +git pull origin dev + +# 2. 작업 브랜치로 이동 후 dev merge +git checkout feature/my-branch +git merge dev + +# 3. 충돌 파일 수동 해결 + +# 4. 해결 후 커밋 +git add [해결된 파일] +git commit -m "chore: resolve merge conflict with dev" + +# 5. push +git push origin feature/my-branch +``` + +--- + +## 15. DB 변경 정책 + +```txt +- Prisma schema 변경은 반드시 팀 승인 후 진행한다. +- ERD 문서가 먼저 업데이트되어야 Prisma schema 변경이 가능하다. +- Migration 파일은 반드시 PR에 포함한다. +- DB relation 변경은 CLAUDE.md 15항 기준으로 승인 필요. +``` + +--- + +## 16. API 변경 정책 + +```txt +- API endpoint 추가 / 삭제 / 구조 변경은 반드시 팀 승인 후 진행한다. +- API_SPEC.md 문서를 먼저 업데이트한 후 구현한다. +- API 응답 구조 변경은 CLAUDE.md 15항 기준으로 승인 필요. +``` + +--- + +## 17. 환경변수 / 보안 정책 + +### 운영 원칙 + +```txt +- 실제 secret 값을 코드, PR, 메신저에 포함하지 않는다. +- .env.local은 Git에 커밋하지 않는다. +- NEXT_PUBLIC_ prefix에 secret 값 사용 금지. +``` + +### 환경변수 동기화 + +PM이 Vercel에 등록. 팀원은 아래 명령어로 동기화한다. + +```bash +vercel env pull .env.local +``` + +### Supabase 보안 원칙 + +```txt +- Supabase는 실제 사용 인프라로 확정. +- DB는 Supabase Postgres 사용. Prisma는 DATABASE_URL로 연결. +- Storage는 Supabase Storage 사용. MVP 범위는 result-cards bucket. +- Supabase Auth는 사용하지 않음. 인증은 NextAuth + Kakao OAuth 유지. +- SUPABASE_SERVICE_ROLE_KEY는 서버 전용. 클라이언트 노출 절대 금지. +- 업로드 / 삭제 / 비공개 파일 접근은 Next.js API Route를 통해 서버에서 처리. +``` + +### 환경변수 목록 (key만 참고) + +```env +DATABASE_URL= + +SUPABASE_URL= +SUPABASE_ANON_KEY= +SUPABASE_SERVICE_ROLE_KEY= +SUPABASE_STORAGE_BUCKET_RESULT_CARDS= + +NEXTAUTH_URL= +NEXTAUTH_SECRET= + +KAKAO_CLIENT_ID= +KAKAO_CLIENT_SECRET= + +GEMINI_API_KEY= + +ROOM_TOKEN_SECRET= +CRON_SECRET= +``` + +--- + +## 18. Package 관리 정책 + +```txt +- 패키지 추가는 반드시 팀 공유 후 진행한다. +- package-lock.json은 Git에 포함한다. +- 팀원은 신규 패키지 포함 PR 병합 후 npm ci로 설치한다. +- MVP에서 @supabase/supabase-js 설치는 Storage/DB 유틸 구현 브랜치에서 별도 진행한다. +``` + +--- + +## 19. UI / Design 변경 정책 + +```txt +- 공통 컴포넌트 변경 시 반드시 팀에 공유한다. +- 도메인 전용 컴포넌트는 담당자가 직접 구현한다. +- SCSS Module 기준으로 스타일링한다. (전역 스타일은 src/styles/) +- public/images는 정적 에셋 관리용으로 유지한다. +``` + +--- + +## 20. AI / Prompt 변경 정책 + +```txt +- Gemini API 프롬프트 구조 변경은 반드시 팀 승인 후 진행한다. +- AI 판결 결과 항목 변경은 CLAUDE.md 기준에서 벗어나지 않는다. +- A/B 공감 지수 / 소통 태도 점수 구현 절대 금지. +``` + +--- + +## 21. 테스트 / 확인 정책 + +```txt +PR 전 로컬 확인 필수: +npm run lint +npm run type-check +npm run build (가능하면) + +빌드 에러가 있으면 PR 생성 전에 해결한다. +``` + +--- + +## 22. 문서 관리 정책 + +```txt +- 도메인 상세 설계는 docs/domains/*.md에서 관리한다. +- 프로젝트 최종 결정사항은 docs/PROJECT_DECISIONS.md에 반영한다. +- 기술스택은 docs/TECH_STACK.md에서 관리한다. +- 협업 정책 변경 시 이 문서의 변경 이력을 업데이트한다. +``` + +--- + +## 23. 금지 사항 + +```txt +- main 직접 push 금지 +- dev 직접 push 금지 +- 셀프 Merge 금지 (긴급 hotfix 제외) +- .env.local Git 커밋 금지 +- 실제 secret 값 코드/PR/메신저 노출 금지 +- SUPABASE_SERVICE_ROLE_KEY 클라이언트 코드 사용 금지 +- @supabase/supabase-js 무단 설치 금지 +- src/features 폴더 사용 금지 +- MVP 제외 기능 구현 금지 (shop, points, user-items, 독립 statistics 화면 등) +- Prisma schema 무단 변경 금지 +- API endpoint 무단 변경 금지 +- 결과 유형 Enum 하드코딩 금지 +- 감정일기 원문 / 진술 원문 공유 이미지 / Storage 저장 금지 +- GitHub Actions workflow 무단 추가 금지 +``` + +--- + +## 24. 최종 체크리스트 + +PR 생성 전 아래 항목을 확인한다. + +```txt +- [ ] Issue가 존재하고 PR과 연결됨 +- [ ] 브랜치가 dev 기준으로 생성됨 +- [ ] PR 제목에 prefix 포함 +- [ ] PR Template 모든 항목 작성 +- [ ] lint / type-check 통과 +- [ ] 빌드 에러 없음 +- [ ] .env.local 미포함 +- [ ] 실제 secret 값 미포함 +- [ ] SUPABASE_SERVICE_ROLE_KEY 클라이언트 미노출 +- [ ] MVP 범위 내 작업 +- [ ] 리뷰어 지정 +``` + +--- + +## 25. 변경 이력 + +| 날짜 | 작성자 | 내용 | +|------|--------|------| +| 2026-06-15 | - | 최초 작성 (dev 브랜치 기준, Supabase 인프라 확정 반영) | diff --git a/docs/guides/GIT_WORKFLOW.md b/docs/guides/GIT_WORKFLOW.md new file mode 100644 index 0000000..428c250 --- /dev/null +++ b/docs/guides/GIT_WORKFLOW.md @@ -0,0 +1,141 @@ +# GIT_WORKFLOW.md + +Git 작업 흐름 가이드 + +--- + +## 1. 기본 브랜치 + +| 브랜치 | 용도 | +|--------|------| +| `main` | 최종 배포 브랜치 — 직접 push 금지 | +| `dev` | 개발 통합 브랜치 — 직접 push 금지 | + +--- + +## 2. 작업 브랜치 종류 + +모든 작업 브랜치는 `dev`에서 분기한다. + +| 브랜치 | 용도 | +|--------|------| +| `feature/*` | 새 기능 | +| `fix/*` | 버그 수정 | +| `refactor/*` | 리팩토링 | +| `docs/*` | 문서 작업 | +| `chore/*` | 패키지, 설정, 기타 | +| `infra/*` | 환경설정, 인프라 | +| `hotfix/*` | main 긴급 수정 후 dev 반영 | + +예시: + +```txt +feature/auth-kakao-login +feature/room-ai-chat-create-room +fix/judgement-duplicate-request +refactor/diary-query-optimization +docs/add-user-domain-spec +chore/setup-github-templates +infra/setup-eslint-config +``` + +--- + +## 3. 기본 작업 흐름 + +```txt +Issue 생성 +→ dev 최신화 +→ 작업 브랜치 생성 +→ 작업 +→ 검증 (lint / type-check) +→ PR 생성 (대상: dev) +→ 리뷰 및 수정 +→ Squash Merge +→ Issue 자동 종료 +``` + +--- + +## 4. 작업 시작 명령어 예시 + +```bash +# 1. dev 최신화 +git checkout dev +git pull origin dev + +# 2. 작업 브랜치 생성 +git checkout -b feature/room-ai-chat-create-room + +# 3. 작업 후 검증 +npm run lint +npm run type-check + +# 4. 커밋 +git add [파일명] +git commit -m "feat(room): add create room api" + +# 5. push +git push -u origin feature/room-ai-chat-create-room + +# 6. GitHub에서 PR 생성 → base: dev +``` + +--- + +## 5. 커밋 메시지 규칙 + +```txt +feat: 새 기능 추가 +fix: 버그 수정 +docs: 문서 변경 +refactor: 리팩토링 +chore: 패키지, 설정, 기타 +infra: 환경설정, 인프라 +``` + +예시: + +```txt +feat(auth): add kakao oauth login +fix(room): resolve token expiry validation +docs(infra): confirm Supabase as project infrastructure +chore(github): add collaboration templates and policy +``` + +--- + +## 6. Conflict 해결 절차 + +```bash +# 1. dev 최신화 +git checkout dev +git pull origin dev + +# 2. 작업 브랜치로 이동 후 dev merge +git checkout feature/my-branch +git merge dev + +# 3. 충돌 파일 수동 해결 + +# 4. 해결 후 커밋 +git add [해결된 파일] +git commit -m "chore: resolve merge conflict with dev" + +# 5. push +git push origin feature/my-branch +``` + +--- + +## 7. 금지 사항 + +```txt +- main 직접 push 금지 +- dev 직접 push 금지 +- 커밋에 .env.local 포함 금지 +- 커밋에 실제 secret 값 포함 금지 +- 커밋에 SUPABASE_SERVICE_ROLE_KEY 실제 값 포함 금지 +- git push --force 금지 (팀 공유 브랜치 대상) +- 브랜치 없이 직접 작업 금지 +``` diff --git a/docs/guides/PR_RULES.md b/docs/guides/PR_RULES.md new file mode 100644 index 0000000..df233cf --- /dev/null +++ b/docs/guides/PR_RULES.md @@ -0,0 +1,117 @@ +# PR_RULES.md + +Pull Request 규칙 가이드 + +--- + +## 1. PR 대상 브랜치 + +```txt +기본 대상: dev +hotfix 대상: main (병합 후 dev 반영 필수) +main 직접 병합은 최종 배포 시에만 진행 +``` + +--- + +## 2. PR 제목 규칙 + +제목은 `[Prefix] 내용` 형식으로 작성한다. + +| Prefix | 용도 | +|--------|------| +| `[Feat]` | 새 기능 추가 | +| `[Fix]` | 버그 수정 | +| `[Docs]` | 문서 작업 | +| `[Infra]` | 환경설정, 인프라 | +| `[Refactor]` | 리팩토링 | +| `[Chore]` | 패키지, 설정, 기타 | + +예시: + +```txt +[Feat] 카카오 로그인 구현 +[Fix] 초대 링크 만료 검증 수정 +[Docs] Supabase 인프라 사용 확정 반영 +[Chore] GitHub 협업 템플릿 추가 +``` + +--- + +## 3. PR 본문 필수 항목 + +PR Template(`.github/pull_request_template.md`)을 사용한다. + +포함 항목: + +```txt +1. 작업 내용 +2. 담당 작업 영역 (체크박스) +3. 관련 Issue (close # 링크) +4. 관련 기능 요구사항 (FR-) +5. 관련 비기능 요구사항 (NFR-) +6. 변경 사항 +7. 테스트 결과 (체크박스) +8. 작업 범위 확인 (체크박스) +9. 보안 / 개인정보 확인 (체크박스) +10. DB / API / Storage 변경 여부 (체크박스) +11. 스크린샷 (필요 시) +12. 추가 공유 사항 +``` + +--- + +## 4. PR 전 확인 사항 + +```bash +npm run lint # ESLint 통과 확인 +npm run type-check # TypeScript 오류 없음 확인 +npm run build # 빌드 에러 없음 확인 (가능하면) +``` + +--- + +## 5. Merge 기준 + +```txt +- 리뷰 승인(Approve) 1명 이상 +- 충돌(Conflict) 없음 +- 빌드 성공 (로컬 확인) +- 환경변수 / secret 값 노출 없음 +- SUPABASE_SERVICE_ROLE_KEY 클라이언트 노출 없음 +``` + +Merge 방식은 Squash Merge를 권장한다. +GitHub Settings > General > Pull Requests에서 직접 설정한다. + +--- + +## 6. 리뷰 체크 항목 + +```txt +기능 범위: MVP 외 기능 구현 여부 확인 +문서 기준: CLAUDE.md / 도메인 문서와 일치 여부 +폴더 구조: src/features 폴더, 금지 구조 사용 여부 +보안: 권한 검증 서버 수행 여부, 민감 정보 노출 여부 +환경변수: .env.local, secret 값 커밋 여부 +Supabase: Service Role Key 클라이언트 노출 여부 +상태 전이: CLAUDE.md 기준 임의 상태 점프 여부 +DB / API: 무단 schema 변경, 무단 endpoint 추가 여부 +``` + +--- + +## 7. 금지 사항 + +```txt +- 셀프 Merge 금지 (긴급 hotfix 제외) +- 리뷰 없이 Merge 금지 +- 빌드 에러 상태로 Merge 금지 +- .env.local 포함 PR 금지 +- 실제 secret 값 포함 PR 금지 +- SUPABASE_SERVICE_ROLE_KEY 실제 값 PR 포함 금지 +- MVP 제외 기능 포함 PR 금지 (shop, points, user-items 등) +- Prisma schema 무단 변경 포함 PR 금지 +- API endpoint 무단 변경 포함 PR 금지 +- 리뷰어 미지정 Merge 금지 +``` diff --git a/docs/guides/VERCEL_DEPLOYMENT_GUIDE.md b/docs/guides/VERCEL_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..2a2f0c6 --- /dev/null +++ b/docs/guides/VERCEL_DEPLOYMENT_GUIDE.md @@ -0,0 +1,278 @@ +# VERCEL_DEPLOYMENT_GUIDE.md + +Vercel 배포 운영 가이드 + +--- + +## 1. 문서 목적 + +이 문서는 TALKY-OWL 프로젝트의 Vercel 배포 전략과 환경변수 운영 기준을 정의한다. + +```txt +- 이 문서는 배포 전략과 환경변수 운영 기준 문서이다. +- 실제 GitHub Actions workflow 파일은 별도 작업에서 생성한다. +- 실제 Vercel 프로젝트 생성은 사람이 직접 한다. +- 실제 Vercel Environment Variables 등록은 사람이 직접 한다. +``` + +--- + +## 2. 운영 방식 요약 + +```txt +GitHub Organization repo +→ dev 브랜치 PR 병합 +→ GitHub Actions에서 Vercel CLI 배포 +→ 개인 Vercel Hobby 프로젝트로 배포 +``` + +--- + +## 3. Vercel Hobby 단일 배포 계정 운영 기준 + +```txt +- Vercel Team은 사용하지 않는다. +- 배포 전용 Google 계정 1개로 Vercel Hobby 프로젝트를 운영한다. +- 팀원은 Vercel Team에 초대하지 않는다. +- 팀원은 GitHub PR 중심으로 작업한다. +- Vercel 환경변수 등록/수정은 배포 담당자 또는 PM이 수행한다. +``` + +이유: + +```txt +Vercel Team은 유료 플랜이다. +GitHub Organization repo와 Vercel Hobby를 연결하려면 GitHub Actions + Vercel CLI 방식으로 배포한다. +팀원은 Vercel 접근 없이 GitHub PR 흐름으로만 협업한다. +``` + +--- + +## 4. GitHub Organization repo와 Vercel 배포 구조 + +```txt +GitHub Organization (I5-Project/TALKY-OWL) + └─ dev 브랜치 + └─ PR 병합 트리거 + └─ GitHub Actions + └─ Vercel CLI (vercel --prod) + └─ 개인 Vercel Hobby 프로젝트 +``` + +GitHub Actions가 Vercel CLI를 통해 배포를 수행하므로, 팀원은 Vercel 계정이 없어도 된다. + +--- + +## 5. GitHub Actions + Vercel CLI 배포 개념 + +배포 흐름 (개념): + +```txt +1. dev 브랜치에 PR 병합 +2. GitHub Actions workflow 트리거 +3. workflow 내에서 vercel CLI를 사용하여 배포 +4. 배포 결과를 GitHub Actions 로그에서 확인 +``` + +필요한 GitHub Actions Secrets: + +```txt +VERCEL_TOKEN Vercel Personal Access Token +VERCEL_ORG_ID Vercel 프로젝트의 orgId +VERCEL_PROJECT_ID Vercel 프로젝트 ID +``` + +주의: + +```txt +- 실제 GitHub Actions workflow 파일은 이 문서에서 생성하지 않는다. +- workflow 생성은 별도 작업 브랜치에서 진행한다. +``` + +--- + +## 6. Vercel Environment Variables 등록 기준 + +배포 담당자 또는 PM이 Vercel Dashboard에서 직접 등록한다. + +등록 경로: + +```txt +Vercel Dashboard > 프로젝트 선택 > Settings > Environment Variables +``` + +등록할 key 목록 (실제 값은 작성하지 않음): + +```env +DATABASE_URL= + +SUPABASE_URL= +SUPABASE_ANON_KEY= +SUPABASE_SERVICE_ROLE_KEY= +SUPABASE_STORAGE_BUCKET_RESULT_CARDS= + +NEXTAUTH_URL= +NEXTAUTH_SECRET= + +KAKAO_CLIENT_ID= +KAKAO_CLIENT_SECRET= + +GEMINI_API_KEY= + +ROOM_TOKEN_SECRET= +CRON_SECRET= + +NEXT_PUBLIC_APP_URL= +NEXT_PUBLIC_SITE_NAME= +``` + +환경 구분: + +```txt +Production → 프로덕션 배포용 +Preview → PR Preview 배포용 (필요 시) +Development → 개발 환경용 (필요 시) +``` + +--- + +## 7. GitHub Actions Secrets 등록 기준 + +배포 담당자가 GitHub Repository Settings에서 직접 등록한다. + +등록 경로: + +```txt +GitHub Repository > Settings > Secrets and variables > Actions +``` + +등록할 Secrets (실제 값은 작성하지 않음): + +```txt +VERCEL_TOKEN Vercel Personal Access Token +VERCEL_ORG_ID Vercel 프로젝트 orgId +VERCEL_PROJECT_ID Vercel 프로젝트 ID +``` + +VERCEL_TOKEN 발급 경로: + +```txt +Vercel Dashboard > 계정 Settings > Tokens > Create Token +``` + +VERCEL_ORG_ID / VERCEL_PROJECT_ID 확인 방법: + +```txt +vercel link 실행 후 생성되는 .vercel/project.json 파일에서 확인 +``` + +주의: + +```txt +- 위 Secrets는 .env.example에 포함하지 않는다. +- 실제 값을 문서, PR, 메신저에 작성하지 않는다. +``` + +--- + +## 8. 팀원 로컬 환경변수 관리 + +현재 프로젝트는 Vercel Team을 사용하지 않으므로, 팀원이 `vercel env pull`을 직접 사용하기 어렵다. + +**권장 방식:** + +```txt +1. 배포 담당자 또는 PM이 .env.example 기준으로 각 key의 값을 보안 채널로 전달한다. +2. 팀원은 전달받은 값을 바탕으로 로컬에 .env.local 파일을 직접 생성한다. +3. .env.local은 Git에 커밋하지 않는다. +4. 전달 과정에서 GitHub, Notion, PR, 공개 메신저에 secret 값을 작성하지 않는다. +``` + +--- + +## 9. Supabase 환경변수 등록 기준 + +Supabase 프로젝트 생성 후 아래 값을 확인하여 Vercel에 등록한다. + +| 키 | 확인 경로 | +|----|----------| +| `DATABASE_URL` | Supabase Dashboard > Project Settings > Database > Connection String (URI 형식) | +| `SUPABASE_URL` | Supabase Dashboard > Project Settings > API > Project URL | +| `SUPABASE_ANON_KEY` | Supabase Dashboard > Project Settings > API > anon (public) key | +| `SUPABASE_SERVICE_ROLE_KEY` | Supabase Dashboard > Project Settings > API > service_role key | +| `SUPABASE_STORAGE_BUCKET_RESULT_CARDS` | 생성한 bucket 이름. 권장: `result-cards` | + +Supabase bucket 생성: + +```txt +Supabase Dashboard > Storage > New bucket +bucket 이름: result-cards +``` + +--- + +## 10. Kakao OAuth Redirect URI 관리 기준 + +Kakao Developers에서 Redirect URI를 등록해야 한다. + +등록 경로: + +```txt +Kakao Developers > 앱 선택 > 카카오 로그인 > Redirect URI +``` + +등록할 URI: + +```txt +로컬: +http://localhost:3030/api/auth/callback/kakao + +Vercel Production: +https://[프로덕션도메인]/api/auth/callback/kakao + +Vercel Preview (필요 시): +Preview URL 기준으로 별도 등록 +``` + +프로덕션 도메인이 확정되면 위 플레이스홀더를 실제 도메인으로 변경한다. + +--- + +## 11. Gemini API Key 관리 기준 + +```txt +- Google AI Studio 또는 Google Cloud Console에서 발급한다. +- 서버 API Route에서만 사용한다. +- NEXT_PUBLIC_ prefix를 절대 사용하지 않는다. +- 클라이언트 코드에서 노출하지 않는다. +``` + +--- + +## 12. 배포 전 체크리스트 + +```txt +- [ ] Vercel Environment Variables 모두 등록 +- [ ] GitHub Actions Secrets 모두 등록 +- [ ] Supabase result-cards bucket 생성 +- [ ] Kakao Redirect URI 등록 +- [ ] .env.example key와 Vercel 등록 key 일치 여부 확인 +- [ ] SUPABASE_SERVICE_ROLE_KEY가 클라이언트 코드에 노출되지 않음 확인 +- [ ] GEMINI_API_KEY가 클라이언트 코드에 노출되지 않음 확인 +- [ ] npm run build 로컬 성공 확인 +- [ ] npm run lint 통과 확인 +- [ ] npm run type-check 통과 확인 +``` + +--- + +## 13. 보안 주의사항 + +```txt +- 실제 secret 값을 GitHub, Notion, PR, 메신저, 문서에 작성하지 않는다. +- SUPABASE_SERVICE_ROLE_KEY는 서버 전용이며 클라이언트에 절대 노출하지 않는다. +- VERCEL_TOKEN은 GitHub Actions Secrets에만 등록하며 다른 곳에 공유하지 않는다. +- .env.local을 Git에 커밋하지 않는다. +- Kakao Client Secret은 클라이언트 코드에 포함하지 않는다. +- Gemini API Key는 클라이언트 코드에 포함하지 않는다. +``` diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..13428d3 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,17 @@ +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + { ignores: ['next-env.d.ts', '.next/**'] }, + ...compat.extends('next/core-web-vitals', 'next/typescript'), +]; + +export default eslintConfig; diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..830fb59 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..b22af96 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,5 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = {}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1013720 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9102 @@ +{ + "name": "talky-owl", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "talky-owl", + "version": "0.1.0", + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@google/generative-ai": "^0.21.0", + "@hookform/resolvers": "^3.9.1", + "@mui/material": "^9.1.1", + "@mui/x-date-pickers": "^9.5.0", + "@prisma/client": "^6.0.0", + "@tanstack/react-query": "^5.62.0", + "dayjs": "^1.11.21", + "html-to-image": "^1.11.11", + "lucide-react": "^0.468.0", + "next": "^15.0.0", + "next-auth": "^4.24.11", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-hook-form": "^7.54.1", + "recharts": "^3.8.1", + "sass": "^1.83.0", + "zod": "^3.23.8", + "zustand": "^5.0.2" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "eslint": "^9.0.0", + "eslint-config-next": "^15.0.0", + "json-server": "^0.17.4", + "prettier": "^3.4.2", + "prisma": "^6.0.0", + "typescript": "^5.7.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "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.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "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.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "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.5", + "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.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "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/@google/generative-ai": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.21.0.tgz", + "integrity": "sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.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.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.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.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "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/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/@mui/core-downloads-tracker": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-9.1.1.tgz", + "integrity": "sha512-AupmMICbdJHqAh6FfOMaaiiIr7dfEgZJn5DFfiPuGNrbs+ZZy9cD1APwO0TSVBz5j08MJEEY6n7iC76/2wjMEA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/material": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-9.1.1.tgz", + "integrity": "sha512-Wv+gInjrpf99l1Q0oHe0eOWGTnlbkzs5nowClX65KCT/2fyPMwcbFEEkUsOHdpcHhB5UAbz/d7jlwt5ajWVvlA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/core-downloads-tracker": "^9.1.1", + "@mui/system": "^9.1.1", + "@mui/types": "^9.1.1", + "@mui/utils": "^9.1.1", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.2.3", + "prop-types": "^15.8.1", + "react-is": "^19.2.6", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^9.1.1", + "@types/react": "^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" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-9.1.1.tgz", + "integrity": "sha512-oH6c+d6sJ1CZT0Vg2/fHdUQ5zvo9Pn+f+WWk0tlQliHqqIRdN32DZ7UxjalW3LUj4OkHbdWR31biWuLxK9i7Cg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/utils": "^9.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-9.1.1.tgz", + "integrity": "sha512-neaYKdJfvEG54q8efHLJR7swpHG/gfSv9xGqW5iTSMsubD7yPCPFrhVBt284j1DOF3uZaaDJSHQL7gz6jGF21Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.2.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-9.1.1.tgz", + "integrity": "sha512-q+aqNa58QZUwmmyUvJKKrStrej+4BcWFw4M0Ug+zRylPIQgR64cqvBnE3QTfLZm4OXulydp8Hl3zwKxMayrdsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/private-theming": "^9.1.1", + "@mui/styled-engine": "^9.1.1", + "@mui/types": "^9.1.1", + "@mui/utils": "^9.1.1", + "clsx": "^2.1.1", + "csstype": "^3.2.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-9.1.1.tgz", + "integrity": "sha512-Zjt7u8wNvDg40rPTGoL+TnfkpuSKjwubsNSFRH1KAVZLcaV4I3AFNHIFbvH7p4F3alEibSbdd90xAgn5Rnfndg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-9.1.1.tgz", + "integrity": "sha512-qSNfnkzZMptaaWFFklpDf4NPJztgwsMDVfM/sSDt+wq4ssYSBhLYwwjuB6eS/+p2IUYbeRzHluzXbw0Zn7aI4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/types": "^9.1.1", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.6" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "license": "MIT" + }, + "node_modules/@mui/x-date-pickers": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-9.5.0.tgz", + "integrity": "sha512-Pzd8gU2qOoIAUMMesjbrq3gFs6akWXcSsEkFIHVA4dtuoh6SeWISu+WR+ymq/sBOcn2tk9IBIjqRQkqLhkm+tg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.7", + "@mui/utils": "9.0.1", + "@mui/x-internals": "^9.1.0", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^7.3.0 || ^9.0.0", + "@mui/system": "^7.3.0 || ^9.0.0", + "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2 || ^3.0.0", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@mui/x-date-pickers/node_modules/@mui/utils": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-9.0.1.tgz", + "integrity": "sha512-f3UO3jNN1pYg5zxqXC81Bvv8hx5ACcYc0387382ZI7M5ono1heIwHYLrKsz85myguWdeVKPRZGmDdynWUBjK2g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/types": "^9.0.0", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/x-date-pickers/node_modules/react-is": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "license": "MIT" + }, + "node_modules/@mui/x-internals": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-9.1.0.tgz", + "integrity": "sha512-fVezTa1lU+Hb3y9UMI8D/iWXADhs0I8PaZqoh2LOUXjGEUJmKqwsRD19ZXInZsH2yu+YS0dqYMPDvzjYTTyo+Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/utils": "9.0.0", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-internals/node_modules/@mui/utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-9.0.0.tgz", + "integrity": "sha512-bQcqyg/gjULUqTuyUjSAFr6LQGLvtkNtDbJerAtoUn9kGZ0hg5QJiN1PLHMLbeFpe3te1831uq7GFl2ITokGdg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/types": "^9.0.0", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/x-internals/node_modules/react-is": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", + "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@next/env": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.19.tgz", + "integrity": "sha512-sWWluFvcv5v3Fxznmf2ZfjyoVQt/64oCnYqS90inQWGzMPK1VjvekPiz3OPHKmFT30EnHrjlbyaHLt3M0vWabw==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.19.tgz", + "integrity": "sha512-Ctwb4qYuMbHN/1oXLlTdMchwG8h8Xzwq+wGZZMgF3o6+uwyBKAI2c96bdOsl+C62PaUD0Jkh+QpNkhUeDlam0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.19.tgz", + "integrity": "sha512-jx9wWlTKueHKPvVOndyr7WuaevWCkuYqsQ8gC0TMPKAVWG3MhcdMrjfo9tvIZNXd0QOUYXXvAcZ325y8Uq7uzg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.19.tgz", + "integrity": "sha512-291KFcsIQ3OenRdiUDFOR6W3wezzH4auENXm1gbm1Bjd4ANMMRgxPrWTUztQN43BnVoVuMnHCrLeECIMwgFKbA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.19.tgz", + "integrity": "sha512-WeH+nelQyyMeE2f8FxBRZNrGipya5zHZV2vjzfCOAYyiI6am+NbnWAAldOBFQBB2w0DjJcsvrKqoFT2b7+5YoA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.19.tgz", + "integrity": "sha512-5xTOE0lDlDCSSfp+BAif7j17VRRCjWp//ZPZy6NI0QpdrhxtQnsZguSx0xAAZ0c9XZLrLLwCe/XVe5YPrRilKw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.19.tgz", + "integrity": "sha512-LTxRmMgqqMv05Had879W00Fm53quiJd3Zuz8h1JSNJ3nGSlbZ/7Tjs1tKyScgN3Au3t3MyPsjPlq60fMmSHLsg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.19.tgz", + "integrity": "sha512-eoNQSpA5PQfB9wBO4RA47MTDXWz1fizy9Y3Z6e4DetYIF3dvjuu8sj7aIGn/bFCU6lnFzTK34NtCaffP4NsQ7Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.19.tgz", + "integrity": "sha512-6UNt2dFuCHOe446sm/Kp69nUe8/wIhnh9bm6Xcqw4qEWCOppLMOvhTBVgvM7invVUNr4SPpP6NOQsACtn2IN9Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.19.tgz", + "integrity": "sha512-PhmojAHyqMne56HBLGu9dhDnHPuFmEjrXSQMM/nW0J6j849lk3ESrVtqNJcCk8CKOV7brpTTbaYAjwKPzKM69w==", + "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/@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/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@prisma/client": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.3.tgz", + "integrity": "sha512-mKq3jQFhjvko5LTJFHGilsuQs+W+T3Gm451NzuTDGQxwCzwXHYnIu2zGkRoW+Exq3Rob7yp2MfzSrdIiZVhrBg==", + "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.3", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.3.tgz", + "integrity": "sha512-CBPT44BjlQxEt8kiMEauji2WHTDoVBOKl7UlewXmUgBPnr/oPRZC3psci5chJnYmH0ivEIog2OU9PGWoki3DLQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.21.0", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.3.tgz", + "integrity": "sha512-ljkJ+SgpXNktLG0Q/n4JGYCkKf0f8oYLyjImS2I8e2q2WCfdRRtWER062ZV/ixaNP2M2VKlWXVJiGzZaUgbKZw==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.3.tgz", + "integrity": "sha512-RSYxtlYFl5pJ8ZePgMv0lZ9IzVCOdTPOegrs2qcbAEFrBI1G33h6wyC9kjQvo0DnYEhEVY0X4LsuFHXLKQk88g==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.3", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/fetch-engine": "6.19.3", + "@prisma/get-platform": "6.19.3" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.3.tgz", + "integrity": "sha512-tKtl/qco9Nt7LU5iKhpultD8O4vMCZcU2CHjNTnRrL1QvSUr5W/GcyFPjNL87GtRrwBc7ubXXD9xy4EvLvt8JA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.3", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/get-platform": "6.19.3" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.3.tgz", + "integrity": "sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.3" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", + "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==", + "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.8", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.8.tgz", + "integrity": "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "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.16.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.16.1.tgz", + "integrity": "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "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/@tanstack/query-core": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.0.tgz", + "integrity": "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.0.tgz", + "integrity": "sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.101.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "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/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/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/node": { + "version": "22.19.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.21.tgz", + "integrity": "sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "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==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "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.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.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.61.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.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.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.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.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.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.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", + "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.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", + "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.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.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.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "eslint-visitor-keys": "^5.0.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/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "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.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "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-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "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==", + "dev": true, + "license": "Python-2.0" + }, + "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-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "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/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-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/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==", + "dev": true, + "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.12.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.12.1.tgz", + "integrity": "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/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/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "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/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/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "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/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "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/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/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/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/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "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/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/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "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.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/connect-pause": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-pause/-/connect-pause-0.1.1.tgz", + "integrity": "sha512-a1gSWQBQD73krFXdUEYJom2RTFrWUL3YvXDCRkyv//GVXc79cdW9MngtRuN9ih4FDKBtfJAJId+BbDuX+1rh2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "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/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "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/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/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/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "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/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==", + "dev": true, + "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.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "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", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "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/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "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==", + "dev": true, + "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/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.21.0.tgz", + "integrity": "sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "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/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/errorhandler": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.2.tgz", + "integrity": "sha512-kNAL7hESndBCrWwS72QyV3IVOTrVmj9D062FV5BQswNL5zEdeRmz/WJFyh6Aj/plvvSOrzddkxW57HgkZcR9Fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "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==", + "dev": true, + "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.3.3", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz", + "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "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", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "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==", + "dev": true, + "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.47.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.1.tgz", + "integrity": "sha512-5RAqEwf4P4E17p+W75KLOWw/nOvKZzSQpxM32IpI2KZLaVonjTrZ0Ai5ghMaVI9eKC2p8eoQgcBdkEDgzFk6+Q==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "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.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@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.14.0", + "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.5", + "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.19", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.19.tgz", + "integrity": "sha512-UZwkuhBCNxVZfo93MSHRDOVNWXooJJGcAUyTAVIp0+9QFhH4SqJxWY0s6Mk9C2kMi777HPMn3dseOrZshWpG9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "15.5.19", + "@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.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "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.13.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.13.0.tgz", + "integrity": "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==", + "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/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/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/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-urlrewrite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/express-urlrewrite/-/express-urlrewrite-1.4.0.tgz", + "integrity": "sha512-PI5h8JuzoweS26vFizwQl6UTF25CAHSggNv0J25Dn/IKZscJHWZzPrI5z2Y2jgOzIaw2qh8l6+/jUcig23Z2SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "*", + "path-to-regexp": "^1.0.3" + } + }, + "node_modules/express-urlrewrite/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/express-urlrewrite/node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "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/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==", + "dev": true, + "license": "MIT" + }, + "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/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/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/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "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.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "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==", + "dev": true, + "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-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "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.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.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/immutable": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz", + "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "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==", + "dev": true, + "license": "ISC" + }, + "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/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "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-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "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-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "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==", + "devOptional": 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-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "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==", + "devOptional": 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-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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/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/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.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jose": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "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.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jju": "^1.1.0" + } + }, + "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-server": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-0.17.4.tgz", + "integrity": "sha512-bGBb0WtFuAKbgI7JV3A864irWnMZSvBYRJbohaOuatHwKSRFUfqtQlrYMrB6WbalXy/cJabyjlb7JkHli6dYjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "body-parser": "^1.19.0", + "chalk": "^4.1.2", + "compression": "^1.7.4", + "connect-pause": "^0.1.1", + "cors": "^2.8.5", + "errorhandler": "^1.5.1", + "express": "^4.17.1", + "express-urlrewrite": "^1.4.0", + "json-parse-helpfulerror": "^1.0.3", + "lodash": "^4.17.21", + "lodash-id": "^0.14.1", + "lowdb": "^1.0.0", + "method-override": "^3.0.0", + "morgan": "^1.10.0", + "nanoid": "^3.1.23", + "please-upgrade-node": "^3.2.0", + "pluralize": "^8.0.0", + "server-destroy": "^1.0.1", + "yargs": "^17.0.1" + }, + "bin": { + "json-server": "lib/cli/bin.js" + }, + "engines": { + "node": ">=12" + } + }, + "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/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/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/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "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.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-id": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.1.tgz", + "integrity": "sha512-ikQPBTiq/d5m6dfKQlFdIXFzvThPi2Be9/AHxktOnDSfSxE1j9ICbBT5Elk1ke7HSTgM38LHTpmJovo9/klnLg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "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/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lucide-react": { + "version": "0.468.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz", + "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/method-override/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/method-override/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "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/morgan": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.11.0.tgz", + "integrity": "sha512-zSkVu3t18r39pw4ixfBKvfZi3y2UOqr7d4WYwcj3m8nXpEQK4rPO6GLzs/CExoRgmX3y9EjmmcXqv6jq0SK46g==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.4.1", + "on-headers": "~1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "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.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "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/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.19.tgz", + "integrity": "sha512-xNOW6tYshGX1/Oi3F8uuk4gpDeWsSUE/1Z0G5uUMekIxaQ0xc03UXd9II0VQHYMWviMeA0OHpJFAKsHf8bTYVg==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.19", + "@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.19", + "@next/swc-darwin-x64": "15.5.19", + "@next/swc-linux-arm64-gnu": "15.5.19", + "@next/swc-linux-arm64-musl": "15.5.19", + "@next/swc-linux-x64-gnu": "15.5.19", + "@next/swc-linux-x64-musl": "15.5.19", + "@next/swc-win32-arm64-msvc": "15.5.19", + "@next/swc-win32-x64-msvc": "15.5.19", + "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": "4.24.14", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.14.tgz", + "integrity": "sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig==", + "license": "ISC", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@panva/hkdf": "^1.0.2", + "cookie": "^0.7.0", + "jose": "^4.15.5", + "oauth": "^0.9.15", + "openid-client": "^5.4.0", + "preact": "^10.6.3", + "preact-render-to-string": "^5.1.19", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "@auth/core": "0.34.3", + "next": "^12.2.5 || ^13 || ^14 || ^15 || ^16", + "nodemailer": "^7.0.7", + "react": "^17.0.2 || ^18 || ^19", + "react-dom": "^17.0.2 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@auth/core": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/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/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/nypm": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.7.tgz", + "integrity": "sha512-s3ds97SD5pd1dULE+tHUk1DrV0cSHOnsfpcdGATJ8JpBo21DoKqN9exTH4/2nhPQNOLomBdTFMicN94S4DrZrQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.2.2", + "pathe": "^2.0.3", + "tinyexec": "^1.2.4" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/nypm/node_modules/citty": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz", + "integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==", + "license": "MIT" + }, + "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-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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/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/oidc-token-hash": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz", + "integrity": "sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/openid-client": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", + "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", + "license": "MIT", + "dependencies": { + "jose": "^4.15.9", + "lru-cache": "^6.0.0", + "object-hash": "^2.2.0", + "oidc-token-hash": "^5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "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/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/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==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/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": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.4", + "exsolve": "^1.0.8", + "pathe": "^2.0.3" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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/preact": { + "version": "10.29.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.2.tgz", + "integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/preact-render-to-string": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", + "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", + "license": "MIT", + "dependencies": { + "pretty-format": "^3.8.0" + }, + "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.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz", + "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==", + "license": "MIT" + }, + "node_modules/prisma": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.3.tgz", + "integrity": "sha512-++ZJ0ijLrDJF6hNB4t4uxg2br3fC4H9Yc9tcbjr2fcNFP3rh/SBNrAgjhsqBU4Ght8JPrVofG/ZkXfnSfnYsFg==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "6.19.3", + "@prisma/engines": "6.19.3" + }, + "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/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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/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/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/react-hook-form": { + "version": "7.79.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.79.0.tgz", + "integrity": "sha512-mhYp/MTmXvzYX6AJcJVko0rktoIhhmRnEouObj4wF5i/tCttgJvnp1+9wRkpITZjDTqpo4IOSJqu0dBlPlV/Lw==", + "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-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-redux": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", + "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/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-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "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.8.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", + "integrity": "sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "^1.9.0 || 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/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/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.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==", + "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/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.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "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==", + "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/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==", + "dev": true, + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.101.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.101.0.tgz", + "integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==", + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "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.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "dev": true, + "license": "ISC" + }, + "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==", + "dev": true, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "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.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "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.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "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/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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/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/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.3" + } + }, + "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/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "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.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "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/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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/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/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/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/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "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/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-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "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==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "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": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "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-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/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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/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.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "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/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/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "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/zustand": { + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.14.tgz", + "integrity": "sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5c0cfd1 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "talky-owl", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev -p 3030", + "build": "next build", + "start": "next start -p 3030", + "lint": "eslint .", + "type-check": "tsc --noEmit", + "format": "prettier --write .", + "format:check": "prettier --check .", + "mock": "json-server --watch data/mock/db.json --port 8081", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev" + }, + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@google/generative-ai": "^0.21.0", + "@hookform/resolvers": "^3.9.1", + "@mui/material": "^9.1.1", + "@mui/x-date-pickers": "^9.5.0", + "@prisma/client": "^6.0.0", + "@tanstack/react-query": "^5.62.0", + "dayjs": "^1.11.21", + "html-to-image": "^1.11.11", + "lucide-react": "^0.468.0", + "next": "^15.0.0", + "next-auth": "^4.24.11", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-hook-form": "^7.54.1", + "recharts": "^3.8.1", + "sass": "^1.83.0", + "zod": "^3.23.8", + "zustand": "^5.0.2" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "eslint": "^9.0.0", + "eslint-config-next": "^15.0.0", + "json-server": "^0.17.4", + "prettier": "^3.4.2", + "prisma": "^6.0.0", + "typescript": "^5.7.2" + } +} diff --git a/prisma/.gitkeep b/prisma/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..cc10721 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,8 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} diff --git a/public/.gitkeep b/public/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/.gitkeep b/public/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/backgrounds/.gitkeep b/public/images/backgrounds/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/characters/.gitkeep b/public/images/characters/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/icons/.gitkeep b/public/images/icons/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/result-card-templates/.gitkeep b/public/images/result-card-templates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/.gitkeep b/src/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/.gitkeep b/src/app/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/api/.gitkeep b/src/app/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/api/auth/.gitkeep b/src/app/api/auth/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/api/v1/.gitkeep b/src/app/api/v1/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..358413a --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,15 @@ +'use client'; + +export default function Error({ + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + return ( +
+

오류가 발생했습니다.

+ +
+ ); +} diff --git a/src/app/globals.scss b/src/app/globals.scss new file mode 100644 index 0000000..8054583 --- /dev/null +++ b/src/app/globals.scss @@ -0,0 +1 @@ +@use '../styles/main'; diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..dd34654 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from 'next'; +import './globals.scss'; + +export const metadata: Metadata = { + title: 'TALKY-OWL', + description: 'AI 갈등 조정 판결 서비스', +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 0000000..5d98cfc --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+

로딩 중...

+
+ ); +} diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..f795d2b --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

404 — 페이지를 찾을 수 없습니다.

+
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..eb14c3b --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,8 @@ +export default function RootPage() { + return ( +
+

TALKY-OWL

+

Next.js 초기 세팅 완료

+
+ ); +} diff --git a/src/app/page/.gitkeep b/src/app/page/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/calendar/.gitkeep b/src/app/page/calendar/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/diary/.gitkeep b/src/app/page/diary/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/disputes/.gitkeep b/src/app/page/disputes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/home/.gitkeep b/src/app/page/home/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/join/.gitkeep b/src/app/page/join/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/landing/.gitkeep b/src/app/page/landing/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/login/.gitkeep b/src/app/page/login/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/mypage/.gitkeep b/src/app/page/mypage/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/personal-analyses/.gitkeep b/src/app/page/personal-analyses/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/rooms/.gitkeep b/src/app/page/rooms/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/page/terms/.gitkeep b/src/app/page/terms/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/components/.gitkeep b/src/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/components/feedback/.gitkeep b/src/components/feedback/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/components/layout/.gitkeep b/src/components/layout/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/components/ui/.gitkeep b/src/components/ui/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/.gitkeep b/src/domains/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/auth/.gitkeep b/src/domains/auth/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/calendar/.gitkeep b/src/domains/calendar/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/common/.gitkeep b/src/domains/common/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/diary/.gitkeep b/src/domains/diary/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/dispute/.gitkeep b/src/domains/dispute/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/gift/.gitkeep b/src/domains/gift/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/judgement/.gitkeep b/src/domains/judgement/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/personal-analysis/.gitkeep b/src/domains/personal-analysis/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/room/.gitkeep b/src/domains/room/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/statistics/.gitkeep b/src/domains/statistics/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/domains/user/.gitkeep b/src/domains/user/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/.gitkeep b/src/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/ai/.gitkeep b/src/lib/ai/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/api/.gitkeep b/src/lib/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/auth/.gitkeep b/src/lib/auth/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/constants/.gitkeep b/src/lib/constants/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/db/.gitkeep b/src/lib/db/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/security/.gitkeep b/src/lib/security/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/utils/.gitkeep b/src/lib/utils/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/validators/.gitkeep b/src/lib/validators/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/stores/.gitkeep b/src/stores/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/.gitkeep b/src/styles/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/abstracts/.gitkeep b/src/styles/abstracts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/abstracts/_mixins.scss b/src/styles/abstracts/_mixins.scss new file mode 100644 index 0000000..af78115 --- /dev/null +++ b/src/styles/abstracts/_mixins.scss @@ -0,0 +1,17 @@ +// Flex center +@mixin flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +// Responsive breakpoint (mobile-first) +@mixin respond-to($breakpoint) { + @if $breakpoint == 'sm' { + @media (min-width: 480px) { @content; } + } @else if $breakpoint == 'md' { + @media (min-width: 768px) { @content; } + } @else if $breakpoint == 'lg' { + @media (min-width: 1024px) { @content; } + } +} diff --git a/src/styles/abstracts/_variables.scss b/src/styles/abstracts/_variables.scss new file mode 100644 index 0000000..d947b7a --- /dev/null +++ b/src/styles/abstracts/_variables.scss @@ -0,0 +1,10 @@ +// Color +$color-white: #ffffff; +$color-black: #000000; + +// Typography +$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +$font-size-base: 16px; + +// Spacing +$spacing-unit: 8px; diff --git a/src/styles/base/.gitkeep b/src/styles/base/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/base/_global.scss b/src/styles/base/_global.scss new file mode 100644 index 0000000..222a04f --- /dev/null +++ b/src/styles/base/_global.scss @@ -0,0 +1,10 @@ +@use '../abstracts/variables' as v; + +body { + font-family: v.$font-family-base; + font-size: v.$font-size-base; + background-color: v.$color-white; + color: v.$color-black; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/styles/base/_reset.scss b/src/styles/base/_reset.scss new file mode 100644 index 0000000..6b0e80e --- /dev/null +++ b/src/styles/base/_reset.scss @@ -0,0 +1,28 @@ +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +ul, +ol { + list-style: none; +} + +a { + text-decoration: none; + color: inherit; +} + +button { + cursor: pointer; + background: none; + border: none; +} + +img { + display: block; + max-width: 100%; +} diff --git a/src/styles/layout/.gitkeep b/src/styles/layout/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/layout/_page.scss b/src/styles/layout/_page.scss new file mode 100644 index 0000000..fe5e618 --- /dev/null +++ b/src/styles/layout/_page.scss @@ -0,0 +1,2 @@ +// 페이지 기본 레이아웃 +// 상세 스타일은 각 페이지 SCSS Module에서 작성 diff --git a/src/styles/main.scss b/src/styles/main.scss new file mode 100644 index 0000000..c4bc026 --- /dev/null +++ b/src/styles/main.scss @@ -0,0 +1,5 @@ +@use './abstracts/variables'; +@use './abstracts/mixins'; +@use './base/reset'; +@use './base/global'; +@use './layout/page'; diff --git a/src/types/.gitkeep b/src/types/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d2bdd9b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "paths": { + "@/*": ["./src/*"] + }, + "plugins": [ + { + "name": "next" + } + ] + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} From 7ef18f90365d42c7590f51a9beef260cde96aedf Mon Sep 17 00:00:00 2001 From: evenif99 Date: Mon, 22 Jun 2026 18:44:55 +0900 Subject: [PATCH 04/12] =?UTF-8?q?fix:=20dev=20=E2=86=92=20main=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EB=8D=95=EC=85=98=20=EB=B0=B0=ED=8F=AC=20=EB=B3=91?= =?UTF-8?q?=ED=95=A9=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: initialize project folder structure (#1) * chore: initialize project folder structure - Add base directory layout for Next.js + domain-driven architecture - Add .gitkeep to track empty directories in git - Exclude MVP out-of-scope domains (shop, points, user-items) - No implementation files included, structure only Co-Authored-By: Claude Sonnet 4.6 * Update README.md --------- Co-authored-by: Claude Sonnet 4.6 * docs: add CLAUDE.md with project rules and work guidelines (#2) - Add project overview and MVP scope definition - Add fixed product rules (categories, AI chat policy, judgement output) - Add architecture, domain scope, and state transition rules - Add auth/security, DB, frontend state, API, logging rules - Add Git workflow, Claude work process, STOP conditions - Add approval-required list and required reference documents Co-authored-by: Claude Sonnet 4.6 * infra: setup project config and install dependencies (#3) - Add package.json with Next.js 15, React 19, TypeScript stack - Add next.config.ts (minimal Next.js 15 config) - Add tsconfig.json (strict mode, @/* path alias) - Add eslint.config.mjs (next/core-web-vitals + next/typescript) - Add .prettierrc and .prettierignore - Add .gitignore (node_modules, .next, .env.local, etc.) - Add .env.example (key names only, no real values) - Add prisma/schema.prisma (generator + datasource only) - Add data/mock/db.json (health check stub for json-server) - Add docs/TECH_STACK.md (package list and selection rationale) - Update README.md with run commands and env guide Co-authored-by: Claude Sonnet 4.6 * docs: add base documentation structure (#4) - Add PROJECT_DECISIONS.md (MVP scope, architecture, security principles) - Add guides/CLAUDE_WORKFLOW.md (work process, STOP conditions, approval rules) - Add guides/GIT_WORKFLOW.md (branch naming, commit convention, workflow) - Add guides/PR_RULES.md (PR target, title rules, review criteria) - Add guides/ENV_GUIDE.md (Vercel env pull, .env.example management) - Add guides/CODING_CONVENTION.md (naming, state management, folder rules) - Add db/STATUS_TRANSITION.md (room_mode, dispute_status transitions) - Add db/PRISMA_MAPPING.md (snake_case/camelCase mapping rules) - Add db/MASTER_DATA.md (categories, result types, DB master principles) - Add domains/README.md (domain list, MVP scope, writing guidelines) - Add domains/_DOMAIN_TEMPLATE.md (template for domain docs) Co-authored-by: Claude Sonnet 4.6 * docs: add domain document drafts for all MVP domains (#5) - Add AUTH.md (kakao login, terms, session management) - Add COMMON.md (error handling, logging, common response) - Add ROOM.md (AI chat room, invite link, room_mode transitions) - Add PERSONAL_ANALYSIS.md (AI-based personal conflict analysis) - Add DISPUTE.md (1:1 mediation, roles, statements, dispute_status) - Add JUDGEMENT.md (AI judgement, Gemini API, result card) - Add GIFT.md (gift recommendation after judgement) - Add USER.md (mypage, profile, bottom tab) - Add CALENDAR.md (date-based record marking, monthly summary) - Add DIARY.md (emotion diary, author-only access, content protection) - Add STATISTICS.md (anonymous aggregation, summary components) - Add SHOP_FUTURE.md (v2.0 planned, MVP excluded) - Add POINTS_FUTURE.md (v2.0 planned, MVP excluded) - Add USER_ITEMS_FUTURE.md (v2.0 planned, MVP excluded) All documents are draft templates with TODO markers for assignees. No implementation, no API routes, no schema changes. Co-authored-by: Claude Sonnet 4.6 * infra: add Next.js App Router entry files and SCSS base structure (#6) - Add src/app/layout.tsx (root layout with metadata and globals.scss import) - Add src/app/page.tsx (minimal root page for build verification) - Add src/app/globals.scss (imports src/styles/main.scss) - Add src/app/error.tsx (minimal error boundary with reset) - Add src/app/not-found.tsx (minimal 404 page) - Add src/app/loading.tsx (minimal loading page) - Add src/styles/main.scss (ordered SCSS entry point) - Add src/styles/abstracts/_variables.scss (color, typography, spacing tokens) - Add src/styles/abstracts/_mixins.scss (flex-center, respond-to breakpoints) - Add src/styles/base/_reset.scss (box-sizing, margin, button, img reset) - Add src/styles/base/_global.scss (body font, background, color defaults) - Add src/styles/layout/_page.scss (placeholder for page layout) Verified: type-check, lint, build all pass Co-authored-by: Claude Sonnet 4.6 * Infra/init next setup (#7) * infra: add Next.js App Router entry files and SCSS base structure - Add src/app/layout.tsx (root layout with metadata and globals.scss import) - Add src/app/page.tsx (minimal root page for build verification) - Add src/app/globals.scss (imports src/styles/main.scss) - Add src/app/error.tsx (minimal error boundary with reset) - Add src/app/not-found.tsx (minimal 404 page) - Add src/app/loading.tsx (minimal loading page) - Add src/styles/main.scss (ordered SCSS entry point) - Add src/styles/abstracts/_variables.scss (color, typography, spacing tokens) - Add src/styles/abstracts/_mixins.scss (flex-center, respond-to breakpoints) - Add src/styles/base/_reset.scss (box-sizing, margin, button, img reset) - Add src/styles/base/_global.scss (body font, background, color defaults) - Add src/styles/layout/_page.scss (placeholder for page layout) Verified: type-check, lint, build all pass Co-Authored-By: Claude Sonnet 4.6 * fix: resolve ESLint and TypeScript config warnings - eslint.config.mjs: ignore next-env.d.ts and .next/** (auto-generated by Next.js, triple-slash reference false positive) - tsconfig.json: remove deprecated baseUrl option (TypeScript 5.x+, paths works without baseUrl) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * Update README.md (#8) * docs(infra): confirm Supabase as project infrastructure (#9) * chore(github): add collaboration templates and policy (#10) * docs(env): document environment variable management (#11) * docs(calendar): confirm MUI date picker usage (#12) 달력 UI 라이브러리로 MUI X Date Pickers + Day.js 사용을 확정하고 관련 문서(TECH_STACK, PROJECT_DECISIONS, CODING_CONVENTION, CALENDAR, DIARY, CLAUDE.md)에 반영한다. * chore(deps): install MUI X Date Pickers and peer dependencies (#13) 달력 UI 구현을 위해 MUI X Date Pickers 및 필수 peer dependency를 설치한다. @mui/material@9.1.1, @emotion/react@11.14.0, @emotion/styled@11.14.1, @mui/x-date-pickers@9.5.0, dayjs@1.11.21 * Update README.md (#15) * fix: resolve ESLint and TypeScript config warnings (#20) * infra: add Next.js App Router entry files and SCSS base structure - Add src/app/layout.tsx (root layout with metadata and globals.scss import) - Add src/app/page.tsx (minimal root page for build verification) - Add src/app/globals.scss (imports src/styles/main.scss) - Add src/app/error.tsx (minimal error boundary with reset) - Add src/app/not-found.tsx (minimal 404 page) - Add src/app/loading.tsx (minimal loading page) - Add src/styles/main.scss (ordered SCSS entry point) - Add src/styles/abstracts/_variables.scss (color, typography, spacing tokens) - Add src/styles/abstracts/_mixins.scss (flex-center, respond-to breakpoints) - Add src/styles/base/_reset.scss (box-sizing, margin, button, img reset) - Add src/styles/base/_global.scss (body font, background, color defaults) - Add src/styles/layout/_page.scss (placeholder for page layout) Verified: type-check, lint, build all pass Co-Authored-By: Claude Sonnet 4.6 * fix: resolve ESLint and TypeScript config warnings - eslint.config.mjs: ignore next-env.d.ts and .next/** (auto-generated by Next.js, triple-slash reference false positive) - tsconfig.json: remove deprecated baseUrl option (TypeScript 5.x+, paths works without baseUrl) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * infra: add MVP Prisma schema with NextAuth and TALKY-OWL models (#21) - datasource: add directUrl for Supabase connection pooler support - enums: CategoryGroup, RoomMode, DisputeStatus, ParticipantRole, etc. - NextAuth models: User (with TALKY-OWL fields), Account, Session, VerificationToken - core models: DisputeRoom, RoomAiConversation, RoomAiMessage - dispute models: Dispute, DisputeParticipant, DisputeStatement - judgment models: AiJudgment, JudgmentResultCard - gift models: GiftRecommendation, GiftRecommendationItem - feature models: EmotionDiary, CalendarRecord - master data: ConflictTypeGroup, ConflictTypeDetail (DB-based, no enum hardcoding) - log models: AuditLog, ApiErrorLog, ModerationLog, RoomAccessLog, UserDeletionLog - .env.example: add DIRECT_URL for Supabase directUrl - v2.0 TODO: ShopItem, PointTransaction, UserItem, DisputeStatistic excluded Co-authored-by: Claude Sonnet 4.6 * infra: align project structure with guide v2 (#22) folders added: - src/components/{personal-analysis,room,dispute,judgement,calendar,diary,statistics,gift} - src/app/api/auth/[...nextauth] - src/app/api/v1/{users,personal-analyses,rooms,disputes,statements,calendar,diary,statistics,cron} files added: - prisma/seed.ts (placeholder for ConflictTypeGroup master data) docs updated (minimal): - docs/domains/COMMON.md: add log table list, judgement_logs TODO note - docs/domains/JUDGEMENT.md: clarify Storage is MVP-excluded scaffolding - docs/guides/ENV_GUIDE.md: clarify Supabase Storage vars are MVP-excluded Co-authored-by: Claude Sonnet 4.6 * infra: rename src/app/page to src/app/(page) for correct Next.js route group (#23) src/app/page/ (괄호 없음)는 /page/* URL segment를 생성하므로, Next.js App Router route group 문법인 src/app/(page)/로 변경한다. URL은 /landing, /home 등으로 노출되어야 하며 /page/... 가 아니다. 관련 문서 내 경로 참조도 모두 업데이트 (CLAUDE.md, docs/domains/*, docs/guides/*). Co-authored-by: Claude Sonnet 4.6 * [Style] 디자인 토큰 및 전역 스타일 설정 (#25) * feat(styles): 디자인 토큰 및 전역 스타일 설정 - _variables.scss에 글로벌 컬러 팔레트, 타이포그래피 변수, 시맨틱 CSS 커스텀 프로퍼티(:root) 추가 - _mixins.scss에 타이포그래피 mixin 추가 (text-display ~ text-value-m) - _global.scss body 폰트 Pretendard 적용 - next/font/local로 PretendardVariable 폰트 로드 (layout.tsx) - GIT_WORKFLOW.md 커밋 메시지 예시 한글로 변경 Co-Authored-By: Claude Sonnet 4.6 * docs: 커밋 타입 style 추가 및 scope 제거 Co-Authored-By: Claude Sonnet 4.6 * style: 컨테이너 max-width 1000px 설정 Co-Authored-By: Claude Sonnet 4.6 * style: 루트 레이아웃 container 적용 및 개발 확인용 임시 border 추가 Co-Authored-By: Claude Sonnet 4.6 * style: 개발 확인용 임시 border 색상 회색으로 변경 Co-Authored-By: Claude Sonnet 4.6 * style: container min-height 100vh 추가 Co-Authored-By: Claude Sonnet 4.6 * docs: 커밋 타입 style 추가 및 scope 제거 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * style: 디자인 시스템 기반 설정 (#27) * feat(styles): 디자인 토큰 및 전역 스타일 설정 - _variables.scss에 글로벌 컬러 팔레트, 타이포그래피 변수, 시맨틱 CSS 커스텀 프로퍼티(:root) 추가 - _mixins.scss에 타이포그래피 mixin 추가 (text-display ~ text-value-m) - _global.scss body 폰트 Pretendard 적용 - next/font/local로 PretendardVariable 폰트 로드 (layout.tsx) - GIT_WORKFLOW.md 커밋 메시지 예시 한글로 변경 Co-Authored-By: Claude Sonnet 4.6 * docs: 커밋 타입 style 추가 및 scope 제거 Co-Authored-By: Claude Sonnet 4.6 * style: 컨테이너 max-width 1000px 설정 Co-Authored-By: Claude Sonnet 4.6 * style: 루트 레이아웃 container 적용 및 개발 확인용 임시 border 추가 Co-Authored-By: Claude Sonnet 4.6 * style: 개발 확인용 임시 border 색상 회색으로 변경 Co-Authored-By: Claude Sonnet 4.6 * style: container min-height 100vh 추가 Co-Authored-By: Claude Sonnet 4.6 * docs: 커밋 타입 style 추가 및 scope 제거 Co-Authored-By: Claude Sonnet 4.6 * style: rem 스케일 토큰 추가 및 타이포그래피 변수 rem 참조로 전환 - Rem scale 섹션 추가 (0.25rem ~ 30rem) - 폰트 토큰에서 누락된 0.875rem(14px), 1.125rem(18px) 추가 - font-size, line-height 변수를 rem 스케일 변수 참조로 전환 - rem 스케일을 typography 섹션보다 상단으로 이동 (선언 순서) - 컴포넌트 width/height 대응을 위해 큰 단위(9rem~30rem) 포함 Co-Authored-By: Claude * style: r() 함수 분리 및 타이포그래피 변수 함수 기반으로 전환 - _functions.scss 신규 추가 — px → rem 변환 함수 r() 단독 관리 - _variables.scss에서 rem 스케일 변수 제거, fn.r() 참조로 전환 - _mixins.scss에 functions @use 추가 - 순환 참조 없이 variables → functions → (없음) 단방향 의존성 구성 Co-Authored-By: Claude --------- Co-authored-by: Claude Sonnet 4.6 * Feature/common component jw (#28) * feat(common): add Button, Toast, Header, BottomNavigation components - Button: primary / outline / disabled variants, design token 기반 - Toast: Zustand store 연동, 상단 고정, 시맨틱 컬러 토큰 적용 - Header: 뒤로가기 + title + subtitle 구조, 조건부 title centering - BottomNavigation: 4탭(홈/사건기록/일기/마이페이지), lucide-react 아이콘 - toastStore: Zustand UI 상태 (show/hide/message) * docs: update collaboration policy - GitHub Ruleset 브랜치 규칙 추가 (브랜치 Pattern 2, PR 제목 Pattern 1 분리) - Issues / Milestones / Project Board 미사용으로 관련 내용 제거 - GIT_WORKFLOW 작업 흐름에서 Issue 생성/자동종료 단계 제거 - PR_RULES PR 본문에서 관련 Issue 항목 제거 * fix: :root {} 시맨틱 토큰을 _global.scss로 분리 (#29) * feat(styles): 디자인 토큰 및 전역 스타일 설정 - _variables.scss에 글로벌 컬러 팔레트, 타이포그래피 변수, 시맨틱 CSS 커스텀 프로퍼티(:root) 추가 - _mixins.scss에 타이포그래피 mixin 추가 (text-display ~ text-value-m) - _global.scss body 폰트 Pretendard 적용 - next/font/local로 PretendardVariable 폰트 로드 (layout.tsx) - GIT_WORKFLOW.md 커밋 메시지 예시 한글로 변경 Co-Authored-By: Claude Sonnet 4.6 * docs: 커밋 타입 style 추가 및 scope 제거 Co-Authored-By: Claude Sonnet 4.6 * style: 컨테이너 max-width 1000px 설정 Co-Authored-By: Claude Sonnet 4.6 * style: 루트 레이아웃 container 적용 및 개발 확인용 임시 border 추가 Co-Authored-By: Claude Sonnet 4.6 * style: 개발 확인용 임시 border 색상 회색으로 변경 Co-Authored-By: Claude Sonnet 4.6 * style: container min-height 100vh 추가 Co-Authored-By: Claude Sonnet 4.6 * docs: 커밋 타입 style 추가 및 scope 제거 Co-Authored-By: Claude Sonnet 4.6 * style: rem 스케일 토큰 추가 및 타이포그래피 변수 rem 참조로 전환 - Rem scale 섹션 추가 (0.25rem ~ 30rem) - 폰트 토큰에서 누락된 0.875rem(14px), 1.125rem(18px) 추가 - font-size, line-height 변수를 rem 스케일 변수 참조로 전환 - rem 스케일을 typography 섹션보다 상단으로 이동 (선언 순서) - 컴포넌트 width/height 대응을 위해 큰 단위(9rem~30rem) 포함 Co-Authored-By: Claude * style: r() 함수 분리 및 타이포그래피 변수 함수 기반으로 전환 - _functions.scss 신규 추가 — px → rem 변환 함수 r() 단독 관리 - _variables.scss에서 rem 스케일 변수 제거, fn.r() 참조로 전환 - _mixins.scss에 functions @use 추가 - 순환 참조 없이 variables → functions → (없음) 단방향 의존성 구성 Co-Authored-By: Claude * fix: :root {} 시맨틱 토큰을 _global.scss로 분리 _variables.scss에 :root {}가 있으면 module.scss에서 @use 시 CSS Modules 'not pure' 에러 발생. SCSS 변수는 _variables.scss, CSS 출력은 _global.scss로 분리. Co-Authored-By: Claude --------- Co-authored-by: Claude Sonnet 4.6 * feat(common): 공통 UI 컴포넌트 추가 및 MUI 정책 적용 (#30) * feat(common): add Button, Toast, Header, BottomNavigation components - Button: primary / outline / disabled variants, design token 기반 - Toast: Zustand store 연동, 상단 고정, 시맨틱 컬러 토큰 적용 - Header: 뒤로가기 + title + subtitle 구조, 조건부 title centering - BottomNavigation: 4탭(홈/사건기록/일기/마이페이지), lucide-react 아이콘 - toastStore: Zustand UI 상태 (show/hide/message) * docs: update collaboration policy - GitHub Ruleset 브랜치 규칙 추가 (브랜치 Pattern 2, PR 제목 Pattern 1 분리) - Issues / Milestones / Project Board 미사용으로 관련 내용 제거 - GIT_WORKFLOW 작업 흐름에서 Issue 생성/자동종료 단계 제거 - PR_RULES PR 본문에서 관련 Issue 항목 제거 * feat(common): add Tabs, CaseCard, ActionPrompt, Input, Select, Textarea components Co-Authored-By: Claude Sonnet 4.6 * feat(common): apply MUI icons and Snackbar, update MUI usage policy - Toast: MUI Snackbar (3s auto-dismiss) - BottomNavigation, Header, Select: lucide-react → @mui/icons-material - Install @mui/icons-material - CLAUDE.md, CODING_CONVENTION.md: MUI usage policy updated Co-Authored-By: Claude Sonnet 4.6 * docs: update icon policy — @mui/icons-material except diary feature Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 사건 목록 공통 UI 컴포넌트 추가 (Tab, StatusBadge) (#31) * feat: 사건조회 페이지 판결,유형 tab 공통 컴포넌트 생성 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건 관련 페이지의 진행 상태 컴포넌트 Co-Authored-By: Claude Sonnet 4.6 * fix: StatusBadge CSS 변수 하드코딩 제거 및 Tab className trailing space 수정 --------- Co-authored-by: jungmin park Co-authored-by: Claude Sonnet 4.6 * fix(common): ActionPrompt message 제거 및 Textarea 글자수 카운터 위치 수정 (#32) * feat(common): add Button, Toast, Header, BottomNavigation components - Button: primary / outline / disabled variants, design token 기반 - Toast: Zustand store 연동, 상단 고정, 시맨틱 컬러 토큰 적용 - Header: 뒤로가기 + title + subtitle 구조, 조건부 title centering - BottomNavigation: 4탭(홈/사건기록/일기/마이페이지), lucide-react 아이콘 - toastStore: Zustand UI 상태 (show/hide/message) * docs: update collaboration policy - GitHub Ruleset 브랜치 규칙 추가 (브랜치 Pattern 2, PR 제목 Pattern 1 분리) - Issues / Milestones / Project Board 미사용으로 관련 내용 제거 - GIT_WORKFLOW 작업 흐름에서 Issue 생성/자동종료 단계 제거 - PR_RULES PR 본문에서 관련 Issue 항목 제거 * feat(common): add Tabs, CaseCard, ActionPrompt, Input, Select, Textarea components Co-Authored-By: Claude Sonnet 4.6 * feat(common): apply MUI icons and Snackbar, update MUI usage policy - Toast: MUI Snackbar (3s auto-dismiss) - BottomNavigation, Header, Select: lucide-react → @mui/icons-material - Install @mui/icons-material - CLAUDE.md, CODING_CONVENTION.md: MUI usage policy updated Co-Authored-By: Claude Sonnet 4.6 * docs: update icon policy — @mui/icons-material except diary feature Co-Authored-By: Claude Sonnet 4.6 * fix(common): ActionPrompt message 제거 및 Textarea 글자수 카운터 absolute 배치 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 공통 및 dispute·judgment DTO 타입 정의 - ApiResponse, ApiError, ApiFieldError, CategoryGroup (common.ts) - DisputeDto, CreateDisputeRequest, DisputeListResponse 등 (dispute.ts) - AiJudgmentDto, CreateAiJudgmentRequest 등 (judgment.ts) Co-Authored-By: Claude Sonnet 4.6 * feat: dispute 도메인 공유 상수·헬퍼·mapper 추가 - VALID_CATEGORY_GROUPS, IMMUTABLE_DISPUTE_STATUSES 상수 (constants/dispute.ts) - getSessionUserId NextAuth 세션 헬퍼 (auth/session.ts) - toAiJudgmentDto 공유 mapper (judgement/judgment.mapper.ts) Co-Authored-By: Claude Sonnet 4.6 * feat: 사건 목록 조회·생성·수정·삭제 API 구현 - GET /api/v1/disputes — 참여 사건 목록, categoryGroup 필터, 페이지네이션 - POST /api/v1/disputes — 사건 생성 + role_a 참여자 트랜잭션 등록 - GET /api/v1/disputes/:id — 사건 상세 조회 - PATCH /api/v1/disputes/:id — 사건 수정 (role_a 전용, 변경 불가 상태 차단) - DELETE /api/v1/disputes/:id — 사건 소프트 삭제 Co-Authored-By: Claude Sonnet 4.6 * feat: AI 판결 요청·결과 조회 API 구현 - POST /api/v1/disputes/:id/judge — AI 판결 요청, JUDGING 상태 잠금으로 멱등성 보장 - GET /api/v1/disputes/:id/result — 판결 결과 조회 (참여자 전용) - AI 모듈 미구현 구간은 TODO 주석으로 마킹, 완료 전까지 503 반환 Co-Authored-By: Claude Sonnet 4.6 * feat: 공통 UI 컴포넌트 - StatusBadge, Tab, 진행 상태 (#33) * feat: 사건조회 페이지 판결,유형 tab 공통 컴포넌트 생성 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건 관련 페이지의 진행 상태 컴포넌트 Co-Authored-By: Claude Sonnet 4.6 * fix: StatusBadge CSS 변수 하드코딩 제거 및 Tab className trailing space 수정 * fix: StatusBadge 크기 조정 및 .playwright-mcp gitignore 추가 - StatusBadge min-width, height, padding, border-radius 수정 - justify-content: center 추가 - .playwright-mcp/ gitignore 등록 - package-lock.json peer dependency 재분류 반영 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: jungmin park Co-authored-by: Claude Sonnet 4.6 * feat: Prisma 클라이언트, NextAuth Kakao OAuth 설정 및 핸들러 추가 - src/lib/db/index.ts — Prisma 전역 싱글턴 - src/lib/auth/index.ts — NextAuth authOptions (Kakao OAuth, session user.id 매핑) - src/app/api/auth/[...nextauth]/route.ts — NextAuth GET/POST 핸들러 - @mui/icons-material 패키지 설치 (빌드 에러 해결) Co-Authored-By: Claude Sonnet 4.6 * chore: 빌드 스크립트에 prisma generate 추가 Co-Authored-By: Claude Sonnet 4.6 * docs: MVP 전체 API 명세서 작성 (API_SPEC.md) (#36) * docs: MVP 전체 API 명세서 작성 (API_SPEC.md) - 도메인 문서 및 기존 합의 기반 MVP API 명세 초안 작성 - 공통 응답 구조, 에러 코드 체계 정의 - Auth / User / Room / Dispute / Statement / Judgement / Diary / Calendar / Statistics / Gift / Cron 도메인 API 명세 포함 - 경로 충돌 항목 (withdraw, judge/result, diary 경로) 확정 필요 사항으로 명시 - 미확정 TODO 항목 섹션 7에 전체 정리 - MVP 제외 항목 (shop, points, 단독판결, 독립 통계 화면 등) 명시적으로 제거 처리 Co-Authored-By: Claude Sonnet 4.6 * docs: 단독 판결 MVP 포함 반영 및 라우트 주석 명확화 - 단독 판결(상대방 없는 AI 판결)을 MVP 포함 범위로 변경 - Personal Analysis 섹션에 단독 판결 API 초안 추가 (POST/GET /api/v1/personal-analyses) - 라우트 트리 personal-analyses 디렉터리 구조 구체화 - /auth/withdraw route.ts 주석을 경로 충돌 상호 참조가 명확한 형태로 수정 (경로 충돌 → /auth/withdraw vs DELETE /users/me) - MVP 제외 목록에서 단독 판결 항목 제거 Co-Authored-By: Claude Sonnet 4.6 * docs: 카카오 로그인 시 약관 동의 자동 간주 정책 반영 - 카카오 OAuth 로그인 완료를 약관 동의로 간주 - 별도 약관 동의 페이지 이동 플로우 제거 - 확정 필요 항목에서 약관 동의 기준 항목 제거 Co-Authored-By: Claude Sonnet 4.6 * docs: 도메인 API 목록 중복 제거 및 회원탈퇴 경로 확정 - docs/domains/*.md 8개 파일의 API 목록 섹션을 docs/API_SPEC.md 참조로 교체 (AUTH, USER, ROOM, DISPUTE, JUDGEMENT, DIARY, CALENDAR, STATISTICS) - API_SPEC.md 단일 소스 체계 확립 - 회원탈퇴 경로 DELETE /api/v1/users/me 채택 확정 - §3 요약표, §4.1·§4.2 상세, §5 라우트 트리, §6 충돌 목록, §7 체크리스트 반영 - /auth/withdraw 라우트 제거, /users/me route.ts에 DELETE 추가 - CLAUDE_WORKFLOW.md PR 템플릿 준수 문구 추가 Co-Authored-By: Claude Sonnet 4.6 * docs: 날짜 포맷 및 Pagination 구조 확정 반영 - 날짜/시간 포맷 ISO 8601 (YYYY-MM-DDTHH:mm:ssZ) 확정 - Pagination 공통 구조 확정 - data 필드: items 배열 - page 필드: page / totalPages / sortBy / isNext - 섹션 7 확정 필요 항목 두 개 체크 처리 - Room 목록, Diary 목록 섹션 Pagination 참조로 갱신 Co-Authored-By: Claude Sonnet 4.6 * docs: Pagination 구조에 size / sort / hasNext / hasPrevious 추가 - size: 한 번에 가져오는 항목 수 - sort: 정렬 방향 (asc | desc) - isNext → hasNext로 변경 (다음 페이지 존재 여부) - hasPrevious 추가 (이전 페이지 존재 여부) - §7 체크리스트 항목 갱신 Co-Authored-By: Claude Sonnet 4.6 * docs: 날짜 포맷 코드블록 언어 지정자 추가 (MD040) 코드래빗 지적 사항 반영 — 언어 미지정 펜스 코드블록에 text 지정자 추가 Co-Authored-By: Claude Sonnet 4.6 * docs: 통계 API 비로그인 공개 조회로 변경 홈 화면 진입 시 비로그인 회원도 통계 조회 가능하도록 수정 - GET /api/v1/statistics/summary: 🔒 → 공개 - GET /api/v1/statistics/top-types: 🔒 → 공개 - §3 요약표, §4.9 상세 명세 인증 표기 및 설명 반영 Co-Authored-By: Claude Sonnet 4.6 * docs: 목록 응답 예시에 page 객체 추가 (코드래빗 지적 반영) - GET /api/v1/rooms 응답 예시에 page 객체 추가 - GET /api/v1/diary 응답 예시에 page 객체 추가 - GET /api/v1/statistics/top-types 응답 예시에 page 객체 추가 (Top5 고정 목록 특성 반영: size=5, totalPages=1, hasNext=false) - 코드래빗 제안의 구버전 필드(isNext) 대신 확정 구조(hasNext/hasPrevious/size/sort) 적용 - §7 Room Pagination 항목 체크 처리 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: Spinner, Avatar, AvatarGroup 공통 컴포넌트 추가 (#37) * chore: 정적 이미지 에셋 추가 및 정리 주요 페이지용 캐릭터 이미지 추가 및 공통 에셋 정리. gift, loading 캐릭터를 common에서 characters로 이동하여 캐릭터 이미지를 한 폴더로 통합. Co-Authored-By: Claude * feat: Spinner 공통 컴포넌트 추가 캐릭터 로딩 이미지를 중앙에 배치한 88x88 스피너 컴포넌트 추가. 트랙(배경 원)과 애니메이션 링을 분리하여 각각 border-default, bg-brand 색상 적용. Co-Authored-By: Claude * feat: Avatar, AvatarGroup 공통 컴포넌트 추가 MUI Avatar, AvatarGroup 래핑 컴포넌트 추가. size prop으로 s/m/l 사이즈 조절, src prop으로 프로필 사진 지원. global.scss에 --color-white, --color-black CSS 변수 추가. Co-Authored-By: Claude * fix: Avatar Context로 AvatarGroup size 전달 및 토큰 수정 AvatarGroup size prop이 자식 Avatar에 적용 안 되는 버그 수정. Context를 통해 size를 내려주고 Avatar가 그룹 size를 우선 적용. color 토큰 --color-white를 --text-inverse로 교체. Co-Authored-By: Claude * fix: Avatar src 없을 때 기본 썸네일 이미지로 fallback 처리 Co-Authored-By: Claude * test: Spinner, Avatar, AvatarGroup 테스트 페이지 추가 Co-Authored-By: Claude --------- Co-authored-by: Claude * feat: 공통 UI 컴포넌트 - CategoryFilter, CategoryIcon, Tab, StatusBadge (#38) * feat: 사건조회 페이지 판결,유형 tab 공통 컴포넌트 생성 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건 관련 페이지의 진행 상태 컴포넌트 Co-Authored-By: Claude Sonnet 4.6 * fix: StatusBadge CSS 변수 하드코딩 제거 및 Tab className trailing space 수정 * fix: StatusBadge 크기 조정 및 .playwright-mcp gitignore 추가 - StatusBadge min-width, height, padding, border-radius 수정 - justify-content: center 추가 - .playwright-mcp/ gitignore 등록 - package-lock.json peer dependency 재분류 반영 Co-Authored-By: Claude Sonnet 4.6 * feat: CategoryFilter 공통 컴포넌트 생성 - 전체/연애/직장/친구/가족 카테고리 필터 구현 - 아이콘 박스 44x44, border-radius 8, 아이콘 24x24 - 선택 상태: icon-primary bg / 미선택: bg-disabled - MUI icons 사용 (GridViewRounded, Favorite, BusinessCenter, Diversity3, FamilyRestroom) - Category 타입 export Co-Authored-By: Claude Sonnet 4.6 * fix: Tab 라벨 폰트 스타일 명시 - item.label을 span.label로 래핑 - Body-M 기준 font-size 16, line-height 28 적용 Co-Authored-By: Claude Sonnet 4.6 * chore: @mui/icons-material 패키지 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: CategoryFilter 스타일 및 single 모드 적용 - 선택: bg-page + border-brand(1px) + icon-primary + 텍스트 bold - 미선택: bg-page + border-default(1px) + icon-secondary + 텍스트 regular - mode prop 추가 (filter 기본값 / single: 선택된 박스 하나만 표시) Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 타입을 DB CategoryGroup 기준으로 통일 ## 수정 배경 CategoryIcon, CategoryFilter가 한국어 문자열('연애', '직장' 등)을 타입으로 사용하고 있어 API/DB의 CategoryGroup('romance', 'work' 등)과 불일치가 발생. 페이지에서 연결 시 별도 변환 레이어가 필요해지는 문제를 사전 차단. ## 변경 파일별 수정 내용 ### CategoryIcon.tsx - CategoryWithoutAll 타입 제거 → @/types/common의 CategoryGroup 직접 사용 - 아이콘/레이블/컬러 맵 키를 한국어 → 영문 DB 값으로 변경 (romance, work, friend, family) - CATEGORY_LABEL_MAP export 추가 (CategoryFilter에서 레이블 참조용) ### CategoryFilter.tsx - Category 타입을 'all' | CategoryGroup으로 변경 (기존: 한국어 문자열) - CATEGORIES 배열에 label 필드 추가, CATEGORY_LABEL_MAP에서 참조 - 전체 키를 '전체' → 'all'로 변경 (API 필터 미적용 값과 일치) ### CaseCard.tsx (타팀원 파일 수정) - 수정 이유: CATEGORY_EMOJI 맵 키가 대문자('ROMANCE')였으나 API 응답은 소문자('romance')로 내려와 emoji가 항상 '📋' fallback만 표시되는 버그 존재 - 해결 방법: emoji 방식 전체 제거, CategoryIcon 컴포넌트로 교체 - categoryGroup prop 타입을 string → CategoryGroup으로 명시 - categoryGroup 미전달 시 아이콘 미표시 처리 (optional 유지) Co-Authored-By: Claude Sonnet 4.6 * Update src/components/ui/CategoryIcon.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: CategoryIcon 중복 import 제거 및 CategoryFilter discriminated union 타입 에러 수정 - CategoryIcon: FamilyRestroomIcon, CategoryGroup 중복 import 제거 - CategoryFilter: discriminated union(CodeRabbit 피드백 반영) 유지하면서 props 전체로 받아 props.mode로 narrowing 처리해 타입 에러 해결 (mode='single'일 때 onChange가 CategoryGroup을 기대하는 문제) - Tab.module.scss: height → min-height 변경 (유연한 높이 대응) Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard 카테고리 아이콘을 제목 왼쪽 인라인으로 이동 - card__header 구조 변경: titleRow(아이콘+제목)와 badge를 좌우 배치 - card__titleRow 추가: flex row, align-items center, gap 6px - 아이콘이 제목 위에 쌓이던 문제 수정 → 제목 왼쪽에 인라인 배치 - card__icon: font-size/line-height(이모지 잔재) → display:flex 로 변경 - card__title: margin-bottom 제거(card__header margin-bottom으로 대체) Co-Authored-By: Claude Sonnet 4.6 * docs: 공통 컴포넌트 테스트 스크린샷 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard titleRow flex 축소 보완 (min-width: 0, flex: 1) 긴 제목에서 card__titleRow가 축소되지 않아 배지가 밀리는 문제 방지. card__header가 space-between일 때 titleRow가 flex: 1로 가용 공간을 차지하고 min-width: 0으로 내부 콘텐츠가 넘치지 않도록 제약. Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: jungmin park Co-authored-by: Claude Sonnet 4.6 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix(common): BottomNavigation 아이콘 MUI MD2 기본 스타일로 수정 (#39) * fix(common): BottomNavigation 아이콘을 MUI MD2 기본 스타일로 수정 - HomeRounded → Home - GavelRounded → MenuBook (사건기록 아이콘 자체 변경) - CalendarMonthRounded → CalendarMonth - PersonRounded → Person 디자인 시안 기준 MD2 filled 아이콘으로 통일 Co-Authored-By: Claude Sonnet 4.6 * docs: BottomNavigation 테스트 스크린샷 추가 Co-Authored-By: Claude Sonnet 4.6 * fix(common): BottomNavigation 활성 탭 레이블 색상 black-700으로 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(common): BottomNavigation 테스트 스크린샷 삭제 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 Co-authored-by: wjdalss21 * feat: 사건·방 도메인 타입 정의 및 API 구현 (#40) * feat: room DTO 타입 정의 - RoomMode, RoomDto, CreateRoomRequest, RoomListResponse Co-Authored-By: Claude Sonnet 4.6 * feat: 방 목록 조회·생성·상세 조회·종료·삭제 API 구현 - GET /api/v1/rooms — 내 방 목록 조회 (페이지네이션) - POST /api/v1/rooms — AI 대화방 생성 (roomMode = ai_chat) - GET /api/v1/rooms/:id — 방 상세 조회 - POST /api/v1/rooms/:id/close — 방 종료 (closedAt + roomMode = closed) - DELETE /api/v1/rooms/:id — 방 소프트 삭제 (deletedAt + roomMode = deleted) Co-Authored-By: Claude Sonnet 4.6 * fix: 방 목록 페이지네이션 파라미터 NaN 방어 처리 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix: API 라우트 경로 v1 버전 세그먼트 제거 (#42) * fix: API 라우트 경로에서 v1 버전 세그먼트 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 라우트 핸들러 주석 경로 v1 제거 (/api/v1/ -> /api/) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix(docs): 서비스 흐름 기반 문서 구조 수정 및 페이지 문서 생성 (#43) * fix(docs): 서비스 흐름 기반 문서 구조 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(docs): PAGES.md 코드 블록 언어 명시 추가 (MD040) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix: personal-analyses 페이지 및 API 폴더 삭제 (#45) * fix: personal-analyses 페이지 및 API 폴더 삭제 Co-Authored-By: Claude Sonnet 4.6 * fix(docs): personal-analysis 도메인 참조 MD 문서 일괄 정리 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 통계 API 구현 (GET /api/statistics/categories) (#44) * feat: 사건조회 페이지 판결,유형 tab 공통 컴포넌트 생성 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건 관련 페이지의 진행 상태 컴포넌트 Co-Authored-By: Claude Sonnet 4.6 * fix: StatusBadge CSS 변수 하드코딩 제거 및 Tab className trailing space 수정 * fix: StatusBadge 크기 조정 및 .playwright-mcp gitignore 추가 - StatusBadge min-width, height, padding, border-radius 수정 - justify-content: center 추가 - .playwright-mcp/ gitignore 등록 - package-lock.json peer dependency 재분류 반영 Co-Authored-By: Claude Sonnet 4.6 * feat: CategoryFilter 공통 컴포넌트 생성 - 전체/연애/직장/친구/가족 카테고리 필터 구현 - 아이콘 박스 44x44, border-radius 8, 아이콘 24x24 - 선택 상태: icon-primary bg / 미선택: bg-disabled - MUI icons 사용 (GridViewRounded, Favorite, BusinessCenter, Diversity3, FamilyRestroom) - Category 타입 export Co-Authored-By: Claude Sonnet 4.6 * fix: Tab 라벨 폰트 스타일 명시 - item.label을 span.label로 래핑 - Body-M 기준 font-size 16, line-height 28 적용 Co-Authored-By: Claude Sonnet 4.6 * chore: @mui/icons-material 패키지 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: CategoryFilter 스타일 및 single 모드 적용 - 선택: bg-page + border-brand(1px) + icon-primary + 텍스트 bold - 미선택: bg-page + border-default(1px) + icon-secondary + 텍스트 regular - mode prop 추가 (filter 기본값 / single: 선택된 박스 하나만 표시) Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 타입을 DB CategoryGroup 기준으로 통일 ## 수정 배경 CategoryIcon, CategoryFilter가 한국어 문자열('연애', '직장' 등)을 타입으로 사용하고 있어 API/DB의 CategoryGroup('romance', 'work' 등)과 불일치가 발생. 페이지에서 연결 시 별도 변환 레이어가 필요해지는 문제를 사전 차단. ## 변경 파일별 수정 내용 ### CategoryIcon.tsx - CategoryWithoutAll 타입 제거 → @/types/common의 CategoryGroup 직접 사용 - 아이콘/레이블/컬러 맵 키를 한국어 → 영문 DB 값으로 변경 (romance, work, friend, family) - CATEGORY_LABEL_MAP export 추가 (CategoryFilter에서 레이블 참조용) ### CategoryFilter.tsx - Category 타입을 'all' | CategoryGroup으로 변경 (기존: 한국어 문자열) - CATEGORIES 배열에 label 필드 추가, CATEGORY_LABEL_MAP에서 참조 - 전체 키를 '전체' → 'all'로 변경 (API 필터 미적용 값과 일치) ### CaseCard.tsx (타팀원 파일 수정) - 수정 이유: CATEGORY_EMOJI 맵 키가 대문자('ROMANCE')였으나 API 응답은 소문자('romance')로 내려와 emoji가 항상 '📋' fallback만 표시되는 버그 존재 - 해결 방법: emoji 방식 전체 제거, CategoryIcon 컴포넌트로 교체 - categoryGroup prop 타입을 string → CategoryGroup으로 명시 - categoryGroup 미전달 시 아이콘 미표시 처리 (optional 유지) Co-Authored-By: Claude Sonnet 4.6 * Update src/components/ui/CategoryIcon.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: CategoryIcon 중복 import 제거 및 CategoryFilter discriminated union 타입 에러 수정 - CategoryIcon: FamilyRestroomIcon, CategoryGroup 중복 import 제거 - CategoryFilter: discriminated union(CodeRabbit 피드백 반영) 유지하면서 props 전체로 받아 props.mode로 narrowing 처리해 타입 에러 해결 (mode='single'일 때 onChange가 CategoryGroup을 기대하는 문제) - Tab.module.scss: height → min-height 변경 (유연한 높이 대응) Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard 카테고리 아이콘을 제목 왼쪽 인라인으로 이동 - card__header 구조 변경: titleRow(아이콘+제목)와 badge를 좌우 배치 - card__titleRow 추가: flex row, align-items center, gap 6px - 아이콘이 제목 위에 쌓이던 문제 수정 → 제목 왼쪽에 인라인 배치 - card__icon: font-size/line-height(이모지 잔재) → display:flex 로 변경 - card__title: margin-bottom 제거(card__header margin-bottom으로 대체) Co-Authored-By: Claude Sonnet 4.6 * docs: 공통 컴포넌트 테스트 스크린샷 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard titleRow flex 축소 보완 (min-width: 0, flex: 1) 긴 제목에서 card__titleRow가 축소되지 않아 배지가 밀리는 문제 방지. card__header가 space-between일 때 titleRow가 flex: 1로 가용 공간을 차지하고 min-width: 0으로 내부 콘텐츠가 넘치지 않도록 제약. Co-Authored-By: Claude Sonnet 4.6 * feat: 통계 도메인 서비스 레이어 생성 (statisticsService.ts) ## 생성 이유 통계 API의 DB 쿼리 로직을 Route Handler와 분리하기 위해 도메인 서비스 레이어를 별도 파일로 작성했다. ## 폴더 선택 이유 src/domains/statistics/ - CLAUDE.md §4 아키텍처 원칙에 따라 도메인별 비즈니스 로직은 src/domains/{domain}/ 에 위치한다. - statistics는 MVP 도메인 목록에 포함된 독립 도메인이다. - Route Handler(src/app/api/)는 요청/응답 처리만 담당하고, 실제 DB 쿼리 로직은 서비스 레이어에서 관리한다. ## 구현 내용 ### getSummary() - 서비스 전체 판결 완료 건수(totalJudgements) 집계 - dispute.status = JUDGED 조건 명시: ai_judgements는 판결 완료 시에만 생성되지만 의도를 코드에 명시적으로 표현 - deletedAt / anonymizedAt IS NULL: 삭제·익명화된 사건 제외 (CLAUDE.md §7) ### getTopTypes(size = 5) - ai_judgements.result_conflict_detail_id 기준 GROUP BY COUNT DESC - 결과 유형 마스터(conflict_type_details)를 JOIN해 detailCode·displayName 반환 - isActive = true 필터: 비활성화된 유형은 통계에서 제외 - percentage 서버 계산: count / total * 100 (소수점 1자리) FE에서 별도 계산 없이 바로 사용할 수 있도록 서버에서 내려줌 - prisma.conflictTypeDetail 사용 (prisma.conflictDetail은 스키마에 존재하지 않음) Co-Authored-By: Claude Sonnet 4.6 * feat: 통계 API Route Handler 생성 (GET /api/v1/statistics/top-types) ## 생성 이유 statisticsService의 getTopTypes()를 HTTP 엔드포인트로 노출하기 위해 Next.js App Router 기반 Route Handler를 생성했다. ## 폴더 선택 이유 src/app/api/v1/statistics/top-types/ - CLAUDE.md §4 아키텍처 원칙에 따라 API Route는 src/app/api/v1/ 하위에 위치한다. - API_SPEC.md §4.9 기준 엔드포인트 경로: GET /api/v1/statistics/top-types - summary 엔드포인트는 현재 MVP 범위에서 불필요하여 top-types만 생성 ## 구현 내용 - getServerSession으로 서버에서 직접 세션 검증 (FE 리다이렉트만으로는 API 직접 호출을 막을 수 없으므로 서버 검증 필수 — CLAUDE.md §7) - 인증 실패 시 401 UNAUTHORIZED 반환 - getTopTypes(5) 호출 → 판결 완료 기준 Top5 유형 + 비율 반환 - ApiResponse 타입 준수: data/error는 null 아닌 undefined(optional) 사용 Co-Authored-By: Claude Sonnet 4.6 * fix: statistics top-types 인증 제거 (메인 페이지 공개 접근 허용) 메인 페이지에서도 통계 차트가 노출되는 익명 집계 데이터이므로 세션 없이 접근 가능하도록 수정. - getServerSession 및 관련 import 제거 - 401 인증 체크 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: statistics top-types 에러 핸들링 보완 코드래빗 피드백 반영: - catch {} -> catch (error): 에러 정보 유실 방지 - 타임아웃 감지 후 504 분기 처리 - console.error 로깅 추가 (CLAUDE.md 11 API 오류 로그 대상) - 세션 체크는 이전 커밋에서 이미 제거됨 (공개 엔드포인트) Co-Authored-By: Claude Sonnet 4.6 * refactor: 통계 API 카테고리 기준으로 재설계 - 결과 유형(top-types) → 작성 카테고리(ROMANCE/FAMILY/FRIEND/WORK) 기준으로 변경 - route.ts에 DB 쿼리 직접 작성, statisticsService.ts 제거 - 비율 계산은 프론트 훅(useStatistics)에서 담당 - revalidate = 86400 (하루 1회 재계산) - src/hooks/ 폴더 신설 및 useStatistics.ts 생성 Co-Authored-By: Claude Sonnet 4.6 * fix: 통계 API 서버 측 세션 인증 추가 - GET /api/statistics/categories 진입 시 getServerSession으로 인증 검증 - 미인증 요청 401 UNAUTHORIZED 반환 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: jungmin park Co-authored-by: Claude Sonnet 4.6 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * feat: Header variant 분리 (logo/title) 및 홈 화면 적용 (#47) * feat: 홈 화면 기본 구조 생성 (헤더, 일기 박스) - 헤더: 세션 유저명 + character-welcome.png 부엉이 이미지 - 일기 박스: 365x88, border black-700 2px, bg primary-100 - TODO: GangwonEduPower 폰트 추가 후 헤더 로고 텍스트 적용 필요 Co-Authored-By: Claude Sonnet 4.6 * feat: Header variant 분리 (logo/title) 및 홈 화면 적용 - Header.tsx에 variant prop 추가 (logo | title) - logo: 좌측 상단 말해부엉 로고 표시 (66x19, h:56, padding: 16px 20px) - title: 기존 뒤로가기 + 페이지 제목 형태 유지 - Header.module.scss에 __logo 스타일 추가 - home/page.tsx에 Header variant='logo' 적용 - 헤더를 컨테이너 padding 밖으로 분리하여 상단 여백 제거 - home/page.module.scss diaryBox에 align-self: center 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 페이지 생성 및 로고 헤더 적용 (/records) Co-Authored-By: Claude Sonnet 4.6 * fix: diaryBox 고정 폭을 max-width + width 100%로 반응형 처리 - width: 365px → width: 100% + max-width: 365px - 작은 화면에서 좌우 패딩과 결합 시 오버플로우 방지 Co-Authored-By: Claude Sonnet 4.6 * feat: 감정일기 작성 버튼 /diary/new 네비게이션 연결 - 일기 박스 전체를 Link로 변경 (텍스트 + 버튼 모두 클릭 가능) - diaryBox에 text-decoration: none, cursor: pointer 추가 - /diary/new 경로는 임시 지정 (담당자 확인 후 수정 예정) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 캐릭터 이미지 교체 및 위치 조정 - character-welcome.png → character-home.png 교체 (169x138) - 캐릭터 절대 위치 적용 (top: 41px, right: -20px) - 캐릭터가 일기 박스 뒤에 위치하도록 z-index 조정 (character: 0, container: 1) Co-Authored-By: Claude Sonnet 4.6 * fix: 홈 화면 코드래빗 피드백 반영 - 캐릭터 이미지 가로 스크롤 방지: .page에 overflow-x: hidden 추가 - 비로그인 사용자 분기 처리: 말해부엉 알아보기 박스 추가 (/login 이동) Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 화면 typography 믹신 적용 - greetingText, diaryTitle, diarySubtitle에 typography 믹신 사용 - 개별 font 속성 직접 선언 → @include m.text-* 토큰으로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: 비로그인 알아보기 박스 위치 수정 - 인사/일기 박스는 로그인 여부 무관하게 항상 표시 - 말해부엉 알아보기 박스를 진행중인 사건 위치(구분선 아래)로 이동 - 비로그인 인사: '안녕하세요' 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면에 통계 섹션 및 구분선 통합 - StatsCategorySection, useStatistics, QueryProvider 병합 - 고민 카테고리 TOP4 통계 섹션 추가 - 통계 섹션 하단 구분선 추가 (h:8px, black-100, gap:42px) Co-Authored-By: Claude Sonnet 4.6 * chore: 개발 편의용 로그인 상태 강제 설정 (배포 전 제거 필요) - isLoggedIn = true 하드코딩으로 로그인 상태 유지 - TODO 주석으로 배포 전 제거 안내 표시 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 사건작성 페이지 구현 (disputes/[id]/statement) (#46) * feat: 사건작성 페이지 구현 (disputes/[id]/statement) - 사건 카테고리 선택 (연애/직장/친구/가족) - MBTI 선택 드롭다운 - 진술 내용 입력 (최대 1000자) - 진술저장 버튼 (내용 입력 시 활성화) - TODO: 진술 저장 API 연결 Co-Authored-By: Claude Sonnet 4.6 * fix: 사건작성 페이지 카테고리/간격/드롭다운 수정 - 카테고리를 searchParams에서 읽어 하나만 표시 (비상호작용) - 카테고리 없을 시 모달 표시 후 이전 페이지로 이동 - Select/Textarea 사이 간격 8px (statementGroup) - label/Select 사이 간격 16px 유지 - Textarea placeholder 줄바꿈 적용 (\n) - content overflow-y 제거 → Select 드롭다운 아래 방향 열림 수정 - Select placeholder 색상 var(--text-secondary) 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 없음 모달에서 버튼 제거 — 페이지 블로킹만 유지 확인 버튼 클릭 시 이동하지 않고 Header 뒤로가기로만 탈출 가능 Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 기본값 romance 적용, 모달 확인 버튼 복원 - searchParams에 카테고리 없을 시 임시로 romance 기본값 사용 - 모달 확인 버튼 클릭 시 router.back() 복원 - TODO: 이전 페이지 카테고리 데이터 연동 후 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: Select 커스텀 드롭다운 교체 및 Textarea focus 스타일 제거 - Select: 네이티브 select → 커스텀 드롭다운 (항상 아래 방향 열림) - Select: placeholder 색상 --text-secondary 적용 (option 색 영향 없음) - Select: 아이콘 회전 애니메이션 추가 - Textarea: focus 시 border-color 변경 제거 Co-Authored-By: Claude Sonnet 4.6 * style: Button 좌우 패딩 16 → 12으로 조정 Co-Authored-By: Claude Sonnet 4.6 * style: SCSS import 상대경로 → 절대경로(@/) 변환 및 컨벤션 문서 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: Select 접근성 및 스타일 개선 - ul 기본 margin 리셋 - hasValue를 options.find 기준으로 판단 (빈 문자열 오인 방지) - aria-invalid / aria-describedby 연결로 보조기기 지원 - 키보드 내비게이션 추가 (ArrowUp/Down, Enter/Space, Escape) Co-Authored-By: Claude Sonnet 4.6 * fix: dispute 생성 조건을 active room 전체로 완화 (ONE_TO_ONE 제한 제거) 혼자서도 판결 가능한 흐름을 지원하기 위해 room.roomMode !== 'ONE_TO_ONE' 체크를 제거하고 CLOSED/EXPIRED 방만 차단하도록 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: Select id 안정화, 빈 options 가드, Tab 기본 포커스 이동 허용 - resolvedId를 label 문자열 대신 useId() 기반으로 고정 - option id를 value 대신 index 기반으로 변경 - Enter/Space 시 options 길이 가드 추가 (크래시 방지) - Tab은 preventDefault 제거 — 닫기만 하고 포커스 이동은 브라우저에 위임 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * docs: 단독 판결 MVP 포함 및 관련 정책 업데이트 (#51) - Section 1: 단독 판결 / 1:1 판결 흐름 분리 명시 - Section 2: 단독 판결을 MVP 포함으로 이동, MVP 제외에서 제거 - Section 3: AI 대화방 정책 수정 (ai_chat/invite_ready 상태 단독 판결 허용) - Section 3: 단독 판결 vs 1:1 판결 제공 결과 비교 섹션 추가 - Section 14: 단독 판결 관련 STOP Condition 항목 제거 Co-authored-by: Claude Sonnet 4.6 * Feature/verdict record display - 캘린더 페이지 ui 제작 (#41) * feat : 다이어리 (감정일기 , 사건기록)탭분리 * feat : 달력 ui 커스텀 추가 및 감정일기 사건기록 분기처리 * refactor: 및 캘린더 페이지구조 개선 (리뷰 피드백 반영) * feat : 감정일기카드 컴포넌트 구현 * fix: build 에러 ( 임시 페이지 ) * refactor: 감정일기 컴포넌트 SCSS 모듈 적용 및 믹스인 토큰 사용 * feat: 달력 페이지 UI 구현 및 스타일 정리 - MUI DateCalendar 커스텀 - 감정일기 / 사건기록 탭 전환 구조 구현 - EmotionDiaryList, RecordList 빈 상태 UI 추가 - DiaryCard mixin 적용 (text-title-s, text-body-s, text-label-s) - 인라인 style 제거 → SCSS 모듈로 분리 - outsideCurrentMonth 감정 아이콘 노출 차단 - 새 일기 FAB 버튼 추가 (감정일기 탭 전용) - 불필요한 파일 삭제 (DiaryMode, EmotionDiaryCard 등) * style : EmotionDiaryList.moulde 스타일 수정 * feat: 달력 RecordList에 CaseCard 연동 및 스타일 개선 * Update model name from 'gpt-5.5' to 'gemini-2.5-flash' seed.ts Ai modelName 수정 --------- Co-authored-by: 배근영 * feat: 사건작성(진술서) 페이지 구현 및 욕설 감지 필터 연동 (#49) * feat: 사건작성 페이지 구현 (disputes/[id]/statement) - 사건 카테고리 선택 (연애/직장/친구/가족) - MBTI 선택 드롭다운 - 진술 내용 입력 (최대 1000자) - 진술저장 버튼 (내용 입력 시 활성화) - TODO: 진술 저장 API 연결 Co-Authored-By: Claude Sonnet 4.6 * fix: 사건작성 페이지 카테고리/간격/드롭다운 수정 - 카테고리를 searchParams에서 읽어 하나만 표시 (비상호작용) - 카테고리 없을 시 모달 표시 후 이전 페이지로 이동 - Select/Textarea 사이 간격 8px (statementGroup) - label/Select 사이 간격 16px 유지 - Textarea placeholder 줄바꿈 적용 (\n) - content overflow-y 제거 → Select 드롭다운 아래 방향 열림 수정 - Select placeholder 색상 var(--text-secondary) 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 없음 모달에서 버튼 제거 — 페이지 블로킹만 유지 확인 버튼 클릭 시 이동하지 않고 Header 뒤로가기로만 탈출 가능 Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 기본값 romance 적용, 모달 확인 버튼 복원 - searchParams에 카테고리 없을 시 임시로 romance 기본값 사용 - 모달 확인 버튼 클릭 시 router.back() 복원 - TODO: 이전 페이지 카테고리 데이터 연동 후 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: Select 커스텀 드롭다운 교체 및 Textarea focus 스타일 제거 - Select: 네이티브 select → 커스텀 드롭다운 (항상 아래 방향 열림) - Select: placeholder 색상 --text-secondary 적용 (option 색 영향 없음) - Select: 아이콘 회전 애니메이션 추가 - Textarea: focus 시 border-color 변경 제거 Co-Authored-By: Claude Sonnet 4.6 * style: Button 좌우 패딩 16 → 12으로 조정 Co-Authored-By: Claude Sonnet 4.6 * style: SCSS import 상대경로 → 절대경로(@/) 변환 및 컨벤션 문서 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: Select 접근성 및 스타일 개선 - ul 기본 margin 리셋 - hasValue를 options.find 기준으로 판단 (빈 문자열 오인 방지) - aria-invalid / aria-describedby 연결로 보조기기 지원 - 키보드 내비게이션 추가 (ArrowUp/Down, Enter/Space, Escape) Co-Authored-By: Claude Sonnet 4.6 * fix: dispute 생성 조건을 active room 전체로 완화 (ONE_TO_ONE 제한 제거) 혼자서도 판결 가능한 흐름을 지원하기 위해 room.roomMode !== 'ONE_TO_ONE' 체크를 제거하고 CLOSED/EXPIRED 방만 차단하도록 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: Select id 안정화, 빈 options 가드, Tab 기본 포커스 이동 허용 - resolvedId를 label 문자열 대신 useId() 기반으로 고정 - option id를 value 대신 index 기반으로 변경 - Enter/Space 시 options 길이 가드 추가 (크래시 방지) - Tab은 preventDefault 제거 — 닫기만 하고 포커스 이동은 브라우저에 위임 Co-Authored-By: Claude Sonnet 4.6 * feat: Textarea 바이트 카운팅 및 filterMessage prop 추가 - 한글 2바이트/ASCII 1바이트 기준으로 글자 수 계산 - maxLength 초과 시 바이트 기준으로 자동 truncate - filterMessage prop 추가 — 욕설 차단 메시지 동적 표시 - border 색상 변경은 error prop에만 적용 (filter는 border 유지) - filter-warning 텍스트: Body-S + var(--text-danger) - field gap 8 → 10px (Figma 기준) Co-Authored-By: Claude Sonnet 4.6 * feat: 욕설 감지 필터 구현 (Gemini 2.5 Flash) - moderation.ts: Gemini 2.5 Flash 기반 욕설/개인정보 감지 - isBlocked: 욕설·혐오·위협 차단 (보수적 기준) - hasPersonalInfo: 개인정보 경고 (차단 없음) - fail-open: Gemini 실패 시 pending 상태로 저장 - statements/route.ts: 진술 저장 API - 모더레이션 통과 후 upsert + ModerationLog 트랜잭션 - 차단 시 ModerationLog만 기록, 저장 없이 422 반환 - dev bypass: 개발 환경에서 세션 없이 모더레이션 테스트 가능 - page.tsx: handleSave 연결, filterMessage 상태, 개인정보 경고 모달 - StatementPage.module.scss: 모달 스타일, Stylelint 공백 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: PR #49 코드리뷰 수정 — MBTI 연동, 파싱 에러, 인젝션, 타임아웃 - MBTI: GET /api/user/me 신규 생성, statement 페이지 마운트 시 user.mbti 초기화 - MBTI: handleSave body에 mbti 포함, statements route에서 user.mbti 업데이트 (트랜잭션) - statement/page.tsx: res.json() 파싱 실패를 별도 try-catch로 분리 - Textarea.tsx: e.target.value 직접 변경 → Object.assign으로 새 이벤트 객체 전달 - moderation.ts: content 삽입 전 < > HTML 이스케이프 (프롬프트 인젝션 방지) - moderation.ts: Promise.race() 기반 10초 타임아웃 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: user/me route catch 블록에 에러 로깅 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: judge route 1인 판결 허용 — isSolo 분기 및 rollback 상태 수정 - 2인: BOTH_SUBMITTED 상태 확인 유지 - 1인: 진술 제출 여부만 확인 (statements.length > 0) - 롤백 대상을 하드코딩된 BOTH_SUBMITTED → previousStatus로 교체 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 카카오 로그인 기능 구현 (#50) * feat(common): add Button, Toast, Header, BottomNavigation components - Button: primary / outline / disabled variants, design token 기반 - Toast: Zustand store 연동, 상단 고정, 시맨틱 컬러 토큰 적용 - Header: 뒤로가기 + title + subtitle 구조, 조건부 title centering - BottomNavigation: 4탭(홈/사건기록/일기/마이페이지), lucide-react 아이콘 - toastStore: Zustand UI 상태 (show/hide/message) * docs: update collaboration policy - GitHub Ruleset 브랜치 규칙 추가 (브랜치 Pattern 2, PR 제목 Pattern 1 분리) - Issues / Milestones / Project Board 미사용으로 관련 내용 제거 - GIT_WORKFLOW 작업 흐름에서 Issue 생성/자동종료 단계 제거 - PR_RULES PR 본문에서 관련 Issue 항목 제거 * feat(common): add Tabs, CaseCard, ActionPrompt, Input, Select, Textarea components Co-Authored-By: Claude Sonnet 4.6 * feat(common): apply MUI icons and Snackbar, update MUI usage policy - Toast: MUI Snackbar (3s auto-dismiss) - BottomNavigation, Header, Select: lucide-react → @mui/icons-material - Install @mui/icons-material - CLAUDE.md, CODING_CONVENTION.md: MUI usage policy updated Co-Authored-By: Claude Sonnet 4.6 * docs: update icon policy — @mui/icons-material except diary feature Co-Authored-By: Claude Sonnet 4.6 * fix(common): ActionPrompt message 제거 및 Textarea 글자수 카운터 absolute 배치 Co-Authored-By: Claude Sonnet 4.6 * feat: 카카오 로그인 기능 구현 - 로그인 페이지 UI 및 카카오 signIn 버튼 연결 - @auth/prisma-adapter 설치 및 authOptions에 적용 - 최초 로그인 시 kakaoId, nickname, termsAgreedAt 자동 설정 - 닉네임 자동 생성 유틸 추가 (~하는부엉이 + 4자리 난수) - middleware 추가: 비인증 사용자 /login 리다이렉트 Co-Authored-By: Claude Sonnet 4.6 * fix: 로그인 페이지 및 인증 로직 개선 - SCSS import 절대경로(@/) 수정 - 캐릭터 이미지 Next/Image fill → img 태그로 변경 - 이용약관/개인정보처리방침 링크(/terms, /privacy) 추가 및 스타일 적용 - 닉네임 유니크 제약(@unique) 추가 및 충돌 재시도 로직 구현 (최대 10회) - middleware matcher 패턴 보완 (/login-help 등 우회 경로 차단) Co-Authored-By: Claude Sonnet 4.6 * fix: disclaimer mixin 적용, nickname 유실 복구 및 fallback 랜덤화 - .disclaimer에 @include m.text-caption mixin 적용 - 유실된 nickname.ts 복구 - fallback 닉네임 Date.now() → 랜덤 8자리 숫자로 변경 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * docs: 단독/1:1 판결 공통 진입 흐름 반영 및 관련 문서 일괄 수정 (#54) - 단독 판결과 1:1 판결이 완전히 분리된 진입이 아니라 AI 대화방 → 진술저장 → [분기] → disputes/[id]/statement 경로를 공통으로 거침 - CLAUDE.md: 핵심 서비스 흐름 분기 구조로 수정, 단독 판결 MVP 포함 반영, AI 대화방 정책 단독/1:1 병행 기술, dispute_status 단독 경로 추가 - PROJECT_DECISIONS.md: 흐름·MVP포함·MVP제외·dispute_status 동기화 - STATUS_TRANSITION.md: 단독 판결 경로(draft→judging→judged) 추가 - DISPUTE.md: 상태 전이 단독/1:1 경로 분리 기술, 주의사항 확정 내용 반영 - ROOM.md: 진술저장 후 분기 흐름 포함 기능에 명시 Co-authored-by: Claude Sonnet 4.6 * fix: Login 페이지 hydration removeChild 에러 수정 (#55) * feat(common): add Button, Toast, Header, BottomNavigation components - Button: primary / outline / disabled variants, design token 기반 - Toast: Zustand store 연동, 상단 고정, 시맨틱 컬러 토큰 적용 - Header: 뒤로가기 + title + subtitle 구조, 조건부 title centering - BottomNavigation: 4탭(홈/사건기록/일기/마이페이지), lucide-react 아이콘 - toastStore: Zustand UI 상태 (show/hide/message) * docs: update collaboration policy - GitHub Ruleset 브랜치 규칙 추가 (브랜치 Pattern 2, PR 제목 Pattern 1 분리) - Issues / Milestones / Project Board 미사용으로 관련 내용 제거 - GIT_WORKFLOW 작업 흐름에서 Issue 생성/자동종료 단계 제거 - PR_RULES PR 본문에서 관련 Issue 항목 제거 * feat(common): add Tabs, CaseCard, ActionPrompt, Input, Select, Textarea components Co-Authored-By: Claude Sonnet 4.6 * feat(common): apply MUI icons and Snackbar, update MUI usage policy - Toast: MUI Snackbar (3s auto-dismiss) - BottomNavigation, Header, Select: lucide-react → @mui/icons-material - Install @mui/icons-material - CLAUDE.md, CODING_CONVENTION.md: MUI usage policy updated Co-Authored-By: Claude Sonnet 4.6 * docs: update icon policy — @mui/icons-material except diary feature Co-Authored-By: Claude Sonnet 4.6 * fix(common): ActionPrompt message 제거 및 Textarea 글자수 카운터 absolute 배치 Co-Authored-By: Claude Sonnet 4.6 * feat: 카카오 로그인 기능 구현 - 로그인 페이지 UI 및 카카오 signIn 버튼 연결 - @auth/prisma-adapter 설치 및 authOptions에 적용 - 최초 로그인 시 kakaoId, nickname, termsAgreedAt 자동 설정 - 닉네임 자동 생성 유틸 추가 (~하는부엉이 + 4자리 난수) - middleware 추가: 비인증 사용자 /login 리다이렉트 Co-Authored-By: Claude Sonnet 4.6 * fix: 로그인 페이지 및 인증 로직 개선 - SCSS import 절대경로(@/) 수정 - 캐릭터 이미지 Next/Image fill → img 태그로 변경 - 이용약관/개인정보처리방침 링크(/terms, /privacy) 추가 및 스타일 적용 - 닉네임 유니크 제약(@unique) 추가 및 충돌 재시도 로직 구현 (최대 10회) - middleware matcher 패턴 보완 (/login-help 등 우회 경로 차단) Co-Authored-By: Claude Sonnet 4.6 * fix: disclaimer mixin 적용, nickname 유실 복구 및 fallback 랜덤화 - .disclaimer에 @include m.text-caption mixin 적용 - 유실된 nickname.ts 복구 - fallback 닉네임 Date.now() → 랜덤 8자리 숫자로 변경 Co-Authored-By: Claude Sonnet 4.6 * chore: update claude settings * fix: Login 페이지 hydration removeChild 에러 수정 html, body 태그에 suppressHydrationWarning 추가하여 브라우저 확장 프로그램의 DOM 조작으로 인한 hydration 불일치 에러를 방지한다. Co-Authored-By: Claude --------- Co-authored-by: Claude Sonnet 4.6 * fix: statements submittedAt 멱등성 보장, 에러 로깅, moderation JSON 파싱 에러 처리 (#56) * fix: statements route submittedAt 설정 및 에러 로깅, moderation JSON.parse 에러 처리 - statements: fail-open/approved 경로 모두 submittedAt 설정 → 재제출 방지 멱등성 보장 - statements: StatementData.submittedAt 타입 string | null로 수정 - statements: 외부 catch 블록에 console.error 에러 로깅 추가 - moderation: JSON.parse를 try-catch로 감싸 파싱 실패 시 명확한 에러 전파 Co-Authored-By: Claude Sonnet 4.6 * fix: statements 중복 제출 원자적 차단 upsert가 submittedAt 여부와 무관하게 update를 실행해 동시 요청이 모두 통과하는 경쟁 조건을 제거한다. - isNew: create 사용, P2002 unique 충돌 → StatementConflictError → 409 - !isNew: updateMany(where: submittedAt: null) 사용, count === 0 → StatementConflictError → 409 - fail-open/approved 경로 모두 동일 패턴 적용 - outer catch에서 StatementConflictError 분기하여 409 반환 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 홈 화면 진행중인 사건 섹션 구현 (#52) * feat: 홈 화면 기본 구조 생성 (헤더, 일기 박스) - 헤더: 세션 유저명 + character-welcome.png 부엉이 이미지 - 일기 박스: 365x88, border black-700 2px, bg primary-100 - TODO: GangwonEduPower 폰트 추가 후 헤더 로고 텍스트 적용 필요 Co-Authored-By: Claude Sonnet 4.6 * feat: Header variant 분리 (logo/title) 및 홈 화면 적용 - Header.tsx에 variant prop 추가 (logo | title) - logo: 좌측 상단 말해부엉 로고 표시 (66x19, h:56, padding: 16px 20px) - title: 기존 뒤로가기 + 페이지 제목 형태 유지 - Header.module.scss에 __logo 스타일 추가 - home/page.tsx에 Header variant='logo' 적용 - 헤더를 컨테이너 padding 밖으로 분리하여 상단 여백 제거 - home/page.module.scss diaryBox에 align-self: center 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 페이지 생성 및 로고 헤더 적용 (/records) Co-Authored-By: Claude Sonnet 4.6 * fix: diaryBox 고정 폭을 max-width + width 100%로 반응형 처리 - width: 365px → width: 100% + max-width: 365px - 작은 화면에서 좌우 패딩과 결합 시 오버플로우 방지 Co-Authored-By: Claude Sonnet 4.6 * feat: 감정일기 작성 버튼 /diary/new 네비게이션 연결 - 일기 박스 전체를 Link로 변경 (텍스트 + 버튼 모두 클릭 가능) - diaryBox에 text-decoration: none, cursor: pointer 추가 - /diary/new 경로는 임시 지정 (담당자 확인 후 수정 예정) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 캐릭터 이미지 교체 및 위치 조정 - character-welcome.png → character-home.png 교체 (169x138) - 캐릭터 절대 위치 적용 (top: 41px, right: -20px) - 캐릭터가 일기 박스 뒤에 위치하도록 z-index 조정 (character: 0, container: 1) Co-Authored-By: Claude Sonnet 4.6 * fix: 홈 화면 코드래빗 피드백 반영 - 캐릭터 이미지 가로 스크롤 방지: .page에 overflow-x: hidden 추가 - 비로그인 사용자 분기 처리: 말해부엉 알아보기 박스 추가 (/login 이동) Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 화면 typography 믹신 적용 - greetingText, diaryTitle, diarySubtitle에 typography 믹신 사용 - 개별 font 속성 직접 선언 → @include m.text-* 토큰으로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: 비로그인 알아보기 박스 위치 수정 - 인사/일기 박스는 로그인 여부 무관하게 항상 표시 - 말해부엉 알아보기 박스를 진행중인 사건 위치(구분선 아래)로 이동 - 비로그인 인사: '안녕하세요' 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면에 통계 섹션 및 구분선 통합 - StatsCategorySection, useStatistics, QueryProvider 병합 - 고민 카테고리 TOP4 통계 섹션 추가 - 통계 섹션 하단 구분선 추가 (h:8px, black-100, gap:42px) Co-Authored-By: Claude Sonnet 4.6 * chore: 개발 편의용 로그인 상태 강제 설정 (배포 전 제거 필요) - isLoggedIn = true 하드코딩으로 로그인 상태 유지 - TODO 주석으로 배포 전 제거 안내 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 진행중인 사건 섹션 UI 구현 - ActiveCasesSection 컴포넌트 추가 - 진행중인 사건 목록 표시 (waiting_opponent / opponent_joined / both_submitted) - CaseCard 공통 컴포넌트 재사용 - 좌측 카테고리 컬러 accent bar - 카드 간격 12px - useActiveCases 훅 추가 (mock 데이터, TODO: 실 API 연동) - CaseCard에 participants prop 추가 (AvatarGroup 렌더링) - CategoryIcon의 CATEGORY_COLOR_MAP export 추가 - 홈 페이지에 로그인 시 ActiveCasesSection 표시 - 구분선 ↔ 섹션 간격 20px 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 수정 - CaseCard 원본 구조 유지, 좌측 컬러바 제거, Avatar 좌측 배치 - CaseCard 원본 구조 완전 원복 (participants prop 제거, div 래퍼 제거) - CategoryIcon CATEGORY_COLOR_MAP export 원복 - 불필요한 좌측 카테고리 accent bar 제거 - Avatar absolute 오버레이 우측→좌측 하단 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard preview 텍스트 컬러 black-700으로 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 섹션 내 진행중 뱃지 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 푸터 레이아웃 및 외곽선 black-700 2px inset 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 preview-footer 간격 8px 조정 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드래빗 리뷰 반영 - 린트, loading/error 상태 처리, onClick li로 이동 Co-Authored-By: Claude Sonnet 4.6 * chore: 홈 화면 캐릭터 이미지 추가 Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 페이지를 /home에서 / 루트 경로로 이동 변경 이유: - src/app/page.tsx: 홈 화면 콘텐츠를 루트 경로(/)에서 서빙하도록 이동 → Next.js App Router에서 루트 경로는 src/app/page.tsx가 담당하므로 기존 (page)/home/page.tsx 대신 루트로 이동하는 것이 구조적으로 올바름 - src/app/page.module.scss: (page)/home/page.module.scss를 루트로 이동 → page.tsx와 동일 위치에서 관리하도록 이동 (git rename으로 추적됨) - src/app/(page)/home/page.tsx: redirect('/')로 교체 → 기존 /home URL 접근 시 /로 리다이렉트하여 북마크/공유 링크 호환성 유지 - src/app/(page)/login/page.tsx: callbackUrl '/home' → '/' → 로그인 성공 후 이동 경로를 변경된 홈 경로(/)에 맞게 수정 - src/components/layout/BottomNavigation.tsx: href '/home' → '/' → 하단 탭 홈 버튼이 올바른 경로를 가리키도록 수정 → pathname.startsWith('/') 는 모든 경로에서 true이므로 홈 탭 활성 조건을 pathname === '/' 로 변경하여 활성 상태 오류 수정 - src/components/home/StatsCategorySection.module.scss: width 100%로 변경 → 고정 픽셀(346px) 대신 width: 100%로 반응형 처리 - src/middleware.ts: 개발 환경 인증 bypass 추가 → PR #50 카카오 로그인 병합 후 next-auth/middleware가 모든 경로를 차단하게 됨 → 개발 편의를 위해 NODE_ENV === development 일 때 인증 없이 접근 허용 → 배포 전 반드시 제거 필요 (TODO 주석 명시) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 사건조회 페이지 구현 (진행중/진행완료, 1인/2인 분기) (#53) * feat: 사건작성 페이지 구현 (disputes/[id]/statement) - 사건 카테고리 선택 (연애/직장/친구/가족) - MBTI 선택 드롭다운 - 진술 내용 입력 (최대 1000자) - 진술저장 버튼 (내용 입력 시 활성화) - TODO: 진술 저장 API 연결 Co-Authored-By: Claude Sonnet 4.6 * fix: 사건작성 페이지 카테고리/간격/드롭다운 수정 - 카테고리를 searchParams에서 읽어 하나만 표시 (비상호작용) - 카테고리 없을 시 모달 표시 후 이전 페이지로 이동 - Select/Textarea 사이 간격 8px (statementGroup) - label/Select 사이 간격 16px 유지 - Textarea placeholder 줄바꿈 적용 (\n) - content overflow-y 제거 → Select 드롭다운 아래 방향 열림 수정 - Select placeholder 색상 var(--text-secondary) 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 없음 모달에서 버튼 제거 — 페이지 블로킹만 유지 확인 버튼 클릭 시 이동하지 않고 Header 뒤로가기로만 탈출 가능 Co-Authored-By: Claude Sonnet 4.6 * fix: 카테고리 기본값 romance 적용, 모달 확인 버튼 복원 - searchParams에 카테고리 없을 시 임시로 romance 기본값 사용 - 모달 확인 버튼 클릭 시 router.back() 복원 - TODO: 이전 페이지 카테고리 데이터 연동 후 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: Select 커스텀 드롭다운 교체 및 Textarea focus 스타일 제거 - Select: 네이티브 select → 커스텀 드롭다운 (항상 아래 방향 열림) - Select: placeholder 색상 --text-secondary 적용 (option 색 영향 없음) - Select: 아이콘 회전 애니메이션 추가 - Textarea: focus 시 border-color 변경 제거 Co-Authored-By: Claude Sonnet 4.6 * style: Button 좌우 패딩 16 → 12으로 조정 Co-Authored-By: Claude Sonnet 4.6 * style: SCSS import 상대경로 → 절대경로(@/) 변환 및 컨벤션 문서 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: Select 접근성 및 스타일 개선 - ul 기본 margin 리셋 - hasValue를 options.find 기준으로 판단 (빈 문자열 오인 방지) - aria-invalid / aria-describedby 연결로 보조기기 지원 - 키보드 내비게이션 추가 (ArrowUp/Down, Enter/Space, Escape) Co-Authored-By: Claude Sonnet 4.6 * fix: dispute 생성 조건을 active room 전체로 완화 (ONE_TO_ONE 제한 제거) 혼자서도 판결 가능한 흐름을 지원하기 위해 room.roomMode !== 'ONE_TO_ONE' 체크를 제거하고 CLOSED/EXPIRED 방만 차단하도록 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: Select id 안정화, 빈 options 가드, Tab 기본 포커스 이동 허용 - resolvedId를 label 문자열 대신 useId() 기반으로 고정 - option id를 value 대신 index 기반으로 변경 - Enter/Space 시 options 길이 가드 추가 (크래시 방지) - Tab은 preventDefault 제거 — 닫기만 하고 포커스 이동은 브라우저에 위임 Co-Authored-By: Claude Sonnet 4.6 * feat: Textarea 바이트 카운팅 및 filterMessage prop 추가 - 한글 2바이트/ASCII 1바이트 기준으로 글자 수 계산 - maxLength 초과 시 바이트 기준으로 자동 truncate - filterMessage prop 추가 — 욕설 차단 메시지 동적 표시 - border 색상 변경은 error prop에만 적용 (filter는 border 유지) - filter-warning 텍스트: Body-S + var(--text-danger) - field gap 8 → 10px (Figma 기준) Co-Authored-By: Claude Sonnet 4.6 * feat: 욕설 감지 필터 구현 (Gemini 2.5 Flash) - moderation.ts: Gemini 2.5 Flash 기반 욕설/개인정보 감지 - isBlocked: 욕설·혐오·위협 차단 (보수적 기준) - hasPersonalInfo: 개인정보 경고 (차단 없음) - fail-open: Gemini 실패 시 pending 상태로 저장 - statements/route.ts: 진술 저장 API - 모더레이션 통과 후 upsert + ModerationLog 트랜잭션 - 차단 시 ModerationLog만 기록, 저장 없이 422 반환 - dev bypass: 개발 환경에서 세션 없이 모더레이션 테스트 가능 - page.tsx: handleSave 연결, filterMessage 상태, 개인정보 경고 모달 - StatementPage.module.scss: 모달 스타일, Stylelint 공백 수정 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건조회 페이지 구현 (진행중/진행완료 분기, 1인/2인 분기) - 진행중: 진술카드 + 판결받기 버튼 - 1인: 판결받기 클릭 시 solo modal (혼자서 진행 / 상대방 초대) - 2인: 판결받기 클릭 시 바로 judge API 호출 - 진행완료(judged/closed): 탭(진술|판결) + 진술카드 - 1인: 진술카드 1개 - 2인: 진술카드 2개 - judging 상태 또는 판결받기 직후: 전체화면 로딩 (Spinner + 그라데이션 배경) - 기존 Spinner, Tabs, StatusBadge, CategoryIcon, Button 재사용 Co-Authored-By: Claude Sonnet 4.6 * chore: 1인 판결 모달에 추후 Modal 컴포넌트 교체 예정 주석 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건 참여자 프로필 이미지 연동 - DisputeParticipantDto에 profileImageUrl 추가 - GET/POST /api/disputes, GET/PATCH /api/disputes/[id] participants include에 user.profileImageUrl 추가 - 사건조회 infoCard 날짜 좌측 아바타 스택 스타일 추가 (1인 1개, 2인 2개 겹침) - 프로필 이미지 없을 경우 fallback 원형 placeholder Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 초대 참여 페이지 퍼블리싱 및 공통 UI 컴포넌트 추가 (#57) * feat(join): 초대 참여 페이지 퍼블리싱 Figma 시안 기반 /join 페이지 UI 구현. - 판사 부엉이 캐릭터 이미지 표시 (판사 이미지 준비 시 교체 예정) - 초대자 이름 teal 색상 강조, 사건 요청 안내 문구 - 하단 고정 '진술하러 가기' 버튼 - SCSS 절대경로 사용을 위해 next.config.ts sassOptions.includePaths 추가 Co-Authored-By: Claude Sonnet 4.6 * revert(config): next.config.ts sassOptions 제거, SCSS 상대경로 복원 sassOptions.includePaths는 로컬 환경에서 개별 설정. join.module.scss 상대경로로 복원하여 기존 코드 컨벤션 통일. Co-Authored-By: Claude Sonnet 4.6 * build(config): SCSS 절대경로 지원을 위한 sassOptions.includePaths 추가 next.config.ts에 sassOptions.includePaths: ['src'] 설정. 이후 SCSS 파일에서 상대경로 대신 'styles/abstracts/...' 절대경로 사용 가능. join.module.scss 절대경로로 전환. Co-Authored-By: Claude Sonnet 4.6 * feat(join): 초대 에러 상태 화면 추가 (접근불가·종료만료) JoinStatusView 공통 레이아웃 컴포넌트 추출. - error: 접근 불가 (무효 토큰·차단) 화면 - closed: 사건 종료 또는 링크 만료 화면 - 세 상태 모두 동일 레이아웃, 캐릭터·문구·버튼만 상이 - TODO: API 연동 후 currentState 실제 값으로 교체 Co-Authored-By: Claude Sonnet 4.6 * ref(join): JoinStatusView를 공용 컴포넌트로 이동 _components/에서 src/components/ui/로 이동하여 /disputes 등 다른 페이지에서도 재사용 가능하도록 변경. Co-Authored-By: Claude Sonnet 4.6 * feat(ui): Button size prop 추가 및 InviteChoiceModal 컴포넌트 구현 - Button에 size prop 추가 (md 기본 52px, sm 48px) - ActionPrompt 점선 테두리·패딩 제거, size/secondaryVariant prop 추가 - Modal 공용 컴포넌트 추가 (MuiDialog 래핑) - InviteChoiceModal 구현 (ActionPrompt 사용, soft+primary 조합) - SCSS @use 상대경로 → 절대경로 변환 Co-Authored-By: Claude Sonnet 4.6 * feat(join): InviteChoiceModal 열고닫기 및 스타일 수정 - 진술하러 가기 버튼 클릭 시 모달 열기 (useState) - 딤 클릭 시 모달 닫기 (onClose 연결) - InviteChoiceModal 메시지 타이포 text-title-s 적용 - Modal 테두리 color-black-700 적용, border !important 추가 Co-Authored-By: Claude * refactor(join): 하드코딩 제거 및 API 연동 TODO 정리 * fix: stylelint declaration-empty-line-before 수정 및 Button type 기본값 추가 * fix(join): closed/expired 상태 분리 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 이용약관, 개인정보처리방침 페이지 추가 (#58) * feat(common): add Button, Toast, Header, BottomNavigation components - Button: primary / outline / disabled variants, design token 기반 - Toast: Zustand store 연동, 상단 고정, 시맨틱 컬러 토큰 적용 - Header: 뒤로가기 + title + subtitle 구조, 조건부 title centering - BottomNavigation: 4탭(홈/사건기록/일기/마이페이지), lucide-react 아이콘 - toastStore: Zustand UI 상태 (show/hide/message) * docs: update collaboration policy - GitHub Ruleset 브랜치 규칙 추가 (브랜치 Pattern 2, PR 제목 Pattern 1 분리) - Issues / Milestones / Project Board 미사용으로 관련 내용 제거 - GIT_WORKFLOW 작업 흐름에서 Issue 생성/자동종료 단계 제거 - PR_RULES PR 본문에서 관련 Issue 항목 제거 * feat(common): add Tabs, CaseCard, ActionPrompt, Input, Select, Textarea components Co-Authored-By: Claude Sonnet 4.6 * feat(common): apply MUI icons and Snackbar, update MUI usage policy - Toast: MUI Snackbar (3s auto-dismiss) - BottomNavigation, Header, Select: lucide-react → @mui/icons-material - Install @mui/icons-material - CLAUDE.md, CODING_CONVENTION.md: MUI usage policy updated Co-Authored-By: Claude Sonnet 4.6 * docs: update icon policy — @mui/icons-material except diary feature Co-Authored-By: Claude Sonnet 4.6 * fix(common): ActionPrompt message 제거 및 Textarea 글자수 카운터 absolute 배치 Co-Authored-By: Claude Sonnet 4.6 * feat: 카카오 로그인 기능 구현 - 로그인 페이지 UI 및 카카오 signIn 버튼 연결 - @auth/prisma-adapter 설치 및 authOptions에 적용 - 최초 로그인 시 kakaoId, nickname, termsAgreedAt 자동 설정 - 닉네임 자동 생성 유틸 추가 (~하는부엉이 + 4자리 난수) - middleware 추가: 비인증 사용자 /login 리다이렉트 Co-Authored-By: Claude Sonnet 4.6 * fix: 로그인 페이지 및 인증 로직 개선 - SCSS import 절대경로(@/) 수정 - 캐릭터 이미지 Next/Image fill → img 태그로 변경 - 이용약관/개인정보처리방침 링크(/terms, /privacy) 추가 및 스타일 적용 - 닉네임 유니크 제약(@unique) 추가 및 충돌 재시도 로직 구현 (최대 10회) - middleware matcher 패턴 보완 (/login-help 등 우회 경로 차단) Co-Authored-By: Claude Sonnet 4.6 * fix: disclaimer mixin 적용, nickname 유실 복구 및 fallback 랜덤화 - .disclaimer에 @include m.text-caption mixin 적용 - 유실된 nickname.ts 복구 - fallback 닉네임 Date.now() → 랜덤 8자리 숫자로 변경 Co-Authored-By: Claude Sonnet 4.6 * chore: update claude settings * fix: Login 페이지 hydration removeChild 에러 수정 html, body 태그에 suppressHydrationWarning 추가하여 브라우저 확장 프로그램의 DOM 조작으로 인한 hydration 불일치 에러를 방지한다. Co-Authored-By: Claude * feat(auth): Add terms of service and privacy policy pages Add /terms and /privacy pages with 7 articles each covering AI mediation service usage, AI data processing, liability limits, and personal information handling. Both pages use text-only layout with MUI ArrowBack icon for navigation. Co-Authored-By: Claude * fix(auth): Allow unauthenticated access to terms and privacy pages Add /terms and /privacy to middleware matcher exclusion list so users can view these pages without logging in first. Co-Authored-By: Claude * fix(auth): Update terms and privacy page content and header layout Expand terms of service to 15 articles and privacy policy to 13 articles with detailed service-specific content. Update header layout to center-aligned title with ArrowBackIosNew icon and bottom border matching existing Header component style. Co-Authored-By: Claude --------- Co-authored-by: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 시 UUID 형식 검증 오류 수정 (#59) * fix(auth): signIn 콜백에서 UUID 형식 검증 추가 카카오 OAuth 최초 로그인 시 PrismaAdapter가 User를 생성하기 전에 signIn 콜백이 실행되면서 카카오 숫자 ID(길이 10)로 UUID 컬럼을 조회하여 Prisma 에러가 발생하던 문제 수정. - signIn 콜백에 UUID 형식 검증 추가하여 비-UUID ID는 스킵 - events.createUser에서 신규 사용자 커스텀 필드 설정 처리 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 OAuth linkAccount 시 미지원 필드 필터링 카카오 OAuth 토큰 응답에 포함된 refresh_token_expires_in 필드가 Account 스키마에 없어서 linkAccount 단계에서 Prisma 에러 발생. PrismaAdapter를 래핑하여 Account 스키마에 정의된 필드만 저장하도록 필터링. Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 버튼 및 약관 문구 수정 - 카카오 버튼 아이콘을 말풍선에서 TALK 아이콘으로 변경 - 버튼 배경색 #FFE812로 수정 - 약관 동의 문구를 서비스 가이드에 맞게 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 버튼 아이콘을 기본 말풍선으로 복원 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 리다이렉트 오류 수정 (SessionProvider 추가) (#61) * fix(auth): signIn 콜백에서 UUID 형식 검증 추가 카카오 OAuth 최초 로그인 시 PrismaAdapter가 User를 생성하기 전에 signIn 콜백이 실행되면서 카카오 숫자 ID(길이 10)로 UUID 컬럼을 조회하여 Prisma 에러가 발생하던 문제 수정. - signIn 콜백에 UUID 형식 검증 추가하여 비-UUID ID는 스킵 - events.createUser에서 신규 사용자 커스텀 필드 설정 처리 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 OAuth linkAccount 시 미지원 필드 필터링 카카오 OAuth 토큰 응답에 포함된 refresh_token_expires_in 필드가 Account 스키마에 없어서 linkAccount 단계에서 Prisma 에러 발생. PrismaAdapter를 래핑하여 Account 스키마에 정의된 필드만 저장하도록 필터링. Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 버튼 및 약관 문구 수정 - 카카오 버튼 아이콘을 말풍선에서 TALK 아이콘으로 변경 - 버튼 배경색 #FFE812로 수정 - 약관 동의 문구를 서비스 가이드에 맞게 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 버튼 아이콘을 기본 말풍선으로 복원 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): SessionProvider 추가 및 카카오 로그인 콜백 페이지 구현 SessionProvider가 앱 전역에 적용되지 않아 signIn() 호출과 콜백 후 세션 인식이 실패하던 문제를 수정한다. AuthProvider 래퍼 컴포넌트를 추가하고 layout.tsx에 적용한다. 카카오 OAuth 콜백 후 세션 상태를 확인하고 홈으로 리다이렉트하는 중간 페이지(/auth/callback)를 추가한다. middleware matcher에 해당 경로를 인증 체크 제외 대상으로 등록한다. Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 콜백 페이지 오픈 리다이렉트 취약점 수정 및 Stylelint 규칙 위반 해결 callbackUrl 파라미터가 검증 없이 router.replace()로 전달되어 외부 도메인으로 리다이렉트될 수 있는 취약점을 수정한다. 로컬 경로만 허용하고 프로토콜 상대 URL과 무한 루프를 차단한다. 로그인 페이지에서 원래 목적지(callbackUrl)를 콜백 페이지로 전달하도록 수정하여 인증 후 원래 페이지로 복귀 가능하게 한다. callback.module.scss의 declaration-empty-line-before 규칙 위반을 빈 줄 추가로 해결한다. Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 홈 화면 새 사건 버튼, 카테고리 모달, 서비스 정보 푸터 구현 (#62) * feat: 홈 화면 기본 구조 생성 (헤더, 일기 박스) - 헤더: 세션 유저명 + character-welcome.png 부엉이 이미지 - 일기 박스: 365x88, border black-700 2px, bg primary-100 - TODO: GangwonEduPower 폰트 추가 후 헤더 로고 텍스트 적용 필요 Co-Authored-By: Claude Sonnet 4.6 * feat: Header variant 분리 (logo/title) 및 홈 화면 적용 - Header.tsx에 variant prop 추가 (logo | title) - logo: 좌측 상단 말해부엉 로고 표시 (66x19, h:56, padding: 16px 20px) - title: 기존 뒤로가기 + 페이지 제목 형태 유지 - Header.module.scss에 __logo 스타일 추가 - home/page.tsx에 Header variant='logo' 적용 - 헤더를 컨테이너 padding 밖으로 분리하여 상단 여백 제거 - home/page.module.scss diaryBox에 align-self: center 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 페이지 생성 및 로고 헤더 적용 (/records) Co-Authored-By: Claude Sonnet 4.6 * fix: diaryBox 고정 폭을 max-width + width 100%로 반응형 처리 - width: 365px → width: 100% + max-width: 365px - 작은 화면에서 좌우 패딩과 결합 시 오버플로우 방지 Co-Authored-By: Claude Sonnet 4.6 * feat: 감정일기 작성 버튼 /diary/new 네비게이션 연결 - 일기 박스 전체를 Link로 변경 (텍스트 + 버튼 모두 클릭 가능) - diaryBox에 text-decoration: none, cursor: pointer 추가 - /diary/new 경로는 임시 지정 (담당자 확인 후 수정 예정) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 캐릭터 이미지 교체 및 위치 조정 - character-welcome.png → character-home.png 교체 (169x138) - 캐릭터 절대 위치 적용 (top: 41px, right: -20px) - 캐릭터가 일기 박스 뒤에 위치하도록 z-index 조정 (character: 0, container: 1) Co-Authored-By: Claude Sonnet 4.6 * fix: 홈 화면 코드래빗 피드백 반영 - 캐릭터 이미지 가로 스크롤 방지: .page에 overflow-x: hidden 추가 - 비로그인 사용자 분기 처리: 말해부엉 알아보기 박스 추가 (/login 이동) Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 화면 typography 믹신 적용 - greetingText, diaryTitle, diarySubtitle에 typography 믹신 사용 - 개별 font 속성 직접 선언 → @include m.text-* 토큰으로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: 비로그인 알아보기 박스 위치 수정 - 인사/일기 박스는 로그인 여부 무관하게 항상 표시 - 말해부엉 알아보기 박스를 진행중인 사건 위치(구분선 아래)로 이동 - 비로그인 인사: '안녕하세요' 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면에 통계 섹션 및 구분선 통합 - StatsCategorySection, useStatistics, QueryProvider 병합 - 고민 카테고리 TOP4 통계 섹션 추가 - 통계 섹션 하단 구분선 추가 (h:8px, black-100, gap:42px) Co-Authored-By: Claude Sonnet 4.6 * chore: 개발 편의용 로그인 상태 강제 설정 (배포 전 제거 필요) - isLoggedIn = true 하드코딩으로 로그인 상태 유지 - TODO 주석으로 배포 전 제거 안내 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 진행중인 사건 섹션 UI 구현 - ActiveCasesSection 컴포넌트 추가 - 진행중인 사건 목록 표시 (waiting_opponent / opponent_joined / both_submitted) - CaseCard 공통 컴포넌트 재사용 - 좌측 카테고리 컬러 accent bar - 카드 간격 12px - useActiveCases 훅 추가 (mock 데이터, TODO: 실 API 연동) - CaseCard에 participants prop 추가 (AvatarGroup 렌더링) - CategoryIcon의 CATEGORY_COLOR_MAP export 추가 - 홈 페이지에 로그인 시 ActiveCasesSection 표시 - 구분선 ↔ 섹션 간격 20px 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 수정 - CaseCard 원본 구조 유지, 좌측 컬러바 제거, Avatar 좌측 배치 - CaseCard 원본 구조 완전 원복 (participants prop 제거, div 래퍼 제거) - CategoryIcon CATEGORY_COLOR_MAP export 원복 - 불필요한 좌측 카테고리 accent bar 제거 - Avatar absolute 오버레이 우측→좌측 하단 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard preview 텍스트 컬러 black-700으로 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 섹션 내 진행중 뱃지 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 푸터 레이아웃 및 외곽선 black-700 2px inset 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 preview-footer 간격 8px 조정 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드래빗 리뷰 반영 - 린트, loading/error 상태 처리, onClick li로 이동 Co-Authored-By: Claude Sonnet 4.6 * chore: 홈 화면 캐릭터 이미지 추가 Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 페이지를 /home에서 / 루트 경로로 이동 변경 이유: - src/app/page.tsx: 홈 화면 콘텐츠를 루트 경로(/)에서 서빙하도록 이동 → Next.js App Router에서 루트 경로는 src/app/page.tsx가 담당하므로 기존 (page)/home/page.tsx 대신 루트로 이동하는 것이 구조적으로 올바름 - src/app/page.module.scss: (page)/home/page.module.scss를 루트로 이동 → page.tsx와 동일 위치에서 관리하도록 이동 (git rename으로 추적됨) - src/app/(page)/home/page.tsx: redirect('/')로 교체 → 기존 /home URL 접근 시 /로 리다이렉트하여 북마크/공유 링크 호환성 유지 - src/app/(page)/login/page.tsx: callbackUrl '/home' → '/' → 로그인 성공 후 이동 경로를 변경된 홈 경로(/)에 맞게 수정 - src/components/layout/BottomNavigation.tsx: href '/home' → '/' → 하단 탭 홈 버튼이 올바른 경로를 가리키도록 수정 → pathname.startsWith('/') 는 모든 경로에서 true이므로 홈 탭 활성 조건을 pathname === '/' 로 변경하여 활성 상태 오류 수정 - src/components/home/StatsCategorySection.module.scss: width 100%로 변경 → 고정 픽셀(346px) 대신 width: 100%로 반응형 처리 - src/middleware.ts: 개발 환경 인증 bypass 추가 → PR #50 카카오 로그인 병합 후 next-auth/middleware가 모든 경로를 차단하게 됨 → 개발 편의를 위해 NODE_ENV === development 일 때 인증 없이 접근 허용 → 배포 전 반드시 제거 필요 (TODO 주석 명시) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 새 사건 버튼 및 서비스 정보 푸터 구현 - NewCaseButton: 홈 화면 우측 하단 고정 플로팅 버튼 추가 (w115 h48, color/black-700, border-radius 100, text-title-s) 새 사건 작성 페이지 생성 후 href 연결 필요 (TODO 주석) - HomeServiceInfo: 서비스 정보 박스 구현 (로고 w66 h19, 서비스 소개/개인정보처리방침/이용약관/고객문의 링크, Copyright 텍스트, 전체 너비 반응형, 탭바 뒤에 위치) - BottomNavigation: 홈 페이지에 탭바 추가, z-index 100 유지 (서비스 정보 박스보다 앞에 렌더링) - page.tsx: NewCaseButton, HomeServiceInfo, BottomNavigation 렌더링 추가 - page.module.scss: container padding-bottom 60px, serviceInfoWrapper 스타일 Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 카테고리 선택 모달 구현 - 새 사건 + 버튼 클릭 시 카테고리 선택 모달 표시 - 모달 오버레이: color-black-700 40% 틴트 + bg-page 불투명 베이스 (배경 콘텐츠가 비치지 않도록 레이어드 배경 처리) - 카테고리 박스: w133 h176, 흰 배경, 4개 카테고리 항목 가운데 정렬 (CategoryIcon 공통 컴포넌트 사용, 연인관계/직장관계/친구관계/가족관계) (텍스트: text-body-m, text/primary, 아이콘과 9px 간격) - X 닫기 버튼: 48x48 흰 원형, CloseIcon 24x24 - 모달 오픈 시 body overflow hidden으로 스크롤 잠금 - 카테고리 href: '#' 임시 처리 (새 사건 작성 페이지 생성 후 교체 필요) Co-Authored-By: Claude Sonnet 4.6 * fix: CodeRabbit 리뷰 반영 — isLoggedIn 하드코딩 제거, 서비스 링크 경로 교체, SCSS 빈 줄 정리 - isLoggedIn = true → !!session 으로 교체, 개발용 TODO 주석 제거 - HomeServiceInfo /privacy, /terms 실제 경로 연결 - page.module.scss 불필요 인라인 주석 제거 - HomeServiceInfo.module.scss .link/.copyright @include 뒤 빈 줄 추가 - NewCaseButton.module.scss @include 뒤 빈 줄, 주석/선언 그룹 간격 정리 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * refactor: 진술 제출 시 dispute 상태 동기화 및 판결 조건 수정 (#67) - 진술 제출(POST /statements) 후 dispute 상태를 WAITING_OPPONENT / BOTH_SUBMITTED로 자동 업데이트 - 1인 판결 가능 조건을 진술 건수 체크 → 상태값(WAITING_OPPONENT) 기준으로 변경 - AI 판결 실패 시 상태 롤백을 BOTH_SUBMITTED 하드코딩에서 previousStatus로 수정 - 판결받기 버튼에 canJudge 조건 추가 (waiting_opponent / both_submitted 상태에서만 활성화) Co-authored-by: Claude Sonnet 4.6 * feat(mypage): 마이페이지 UI/레이아웃 및 기능 구현 (#63) * fix(auth): signIn 콜백에서 UUID 형식 검증 추가 카카오 OAuth 최초 로그인 시 PrismaAdapter가 User를 생성하기 전에 signIn 콜백이 실행되면서 카카오 숫자 ID(길이 10)로 UUID 컬럼을 조회하여 Prisma 에러가 발생하던 문제 수정. - signIn 콜백에 UUID 형식 검증 추가하여 비-UUID ID는 스킵 - events.createUser에서 신규 사용자 커스텀 필드 설정 처리 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 OAuth linkAccount 시 미지원 필드 필터링 카카오 OAuth 토큰 응답에 포함된 refresh_token_expires_in 필드가 Account 스키마에 없어서 linkAccount 단계에서 Prisma 에러 발생. PrismaAdapter를 래핑하여 Account 스키마에 정의된 필드만 저장하도록 필터링. Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 버튼 및 약관 문구 수정 - 카카오 버튼 아이콘을 말풍선에서 TALK 아이콘으로 변경 - 버튼 배경색 #FFE812로 수정 - 약관 동의 문구를 서비스 가이드에 맞게 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 버튼 아이콘을 기본 말풍선으로 복원 Co-Authored-By: Claude Sonnet 4.6 * fix(auth): SessionProvider 추가 및 카카오 로그인 콜백 페이지 구현 SessionProvider가 앱 전역에 적용되지 않아 signIn() 호출과 콜백 후 세션 인식이 실패하던 문제를 수정한다. AuthProvider 래퍼 컴포넌트를 추가하고 layout.tsx에 적용한다. 카카오 OAuth 콜백 후 세션 상태를 확인하고 홈으로 리다이렉트하는 중간 페이지(/auth/callback)를 추가한다. middleware matcher에 해당 경로를 인증 체크 제외 대상으로 등록한다. Co-Authored-By: Claude Sonnet 4.6 * feat(mypage): 마이페이지 UI/레이아웃 및 기능 구현 마이페이지 화면 구성 및 메뉴 기능을 구현한다. - 마이페이지 프로필 카드 (아바타, 닉네임, MBTI 뱃지, 설정 링크) - 메뉴 리스트 7개 항목 라우팅 연결 - 로그아웃/회원탈퇴 확인 모달 (ConfirmModal 공통 컴포넌트) - Modal backdrop 블러 처리 및 스타일 개선 - 상점/고객문의 준비중 토스트 페이지 - 개인정보 수정/회원탈퇴/서비스 소개 빈 라우트 페이지 Co-Authored-By: Claude * fix(ui): Restore Modal border styles and use Spinner component in callback Restore border-radius and border declarations that were accidentally removed from Modal.module.scss. Replace the CSS-only spinner in the auth callback page with the shared Spinner component from src/components/ui, and remove the now-unused spinner CSS and keyframes. Co-Authored-By: Claude --------- Co-authored-by: Claude Sonnet 4.6 * feat: 홈 화면 개선 — DB 닉네임 인사말, 통계 API, 새 사건 버튼 연결 (#68) * feat: 홈 화면 기본 구조 생성 (헤더, 일기 박스) - 헤더: 세션 유저명 + character-welcome.png 부엉이 이미지 - 일기 박스: 365x88, border black-700 2px, bg primary-100 - TODO: GangwonEduPower 폰트 추가 후 헤더 로고 텍스트 적용 필요 Co-Authored-By: Claude Sonnet 4.6 * feat: Header variant 분리 (logo/title) 및 홈 화면 적용 - Header.tsx에 variant prop 추가 (logo | title) - logo: 좌측 상단 말해부엉 로고 표시 (66x19, h:56, padding: 16px 20px) - title: 기존 뒤로가기 + 페이지 제목 형태 유지 - Header.module.scss에 __logo 스타일 추가 - home/page.tsx에 Header variant='logo' 적용 - 헤더를 컨테이너 padding 밖으로 분리하여 상단 여백 제거 - home/page.module.scss diaryBox에 align-self: center 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 페이지 생성 및 로고 헤더 적용 (/records) Co-Authored-By: Claude Sonnet 4.6 * fix: diaryBox 고정 폭을 max-width + width 100%로 반응형 처리 - width: 365px → width: 100% + max-width: 365px - 작은 화면에서 좌우 패딩과 결합 시 오버플로우 방지 Co-Authored-By: Claude Sonnet 4.6 * feat: 감정일기 작성 버튼 /diary/new 네비게이션 연결 - 일기 박스 전체를 Link로 변경 (텍스트 + 버튼 모두 클릭 가능) - diaryBox에 text-decoration: none, cursor: pointer 추가 - /diary/new 경로는 임시 지정 (담당자 확인 후 수정 예정) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 캐릭터 이미지 교체 및 위치 조정 - character-welcome.png → character-home.png 교체 (169x138) - 캐릭터 절대 위치 적용 (top: 41px, right: -20px) - 캐릭터가 일기 박스 뒤에 위치하도록 z-index 조정 (character: 0, container: 1) Co-Authored-By: Claude Sonnet 4.6 * fix: 홈 화면 코드래빗 피드백 반영 - 캐릭터 이미지 가로 스크롤 방지: .page에 overflow-x: hidden 추가 - 비로그인 사용자 분기 처리: 말해부엉 알아보기 박스 추가 (/login 이동) Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 화면 typography 믹신 적용 - greetingText, diaryTitle, diarySubtitle에 typography 믹신 사용 - 개별 font 속성 직접 선언 → @include m.text-* 토큰으로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: 비로그인 알아보기 박스 위치 수정 - 인사/일기 박스는 로그인 여부 무관하게 항상 표시 - 말해부엉 알아보기 박스를 진행중인 사건 위치(구분선 아래)로 이동 - 비로그인 인사: '안녕하세요' 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면에 통계 섹션 및 구분선 통합 - StatsCategorySection, useStatistics, QueryProvider 병합 - 고민 카테고리 TOP4 통계 섹션 추가 - 통계 섹션 하단 구분선 추가 (h:8px, black-100, gap:42px) Co-Authored-By: Claude Sonnet 4.6 * chore: 개발 편의용 로그인 상태 강제 설정 (배포 전 제거 필요) - isLoggedIn = true 하드코딩으로 로그인 상태 유지 - TODO 주석으로 배포 전 제거 안내 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 진행중인 사건 섹션 UI 구현 - ActiveCasesSection 컴포넌트 추가 - 진행중인 사건 목록 표시 (waiting_opponent / opponent_joined / both_submitted) - CaseCard 공통 컴포넌트 재사용 - 좌측 카테고리 컬러 accent bar - 카드 간격 12px - useActiveCases 훅 추가 (mock 데이터, TODO: 실 API 연동) - CaseCard에 participants prop 추가 (AvatarGroup 렌더링) - CategoryIcon의 CATEGORY_COLOR_MAP export 추가 - 홈 페이지에 로그인 시 ActiveCasesSection 표시 - 구분선 ↔ 섹션 간격 20px 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 수정 - CaseCard 원본 구조 유지, 좌측 컬러바 제거, Avatar 좌측 배치 - CaseCard 원본 구조 완전 원복 (participants prop 제거, div 래퍼 제거) - CategoryIcon CATEGORY_COLOR_MAP export 원복 - 불필요한 좌측 카테고리 accent bar 제거 - Avatar absolute 오버레이 우측→좌측 하단 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard preview 텍스트 컬러 black-700으로 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 섹션 내 진행중 뱃지 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 푸터 레이아웃 및 외곽선 black-700 2px inset 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 preview-footer 간격 8px 조정 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드래빗 리뷰 반영 - 린트, loading/error 상태 처리, onClick li로 이동 Co-Authored-By: Claude Sonnet 4.6 * chore: 홈 화면 캐릭터 이미지 추가 Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 페이지를 /home에서 / 루트 경로로 이동 변경 이유: - src/app/page.tsx: 홈 화면 콘텐츠를 루트 경로(/)에서 서빙하도록 이동 → Next.js App Router에서 루트 경로는 src/app/page.tsx가 담당하므로 기존 (page)/home/page.tsx 대신 루트로 이동하는 것이 구조적으로 올바름 - src/app/page.module.scss: (page)/home/page.module.scss를 루트로 이동 → page.tsx와 동일 위치에서 관리하도록 이동 (git rename으로 추적됨) - src/app/(page)/home/page.tsx: redirect('/')로 교체 → 기존 /home URL 접근 시 /로 리다이렉트하여 북마크/공유 링크 호환성 유지 - src/app/(page)/login/page.tsx: callbackUrl '/home' → '/' → 로그인 성공 후 이동 경로를 변경된 홈 경로(/)에 맞게 수정 - src/components/layout/BottomNavigation.tsx: href '/home' → '/' → 하단 탭 홈 버튼이 올바른 경로를 가리키도록 수정 → pathname.startsWith('/') 는 모든 경로에서 true이므로 홈 탭 활성 조건을 pathname === '/' 로 변경하여 활성 상태 오류 수정 - src/components/home/StatsCategorySection.module.scss: width 100%로 변경 → 고정 픽셀(346px) 대신 width: 100%로 반응형 처리 - src/middleware.ts: 개발 환경 인증 bypass 추가 → PR #50 카카오 로그인 병합 후 next-auth/middleware가 모든 경로를 차단하게 됨 → 개발 편의를 위해 NODE_ENV === development 일 때 인증 없이 접근 허용 → 배포 전 반드시 제거 필요 (TODO 주석 명시) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 새 사건 버튼 및 서비스 정보 푸터 구현 - NewCaseButton: 홈 화면 우측 하단 고정 플로팅 버튼 추가 (w115 h48, color/black-700, border-radius 100, text-title-s) 새 사건 작성 페이지 생성 후 href 연결 필요 (TODO 주석) - HomeServiceInfo: 서비스 정보 박스 구현 (로고 w66 h19, 서비스 소개/개인정보처리방침/이용약관/고객문의 링크, Copyright 텍스트, 전체 너비 반응형, 탭바 뒤에 위치) - BottomNavigation: 홈 페이지에 탭바 추가, z-index 100 유지 (서비스 정보 박스보다 앞에 렌더링) - page.tsx: NewCaseButton, HomeServiceInfo, BottomNavigation 렌더링 추가 - page.module.scss: container padding-bottom 60px, serviceInfoWrapper 스타일 Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 카테고리 선택 모달 구현 - 새 사건 + 버튼 클릭 시 카테고리 선택 모달 표시 - 모달 오버레이: color-black-700 40% 틴트 + bg-page 불투명 베이스 (배경 콘텐츠가 비치지 않도록 레이어드 배경 처리) - 카테고리 박스: w133 h176, 흰 배경, 4개 카테고리 항목 가운데 정렬 (CategoryIcon 공통 컴포넌트 사용, 연인관계/직장관계/친구관계/가족관계) (텍스트: text-body-m, text/primary, 아이콘과 9px 간격) - X 닫기 버튼: 48x48 흰 원형, CloseIcon 24x24 - 모달 오픈 시 body overflow hidden으로 스크롤 잠금 - 카테고리 href: '#' 임시 처리 (새 사건 작성 페이지 생성 후 교체 필요) Co-Authored-By: Claude Sonnet 4.6 * fix: CodeRabbit 리뷰 반영 — isLoggedIn 하드코딩 제거, 서비스 링크 경로 교체, SCSS 빈 줄 정리 - isLoggedIn = true → !!session 으로 교체, 개발용 TODO 주석 제거 - HomeServiceInfo /privacy, /terms 실제 경로 연결 - page.module.scss 불필요 인라인 주석 제거 - HomeServiceInfo.module.scss .link/.copyright @include 뒤 빈 줄 추가 - NewCaseButton.module.scss @include 뒤 빈 줄, 주석/선언 그룹 간격 정리 Co-Authored-By: Claude Sonnet 4.6 * feat: HomeGreeting 컴포넌트 추가 및 DB 닉네임 기반 인사말 적용 - useUserMe 훅 추가 (/api/user/me 호출, TanStack Query) - HomeGreeting 클라이언트 컴포넌트 추가 (DB 닉네임 기반 인사말) - page.tsx에서 session.user.name 제거, HomeGreeting으로 교체 Co-Authored-By: Claude Sonnet 4.6 * feat: 통계 데이터 없을 때 목 데이터 fallback 추가 (UI 확인용) 실제 판결 데이터 쌓이면 자동으로 실제 데이터로 전환됨. TODO: 실제 데이터 쌓이면 MOCK_ITEMS 및 fallback 로직 제거 Co-Authored-By: Claude Sonnet 4.6 * chore: 진행중인 사건 목 데이터 제거 실 API 미연동 상태로 빈 배열 반환 처리. API 연동 시 fetchActiveCases 주석 해제 후 교체 필요. Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 카테고리 클릭 시 진술 작성 페이지로 이동 선택한 카테고리를 ?category= 쿼리 파라미터로 전달. /disputes/test/statement?category={category}로 임시 연결. Co-Authored-By: Claude Sonnet 4.6 * fix: 서비스 소개·고객문의 링크 미연결 항목 span으로 교체 href 없는 항목은 a 태그 대신 span(aria-disabled)으로 렌더링. Co-Authored-By: Claude Sonnet 4.6 * style: NewCaseButton SCSS declaration-empty-line-before 위반 수정 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 사건기록 페이지 구현 (#65) * feat: 사건기록 페이지 구현 - /records 페이지 생성: 진행완료(judged/closed) 사건 목록 표시 - RecordListSection 컴포넌트 구현: 카테고리 필터 + 사건 카드 리스트 - 사건 카드에 Avatar(프로필) + 날짜 + 진행완료 배지 외부 footer 구조 적용 - CaseCard: disputeStatus 기반 footer 렌더링 추가 (card__footer 스타일 포함) - StatusBadge: DisputeStatus 타입 export 추가 - src/app/(page)/home 폴더 제거: 홈은 src/app/page.tsx 단일 진입점으로 정리 - join/page.tsx: 메인 이동 경로 /home → / 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: CodeRabbit PR65 리뷰 반영 - records/page.tsx: 비로그인 redirect 가드 복구 - RecordListSection: div role=button → Link 교체로 키보드 접근성 개선 - RecordListSection: formatDate slice(2) → slice(2,10) 날짜 포맷 수정 - CaseCard: 미사용 status prop 제거 - RecordList: status prop 전달 제거 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 감정일기 상세 페이지 ui 구현 (#64) * feat : 다이어리 (감정일기 , 사건기록)탭분리 * feat : 달력 ui 커스텀 추가 및 감정일기 사건기록 분기처리 * refactor: 및 캘린더 페이지구조 개선 (리뷰 피드백 반영) * feat : 감정일기카드 컴포넌트 구현 * fix: build 에러 ( 임시 페이지 ) * refactor: 감정일기 컴포넌트 SCSS 모듈 적용 및 믹스인 토큰 사용 * feat: 달력 페이지 UI 구현 및 스타일 정리 - MUI DateCalendar 커스텀 - 감정일기 / 사건기록 탭 전환 구조 구현 - EmotionDiaryList, RecordList 빈 상태 UI 추가 - DiaryCard mixin 적용 (text-title-s, text-body-s, text-label-s) - 인라인 style 제거 → SCSS 모듈로 분리 - outsideCurrentMonth 감정 아이콘 노출 차단 - 새 일기 FAB 버튼 추가 (감정일기 탭 전용) - 불필요한 파일 삭제 (DiaryMode, EmotionDiaryCard 등) * style : EmotionDiaryList.moulde 스타일 수정 * feat: 달력 RecordList에 CaseCard 연동 및 스타일 개선 * feat: 감정일기 상세 페이지 ui 구현 * refactor(LSG): 타입 분리 및 import 절대경로 통일, Type 폴더 분리 * fix : schema.prisma 변동으로 인한 Group 정보삭제 --------- Co-authored-by: 배근영 * feat: AI 판결 스키마 분리 및 판결 로직 구현 (#70) * feat(judgment): AI 판결 스키마 분리 및 판결 로직 구현 - AiJudgment 스키마: reasoning/advice → aFault/bFault/aSuggestedLine/bSuggestedLine 분리 - prisma generate 반영 및 seed.ts 필드 업데이트 - src/lib/ai/judgment.ts: extractDisputeMeta(Step1), generateAiJudgment(Step2) 구현 - judge route: TODO 제거 후 실제 AI 판결 로직 연결 (DB 갈등유형 조회 → AI 호출 → AiJudgment 저장) - judgment.mapper.ts / types/judgment.ts: 새 필드 반영 Co-Authored-By: Claude Sonnet 4.6 * feat(dispute): 진술 제출 API 및 도메인 훅 추가 - POST /api/disputes/[id]/statements/submit: 진술 최종 제출 (멱등성 보장) - GET /api/users/me: 경로 스펙 수정 (/api/user/me → /api/users/me) - StatementSubmitResponse 타입 추가 (src/types/dispute.ts) - dispute.api.ts: fetchDispute, saveStatement, submitStatement, requestJudgment - dispute.hooks.ts: useDispute, useSaveStatement, useSubmitStatement, useRequestJudgment Co-Authored-By: Claude Sonnet 4.6 * refactor(dispute-page): TanStack Query 전환 및 Toast 전역 연결 - page.tsx: useEffect+raw fetch → useDispute/useRequestJudgment 훅으로 교체 - runJudge onError에 useToastStore.show 연결 - layout.tsx: 전역 마운트 추가 Co-Authored-By: Claude Sonnet 4.6 * feat(statements): 진술저장 로직 개선 및 AI Step1 연결 - statements/route.ts: 수정 허용 (CONFLICT 체크 제거, 조건부 상태 전이) - 최초 저장 시에만 DRAFT→WAITING_OPPONENT / OPPONENT_JOINED→BOTH_SUBMITTED 전이 - 욕설 필터링 통과 후 extractDisputeMeta 비동기 호출 → dispute.title/description 업데이트 - StatementConflictError 제거 - statements/submit/route.ts: ROLE_B 제출 시 OPPONENT_JOINED 상태 검증 추가 - lib/ai/judgment.ts: categoryGroup 한글 매핑(ROMANCE→연애 등) AI 프롬프트 적용 - judge/route.ts: cardTitle을 dispute.title로 교체 (summary.slice 제거) Co-Authored-By: Claude Sonnet 4.6 * fix: isSolo 판별 강화 및 API 응답 파싱 안전성 개선 - judgment.ts: isSolo 판별에 빈 문자열 케이스 추가 (statementB.trim() === '') - dispute.api.ts: res.json() 직접 호출 제거, parseJson 헬퍼로 교체 - 비JSON/빈 본문 응답에서 SyntaxError 대신 일관된 에러 메시지 반환 - submit/route.ts: 삭제·종료·판결 완료 상태 선검증 추가 (DELETED/CLOSED/EXPIRED/JUDGED/JUDGING → 409) Co-Authored-By: Claude Sonnet 4.6 * fix(statements): ROLE_A 최초 저장 시에만 extractDisputeMeta 호출 --------- Co-authored-by: Claude Sonnet 4.6 * fix: seed ConflictTypeGroup 추가 및 판결 매퍼 타입 오류 수정 (#75) * fix: seed ConflictTypeGroup 추가 및 판결 매퍼 타입 오류 수정 - seed.ts: ConflictTypeGroup 3개 생성 후 ConflictTypeDetail groupId 연결 - judgment.mapper.ts: resultConflictGroup 미포함 필드 참조 제거, cardImageUrl 제거 - judgment.ts: ConflictTypeDetailDto에서 cardImageUrl 필드 제거 (schema 불일치) Co-Authored-By: Claude Sonnet 4.6 * fix: DB schema 동기화 및 ConflictTypeGroup 제거 - prisma db pull로 최신 schema 반영 (ConflictTypeGroup 테이블 제거됨) - seed.ts: ConflictTypeGroup 섹션 제거, ConflictTypeDetail groupId 제거, AiJudgment에 reasoning/advice 추가 - judge/route.ts: groupId select 제거, resultConflictGroupId 제거, reasoning/advice 필드 추가 - judgment.mapper.ts: resultConflictGroup 참조 제거 - judgment.ts: ConflictTypeDetailDto cardImageUrl 필드 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: DB schema 재동기화 — reasoning/advice 필드 제거 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 마이페이지 개인정보 수정 페이지 구현 (#71) * @ feat(user): 마이페이지 프로필 편집 및 이미지 업로드 구현 - 마이페이지 편집 페이지 UI 및 프로필 수정 로직 구현 - 프로필 이미지 업로드 API (Supabase Storage 연동) - user/me API에 PATCH 메서드 추가 (닉네임, MBTI 수정) - user 도메인 API client, hooks, constants 구성 - auth constants 및 lib/storage 유틸 추가 - API 명세서 업데이트 - dev 최신 반영 (사건기록, 홈 화면 개선) Co-Authored-By: Claude @ * fix(user): 닉네임 검증 상한을 DB 기준 100자로 변경 nickname 컬럼이 VarChar(100)이므로 검증 상한을 20자에서 100자로 수정. 서버 검증(route.ts)과 클라이언트 검증(edit page) 모두 반영. Co-Authored-By: Claude * fix(user): PR #71 리뷰 반영 — 보안·안정성 개선 - Stylelint declaration-empty-line-before 규칙 위반 해소 - 프로필 이미지 업로드 시 매직 바이트 검증 추가 - 스토리지 업로드 후 DB 실패 시 보상 삭제 처리 - PATCH 요청 JSON 파싱 실패 시 400 응답 분기 - PATCH 사용자 미존재 시 404 응답 추가 - 약관 동의 createMany에 skipDuplicates 적용 - UserTermsAgreement 모델에 unique 제약 추가 Co-Authored-By: Claude * ref(user): 프로필 편집 폼 상태 관리를 useState에서 Zustand로 변경 - src/stores/profileEditStore.ts 신규 생성 - page.tsx에서 useState 5개를 Zustand store로 이관 - setFieldError/clearFieldError 액션으로 에러 처리 단순화 Co-Authored-By: Claude * fix(user): 프로필 편집 에러 분기·SVG 허용·인라인 스타일 제거 - isError와 !user 에러 메시지 분리 - 프로필 이미지 accept에 SVG 추가 (프론트/백엔드 동시 적용) - errors.general 인라인 스타일을 SCSS Module 클래스로 이관 Co-Authored-By: Claude * ref(user): PATCH /api/user/me에 프로필 이미지 업로드 통합 - PATCH를 multipart/form-data 기반으로 변경 - 텍스트 필드(email, nickname, mbti) + 이미지 파일을 한 번에 처리 - Supabase Storage 업로드 로직을 PATCH에 통합 - 별도 profile-image 엔드포인트 삭제 - 프론트 hooks에서 useUploadProfileImage 제거, 단일 호출로 단순화 Co-Authored-By: Claude --------- Co-authored-by: Claude * fix: Prisma schema 중복 UserTermsAgreement 모델 제거 (#77) * @ feat(user): 마이페이지 프로필 편집 및 이미지 업로드 구현 - 마이페이지 편집 페이지 UI 및 프로필 수정 로직 구현 - 프로필 이미지 업로드 API (Supabase Storage 연동) - user/me API에 PATCH 메서드 추가 (닉네임, MBTI 수정) - user 도메인 API client, hooks, constants 구성 - auth constants 및 lib/storage 유틸 추가 - API 명세서 업데이트 - dev 최신 반영 (사건기록, 홈 화면 개선) Co-Authored-By: Claude @ * fix(user): 닉네임 검증 상한을 DB 기준 100자로 변경 nickname 컬럼이 VarChar(100)이므로 검증 상한을 20자에서 100자로 수정. 서버 검증(route.ts)과 클라이언트 검증(edit page) 모두 반영. Co-Authored-By: Claude * fix(user): PR #71 리뷰 반영 — 보안·안정성 개선 - Stylelint declaration-empty-line-before 규칙 위반 해소 - 프로필 이미지 업로드 시 매직 바이트 검증 추가 - 스토리지 업로드 후 DB 실패 시 보상 삭제 처리 - PATCH 요청 JSON 파싱 실패 시 400 응답 분기 - PATCH 사용자 미존재 시 404 응답 추가 - 약관 동의 createMany에 skipDuplicates 적용 - UserTermsAgreement 모델에 unique 제약 추가 Co-Authored-By: Claude * ref(user): 프로필 편집 폼 상태 관리를 useState에서 Zustand로 변경 - src/stores/profileEditStore.ts 신규 생성 - page.tsx에서 useState 5개를 Zustand store로 이관 - setFieldError/clearFieldError 액션으로 에러 처리 단순화 Co-Authored-By: Claude * fix(user): 프로필 편집 에러 분기·SVG 허용·인라인 스타일 제거 - isError와 !user 에러 메시지 분리 - 프로필 이미지 accept에 SVG 추가 (프론트/백엔드 동시 적용) - errors.general 인라인 스타일을 SCSS Module 클래스로 이관 Co-Authored-By: Claude * ref(user): PATCH /api/user/me에 프로필 이미지 업로드 통합 - PATCH를 multipart/form-data 기반으로 변경 - 텍스트 필드(email, nickname, mbti) + 이미지 파일을 한 번에 처리 - Supabase Storage 업로드 로직을 PATCH에 통합 - 별도 profile-image 엔드포인트 삭제 - 프론트 hooks에서 useUploadProfileImage 제거, 단일 호출로 단순화 Co-Authored-By: Claude * fix(prisma): 중복 UserTermsAgreement 모델 선언 제거 merge 충돌 해결 과정에서 UserTermsAgreement 모델이 중복 삽입되고 닫는 괄호가 누락되어 Prisma validation 에러 발생. 675~691행의 중복 블록을 제거하고 68행의 정상 선언만 유지. Co-Authored-By: Claude --------- Co-authored-by: Claude * fix(prisma): 중복 UserTermsAgreement 모델 제거 및 SCSS mixin 수정 (#78) - prisma/schema.prisma: 중복 UserTermsAgreement 모델 블록 삭제 (68행 정상 선언 유지) - page.module.scss: 존재하지 않는 text-body2 mixin을 text-body-s로 수정 Co-authored-by: Claude * feat: 새 사건 버튼 — POST /api/rooms 연결 및 roomId 전달 (#73) * feat: 홈 화면 기본 구조 생성 (헤더, 일기 박스) - 헤더: 세션 유저명 + character-welcome.png 부엉이 이미지 - 일기 박스: 365x88, border black-700 2px, bg primary-100 - TODO: GangwonEduPower 폰트 추가 후 헤더 로고 텍스트 적용 필요 Co-Authored-By: Claude Sonnet 4.6 * feat: Header variant 분리 (logo/title) 및 홈 화면 적용 - Header.tsx에 variant prop 추가 (logo | title) - logo: 좌측 상단 말해부엉 로고 표시 (66x19, h:56, padding: 16px 20px) - title: 기존 뒤로가기 + 페이지 제목 형태 유지 - Header.module.scss에 __logo 스타일 추가 - home/page.tsx에 Header variant='logo' 적용 - 헤더를 컨테이너 padding 밖으로 분리하여 상단 여백 제거 - home/page.module.scss diaryBox에 align-self: center 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 페이지 생성 및 로고 헤더 적용 (/records) Co-Authored-By: Claude Sonnet 4.6 * fix: diaryBox 고정 폭을 max-width + width 100%로 반응형 처리 - width: 365px → width: 100% + max-width: 365px - 작은 화면에서 좌우 패딩과 결합 시 오버플로우 방지 Co-Authored-By: Claude Sonnet 4.6 * feat: 감정일기 작성 버튼 /diary/new 네비게이션 연결 - 일기 박스 전체를 Link로 변경 (텍스트 + 버튼 모두 클릭 가능) - diaryBox에 text-decoration: none, cursor: pointer 추가 - /diary/new 경로는 임시 지정 (담당자 확인 후 수정 예정) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 캐릭터 이미지 교체 및 위치 조정 - character-welcome.png → character-home.png 교체 (169x138) - 캐릭터 절대 위치 적용 (top: 41px, right: -20px) - 캐릭터가 일기 박스 뒤에 위치하도록 z-index 조정 (character: 0, container: 1) Co-Authored-By: Claude Sonnet 4.6 * fix: 홈 화면 코드래빗 피드백 반영 - 캐릭터 이미지 가로 스크롤 방지: .page에 overflow-x: hidden 추가 - 비로그인 사용자 분기 처리: 말해부엉 알아보기 박스 추가 (/login 이동) Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 화면 typography 믹신 적용 - greetingText, diaryTitle, diarySubtitle에 typography 믹신 사용 - 개별 font 속성 직접 선언 → @include m.text-* 토큰으로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: 비로그인 알아보기 박스 위치 수정 - 인사/일기 박스는 로그인 여부 무관하게 항상 표시 - 말해부엉 알아보기 박스를 진행중인 사건 위치(구분선 아래)로 이동 - 비로그인 인사: '안녕하세요' 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면에 통계 섹션 및 구분선 통합 - StatsCategorySection, useStatistics, QueryProvider 병합 - 고민 카테고리 TOP4 통계 섹션 추가 - 통계 섹션 하단 구분선 추가 (h:8px, black-100, gap:42px) Co-Authored-By: Claude Sonnet 4.6 * chore: 개발 편의용 로그인 상태 강제 설정 (배포 전 제거 필요) - isLoggedIn = true 하드코딩으로 로그인 상태 유지 - TODO 주석으로 배포 전 제거 안내 표시 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 진행중인 사건 섹션 UI 구현 - ActiveCasesSection 컴포넌트 추가 - 진행중인 사건 목록 표시 (waiting_opponent / opponent_joined / both_submitted) - CaseCard 공통 컴포넌트 재사용 - 좌측 카테고리 컬러 accent bar - 카드 간격 12px - useActiveCases 훅 추가 (mock 데이터, TODO: 실 API 연동) - CaseCard에 participants prop 추가 (AvatarGroup 렌더링) - CategoryIcon의 CATEGORY_COLOR_MAP export 추가 - 홈 페이지에 로그인 시 ActiveCasesSection 표시 - 구분선 ↔ 섹션 간격 20px 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 수정 - CaseCard 원본 구조 유지, 좌측 컬러바 제거, Avatar 좌측 배치 - CaseCard 원본 구조 완전 원복 (participants prop 제거, div 래퍼 제거) - CategoryIcon CATEGORY_COLOR_MAP export 원복 - 불필요한 좌측 카테고리 accent bar 제거 - Avatar absolute 오버레이 우측→좌측 하단 변경 Co-Authored-By: Claude Sonnet 4.6 * fix: CaseCard preview 텍스트 컬러 black-700으로 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 섹션 내 진행중 뱃지 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 푸터 레이아웃 및 외곽선 black-700 2px inset 적용 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 카드 preview-footer 간격 8px 조정 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드래빗 리뷰 반영 - 린트, loading/error 상태 처리, onClick li로 이동 Co-Authored-By: Claude Sonnet 4.6 * chore: 홈 화면 캐릭터 이미지 추가 Co-Authored-By: Claude Sonnet 4.6 * refactor: 홈 페이지를 /home에서 / 루트 경로로 이동 변경 이유: - src/app/page.tsx: 홈 화면 콘텐츠를 루트 경로(/)에서 서빙하도록 이동 → Next.js App Router에서 루트 경로는 src/app/page.tsx가 담당하므로 기존 (page)/home/page.tsx 대신 루트로 이동하는 것이 구조적으로 올바름 - src/app/page.module.scss: (page)/home/page.module.scss를 루트로 이동 → page.tsx와 동일 위치에서 관리하도록 이동 (git rename으로 추적됨) - src/app/(page)/home/page.tsx: redirect('/')로 교체 → 기존 /home URL 접근 시 /로 리다이렉트하여 북마크/공유 링크 호환성 유지 - src/app/(page)/login/page.tsx: callbackUrl '/home' → '/' → 로그인 성공 후 이동 경로를 변경된 홈 경로(/)에 맞게 수정 - src/components/layout/BottomNavigation.tsx: href '/home' → '/' → 하단 탭 홈 버튼이 올바른 경로를 가리키도록 수정 → pathname.startsWith('/') 는 모든 경로에서 true이므로 홈 탭 활성 조건을 pathname === '/' 로 변경하여 활성 상태 오류 수정 - src/components/home/StatsCategorySection.module.scss: width 100%로 변경 → 고정 픽셀(346px) 대신 width: 100%로 반응형 처리 - src/middleware.ts: 개발 환경 인증 bypass 추가 → PR #50 카카오 로그인 병합 후 next-auth/middleware가 모든 경로를 차단하게 됨 → 개발 편의를 위해 NODE_ENV === development 일 때 인증 없이 접근 허용 → 배포 전 반드시 제거 필요 (TODO 주석 명시) Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 화면 새 사건 버튼 및 서비스 정보 푸터 구현 - NewCaseButton: 홈 화면 우측 하단 고정 플로팅 버튼 추가 (w115 h48, color/black-700, border-radius 100, text-title-s) 새 사건 작성 페이지 생성 후 href 연결 필요 (TODO 주석) - HomeServiceInfo: 서비스 정보 박스 구현 (로고 w66 h19, 서비스 소개/개인정보처리방침/이용약관/고객문의 링크, Copyright 텍스트, 전체 너비 반응형, 탭바 뒤에 위치) - BottomNavigation: 홈 페이지에 탭바 추가, z-index 100 유지 (서비스 정보 박스보다 앞에 렌더링) - page.tsx: NewCaseButton, HomeServiceInfo, BottomNavigation 렌더링 추가 - page.module.scss: container padding-bottom 60px, serviceInfoWrapper 스타일 Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 카테고리 선택 모달 구현 - 새 사건 + 버튼 클릭 시 카테고리 선택 모달 표시 - 모달 오버레이: color-black-700 40% 틴트 + bg-page 불투명 베이스 (배경 콘텐츠가 비치지 않도록 레이어드 배경 처리) - 카테고리 박스: w133 h176, 흰 배경, 4개 카테고리 항목 가운데 정렬 (CategoryIcon 공통 컴포넌트 사용, 연인관계/직장관계/친구관계/가족관계) (텍스트: text-body-m, text/primary, 아이콘과 9px 간격) - X 닫기 버튼: 48x48 흰 원형, CloseIcon 24x24 - 모달 오픈 시 body overflow hidden으로 스크롤 잠금 - 카테고리 href: '#' 임시 처리 (새 사건 작성 페이지 생성 후 교체 필요) Co-Authored-By: Claude Sonnet 4.6 * fix: CodeRabbit 리뷰 반영 — isLoggedIn 하드코딩 제거, 서비스 링크 경로 교체, SCSS 빈 줄 정리 - isLoggedIn = true → !!session 으로 교체, 개발용 TODO 주석 제거 - HomeServiceInfo /privacy, /terms 실제 경로 연결 - page.module.scss 불필요 인라인 주석 제거 - HomeServiceInfo.module.scss .link/.copyright @include 뒤 빈 줄 추가 - NewCaseButton.module.scss @include 뒤 빈 줄, 주석/선언 그룹 간격 정리 Co-Authored-By: Claude Sonnet 4.6 * feat: HomeGreeting 컴포넌트 추가 및 DB 닉네임 기반 인사말 적용 - useUserMe 훅 추가 (/api/user/me 호출, TanStack Query) - HomeGreeting 클라이언트 컴포넌트 추가 (DB 닉네임 기반 인사말) - page.tsx에서 session.user.name 제거, HomeGreeting으로 교체 Co-Authored-By: Claude Sonnet 4.6 * feat: 통계 데이터 없을 때 목 데이터 fallback 추가 (UI 확인용) 실제 판결 데이터 쌓이면 자동으로 실제 데이터로 전환됨. TODO: 실제 데이터 쌓이면 MOCK_ITEMS 및 fallback 로직 제거 Co-Authored-By: Claude Sonnet 4.6 * chore: 진행중인 사건 목 데이터 제거 실 API 미연동 상태로 빈 배열 반환 처리. API 연동 시 fetchActiveCases 주석 해제 후 교체 필요. Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 카테고리 클릭 시 진술 작성 페이지로 이동 선택한 카테고리를 ?category= 쿼리 파라미터로 전달. /disputes/test/statement?category={category}로 임시 연결. Co-Authored-By: Claude Sonnet 4.6 * fix: 서비스 소개·고객문의 링크 미연결 항목 span으로 교체 href 없는 항목은 a 태그 대신 span(aria-disabled)으로 렌더링. Co-Authored-By: Claude Sonnet 4.6 * style: NewCaseButton SCSS declaration-empty-line-before 위반 수정 Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 카테고리 클릭 시 POST /api/rooms 호출 후 statement 이동 Co-Authored-By: Claude Sonnet 4.6 * feat: 새 사건 버튼 — POST /api/rooms 후 roomId+category를 statement 페이지로 전달 Co-Authored-By: Claude Sonnet 4.6 * fix: 새 사건 버튼 중복 클릭 방지 및 5초 타임아웃 추가 - isCreating 상태로 in-flight 중 재진입 차단 및 버튼 비활성화 - AbortController 5초 타임아웃으로 네트워크 지연 시 fallback 보장 Co-Authored-By: Claude Sonnet 4.6 * feat: 진행중인 사건 없을 때 캐릭터 이미지 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: 진행중인 사건 빈 상태 이미지 Next.js Image → img 태그로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: PR73 CodeRabbit 피드백 반영 - NewCaseButton: catch fallback 이동 제거 → 에러 메시지 표시로 교체 - NewCaseButton: 성공 시 URL /disputes/new/ → /disputes/[roomId]/ 수정 - ActiveCasesSection: → Next.js priority 적용 - ActiveCasesSection: 장식용 이미지 alt='' 설정 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 초대 링크 발급·참여 API 구현 및 프론트 연결 (#69) * feat: 초대 링크 발급·참여·만료 처리 API 구현 - POST /api/rooms/:id/invite — 초대 링크 발급, room_mode → invite_ready - POST /api/rooms/:id/join — 초대 참여, role_a/b 확정, dispute 생성, room_mode → one_to_one - POST /api/cron/expire-invitations — 만료된 초대 링크 일괄 처리 - src/lib/invite.ts — 토큰 생성/해싱/만료 유틸 Co-Authored-By: Claude Sonnet 4.6 * feat: AuditLog·RoomAccessLog 기록 추가 초대 링크 발급 및 참여 API에 누락된 로그 기록을 추가한다. - invite API: 발급 성공 시 AuditLog(INVITE_LINK_CREATED) 기록 - join API: 참여 성공 시 AuditLog(USER_JOINED_ROOM) + RoomAccessLog(ALLOWED) 기록 - join API: 각 실패 케이스(invalid_token, room_unavailable, invite_expired, self_join, role_b_exists)에 RoomAccessLog(DENIED) 기록 - 로그 실패가 API 응답에 영향 없도록 .catch(() => {}) 처리 Co-Authored-By: Claude * refactor: join API를 토큰 기반 경로로 변경 및 GET 엔드포인트 추가 roomId 경로 파라미터 방식에서 token 경로 파라미터 방식으로 변경한다. 상대방은 초대 링크의 token만 알고 roomId를 알 수 없어 기존 구조로는 API 호출이 불가능했다. - POST /api/rooms/:id/join 삭제 - GET /api/rooms/join/:token 추가 (참여 확인 화면용 방 정보 조회) - POST /api/rooms/join/:token 추가 (참여 확정) - 초대 링크 형식 변경: /join?token=xxx → /join/xxx Co-Authored-By: Claude * feat: join 페이지 API 연동 및 초대 흐름 프론트 연결 - join 페이지를 /join/[token] 경로로 변경 및 API 연동 - 진입 시 GET /api/rooms/join/:token 호출로 방 정보 조회 - 참여 확정 시 POST /api/rooms/join/:token 호출 후 진술 페이지 이동 - GET 응답에 inviterNickname 추가 - disputes 페이지 초대 모달 InviteChoiceModal 컴포넌트로 교체 - 상대방 초대 클릭 시 invite API 연결 및 링크 클립보드 복사 토스트 - Toast 컴포넌트 전역 layout에 마운트 Co-Authored-By: Claude * fix(invite): PR 리뷰 반영 - 초대 참여 흐름 개선 - 비로그인 상태로 초대 링크 접근 시 모달 노출 후 로그인 페이지 이동 - isInviteExpired 유틸 제거, 만료 체크를 route 인라인으로 이동 - 에러코드 INVALID_STATUS → INVITE_EXPIRED / ROOM_UNAVAILABLE 로 분리 - 프론트 메시지 문자열 파싱 → 에러코드 기반 상태 분기로 교체 Co-Authored-By: Claude * fix(invite): res.json() 중복 호출 제거 POST 응답 파싱 후 동일 응답에 res.json()을 재호출하여 body stream already read 오류 발생하는 버그 수정 Co-Authored-By: Claude * fix(prisma): dev 기준 스키마 동기화 - UserTermsAgreement 중복 제거 Co-Authored-By: Claude * fix(mypage): 존재하지 않는 text-body2 믹스인을 text-body-s로 수정 Co-Authored-By: Claude * fix(prisma): AuditLog 모델 복구 Co-Authored-By: Claude --------- Co-authored-by: Claude Sonnet 4.6 * feat(auth): 카카오 로그인 시 약관 동의 레코드 저장 구현 (#72) * feat(auth): 카카오 로그인 시 약관 동의 레코드 저장 및 기존 유저 backfill 스크립트 추가 - 로그인 시 user_terms_agreements 테이블에 service, privacy 약관 동의 레코드 자동 생성 - saveFirstLoginFields에서 $transaction으로 유저 업데이트와 약관 동의 레코드 생성을 원자적 처리 - 약관 버전 상수 정의 (날짜 기반: 2026-06-18) - 기존 유저 대상 backfill 스크립트 추가 (scripts/backfill-user-terms-agreements.ts) Co-Authored-By: Claude Sonnet 4.6 * refactor: /api/user/me → /api/users/me 경로 변경 - API 라우트 디렉토리 이동 (src/app/api/user/me → src/app/api/users/me) - domains/user/hooks.ts 내 API 호출 경로 일괄 수정 Co-Authored-By: Claude Sonnet 4.6 * ref(user): Extract shared user types to src/types/user.ts Move UserMeDto, PatchUserBody, and VALID_MBTI from route handler into a shared type file for reuse across API and client code. Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 사건조회 페이지 분기 UI 및 AI 판결 프롬프트 개선 (#79) * feat: 사건조회 페이지 분기 UI 및 AI 판결 프롬프트 개선 - 초대 배너 추가 (isSolo && !isCompleted 조건) - 푸터 사건종료 + 판결받기 두 버튼으로 변경 - 판결 완료 후 진술/판결 탭 표시 분기 처리 - Solo/Duo 판결 프롬프트 객관성 강화 Co-Authored-By: Claude Sonnet 4.6 * fix: statement 페이지 isLoading 중복 선언 제거 및 useSaveStatement hook으로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: toStatementDto에 hasPersonalInfo 필드 누락 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: hasPersonalInfo 타입 분리 — DisputeStatementDto에서 제거, SaveStatementResponse로 분리 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix: 진술 저장 API 에러 메시지 노출 (#80) * fix: 진술 저장 API 에러 메시지 그대로 노출 Co-Authored-By: Claude Sonnet 4.6 * fix: signIn 콜백 UUID 체크 제거 — PrismaAdapter가 user.id를 DB UUID로 보장 Co-Authored-By: Claude Sonnet 4.6 * fix: res.json() 타입 명시 Co-Authored-By: Claude Sonnet 4.6 * fix: statement 페이지 rebase 충돌 정리 — dev 버전 기준으로 복원 Co-Authored-By: Claude Sonnet 4.6 * revert: UUID_REGEX 체크 복구 Co-Authored-By: Claude Sonnet 4.6 * fix: 새 사건 생성 시 dispute 및 참여자 등록 누락 수정 - POST /api/rooms 후 POST /api/disputes 호출하도록 변경 - dispute_participants에 유저 등록 보장 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix(auth): 카카오 로그인 시 kakao_id 중복 유니크 제약 위반 해결 (#82) * chore: update claude settings.json Co-Authored-By: Claude Sonnet 4.6 * chore: update claude settings.json Co-Authored-By: Claude Sonnet 4.6 * @ feat(user): 마이페이지 프로필 편집 및 이미지 업로드 구현 - 마이페이지 편집 페이지 UI 및 프로필 수정 로직 구현 - 프로필 이미지 업로드 API (Supabase Storage 연동) - user/me API에 PATCH 메서드 추가 (닉네임, MBTI 수정) - user 도메인 API client, hooks, constants 구성 - auth constants 및 lib/storage 유틸 추가 - API 명세서 업데이트 - dev 최신 반영 (사건기록, 홈 화면 개선) Co-Authored-By: Claude @ * fix(auth): 카카오 로그인 시 kakao_id 중복 유니크 제약 위반 해결 동일 카카오 계정으로 user 레코드가 중복 생성된 경우, 기존 유저의 kakao_id를 null로 정리 후 현재 유저에 저장하도록 수정 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix: 홈 진행중인 사건 API 연동 및 UI 수정 (#83) * fix: DisputeParticipantDto에 nickname 필드 추가 * fix: 홈 일기 박스 max-width 제거로 너비 100% 적용 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 진행중인 사건 API 연동 - GET /api/disputes에 active=true 파라미터 추가 → 4개 진행중 상태 필터링 - toParticipantDto에 nickname: null 추가로 타입 불일치 해소 - useActiveCases 실제 fetch 함수 활성화 및 DTO → ActiveCase 변환 구현 Co-Authored-By: Claude Sonnet 4.6 * fix: 사건 생성 AbortController 타임아웃 5초 → 30초로 증가 Co-Authored-By: Claude Sonnet 4.6 * fix: disputes/[id]/route.ts toParticipantDto에 nickname 필드 누락 수정 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * Revert "fix: 홈 진행중인 사건 API 연동 및 UI 수정 (#83)" (#84) This reverts commit 89d9c6f87508a8f1db54d5d342170a87e773a95b. * feat: name/nickname 표시 정책 적용 (#74) * feat(auth): 카카오 로그인 시 약관 동의 레코드 저장 및 기존 유저 backfill 스크립트 추가 - 로그인 시 user_terms_agreements 테이블에 service, privacy 약관 동의 레코드 자동 생성 - saveFirstLoginFields에서 $transaction으로 유저 업데이트와 약관 동의 레코드 생성을 원자적 처리 - 약관 버전 상수 정의 (날짜 기반: 2026-06-18) - 기존 유저 대상 backfill 스크립트 추가 (scripts/backfill-user-terms-agreements.ts) Co-Authored-By: Claude Sonnet 4.6 * refactor: /api/user/me → /api/users/me 경로 변경 - API 라우트 디렉토리 이동 (src/app/api/user/me → src/app/api/users/me) - domains/user/hooks.ts 내 API 호출 경로 일괄 수정 Co-Authored-By: Claude Sonnet 4.6 * feat(user): Apply name/nickname display policy Add name field priority across the application: display name when available, fall back to nickname otherwise. Implement profile edit page with name, nickname, and MBTI fields. Remove hardcoded values from mypage main. - GET/PATCH /api/users/me: add name field to response and request - HomeGreeting: use name ?? nickname for greeting - MyPage main: replace hardcoded nickname/MBTI with useUserMe data - Profile edit page: full form with name, nickname, MBTI, avatar - API_SPEC.md: update GET/PATCH docs with name field Co-Authored-By: Claude * fix: user/me에 name 필드 추가 및 존재하지 않는 auditLog/roomAccessLog 호출 제거 - UserMeDto, UserProfile 타입에 name 필드 추가 - GET/PATCH /api/user/me select 및 응답에 name 포함 - Prisma schema에 모델이 없는 prisma.auditLog, prisma.roomAccessLog 호출 제거 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix: 홈 진행중인 사건 API 연동 및 UI 수정 (#85) * fix: DisputeParticipantDto에 nickname 필드 추가 * fix: 홈 일기 박스 max-width 제거로 너비 100% 적용 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 진행중인 사건 API 연동 - GET /api/disputes에 active=true 파라미터 추가 → 4개 진행중 상태 필터링 - toParticipantDto에 nickname: null 추가로 타입 불일치 해소 - useActiveCases 실제 fetch 함수 활성화 및 DTO → ActiveCase 변환 구현 Co-Authored-By: Claude Sonnet 4.6 * fix: 사건 생성 AbortController 타임아웃 5초 → 30초로 증가 Co-Authored-By: Claude Sonnet 4.6 * fix: disputes/[id]/route.ts toParticipantDto에 nickname 필드 누락 수정 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * perf: 홈 로딩 시 session API 중복 호출 제거 (#86) - React cache()로 getServerSession을 감싼 getCachedSession() 추가 → layout.tsx와 page.tsx에서 동일 요청 내 중복 호출 1회로 dedup - AuthProvider에 session prop 추가 후 SessionProvider에 전달 → SessionProvider 마운트 시 클라이언트 자동 /api/auth/session fetch 제거 - 결과: 홈 로딩 시 session 관련 호출 4회 → 2회(middleware + /api/user/me)로 감소 Co-authored-by: Claude Sonnet 4.6 * feat(diary): 감정일기 작성 페이지 및 CategoryFilter emotion 모드 추가 (#81) * refactor(api): 중복 users/me API 라우트 제거 (#89) /api/users/me(복수)와 /api/user/me(단수)가 동일한 역할로 중복 존재하던 문제를 해결한다. 기능이 완성된 /api/user/me(단수)를 유지하고, 최소 구현만 남아있던 /api/users/me(복수)를 삭제한다. Co-authored-by: Claude Sonnet 4.6 * feat(mypage): 회원탈퇴 전 약관 안내 페이지 추가 (#87) * feat(mypage): 회원탈퇴 전 약관 안내 페이지 추가 마이페이지에서 회원탈퇴 클릭 시 바로 모달이 뜨던 방식을 개선하여, 말해부엉 서비스 기준 탈퇴 안내 조항(5개 조, 약 5000자)을 담은 전용 페이지로 먼저 이동하고, 하단 '탈퇴하기' 버튼으로 최종 확인하는 흐름으로 변경. Co-Authored-By: Claude Sonnet 4.6 * feat(user): 회원탈퇴 DELETE 엔드포인트 및 탈퇴 계정 로그인 차단 추가 - DELETE /api/user/me: 소프트 딜리트(deletedAt, deletionRequestedAt 설정) 처리 및 AuditLog(USER_DELETED) 기록, 이미 탈퇴된 계정 재요청 시 409 반환 - signIn 콜백에서 deletedAt이 설정된 계정의 카카오 로그인을 차단(return false) Co-Authored-By: Claude Sonnet 4.6 * fix(mypage): CodeRabbit 리뷰 반영 — SCSS lint 3건 수정 및 탈퇴 중복 요청 방지 - page.module.scss: @include 뒤 빈 줄 추가(declaration-empty-line-before) 2건 - page.module.scss: word-wrap → overflow-wrap (property-no-deprecated) 1건 - page.tsx: handleWithdraw 재진입 가드(if loading return) 추가 - page.tsx: setConfirmOpen(false)를 API 호출 전으로 이동 - page.tsx: setLoading(false)를 finally 블록으로 통합 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix(mypage): 프로필 이미지 미표시, 이름 기본값, MBTI 미설정 문구 수정 (#88) * fix(mypage): 프로필 이미지 미표시, 이름 기본값, MBTI 미설정 문구 수정 - mypage: Avatar에 profileImageUrl 전달하여 프로필 이미지 표시 - mypage/edit: 이름 필드 초기값을 user.name 우선으로 적용 (카카오 이름 기준) - mypage: MBTI 미설정 시 'MBTI를 설정해주세요' 안내 문구 표시 Co-Authored-By: Claude Sonnet 4.6 * fix(api): GET 핸들러 없는 라우트 빌드 에러 수정 동적 세그먼트 없이 GET 핸들러도 없는 API 라우트에서 Next.js 빌드 시 정적 생성 시도로 인한 'Failed to collect page data' 에러 방지를 위해 force-dynamic 추가 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 판결 결과 페이지 구현 (판결/유형 탭, JudgmentResult, JudgmentTypeResult) (#90) * feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix: ai_room 이름 변경, 초대 링크 버그 수정, 판결받기 버튼 개선 (#92) * ref(schema): ai_chat → ai_room 이름 변경 및 a_submitted 상태 추가 room_mode의 ai_chat을 ai_room으로 변경한다. AI 대화 기능이 없음에도 chat이라는 이름이 오해를 유발해 수정한다. dispute_status에 a_submitted를 추가한다. 단독/1:1 판결 흐름 모두 role_a 진술 제출 시 중간 상태를 명시적으로 표현한다. - 단독: draft → a_submitted → judging → judged - 1:1: ... → opponent_joined → a_submitted → both_submitted → judging → judged Co-Authored-By: Claude * fix(rooms): ai_room 상태 반영 및 초대 링크 재발급 허용 room_mode 변경(ai_chat → ai_room)에 따라 관련 API 코드를 일괄 수정한다. 초대 링크 발급 시 AI_ROOM과 INVITE_READY 모두 허용한다. 기존에는 AI_CHAT 상태에서만 발급 가능해 같은 버튼을 두 번 누르면 실패하는 문제가 있었다. 재발급 시 기존 링크는 무효화된다. 초대 링크 발급 시 dispute가 DRAFT 상태면 WAITING_OPPONENT로 업데이트한다. Co-Authored-By: Claude * fix(invite): 초대 링크 만료 기간 72시간 → 7일로 변경 카카오톡으로 링크를 전달한 뒤 상대방이 며칠 후 확인하는 케이스를 고려해 만료 기간을 7일로 늘린다. Co-Authored-By: Claude * fix(disputes): a_submitted 상태 기반 진술 제출 및 판결 로직 반영 role_a 진술 제출 시 dispute 상태를 WAITING_OPPONENT에서 A_SUBMITTED로 변경한다. role_b는 A_SUBMITTED 이후에만 진술 제출이 가능하도록 조건을 강화한다. 단독 판결 트리거 조건을 WAITING_OPPONENT에서 A_SUBMITTED로 변경한다. 진행중 사건 목록 필터에 A_SUBMITTED 상태를 추가한다. IMMUTABLE_DISPUTE_STATUSES에 A_SUBMITTED를 추가한다. Co-Authored-By: Claude * fix(disputes): 판결받기 버튼 활성화 조건 수정 진술 내용이 존재하면 단독 판결받기 버튼을 활성화한다. 기존에는 a_submitted 상태를 확인했으나 진술 작성 완료와 동시에 제출이 이루어지므로 content 존재 여부로 조건을 변경한다. StatusBadge에 a_submitted 상태를 추가한다. Co-Authored-By: Claude * docs: CLAUDE.md 상태 전이 및 서비스 흐름 업데이트 room_mode: ai_chat → ai_room 반영 dispute_status: a_submitted 추가 및 단독/1:1 흐름 분리 명시 서비스 흐름에서 AI 대화 단계 제거 (AI 대화 페이지 미구현) 방 정책 섹션 현행화 Co-Authored-By: Claude * ref(disputes): a_submitted 상태 제거 및 초대 트랜잭션 안전성 개선 waiting_opponent이 이미 'A 진술 제출 완료' 의미를 포함하므로 별도의 a_submitted 상태가 불필요하다고 판단해 제거. - schema, migration, types, constants에서 A_SUBMITTED 제거 - ROLE_A 진술 제출 후 상태: A_SUBMITTED → WAITING_OPPONENT 복원 - ROLE_B 제출 guard: OPPONENT_JOINED 기준으로 복원 (BOTH_SUBMITTED 허용으로 재시도 멱등성 보장) - 단독 판결 guard: WAITING_OPPONENT 기준으로 복원 - invite/route.ts: existingDispute 조회를 트랜잭션 내부로 이동 (TOCTOU 방지) - CLAUDE.md 상태 전이 업데이트 Co-Authored-By: Claude * ref(schema): 마이그레이션 두 단계 → 단일 파일로 통합 ai_chat → open → ai_room 두 단계 마이그레이션을 ai_chat → ai_room 단일 파일로 통합. Co-Authored-By: Claude --------- Co-authored-by: Claude * fix: disputes/[id] 페이지 UI 및 판결 플로우 수정 (#91) * refactor(ai): 메타 추출 모델 분리 및 프롬프트 출력 길이 축소 - extractDisputeMeta 전용 모델을 gemini-2.0-flash-lite로 분리 - moderation 모델도 gemini-2.0-flash-lite로 변경 - 제목 30자→20자, 요약 100자→50자로 축소 Co-Authored-By: Claude Sonnet 4.6 * feat(dispute): 사건종료 API 및 훅 구현 - PATCH /api/disputes/[id]/status 엔드포인트 추가 - closeDispute API 함수 및 useCloseDispute 훅 추가 - DisputePage 사건종료 버튼에 훅 연결 및 로딩/에러 처리 Co-Authored-By: Claude Sonnet 4.6 * fix(statement): 진술 제출 후 상태 업데이트 및 판결 요청 추가 - 진술 제출 시 dispute 상태를 waiting_opponent로 업데이트 - fire-and-forget 방식으로 judge API 호출 추가 Co-Authored-By: Claude Sonnet 4.6 * refactor(home): AbortController를 AbortSignal.timeout으로 단순화 Co-Authored-By: Claude Sonnet 4.6 * fix(dispute): DisputePage 버튼 너비 및 푸터 보더 스타일 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(dispute): 자동 judge 호출 제거 및 스피너 조건 수정 - statement 제출 후 fire-and-forget judge 호출 제거 - 스피너를 DB status 기반이 아닌 isJudging (API 호출 중) 기준으로만 표시 - 판결 완료 후 query invalidation으로 자동 UI 전환 Co-Authored-By: Claude Sonnet 4.6 * feat(dispute): 새로고침 버튼에 dispute 재조회 연결 Co-Authored-By: Claude Sonnet 4.6 * fix(statement): 진술 저장 중 스피너 표시 및 meta 추출 완료 후 이동 - extractDisputeMeta fire-and-forget → await으로 변경 (title/summary 추출 완료 후 응답) - 저장 중 fullscreen 스피너 화면 추가 - 중복 PATCH /status 호출 제거 (statements route에서 이미 처리) - next/image 적용 및 카카오 이미지 도메인 허용 (next.config.ts) - avatarFallback → 기본 이미지(thumbnail-default.png) 폴백 - categoryChip inline background-color 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드리뷰 반영 - StatementPage: savingContent 폭 반응형 처리 (min(100%, 362px)) - statements/route: extractDisputeMeta에 10초 타임아웃 추가 - status/route: 동일 상태 재요청 시 멱등 성공 반환 - judgment.ts: Array.from 기반 유니코드 안전 문자열 절단 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * fix(auth): 탈퇴 회원이 동일 카카오 계정으로 재가입 가능하도록 수정 (#94) 탈퇴 처리 시 accounts 레코드 삭제 및 kakao_id null 처리를 추가하여 탈퇴 후 동일 카카오 계정으로 재가입이 가능하도록 수정 Co-authored-by: Claude Sonnet 4.6 * fix: 사건조회 UI 개선 및 AI 판결 플로우 버그 수정 (#95) * refactor(ai): 메타 추출 모델 분리 및 프롬프트 출력 길이 축소 - extractDisputeMeta 전용 모델을 gemini-2.0-flash-lite로 분리 - moderation 모델도 gemini-2.0-flash-lite로 변경 - 제목 30자→20자, 요약 100자→50자로 축소 Co-Authored-By: Claude Sonnet 4.6 * feat(dispute): 사건종료 API 및 훅 구현 - PATCH /api/disputes/[id]/status 엔드포인트 추가 - closeDispute API 함수 및 useCloseDispute 훅 추가 - DisputePage 사건종료 버튼에 훅 연결 및 로딩/에러 처리 Co-Authored-By: Claude Sonnet 4.6 * fix(statement): 진술 제출 후 상태 업데이트 및 판결 요청 추가 - 진술 제출 시 dispute 상태를 waiting_opponent로 업데이트 - fire-and-forget 방식으로 judge API 호출 추가 Co-Authored-By: Claude Sonnet 4.6 * refactor(home): AbortController를 AbortSignal.timeout으로 단순화 Co-Authored-By: Claude Sonnet 4.6 * fix(dispute): DisputePage 버튼 너비 및 푸터 보더 스타일 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(dispute): 자동 judge 호출 제거 및 스피너 조건 수정 - statement 제출 후 fire-and-forget judge 호출 제거 - 스피너를 DB status 기반이 아닌 isJudging (API 호출 중) 기준으로만 표시 - 판결 완료 후 query invalidation으로 자동 UI 전환 Co-Authored-By: Claude Sonnet 4.6 * feat(dispute): 새로고침 버튼에 dispute 재조회 연결 Co-Authored-By: Claude Sonnet 4.6 * fix(statement): 진술 저장 중 스피너 표시 및 meta 추출 완료 후 이동 - extractDisputeMeta fire-and-forget → await으로 변경 (title/summary 추출 완료 후 응답) - 저장 중 fullscreen 스피너 화면 추가 - 중복 PATCH /status 호출 제거 (statements route에서 이미 처리) - next/image 적용 및 카카오 이미지 도메인 허용 (next.config.ts) - avatarFallback → 기본 이미지(thumbnail-default.png) 폴백 - categoryChip inline background-color 제거 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드리뷰 반영 - StatementPage: savingContent 폭 반응형 처리 (min(100%, 362px)) - statements/route: extractDisputeMeta에 10초 타임아웃 추가 - status/route: 동일 상태 재요청 시 멱등 성공 반환 - judgment.ts: Array.from 기반 유니코드 안전 문자열 절단 Co-Authored-By: Claude Sonnet 4.6 * fix(ai): gemini-2.0-flash-lite 미지원으로 gemini-2.5-flash로 모델 변경 * fix(api): rooms POST roomMode AI_ROOM 수정 및 에러 로깅 추가 * fix(statement): 진술 저장 성공 시 네비게이션 전까지 스피너 유지 * feat(disputes): AI 메타 추출 완료 전 폴링 스피너 및 에러 로깅 개선 * feat(layout): (page) 그룹 공통 BottomNavigation 레이아웃 적용, statement 제외 * chore(prisma): db pull 스키마 동기화 * fix(layout): 바텀 탭 숨김 경로 추가 (join, login, auth, terms, privacy) * fix(dispute): refetchInterval 콜백 타입 오류 수정 (UseQueryOptions 활용) * fix(dispute): a_submitted enum 제거, 폴링 종료 후 스피너 고정 버그 수정, 분석 중 메시지 순환 적용 * chore(prisma): db pull 스키마 동기화 * chore(prisma): dev 기준 스키마 복원 --------- Co-authored-by: Claude Sonnet 4.6 * fix: dispute UI 버그 수정 및 AI 판결 플로우 개선 (#96) * fix: 카카오 이미지 http 도메인 허용, 새로고침 버튼 로딩 스피너 추가 * fix(dispute): AI 메타 추출을 DB 저장 전에 실행하도록 순서 변경 * fix(dispute): AI 추출 실패 시 에러 반환 및 alert 처리, 화면 유지 * fix(dispute): 바텀탭 높이만큼 푸터 버튼 위치 조정 * fix(statement): 저장 중 AI 분석 풀스크린 제거, 버튼 비활성화로 대체 * fix(dispute): 초대 배너 클릭 시 페이지 이동 대신 handleInvite 호출로 변경 * fix(dispute): 판결 완료 콘텐츠 영역 하단 여백 추가 * fix(dispute): 판결 완료 후 페이지 새로고침으로 결과 화면 전환 * fix(ai): 갈등 유형 선택 시 양측 입장 종합 원칙 프롬프트에 명시 * feat(judgment): MBTI 기반 판결 분석 및 mbtiNote 추가 - JudgmentInput에 mbtiA, mbtiB 옵션 필드 추가 - SOLO/DUO 프롬프트에 MBTI 섹션 조건부 삽입 (있을 때만) - AI 응답 JSON에 mbtiNote 필드 요청 (없으면 null) - judge/route.ts에서 참여자 MBTI 조회 후 generateAiJudgment 전달 - mbtiNote를 rawResponse(JSON)에 저장 - AiJudgmentDto에 mbtiNote 노출, mapper에서 rawResponse 파싱 Co-Authored-By: Claude Sonnet 4.6 * fix(ai): META_PROMPT title 15자 제한, summary 서술형 톤으로 수정 Co-Authored-By: Claude Sonnet 4.6 * fix(ai): 화해 멘트에 진술 말투(반말/존댓말) 반영 지시 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: 리뷰 반영 - refresh 고착 방지, AI 추출 에러 코드 분리, 로그 정리 - handleRefresh: try/finally로 setIsRefreshing(false) 보장 - AI 추출 실패 코드 분리: TIMEOUT(504), PARSE_ERROR(502), FAILED(503) - console.error에서 err 원문 제거 - statement 페이지: AI 에러 코드 3종 alert 처리 Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat: 사건기록 페이지 API 연동 및 홈 UI 개선 (#97) * feat: 판결 결과 컴포넌트 및 도메인 로직 초기 작업 Co-Authored-By: Claude Sonnet 4.6 * feat: 판결 결과 페이지 구현 (#판결탭/유형탭/UI) - DisputePage: 판결/유형 서브탭(Tab 공통컴포넌트) 추가 - JudgmentResult: 이미지 기준 UI 재구성, nickname 적용 - JudgmentTypeResult: 유형탭 컴포넌트 신규 생성 (카드이미지, ActionPrompt) - Tab.module.scss: w60 h36 사이즈 조정 - DisputeParticipantDto: nickname 필드 추가 - disputes/[id]/route: nickname 조회 추가 - judgment.mapper: cardImageUrl 추가 - types/judgment: ConflictTypeDetailDto에 cardImageUrl 추가 - auth/index: 카카오 로그인 시 profileImageUrl 저장 - page.module.scss: diaryBox max-width 제거 - NewCaseButton: AbortController timeout 30s Co-Authored-By: Claude Sonnet 4.6 * chore: next.config에 Supabase Storage 및 카카오 이미지 도메인 추가 Co-Authored-By: Claude Sonnet 4.6 * fix: JudgmentResult Avatar img 태그를 next/image로 교체 Co-Authored-By: Claude Sonnet 4.6 * fix: PR #90 리뷰 반영 - participants nickname → name으로 변경 (DTO, route, 컴포넌트, useActiveCases) - next.config: 카카오 HTTP 패턴 제거 (HTTPS만 허용) - DisputePage: isCompleted null 케이스 처리 (!!dispute) - JudgmentResult.module.scss: declaration-empty-line-before stylelint 수정 - JudgmentTypeResult.module.scss: 동일 stylelint 수정 Co-Authored-By: Claude Sonnet 4.6 * fix: PR #90 추가 리뷰 반영 - JudgmentResult/JudgmentTypeResult: props 대신 disputeId 기반 직접 API 호출 (새로고침 시 데이터 유실 방지, TanStack Query 캐시로 중복 요청 없음) - DisputePage: judgment/participants props 제거, isError 기반 에러 처리 - auth/index.ts: 프로필 이미지 백필 try-catch 감싸기 (실패 시 로그인 차단 방지) - judgement.api.ts: 에러 메시지 사용자 친화적으로 개선 Co-Authored-By: Claude Sonnet 4.6 * chore: 불필요한 스크린샷 PNG 파일 제거 Co-Authored-By: Claude Sonnet 4.6 * refactor: CalendarRecord 모델 제거 및 EmotionDiary title 필드 추가 - CalendarRecord 모델 및 CalendarRecordType enum 제거 - User, DisputeRoom, RoomAiConversation, Dispute에서 calendarRecords relation 제거 - EmotionDiary에 title 필드 추가 (VarChar 200) Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 페이지 API 연동 - GET /api/disputes에 completed=true 쿼리 파라미터 추가 (judged/closed 필터링) - fetchCompletedCases, useCompletedCases 추가 (카테고리 필터 + 최신순) - RecordListSection 더미 데이터 제거, 실제 API 연동 - 사건 박스 클릭 시 /disputes/{id}로 이동 (기존 Link 구조 유지) - 로딩/에러/빈 상태 처리 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건기록 빈 상태 UI 개선 - 빈 상태 텍스트 → '등록한 사건이 없어요' - character-case.png 이미지 + 텍스트 중앙 배치 Co-Authored-By: Claude Sonnet 4.6 * feat: 사건박스 공통 컴포넌트 CaseRecordCard 분리 - CaseRecordCard 신규 생성 (src/components/ui) - MUI AvatarGroup으로 1인/2인 참여자 프로필 겹침 표시 - RecordListSection에서 CaseRecordCard 사용하도록 교체 - 카드 스타일 RecordListSection.module.scss → CaseRecordCard.module.scss로 이동 Co-Authored-By: Claude Sonnet 4.6 * fix: 카카오 CDN http 프로토콜 이미지 허용 (img1.kakaocdn.net) 카카오 기본 프로필 이미지 URL이 http로 오는 경우가 있어 *.kakaocdn.net http 패턴 추가 Co-Authored-By: Claude Sonnet 4.6 * feat: 홈 페이지 배경 그라데이션 추가 (primary-200 → white) Co-Authored-By: Claude Sonnet 4.6 * fix: 홈 그라데이션 범위 15%로 조정 Co-Authored-By: Claude Sonnet 4.6 * chore: dispute.hooks.ts dev 브랜치 import 충돌 사전 해결 - UseQueryOptions, DisputeDto import 추가 (dev 브랜치 기준) Co-Authored-By: Claude Sonnet 4.6 * chore: dispute.hooks.ts dev 브랜치 useDispute refetchInterval 옵션 반영 Co-Authored-By: Claude Sonnet 4.6 * fix: 코드레빗 및 juacheon 리뷰 반영 - disputes/route.ts: active/completed 동시 사용 시 if/else 분기로 필터 충돌 방지 - CaseRecordCard: