# STANDARD AgileHub — Installer Integration (canonico)

> **Autorità**: AgileHub (single source of truth per la suite Agile Software).
> **Versione**: 1.0.1 — 2026-04-19 (patch: chiarimento payload tenants/report)
> **Stato**: ADOTTATO. Sostituisce qualsiasi proposta prodotto in caso di conflitto.
> **Destinatari**: team TRPG, SustainAI, NIS2, TAXAI (AllTax), LG231, DFM, MKTG, ALLRISK, WMS, MADEBYCLOUD, CertiSource.
> **Spec origine**: `AGILEHUB_INSTALLER_INTEGRATION_SPEC.md` v1.0 (TRPG, 2026-04-19) — recepita con override sotto.
> **Registry DB**: record master in `nexus_hub.hub_standards` (slug=`installer-integration`, version=`1.0.1`). Questo file è una **copia derivata** — in caso di disallineamento vince il DB.

## Changelog

### v1.0.1 — 2026-04-19 (patch, non breaking)
- **§3.1 `POST /api/tenants/report`**: chiarito che `license_key` è **obbligatorio** nel body (era implicito via "firma HMAC obbligatoria" ma non listato nel payload d'esempio). Serve al middleware HMAC per il lookup della `hub_signing_key`. Origine: smoke test TRPG 2026-04-19 21:15 — 404 LICENSE_NOT_FOUND senza license_key. Decisione AgileHub: consistency > minimal payload (defence in depth anti-tamper).
- TRPG già conforme via commit `5c1aa2e` (2026-04-19).
- Altri prodotti: allineare payload `tenants/report` aggiungendo `license_key` string.

### v1.0 — 2026-04-19
- Versione iniziale adottata. Spec origine TRPG recepita con override AgileHub.

---

## 1. Portata e autorità

Questo documento definisce **il contratto unico** fra AgileHub e i prodotti installati on-premise (o white-label) della suite. Vale per:

- Registrazione prodotti in AgileHub (`hub_products`)
- Provisioning istanze cliente (orchestrator SSH + installer script prodotto)
- Licensing + heartbeat + alert
- Onboarding tenant (consulting_firms) cross-istanza
- Firma HMAC + vault SSH

**Regola di precedenza**: in caso di conflitto fra una proposta prodotto (es. `*_INTEGRATION_SPEC.md` nel loro `docs/`) e questo standard, **vince questo standard**. Deviazioni motivate vanno chieste via ticket AgileHub con tag `standard-exception`.

---

## 2. Decisioni AgileHub (override sulla spec TRPG v1.0)

### 2.1 Hostname ufficiale

| Ruolo | Hostname | Uso |
|-------|----------|-----|
| Hub UI | `https://agilehub.agile.software` | Dashboard admin, `/admin/products/*` |
| Hub API (licensing) | `https://agilehub.agile.software/api/license/*` | endpoint validate/activate/register/report |
| Hub API (installer orchestrator) | `https://agilehub.agile.software/api/installer/*` | wizard, job status, log streaming |

> **NO `hub.agile.software`**. I prodotti che chiamano `hub.agile.software` vanno corretti prima del pilota.

### 2.2 Stack tecnico

| Layer | Scelta |
|-------|--------|
| Backend licensing/installer | **Node.js 20 + Express** (pattern `nexus-*-ms`), microservizio nuovo `nexus-hub-ms` porta **4217** |
| DB | **MySQL host Hetzner** (172.18.0.1:3306), DB dedicato **`nexus_hub`**, user `nexus_user` |
| Frontend | **Next.js 15 + React 19** in `nexus-dashboard`, nuova sezione `/admin/products/*` |
| Job queue (Fase 3) | **BullMQ su Redis** (da aggiungere infra). Fino a Fase 2: cron + status polling |
| Email | Microservizio esistente **`email-automation-ms`** (NO SendGrid/MailHog esterni) |
| Secret vault | **AES-256-GCM env-based**, chiave in `/etc/agilehub/vault.env` (NO HashiCorp Vault/KMS) |
| SSH worker | **ssh2** (npm) invocato da `nexus-hub-ms`, chiave decifrata on-demand |

### 2.3 Prefisso tabelle e naming DB

- DB dedicato: `nexus_hub`
- Tabelle: prefisso `hub_` mantenuto (compat con spec origine). Accesso esclusivo da `nexus-hub-ms`.
- Cross-DB query verso `nexus_ticket_db`, `nexus_tenant_db`, `nexus_lead_db` sono permesse solo via GRANT dedicato a `nexus_user` (pattern già in uso per SSO).

### 2.4 Ruoli

| Ruolo | Permessi |
|-------|----------|
| `hub_admin` | Tutto tranne provisioning SSH |
| `hub_installer` | **Nuovo**. Lettura `hub_*`, esecuzione wizard, decrypt chiavi SSH con audit obbligatorio |
| `hub_support` | Solo lettura `hub_instances`, `hub_tenants`, `hub_license_heartbeats` |

Il ruolo `hub_installer` è **richiesto** per Fase 3. Non riutilizzare `hub_admin`: blast radius troppo ampio.

### 2.5 Versioning

Recepita la regola TRPG: **version mai hardcodata nei seed o nelle migration**. La hub la registra da payload heartbeat. Per `hub_products.version` (ultima release disponibile) leggere on-demand via `GET https://<product>.agile.software/version.json` oppure aggiornare via `POST /api/products/:slug/version` (admin-only).

### 2.6 Integrazione obbligatoria con SSO

`hub_tenants.owner_email` **DEVE** essere foreign-key logica verso `sso_identities.email` (DB `nexus_tenant_db`). Al provisioning di un nuovo tenant:

1. `nexus-hub-ms` POST `/api/auth/admin/tenants/create` sull'istanza
2. L'istanza crea `consulting_firm` + `user` locale
3. `nexus-hub-ms` replica l'identità in `sso_identities` (se non esiste)
4. Prima login dell'owner → SSO flow standard (Fase 2 SSO)

**Prodotti che non hanno ancora SSO dual-mode**: finché non è attivo, `hub_tenants` funziona stand-alone ma `owner_email` deve comunque essere univoco cross-istanza.

### 2.7 Deprecazione `products.json`

`/opt/agent-ai/hub/products.json` è **deprecato** dalla Fase 2. Entro la Fase 2 completa:
- `hub_products` diventa la sorgente di verità
- La UI legge da `hub_products`, non più da `products.json`
- `products.json` resta come fallback statico per landing page esterne, generato da cron da `hub_products`

### 2.8 Multi-prodotto da subito

Fase 1 va implementata **generica** (non TRPG-specific). Lo schema, gli endpoint e le firme HMAC supportano `product_slug` variabile fin dal primo giorno. Il seed iniziale è per TRPG, ma il codice non hardcoda nulla.

---

## 3. Contratto API canonico

### 3.1 Endpoint hub (Istanza → AgileHub)

Tutti su `https://agilehub.agile.software/api/...`, header obbligatorio:
```
X-Product-Signature: hmac_sha256(body, HUB_SIGNING_KEY_<PRODUCT_SLUG_UPPER>)
Content-Type: application/json
```

| Endpoint | Scopo | Chiamato da |
|----------|-------|-------------|
| `POST /api/license/activate` | Prima attivazione dopo install | `install-<slug>.sh` |
| `POST /api/license/validate` | Heartbeat periodico (24h default, 1h se anomalia) | cron istanza |
| `POST /api/instances/register` | Registrazione finale istanza | `install-<slug>.sh` |
| `POST /api/tenants/report` | Sync tenant create/update/archive | istanza, on-change |
| `GET /api/products/:slug/version` | Ultima versione disponibile | `update-<slug>.sh` |

Payload: identici alla spec TRPG §6 (validate/activate/register/report). Campi obbligatori aggiuntivi in **tutti** i body:
- `product_slug` — sempre, anche dove la spec TRPG lo omette implicitamente
- `license_key` — **sempre** (v1.0.1 clarification). Serve al middleware HMAC per lookup di `hub_signing_key` prima della verifica firma. Include `tenants/report` che nella spec origine non lo listava esplicitamente.

**Eccezione**: `POST /api/license/activate` non porta `X-Product-Signature` (primo handshake, la chiave non esiste ancora) ma deve comunque includere `license_key` per il match iniziale.

### 3.2 Endpoint istanza (AgileHub → Istanza)

Ogni prodotto della suite **deve** esporre:

| Endpoint | Scopo | Auth |
|----------|-------|------|
| `POST /api/auth/admin/tenants/create` | Onboarding tenant da hub | Bearer JWT service + `X-Hub-Signature` |
| `POST /api/auth/admin/tenants/:id/suspend` | Sospensione tenant | idem |
| `POST /api/auth/admin/tenants/:id/resume` | Riattivazione tenant | idem |
| `GET /api/auth/admin/health` | Health check completo per hub | API key service |

**Shape risposta**: identica alla spec TRPG §5.2. Ogni prodotto implementa il proprio endpoint ma lo shape è vincolante.

### 3.3 Installer script non-interattivo (obbligatorio per prodotti orchestrati)

Ogni prodotto della suite che vuole supportare provisioning orchestrato da AgileHub **deve** fornire uno script:

```
install-<slug>.sh --non-interactive --json-output \
  --slug=... --domain=... --client-name=... --admin-email=... --admin-name=... \
  --license-key=... --hub-url=https://agilehub.agile.software \
  --<provider-key-1>=... --<provider-key-2>=... \
  [--smtp-host=... ...] [--force-reinstall]
```

**Exit codes standard** (identici per tutti i prodotti):

| Codice | Significato |
|--------|-------------|
| 0 | Success |
| 10 | Preflight failed (docker, RAM, disk, porte) |
| 20 | Secret generation failed |
| 30 | Hub activation failed (license invalid) |
| 40 | Docker load/up failed |
| 50 | Migration DB failed |
| 60 | Seed/admin creation failed |
| 70 | SSL setup failed |
| 80 | Verify-install failed |
| 90 | Internal error |

**JSON output**: shape identica a spec TRPG §5.1. Campo `product_slug` obbligatorio in entrambi i rami (success/failure).

---

## 4. Schema DB canonico (DB `nexus_hub`)

Recepito integralmente dallo schema TRPG §3.1 (8 tabelle):

- `hub_products`
- `hub_instances`
- `hub_instance_provisioning_logs`
- `hub_licenses`
- `hub_license_heartbeats`
- `hub_license_alerts`
- `hub_tenants`
- `hub_ssh_credentials`

**Modifiche AgileHub**:

1. `hub_products.framework` VARCHAR(32) NULL — aggiunto, indica stack prodotto (`php-vanilla`, `node-express`, `nextjs`, ecc.) utile all'orchestrator
2. `hub_instances.sso_enabled` BOOLEAN DEFAULT FALSE — aggiunto, indica se il prodotto ha SSO attivo su quell'istanza
3. `hub_tenants.sso_identity_id` INT NULL — FK logica a `sso_identities.id` (riempito quando SSO attivo)
4. Tutte le tabelle hanno `tenant_id INT NULL` per compat futuro con multi-tenancy hub (oggi NULL, riservato)

Migration canonical: `nexus-hub-ms/migrations/001-initial-schema.sql` (da creare). **Sub-approval obbligatoria** prima dell'esecuzione su produzione (maintenance mode come da CLAUDE.md).

---

## 5. Sicurezza

### 5.1 Firma HMAC

- **Algoritmo**: HMAC-SHA256
- **Chiave**: `HUB_SIGNING_KEY_<PRODUCT_SLUG_UPPER>` (es. `HUB_SIGNING_KEY_TRPG`, `HUB_SIGNING_KEY_SUSTAINAI`)
- **Generazione**: `openssl rand -hex 32`
- **Storage**: in `/etc/agilehub/vault.env` sull'host AgileHub + `.env` di ogni istanza (propagata da installer al momento di `activate`)
- **Rotazione**: ogni 6 mesi, bidirezionale coordinata

### 5.2 SSH vault

- Cifratura: AES-256-GCM
- Master key: `HUB_VAULT_KEY` in `/etc/agilehub/vault.env` (NON in DB, NON in repo git)
- Ogni decrypt logga in `hub_audit_logs` con `user_id`, `timestamp`, `source_ip`, `purpose`
- Sudo whitelist sul server target: file `/etc/sudoers.d/<slug>-installer` con binari strettamente necessari

### 5.3 JWT service-to-service

- Algoritmo: RS256
- Chiave privata AgileHub + chiave pubblica distribuita ai prodotti al momento dell'attivazione
- Claim obbligatori: `iss=agilehub`, `aud=<product_slug>`, `role=service`, `exp` ≤ 5 minuti
- Ogni prodotto verifica `iss` + `aud` + `exp` + firma

---

## 6. Fasi di rollout (coordinate cross-prodotto)

| Fase | Durata | Chi fa cosa | Bloccante per |
|------|--------|-------------|---------------|
| **Fase 1** — API licensing hub | 2-3 gg | AgileHub: `nexus-hub-ms` + migration `nexus_hub` + 5 endpoint + seed 11 prodotti | Prima installazione cliente qualsiasi prodotto |
| **Fase 1b** — Installer script prodotto | 3-5 gg/prodotto | Ogni prodotto: `install-<slug>.sh` non-interattivo + `update-<slug>.sh` + `/api/auth/admin/tenants/*` endpoint | Pilota white-label di quel prodotto |
| **Fase 2** — UI Prodotti read-only | 3-4 gg | AgileHub: sidebar "Prodotti", elenco, detail read-only, heartbeat dashboard | Visibilità pilota |
| **Fase 3** — Orchestrator + wizard | 6-8 gg | AgileHub: wizard 5-step, SSH worker, log streaming, rollback, BullMQ, encrypt vault | Onboarding cliente self-service |
| **Fase 4** — Multi-prodotto generalizzato | 2-3 gg | AgileHub: template wizard per prodotto, `installer_orchestrator_config` drive-based, billing hook | Scale-up suite |

**Pilota**: TRPG primo. Dopo pilota OK, checklist per onboarding secondo prodotto (SustainAI probabile next).

---

## 7. Obblighi prodotti della suite

Per essere "orchestrabile" da AgileHub, un prodotto **DEVE**:

1. ✅ Fornire `install-<slug>.sh --non-interactive --json-output` con exit codes e shape JSON canonici
2. ✅ Fornire `update-<slug>.sh` (Fase 3, no urgenza) con stesso pattern
3. ✅ Esporre `GET /version.json` con `{version, released_at, changelog_url}`
4. ✅ Esporre `GET /api/auth/admin/health` autenticato
5. ✅ Esporre `POST /api/auth/admin/tenants/create|:id/suspend|:id/resume` con HMAC + JWT service
6. ✅ Chiamare `POST /api/license/activate` alla fine di `install-<slug>.sh`
7. ✅ Avere un cron `license-heartbeat.sh` che chiama `POST /api/license/validate` ogni 24h (1h se anomalia)
8. ✅ Chiamare `POST /api/tenants/report` ad ogni create/update/archive consulting_firm
9. ✅ Gestire stati licenza: `valid → read_only (48h grace) → locked (168h)` con banner UI maintenance
10. ✅ Propagare `HUB_SIGNING_KEY_<SLUG>` nel `.env` istanza al momento dell'attivazione

Un prodotto che **non** rispetta questi 10 punti non può fare parte del catalogo installer AgileHub. Può restare nel menu `products.json` come link esterno (`installer_type=external_link`) finché non si adegua.

---

## 8. Domande aperte — risposte ufficiali

Le 10 domande di §11 della spec TRPG trovano risposta nel capitolo 2 di questo doc. Riepilogo:

1. **Framework hub**: Node.js/Express (non PHP).
2. **DB**: MySQL host Hetzner, DB dedicato `nexus_hub`.
3. **Job queue**: cron fino a Fase 2, BullMQ/Redis da Fase 3.
4. **UI**: Next.js 15 + React 19 (nexus-dashboard).
5. **Vault SSH**: AES-256-GCM env-based.
6. **Monitoring**: `/health` endpoint + cron watchdog esistente. Prometheus opzionale in Fase 4.
7. **Ruolo installer**: nuovo `hub_installer` separato da `hub_admin`.
8. **Email**: `email-automation-ms` esistente.
9. **Multi-prodotto**: generico da Fase 1, seed TRPG ma codice agnostic.
10. **Billing**: nessun Stripe oggi. `hub_customers` placeholder, billing in Fase 4.

---

## 9. Prossimi passi

1. **AgileHub**: scaffold `nexus-hub-ms` + migration `001-initial-schema.sql` (sub-approval richiesta)
2. **AgileHub**: distribuire questo documento a tutti i prodotti della suite via SSH Hetzner
3. **TRPG**: adeguare `install-trpg.sh` al contratto §3.3 (hostname `agilehub.agile.software`, exit codes canonici, JSON shape)
4. **TRPG**: implementare `/api/auth/admin/tenants/*` endpoint con HMAC + JWT (§3.2)
5. **Suite**: ogni team leggere questo doc e aprire ticket AgileHub con tag `installer-readiness` per dichiarare quando saranno pronti

---

## 10. Riferimenti

- Spec origine TRPG: `/var/www/trpg-agile/docs/AGILEHUB_INSTALLER_INTEGRATION_SPEC.md` (v1.0, 2026-04-19)
- Roadmap TRPG: `/var/www/trpg-agile/docs/INSTALLER_ROADMAP.md`
- White-label TRPG: `/var/www/trpg-agile/docs/INSTALLER_WHITELABEL.md`
- Licensing model TRPG: `/var/www/trpg-agile/docs/PROTEZIONE_FASE4_LICENSING.md`
- Multi-studio TRPG: `/var/www/trpg-agile/docs/MULTI_STUDIO_SPEC.md`
- SSO AgileHub: `/projects/agile-services/docs/SPEC_SSO_SINGLE_SIGN_ON.md`
- SSO fasi: `/projects/agile-services/docs/SSO_FASI_IMPLEMENTAZIONE.md`
- CLAUDE.md AgileHub: `/projects/agile-services/CLAUDE.md` (regole maintenance + agent + escalation)

---

**Firma autorità**: questo documento è **canonico** per la suite Agile Software. Modifiche richiedono consenso AgileHub + notifica a tutti i prodotti della suite.

**Versione**: 1.0 — 2026-04-19
**Prossima revisione**: dopo completamento pilota TRPG (stimata 2026-05-31).
