[CONTEXT+MKTG] Contesto sessione + HTML migliorati per comunicazione terze parti
- CONTEXT_LAST_SESSION.md: documento completo di tutto lo sprint B2B - mktg-api-doc.html: Quick Start box con chiave attiva, flusso visivo 4 step, curl pronti - integrazioniext.html tab Inviti: tabella "Chi fa cosa" per ruolo, sezione mktg-agile con chiave API + 3 curl pronti, Quick Start aggiornato con tabella risorse per destinatario Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
13eb8ae8a8
commit
f7347ccd8c
126
docs/context/CONTEXT_LAST_SESSION.md
Normal file
126
docs/context/CONTEXT_LAST_SESSION.md
Normal file
@ -0,0 +1,126 @@
|
||||
# Contesto Ultima Sessione — NIS2 Agile
|
||||
|
||||
**Data**: 2026-03-07
|
||||
**Dominio produzione**: https://nis2.agile.software/
|
||||
|
||||
---
|
||||
|
||||
## Cosa è stato fatto in questa sessione
|
||||
|
||||
### Sprint B2B / Integrazioni / Licenze
|
||||
|
||||
#### 1. Migrazione dominio
|
||||
- DNS A record `nis2.agile.software → 135.181.149.254` via Cloudflare API
|
||||
- SSL Let's Encrypt certbot (`/etc/letsencrypt/live/nis2.agile.software/`)
|
||||
- Apache vhost HTTPS abilitato
|
||||
- Redirect 301 da `nis2.certisource.it → nis2.agile.software`
|
||||
|
||||
#### 2. Test runner
|
||||
- `public/test-runner.php` — token `Nis2Test2026`, SSE streaming, dark terminal UI
|
||||
- Bottone `Reset + Simula + Testa Tutto` (dark green, top Test tab)
|
||||
- `docs/sql/reset-demo.sql` aggiornato: mantiene sempre `cristiano.benassati@gmail.com` (super_admin, `Silvia1978!@`)
|
||||
|
||||
#### 3. Integrazioni B2B (ServicesController)
|
||||
- `POST /api/services/token` — API Key → JWT 15min
|
||||
- `POST /api/services/sso` — SSO federato con responsabilità utente, JWT 2h
|
||||
- `POST /api/services/provision` — provisioning automatico org+utente+api_key da invito
|
||||
- `logExternalCall()` in BaseController per audit trail chiamate esterne
|
||||
- `BaseController::base64UrlEncode/Decode` cambiati da private a protected
|
||||
|
||||
#### 4. Sistema Inviti / Licenze
|
||||
- **`application/controllers/InviteController.php`** — CRUD inviti
|
||||
- Auth: `requireLicenseAuth()` accetta X-API-Key (`admin:licenses`) O JWT super_admin
|
||||
- `POST /api/invites/create` — genera token `inv_xxx`, SHA-256 in DB
|
||||
- `GET /api/invites/list` — lista con filtri status/channel
|
||||
- `GET /api/invites/{id}` — dettaglio
|
||||
- `DELETE /api/invites/{id}` — revoca
|
||||
- `POST /api/invites/{id}/regenerate` — nuovo token
|
||||
- `GET /api/invites/validate?token=` — pubblica, nessuna auth
|
||||
- `static resolveInvite()` / `static markUsed()` — usati da provision
|
||||
- **`ServicesController::provision()`** aggiornato:
|
||||
- Accetta `invite_token` nel body (B2B flow) O `X-Provision-Secret` (admin diretto)
|
||||
- Piano e durata forzati dall'invito
|
||||
- Chiama `InviteController::markUsed()` dopo provisioning riuscito
|
||||
- Salva `license_max_users` nell'org
|
||||
- **`public/index.php`** aggiornato: route `/api/invites/*`
|
||||
|
||||
#### 5. DB Migrations applicate in produzione
|
||||
- **011_provisioning.sql**: `organizations` +provisioned_by, +license_plan, +license_expires_at, +lg231_company_id; `users` +must_change_password, +phone, +job_title; `api_keys` +created_by
|
||||
- **012_invites.sql**: tabella `invites` (token_hash, plan, duration_months, max_uses, expires_at, channel, restrict_vat/email, status, used_by_org_id)
|
||||
- **013_license_ext.sql**: `invites` +max_users_per_org, +price_eur, +reseller_name; `organizations` +license_max_users
|
||||
|
||||
#### 6. Pagine HTML nuove
|
||||
- **`public/integrazioniext.html`** — documentazione partner tecnici (lg231, e-commerce)
|
||||
- Tab: Services API, Inviti & Licenze, Guida lg231, Webhook, Quick Start
|
||||
- **`public/licenseExt.html`** — pannello marketing per gestione licenze
|
||||
- Login JWT super_admin, stats strip, genera licenze, lista/filtri, revoca/rigenera, export CSV
|
||||
- **`public/mktg-api-doc.html`** — risponde alle 6 domande marketing
|
||||
- Quick start, endpoint, auth, response format, lista, revoca, spiegazione pagine
|
||||
- **`public/nis2-license-api.postman.json`** — Postman collection scaricabile
|
||||
- **`docs/integration/nis2-license-api.postman.json`** — copia in repo
|
||||
|
||||
#### 7. API Key mktg-agile (generata in produzione)
|
||||
- **Chiave**: `nis2_mktg_8c8bd38e78fccb9faa749d8601051f42`
|
||||
- **Scope**: `admin:licenses`
|
||||
- **DB api_keys.id**: 1
|
||||
- **Scade**: 2028-03-07
|
||||
|
||||
#### 8. Documentazione lg231
|
||||
- `docs/integration/lg231-nis2-integration.md` — spec completa per agente Claude lg231
|
||||
- `public/settings.html` — aggiunto scope `admin:licenses`, `admin:org`, `sso:login` al form API Keys
|
||||
|
||||
---
|
||||
|
||||
## File creati o modificati
|
||||
| File | Azione |
|
||||
|------|--------|
|
||||
| `application/controllers/InviteController.php` | NUOVO |
|
||||
| `application/controllers/ServicesController.php` | MODIFICATO (provision + sso + token) |
|
||||
| `application/controllers/BaseController.php` | MODIFICATO (base64Url protected) |
|
||||
| `application/config/config.php` | MODIFICATO (PROVISION_SECRET) |
|
||||
| `public/index.php` | MODIFICATO (route invites) |
|
||||
| `public/integrazioniext.html` | NUOVO |
|
||||
| `public/licenseExt.html` | NUOVO |
|
||||
| `public/mktg-api-doc.html` | NUOVO |
|
||||
| `public/nis2-license-api.postman.json` | NUOVO |
|
||||
| `public/settings.html` | MODIFICATO (scopes) |
|
||||
| `public/js/common.js` | MODIFICATO (sidebar link integrazioniext) |
|
||||
| `docs/sql/011_provisioning.sql` | NUOVO |
|
||||
| `docs/sql/012_invites.sql` | NUOVO |
|
||||
| `docs/sql/013_license_ext.sql` | NUOVO |
|
||||
| `docs/sql/reset-demo.sql` | MODIFICATO (super_admin persistente) |
|
||||
| `docs/integration/lg231-nis2-integration.md` | NUOVO |
|
||||
| `docs/integration/nis2-license-api.postman.json` | NUOVO |
|
||||
|
||||
---
|
||||
|
||||
## File deployati su Hetzner
|
||||
Tutti i file sopra tramite `git push + git pull`. Migrations applicate via SSH/mysql.
|
||||
|
||||
---
|
||||
|
||||
## URL attivi in produzione
|
||||
| Risorsa | URL |
|
||||
|---------|-----|
|
||||
| App | https://nis2.agile.software/ |
|
||||
| Test runner | https://nis2.agile.software/test-runner.php?t=Nis2Test2026 |
|
||||
| Doc partner (lg231) | https://nis2.agile.software/integrazioniext.html |
|
||||
| Pannello licenze (mktg) | https://nis2.agile.software/licenseExt.html |
|
||||
| Doc API marketing | https://nis2.agile.software/mktg-api-doc.html |
|
||||
| Postman collection | https://nis2.agile.software/nis2-license-api.postman.json |
|
||||
|
||||
---
|
||||
|
||||
## Prossimi passi consigliati
|
||||
1. **mktg-agile**: recepire API Key + integrare `POST /api/invites/create` nel flusso di acquisto
|
||||
2. **lg231**: leggere `integrazioniext.html` + `docs/integration/lg231-nis2-integration.md` e implementare Nis2Client + provisioning
|
||||
3. **E-commerce**: usare `GET /api/invites/validate?token=` per mostrare anteprima piano prima dell'attivazione
|
||||
4. **Controllo utenti per org**: aggiungere check `license_max_users` in `OrganizationController` quando si invitano nuovi utenti
|
||||
5. **Rinnovo licenze**: endpoint `POST /api/invites/{id}/renew` che estende `license_expires_at` sull'org
|
||||
|
||||
---
|
||||
|
||||
## Credenziali importanti (non committare)
|
||||
- Super admin: `cristiano.benassati@gmail.com` / `Silvia1978!@`
|
||||
- API Key mktg: `nis2_mktg_8c8bd38e78fccb9faa749d8601051f42` (scope: admin:licenses, scade 2028)
|
||||
- SSH Hetzner: `ssh -i docs/credentials/hetzner_key root@135.181.149.254`
|
||||
@ -324,9 +324,46 @@
|
||||
<strong>Sistema Inviti / Licenze B2B:</strong> NIS2 Agile genera token di invito che abilitano
|
||||
il provisioning automatico di organizzazioni e utenti. L'e-commerce o il partner riceve l'invito,
|
||||
lo consegna al cliente finale (es. lg231), che lo usa per attivarsi automaticamente.
|
||||
L'accesso si interrompe alla scadenza dell'invito.
|
||||
L'accesso si interrompe alla scadenza della licenza.
|
||||
</div>
|
||||
|
||||
<div class="section-title">Chi fa cosa — ruoli nell'ecosistema</div>
|
||||
<table class="api-table" style="margin-bottom:1.5rem">
|
||||
<thead><tr><th>Sistema</th><th>Ruolo</th><th>API usata</th><th>Auth</th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>NIS2 Admin</strong><br><span style="font-size:.72rem;color:var(--text-secondary)">o mktg-agile</span></td>
|
||||
<td>Genera i token licenza, fissa piano/durata/utenti/prezzo</td>
|
||||
<td><code>POST /api/invites/create</code></td>
|
||||
<td><span class="badge-status s-pending" style="font-size:.65rem">API Key admin:licenses</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>E-commerce</strong></td>
|
||||
<td>Riceve token all'acquisto, lo consegna al cliente con l'ordine</td>
|
||||
<td>— (semplice consegna token)</td>
|
||||
<td><span class="badge-status s-pending" style="font-size:.65rem">API Key admin:licenses</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>lg231 / partner</strong></td>
|
||||
<td>Valida il token, fa provisioning automatico per il cliente</td>
|
||||
<td><code>GET /api/invites/validate</code><br><code>POST /api/services/provision</code></td>
|
||||
<td><span class="badge-status s-used" style="font-size:.65rem">invite_token nel body</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Cliente finale</strong></td>
|
||||
<td>Apre invite_url e si registra in autonomia via wizard</td>
|
||||
<td><code>onboarding.html?invite=inv_...</code></td>
|
||||
<td><span class="badge-status" style="font-size:.65rem;background:rgba(156,163,175,.1);color:#9ca3af">nessuna auth</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>NIS2 Admin</strong></td>
|
||||
<td>Monitora uso licenze, revoca, rigenera</td>
|
||||
<td><code>GET /api/invites/list</code><br><code>DELETE /api/invites/{id}</code></td>
|
||||
<td><span class="badge-status s-pending" style="font-size:.65rem">API Key o JWT super_admin</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="section-title">Flusso completo</div>
|
||||
<div class="code-block" style="font-family:monospace;line-height:1.8;font-size:.82rem">
|
||||
<span style="color:#22c55e">1. GENERAZIONE</span> NIS2 Admin (super_admin)
|
||||
@ -458,6 +495,31 @@ curl "https://nis2.agile.software/api/invites/validate?token=inv_a1b2c3..."
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="section-title">Per mktg-agile / E-commerce — Quick Start</div>
|
||||
<div class="callout">
|
||||
Chiave API già attiva per mktg-agile: <code style="color:#4ade80">nis2_mktg_8c8bd38e78fccb9faa749d8601051f42</code>
|
||||
· Scope: <code>admin:licenses</code> · Scade: 2028-03-07
|
||||
· Doc completa: <a href="/mktg-api-doc.html" style="color:var(--primary)">mktg-api-doc.html</a>
|
||||
· Pannello web: <a href="/licenseExt.html" style="color:var(--primary)">licenseExt.html</a>
|
||||
</div>
|
||||
<div class="code-block"><span class="cmt"># 1. Crea licenza (mktg-agile → NIS2)</span>
|
||||
curl -X POST https://nis2.agile.software/api/invites/create \
|
||||
-H <span class="str">"X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42"</span> \
|
||||
-H <span class="str">"Content-Type: application/json"</span> \
|
||||
-d <span class="str">'{"plan":"professional","duration_months":12,"max_users_per_org":10,
|
||||
"label":"Ordine MKT-001","channel":"ecommerce","price_eur":990}'</span>
|
||||
|
||||
<span class="cmt"># → risposta contiene token (inv_xxx) e invite_url</span>
|
||||
<span class="cmt"># → consegna invite_url al cliente nel messaggio di conferma ordine</span>
|
||||
|
||||
<span class="cmt"># 2. Verifica stato licenza in qualsiasi momento</span>
|
||||
curl -H <span class="str">"X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42"</span> \
|
||||
"https://nis2.agile.software/api/invites/42"
|
||||
|
||||
<span class="cmt"># 3. Lista licenze attive per canale ecommerce</span>
|
||||
curl -H <span class="str">"X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42"</span> \
|
||||
"https://nis2.agile.software/api/invites/list?channel=ecommerce&status=pending"</div>
|
||||
|
||||
<div class="callout">
|
||||
<strong>Sicurezza token:</strong> il token <code>inv_</code> viene restituito in chiaro UNA SOLA VOLTA
|
||||
alla creazione. Nel DB è conservato solo il hash SHA-256. Il <code>token_prefix</code> (es: <code>inv_a1b2c3...</code>)
|
||||
@ -729,14 +791,45 @@ curl -H <span class="str">"X-API-Key: nis2_TUA_CHIAVE"</span> \
|
||||
curl -H <span class="str">"X-API-Key: nis2_TUA_CHIAVE"</span> \
|
||||
"https://nis2.agile.software/api/services/risks/feed?level=high,critical"</div>
|
||||
|
||||
<div class="section-title">Contatti e riferimenti</div>
|
||||
<div class="section-title">Risorse per ogni tipo di integratore</div>
|
||||
<table class="api-table">
|
||||
<thead><tr><th>Destinatario</th><th>Risorsa</th><th>URL</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>App NIS2 Agile</td><td><a href="https://nis2.agile.software" style="color:var(--primary)">https://nis2.agile.software</a></td></tr>
|
||||
<tr><td>Specifiche OpenAPI</td><td><code>GET /api/services/openapi.json</code></td></tr>
|
||||
<tr><td>Test Runner</td><td><a href="/test-runner.php?t=Nis2Test2026" style="color:var(--primary)">test-runner.php</a></td></tr>
|
||||
<tr><td>Amministratore</td><td>cristiano.benassati@gmail.com</td></tr>
|
||||
<tr><td>Documento tecnico lg231</td><td><code>docs/integration/lg231-nis2-integration.md</code></td></tr>
|
||||
<tr>
|
||||
<td><strong>mktg-agile / E-commerce</strong></td>
|
||||
<td>Documentazione API licenze + Quick Start</td>
|
||||
<td><a href="/mktg-api-doc.html" style="color:var(--primary)">mktg-api-doc.html</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>mktg-agile / E-commerce</strong></td>
|
||||
<td>Pannello web gestione licenze</td>
|
||||
<td><a href="/licenseExt.html" style="color:var(--primary)">licenseExt.html</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>mktg-agile / E-commerce</strong></td>
|
||||
<td>Postman Collection (import diretto)</td>
|
||||
<td><a href="/nis2-license-api.postman.json" download style="color:var(--primary)">nis2-license-api.postman.json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>lg231 / Partner tecnici</strong></td>
|
||||
<td>Questa pagina — tab Guida lg231</td>
|
||||
<td><a href="/integrazioniext.html" style="color:var(--primary)">integrazioniext.html</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>lg231 (agente Claude)</strong></td>
|
||||
<td>Spec tecnica completa per implementazione</td>
|
||||
<td><code>docs/integration/lg231-nis2-integration.md</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Tutti</strong></td>
|
||||
<td>Health check (no auth)</td>
|
||||
<td><code>GET https://nis2.agile.software/api/services/status</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Tutti</strong></td>
|
||||
<td>App NIS2 Agile</td>
|
||||
<td><a href="https://nis2.agile.software" style="color:var(--primary)">https://nis2.agile.software</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -103,6 +103,57 @@ table.resp code { background: rgba(255,255,255,.06); padding: .1rem .3rem; borde
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── QUICK START ── -->
|
||||
<div style="background:rgba(6,182,212,.06);border:1px solid rgba(6,182,212,.25);border-radius:12px;padding:1.5rem;margin-bottom:2rem">
|
||||
<div style="font-size:.75rem;font-weight:700;color:var(--primary);letter-spacing:.06em;margin-bottom:1rem">QUICK START — OPERATIVO IN 2 MINUTI</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:1rem;margin-bottom:1.25rem">
|
||||
<div style="background:rgba(0,0,0,.25);border-radius:8px;padding:1rem">
|
||||
<div style="font-size:.7rem;color:var(--text-secondary);margin-bottom:.4rem">CHIAVE API (già attiva)</div>
|
||||
<code style="font-size:.75rem;color:#4ade80;word-break:break-all">nis2_mktg_8c8bd38e78fccb9faa749d8601051f42</code>
|
||||
<div style="font-size:.68rem;color:var(--text-secondary);margin-top:.3rem">Scope: admin:licenses · Scade: 2028-03-07</div>
|
||||
</div>
|
||||
<div style="background:rgba(0,0,0,.25);border-radius:8px;padding:1rem">
|
||||
<div style="font-size:.7rem;color:var(--text-secondary);margin-bottom:.4rem">BASE URL</div>
|
||||
<code style="font-size:.8rem;color:var(--text-primary)">https://nis2.agile.software/api</code>
|
||||
<div style="font-size:.68rem;color:var(--text-secondary);margin-top:.3rem">Tutti gli endpoint sotto questo path</div>
|
||||
</div>
|
||||
<div style="background:rgba(0,0,0,.25);border-radius:8px;padding:1rem">
|
||||
<div style="font-size:.7rem;color:var(--text-secondary);margin-bottom:.4rem">TEST IMMEDIATO</div>
|
||||
<code style="font-size:.75rem;color:#fbbf24">curl nis2.agile.software/api/services/status</code>
|
||||
<div style="font-size:.68rem;color:var(--text-secondary);margin-top:.3rem">Nessuna auth — deve rispondere 200</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="font-size:.78rem;color:var(--text-secondary);margin-bottom:.5rem;font-weight:600">FLUSSO COMPLETO — dalla vendita all'attivazione cliente</div>
|
||||
<div style="display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;font-size:.8rem">
|
||||
<div style="background:rgba(168,85,247,.15);border:1px solid rgba(168,85,247,.3);border-radius:6px;padding:.3rem .7rem;color:#a855f7;white-space:nowrap">
|
||||
<strong>1. mktg-agile</strong><br><span style="font-size:.7rem">POST /invites/create</span>
|
||||
</div>
|
||||
<div style="color:var(--text-secondary)">→ token inv_xxx</div>
|
||||
<div style="background:rgba(249,115,22,.12);border:1px solid rgba(249,115,22,.25);border-radius:6px;padding:.3rem .7rem;color:#f97316;white-space:nowrap">
|
||||
<strong>2. e-commerce</strong><br><span style="font-size:.7rem">consegna token al cliente</span>
|
||||
</div>
|
||||
<div style="color:var(--text-secondary)">→ inv_xxx</div>
|
||||
<div style="background:rgba(6,182,212,.12);border:1px solid rgba(6,182,212,.25);border-radius:6px;padding:.3rem .7rem;color:#06b6d4;white-space:nowrap">
|
||||
<strong>3. lg231 / cliente</strong><br><span style="font-size:.7rem">POST /services/provision</span>
|
||||
</div>
|
||||
<div style="color:var(--text-secondary)">→ org + api_key</div>
|
||||
<div style="background:rgba(34,197,94,.12);border:1px solid rgba(34,197,94,.25);border-radius:6px;padding:.3rem .7rem;color:#22c55e;white-space:nowrap">
|
||||
<strong>4. NIS2 attivo</strong><br><span style="font-size:.7rem">fino a license_expires_at</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre style="margin-top:1rem;margin-bottom:0;font-size:.78rem"><span class="cm"># Crea licenza in 1 chiamata:</span>
|
||||
curl -X POST https://nis2.agile.software/api/invites/create \
|
||||
-H <span class="sv">"X-API-Key: nis2_mktg_8c8bd38e78fccb9faa749d8601051f42"</span> \
|
||||
-H <span class="sv">"Content-Type: application/json"</span> \
|
||||
-d <span class="sv">'{"plan":"professional","duration_months":12,"label":"Ordine #123","channel":"ecommerce","max_users_per_org":10,"price_eur":990}'</span>
|
||||
|
||||
<span class="cm"># Risposta → prendi invites[0].token (inv_xxx) e invites[0].invite_url</span>
|
||||
<span class="cm"># Consegna invite_url al cliente — lui clicca e si attiva in autonomia</span></pre>
|
||||
</div>
|
||||
|
||||
<!-- ── Q1 ── -->
|
||||
<h2><span class="num">1</span> API di creazione licenza</h2>
|
||||
<div class="answer-box highlight">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user