[FEAT] Epic C / C5.2b — Portale esterno stakeholder + sotto-dashboard feedback (mig.053)

Completa C5 (Epic C). Gli stakeholder rispondono in self-service tramite magic-link
(token SHA-256 per destinatario, NESSUN account/JWT); il compliance manager vede gli
esiti, i commenti e gli allegati nel dettaglio dell'attività.

- StakeholderPortalController (non-JWT, token-only): access / respond (questionario) /
  acknowledge (firma di avvenuta lettura) / comment / attachment. Submit one-shot (409),
  validazione risposte obbligatorie, anti-IDOR (un token = un solo destinatario),
  auto-completamento attività quando tutti hanno risposto/firmato.
- StakeholderActivityController: feedback (risposte per destinatario), comments
  (GET/POST), attachments (upload interno + lista; riuso evidence_files entity_type=
  'stk_activity', file sotto public/uploads/stk_activity/{org}/).
- mig.053: stk_activity_responses (answers JSON / acknowledged_at), stk_activity_comments
  (interni/esterni). Estende il seeder idempotente.
- Frontend: stk-portal.html (pagina pubblica dependency-free: questionario per tipo di
  domanda o testo+firma, commento, upload); dettaglio attività in stakeholder-activities.html
  con esiti, thread commenti e allegati.

Email disattivate (kill-switch) → i magic-link si condividono manualmente. Smoke prod OK
(access no-auth, respond+required+409, acknowledge+WRONG_TYPE, comment esterno/interno,
bad-token 404, feedback interno, auto-complete; cleanup org 151 pulita). Additivo. v1.21.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-16 22:20:14 +02:00
co-authored by Claude Opus 4.8
parent a5ff29e0da
commit 4f386faae5
44 changed files with 825 additions and 151 deletions
+15
View File
@@ -93,6 +93,7 @@ $controllerMap = [
'framework' => 'FrameworkController', // Epic C / C1 — Elenco canonico Misure/Requisiti (cfg_nis2_*, read-only)
'stakeholders' => 'StakeholderController', // Epic C / C5 — Registro stakeholder + matrice di Mendelow
'stakeholder-activities' => 'StakeholderActivityController', // Epic C / C5.2 — Attività stakeholder (questionari/azioni + calendario)
'stakeholder-portal' => 'StakeholderPortalController', // Epic C / C5.2b — Portale esterno stakeholder (token magic-link, NO JWT)
'assessments' => 'AssessmentController',
'isms' => 'IsmsModelController', // Modello Organizzativo SGSI (ISO 27001/27017/27018 + SoA)
'dashboard' => 'DashboardController',
@@ -458,6 +459,20 @@ $actionMap = [
'DELETE:{id}' => 'delete',
'POST:{id}/assign' => 'assign',
'POST:{id}/send' => 'send',
'GET:{id}/feedback' => 'feedback',
'GET:{id}/comments' => 'comments',
'POST:{id}/comments' => 'addComment',
'GET:{id}/attachments' => 'attachments',
'POST:{id}/attachments' => 'uploadAttachment',
],
// ── StakeholderPortalController (Epic C / C5.2b — portale esterno, token magic-link, NO JWT) ──
'stakeholder-portal' => [
'GET:access' => 'access',
'POST:respond' => 'respond',
'POST:acknowledge'=> 'acknowledge',
'POST:comment' => 'comment',
'POST:attachment' => 'attachment',
],
// ── AuditController ─────────────────────────────