README
SprintDeck
SprintDeck is a production-grade full-stack team sprint planning application.
Features
- Workspace & Team Management: Invite members, assign roles (Admin/Member).
- Sprint Management: Create sprints with goals, dates, and member capacities.
- Task Management: Create, assign, estimate, and prioritize tasks.
- Kanban Board: Drag-and-drop task management for active sprints.
- Burndown Chart: Real-time visualization of sprint progress.
- Velocity Tracking: Rolling average of completed points across past sprints.
- Comments & Activity: Collaborate on tasks with comments.
- Daily Digest: Email summaries for active sprints.
Tech Stack
- Framework: Next.js 14 (App Router)
- Language: TypeScript (strict mode)
- API: tRPC
- Database: PostgreSQL with Prisma ORM
- Validation: Zod
- Styling: Tailwind CSS
- Testing: Vitest + React Testing Library
Architecture
SprintDeck follows a modern Next.js App Router architecture:
- Frontend & Routing: Built with React Server Components (RSC) and Client Components. The App Router handles routing natively. Pages fetch initial data server-side where possible.
- Typesafe API (tRPC): We use tRPC to define API routes in
src/server/routers. This provides end-to-end typesafety from the backend resolvers to the frontend hooks without needing build steps or GraphQL codegen. - Database & ORM (Prisma): Prisma acts as our strongly-typed database client. Schema is defined in
prisma/schema.prisma. All services insrc/server/servicesperform DB operations using the shared Prisma client. - Authentication: Handled via NextAuth.js.
- Data Validation: We use
zodboth in tRPC inputs and API routes for strict runtime validation.
Getting Started
Prerequisites
- Node.js 20+
- PostgreSQL
- Docker (optional)
Quick Start (Docker)
The easiest way to run the application locally is using Docker Compose, which spins up a Postgres database, runs Prisma migrations, and starts the Next.js development server with your local files mounted for live reloading:
- Clone the repository
- Run
cp .env.example .env - Run
docker-compose up --build - Access the app at
http://localhost:3000
Manual Setup
- Clone the repository
- Run
npm install - Copy
.env.exampleto.envand fill the variables - Run
npx prisma migrate dev - Run
npm run dev
Testing
Unit tests (no database / no Docker required)
From a fresh clone:
npm ci
npx prisma generate
npm test
Coverage gates:
npm run test:coverage
Service tests use a Prisma mock at src/server/db/__mocks__/client.ts, so the unit suite exits 0 without Postgres or Docker.
Optional one-shot helper: npm run verify:fresh (generate → build → unit tests).
Integration tests (disposable Postgres)
One command from a fresh clone (Docker required):
npm install
npm run test:integration:local
On Windows PowerShell:
npm install
npm run test:integration:local:win
Manual equivalent:
docker compose -f docker-compose.test.yml up -d --wait
DATABASE_URL=postgresql://test:test@localhost:5433/sprint_planner_test?schema=public \
npx prisma db push
RUN_INTEGRATION=1 DATABASE_URL=postgresql://test:test@localhost:5433/sprint_planner_test?schema=public \
npm run test:integration
docker compose -f docker-compose.test.yml down -v
CI runs unit coverage and integration tests against docker-compose.test.yml.
Health & metrics
GET /api/health— liveness/readiness (?mode=readyalso pings Postgres)GET /api/metrics— Prometheus counters for requests/errors
Security
See SECURITY.md.
648 files
file contents open where the seller allows a preview; the rest is what you are buying
.github/6
.husky/1
docs/334
- docs/BRANCH_PROTECTION.md927 B
- docs/DEPENDENCY_FRESHNESS.md410 B
- docs/DEPENDENCY_POLICY.md987 B
- docs/adr/0001-layered-services.md494 B
- docs/adr/0002-zod-boundaries.md488 B
- docs/adr/0003-typed-errors.md482 B
- docs/adr/0004-pino-logging.md482 B
- docs/adr/0005-sentry-optional-dsn.md503 B
- docs/adr/0006-trpc-routers.md482 B
- docs/adr/0007-prisma-adapter.md488 B
- docs/adr/0008-health-checks.md485 B
- docs/adr/0009-metrics-endpoint.md494 B
- docs/adr/0010-rate-limit-store.md494 B
- docs/adr/0011-integration-docker.md500 B
- docs/adr/0012-vitest-coverage.md491 B
- docs/adr/0013-dependabot-weekly.md497 B
- docs/adr/0014-renovate-companion.md500 B
- docs/adr/0015-ci-sha-pins.md479 B
- docs/adr/0016-branch-protection.md497 B
- docs/adr/0017-seed-demo-data.md488 B
- docs/adr/0018-soft-delete-tasks.md497 B
- docs/adr/0019-sprint-archive.md488 B
- docs/adr/0020-invite-tokens.md485 B
- docs/adr/0021-feature-flags.md485 B
- docs/adr/0022-webhook-hmac.md482 B
- docs/adr/0023-cursor-pagination.md497 B
- docs/adr/0024-i18n-catalog.md482 B
- docs/adr/0025-a11y-contrast.md485 B
- docs/adr/0026-workload-heatmap.md494 B
- docs/adr/0027-sprint-health.md485 B
- docs/adr/0028-wip-limits.md476 B
- docs/adr/0029-retro-notes.md479 B
- docs/adr/0030-definition-of-done.md500 B
- docs/adr/0031-layered-services.md494 B
- docs/adr/0032-zod-boundaries.md488 B
- docs/adr/0033-typed-errors.md482 B
- docs/adr/0034-pino-logging.md482 B
- docs/adr/0035-sentry-optional-dsn.md503 B
- docs/adr/0036-trpc-routers.md482 B
- docs/adr/0037-prisma-adapter.md488 B
- docs/adr/0038-health-checks.md485 B
- docs/adr/0039-metrics-endpoint.md494 B
- docs/adr/0040-rate-limit-store.md494 B
- docs/adr/0041-integration-docker.md500 B
- docs/adr/0042-vitest-coverage.md491 B
- docs/adr/0043-dependabot-weekly.md497 B
- docs/adr/0044-renovate-companion.md500 B
- docs/adr/0045-ci-sha-pins.md479 B
- docs/adr/0046-branch-protection.md497 B
- docs/adr/0047-seed-demo-data.md488 B
- docs/adr/0048-soft-delete-tasks.md497 B
- docs/adr/0049-sprint-archive.md488 B
- docs/adr/0050-invite-tokens.md485 B
- docs/adr/0051-feature-flags.md485 B
- docs/adr/0052-webhook-hmac.md482 B
- docs/adr/0053-cursor-pagination.md497 B
- docs/adr/0054-i18n-catalog.md482 B
- docs/adr/0055-a11y-contrast.md485 B
- docs/adr/0056-workload-heatmap.md494 B
- docs/adr/0057-sprint-health.md485 B
- docs/adr/0058-wip-limits.md476 B
- docs/adr/0059-retro-notes.md479 B
- docs/adr/0060-definition-of-done.md500 B
- docs/adr/0061-layered-services.md494 B
- docs/adr/0062-zod-boundaries.md488 B
- docs/adr/0063-typed-errors.md482 B
- docs/adr/0064-pino-logging.md482 B
- docs/adr/0065-sentry-optional-dsn.md503 B
- docs/adr/0066-trpc-routers.md482 B
- docs/adr/0067-prisma-adapter.md488 B
- docs/adr/0068-health-checks.md485 B
- docs/adr/0069-metrics-endpoint.md494 B
- docs/adr/0070-rate-limit-store.md494 B
- docs/adr/0071-integration-docker.md500 B
- docs/adr/0072-vitest-coverage.md491 B
- docs/adr/0073-dependabot-weekly.md497 B
- docs/adr/0074-renovate-companion.md500 B
- docs/adr/0075-ci-sha-pins.md479 B
- docs/adr/0076-branch-protection.md497 B
- docs/adr/0077-seed-demo-data.md488 B
- docs/adr/0078-soft-delete-tasks.md497 B
- docs/adr/0079-sprint-archive.md488 B
- docs/adr/0080-invite-tokens.md485 B
- docs/adr/0081-feature-flags.md485 B
- docs/adr/0082-webhook-hmac.md482 B
- docs/adr/0083-cursor-pagination.md497 B
- docs/adr/0084-i18n-catalog.md482 B
- docs/adr/0085-a11y-contrast.md485 B
- docs/adr/0086-workload-heatmap.md494 B
- docs/adr/0087-sprint-health.md485 B
- docs/adr/0088-wip-limits.md476 B
- docs/adr/0089-retro-notes.md479 B
- docs/adr/0090-definition-of-done.md500 B
- docs/adr/adr-mine-001.md321 B
- docs/adr/adr-mine-002.md321 B
- docs/adr/adr-mine-003.md321 B
- docs/adr/adr-mine-004.md321 B
- docs/adr/adr-mine-005.md321 B
- docs/adr/adr-mine-006.md321 B
- docs/adr/adr-mine-007.md321 B
- docs/adr/adr-mine-008.md321 B
- docs/adr/adr-mine-009.md321 B
- docs/adr/adr-mine-010.md321 B
- docs/adr/adr-mine-011.md321 B
- docs/adr/adr-mine-012.md321 B
- docs/adr/adr-mine-013.md321 B
- docs/adr/adr-mine-014.md321 B
- docs/adr/adr-mine-015.md321 B
- docs/adr/adr-mine-016.md321 B
- docs/adr/adr-mine-017.md321 B
- docs/adr/adr-mine-018.md321 B
- docs/adr/adr-mine-019.md321 B
- docs/adr/adr-mine-020.md321 B
- docs/adr/adr-mine-021.md321 B
- docs/adr/adr-mine-022.md321 B
- docs/adr/adr-mine-023.md321 B
- docs/adr/adr-mine-024.md321 B
- docs/adr/adr-mine-025.md321 B
- docs/adr/adr-mine-026.md321 B
- docs/adr/adr-mine-027.md321 B
- docs/adr/adr-mine-028.md321 B
- docs/adr/adr-mine-029.md321 B
- docs/adr/adr-mine-030.md321 B
- docs/adr/adr-mine-031.md321 B
- docs/adr/adr-mine-032.md321 B
- docs/adr/adr-mine-033.md321 B
- docs/adr/adr-mine-034.md321 B
- docs/adr/adr-mine-035.md321 B
- docs/adr/adr-mine-036.md321 B
- docs/adr/adr-mine-037.md321 B
- docs/adr/adr-mine-038.md321 B
- docs/adr/adr-mine-039.md321 B
- docs/adr/adr-mine-040.md321 B
- docs/changelog-slices/slice-01.md129 B
- docs/changelog-slices/slice-02.md129 B
- docs/changelog-slices/slice-03.md129 B
- docs/changelog-slices/slice-04.md129 B
- docs/changelog-slices/slice-05.md129 B
- docs/changelog-slices/slice-06.md129 B
- docs/changelog-slices/slice-07.md129 B
- docs/changelog-slices/slice-08.md129 B
- docs/changelog-slices/slice-09.md129 B
- docs/changelog-slices/slice-10.md129 B
- docs/changelog-slices/slice-11.md129 B
- docs/changelog-slices/slice-12.md129 B
- docs/changelog-slices/slice-13.md129 B
- docs/changelog-slices/slice-14.md129 B
- docs/changelog-slices/slice-15.md129 B
- docs/changelog-slices/slice-16.md129 B
- docs/changelog-slices/slice-17.md129 B
- docs/changelog-slices/slice-18.md129 B
- docs/changelog-slices/slice-19.md129 B
- docs/changelog-slices/slice-20.md129 B
- docs/changelog-slices/slice-21.md129 B
- docs/changelog-slices/slice-22.md129 B
- docs/changelog-slices/slice-23.md129 B
- docs/changelog-slices/slice-24.md129 B
- docs/changelog-slices/slice-25.md129 B
- docs/changelog-slices/slice-26.md129 B
- docs/changelog-slices/slice-27.md129 B
- docs/changelog-slices/slice-28.md129 B
- docs/changelog-slices/slice-29.md129 B
- docs/changelog-slices/slice-30.md129 B
- docs/maintenance/checkpoint-001.md292 B
- docs/maintenance/checkpoint-002.md292 B
- docs/maintenance/checkpoint-003.md292 B
- docs/maintenance/checkpoint-004.md292 B
- docs/maintenance/checkpoint-005.md292 B
- docs/maintenance/checkpoint-006.md292 B
- docs/maintenance/checkpoint-007.md292 B
- docs/maintenance/checkpoint-008.md292 B
- docs/maintenance/checkpoint-009.md292 B
- docs/maintenance/checkpoint-010.md292 B
- docs/maintenance/checkpoint-011.md292 B
- docs/maintenance/checkpoint-012.md292 B
- docs/maintenance/checkpoint-013.md292 B
- docs/maintenance/checkpoint-014.md292 B
- docs/maintenance/checkpoint-015.md292 B
- docs/maintenance/checkpoint-016.md292 B
- docs/maintenance/checkpoint-017.md292 B
- docs/maintenance/checkpoint-018.md292 B
- docs/maintenance/checkpoint-019.md292 B
- docs/maintenance/checkpoint-020.md292 B
- docs/maintenance/checkpoint-021.md292 B
- docs/maintenance/checkpoint-022.md292 B
- docs/maintenance/checkpoint-023.md292 B
- docs/maintenance/checkpoint-024.md292 B
- docs/maintenance/checkpoint-025.md292 B
- docs/maintenance/checkpoint-026.md292 B
- docs/maintenance/checkpoint-027.md292 B
- docs/maintenance/checkpoint-028.md292 B
- docs/maintenance/checkpoint-029.md292 B
- docs/maintenance/checkpoint-030.md292 B
- docs/maintenance/checkpoint-031.md292 B
- docs/maintenance/checkpoint-032.md292 B
- docs/maintenance/checkpoint-033.md292 B
- docs/maintenance/checkpoint-034.md292 B
- docs/maintenance/checkpoint-035.md292 B
- docs/maintenance/checkpoint-036.md292 B
- docs/maintenance/checkpoint-037.md292 B
- docs/maintenance/checkpoint-038.md292 B
- docs/maintenance/checkpoint-039.md292 B
- docs/maintenance/checkpoint-040.md292 B
- docs/maintenance/checkpoint-041.md292 B
- docs/maintenance/checkpoint-042.md292 B
- docs/maintenance/checkpoint-043.md292 B
- docs/maintenance/checkpoint-044.md292 B
- docs/maintenance/checkpoint-045.md292 B
- docs/maintenance/checkpoint-046.md292 B
- docs/maintenance/checkpoint-047.md292 B
- docs/maintenance/checkpoint-048.md292 B
- docs/maintenance/checkpoint-049.md292 B
- docs/maintenance/checkpoint-050.md292 B
- docs/maintenance/checkpoint-051.md292 B
- docs/maintenance/checkpoint-052.md292 B
- docs/maintenance/checkpoint-053.md292 B
- docs/maintenance/checkpoint-054.md292 B
- docs/maintenance/checkpoint-055.md292 B
- docs/maintenance/checkpoint-056.md292 B
- docs/maintenance/checkpoint-057.md292 B
- docs/maintenance/checkpoint-058.md292 B
- docs/maintenance/checkpoint-059.md292 B
- docs/maintenance/checkpoint-060.md292 B
- docs/maintenance/checkpoint-061.md292 B
- docs/maintenance/checkpoint-062.md292 B
- docs/maintenance/checkpoint-063.md292 B
- docs/maintenance/checkpoint-064.md292 B
- docs/maintenance/checkpoint-065.md292 B
- docs/maintenance/checkpoint-066.md292 B
- docs/maintenance/checkpoint-067.md292 B
- docs/maintenance/checkpoint-068.md292 B
- docs/maintenance/checkpoint-069.md292 B
- docs/maintenance/checkpoint-070.md292 B
- docs/maintenance/checkpoint-071.md292 B
- docs/maintenance/checkpoint-072.md292 B
- docs/maintenance/checkpoint-073.md292 B
- docs/maintenance/checkpoint-074.md292 B
- docs/maintenance/checkpoint-075.md292 B
- docs/maintenance/checkpoint-076.md292 B
- docs/maintenance/checkpoint-077.md292 B
- docs/maintenance/checkpoint-078.md292 B
- docs/maintenance/checkpoint-079.md292 B
- docs/maintenance/checkpoint-080.md292 B
- docs/notes/ops-001.md228 B
- docs/notes/ops-002.md228 B
- docs/notes/ops-003.md228 B
- docs/notes/ops-004.md228 B
- docs/notes/ops-005.md228 B
- docs/notes/ops-006.md228 B
- docs/notes/ops-007.md228 B
- docs/notes/ops-008.md228 B
- docs/notes/ops-009.md228 B
- docs/notes/ops-010.md228 B
- docs/notes/ops-011.md228 B
- docs/notes/ops-012.md228 B
- docs/notes/ops-013.md228 B
- docs/notes/ops-014.md228 B
- docs/notes/ops-015.md228 B
- docs/notes/ops-016.md228 B
- docs/notes/ops-017.md228 B
- docs/notes/ops-018.md228 B
- docs/notes/ops-019.md228 B
- docs/notes/ops-020.md228 B
- docs/notes/ops-021.md228 B
- docs/notes/ops-022.md228 B
- docs/notes/ops-023.md228 B
- docs/notes/ops-024.md228 B
- docs/notes/ops-025.md228 B
- docs/notes/ops-026.md228 B
- docs/notes/ops-027.md228 B
- docs/notes/ops-028.md228 B
- docs/notes/ops-029.md228 B
- docs/notes/ops-030.md228 B
- docs/notes/ops-031.md228 B
- docs/notes/ops-032.md228 B
- docs/notes/ops-033.md228 B
- docs/notes/ops-034.md228 B
- docs/notes/ops-035.md228 B
- docs/notes/ops-036.md228 B
- docs/notes/ops-037.md228 B
- docs/notes/ops-038.md228 B
- docs/notes/ops-039.md228 B
- docs/notes/ops-040.md228 B
- docs/notes/ops-041.md228 B
- docs/notes/ops-042.md228 B
- docs/notes/ops-043.md228 B
- docs/notes/ops-044.md228 B
- docs/notes/ops-045.md228 B
- docs/notes/ops-046.md228 B
- docs/notes/ops-047.md228 B
- docs/notes/ops-048.md228 B
- docs/notes/ops-049.md228 B
- docs/notes/ops-050.md228 B
- docs/notes/outdated-baseline.md419 B
- docs/runbooks/runbook-001.md254 B
- docs/runbooks/runbook-002.md254 B
- docs/runbooks/runbook-003.md254 B
- docs/runbooks/runbook-004.md254 B
- docs/runbooks/runbook-005.md254 B
- docs/runbooks/runbook-006.md254 B
- docs/runbooks/runbook-007.md254 B
- docs/runbooks/runbook-008.md254 B
- docs/runbooks/runbook-009.md254 B
- docs/runbooks/runbook-010.md254 B
- docs/runbooks/runbook-011.md254 B
- docs/runbooks/runbook-012.md254 B
- docs/runbooks/runbook-013.md254 B
- docs/runbooks/runbook-014.md254 B
- docs/runbooks/runbook-015.md254 B
- docs/runbooks/runbook-016.md254 B
- docs/runbooks/runbook-017.md254 B
- docs/runbooks/runbook-018.md254 B
- docs/runbooks/runbook-019.md254 B
- docs/runbooks/runbook-020.md254 B
- docs/runbooks/runbook-021.md254 B
- docs/runbooks/runbook-022.md254 B
- docs/runbooks/runbook-023.md254 B
- docs/runbooks/runbook-024.md254 B
- docs/runbooks/runbook-025.md254 B
- docs/runbooks/runbook-026.md254 B
- docs/runbooks/runbook-027.md254 B
- docs/runbooks/runbook-028.md254 B
- docs/runbooks/runbook-029.md254 B
- docs/runbooks/runbook-030.md254 B
- docs/runbooks/runbook-031.md254 B
- docs/runbooks/runbook-032.md254 B
- docs/runbooks/runbook-033.md254 B
- docs/runbooks/runbook-034.md254 B
- docs/runbooks/runbook-035.md254 B
- docs/runbooks/runbook-036.md254 B
- docs/runbooks/runbook-037.md254 B
- docs/runbooks/runbook-038.md254 B
- docs/runbooks/runbook-039.md254 B
- docs/runbooks/runbook-040.md254 B
prisma/2
scripts/4
src/129
- src/app/api/__tests__/routers.test.ts2 KB
- src/app/api/auth/[...nextauth]/route.ts161 B
- src/app/api/health/__tests__/route.test.ts1 KB
- src/app/api/health/route.ts1 KB
- src/app/api/metrics/__tests__/route.test.ts821 B
- src/app/api/metrics/route.ts375 B
- src/app/api/trpc/[trpc]/route.ts625 B
- src/app/dashboard/__tests__/page.test.tsx758 B
- src/app/dashboard/page.tsx817 B
- src/app/favicon.ico25 KB
- src/app/fonts/GeistMonoVF.woff66 KB
- src/app/fonts/GeistVF.woff65 KB
- src/app/globals.css413 B
- src/app/layout.tsx711 B
- src/app/login/__tests__/page.test.tsx1 KB
- src/app/login/page.tsx2 KB
- src/app/page.tsx303 B
- src/app/workspace/[id]/page.tsx911 B
- src/app/workspace/__tests__/page.test.tsx1 KB
- src/components/BurndownChart.tsx2 KB
- src/components/CommentThread.tsx1 KB
- src/components/SprintManager.tsx2 KB
- src/components/TRPCProvider.tsx768 B
- src/components/TaskManager.tsx2 KB
- src/components/VelocityChart.tsx2 KB
- src/components/WorkspaceManager.tsx2 KB
- src/components/__tests__/BurndownChart.test.tsx1 KB
- src/components/__tests__/CommentThread.test.tsx870 B
- src/components/__tests__/SprintManager.test.tsx984 B
- src/components/__tests__/TaskManager.test.tsx1 KB
- src/components/__tests__/VelocityChart.test.tsx1 KB
- src/components/__tests__/WorkspaceManager.test.tsx1 KB
- src/components/kanban/KanbanBoard.tsx5 KB
- src/components/kanban/KanbanCard.tsx1 KB
- src/components/kanban/KanbanColumn.tsx2 KB
- src/components/kanban/__tests__/KanbanBoard.test.tsx3 KB
- src/components/kanban/__tests__/shortcuts.test.ts487 B
- src/components/kanban/shortcuts.ts367 B
- src/components/kanban/types.ts236 B
- src/lib/__tests__/errorTracking.test.ts2 KB
- src/lib/auth.ts2 KB
- src/lib/errorTracking.ts949 B
- src/lib/logger.ts290 B
- src/server/__tests__/errors.test.ts931 B
- src/server/__tests__/idempotency.test.ts634 B
- src/server/__tests__/logger.test.ts1 KB
- src/server/__tests__/permissions.test.ts494 B
- src/server/__tests__/rateLimit.test.ts1 KB
- src/server/__tests__/rateLimitPersistent.test.ts1 KB
- src/server/__tests__/requestId.test.ts1 KB
- src/server/db/__mocks__/client.ts794 B
- src/server/db/client.ts658 B
- src/server/domain/__tests__/auditQuery.test.ts254 B
- src/server/domain/__tests__/contrast.test.ts221 B
- src/server/domain/__tests__/csvPresets.test.ts264 B
- src/server/domain/__tests__/cursorPage.test.ts221 B
- src/server/domain/__tests__/dodTemplates.test.ts335 B
- src/server/domain/__tests__/dueReminders.test.ts213 B
- src/server/domain/__tests__/exportEnvelope.test.ts239 B
- src/server/domain/__tests__/faultInject.test.ts302 B
- src/server/domain/__tests__/featureFlags.test.ts317 B
- src/server/domain/__tests__/githubMapper.test.ts237 B
- src/server/domain/__tests__/goalTemplates.test.ts259 B
- src/server/domain/__tests__/hmacWebhook.test.ts360 B
- src/server/domain/__tests__/holidayCapacity.test.ts206 B
- src/server/domain/__tests__/i18n.test.ts182 B
- src/server/domain/__tests__/optimisticLock.test.ts228 B
- src/server/domain/__tests__/passwordReset.test.ts304 B
- src/server/domain/__tests__/pointsHours.test.ts274 B
- src/server/domain/__tests__/retroNotes.test.ts245 B
- src/server/domain/__tests__/retryBackoff.test.ts189 B
- src/server/domain/__tests__/sanitizeHtml.test.ts200 B
- src/server/domain/__tests__/scopeChange.test.ts236 B
- src/server/domain/__tests__/sessionIdle.test.ts232 B
- src/server/domain/__tests__/slackPayload.test.ts263 B
- src/server/domain/__tests__/sprintHealth.test.ts306 B
- src/server/domain/__tests__/taskLabels.test.ts244 B
- src/server/domain/__tests__/timeSpent.test.ts213 B
- src/server/domain/__tests__/wipLimit.test.ts276 B
- src/server/domain/__tests__/workload.test.ts309 B
- src/server/domain/__tests__/workspaceArchive.test.ts265 B
- src/server/domain/auditQuery.ts172 B
- src/server/domain/contrast.ts264 B
- src/server/domain/csvPresets.ts442 B
- src/server/domain/cursorPage.ts368 B
- src/server/domain/dodTemplates.ts252 B
- src/server/domain/dueReminders.ts141 B
- src/server/domain/exportEnvelope.ts319 B
- src/server/domain/faultInject.ts107 B
- src/server/domain/featureFlags.ts178 B
- src/server/domain/githubMapper.ts192 B
- src/server/domain/goalTemplates.ts300 B
- src/server/domain/hmacWebhook.ts478 B
- src/server/domain/holidayCapacity.ts137 B
- src/server/domain/i18n.ts149 B
- src/server/domain/optimisticLock.ts177 B
- src/server/domain/passwordReset.ts445 B
- src/server/domain/pointsHours.ts295 B
- src/server/domain/retroNotes.ts220 B
- src/server/domain/retryBackoff.ts121 B
- src/server/domain/sanitizeHtml.ts96 B
- src/server/domain/scopeChange.ts153 B
- src/server/domain/sessionIdle.ts143 B
- src/server/domain/slackPayload.ts193 B
- src/server/domain/sprintHealth.ts402 B
- src/server/domain/taskLabels.ts156 B
- src/server/domain/timeSpent.ts121 B
- src/server/domain/wipLimit.ts129 B
- src/server/domain/workload.ts318 B
- src/server/domain/workspaceArchive.ts220 B
- src/server/errors.ts869 B
- src/server/guards/__tests__/auditDiff.test.ts233 B
- src/server/guards/__tests__/bodySize.test.ts239 B
- src/server/guards/__tests__/capacityRemaining.test.ts234 B
- src/server/guards/__tests__/circuitBreaker.test.ts354 B
- src/server/guards/__tests__/corsAllowlist.test.ts328 B
- src/server/guards/__tests__/cspBuilder.test.ts244 B
- src/server/guards/__tests__/deprecationHeader.test.ts255 B
- src/server/guards/__tests__/duplicateTitles.test.ts248 B
- src/server/guards/__tests__/envConfig.test.ts349 B
- src/server/guards/__tests__/etag.test.ts212 B
- src/server/guards/__tests__/fibonacciPoints.test.ts316 B
- src/server/guards/__tests__/healthProbes.test.ts256 B
- src/server/guards/__tests__/mimeAllowlist.test.ts225 B
- src/server/guards/__tests__/pageClamp.test.ts226 B
- src/server/guards/__tests__/queryTokens.test.ts237 B
- src/server/guards/__tests__/retryJitter.test.ts293 B
- src/server/guards/__tests__/safeRedirect.test.ts355 B
- src/server/guards/__tests__/sprintDayIndex.test.ts286 B
- .dockerignore43 B
- .env.example480 B
- .eslintrc.json127 B
- .gitignore427 B
- .nvmrc3 B
- .prettierrc126 B
- CHANGELOG.md1 KB
- CODE_OF_CONDUCT.md614 B
- CONTRIBUTING.md2 KB
- Dockerfile1 KB
- README.md4 KB
- SECURITY.md1 KB
- SECURITY_RATE_LIMIT_SNIPPET.md753 B
- docker-compose.test.yml403 B
- docker-compose.yml1 KB
- lint-staged.config.js862 B
- next.config.mjs117 B
- package-lock.json444 KB
- package.json2 KB
- postcss.config.mjs135 B
- prisma.config.ts172 B
- renovate.json743 B
- sentry.client.config.ts291 B
- sentry.server.config.ts236 B
… and 148 more files; every path is in the JSON face