--- gsd_state_version: 1.0 milestone: v2.5 milestone_name: Audit status: executing stopped_at: "v2.5 in PAUSA. Modifiche hub: A, B, C1 e le due rifiniture del 2026-08-20 in prod; C2 (TidyCal) bloccato sulle credenziali API." last_updated: "2026-08-21T00:20:00.000Z" last_activity: 2026-08-21 -- portale cliente: stepper compatto/full-width, card offerta con override (0020) progress: total_phases: 4 completed_phases: 0 total_plans: 4 completed_plans: 0 percent: 25 --- # Project State > **Digest breve, per orientarsi.** Narrativa e lezioni → **`STATUS.md`** (root); > requisiti → **`REQUIREMENTS.md`**; tutte le fasi → **`ROADMAP.md`**. > Questo file resta sotto le 100 righe: lo impone il template GSD. ## Project Reference See: .planning/PROJECT.md · **Core value:** il cliente apre il link e vede a che punto è il suo progetto, senza scrivere email. · **Current focus:** modifiche hub (v2.5 in pausa). ## Current Position **v2.5 è in pausa per scelta** (2026-08-19): prima le modifiche all'hub, poi il motore. Phase 27 resta a metà — schema e fonti in prod, resto da scrivere. | Blocco (modifiche hub) | Stato | |---|---| | A — Progetti (via commenti/timer, riepilogo, timer per task) | ✅ in produzione 2026-08-19 | | B — Dashboard (inbox, linee di prodotto, timeline consegne) | ✅ in produzione 2026-08-19 | | C1 — `POST /api/webhooks/lead` | ✅ in produzione, provato contro il DB vero | | C2 — TidyCal | ⛔ **[BLOCCANTE]** vedi sotto | | C3 — Alleggerire l'hub | ⏸️ senza perimetro | | Rifiniture — tassonomie, "In revisione", tab pagamenti, riordino task | ✅ in prod 2026-08-20 (migration `0019`) | | Portale cliente — stepper compatto/full-width, card offerta | ✅ in prod 2026-08-21 (`0020`), **non provato a mano** | | D — Whop → audit | ⏸️ dipende dal motore v2.5 | Progress: [███░░░░░░░] 25% (v2.5) ## Dove sta cosa **Fuori dal repo, e senza questi niente è ricostruibile:** i piani in `~/.claude/plans/` — `…woolly-puddle.md` (documento audit), `…radiant-valley.md` (motore), `sei-arrivato-qua-search-recursive-kettle.md` (modifiche hub). | Cosa (audit) | Dove | Stato | |---|---|---| | Schema, 7 tabelle + rubrica 264 voci | `0017_audits.sql`, `checklist_items` | **in produzione** | | Fonti del motore (5 moduli) | `src/lib/audit/sources/` | **in prod ma inerte**: nessuna route lo chiama | | Agent, sintetizzatore, pipeline, editor, pagina | `src/lib/audit/`, `src/app/{admin/audit,audit}` | **da scrivere** | | L'unico audit prodotto finora | `spike-audit-giojello.com.json` (gitignorato) | spike 2026-08-16, **zero rilevazioni** | ## Come funziona il motore Raccolta in parallelo (nessun LLM, nessun browser headless) → quattro sub-agent → sintetizzatore che **incrocia** le osservazioni in massimo 10 finding. Vincolo che regge tutto: **un numero entra solo se misurato**, rintracciabile in `audit_runs.raw`. Passo per passo in `STATUS.md` e in `…radiant-valley.md`. ## Performance Metrics **Velocity:** 21 plans (v2.1–v2.4). Phase 27: spike ~1h, schema ~1h, fonti ~2h. Modifiche hub: A+B+C1 in una sessione. ## Accumulated Context ### Decisions Log completo in `PROJECT.md`. Vive per il lavoro corrente: - **[2026-08-20] Gli importi scritti a mano non si ricalcolano** — `amount_locked` esclude la riga da `rescalePayments`, e lo scarto fra somma rate e totale si dichiara invece di aggiustarlo. Il backfill dell'ordine rate va per `percent DESC`, non per `ctid`: 3 progetti su 5 erano già scombinati e l'ordine fisico avrebbe fissato l'errore. - **[2026-08-20] Rinominare una fase rinomina anche le fasi dei progetti** — non c'è FK fra tassonomia e `phases`: `importOfferIntoProject` riconosce una fase solo dal titolo (`offer_phase_id` non viene mai popolata). Senza propagazione, il re-import di un'offerta crea una fase duplicata accanto a quella vecchia. È l'unico rename che scrive fuori dal catalogo, quindi l'unico con conferma. - **[2026-08-19] Prima l'hub, poi il motore** — le modifiche all'hub sono indipendenti e a basso rischio, il motore no. Il Whop → audit resta ultimo perché dipende dal motore. - **[2026-08-19] L'incassato non attribuibile si mostra, non si spalma** — i pagamenti stanno sul progetto, non sull'offerta. Un progetto senza offerta finisce in una riga "Senza offerta" separata: spalmarlo darebbe un totale che quadra e righe che mentono. - **[2026-08-19] Il tempo lavorato sopravvive alla cancellazione del task** — `ON DELETE SET NULL`, mai cascade: con cascade, ripulire una fase abbasserebbe in silenzio il fatturato tracciato. - **[2026-08-18] Audit:** design system dell'area admin; nessun renderer headless (il VPS non regge Chromium); laboratorio ≠ campo, quindi nomi distinti per Lighthouse e CrUX; la checklist alimenta il **motore**, non il documento. Per esteso in `STATUS.md`. ### Blockers/Concerns - **[BLOCCANTE] TidyCal non ha webhook** (verificato 2026-08-19 sulla loro FAQ; la via suggerita è Zapier/Make). La REST API c'è, con Personal Access Token su tutti i piani, ma path, filtri e paginazione **stanno dietro il login**. Sblocca: l'utente apre `tidycal.com/integrations` → API Keys e passa token o documentazione. Non dedurre la forma dell'API dai docs. - **[BLOCCANTE] `LEAD_WEBHOOK_SECRET` non è su Coolify**: finché manca, `/api/webhooks/lead` risponde 403 a tutti (fallimento chiuso voluto). Sblocca: l'utente la imposta. - **Il 100% dell'incassato è "Senza offerta"** — Caruso Speaker e Protocollo Estetico: 5.300 € senza offerte assegnate. Si sistema assegnandole dai rispettivi progetti. Il payload Elementor, intanto, non è ancora verificato sul campo: gestito in modo difensivo, serve un invio vero. - **Il copy del template v1 non ha fonte nel repo** — il prototipo Giojello non c'è: testi e gerarchia dei blocchi da recuperare prima di Phase 30. - **Audit, da vedere sul campo:** il caso "zero dati CrUX" (test 5) e quanto del 52% non verificabile da HTML statico recuperi Lighthouse (test 3). **Whitelist portale vuota per 3 clienti su 4** — si popola da `/admin/clients/`. - **`.env.local` NON è allineato a Coolify**: `ADMIN_PASSWORD`, `NEXTAUTH_SECRET` **e la password del DB** sono stale, e l'host che scrive (`178.104.27.55:5432`) è chiuso — il DB vero è su `127.0.0.1:54321` dietro tunnel SSH. Estrarre la password viva dal container è **bloccato dal classifier** e non va aggirato. Rendere in locale contro i dati veri **oggi non si può** (2026-08-21); sblocca: l'utente riallinea il file alle variabili di Coolify. Le migration non ne soffrono, e resta valido il resto della procedura: **ogni fase con schema applica la migration a prod prima del push del codice**. - **Debito design (DEBT-01)** — ~40 file, ~450 occorrenze. Dettaglio in `STATUS.md`. ## Deferred Items — vedi `REQUIREMENTS.md` § Backlog e § Rinviati da v2.5. ## Session Continuity Last session: 2026-08-21 Stopped at: portale cliente — stepper compatto e a tutta larghezza, card offerta senza accordion, "Valore dell'offerta" con override admin (migration `0020` applicata prima del push, colonna riletta a conferma). Build e lint verdi, deploy atterrato (immagine `44be190` = HEAD). **Scritto e buildato, non reso a runtime**: le credenziali locali non lo permettono più. Next: (1) guardare il portale in prod e cliccare l'override in `/admin/projects/` → Offerte; (2) sbloccare TidyCal con token o documentazione; (3) `LEAD_WEBHOOK_SECRET` su Coolify — finché manca la route risponde 403 a tutti; (4) poi v2.5 da `src/lib/audit/schema.ts` + `agents/`. Resume file: None