Files
clienthub/.planning/REQUIREMENTS.md
T
simone d14f95c80d docs: verifica del giro 0020, e .env.local non è più utilizzabile
Cosa è stato verificato davvero: build e lint verdi, migration 0020
applicata a prod prima del push con la colonna riletta a conferma,
deploy atterrato (immagine taggata 44be190 = HEAD).

Cosa no, e ora è scritto: le pagine non sono state rese a runtime.
.env.local è scaduto su tre fronti — ADMIN_PASSWORD, NEXTAUTH_SECRET e
la password del DB — e l'host che dichiara (…:5432) è chiuso dal
firewall; il DB vero sta su 127.0.0.1:54321. Estrarre la password viva
dal container è bloccato dal classifier e non è stato aggirato. La nota
tecnica che dava per buone quelle credenziali diceva il falso.

Aggiunto come vedere se un deploy è atterrato: il tag dell'immagine in
docker ps è lo SHA del commit.

REQUIREMENTS: HUB-14 e HUB-15 registrati come fatti, HUB-16 apre la
verifica a mano che resta da fare, e il riallineamento di .env.local
entra fra le cose aperte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 13:05:39 +02:00

12 KiB
Raw Blame History

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, 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)

  • AUD-01: Schema additivo per audit, finding, ottimizzazioni, rubrica, esiti, run e visite — migration 0017_audits.sql, in prod 2026-08-18
  • AUD-02: La rubrica del motore (264 voci falsificabili) vive in checklist_items, non nel documento — in prod 2026-08-18
  • 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
  • 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
  • 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.

Modifiche hub (richieste 2026-08-18, in corso)

Fuori dalla milestone v2.5, che è in pausa. Piano in ~/.claude/plans/sei-arrivato-qua-search-recursive-kettle.md.

  • HUB-01: Via il tab Commenti dal progetto — /admin/conversazioni li aggrega già tutti con l'etichetta dell'entità. Perde solo la risposta sulla singola entità, che era già confluita sul thread generale.
  • HUB-02: Via il timer dalla lista progetti — si avvia dove c'è il contesto
  • HUB-03: Riepilogo soldi + avanzamento in testa al progetto, senza query nuove
  • HUB-04: Timer per fase e task — migration 0018, ON DELETE SET NULL perché le ore sopravvivono al task
  • HUB-05: Inbox in cima alla dashboard, con da-quanto-aspetta e contesto del messaggio
  • HUB-06: Analytics per linea di prodotto (Entry/Signature/Retainer) dalla tassonomia, con l'incassato non attribuibile mostrato a parte
  • HUB-07: Timeline delle consegne con semaforo ritardo/anticipo; scadenza dedotta da offerta + durata, projects.due_date come override
  • HUB-08: POST /api/webhooks/lead — un endpoint per form del sito e bridge, con dedup sull'email
  • HUB-09: Confermare la forma del payload Elementor con un invio vero — oggi è gestita in modo difensivo
  • HUB-10: LEAD_WEBHOOK_SECRET su Coolify — finché manca, la route risponde 403 a tutti
  • HUB-11: TidyCal. [BLOCCANTE] Niente webhook (loro FAQ): serve polling della REST API. Path e filtri stanno dietro il login → servono token o documentazione dall'utente
  • HUB-12: Alleggerire l'hub. Senza perimetro: si definisce guardando cosa è poco usato
  • HUB-13: Whop → progetto + audit automatico. Dipende dal motore v2.5 (AUD-06→11)
  • HUB-14: Rifiniture dall'uso reale del pannello — rinomina di un valore di tassonomia con propagazione alle fasi dei progetti, stato task "In revisione", tab pagamenti con ordine stabile e importi a mano, riordino task per trascinamento. In prod 2026-08-20, migration 0019.
  • HUB-15: Portale cliente — barra di avanzamento compatta e a tutta larghezza, card offerta senza accordion, "Valore dell'offerta" con override admin (project_offers.offer_value_override). In prod 2026-08-21, migration 0020. Serviva perché la somma dei prezzi di catalogo mostrava €20.250 su offerte vendute a 7.000 e 5.500.
  • HUB-16: Guardare a mano HUB-14 e HUB-15 in produzione — le scritture nuove (reorderTasks, updatePaymentField, clearPaymentOverride, updateOfferValueOverride) e il drag non sono mai state cliccate, e dal 2026-08-21 la verifica locale contro i dati veri non è più possibile

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

.env.local da riallineare a Coolify. ADMIN_PASSWORD, NEXTAUTH_SECRET e la password del DB sono stale, e l'host che il file dichiara (178.104.27.55:5432) è chiuso dal firewall — il DB vero è su 127.0.0.1:54321 dietro tunnel. Finché resta così una modifica al portale si verifica solo in produzione: build, migration e query di controllo, poi occhio umano sul sito. Recuperare la password viva dal container è bloccato dal classifier dei permessi e non va aggirato: la sblocca l'utente copiando le variabili da Coolify. Le migration non ne soffrono (docker exec non usa quelle credenziali).

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).