4.1 KiB
4.1 KiB
Draft: Multi-Tenant Club Work Manager
Requirements (confirmed)
- Multi-tenant: Multiple clubs (tennis, cycling, etc.) share one application
- Tenant identification: Credential-based — user logs in, system resolves which club(s) they belong to. No subdomains or URL paths for tenant routing.
- Data isolation: PostgreSQL Row-Level Security (RLS) — shared database, tenant isolation via RLS policies
- Work items: Hybrid — both task-based (title, desc, assignee, status) AND schedule/shift-based (time slots, sign-ups, assignments)
- Authentication: External provider (Auth0, Clerk, or Keycloak)
- Target scale: MVP / Proof of concept (1-5 clubs, <100 users)
- Backend: .NET (ASP.NET Core) with PostgreSQL
- Frontend: Next.js with Bun
- Deployment (prod): Kubernetes cluster
- Deployment (local): Docker Compose
Technical Decisions
- Multi-tenancy strategy: RLS + EF Core global query filters (defense-in-depth)
- Tenant resolution: NOT subdomain-based. Tenant derived from authenticated user's JWT claims (club membership)
- Bun runtime: Research shows Bun has P99 latency issues with Next.js SSR in production (March 2026). Use Bun for local dev / package management, Node.js for production runtime.
- Infrastructure: Kustomize (simpler for MVP, no Helm complexity needed yet)
Research Findings
- Finbuckle.MultiTenant: Industry-standard .NET multi-tenancy library. Supports header strategy — good fit for credential-based tenant resolution.
- EF Core Global Query Filters: Auto-filter all queries by tenant_id. Combined with RLS for defense-in-depth.
- PostgreSQL RLS: SET app.current_tenant per connection. Must reset when returning connections to pool.
- Next.js + Bun: Bun has 340ms P99 latency vs 120ms for Node.js (Platformatic benchmarks Jan 2026). Recommendation: Bun for dev, Node.js for prod Docker image.
- K8s deployment: Kustomize with base + overlays (dev/staging/prod). PostgreSQL as StatefulSet for dev, managed DB for prod.
- Docker Compose: Hot reload via
dotnet watchfor .NET, standard Next.js dev server.
Decisions (Round 2)
- Auth provider: Keycloak — self-hosted in K8s cluster, runs alongside the app
- Multi-club membership: YES — a user can belong to multiple clubs, needs a club-switcher/selector after login
- Member roles: 4-tier — Admin, Manager, Member, Viewer (per club, since user can be Admin in one club and Member in another)
- Shift model: Time-slot with sign-up — date, time range, location, description, required headcount. Members sign up or get assigned.
- Repo structure: Monorepo — /backend, /frontend, /infra in one repo
- Notifications: None for MVP — simplest approach, users check the app
Decisions (Round 3)
- .NET version: .NET 10 (user explicitly requested)
- Work item statuses: 5-state — Open → Assigned → In Progress → Review → Done
- Project type: Greenfield — starting from scratch, empty repo
- UI framework: Tailwind CSS + shadcn/ui component library
Test Strategy Decision
- Infrastructure exists: NO (greenfield)
- Automated tests: YES (TDD — tests first)
- Backend framework: xUnit + Testcontainers (PostgreSQL) for .NET 10
- Frontend framework: bun test / Vitest + React Testing Library for Next.js
- Agent-Executed QA: ALWAYS (mandatory — Playwright for UI, curl for API)
- Test infrastructure setup: Must be part of Wave 1 scaffolding tasks
Decisions (Round 4)
- Git repository: Initialize git repo as first step in Task 1 —
git init+ comprehensive.gitignore(dotnet + node + IDE) + initial commit
Open Questions
- (none remaining — all critical decisions made, ready for plan generation)
Scope Boundaries
- INCLUDE: Full backend API, frontend app, Docker Compose, Kubernetes manifests (Kustomize), database schema + EF Core migrations, Keycloak integration, work item CRUD, time-slot shift management with sign-up, club-switcher, role-based access control (4 roles), PostgreSQL RLS
- EXCLUDE: Billing/subscriptions, email/push notifications, mobile app, recurring shift patterns (future), custom roles, reporting/analytics dashboard