docs: STATUS.md unico documento narrativo, STATE.md a digest
STATUS.md e .planning/STATE.md raccontavano la stessa storia in due posti
con date diverse, e STATE.md si contraddiceva: frontmatter fermo a
"milestone v2.3 / executing" quando v2.3 e shipped, l'anteprima admin data
per "NON committata" mentre e il commit 187550f deployato l'8 agosto,
Session Continuity ferma al 29/07 e la tabella Performance Metrics spezzata
a meta.
Il template GSD dice esplicitamente che STATE.md deve stare sotto le 100
righe ("a DIGEST, not an archive"): ne aveva 177, quasi tutte narrativa.
- STATUS.md assorbe la narrativa e diventa l'unico posto dove si racconta
il progetto. Nuova sezione "Lezioni operative" per le trappole in cui si
ricasca: il gate OTP non va nel layout App Router (il payload RSC
trapela), ricreare il dominio Resend rigenera la chiave DKIM, .env.local
non e allineato a produzione dal 28/07, Playwright non funziona contro
npm run dev
- STATE.md sceso a 98 righe, con i campi che state.cjs legge davvero.
Frontmatter corretto a v2.4, blocchi gia risolti (DKIM, env Coolify)
rimossi, nulla risulta piu "non committato"
- il debito design era sottostimato: non 11 pagine ma ~40 file e ~450
occorrenze. Esclusi perche legittimi AdminSidebar (eccezione brand),
mailer.ts (HTML email) e i colori di stato di StatusBadge
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+48
-127
@@ -1,143 +1,68 @@
|
||||
---
|
||||
gsd_state_version: 1.0
|
||||
milestone: v2.3
|
||||
milestone_name: Email & Accesso
|
||||
milestone: v2.4
|
||||
milestone_name: Post-vendita
|
||||
status: executing
|
||||
stopped_at: "anteprima admin del portale + occhiolino login: scritti, buildati e verificati in locale, NON ancora committati né deployati. Resta da popolare la whitelist dei 3 clienti reali"
|
||||
last_updated: "2026-08-08T12:20:00.000Z"
|
||||
last_activity: 2026-08-08 -- anteprima admin in sola lettura del portale cliente + toggle password sul login
|
||||
stopped_at: "Phase 13 e 26 in produzione. Nessun lavoro in sospeso: il prossimo va scelto dal backlog in REQUIREMENTS.md."
|
||||
last_updated: "2026-08-08T20:30:00.000Z"
|
||||
last_activity: 2026-08-08 -- riordino della documentazione di progetto
|
||||
progress:
|
||||
total_phases: 3
|
||||
completed_phases: 3
|
||||
total_plans: 3
|
||||
completed_plans: 3
|
||||
total_phases: 2
|
||||
completed_phases: 2
|
||||
total_plans: 2
|
||||
completed_plans: 2
|
||||
percent: 100
|
||||
---
|
||||
|
||||
# Project State
|
||||
|
||||
> Digest per i comandi `/gsd-*`. La narrativa completa — cosa è stato fatto, cosa
|
||||
> manca, le lezioni operative — sta in **`STATUS.md`** alla radice del repo.
|
||||
> Questo file resta sotto le 100 righe di proposito.
|
||||
|
||||
## Project Reference
|
||||
|
||||
See: .planning/PROJECT.md (updated 2026-06-21)
|
||||
See: .planning/PROJECT.md (updated 2026-08-08)
|
||||
|
||||
**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.
|
||||
|
||||
**Current focus:** Milestone **v2.3 "Email & Accesso"** — **consegnata**. Il portale cliente è protetto da gate email OTP. L'invio del preventivo via email (SEND-01/02) è stato rinviato a v2.4 — si manda a mano.
|
||||
**Current focus:** Milestone **v2.4 "Post-vendita"** — tutto ciò che era pianificato è in produzione. Nessuna fase aperta.
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: v2.3 (23/24/25) e v2.4 Phase 13 in produzione. Sopra, lavoro **non ancora committato**: anteprima admin del portale + occhiolino sul login.
|
||||
Plan: `~/.claude/plans/per-fare-l-accesso-all-admin-elegant-teapot.md`
|
||||
Status: scritto, buildato, verificato in locale contro il DB di produzione. **Non committato, non deployato.**
|
||||
Last activity: 2026-08-08 — anteprima admin in sola lettura del portale cliente
|
||||
Phase: 2 of 2 (Phase 13 Ciclo di vita servizi ricorrenti · Phase 26 Anteprima admin)
|
||||
Plan: 2 of 2 in current milestone
|
||||
Status: Phase complete — nessuna fase aperta, prossimo lavoro da scegliere dal backlog
|
||||
Last activity: 2026-08-08 — riordino della documentazione (`.planning/` e doc di root)
|
||||
|
||||
### 2026-08-08 — Anteprima admin del portale + occhiolino sul login
|
||||
Progress: [██████████] 100%
|
||||
|
||||
**Non è in produzione.** Codice scritto e verificato in locale (`npm run build` verde, nessun nuovo problema di lint), nessun commit e nessun push fatti.
|
||||
Entrambe le fasi sono **in produzione e verificate**:
|
||||
|
||||
**Cosa risolve.** Quando un cliente diceva "non trovo una cosa" non c'era modo di guardare il portale con i suoi occhi: il gate OTP lascia entrare solo lui. Ora l'elenco clienti (`ClientRow`) ha un'icona che apre `/client/<slug>?preview=1` in una scheda nuova.
|
||||
|
||||
**Come funziona.** `getClientGate()` accetta `{ previewRequested }` e salta il gate solo se il query param c'è **e** `getServerSession(authOptions)` è valida. Ritorna `preview: true` senza sintetizzare una `ClientSession`: un admin in anteprima non è un cliente autenticato, e confondere i due stati renderebbe i casi indistinguibili a valle. La sola lettura passa da `PreviewProvider` (`usePreview()`), consumato da `ApproveButton` e dal composer di `ChatPanel` — context e non prop drilling, perché `ApproveButton` sta quattro livelli sotto la dashboard.
|
||||
|
||||
**Perché sola lettura e non anteprima interattiva.** Il portale scrive davvero: `/api/client/approve` e `/api/client/comment` autenticano sul token nel body, non sulla sessione. Un click distratto approverebbe un deliverable, e `approved_at` è immutabile una volta impostato (vincolo LOCKED #3). La protezione è a livello di UI, non di API: un admin può ancora chiamare le route a mano. È voluto — l'obiettivo è impedire l'incidente, non difendersi da sé stessi.
|
||||
|
||||
**Deviazione consapevole dal vincolo LOCKED #4** (`/client/*` → token, `/admin/*` → Auth.js): ora una route client legge anche la sessione Auth.js. Non indebolisce nulla — per i clienti il gate OTP è identico — ma `CLAUDE.md` **non è stato ancora aggiornato**: serve l'ok dell'utente per toccare la sezione LOCKED.
|
||||
|
||||
**Verificato in locale** (build di produzione su :3100, DB di prod via tunnel SSH, sole letture): `?preview=1` **senza** sessione admin → gate OTP; con cookie di sessione contraffatto → gate OTP; `?preview=0`, `?preview=abc`, `?preview=` → gate OTP; senza query param e **con** sessione admin → gate OTP (nessuna regressione); con sessione admin valida + `?preview=1` → portale con banner e composer disattivato, sia sul cliente a progetto singolo sia su quello a due progetti (tab).
|
||||
|
||||
**Non verificato dal vivo:** il ramo `ApproveButton` — in produzione la tabella `deliverables` è **vuota** (0 righe), quindi quel pulsante oggi non si renderizza mai. Wiring controllato solo a livello di codice. Il click dell'occhiolino sul login è verificato solo nel markup renderizzato (`type="button"`, `tabindex="-1"`, `aria-label`): manca la prova a schermo, Playwright non ha browser in cache.
|
||||
|
||||
**Perché la password di `.env.local` non funzionava.** Non era un bug: `ADMIN_PASSWORD` è stata ruotata il 2026-07-28 **solo su Coolify** (vedi `SECURITY-REMEDIATION-PLAN.md`), e `.env.local` è rimasto alla precedente. Vale anche per `NEXTAUTH_SECRET`. **`.env.local` non è allineato a produzione** — non trattarlo come fonte di verità per le credenziali.
|
||||
|
||||
**Nota su `.env.local`:** contiene due righe `DATABASE_URL`; vince l'ultima (porta 54321) e punta al DB di produzione. Il DB non è raggiungibile dall'esterno: per puntarci in locale serve `ssh -f -N -L 54321:localhost:54321 root@178.104.27.55` **e** sostituire l'host con `localhost` nella stringa di connessione.
|
||||
|
||||
### ✅ Prerequisiti email risolti (2026-07-29)
|
||||
|
||||
- **Dominio `iamcavalli.net` verificato su Resend.** L'utente ha ricreato la registrazione del dominio (nuovo id `f81202f1-3bba-47c5-8c0f-84101440b960`, la precedente `a2a80798-…` non esiste più) e messo i DNS. Tutti e tre i record `verified`: DKIM TXT su `resend._domainkey`, SPF TXT + MX su `send`. Invio da `no-reply@iamcavalli.net` verso un indirizzo esterno confermato riuscito.
|
||||
- *Nota:* ricreare il dominio su Resend **rigenera la chiave DKIM**. Se in futuro il dominio torna `failed`, non fidarsi di valori DKIM annotati in passato — rileggerli da `GET /domains` e confrontarli con `dig +short TXT resend._domainkey.iamcavalli.net @8.8.8.8`.
|
||||
- `RESEND_API_KEY` + `RESEND_FROM` **configurate su Coolify** (production e preview) via API — verificate presenti.
|
||||
- **Mailer verificato**: `sendEmail()` col template OTP reale ha restituito `{ok:true, id:…}`.
|
||||
- Verificato che quando Resend rifiuta, la route risponde comunque col messaggio neutro e logga l'errore lato server — il no-enumeration tiene anche a provider guasto.
|
||||
|
||||
### ✅ Verificato in produzione (2026-07-29, commit 27da969)
|
||||
|
||||
Su `hub.iamcavalli.net`: gate mostrato senza cookie e **zero dati di progetto nell'HTML** (12.487 byte); email fuori whitelist e in whitelist danno risposta identica e solo la seconda genera un OTP; codice sbagliato rifiutato, corretto accettato; cookie `ch_sess_<id>` con `Secure` + `HttpOnly` + `SameSite=lax` + `Max-Age=7776000` (90 giorni); rientro col cookie mostra la dashboard; sessione di un cliente sull'URL di un altro mostra il gate. Nessun errore d'invio nei log del container. Dati di test rimossi, tabelle protette invariate (4/5/11/10).
|
||||
|
||||
### Da fare
|
||||
|
||||
Popolare la whitelist dei 3 clienti reali da `/admin/clients/<id>` → "Accessi al portale", e reinviare loro il link. La migration aveva seedato solo `mario@test.it` (cliente di test "Rossi Inc"); Protocollo Estetico, Caruso Speaker e Teckell hanno whitelist vuota e finché lo è il loro portale non è accessibile.
|
||||
|
||||
### Cosa è stato consegnato in v2.3 (codice locale, buildato e testato)
|
||||
|
||||
- **Resend**: `resend@6.18.1`, `src/lib/mailer.ts` (Result tipizzato, mai catch silenzioso) + template OTP in italiano.
|
||||
- **Schema**: migration `0015_otp_access.sql` **già applicata a prod** — `client_emails` (whitelist, unique case-insensitive), `otp_codes` (hash del codice, mai il codice), `clients.sessions_valid_from` (revoca). Additiva pura: conteggi pre/post identici su clients 4 / projects 5 / payments 11 / phases 10.
|
||||
- **Admin**: sezione "Accessi al portale" in `/admin/clients/[id]` — aggiungi/rimuovi email + "Revoca sessioni attive". Server actions in `clients/[id]/actions.ts`. Scritta a token semantici benché la pagina attorno sia ancora a palette vecchia.
|
||||
- **Gate**: `src/lib/otp.ts` (codice 6 cifre CSPRNG, hash SHA-256 con `NEXTAUTH_SECRET`+clientId, TTL 15 min, max 5 tentativi), `src/lib/client-session.ts` (cookie HMAC per-cliente `ch_sess_<id>`, 90 giorni, httpOnly/secure/lax, path=/client), `src/lib/client-gate.ts`, route `/api/client/otp/request|verify`, componente `OtpGate`.
|
||||
|
||||
### ⚠️ Lezione: il gate NON va nel layout
|
||||
|
||||
Prima implementazione: gate in `client/[token]/layout.tsx` che rendeva `<OtpGate/>` al posto di `{children}`. **Non funziona come protezione.** Nell'App Router il segmento `page` viene renderizzato in parallelo al layout: la dashboard spariva a schermo ma fasi, task e pagamenti restavano leggibili nel payload RSC dell'HTML (46.907 byte → 17.594 dopo il fix). Il gate è ora in cima alla `page`, prima di ogni query, via `getClientGate()`. **Ogni nuova route sotto `/client/[token]/` deve fare lo stesso** — il layout porta un commento che lo ricorda.
|
||||
|
||||
### Lavoro recente precedente (in prod)
|
||||
|
||||
- **[2026-07-27/28] Audit di sicurezza**: 4 vulnerabilità chiuse e deployate (secondo gate admin, hardening slug, XSS, CSP/HSTS); slug clienti deboli ruotati a 12 char CSPRNG; `INTERNAL_SECRET` e `ADMIN_PASSWORD` configurati su Coolify. Finding #1 (password Postgres committata) declassato CRITICO→BASSO: verificata inattiva, già ruotata. Report in `.planning/SECURITY-*.md`.
|
||||
- **[2026-07-28] Riorganizzazione cartella**: fasi di planning consolidate, script one-off archiviati in `cestino/`, `CLAUDE.md` arricchito.
|
||||
- **Design system "Quiet Luxury"**: dashboard, liste (Clienti/Offerte/Catalogo/Preventivi/Progetti), Conversazioni, Impostazioni, Pipeline+Kanban, dettaglio Lead e portale cliente base sono a token e dual-theme. **Ancora a design vecchio** (funzionanti, solo estetica): `/admin/offers/[id]/edit`, `/admin/projects/[id]` (il cluster peggiore, ~140 occorrenze fra i suoi tab), `/admin/projects/new`, `/admin/clients/[id]`, `/admin/clients/[id]/edit`, `/admin/login`, badge in `/admin/preventivi/[id]`, chat portale cliente — più, non censiti prima: **tutto `/quote/[token]`** (~40 occorrenze, pagina rivolta al cliente) e `ui/dialog.tsx`, che propaga la palette vecchia a ogni modale.
|
||||
- **Tassonomie**: gestione centralizzata categorie/tag in Impostazioni (`src/lib/taxonomy.ts`).
|
||||
- **Lead → Cliente (A+B)**: `clients.email/phone` + `leads.archived` (migration 0011); `convertLeadToClient`.
|
||||
|
||||
### Fasi completate (v2.2, storico)
|
||||
|
||||
Phase 18 (cleanup), Phase 19 (Kanban CRM), Phase 20 (transcript KB), Phase 21 (AI agent), Phase 22 (deck pubblico) — consegnate e in prod 2026-06-20.
|
||||
- Phase 13 → `5177a37`, migr. 0016, prod 2026-08-01 · [13-SUMMARY.md](phases/13-ciclo-vita-servizi-ricorrenti/13-SUMMARY.md)
|
||||
- Phase 26 → `09a5b1f` + `187550f`, prod 2026-08-08 · [26-SUMMARY.md](phases/26-anteprima-admin-e-login/26-SUMMARY.md)
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
**Velocity:**
|
||||
|
||||
- Total plans completed: 7 (v2.1) + 9 (v2.2) = 16 totali
|
||||
- Average duration: —
|
||||
- Total execution time: —
|
||||
|
||||
**By Phase:**
|
||||
**Velocity:** 21 plans completati in totale — 7 (v2.1) + 9 (v2.2) + 3 (v2.3) + 2 (v2.4).
|
||||
**Recent Trend:** — · v2.3 e v2.4 sono state eseguite fuori dal ciclo GSD, quindi non cronometrate.
|
||||
|
||||
| Phase | Plans | Total | Avg/Plan |
|
||||
|-------|-------|-------|----------|
|
||||
| Phase 11 P01 | 25min | 2 tasks | 6 files |
|
||||
| 11 | 4 | - | - |
|
||||
| 14 | 3 | - | - |
|
||||
|
||||
**Recent Trend:**
|
||||
|
||||
- Last 5 plans: —
|
||||
- Trend: —
|
||||
| 13 | 1 | — | — |
|
||||
| 26 | 1 | — | — |
|
||||
|
||||
*Updated after each plan completion*
|
||||
| Phase 11 P02 | 12min | 2 tasks | 2 files |
|
||||
| Phase 11 P03 | 9min | 2 tasks | 2 files |
|
||||
| Phase 11 P04 | 12min | 2 tasks | 4 files |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
### Decisions
|
||||
|
||||
Decisions are logged in PROJECT.md Key Decisions table.
|
||||
Recent decisions affecting current work:
|
||||
Log completo in PROJECT.md (Key Decisions). Rilevanti per il lavoro corrente:
|
||||
|
||||
- **[v2.3 2026-06-21] Resend come provider email unico** — PUB-03 (invio preventivo) e AUTH-OTP-01 (OTP gate) condividono la stessa integrazione Resend. Phase 23 configura SDK + env vars, Phase 25 li riusa.
|
||||
- **[v2.3 2026-06-21] OTP gate è strato aggiuntivo, non rimpiazzo del token middleware** — proxy.ts e `/api/internal/validate-token` rimangono invariati. Il gate OTP interviene dopo la validazione del token, nel rendering della route `/client/[token]/*`.
|
||||
- **[v2.3 2026-06-21] Migration Phase 24 è additiva pura** — `client_emails` e `otp_codes` sono nuove tabelle. Nessun drop/truncate. SQL a mano (drizzle-kit generate rotto). Applicare via SSH prima del codice dipendente.
|
||||
- **[RESET 2026-06-19] Milestone v2.2 "Sales Loop"** sostituisce le fasi residue v2.1. Decisioni bloccate: (1) URL preventivo = `/preventivo/[slug]` pubblico; (2) tagliare Forecast + quote builder manuale + Phase 15, fondere `/admin/analytics` nella dashboard; (3) portale post-vendita resta core, non si tocca (Phase 13 congelata); (4) agente AI = "io scelgo l'offerta, l'AI personalizza" leggendo i transcript, provider Claude. Piano: `.claude/plans/glittery-sprouting-pudding.md`
|
||||
- [SUPERSEDED dal reset] v2.1 roadmap: Offer Studio (Phases 11-15) sequenced before Proposal AI (Phases 16-17) — clean/fast data UX before the AI builder
|
||||
- Phase 11 bundles catalog database-view UX (OFFER-07..10) with legacy consolidation (OFFER-13) since the new UX should be built on a single unified `services` table, not on top of legacy `service_catalog`/`offer_services`
|
||||
- Phase 13 (Workspace — Servizi Attivi) is independent of Phases 11/12 — can execute in parallel order if useful, but numbered after for narrative flow
|
||||
- Phase 15 (Dashboard Revenue Stats / DASH-11) is isolated and BLOCKED on user-provided mockup; no other phase depends on it — can be deferred/skipped without blocking Phase 16/17
|
||||
- Phase 16/17 split: schema/automation (payment link field + auto-provisioning) first, then AI builder + public page redesign + email — keeps the AI-dependent work last
|
||||
- [Phase 11]: Phase 11: hand-write Drizzle migration SQL (0006_add_tags_table.sql) following the project's established convention since drizzle-kit generate is non-functional (meta snapshots out of sync since migration 0001, pre-existing since Phase 8) — Avoids architectural snapshot-reconciliation work (Rule 4, out of scope) while matching exact precedent from migrations 0003-0005
|
||||
- [Phase 11]: Phase 11 Plan 02: onConflictDoNothing() without explicit target compiles cleanly for tags table (single unique index tags_entity_name_unique) — used as written in plan, no fallback needed — Avoids unnecessary deviation; Drizzle's no-target ON CONFLICT DO NOTHING is correct given the single unique constraint from Plan 01
|
||||
- [Phase 11]: Phase 11 Plan 03: removed the plan's prescribed value-sync useEffect (and a follow-up render-time ref-read attempt) from EditableCell — both violate this project's react-hooks lint rules (set-state-in-effect, refs-during-render / React Compiler). tempValue is now only (re)initialized in startEdit()/cancel(), and the toggle display branch reads `value` directly instead of `tempValue` — Rule 1 lint fix, no behavioral change to the 8 spec'd test behaviors
|
||||
- [Phase 11]: Phase 11 Plan 04: left `createService`/`serviceSchema` in `src/app/admin/catalog/actions.ts` as unused dead code after deleting `ServiceForm.tsx` (its only consumer) — `actions.ts` was outside this plan's `files_modified` scope and `updateService` still depends on `serviceSchema`; logged to deferred-items.md for future cleanup
|
||||
- [Phase 18-02]: fmtEur unified to number version (analytics/page.tsx variant); KPI card callers using DB string values wrapped with parseFloat() — cleaner than maintaining two named variants
|
||||
- [Phase 18-02]: /admin/analytics route deleted; YearSelector now routes to /admin?year=Y — single admin entry point for statistics (CLEAN-03)
|
||||
- **[Phase 26, 2026-08-08] Deviazione consapevole dal vincolo LOCKED #4** — una route `/client/*` ora legge anche la sessione Auth.js per l'anteprima admin. Non indebolisce il gate per i clienti; annotata in `CLAUDE.md`.
|
||||
- **[Phase 26] L'anteprima è in sola lettura a livello UI, non API** — le route `/api/client/*` autenticano sul token nel body. L'obiettivo è impedire l'incidente, non difendersi da sé stessi.
|
||||
- **[Phase 13] Storico di vendita ≠ forecast** — `getOffersSoldBreakdown` non filtra per stato: escludere le offerte cessate riscriverebbe il fatturato passato.
|
||||
- **[v2.3, 2026-07-28] Sessione OTP a 90 giorni invece di 30** — rientro più fluido, compensato dalla revoca in blocco lato admin (OTP-08).
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -147,31 +72,27 @@ None yet.
|
||||
|
||||
### Blockers/Concerns
|
||||
|
||||
- ~~Record DKIM / dominio Resend~~ — **risolto 2026-07-29**: dominio ricreato e `verified`, invio dal dominio reale confermato.
|
||||
- ~~`RESEND_API_KEY` + `RESEND_FROM` su Coolify~~ — **fatto 2026-07-29**, production e preview.
|
||||
- **Whitelist vuota per 3 clienti su 4** (non bloccante: l'utente li re-invita) — da popolare da `/admin/clients/<id>` → "Accessi al portale".
|
||||
- **Coolify API**: credenziali in `~/.coolify.env` (`export COOLIFY_URL/COOLIFY_TOKEN`, va sorgentato con `set -a; . ~/.coolify.env`). App ClientHub uuid `xsksow44g4kcoo8wocsgkscc`. Il POST su `/api/v1/applications/<uuid>/envs` **non accetta** il campo `is_build_time` (422): mandare solo `key`, `value`, `is_preview`. I token Hetzner/Cloudflare nel file sono **vuoti** → il DNS non è modificabile via API.
|
||||
- **Migrations (sempre valido)**: ogni fase con schema DEVE avere la migration applicata a prod PRIMA di pushare il codice dipendente. `drizzle-kit generate` rotto → SQL a mano. La 0015 è già applicata. Due strade: `cat migration.sql | ssh root@178.104.27.55 "docker exec -i xwkk0040w0kk0gsgcgog8owk psql -U clienthub -d clienthub -v ON_ERROR_STOP=1 --single-transaction"` (autoritativa, nessun tunnel), oppure tunnel `ssh -f -N -L 54321:localhost:54321 root@178.104.27.55` con `DATABASE_URL` riscritto a `127.0.0.1:54321` se serve puntarci il tooling locale.
|
||||
- **`.env.local` punta al DB di PRODUZIONE** (178.104.27.55:54321, richiede il tunnel). Non esiste un DB di sviluppo separato: qualsiasi test in locale scrive su dati reali. Verificare sempre i conteggi delle tabelle protette prima e dopo.
|
||||
- **Debito tecnico (non bloccante)**: tabelle legacy `service_catalog`/`offer_services`/`offer_micro_services` restano come deadweight; `createService`/`serviceSchema` dead code in `catalog/actions.ts`.
|
||||
- **Whitelist portale vuota per 3 clienti su 4** (non bloccante: l'utente li re-invita) — da popolare da `/admin/clients/<id>` → "Accessi al portale".
|
||||
- **`.env.local` punta al DB di PRODUZIONE** e non è allineato a Coolify per `ADMIN_PASSWORD` / `NEXTAUTH_SECRET` (ruotati il 2026-07-28). Nessun DB di sviluppo separato: ogni prova locale scrive su dati reali.
|
||||
- **Ogni fase con schema** DEVE avere la migration applicata a prod PRIMA del push del codice dipendente. `drizzle-kit generate` è rotto → SQL a mano. Procedura in `CLAUDE.md`.
|
||||
- **Debito design (DEBT-01)** — ~40 file, ~450 occorrenze di palette raw/hex. Misurato il 2026-08-08. Dettaglio in `STATUS.md`.
|
||||
|
||||
## Deferred Items
|
||||
|
||||
Items acknowledged and carried forward from previous milestone close:
|
||||
|
||||
| Category | Item | Status | Deferred At |
|
||||
|----------|------|--------|-------------|
|
||||
| v2.4 | PROP-03 — Stripe Payment Link su deck pubblico | Backlog | v2.3 kickoff |
|
||||
| v2.4 | PROP-04 — Auto-provisioning cliente/progetto/fasi al "Vinto" | Backlog | v2.3 kickoff |
|
||||
| v2+ | Phase 13 — Servizi attivi/ricorrenti post-vendita | Congelata | v2.1 kickoff |
|
||||
| v2 | OFFER-14 — Sezioni analitiche stile Notion | Backlog | v2.1 kickoff |
|
||||
| v2 | ARCH-01 — Split modulo "compartimento stagno" in deploy separato | Backlog (only if module grows) | v2.1 kickoff |
|
||||
| v2.4 | SEND-01/02 — Invio link preventivo via email dall'admin | Backlog (mailer già pronto) | 2026-07-28 |
|
||||
| Design | 11 pagine ancora a palette vecchia — vedi elenco in "Lavoro recente" | Backlog | 2026-07-28 |
|
||||
| v2.4 | RET-06 — Canoni mensili tracciabili (serve tabella nuova) | Backlog | 2026-08-01 |
|
||||
| v2.4 | SEND-01/02 — Invio link preventivo via email (mailer già pronto) | Backlog | 2026-07-28 |
|
||||
| v2.4+ | PROP-03 — Stripe Payment Link sul deck | Backlog | v2.3 kickoff |
|
||||
| v2.4+ | PROP-04 — Auto-provisioning cliente/progetto/fasi al "Vinto" | Backlog | v2.3 kickoff |
|
||||
| Design | DEBT-01 — Migrazione a token semantici | Backlog | 2026-07-28 |
|
||||
| Tech debt | DEBT-02 — Tabelle legacy catalogo + dead code | Backlog | v2.1 |
|
||||
| v2+ | OFFER-14 — Sezioni analitiche stile Notion | Backlog | v2.1 kickoff |
|
||||
| v2+ | ARCH-01 — Split modulo in deploy separato | Backlog (solo se cresce) | v2.1 kickoff |
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-07-29T21:20:00.000Z
|
||||
Stopped at: v2.3 deployata in produzione. Dominio Resend verificato, Coolify configurato, gate OTP live su `hub.iamcavalli.net`.
|
||||
Next: popolare la whitelist dei 3 clienti reali da `/admin/clients/<id>` → "Accessi al portale", e reinviare loro il link.
|
||||
Resume file: .planning/STATE.md
|
||||
Last session: 2026-08-08 20:30
|
||||
Stopped at: Riordino della documentazione — milestone chiuse archiviate, v2.4 documentata, STATUS.md unico documento narrativo.
|
||||
Next: Popolare la whitelist dei 3 clienti reali, oppure attaccare DEBT-01 (debito design).
|
||||
Resume file: None
|
||||
|
||||
Reference in New Issue
Block a user