[FEAT] Services API, Webhook, Whistleblowing, Normative + integrazioni
Sprint completo — prodotto presentation-ready:
Services API (read-only, API Key + scope):
- GET /api/services/status|compliance-summary|risks-feed|incidents-feed
- GET /api/services/controls-status|assets-critical|suppliers-risk|policies-approved
- GET /api/services/openapi (spec OpenAPI 3.0.3 JSON)
Webhook Outbound (Stripe-like HMAC-SHA256):
- CRUD api_keys + webhook_subscriptions (Settings → 2 nuovi tab)
- WebhookService: retry 3x backoff (0s/5min/30min), delivery log
- Trigger auto in IncidentController, RiskController, PolicyController
- Delivery log, test ping, processRetry
Nuovi moduli:
- WhistleblowingController (Art.32 NIS2): anonimato garantito, timeline, token tracking
- NormativeController: feed NIS2/ACN/DORA con ACK tracciato per audit
Frontend:
- whistleblowing.html: form submit anonimo/firmato + gestione CISO
- normative.html: feed con presa visione documentata + progress bar ACK
- public/docs/api.html: documentazione API dark theme (Swagger-like)
- settings.html: tab API Keys + tab Webhook
- integrations/: guide per lg231, SustainAI, AllRisk, SIEM (widget + codice)
- Sidebar: Segnalazioni + Normative aggiunte a common.js
DB: migration 007 (api_keys, webhook_subscriptions, webhook_deliveries),
008 (whistleblowing_reports + timeline),
009 (normative_updates + normative_ack + seed NIS2/ACN/DORA/ISO)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
3f4b451e2a
commit
86e9bdded2
@@ -98,6 +98,10 @@ $controllerMap = [
|
||||
'admin' => 'AdminController',
|
||||
'onboarding' => 'OnboardingController',
|
||||
'ncr' => 'NonConformityController',
|
||||
'services' => 'ServicesController',
|
||||
'webhooks' => 'WebhookController',
|
||||
'whistleblowing'=> 'WhistleblowingController',
|
||||
'normative' => 'NormativeController',
|
||||
];
|
||||
|
||||
if (!isset($controllerMap[$controllerName])) {
|
||||
@@ -289,6 +293,55 @@ $actionMap = [
|
||||
'POST:{id}/sync' => 'syncExternal',
|
||||
'POST:webhook' => 'webhook',
|
||||
],
|
||||
|
||||
// ── ServicesController (API pubblica) ──────────
|
||||
'services' => [
|
||||
'GET:status' => 'status',
|
||||
'GET:complianceSummary' => 'complianceSummary',
|
||||
'GET:risksFeed' => 'risksFeed',
|
||||
'GET:incidentsFeed' => 'incidentsFeed',
|
||||
'GET:controlsStatus' => 'controlsStatus',
|
||||
'GET:assetsCritical' => 'assetsCritical',
|
||||
'GET:suppliersRisk' => 'suppliersRisk',
|
||||
'GET:policiesApproved' => 'policiesApproved',
|
||||
'GET:openapi' => 'openapi',
|
||||
],
|
||||
|
||||
// ── WebhookController (CRUD keys + subscriptions) ──
|
||||
'webhooks' => [
|
||||
'GET:apiKeys' => 'listApiKeys',
|
||||
'POST:apiKeys' => 'createApiKey',
|
||||
'DELETE:apiKeys/{subId}' => 'deleteApiKey',
|
||||
'GET:subscriptions' => 'listSubscriptions',
|
||||
'POST:subscriptions' => 'createSubscription',
|
||||
'PUT:subscriptions/{subId}' => 'updateSubscription',
|
||||
'DELETE:subscriptions/{subId}' => 'deleteSubscription',
|
||||
'POST:subscriptions/{subId}/test' => 'testSubscription',
|
||||
'GET:deliveries' => 'listDeliveries',
|
||||
'POST:retry' => 'processRetry',
|
||||
],
|
||||
|
||||
// ── WhistleblowingController (Art.32 NIS2) ─────
|
||||
'whistleblowing' => [
|
||||
'POST:submit' => 'submit',
|
||||
'GET:list' => 'list',
|
||||
'GET:{id}' => 'get',
|
||||
'PUT:{id}' => 'update',
|
||||
'POST:{id}/assign' => 'assign',
|
||||
'POST:{id}/close' => 'close',
|
||||
'GET:stats' => 'stats',
|
||||
'GET:trackAnonymous' => 'trackAnonymous',
|
||||
],
|
||||
|
||||
// ── NormativeController (Feed NIS2/ACN) ─────────
|
||||
'normative' => [
|
||||
'GET:list' => 'list',
|
||||
'GET:{id}' => 'get',
|
||||
'POST:{id}/ack' => 'acknowledge',
|
||||
'GET:pending' => 'pending',
|
||||
'GET:stats' => 'stats',
|
||||
'POST:create' => 'create',
|
||||
],
|
||||
];
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -340,6 +393,8 @@ if (is_numeric($actionName)) {
|
||||
$sid = (int) $subResourceId;
|
||||
$candidates[] = ['p' => "{$method}:{id}/{$camelSub}/{subId}", 'a' => [$rid, $sid]];
|
||||
}
|
||||
// e.g. POST:subscriptions/{subId}/test
|
||||
$candidates[] = ['p' => "{$method}:{$actionName}/{subId}/{$camelSub}", 'a' => [$rid]];
|
||||
$candidates[] = ['p' => "{$method}:{id}/{$camelSub}", 'a' => [$rid]];
|
||||
$candidates[] = ['p' => "{$method}:{$actionName}/{subId}", 'a' => [$rid]];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user