# AGENT.md

## Scopo

Questo workspace ospita una suite gestionale hospitality in evoluzione.

L'obiettivo non e' "rifare tutto", ma consolidare una piattaforma unica attorno a moduli esistenti e nuovi moduli nativi.

Questo file serve come contesto operativo rapido per nuove sessioni.

## Mappa reale del progetto

- `apps/portal`
  Hub UI principale di `powerup.cool`.
  Stack: React + Vite.
  E' la reference visiva del prodotto.

- `apps/backend-hub`
  Backend centrale leggero.
  Stack: FastAPI.
  Gestisce orchestrazione comune, chat/LLM, Google Workspace, auth e tenancy persistenti.
  E' anche la sorgente centrale dei prompt condivisi e delle configurazioni AI tenant-aware.

- `apps/ordini`
  Modulo nativo ordini.
  Stack: frontend statico + Nginx, backend FastAPI + SQLAlchemy, database tenant-aware.

- `PRENOTAZIONI_IA`
  Legacy prenotazioni preservata.
  Non va trattata come codice "nuovo" da rifattorizzare a caso.

- `MENU2.0`
  Legacy menu preservata.
  Anche questa va considerata legacy integrata, non base da stravolgere.

- `apps/prenotazioni-legacy`
  Wrapper/integrazione Docker della legacy prenotazioni.

- `apps/menu-legacy`
  Wrapper/integrazione Docker della legacy menu.

- `packages/*`
  Shared layer del workspace.
  `config`, `types`, `shared` sono usati davvero.
  `auth`, `billing`, `tenancy`, `ui` sono ancora placeholder o semi-placeholder.

## Vincoli importanti

- Non modificare `/var/www/html8000`.
  In particolare `/var/www/html8000/ordini.html` e' solo riferimento funzionale/storico.

- Le due legacy principali sono preservate:
  `PRENOTAZIONI_IA` e `MENU2.0`.
  Prima di modificarle serve un motivo concreto.

- I nuovi moduli devono sembrare parte del gestionale `powerup.cool`.
  Non devono sembrare tool esterni standalone.

- Non mettere segreti nei file di documentazione o nel codice.
  Riferirsi sempre a variabili ambiente, mai a valori sensibili reali.

## Routing e deploy reali

Produzione corrente: `https://powerup.cool`

Nota pratica su `.env.example`:
- gli URL pubblici di esempio sono orientati alla produzione `powerup.cool`
- per sviluppo locale vanno sostituiti con URL `localhost` coerenti con le porte del compose

Ingresso HTTPS:
- Apache su `*:443`

Proxy reali:
- `/` -> `portal` (`localhost:3000`)
- `/api/` -> `backend-hub` (`localhost:8101`)
- `/prenotazioni` e `/prenotazioni/` -> frontend prenotazioni (`localhost:3100`)
- `/prenotazioni-api/` -> backend prenotazioni (`localhost:8100`)
- `/menu/` -> menu legacy (`localhost:3200`)

Nota importante su `Ordini`:
- Apache inoltra `/` al `portal`
- Il `portal` Nginx gestisce internamente `/ordini/`
- `/ordini/` -> `ordini-frontend`
- `ordini-frontend` proxya `/api/` verso `ordini-backend`

Quindi in produzione il modulo ordini corretto e':
- `https://powerup.cool/ordini/`

Non bisogna affidarsi a `powerup.cool:3300` come URL pubblico di prodotto.

Stato attuale del `portal`:
- `/` mostra la pagina di accesso
- il tab iniziale e' `Login`
- la registrazione del locale e' disponibile nello stesso pannello
- dopo login valido il portale usa tenant reale e redirect a `/home`
- `Home` e' la prima schermata autenticata del gestionale
- non esiste piu' una pagina globale `/settings`: la configurazione AI resta dentro i singoli moduli

## Stato attuale di Auth e Tenancy

Persistenza:
- registry centrale su SQLite in `backend-hub`
- path di default: `/data/platform_registry.sqlite3`
- database dedicati dei tenant: `/data/tenants/<tenant-slug>.sqlite3`
- `backend-hub` e `ordini-backend` devono condividere il volume `/data`

Comportamento attuale:
- la registrazione crea tenant, venue, utente admin, moduli tenant e database del locale
- il `portal` salva una sessione reale, non usa piu' `tenantContext` mock
- il nome del locale mostrato nella UI arriva dai dati salvati in registrazione
- `packages/auth` e `packages/tenancy` restano placeholder: la logica reale vive in `apps/backend-hub`

## Stato attuale di LLM e Prompt

Regola base:
- ogni nuovo locale deve partire da un prompt base condiviso
- non devono esistere fallback che riusano prompt di un locale demo o di test

Home del portale:
- la chat `Home` del `portal` e' l'assistente operativo globale del locale
- il backend reale vive in `apps/backend-hub/app/services/operational_assistant_service.py`
- la Home deve restare grounded sui dati reali del tenant, non puo' inventare numeri, ordini o prenotazioni
- oggi la Home puo' leggere dati reali di:
  ordini, storico acquisti, prodotti, prenotazioni, note condivise e obiettivi vendita
- oggi la Home puo' anche scrivere:
  ordine sospeso, prenotazioni, note condivise, obiettivi vendita
- per richieste molto chiare e rischiose il routing e' ibrido:
  prima passano filtri software deterministici, poi eventualmente planner/sintesi LLM sopra tool reali
- i follow-up brevi tipo `e grey goose?` devono mantenere il contesto della domanda precedente quando possibile
- per la creazione prenotazioni dalla Home esiste ora un parsing diretto:
  riconosce anche verbi come `segna`, `registra`, `appunta`
- i follow-up della stessa conversazione tipo `5 persone` o il numero di telefono devono completare la prenotazione in corso, non ripartire dal planner libero
- se nel messaggio compaiono piu' orari, la Home deve chiedere chiarimento e non inventare orari del locale o disponibilita'
- una prenotazione dalla Home va considerata riuscita solo se il tool reale `create_reservation` ha scritto nel DB di `PRENOTAZIONI_IA`
- se il comportamento della Home sembra vecchio, il primo controllo da fare e' `backend-hub`, non il frontend del `portal`

Persistenza e ownership:
- `backend-hub` salva la configurazione AI tenant-aware nel registry SQLite centrale
- per il modulo `menu` la configurazione tenant vive nella tabella `tenant_llm_settings`
- il prompt finale del `menu` viene composto lato `backend-hub`, non hardcodato nella legacy

Menu:
- il prompt tenant del `menu` parte dal prompt base condiviso
- il campo manuale tenant attuale e' `sales_focus`
- `menu_text` e `cocktail_list_text` non sono piu' compilabili a mano nella UI
- il contesto menu viene costruito soprattutto dai file caricati in `Configura menu`
- i materiali caricati possono essere foto, PDF o testi, e possono essere rinominati o eliminati
- `MENU2.0` espone anche una UI interna raggiungibile dal bottone `Configura menu`
- la UI tenant del `menu` compare solo se il modulo viene aperto dal `portal` con `?session=...`
- se apri `MENU2.0` standalone senza sessione del `portal`, la vista resta pubblica e non mostra la configurazione tenant

Prenotazioni e canali:
- le richieste che arrivano da canali diversi non devono condividere automaticamente lo stesso comportamento LLM
- il canale WhatsApp di `PRENOTAZIONI_IA` ha un prompt dedicato alle prenotazioni
- il prompt WhatsApp prenotazioni e' configurabile dal modulo prenotazioni, non dal menu
- il valore tenant-specifico viene salvato in `venue_booking_settings.whatsapp_assistant_prompt`
- le richieste WhatsApp fuori dal flow booking devono restare nel perimetro prenotazioni, non comportarsi come assistente menu o concierge generico
- il modulo `Prenotazioni` risolve il locale corrente dalla sessione del `portal` tramite `portal-context/sync`
- se la sessione e' quella di `Baco'`, `booking-settings` e `reservations` devono riferirsi al venue `Baco' Lounge Bar`, non a `Ritual`

## Stato attuale di Ordini

Percorso:
- frontend: `apps/ordini/frontend`
- backend: `apps/ordini/backend`

Persistenza:
- tenant autenticato: database SQLite dedicato del locale
- fallback legacy: `ORDINI_DATABASE_URL` PostgreSQL
- niente CSV come storage runtime

Funzioni principali gia' presenti:
- accesso diretto dal `portal` tramite sessione del gestionale
- login manuale fallback con credenziali admin
- catalogo prodotti
- import CSV verso SQL
- aggiunta prodotto
- ordine confermato
- ordine sospeso
- storico annuale
- confronto ordini
- ultimo ordine
- export CSV storico
- note condivise
- obiettivi stagionali

UI/UX attuale:
- design riallineato al linguaggio visivo di `powerup.cool`
- se arrivi dal `portal`, il modulo entra direttamente senza doppio login
- se apri `ordini` fuori dal `portal`, resta disponibile un login fallback
- i menu espandibili devono aprirsi inline sotto il bottone, non sovrapporsi al contenuto sottostante

Regola di design per Ordini:
- quando si interviene sul frontend, prendere come riferimento visivo `apps/portal/src/styles.css`, non il vecchio look standalone dell'esempio in `html8000`

## File chiave da conoscere

Portal:
- `apps/portal/src/styles.css`
- `apps/portal/src/components/AppShell.tsx`
- `apps/portal/src/context/PortalSessionContext.tsx`
- `apps/portal/src/config/runtime.ts`
- `apps/portal/src/lib/api.ts`
- `apps/portal/src/pages/LoginPage.tsx`
- `apps/portal/src/pages/LandingPage.tsx`

Backend Hub:
- `apps/backend-hub/app/api/routes/auth.py`
- `apps/backend-hub/app/api/routes/tenants.py`
- `apps/backend-hub/app/api/routes/llm.py`
- `apps/backend-hub/app/services/tenant_store.py`
- `apps/backend-hub/app/services/venue_prompt.py`
- `apps/backend-hub/app/services/operational_assistant_service.py`
- `apps/backend-hub/app/api/deps.py`

Ordini frontend:
- `apps/ordini/frontend/index.html`
- `apps/ordini/frontend/styles.css`
- `apps/ordini/frontend/app.js`
- `apps/ordini/frontend/nginx.conf`

Ordini backend:
- `apps/ordini/backend/app/api/routes.py`
- `apps/ordini/backend/app/core/config.py`
- `apps/ordini/backend/app/core/tenancy.py`
- `apps/ordini/backend/app/core/database.py`
- `apps/ordini/backend/app/models/*`

Portal AI / Home:
- `apps/portal/src/pages/LandingPage.tsx`
- `apps/portal/src/lib/api.ts`
- `apps/portal/src/config/runtime.ts`

Menu legacy:
- `MENU2.0/index.html`
- `MENU2.0/app.js`
- `MENU2.0/styles.css`

Prenotazioni legacy:
- `PRENOTAZIONI_IA/backend/app/api/routes.py`
- `PRENOTAZIONI_IA/backend/app/services/booking_settings_service.py`
- `PRENOTAZIONI_IA/backend/app/services/tenant_sync_service.py`
- `PRENOTAZIONI_IA/backend/app/services/whatsapp_service.py`
- `PRENOTAZIONI_IA/backend/app/main.py`
- `PRENOTAZIONI_IA/frontend/lib/api.ts`
- `PRENOTAZIONI_IA/frontend/app/whatsapp/page.tsx`

Infra:
- `docker-compose.yml`
- `.env.example`
- `.env`
- `/etc/apache2/sites-available/powerup.cool.conf`

## Variabili ambiente rilevanti

Le principali per il deploy attuale sono:

- `PORTAL_PUBLIC_URL`
- `BACKEND_HUB_PUBLIC_URL`
- `PRENOTAZIONI_FRONTEND_PUBLIC_URL`
- `PRENOTAZIONI_BACKEND_PUBLIC_URL`
- `MENU_LEGACY_PUBLIC_URL`
- `ORDINI_FRONTEND_PUBLIC_URL`
- `ORDINI_BACKEND_PUBLIC_URL`
- `ORDINI_DATABASE_URL`
- `ORDINI_BACKEND_CORS_ORIGINS`
- `ORDINI_ADMIN_PASSWORD`
- `ORDINI_API_TOKEN`
- `TENANCY_REGISTRY_DATABASE`
- `TENANCY_DATABASES_DIR`
- `TENANCY_SESSION_DURATION_HOURS`

Se cambi URL pubblici o subpath:
- aggiorna `.env`
- ricostruisci il servizio interessato
- se coinvolge il `portal`, rebuild obbligatoria del container `portal`

## Comandi pratici

Build completa:

```bash
docker compose build
```

Avvio completo:

```bash
docker compose up -d --build
```

Solo modulo ordini:

```bash
docker compose up -d --build ordini-db ordini-backend ordini-frontend
```

Solo portal:

```bash
docker compose up -d --build portal
```

Verifica stato:

```bash
docker compose ps
```

Health backend ordini:

```bash
curl -s http://localhost:8200/health
```

Test login ordini:

```bash
curl -s -H 'Content-Type: application/json' \
  -d '{"identifier":"admin_locale","password":"***"}' \
  http://localhost:8200/api/login
```

Test sessione ordini da portale:

```bash
curl -s -H 'Authorization: Bearer ***' \
  http://localhost:8200/api/session
```

Test stato auth backend hub:

```bash
curl -s http://localhost:8101/auth/status
```

Test pubblico HTTPS locale:

```bash
curl -sk --resolve powerup.cool:443:127.0.0.1 https://powerup.cool/ordini/
```

Se modifichi Apache:

```bash
apache2ctl configtest
apache2ctl graceful
```

## Trappole gia' incontrate

- Se `Ordini` punta a `localhost:3300` o `powerup.cool:3300`, il deploy pubblico e' sbagliato.
  L'URL corretto di prodotto e' `https://powerup.cool/ordini/`.

- Se modifichi gli URL di lancio modulo e non ricrei `portal`, il bottone nel catalogo puo' restare su bundle vecchio.

- Se il browser sembra mostrare ancora comportamento vecchio del `portal`, controlla la cache.
  `index.html` del portal e' gia' configurato come no-cache, ma un hard refresh puo' comunque essere utile.

- Se `Ordini` deve aprirsi diretto dal `portal`, controlla che l'URL contenga `?session=...` e che `/api/session` risponda `200`.

- Se `backend-hub` e `ordini-backend` non condividono `/data`, il modulo ordini non vedra' registry e database tenant.

- Se il `menu` sembra usare ancora un prompt di prova, controlla prima `backend-hub`:
  il fallback corretto e' solo il prompt base condiviso, non un locale demo.

- Se dentro `MENU2.0` non vedi `Configura menu`, verifica che il modulo sia stato aperto dal `portal`.
  Senza `?session=...` il pannello tenant non deve comparire.

- Se la Home del `portal` risponde in modo strano su ordini o prenotazioni, controlla prima
  `apps/backend-hub/app/services/operational_assistant_service.py`.
  Molti casi non dipendono dal prompt, ma dal routing deterministico dei tool.

- Se la Home conferma una prenotazione ma non la vedi nel modulo, verifica subito `GET /reservations` sul tenant attivo:
  la conferma valida deve corrispondere a una riga reale nel DB, non solo a una reply del planner.

- Se `Prenotazioni` sembra mostrare il locale sbagliato, controlla prima se stai usando una UI vecchia o in cache.
  Il backend corretto del tenant si verifica da `/booking-settings`, non dal solo titolo visibile in pagina.

- Le richieste tipo `segna una prenotazione`, `registra una prenotazione`, `appunta una prenotazione`
  devono essere trattate come create reali, non come semplice domanda su disponibilita' o snapshot prenotazioni.

- Le richieste tipo `ultimo ordine`, `quante volte ho ordinato X`, `quando abbiamo preso Y`
  non sono equivalenti:
  usano percorsi diversi e vanno tenute semanticamente separate.

- Se aggiorni la UI o il runtime del `menu`, ricostruisci almeno `backend-hub`, `portal` e `menu-legacy`.
  Poi fai hard refresh del browser.

- Il prompt WhatsApp di `PRENOTAZIONI_IA` non va cercato nel `backend-hub` come configurazione menu.
  Va letto e modificato nelle booking settings della legacy prenotazioni.

- Se `Ordini` viene montato sotto `/ordini/`, il frontend deve usare path compatibili col subpath.
  Evitare assunzioni che funzionano solo da root `/`.

- Non usare il design del file di esempio come stile finale di prodotto.
  L'esempio serve per il flusso, non per l'integrazione visuale finale.

## Strategia consigliata per nuove sessioni

Quando inizi una nuova sessione:

1. Leggi questo file.
2. Identifica subito se il task tocca:
   `portal`, `backend-hub`, `ordini`, legacy o infrastruttura.
3. Se il task tocca UI di un modulo nativo, controlla sempre coerenza con `apps/portal/src/styles.css`.
4. Se il task tocca routing o URL pubblici, controlla insieme:
   `.env`, `docker-compose.yml`, `portal` runtime config e Apache.
5. Se il task riguarda `Ordini`, non usare `html8000` come sorgente da modificare.
6. Se il task riguarda auth o tenancy, guarda prima `backend-hub` e non i package placeholder.
7. Se il task riguarda LLM o prompt, distingui subito tra:
   prompt base condiviso, Home assistant operativa, configurazione tenant del `menu`, prompt WhatsApp di `prenotazioni`.
8. Se il task riguarda il modulo `menu`, verifica sia la UI nel `portal` sia la UI interna `Configura menu` in `MENU2.0`.

## Obiettivo di qualità

Ogni modifica dovrebbe mantenere queste proprieta':

- il modulo sembra interno a `powerup.cool`
- il flusso e' coerente con l'operativita' del locale
- i dati persistono su SQL quando il modulo e' nativo
- il deploy pubblico HTTPS resta coerente con i subpath reali
