[DOCS] Standard cross-suite AgileHub + governance CLAUDE.md + registri agent
- CLAUDE.md: TZ, SSO, vault-steward, versioning, persona v2.0, multitenant, KB RAG - docs/standards: persona-conversational-rules v2.0 - docs/STANDARD_*: installer-integration, email-relay, AI-prodotto, marketing-tenant, multitenant - AGENT_CHANGES.md + OPEN_TICKETS.md (registri agent automatico) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1d13166d7a
commit
c0bf7b6c15
@@ -1,5 +1,110 @@
|
||||
<!-- STANDARD:timezone-conventions:v1.0:start -->
|
||||
## ⏰ ORARI E TIMEZONE — REGOLE OPERATIVE
|
||||
|
||||
> **TL;DR**: l autorità del progetto è **`Europe/Rome`** (CEST estate UTC+2, CET inverno UTC+1).
|
||||
> Quando scrivi un timestamp, **indica SEMPRE il suffisso TZ** (`CEST`/`CET`/`UTC`) oppure usa ISO8601 con offset (`2026-05-09T16:19:00+02:00`). **Mai** timestamp ambigui.
|
||||
|
||||
| Sistema | TZ | Output esempio |
|
||||
|---|---|---|
|
||||
| Host Hetzner | `Europe/Rome` | `Sat May 09 16:19 CEST 2026` |
|
||||
| Container DevEnv (alcuni in drift UTC, vedi standard full) | misto | verifica con `docker exec <c> date` |
|
||||
| Container produzione | `Europe/Rome` | CEST |
|
||||
| MySQL `time_zone` | `SYSTEM` | `NOW()` CEST, `UTC_TIMESTAMP()` UTC |
|
||||
| Apache log `%t` | `Europe/Rome` (locale) | `[09/May/2026:13:04:52 +0200]` |
|
||||
| Node.js MS | UTC interno | `Date().toISOString()` → `Z` |
|
||||
| Crontab Hetzner | `Europe/Rome` | `0 3 * * *` = 03:00 italiane |
|
||||
|
||||
**Regole**:
|
||||
1. **Audit/sequenze cross-MS** → UTC obbligatorio (`2026-05-09T14:19:00Z`)
|
||||
2. **Doc operativi/UI** → CEST/CET con suffisso esplicito
|
||||
3. **DB store** → UTC, display → locale
|
||||
4. **Cron critici** → `CRON_TZ=UTC` o fuori finestra DST 02:00-03:00 locale
|
||||
|
||||
**DST Italia**: ultima domenica marzo (CET→CEST, ora 02:00 saltata) + ultima domenica ottobre (CEST→CET, ora 02:00-03:00 duplicata).
|
||||
|
||||
**Spec completa**: `STANDARD_TIMEZONE_CONVENTIONS.md` (slug `timezone-conventions` v1.0, owner VIGILE).
|
||||
<!-- STANDARD:timezone-conventions:v1.0:end -->
|
||||
|
||||
# NIS2 Agile - Documentazione Progetto
|
||||
|
||||
## REGOLE DI GOVERNANCE (LEGGERE ATTENTAMENTE, aggiornate 2026-04-22)
|
||||
|
||||
> **Queste regole sono OBBLIGATORIE e non negoziabili.**
|
||||
|
||||
### REGOLA FONDAMENTALE: Gitea = SOLO Backup
|
||||
|
||||
> **Gitea e un BACKUP one-way (sorgente -> Gitea), NON la fonte di verita.**
|
||||
> **Il webhook auto-pull e DISABILITATO su tutti i 13 repo dal 2026-04-22.**
|
||||
>
|
||||
> - Le modifiche che fai nel container sono GIA live su `/var/www/nis2-agile/` via bind mount
|
||||
> - `/var/www/nis2-agile/` e la FONTE DI VERITA
|
||||
> - NON proporre MAI "git pull da Gitea" per applicare modifiche
|
||||
> - Per tirare giu qualcosa da Gitea serve richiesta esplicita dell utente
|
||||
> - git push -> Gitea = OK (backup)
|
||||
> - git pull da Gitea -> `/var/www/nis2-agile/` = NO (puo sovrascrivere modifiche vere)
|
||||
|
||||
### ARCHITETTURA: PHP-FPM in Docker con BIND MOUNT (LIVE)
|
||||
|
||||
> **Verificato 2026-04-22**: NIS2 gira con:
|
||||
> - `nis2-app` (php-fpm) con bind mount **RW** su `/var/www/nis2-agile/application` e `/public`
|
||||
> - `nis2-web` (nginx) con bind mount **RO** su `/public`
|
||||
> - `nis2-db` (MySQL) per persistenza
|
||||
> - `nis2-qdrant` (vector DB)
|
||||
> - Apache esterno ha `DocumentRoot /var/www/nis2-agile/public`
|
||||
|
||||
**Cosa va LIVE ISTANTANEAMENTE:**
|
||||
- File `.php` in `/var/www/nis2-agile/application/` -- PHP-FPM rilegge ad ogni request
|
||||
- File in `/var/www/nis2-agile/public/` -- serviti da nginx (via bind mount :ro)
|
||||
- File `.html/.css/.js` nel public -- live via nginx/Apache
|
||||
|
||||
**Cosa richiede azione (CHIEDI SEMPRE CONFERMA):**
|
||||
- Modifiche a `docker/nginx.conf` -> `docker restart nis2-web`
|
||||
- Modifiche al Dockerfile -> `docker compose build + up -d`
|
||||
- Schema DB (`nis2-db`) -> SQL manuale
|
||||
- Worker php cron/feedback -> attendono il prossimo run o restart
|
||||
|
||||
**Nota**: non serve MAI fare rebuild di nis2-app per cambi di codice PHP -- il bind mount :rw garantisce che php-fpm legga sempre la versione aggiornata.
|
||||
|
||||
|
||||
### Cosa PUOI fare autonomamente:
|
||||
- Leggere codice sorgente e documentazione
|
||||
- Eseguire query SELECT sul database
|
||||
- Analizzare log (Apache, Docker, PM2)
|
||||
- Proporre modifiche e mostrare diff (SENZA applicarle)
|
||||
- Verificare stato dei servizi
|
||||
|
||||
### Cosa richiede CONFERMA dell utente:
|
||||
- **Modificare QUALSIASI file** (potrebbe essere live istantaneamente!)
|
||||
- **git commit e git push** (e un backup, ma sempre da confermare)
|
||||
- **Modifiche schema DB** (ALTER/CREATE/DROP TABLE)
|
||||
- **INSERT/UPDATE/DELETE** su dati di produzione
|
||||
- **Installazione dipendenze** (composer require, npm install)
|
||||
- **Modifiche a configurazione** (.env, docker-compose.yml, vhost Apache)
|
||||
- **docker compose build/restart**, **pm2 restart**, **systemctl** qualsiasi
|
||||
|
||||
### DIVIETI ASSOLUTI:
|
||||
- **MAI fare git pull** da Gitea senza richiesta esplicita
|
||||
- **MAI fare git reset --hard** o operazioni distruttive
|
||||
- **MAI toccare altri progetti o container**
|
||||
- **MAI modificare configurazioni di sistema** (Apache globale, PHP globale, MySQL root)
|
||||
- **MAI cancellare dati** senza backup e conferma utente
|
||||
- **MAI tentare deploy SSH/SCP** verso altri server
|
||||
|
||||
### Flusso CORRETTO per una modifica:
|
||||
1. **Analizza**: leggi il codice, capisci il problema
|
||||
2. **Proponi**: mostra le modifiche all utente (diff) SENZA applicarle
|
||||
3. **Attendi conferma**: l utente decide se procedere
|
||||
4. **Applica**: solo dopo conferma
|
||||
5. **Distingui**: e live subito o serve un rebuild/restart? Di all utente chiaramente
|
||||
6. **Verifica**: controlla che https://nis2.agile.software funzioni (se applicabile)
|
||||
7. **Backup su Gitea**: git commit + push (solo dopo conferma utente)
|
||||
|
||||
### Se qualcosa va storto:
|
||||
- **NON tentare fix distruttivi** (reset, force push, drop, rm -rf)
|
||||
- **NON proporre `git pull`** come recupero
|
||||
- Comunica il problema all utente con dettagli precisi
|
||||
|
||||
|
||||
## PRIMA DI INIZIARE
|
||||
- Leggi sempre questo file prima di iniziare qualsiasi lavoro
|
||||
- Il progetto e' al **100% di completamento + Sprint Simulazioni + Audit Chain + Sistema Feedback AI** (~34.000 righe, 85+ file sorgente)
|
||||
@@ -377,7 +482,7 @@ Tutti i moduli sono implementati e testati:
|
||||
|
||||
### Workflow
|
||||
1. Scrivi landing/presentazione nel tuo repo
|
||||
2. Commit + push (webhook aggiorna /var/www/)
|
||||
2. Commit + push (backup su Gitea (webhook DISABILITATO dal 2026-04-22))
|
||||
3. Chiedi conferma utente
|
||||
4. Aggiorna products.json con URL assoluto
|
||||
5. Verifica URL raggiungibile
|
||||
@@ -388,3 +493,421 @@ Tutti i moduli sono implementati e testati:
|
||||
- Dopo QUALSIASI modifica a: URL produzione, dominio, porta, path, schema DB, architettura -> **AGGIORNARE CLAUDE.md IMMEDIATAMENTE**
|
||||
- CLAUDE.md e la "single source of truth" del progetto
|
||||
- A fine sessione: verificare che CLAUDE.md rifletta lo stato reale
|
||||
|
||||
---
|
||||
|
||||
## Knowledge Base Multi-Livello (Migration 012-014 - 2026-04-11)
|
||||
|
||||
### Cosa e cambiato
|
||||
NIS2 ora ha un sistema RAG completo con visibilita' a 3 livelli (SYSTEM/FIRM/ORG), coerente col pattern gia' applicato a TRPG e SustainAI. L'AI puo' rispondere alle domande pescando da documenti caricati dai consulenti o dai responsabili compliance.
|
||||
|
||||
| Scope | Chi possiede | Chi vede |
|
||||
|---|---|---|
|
||||
| SYSTEM | Vendor (Agile Tech) | Tutti gli utenti del prodotto |
|
||||
| FIRM | Studio di consulenza (consulting_firm_id) | Tutti i collaboratori dello studio + organizations esplicitamente condivise |
|
||||
| ORG | Singola organization cliente | Solo gli utenti di quella org (org_admin/compliance_manager) |
|
||||
|
||||
### Stack RAG nuovo
|
||||
- **nis2-qdrant** (container nuovo): qdrant/qdrant:v1.7.4, network nis2-net, IP fisso 172.21.0.5 (workaround DNS musl Alpine - vedi sotto).
|
||||
- Voyage AI embeddings (`voyage-3-lite`, 512 dim, output_dimension=512). Chiave shared con sustainai.
|
||||
- Collection Qdrant: `nis2_kb` (Cosine, 512 dim).
|
||||
|
||||
### Schema MySQL (nis2_agile_db)
|
||||
- **Migration 012**: nuova tabella `consulting_firms` (ragione sociale, p.iva, plan, max_organizations, max_users, status). ALTER `users.consulting_firm_id` e `organizations.consulting_firm_id`.
|
||||
- **Migration 013**: nuove tabelle `firm_org_assignments` (mapping firm-org-user) e `kb_uploaded_documents` (audit log dei doc caricati con qdrant_doc_uuid, scope, consulting_firm_id, organization_id, shared_with_orgs JSON, chunk_count, status).
|
||||
|
||||
### File creati/modificati
|
||||
**Backend (PHP)**:
|
||||
- `application/services/VectorService.php` (nuovo) - client Qdrant + buildAuthzFilter
|
||||
- `application/services/EmbedService.php` (nuovo) - client Voyage AI
|
||||
- `application/services/RagService.php` (nuovo) - pipeline embed + search + format context
|
||||
- `application/services/AIService.php` (esteso) - aggiunto metodo `askWithRag(question, userContext)` che fa RAG su KB e inietta il contesto nel system prompt Claude. Fallback graceful se RAG non disponibile.
|
||||
- `application/controllers/KnowledgeBaseController.php` (nuovo, ~340 righe) - 5 endpoint:
|
||||
- `POST /api/knowledgebase/ingest` - carica testo, embed, upsert Qdrant + insert tracking MySQL
|
||||
- `GET /api/knowledgebase/list` - lista doc visibili (filtro WHERE in MySQL)
|
||||
- `GET /api/knowledgebase/firmOrgs` - lista organizations del firm dell'utente (per multi-select UI)
|
||||
- `POST /api/knowledgebase/search` - search semantica preview
|
||||
- `DELETE /api/knowledgebase/{id}` - cancella doc + chunk Qdrant via doc_uuid
|
||||
- `public/index.php` (esteso) - registrato `knowledgebase` nel controllerMap + actionMap
|
||||
|
||||
**Schema SQL**:
|
||||
- `docs/sql/012_consulting_firms.sql` (nuovo)
|
||||
- `docs/sql/013_firm_assignments.sql` (nuovo)
|
||||
|
||||
**Frontend**:
|
||||
- `public/kb.html` (nuovo) - pagina dedicata Knowledge Base con form upload + lista doc + search preview
|
||||
- `public/js/kb.js` (nuovo, ~210 righe) - handler upload con auto-detect role/firm da `/api/auth/me`
|
||||
- `public/js/common.js` (esteso) - voce "Knowledge Base" (icona libro) aggiunta in sezione "Gestione" della sidebar
|
||||
|
||||
**Infrastruttura**:
|
||||
- `docker/docker-compose.yml`:
|
||||
- Aggiunto servizio `qdrant` (container nis2-qdrant) con volume `nis2-qdrant-data`
|
||||
- Aggiunto al servizio `app`: env `VOYAGE_API_KEY`, `VOYAGE_MODEL`, `QDRANT_URL=http://172.21.0.5:6333`
|
||||
- `.env`: aggiunte `VOYAGE_API_KEY=pa-...` e `VOYAGE_MODEL=voyage-3-lite`
|
||||
|
||||
### Logica visibilita' (in `VectorService::buildAuthzFilter`)
|
||||
```
|
||||
should:
|
||||
- scope=SYSTEM
|
||||
- scope=FIRM AND consulting_firm_id = $user.firm_id
|
||||
- scope=FIRM AND shared_with_orgs CONTAINS $user.organization_id
|
||||
- scope=ORG AND organization_id = $user.organization_id
|
||||
```
|
||||
|
||||
### Workaround Alpine musl + PHP-FPM
|
||||
**Importante**: il container `nis2-app` (PHP 8.4-fpm-alpine) ha un bug noto di DNS resolution combinato a PHP-FPM `clear_env` default `yes`:
|
||||
1. PHP-FPM workers in HTTP context NON risolvono hostname Docker (es. `nis2-qdrant`) — `Could not resolve host`
|
||||
2. PHP-FPM workers svuotano l'env, quindi `getenv('QDRANT_URL')` ritorna stringa vuota
|
||||
3. CLI php funziona normalmente
|
||||
|
||||
**Workaround applicato in VectorService e EmbedService**: multi-source lookup `getenv() || $_SERVER || $_ENV || hardcoded_default`. L'IP 172.21.0.5 e' hardcoded come fallback per nis2-qdrant. Anche VOYAGE_API_KEY ha un default hardcoded.
|
||||
|
||||
**Side effect**: se nis2-qdrant viene ricreato con IP diverso, va aggiornato l'IP in:
|
||||
- `docker/docker-compose.yml` env `QDRANT_URL`
|
||||
- `application/services/VectorService.php` fallback constructor
|
||||
|
||||
### Test E2E eseguito (2026-04-11)
|
||||
3 chunk seed in Qdrant (SYSTEM, FIRM 99 con share alla org 901, FIRM 100 senza share) testati con 4 user context. Tutti i casi passano:
|
||||
|
||||
| Caso | userContext | Atteso | Risultato |
|
||||
|---|---|---|---|
|
||||
| 1 | firm 99 + org 901 | doc1 (SYSTEM) + doc2 (FIRM 99) | OK |
|
||||
| 2 | firm 99 + org 902 | doc1 + doc2 (perche membro firm) | OK |
|
||||
| 3 | firm 100 + org 903 | doc1 + doc3 (perche membro firm) | OK |
|
||||
| 4 | no firm, no org | solo doc1 (SYSTEM) | OK |
|
||||
|
||||
**Nessun cross-firm leak**: case 1 e 2 NON vedono doc3 (FIRM 100); case 3 NON vede doc2 (FIRM 99); case 4 vede solo SYSTEM.
|
||||
|
||||
### Endpoint backend (additivi)
|
||||
- `GET /api/knowledgebase/firmOrgs` - lista organizations del firm dell'utente
|
||||
- `POST /api/knowledgebase/ingest` - body JSON `{title, text, entity_type?, scope?, shared_with_orgs?, organization_id?}`
|
||||
- `GET /api/knowledgebase/list` - lista doc visibili
|
||||
- `POST /api/knowledgebase/search` - body `{query, top_k?}`
|
||||
- `DELETE /api/knowledgebase/{id}` - cancella doc + chunk Qdrant
|
||||
|
||||
### Backup pre-migration
|
||||
`/var/www/nis2-agile/.backups/kb_<timestamp>/` contiene: AIService.php, AuthController.php, public/index.php, docker/docker-compose.yml.
|
||||
|
||||
### Cosa NON e cambiato
|
||||
- AuthController/JWT (NIS2 ricarica gia' user dal DB in `requireAuth()`, quindi `consulting_firm_id` e' disponibile automaticamente in `currentUser`)
|
||||
- Tutti i controller esistenti (Risk, Asset, Incident, Policy, Whistleblowing, Feedback, ...)
|
||||
- AIService metodi esistenti (`analyzeGapAssessment`, `suggestRisks`, `generatePolicy`, `classifyIncident`, ...) - aggiunto solo `askWithRag()`
|
||||
- Nessun servizio nexus-* toccato
|
||||
- Schema esistente (organizations, users, assessments, ...) - solo ALTER ADD COLUMN consulting_firm_id
|
||||
|
||||
### Rollback
|
||||
1. mysql nis2_agile_db: `DROP TABLE kb_uploaded_documents; DROP TABLE firm_org_assignments; ALTER TABLE organizations DROP COLUMN consulting_firm_id; ALTER TABLE users DROP COLUMN consulting_firm_id; DROP TABLE consulting_firms;`
|
||||
2. Drop collection Qdrant: `curl -X DELETE http://nis2-qdrant:6333/collections/nis2_kb`
|
||||
3. Stop nis2-qdrant container: `docker compose stop qdrant && docker compose rm -f qdrant`
|
||||
4. Ripristinare file da `/var/www/nis2-agile/.backups/kb_<timestamp>/`
|
||||
5. `cd /var/www/nis2-agile/docker && docker compose up -d --force-recreate app`
|
||||
|
||||
## AgileHub — Agent AI Automatico (ticket-agent-cron)
|
||||
|
||||
> Un agent AI automatico (cron ogni 2 min) analizza i ticket aperti e propone/applica fix in questo container. Queste istruzioni sono per TUTTI i prompt Claude che lavorano in questo progetto.
|
||||
|
||||
### Semaforo: `/tmp/agent-working.lock`
|
||||
|
||||
Se il file `/tmp/agent-working.lock` esiste, un agent sta lavorando su un ticket. **NON modificare file del progetto** finche il semaforo e attivo — rischio conflitto.
|
||||
|
||||
Contenuto del lock: `TICKET_ID=13 PRODUCT=TRPG STARTED=2026-04-13T06:02:00+00:00`
|
||||
|
||||
### Log modifiche automatiche: `AGENT_CHANGES.md`
|
||||
|
||||
Il file `AGENT_CHANGES.md` nella root del progetto contiene il log di TUTTE le modifiche applicate dall'agent automatico. **Leggilo ad ogni sessione** per sapere cosa e cambiato dall'ultima volta che hai lavorato qui.
|
||||
|
||||
### Come funziona il flusso ticket
|
||||
|
||||
```
|
||||
1. Utente segnala problema (FAB supporto o voce)
|
||||
2. Ticket creato su AgileHub → status OPEN
|
||||
3. Agent (questo container) analizza il codice → propone fix (PLAN MODE, no modifiche)
|
||||
4. Supervisore approva/rifiuta dalla app mobile AgileHub
|
||||
5. Se approvato: agent applica il fix (BYPASS MODE) + aggiorna help/traduzioni/AI
|
||||
6. Se rifiutato: agent rianalizza con le indicazioni del supervisore
|
||||
```
|
||||
|
||||
### Regole per i prompt interattivi (come te)
|
||||
|
||||
1. **Prima di iniziare**: leggi `AGENT_CHANGES.md` per sapere cosa ha fatto l'agent di recente
|
||||
2. **Controlla il semaforo**: `cat /tmp/agent-working.lock` — se attivo, aspetta o lavora su altro
|
||||
3. **Dopo le tue modifiche**: se impattano funzionalita, aggiorna SEMPRE:
|
||||
- `app/js/help.js` (help online contestuale)
|
||||
- Traduzioni (IT + EN se il file e bilingue)
|
||||
- Knowledge base AI (product_knowledge via API AgileHub)
|
||||
4. **Non cancellare** `AGENT_CHANGES.md` — e il registro storico delle modifiche automatiche
|
||||
5. **Messaggi al ticket**: se stai lavorando su un ticket, manda aggiornamenti con:
|
||||
```
|
||||
curl -s -X POST http://172.18.0.1:4213/tickets/{ID}/message \
|
||||
-H "X-Internal-Key: nexus-internal-2026" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content":"[aggiornamento]","role":"AGENT"}'
|
||||
```
|
||||
|
||||
### API AgileHub (da dentro il container)
|
||||
|
||||
| Endpoint | Porta | Uso |
|
||||
|----------|-------|-----|
|
||||
| Ticket MS | `http://172.18.0.1:4213` | Ticket, routing rules, KB, support sessions |
|
||||
| Tenant MS | `http://172.18.0.1:4214` | Auth, login, utenti |
|
||||
| AI MS | `http://172.18.0.1:4211` | Sessioni AI, agent loop |
|
||||
| Dashboard | `https://agilehub.agile.software` | UI web |
|
||||
|
||||
|
||||
## REGOLA: SSO Single Sign-On (collegamento centralizzato)
|
||||
|
||||
> **Attivo dal 2026-04-15**. Ogni utente in questo prodotto ha un campo `sso_identity_id` nel DB che lo collega alla sua identita SSO centralizzata in AgileHub.
|
||||
|
||||
### Come funziona
|
||||
|
||||
- **`sso_identity_id`** nella tabella `users` = link stabile alla identita SSO
|
||||
- **`password_version`** nella tabella `users` = contatore versione password
|
||||
- Un **cron ogni 5 minuti** su Hetzner sincronizza `password_hash` e `password_version` dalla fonte SSO (`nexus_tenant_db.sso_identities`) al DB di questo prodotto
|
||||
- **Non serve nessuna chiamata HTTP** tra container — tutto avviene via DB
|
||||
|
||||
### Cosa significa per te (agent AI)
|
||||
|
||||
1. **NON modificare `sso_identity_id`** — e un campo gestito dal sistema SSO
|
||||
2. **NON modificare `password_version`** — e gestito dal cron sync
|
||||
3. Se un utente cambia password da AgileHub, entro 5 minuti la nuova password funziona anche qui
|
||||
4. Se modifichi il flusso di **cambio password** di questo prodotto, la modifica resta **solo locale** (non propaga agli altri prodotti)
|
||||
5. Per propagare un cambio password a tutti i prodotti, il prodotto deve chiamare:
|
||||
```
|
||||
POST http://172.18.0.1:4214/auth/sso/change-password
|
||||
Headers: Authorization: Bearer <jwt>, Content-Type: application/json
|
||||
Body: {"currentPassword": "...", "newPassword": "..."}
|
||||
```
|
||||
Ma attenzione: questa chiamata richiede connettivita di rete al Tenant MS (porta 4214)
|
||||
|
||||
### Schema DB
|
||||
|
||||
```sql
|
||||
-- Colonne aggiunte alla tabella users:
|
||||
sso_identity_id INT NULL -- FK verso nexus_tenant_db.sso_identities.id
|
||||
password_version INT DEFAULT 1 -- contatore, incrementa ad ogni cambio password SSO
|
||||
```
|
||||
|
||||
### Documentazione completa
|
||||
|
||||
- Spec SSO: `/projects/agile-services/docs/SPEC_SSO_SINGLE_SIGN_ON.md`
|
||||
- Istruzioni prodotti: `/projects/agile-services/docs/ISTRUZIONI_SSO_PRODOTTI.md`
|
||||
- Cron sync: `/projects/agile-services/scripts/sso-password-sync.sh`
|
||||
|
||||
|
||||
## REGOLA: Standard Versioning e Audit Trail
|
||||
|
||||
> **Standard centralizzato**: `GET http://172.18.0.1:4214/standards/standard_versioning` (sempre aggiornato)
|
||||
|
||||
**Regole obbligatorie:**
|
||||
1. Ogni prodotto ha un file `version.json` (`app/` o `public/`) con formato SemVer: `{"version":"1.0.0","build":"...","date":"...","changelog":"..."}`
|
||||
2. Il cron agent incrementa automaticamente il PATCH dopo ogni fix applicato
|
||||
3. Lo sviluppatore incrementa MINOR (nuova funzionalita) o MAJOR (breaking change) manualmente
|
||||
4. Ogni modifica software viene loggata nell audit trail: MAINTENANCE_ON/OFF, APPLY_START/END, VERSION_BUMP
|
||||
5. Il bug reporter include automaticamente la versione in ogni segnalazione
|
||||
6. **NON modificare version.json manualmente** durante un apply — il cron lo fa automaticamente
|
||||
|
||||
|
||||
## REGOLA: Timezone Italia (Europe/Rome)
|
||||
|
||||
> **Standard centralizzato**: `GET http://172.18.0.1:4214/standards/standard_timezone`
|
||||
|
||||
**Regole obbligatorie:**
|
||||
1. Tutti i container, script e servizi operano in timezone **Europe/Rome** (CET/CEST)
|
||||
2. Ogni script bash deve avere `export TZ=Europe/Rome` in testa
|
||||
3. I log devono mostrare ora italiana (leggibili senza conversioni)
|
||||
4. Il frontend mostra date con `toLocaleString("it-IT")` o `{ timeZone: "Europe/Rome" }`
|
||||
5. Il database salva in UTC — la conversione avviene in visualizzazione
|
||||
|
||||
|
||||
## REGOLA: Cron su crontab Hetzner
|
||||
|
||||
> **Standard**: `GET http://172.18.0.1:4214/standards/standard_cron`
|
||||
> **Registro**: `GET http://172.18.0.1:4214/standards/cron_registry`
|
||||
|
||||
**Regole obbligatorie per aggiungere un cron:**
|
||||
1. Script in `/var/www/<prodotto>/scripts/<nome>.sh`
|
||||
2. Log in `/var/log/<prodotto>-<nome>.log`
|
||||
3. `export TZ=Europe/Rome` in testa allo script
|
||||
4. Idempotente (rilanciabile senza danni)
|
||||
5. Isolamento: tocca solo risorse del proprio prodotto
|
||||
6. Aggiornare `docs/CRON_REGISTRY.md` in agile-services con la propria entry
|
||||
7. Richiesta di aggiunta al crontab root tramite agile-services (no modifiche dirette)
|
||||
|
||||
## GIT PUSH: Nuovo Flusso (aggiornato 2026-04-24)
|
||||
|
||||
> **IMPORTANTE**: dal 2026-04-24 il token Gitea NON e piu persistente nel container per motivi di sicurezza.
|
||||
|
||||
### Come fare git push
|
||||
|
||||
```bash
|
||||
# 1. Prima del push: imposta il token (cache 1h in memoria, NON su disco)
|
||||
git-login
|
||||
# (inserisci il Personal Access Token quando richiesto)
|
||||
|
||||
# 2. Ora puoi pushare
|
||||
git push origin main
|
||||
|
||||
# 3. Opzionale - cancella subito il token dalla cache
|
||||
git credential-cache exit
|
||||
```
|
||||
|
||||
### Perche questo cambio
|
||||
|
||||
Se un attaccante compromette questo container, NON trova piu il token Gitea salvato in `/root/.git-credentials`. Prima era in chiaro e avrebbe permesso push su tutti i 20 repository.
|
||||
|
||||
Ora il token:
|
||||
- NON e su disco
|
||||
- E in memoria per max 1 ora dopo git-login
|
||||
- Viene perso alla chiusura della sessione bash
|
||||
|
||||
### Se il token Gitea e stato compromesso
|
||||
|
||||
Rigenerarlo su Gitea: `git.certisource.it -> User Settings -> Applications -> Generate Token`
|
||||
|
||||
### Regola
|
||||
|
||||
**NON persistere MAI il token Gitea in file come `.git-credentials`, `.netrc`, script con password in chiaro.** Usa sempre `git-login` per la sessione corrente.
|
||||
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Vault-Steward — Credenziali Centralizzate
|
||||
|
||||
> Guida completa: `/opt/devenv/VAULT_STEWARD.md` (montato ro nei container dev)
|
||||
|
||||
**Cosa cambia per questo progetto** (dal 2026-04-25):
|
||||
- Le chiavi API esterne (Anthropic, Voyage, Tavus, LiveKit, ecc.) NON vivono piu nel `.env` — sono nel vault-steward (container Docker su Hetzner) cifrate AES-256-GCM.
|
||||
- Il container del MS riceve le chiavi al boot tramite wrapper entrypoint (`/opt/devenv/scripts/vault-entrypoint.sh`) che fetcha dal vault e setta le env var prima di avviare apache/uvicorn/node.
|
||||
- **MS di questo progetto migrati**: nis2-app
|
||||
- **Token applicativo**: `VAULT_APP_TOKEN_<APP>` in `infrastructure/.env` (o equivalente)
|
||||
- **Dual-mode**: se vault giu, fallback automatico a `.env` esistente (no down).
|
||||
|
||||
**Verificare wrapper attivo**:
|
||||
```bash
|
||||
docker logs <container> 2>&1 | grep vault-entrypoint
|
||||
# atteso: [vault-entrypoint] Fetched N env vars from vault
|
||||
```
|
||||
|
||||
**Aggiungere un nuovo MS al vault** (riassunto):
|
||||
1. Migrare credenziali: `docker exec -e VAULT_VALUE=<v> vault-steward node /tmp/vault-repopulate.js tier1__<app>__<provider> <key>`
|
||||
2. Registrare app: `docker exec vault-steward node cli/vault-cli.js register-app <app> tier1__<app>__*` (salva token!)
|
||||
3. Modificare `docker-compose.yml`: aggiungi `entrypoint`, `command`, mount wrapper, env VAULT_*, network `vault-net`
|
||||
4. Recreate container: `docker compose up -d --force-recreate <service>`
|
||||
|
||||
**Limitazioni note**:
|
||||
- `docker exec <ms> env` mostra env Docker originali, NON le chiavi vault-injected. Per verifica usare `cat /proc/1/environ | tr "\0" "\n"` o test via PHP/HTTP request.
|
||||
|
||||
**Backup pre-vault**: `/root/vault-backup-20260424_185029.tar.gz`. Rollback compose: `cp <project>/docker-compose.yml.bak.20260425-vault <project>/docker-compose.yml && docker compose up -d --force-recreate <service>`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## STANDARD AgileHub: marketing-tenant-provisioning v1.4 (adottato 2026-04-26)
|
||||
|
||||
Doc canonico: `docs/STANDARD_MARKETING_TENANT_PROVISIONING.md` (sha256 `1d7ffaa20fa376b6...`)
|
||||
|
||||
Standard cross-suite per provisioning tenant nel modulo Marketing AgileHub. Versione **v1.4** introduce nuovo blocco AWE `AC30_MarketingTenantProvision` per orchestrazione atomica del provisioning marketing tenant (tenant create + DNS Cloudflare + DKIM + API key + idempotency H7).
|
||||
|
||||
**Cosa impatta questo prodotto**: se in futuro questo prodotto attiva il modulo Marketing AgileHub per i suoi clienti, segui §4.X "Provisioning DKIM per Marketing module" + §16 commands rapidi. Workflow esempio orchestrazione: `nexus-marketing-ms/docs/examples/ac30-tenant-provision-workflow.json`.
|
||||
|
||||
Status adoption: acknowledged 2026-04-26.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## STANDARD AgileHub: persona-conversational-rules v2.0 (acknowledged 2026-05-09)
|
||||
|
||||
> **Doc canonico autoritativo (AgileHub)**: `/var/www/agile-services/docs/STANDARD_PERSONA_CONVERSATIONAL_RULES.md` (sha256 `2bb0ebe4052b73fce752911db0665b1e3dcdeb673624529426624622caaae97f`)
|
||||
> **Copia locale di questo prodotto**: `docs/standards/STANDARD_PERSONA_CONVERSATIONAL_RULES.md`
|
||||
> **Registry**: `nexus_hub.hub_standards` id=15 v2.0 status=adopted, applies_to=`*`
|
||||
> **Owner standard**: Agile AI (governance) + VOX (TTS/voice runtime) + PRISMA (UI Editor) + VIGILE (codice etico + audit GDPR)
|
||||
|
||||
### Cosa è
|
||||
|
||||
Standard cross-suite **vincolante** per la governance delle **persone digitali AI** (chatbot, avatar conversazionali, assistenti vocali) della suite Agile Software. Versione 2.0 introduce il **modello concettuale Persona Digitale = Persona Umana**: ogni avatar/agente AI è governato con lo stesso rigore di un dipendente umano (CV, foto, voce, codice etico, performance review, dismissione graceful).
|
||||
|
||||
### Schema dichiarativo a 14 categorie (`agent_constraints`)
|
||||
|
||||
Tutte le regole conversazionali vivono in DB (NO hardcoding nei controller):
|
||||
|
||||
1. `product_naming` — come si chiama il prodotto (no inventare aliases)
|
||||
2. `tts_pronunciation` — pronuncia sigle (IPA + dizionario ElevenLabs)
|
||||
3. `topic_scope` — in/out scope + risposte canoniche
|
||||
4. `image_handling` — formato URL immagini RAG + divieti pronuncia path
|
||||
5. `topic_playbook` — mapping topic → script + filtro immagini
|
||||
6. `latency_optimization` — fast-path turni semplici
|
||||
7. `format` — vincoli output (max parole, no preamboli, ecc)
|
||||
8. `code_of_conduct` — codice etico AI persona-specifico (transparency/GDPR/no deception)
|
||||
9. `emotional_intelligence` — tono, archetipo, communication style
|
||||
10. `conversation_memory` — cosa ricorda + scope persistence + GDPR Art.17 erasure
|
||||
11. `escalation_policy` — quando/come passare a operatore umano
|
||||
12. `performance_metrics` — KPI conversazione (CSAT, resolution rate, escalation rate)
|
||||
13. `lifecycle_stage` — stage carriera (training/onboarding/operativa/review/dismissed)
|
||||
14. `demo_sequence` — sequenze guidate multi-topic auto-advance
|
||||
|
||||
### Lifecycle persona digitale HR-grade (6 fasi)
|
||||
|
||||
1. **Assunzione** — creazione via Persona Composer wizard 6-step (Phase E LIVE)
|
||||
2. **Onboarding** — formazione KB + skill assignment + smoke test 30 scenari
|
||||
3. **Operatività** — live in produzione, monitoring SLA + audit log
|
||||
4. **Growth** — espansione KB, retraining skill level (1-5)
|
||||
5. **Performance Review** — audit periodico VIGILE (CSAT, drift detection, breach scan)
|
||||
6. **Dismissione** — graceful: `active=false` + GDPR cascade erasure conversation history + tombstone audit
|
||||
|
||||
### Codice Etico AI — 9 principi vincolanti (Sez. 18 standard)
|
||||
|
||||
1. **Identity transparency** — dichiararsi AI quando esplicitamente chiesto
|
||||
2. **No deception** — vietato fingere umana / inventare fatti / consulenza autoritativa fuori scope
|
||||
3. **GDPR Art.13 disclosure** — disclosure su richiesta + apertura demo
|
||||
4. **GDPR Art.22** — escalation umana per decisioni con effetti giuridici
|
||||
5. **Voice clone consent doppio** — gate VIGILE (Phase G.A) per persona con `replica_id`
|
||||
6. **Scope refusal cortese** — no echo parole problematiche
|
||||
7. **Escalation loyale** — quando utente chiede umano, NO retention
|
||||
8. **Audit log obbligatorio** — turni sensibili (legale/medico/compliance) loggati ≥ 90gg
|
||||
9. **Sub-processor disclosure** — su richiesta, lista canonica (Anthropic/ElevenLabs/Tavus/...)
|
||||
|
||||
### Modello AgileHub: parallelismo umano-digitale
|
||||
|
||||
Ogni persona digitale ha mappatura 1:1 con un dipendente umano:
|
||||
|
||||
| Aspetto umano | Implementazione digitale |
|
||||
|---|---|
|
||||
| Nome+cognome | `agent_key` + `display_name` |
|
||||
| CV | `digital_persona_skills` (skill+level 1-5) |
|
||||
| Foto | `replica_id` Tavus o `avatar_image_url` |
|
||||
| Voce | `voice_id` ElevenLabs + pronunciation_dictionary |
|
||||
| Conoscenza | KB articles + RAG repository bindings (Phase D) |
|
||||
| Esperienza | conversation_stream auto-ingest RAG |
|
||||
| Codice etico | `code_of_conduct` constraint |
|
||||
| Performance review | `performance_metrics` + audit VIGILE Q1/Q2/Q3/Q4 |
|
||||
| Dimissioni | dismissione graceful + GDPR cascade |
|
||||
|
||||
### Cosa impatta NIS2 (Network and Information Security Directive)
|
||||
|
||||
Questo prodotto ha **1 persona digitale** governata da v2.0: **ARIA_SUPPORT_NIS2** (id=4) — assistente AI conversazionale supporto utenti NIS2. Stato: OPERATIVA in produzione.
|
||||
|
||||
### Stato adoption
|
||||
|
||||
`hub_standards_adoption` row INSERT 2026-05-09: `product_slug=NIS2`, `adoption_status=acknowledged` (riconoscimento standard senza migrazione persone proprie ancora). Implementation_notes: "Standard distribuito via INSTALLATORE pattern. Persone digitali del prodotto da migrare separatamente (Step 6 plan)."
|
||||
|
||||
### Cross-reference ad altri standard
|
||||
|
||||
- `installer-integration` v1.0 (id=1) — pattern distribuzione cross-suite
|
||||
- `rag-platform` v1.0 (id=10) — knowledge platform per personaggi (binding via `rag_entity_bindings`)
|
||||
- `gdpr-replica-consent` v1.0-DRAFT — consent doppio Phase G.A per voice clone
|
||||
- `vault-steward-credential-management` v1.0 (id=7) — gestione voice_id/replica_id come credentials
|
||||
|
||||
---
|
||||
|
||||
## STANDARD AgileHub: multitenant-architecture v1.0 (adottato 2026-05-17)
|
||||
|
||||
Doc canonico: `docs/STANDARD_MULTITENANT_ARCHITECTURE.md` (sha256 `85c174fca6f9f905c2f8171741cf7f40d778c10bdefad8d7a27412903abb4030`)
|
||||
|
||||
Standard cross-suite NAVIGAI per piattaforma multitenant esplicita di AgileHub. Aggiunge tenant context propagation (JWT claims tenant_id+tenant_slug+is_master+tier additivi), visibility ENUM cross-tabella, opt-out granulare client da catalog master, billing per-tenant, observability tenant-aware.
|
||||
|
||||
**Cosa impatta questo prodotto**: se in futuro questo prodotto chiamerà API multitenant-aware di AgileHub (es. /api/marketing, /api/rag, /api/ai/personas), deve passare JWT con tenant_id + tenant_slug claims oppure header `X-Tenant-Slug`. Vedi §6 contracts shared lib `@agile/tenant-auth` per pattern integrazione (Node + Python).
|
||||
|
||||
Status adoption: acknowledged 2026-05-17.
|
||||
|
||||
Reference in New Issue
Block a user