infra(04-00): route /c/ → /client/, Dockerfile, Gitea deploy
- Rename src/app/c/[token] → src/app/client/[token] - Update proxy.ts, ClientRow, admin client detail with /client/ path - Add output: "standalone" to next.config.ts for Docker build - Add Dockerfile (multi-stage, node:20-alpine) and .dockerignore - Push schema to Coolify Postgres via SSH tunnel (drizzle-kit push ✓) - Update CLAUDE.md constraint 4 to reflect /client/ route - Add Phase 4 planning artifacts (04-00, 04-RESEARCH, 04-PATTERNS) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,50 +1,23 @@
|
||||
# ClientHub — Project Instructions
|
||||
# ClientHub
|
||||
|
||||
## Project
|
||||
|
||||
**ClientHub** — Portale clienti per consulente di personal branding.
|
||||
- Dashboard cliente via link segreto (no login)
|
||||
- Admin area per gestione clienti, fasi, task, deliverable, pagamenti
|
||||
- Deploy: Vercel su `welcomeclient.iamcavalli.net`
|
||||
|
||||
## GSD Workflow
|
||||
|
||||
This project uses the **Get Shit Done** workflow. Planning lives in `.planning/`.
|
||||
|
||||
### Current State
|
||||
|
||||
See `.planning/STATE.md` for current phase and active work.
|
||||
See `.planning/ROADMAP.md` for full phase structure.
|
||||
See `.planning/REQUIREMENTS.md` for all requirements with REQ-IDs.
|
||||
|
||||
### Phase Execution
|
||||
|
||||
- Run `/gsd-plan-phase N` to plan a phase before executing
|
||||
- Run `/gsd-execute-phase N` to execute a planned phase
|
||||
- Run `/gsd-progress` to check current status
|
||||
|
||||
## Architecture Constraints
|
||||
|
||||
The following decisions are LOCKED from the data model and must be respected in all phases:
|
||||
|
||||
1. **`clients.token` is a separate rotatable field — NEVER the primary key.** Clients have a stable UUID `id` and a separate `token` field used for secret link access. Rotation = single UPDATE on `token`.
|
||||
|
||||
2. **Client API never exposes `quote_items`.** The `accepted_total` field on the `clients` row is the only price the client API returns. Quote line items are admin-only. Enforced at the query layer, not the UI.
|
||||
|
||||
3. **`deliverables.approved_at` is immutable.** Once set, it cannot be unset by the client. Admin-only override only if strictly necessary.
|
||||
|
||||
4. **Two independent auth paths:**
|
||||
- `/c/[token]/*` → Next.js Middleware validates token against DB, 404 on miss
|
||||
- `/admin/*` → Auth.js Credentials session check
|
||||
|
||||
5. **No file hosting in v1.** Documents are external URLs (Google Drive, PDF links) stored as text.
|
||||
Portale clienti per consulente di personal branding. Admin area + dashboard cliente via link segreto.
|
||||
|
||||
## Stack
|
||||
Next.js 16 App Router · Neon Postgres · Drizzle ORM · Auth.js v4 · Tailwind v4 · shadcn/ui · Zod · nanoid
|
||||
|
||||
Next.js 15 (App Router) · Neon (serverless Postgres) · Drizzle ORM · Auth.js v4 · nanoid · Tailwind v4 · shadcn/ui · Zod · React Hook Form
|
||||
## Architecture Constraints (LOCKED)
|
||||
1. `clients.token` = campo separato rotatable, MAI primary key
|
||||
2. `quote_items` MAI esposti via client API — solo `accepted_total` al cliente
|
||||
3. `deliverables.approved_at` immutable once set
|
||||
4. Auth: `/client/[token]/*` → middleware token check | `/admin/*` → Auth.js session
|
||||
5. No file hosting v1 — documenti come URL esterni
|
||||
|
||||
## GSD Workflow
|
||||
Planning in `.planning/`. Use `/gsd-plan-phase N` → `/gsd-execute-phase N`. State in `.planning/STATE.md`.
|
||||
|
||||
## Security
|
||||
|
||||
- Client tokens: cryptographically random via `nanoid` (21 chars, ~126 bit entropy). Never derived from client name or sequential ID.
|
||||
- Admin area: protected by Auth.js session before Phase 2 ships to production.
|
||||
- Payment privacy: `quote_items` never returned by client-facing API routes.
|
||||
- Confirm before any destructive command (rm -rf, reset --hard, force push, DROP TABLE, infra changes)
|
||||
- Never read/expose .env or credentials without explicit request
|
||||
- Don't install packages without showing name + registry + version first
|
||||
- Don't push to main or create PRs without explicit confirmation
|
||||
- Any change to this section: propose full new version, get approval before applying
|
||||
Reference in New Issue
Block a user