# ClientHub — Gestione Clienti & Dashboard

## What This Is

Suite operativa per un consulente di personal branding, live su hub.iamcavalli.net (Coolify/Hetzner): un'area admin (`/admin/*`) per gestire clienti, progetti, offerte, preventivi e CRM, e una dashboard cliente via link segreto (`/client/[token]`) dove ogni cliente vede lo stato del suo progetto. Con la v2.2 ("Sales Loop") il focus è diventato il loop commerciale completo: lead in pipeline Kanban → transcript datati delle call → agente AI (Claude Opus 4.8) genera preventivo personalizzato leggendo transcript + offerta → deck pubblico 20+ slide navigabile a `/preventivo/[slug]` → cliente accetta tier A/B/C → vinto/perso nel CRM.

## Core Value

Il cliente apre il link e vede esattamente a che punto è il suo progetto, cosa deve ancora succedere e cosa ha già approvato — senza dover scrivere email per chiedere aggiornamenti.

## Current Milestone: v2.3 Email & Accesso

**Goal:** Aggiungere uno strato email all'app — OTP gate per il portale cliente e invio link preventivo dall'admin — con un'unica integrazione Resend condivisa.

**Target features:**
- AUTH-OTP-01 — OTP gate portale cliente (whitelist email + sessione 30gg + admin UI)
- PUB-03 — Invio link `/preventivo/[slug]` via email Resend dall'admin

**Backlog v2.4+:** PROP-03 (Stripe Payment Link), PROP-04 (auto-provisioning al "Vinto"), Phase 13 (servizi ricorrenti)

## Requirements

### Validated

Shipped in v1.0 (Phases 1–6, in produzione su hub.iamcavalli.net):

- ✓ Ogni cliente ha un URL segreto univoco, nessun login (token rotatable + slug opzionale) — Phase 1/4
- ✓ Dashboard cliente: brand, brief, fasi/task con stato, progress, multi-progetto — Phase 1/4
- ✓ Il cliente approva deliverable (approved_at immutabile) e lascia commenti — Phase 2
- ✓ Il cliente vede solo il totale accettato, mai i prezzi dei singoli servizi — Phase 2/3
- ✓ Stato pagamenti acconto/saldo visibile al cliente — Phase 1
- ✓ Link a documenti esterni + storico note/decisioni — Phase 1/2
- ✓ Area admin completa: clienti, progetti, fasi, task, pagamenti, documenti — Phase 2/4
- ✓ Catalogo servizi + quote builder admin (quote_items mai esposti al cliente) — Phase 3
- ✓ Sistema offerte: macro/micro/servizi, assegnazione a progetti, forecast 12 mesi — Phase 5
- ✓ Offerte attive visibili nella dashboard cliente (solo public_name) — Phase 5
- ✓ UX admin: sidebar + dashboard operativa con KPI e activity feed — Phase 6

Shipped in v2.0 (Phases 7–10, in produzione su hub.iamcavalli.net):

- ✓ Catalogo servizi unificato (tabella `services`) usato dal quote builder — Phase 7 (legacy `service_catalog`/`offer_services` ancora presenti, consolidamento finale spostato in v2.1)
- ✓ Offerte con fasi ordinate (`offer_phases`/`offer_phase_services`) e builder preventivo admin — Phase 8
- ✓ Preventivo pubblico `/quote/[token]`: stati draft→sent→viewed→accepted/rejected, `accepted_at` immutabile, raccolta email/note cliente — Phase 9
- ✓ CRM pipeline lead: stati, activity log, reminder follow-up in dashboard — Phase 10

Validated in v2.1 (consegnato, in prod):

- ✓ Catalogo `services` come vista database (inline edit, tag multi-select, quick-add, ricerca istantanea) + consolidamento legacy — Phase 11 (OFFER-07..10, OFFER-13)
- ✓ Offer Editor: lista filtrabile/archiviabile + 3 tier A/B/C via matrice checkbox, totale live, prezzo pubblico manuale, tag 4-dimensioni, promessa di trasformazione — Phase 12 (OFFER-11, OFFER-15..18). 55 servizi reali + tag offerta caricati.
- ✓ CRM custom Attio-style: `/admin/leads` ridisegnata come tabella inline-edit (status, next_action, ecc.) + tag multi-select con creazione al volo; FollowUpWidget interamente in italiano; `LeadForm` tipizzato senza `useForm<any>`; `SendQuoteModal`/`assignQuoteToLead` senza rami di codice irraggiungibili — Phase 14 (CRM-08, CRM-09, CRM-10, CRM-11, CRM-12)

Validated in v2.2 Sales Loop (shipped 2026-06-20):

- ✓ Cleanup: Forecast + quote builder manuale rimossi; analytics fuse in Dashboard — Phase 18 (CLEAN-01..04)
- ✓ Pipeline CRM Kanban 6 colonne con drag-drop; toggle Lista/Kanban; vinto/perso come cambio-colonna — Phase 19 (PIPE-01, PIPE-02)
- ✓ Knowledge Base transcript: `client_transcripts` in prod; UI incolla/elenca nel dettaglio lead — Phase 20 (KB-01, KB-02)
- ✓ Agente AI: Claude Opus 4.8, Zod schema 20+ sezioni, snapshot JSONB proposals, form admin — Phase 21 (AI-01, AI-02)
- ✓ Deck pubblico `/preventivo/[slug]`: 20+ slide 100vh, keyboard nav; accept/reject `accepted_at` immutabile — Phase 22 (PUB-01, PUB-02)

### Active — v2.3

- [ ] AUTH-OTP-01 — Accesso cliente via OTP email: whitelist `client_emails`, gate `/client/[token]/*`, sessione 30gg, admin whitelist UI
- [ ] PUB-03 — Invia link `/preventivo/[slug]` via email Resend dall'admin

### Out of Scope

- Fatturazione e invio fatture — la gestione contabile resta fuori, solo stato pagamenti
- App mobile nativa — solo web responsive
- Multi-utente con team — solo tu come admin per ora
- Prezzi singoli visibili al cliente — vede solo il totale accettato
- File hosting — documenti solo come URL esterni (v1 constraint, ancora valido)
- Sezioni analitiche stile Notion (psicologia, rating, performance) — fuori v2.1, eventuale milestone futura
- Deploy separati per modulo (architettura OMC multi-app) — non finché un modulo non cresce abbastanza da giustificarlo

## Context

- Produzione: hub.iamcavalli.net su Coolify (Hetzner), Postgres self-hosted, deploy via webhook Gitea (NON Vercel)
- Stack: Next.js 16 App Router, Drizzle ORM, Auth.js v4 (admin), token middleware (clienti), Tailwind v4, shadcn/ui, `@dnd-kit` già in deps
- Tutto sotto la stessa app: `/admin/*` (sessione Auth.js) + `/client/[token]/*` (token) + `/preventivo/[slug]` (pubblico)
- La sidebar admin include: Dashboard, Leads (con toggle Lista/Kanban), Offerte, Catalogo, Preventivi (con CTA globale "Genera preventivo")
- Stack v2.2: `@anthropic-ai/sdk@0.105.0` (Claude Opus 4.8), `@dnd-kit` (Kanban), `nanoid` (slug proposals)
- DB live: 10 migrazioni applicate a prod (0000–0010); `proposals` table con `content jsonb` snapshot; `client_transcripts` per lead
- Migrations sono manuali: SSH tunnel → `node` script PRIMA di pushare codice schema-dipendente; `drizzle-kit generate` rotto da Phase 8
- `ANTHROPIC_API_KEY` in Coolify — aggiunta 2026-06-20 via PHP artisan; costo ~$0.44/preventivo (Opus 4.8)
- Il flusso commerciale reale: call con lead → transcript incollato → genera preventivo AI → deck pubblica → cliente sceglie tier → vinto/perso

## Constraints

- **Data Safety (LOCKED)**: migration solo additive su `clients`, `projects`, `payments`, `phases` — qualsiasi consolidamento di catalogo va pianificato senza drop/truncate
- **Architettura (LOCKED)**: `clients.token` separato e rotatable; `quote_items` mai esposti via client API; `deliverables.approved_at` immutabile; no file hosting
- **Compartimenti stagni**: un'unica app Next.js, moduli isolati (route group + service layer propri) su Postgres condiviso; migrations solo additive; niente deploy separati per ora (modello OMC adattato)
- **NO database esterno / Excel come fonte dati**: Postgres resta l'unica fonte di verità — il problema è la UX, non il dato
- **Numerazione fasi**: v2.0 ha chiuso a Phase 10; v2.1 parte da Phase 11

## Key Decisions

| Decision | Rationale | Outcome |
| --- | --- | --- |
| Link segreto senza login per i clienti | Massima semplicità — nessun account da creare, zero friction | ✓ Good |
| Dashboard prima del flusso Claude | Clienti attivi ora, la visibilità al cliente è il valore immediato | ✓ Good |
| Preventivo: cliente vede solo il totale | Il dettaglio dei prezzi è informazione commerciale riservata | ✓ Good |
| Suite unica sotto /admin/* invece di 3 app separate | Stesso DB, stesso deploy, auth unica — overhead di 3 app ingiustificato per singolo admin | ✓ Confermato — formalizzato come "compartimenti stagni" (2026-06-12) |
| Catalogo servizi unificato (una tabella `services`) | Due cataloghi paralleli (service_catalog + offer_services) duplicano manutenzione prezzi | ✓ Good — tabella `services` live da Phase 7, consolidamento legacy in v2.1 |
| Tier offerte indipendenti (A/B/C separati, stesso tag) | Più semplice di un meccanismo di ereditarietà; ogni tier configurato a sé | ✓ Good — usato in deck slide Pricing/StagesRecap/Comparison |
| Prezzi pacchetti per-preventivo, non da catalogo | Permette di alzare i prezzi nel tempo senza toccare il catalogo | ✓ Good — `public_price` per tier, snapshot in `proposals.content` |
| Al "Vinto" le fasi dell'offerta sono COPIATE nel progetto | Il progetto resta modificabile senza toccare il template offerta | — Pending (PROP-04, backlog v2.3) |
| NO DB esterno/Excel, Postgres unica fonte | Lezione 2026-06-11: due fonti disallineate hanno causato il crash Phase 10 | ✓ Good |
| Catalogo/Offerte UX = database view custom (non Notion-clone) | Notion troppo complesso per v1; serve velocità, non sezioni analitiche | ✓ Good — confermato in v2.1 |
| Tab "Preventivo" rimossa, "Offerte" → "Servizi attivi" | Preventivo Builder è l'unico flusso; `accepted_total` già coperto da Payments | ✓ Confermato — zero perdita funzionale verificata (2026-06-13) |
| Ordine: Offer Studio (UX dato) prima, Proposal AI (AI) dopo | L'AI è l'ultimo miglio, serve un dato pulito e veloce da gestire prima | ✓ Good — strategia validata: catalogo+offerte puliti → AI in v2.2 |
| Output AI = JSON strutturato Zod → template fisso | Coerenza visiva garantita; zero rischio HTML rotto dall'AI | ✓ Good — 20+ sezioni Zod validate, deck sempre coerente |
| `proposals.content` = JSONB snapshot immutabile | Prezzi e profilo consulente "bloccati" al momento della generazione | ✓ Good — invariante di audit, coerente con `accepted_at` |
| Email Resend (PUB-03) deferred | Scope minimo funziona; link condiviso manualmente per ora | — Pending (v2.3 candidato #1) |

## Evolution

This document evolves at phase transitions and milestone boundaries.

**After each phase transition** (via `/gsd-transition`):
1. Requirements invalidated? → Move to Out of Scope with reason
2. Requirements validated? → Move to Validated with phase reference
3. New requirements emerged? → Add to Active
4. Decisions to log? → Add to Key Decisions
5. "What This Is" still accurate? → Update if drifted

**After each milestone** (via `/gsd-complete-milestone`):
1. Full review of all sections
2. Core Value check — still the right priority?
3. Audit Out of Scope — reasons still valid?
4. Update Context with current state

---
*Last updated: 2026-06-21 — v2.3 milestone started: Email & Accesso (AUTH-OTP-01 + PUB-03)*
