# Requirements: ClientHub v2.4 Post-vendita **Definiti:** 2026-08-08 (ricostruiti a posteriori — v2.4 è partita senza requisiti scritti) **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. Milestone precedente: [v2.3 Email & Accesso](milestones/v2.3-ROADMAP.md), shipped 2026-07-29. ## Consegnati ### Ciclo di vita dei servizi ricorrenti (Phase 13) — ✅ in produzione 2026-08-01 - [x] **RET-01**: Un'offerta ricorrente assegnata a un progetto ha uno stato (attivo / sospeso / cessato) e una data di fine opzionale - [x] **RET-02**: L'admin può sospendere, riattivare e cessare un retainer dalla tab Offerte del progetto - [x] **RET-03**: Il forecast a 12 mesi smette di sommare un retainer sospeso, cessato o oltre la sua `end_date` - [x] **RET-04**: Lo storico del venduto (`getOffersSoldBreakdown`) **non** filtra per stato — escludere le cessate riscriverebbe il passato - [x] **RET-05**: Il cliente vede stato, "attivo dal / fino al" e "canone mensile"; le offerte cessate non gli arrivano ### Anteprima admin e login (Phase 26) — ✅ in produzione 2026-08-08 - [x] **PREV-01**: L'admin può aprire il portale di un cliente in sola lettura senza passare dal gate OTP (`?preview=1` + sessione Auth.js valida) - [x] **PREV-02**: In anteprima approvazione e composer messaggi sono disattivati a livello di UI - [x] **AUTH-09**: Il campo password del login admin ha un toggle mostra/nascondi ## Backlog v2.4+ (non pianificati) Ereditati dalle chiusure di milestone precedenti, nessuno in corso: - [ ] **SEND-01 / SEND-02** — Invio del link `/preventivo/[slug]` via email dall'admin. Il mailer (`src/lib/mailer.ts`) è già pronto e in produzione dalla v2.3: manca solo il pulsante e l'action. *Rinviati il 2026-07-28.* - [ ] **PROP-03** — Stripe Payment Link sul deck pubblico del preventivo. *Rinviato al kickoff v2.3.* - [ ] **PROP-04** — Auto-provisioning di cliente / progetto / fasi al passaggio del lead a "Vinto". *Rinviato al kickoff v2.3.* - [ ] **RET-06** — Canoni mensili tracciabili (agosto pagato / settembre no). **Serve una tabella nuova**: `payments` è protetta dai vincoli di Data Safety e la sua riscalatura è pensata per i piani una tantum. *Fuori scope di Phase 13.* - [ ] **OFFER-14** — Sezioni analitiche stile Notion sull'offerta. *Rinviato al kickoff v2.1.* - [ ] **ARCH-01** — Split del modulo "compartimento stagno" in un deploy separato. *Solo se il modulo cresce.* - [ ] **DEBT-01** — Debito design: **~40 file, ~450 occorrenze** di palette Tailwind raw e hex literal al posto dei token semantici. I cluster: `/admin/projects/[id]` e i suoi tab (~182), `/admin/offers/[id]/edit` (~79), `/admin/clients/[id]` (~59), tutto `/quote/[token]` (~48, ed è rivolto al cliente), `ChatPanel` del portale (37), più `ui/dialog.tsx` che propaga il look vecchio a ogni modale. Esclusi perché legittimi: `AdminSidebar` (eccezione brand documentata), `src/lib/mailer.ts` (HTML email, niente CSS var), i colori di stato di `StatusBadge` (sanzionati dal design system, hanno già le varianti `dark:`). *Misurato il 2026-08-08 — la stima precedente di "11 pagine" era sottostimata.* - [ ] **DEBT-02** — Tabelle legacy `service_catalog` / `offer_services` / `offer_micro_services` come deadweight; `createService` / `serviceSchema` dead code in `src/app/admin/catalog/actions.ts`. ## Aperto, non un requisito **Whitelist del portale vuota per 3 clienti su 4.** La migration 0015 ha seedato solo `mario@test.it` (cliente di test). Protocollo Estetico, Caruso Speaker e Teckell hanno whitelist vuota e finché lo è **il loro portale non è accessibile**. Si popola da `/admin/clients/` → "Accessi al portale", poi va reinviato il link. ## Fuori scope - File hosting (vincolo LOCKED #5: i documenti restano URL esterni). - Tabella utenti / multi-admin: l'auth resta una singola credenziale da env.