Files
clienthub/.planning/REQUIREMENTS.md
T
simone 8000d562dc docs: apre v2.5 "Audit" e rimette in pari roadmap e requisiti
La roadmap era ferma al 2026-08-08 e diceva ancora "nessuna fase aperta" mentre
v2.5 era gia' partita e Phase 27 era a meta'; REQUIREMENTS.md era ancora quello
di v2.4. STATE.md invece era corretto — segno che aggiornare solo quello non
basta. Da qui la divisione dei ruoli, ora esplicita in testa a ogni file:

- STATE.md        orientamento breve (99 righe): dove sta cosa, come funziona il
                  motore, i blocchi vivi. Niente narrativa.
- ROADMAP.md      tutte le fasi 1->30, con lo stato di ciascuna
- REQUIREMENTS.md i 25 requisiti di v2.5 (AUD-01..25) e il backlog
- STATUS.md       l'unica narrativa lunga: lezioni e note tecniche

v2.4 chiusa e archiviata in milestones/v2.4-REQUIREMENTS.md.

Decisione nuova: il documento di restituzione usa il design system dell'area
admin ("Quiet Luxury"), non una tipografia sua — token semantici, Plus Jakarta
Sans, Geist Mono per metriche e date, StatusBadge per gli impatti. Sostituisce
la deroga tipografica prevista dal piano. I font sono gia' self-hostati da
next/font/google, quindi la CSP font-src 'self' e' soddisfatta senza lavoro, e
il documento non aggiunge debito a DEBT-01 perche' nasce gia' a token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 17:48:46 +02:00

98 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Requirements: ClientHub v2.5 Audit
**Definiti:** 2026-08-16 (piano approvato) · **rivisti:** 2026-08-18 (motore)
**Core Value della milestone:** L'imprenditore paga un'analisi del suo sito e riceve un
documento che gli dice, con numeri misurati, cosa non funziona e cosa costa — non un
elenco di quaranta punti generato da un tool gratuito.
Milestone precedente: [v2.4 Post-vendita](milestones/v2.4-REQUIREMENTS.md), chiusa 2026-08-08.
Piani di riferimento (fuori dal repo, in `~/.claude/plans/`):
`dovremmo-fare-una-cosa-woolly-puddle.md` (documento, editor, template) +
`vorrei-solo-farti-capire-radiant-valley.md` (motore — sostituisce §6/§7 del primo).
## Il prodotto
Tre livelli venduti, che sono **configurazioni di un unico documento**, non tre documenti:
| Livello | Blocchi inclusi |
|---|---|
| **Radiografia** | 1, 2, 2b, 3, 4, 5, 8, 9 |
| **Prima/Dopo** | + 6 (il redesign), 6b (cosa il redesign non risolve) |
| **Rotta** | + 7 (le ottimizzazioni, con priorità e impegno in giornate) |
I blocchi non pertinenti **non esistono nel DOM**, non sono nascosti via CSS.
## Requisiti
### Motore (Phase 27)
- [x] **AUD-01**: Schema additivo per audit, finding, ottimizzazioni, rubrica, esiti, run e visite — *migration `0017_audits.sql`, in prod 2026-08-18*
- [x] **AUD-02**: La rubrica del motore (264 voci falsificabili) vive in `checklist_items`, non nel documento — *in prod 2026-08-18*
- [x] **AUD-03**: Le fonti raccolgono **rilevazioni, non stime**: PageSpeed (153 audit sul DOM renderizzato), CrUX (utenti reali), Wayback, RDAP, robots/sitemap/JSON-LD, header — *`src/lib/audit/sources/`, provato sul campo 2026-08-18, non ancora pushato*
- [x] **AUD-04**: Ogni fonte fallisce in modo **non fatale** e dice *perché*: "non ha risposto" e "ha risposto che non ci sono dati" sono informazioni diverse
- [x] **AUD-05**: Quando CrUX non ha dati di campo il documento lo **dice** ("i visitatori non sono abbastanza numerosi perché Google raccolga dati"), non lascia un buco — *`nota` in `crux.ts`; il caso "zero dati" resta da vedere su un sito vero*
- [ ] **AUD-06**: Ogni output di modello è validato con Zod, `safeParse`, fallimento duro — nessun loop di riparazione (precedente: `src/lib/proposal/schema.ts`)
- [ ] **AUD-07**: Quattro sub-agent in parallelo (checklist, visivo, storico, tecnico) più un sintetizzatore che **incrocia** le loro osservazioni in un solo finding con più evidenze indipendenti
- [ ] **AUD-08**: Massimo **10 finding**, ordinati per impatto su tre soli valori (`alto|medio|basso`); la sfumatura sta nell'ordine dentro il gruppo
- [ ] **AUD-09**: Disciplina sui numeri imposta nel prompt di sistema — un numero entra nel documento solo se misurato, e ogni numero consegnato è rintracciabile in `audit_runs.raw`
- [ ] **AUD-10**: Fan-out con tetto di concorrenza e retry con backoff sulle 429/529 di Anthropic
- [ ] **AUD-11**: Heartbeat a ogni passo su `audit_runs`; una run senza battito va in `error` e "Rilancia" riparte dall'ultimo passo completato *(un redeploy Coolify uccide un job in corso)*
### Storage immagini (Phase 28)
- [ ] **AUD-12**: Volume persistente Coolify su `/app/uploads`, lettura da `/api/uploads/[...path]` con guardia sul path traversal, whitelist MIME e limite di dimensione
- [ ] **AUD-13**: Due immagini caricate a mano per audit (hero **prima** e **dopo** del redesign, JPG ≤ 512 KB); due scritte dalla pipeline (screenshot mobile e desktop da PageSpeed)
### Editor admin (Phase 29)
- [ ] **AUD-14**: Creazione **manuale** di un audit (livello, profilo, URL, cliente/lead). L'ingresso Whop è predisposto nello schema (`origin`, `external_ref`) ma **non costruito**
- [ ] **AUD-15**: Editor a payload intero (modello: `admin/offers/actions.ts`) che **salva sempre, anche a metà** — tutti i campi di contenuto sono nullable, la validazione di completezza scatta solo alla consegna
- [ ] **AUD-16**: Riordino di finding e ottimizzazioni con `@dnd-kit/sortable`, con re-sync degli id dei figli
- [ ] **AUD-17**: Il **blocco 8 (La direzione) resta manuale, foglio bianco** — è il blocco che giustifica il prezzo; se diventa formula il cliente lo sente
- [ ] **AUD-18**: Il registro delle visite è visibile nell'editor, in ordine cronologico
### Documento pubblico (Phase 30)
- [ ] **AUD-19**: `/audit/[slug]` — pagina privata, `X-Robots-Tag: noindex, nofollow`, rate limit sul matcher di `proxy.ts`
- [ ] **AUD-20**: Il template è **congelato alla creazione** (`template_version`): migliorare il documento tocca gli audit successivi, mai quelli già consegnati
- [ ] **AUD-21**: PDF via **print CSS**, non libreria: interruzioni di pagina corrette, slider impilato in due immagini, **nessun marcatore di lavorazione sopravvissuto**
- [ ] **AUD-22**: In **scala di grigi** impatti e metriche restano distinguibili — il colore non può essere l'unico portatore di informazione
- [ ] **AUD-23**: Il documento usa **il design system dell'area admin** ("Quiet Luxury", `design-reference/DESIGN-SYSTEM.md`): token semantici, Plus Jakarta Sans per il testo, **Geist Mono per metriche, punteggi e date**, e i primitivi già esistenti (`StatusBadge` per gli impatti). *Decisione del 2026-08-18, sostituisce la deroga tipografica prevista dal piano.* Due conseguenze: i font sono già self-hostati da `next/font/google`, quindi la CSP `font-src 'self'` è soddisfatta senza lavoro; e il documento **non aggiunge debito a DEBT-01** perché nasce già a token.
- [ ] **AUD-24**: Tracciamento delle aperture (`view`) e delle stampe (`print`) via isola client + Server Action; **un admin loggato non viene contato** (altrimenti i numeri li inquiniamo noi rileggendo le bozze)
- [ ] **AUD-25**: L'IP non si salva in chiaro — SHA-256 di `ip + NEXTAUTH_SECRET`, come il digest del gate admin
## Vincoli che questa milestone tocca
- **LOCKED #5 (no file hosting)** — emendato limitatamente agli asset di audit, deroga già annotata in `CLAUDE.md`. Non estendere ad altre entità.
- **Nessun renderer headless, da nessuna parte.** Il VPS non regge Chromium (RAM), e non serve: gli audit Lighthouse arrivano già fatti sul DOM renderizzato.
## Backlog (ereditato, nessuno in corso)
- [ ] **SEND-01 / SEND-02** — Invio del link `/preventivo/[slug]` via email. Il mailer è già in produzione dalla v2.3: manca il pulsante e l'action. *Rinviati il 2026-07-28.*
- [ ] **PROP-03** — Stripe Payment Link sul deck pubblico del preventivo.
- [ ] **PROP-04** — Auto-provisioning cliente / progetto / fasi al passaggio del lead a "Vinto".
- [ ] **RET-06** — Canoni mensili tracciabili. **Serve una tabella nuova**: `payments` è protetta dai vincoli di Data Safety.
- [ ] **OFFER-14** — Sezioni analitiche stile Notion sull'offerta.
- [ ] **ARCH-01** — Split del modulo "compartimento stagno" in un deploy separato. *Solo se cresce.*
- [ ] **DEBT-01** — Debito design: ~40 file, ~450 occorrenze di palette raw/hex al posto dei token. Cluster in `/admin/projects/[id]` (~182), `/admin/offers/[id]/edit` (~79), `/admin/clients/[id]` (~59), `/quote/[token]` (~48, ed è rivolto al cliente), `ChatPanel` (37), `ui/dialog.tsx`. *Misurato il 2026-08-08.*
- [ ] **DEBT-02** — Tabelle legacy `service_catalog` / `offer_services` / `offer_micro_services`; `createService` / `serviceSchema` dead code.
## Rinviati esplicitamente da v2.5
- **Allegato tecnico** — seconda vista sugli stessi finding con registro da sviluppatore (selettori, file, stime). Renderebbe vera la promessa del blocco 9 *"il documento resta tuo e puoi darlo a chiunque lavorerà sul sito"*. Da valutare **dopo il primo audit consegnato**.
- **Affettare lo screenshot a pagina intera** — richiede `sharp`, da verificare su `node:20-alpine`. Non serve in fase 1: `final-screenshot` (250×498) è leggibile.
- **Ingresso via webhook Whop** — schema predisposto, costruzione in fase 2.
## Aperto, non un requisito
**Whitelist del portale vuota per 3 clienti su 4.** La migration 0015 ha seedato solo
`mario@test.it`. Protocollo Estetico, Caruso Speaker e Teckell hanno whitelist vuota e
finché lo è **il loro portale non è accessibile**. Si popola da `/admin/clients/<id>`
"Accessi al portale", poi va reinviato il link.
## Fuori scope
- Tabella utenti / multi-admin: l'auth resta una singola credenziale da env.
- File hosting per i documenti del portale cliente: restano URL esterni (LOCKED #5, non emendato per quelli).