Files
clienthub/CLAUDE.md
T

2.6 KiB

ClientHub

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

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.

Data Safety (LOCKED)

  • Any migration, refactor, or deploy MUST NOT delete or truncate clients, projects, payments, or phases rows
  • Before running any migration: verify it only adds columns/tables — never drops or truncates production data
  • Confirm explicitly before any schema change that removes a column or table used by these entities

Deploy & DB Access (procedure)

  • Environments: local → Gitea (remote is named gitea, NOT origin) → Coolify (prod, auto-deploys on push to main)
  • Prod Postgres is NOT publicly exposed. Claude has working key-based SSH to root@178.104.27.55 and applies migrations directly via docker exec — no SSH tunnel needed from the user: cat src/db/migrations/NNNN.sql | ssh root@178.104.27.55 "docker exec -i xwkk0040w0kk0gsgcgog8owk psql -U clienthub -d clienthub -v ON_ERROR_STOP=1 --single-transaction" (container = xwkk0040w0kk0gsgcgog8owk, db/user = clienthub; if the container hash changes, find it by scanning docker ps for the one whose db has the payments table). A tunnel -L 54321:localhost:54321 is only needed to point local tooling at prod.
  • Migrations are hand-written SQL in src/db/migrations/ (drizzle-kit generate is broken).
  • Ordering: apply an additive migration to prod BEFORE pushing the schema-dependent code, so the live portal never queries a missing column.

Security

  • Confirm before any destructive command (rm -rf, reset --hard, force push, DROP TABLE / drop-column, truncate, infra changes)
  • Never print .env contents or credentials in plaintext output; using them internally to connect is fine
  • Don't install packages without showing name + registry + version first
  • Pushing to main is allowed automatically (standard local → Gitea → Coolify flow); never force-push to main
  • Any change to this section: propose full new version, get approval before applying