Files
clienthub/.planning/STATE.md
T
simone 9ce6f02ee4 fix(conversazioni): il menu dei tag mostra una riga per persona, non per alias
Con un cliente «Gian Luca Caruso / Caruso Speaker» il menu proponeva tre voci
per un destinatario solo. Non era un difetto di resa: al menu era stata passata
la stessa lista che il parser usa per RICONOSCERE un tag rileggendo il testo.

Sono due domande diverse, e il codice le aveva confuse:
  - come lo si puo' scrivere -> tutti gli alias, invisibili, solo in lettura
  - chi si puo' scegliere    -> una riga per destinatario

`MentionTarget` le separa: `label` per il menu, `aliases` per la rilettura.
Scrivere «@Gian» a mano continua a valere come tag e a far partire la mail --
cambia solo cosa viene offerto, non cosa viene accettato.

Il filtro del menu ora passa da `normalizeForSearch`, la stessa
normalizzazione del parser: con un toLowerCase() a parte, digitare «nicolo»
non avrebbe trovato «Nicolò» nel menu mentre nel messaggio sarebbe stato
riconosciuto -- due regole per la stessa domanda, e la seconda si scopre solo
quando la mail non parte.

Il difetto scalava peggio del valore: con tre contatti per cliente sarebbero
diventate nove righe. `mentionTargets()` ritorna gia' un array per questo, ma
il tag per singola persona resta impossibile finche' `client_emails` ha gli
indirizzi e non i nomi: serve una migration, ed e' un lavoro a se'.

Verificato: build e lint puliti, 23 test su parser e menu. Mai visto a schermo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 11:22:38 +02:00

12 KiB


gsd_state_version: 1.0 milestone: v2.5 milestone_name: Audit status: executing stopped_at: "v2.5 in PAUSA. Modifiche hub: A, B, C1, rifiniture, chat a canali (0021), modifica messaggi + firma (0022), stati task e date pagamenti (0023) in prod; C2 (TidyCal) bloccato sulle credenziali API. Conversazioni (scrittura per primo, menzioni, mail sul tag) pushata il 2026-09-01, nessuna migration, MAI provata a mano. Nulla del portale e' stato visto a schermo: .env.local non autentica piu', serve ?preview=1 in prod. Il riquadro 'Prossimo pagamento' non compare finche' nessuna rata ha una due_date." last_updated: "2026-09-01T00:15:00.000Z" last_activity: 2026-09-01 -- conversazioni: scrivere per primo, menzioni, mail sul tag. Pushata dopo aver recuperato l'accesso a gitea dalla CLI admin 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, tab pagamenti, riordino task in prod 2026-08-20 (0019)
Portale cliente — stepper compatto/full-width, card offerta in prod 2026-08-21 (0020); override provato su Caruso Speaker
Chat — canali, modifica messaggi, firma admin in prod 2026-08-21 (0021, 0022); mai provata a mano; manca l'attribuzione
Conversazioni — scrivere per primo, menzioni @Nome, mail sul tag pushata 2026-09-01 (41530b5), nessuna migration. Menu dei tag corretto lo stesso giorno: mostrava una riga per alias invece che per persona. Build + lint puliti, 23 test sul parser e sul menu; nessuna mail di tag mai partita davvero
Portale — stati task (forma, pill, legenda, «Cancellata») + date dei pagamenti in prod 2026-08-22 (2e9bd2a, 8b54f48, fe76789, migration 0023); mai visto a schermo, nessuna due_date ancora inserita
D — Whop → audit ⏸️ dipende dal motore v2.5

Progress: [███░░░░░░░] 25% (v2.5)

Dove sta cosa

I piani della milestone sono nel repo dal 2026-08-26: .claude/plans/v2.5-*.md.

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 .claude/plans/v2.5-audit-motore.md.

Accumulated Context

Decisions

Log completo in PROJECT.md. Vive per il lavoro corrente:

  • [2026-09-01] Una lista che serve a leggere non è una lista da offrire in scrittura — il menu dei tag mostrava tre voci (nome, brand, nome di battesimo) per una persona sola, perché gli era stata passata la stessa lista che il parser usa per riconoscere un tag nel testo. Sono due domande diverse: come lo si può scrivere (tutti gli alias, invisibili) e chi si può scegliere (una riga per destinatario). Ora MentionTarget le tiene separate — label per il menu, aliases per la rilettura — e il filtro passa da normalizeForSearch, la stessa normalizzazione del parser: con un toLowerCase() a parte, digitare «nicolo» non troverebbe «Nicolò» nel menu mentre nel messaggio verrebbe riconosciuto. Il difetto scalava peggio del valore: con tre contatti sarebbero state nove righe.
  • [2026-09-01] L'accesso a Gitea si recupera dalla sua CLI, non dal web — il push rispondeva 403 (la credenziale nel portachiavi leggeva ma non scriveva) e l'account web non era piu' accessibile, quindi la via del browser era chiusa in partenza. Si rientra da dentro il container: docker exec -u git gitea-tgw04ws48sogkso84oogwckk gitea admin user change-password per la password e ... generate-access-token --scopes write:repository --raw per il token del push. Il token va messo nel portachiavi con git credential approve, non nell'URL del remote: li' finirebbe in chiaro dentro .git/config. Da ricordare perche' senza push non esiste deploy — Coolify parte da main e basta.
  • [2026-08-22] Un task cancellato esce dai denominatori, non dalla lista — resta visibile barrato (il cliente ha letto quella voce e deve capire che fine ha fatto) ma non conta, via un solo countsTowardProgress() in task-status.ts: contarlo terrebbe la fase sotto il 100% per sempre, contarlo come fatto racconterebbe una consegna mai avvenuta. Se in una fase restano solo cancellati torna «Da iniziare»: degenere, ma «Completata» mentirebbe.
  • [2026-08-22] Le date dei pagamenti sì, gli importi per riga no — LOCKED #2 parla di cifre, non di date. Salvate a mezzogiorno UTC (a mezzanotte il giorno civile a Roma è già quello dopo) e contate sui giorni civili a Roma in src/lib/payment-dates.ts, lo stesso modulo del futuro promemoria email: mail e portale non devono contraddirsi su quanti giorni mancano.
  • [2026-08-20] Gli importi scritti a mano non si ricalcolanoamount_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 taskON 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/<id>.
  • .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-26 Stopped at: stato task «Cancellata» + date dei pagamenti nel portale (fe76789, migration 0023 applicata a prod prima del push). Un task tolto dal lavoro ora ha dove stare: X nel cerchio, titolo barrato, pill «Cancellata» — l'unico stato chiuso con la pill, perché «Fatto» e «Cancellata» sono entrambi barrati e scambiarli significa credere consegnato ciò che non esiste. Esce da tutti i denominatori via countsTowardProgress(). Nel Kanban cliente la colonna compare solo se piena (mai nascosta se ha dentro qualcosa); nell'admin c'è sempre, ed è così che si cancella un task. Lato pagamenti: payments.due_date (nullable, più indice parziale per il futuro promemoria email), riquadro «Prossimo pagamento» con conto alla rovescia in parole e rosso se scaduto, «Scade il…» / «Pagato il…» su ogni riga, zero importi. Admin: campo Scadenza per rata, «Incassato nel mese» → «Incassato il» (giorno; le analytics raggruppano per mese e non se ne accorgono). Build, typecheck e lint verdi. 2026-08-26 — architettura .claude/: skill /preventivo e /audit, due hook di guardia, piani nel repo. Nessun tocco al prodotto. Le due cose trovate e non risolte sul preventivo → STATUS.md.

Next: (0) [SICUREZZA] rigenerare il token Gitea creato il 2026-09-01: e' stato incollato in chat, quindi va considerato esposto. Si revoca da Settings -> Applications e si rifa'; (1) verificare in prod con ?preview=1 entrambe le cose: stati task su Caruso Speaker, fase «3 - Esecuzione» (l'unica con «In corso» e «In revisione» insieme, 4 + 2 su 11) e box pagamenti — ma prima inserire una scadenza dal tab Pagamenti, altrimenti il riquadro non compare per definizione; (2) due paid_at storici valgono il primo del mese (2026-03-01, 2026-01-01, scritti dal vecchio selettore a mese) e il cliente ora li legge come «Pagato il 1 mar 2026»: correggerli se il giorno vero era un altro; (3) provare la chat in prod: modificare un messaggio admin e vederlo cambiare da solo entro ~20s senza duplicarsi; (4) sbloccare TidyCal con token o documentazione; (5) LEAD_WEBHOOK_SECRET su Coolify, senza cui /api/webhooks/lead risponde 403 a tutti; (6) poi v2.5 da src/lib/audit/schema.ts + agents/. Resume file: None