[FIX] Completamento UI: metodo controlsMonitoring, OpenAPI ingest endpoints, i18n format, help monitoraggio
Il commit 372ccb5 aveva incluso versioni con Edit falliti (ancore errate):
- AuditController::controlsMonitoring ora effettivamente presente (era 501 in prod)
- ServicesController::openapi ora espone incidents-ingest/evidence-ingest/assets-ingest/controls-monitoring
- i18n.js: chiavi nel formato corretto {it,en} (risks.fair_tab/kri_tab, assets.import_btn, audit.monitoring_tab)
- help.js: sezione Monitoraggio Continuo in reports
Verificato in prod: openapi 4/4, controlsMonitoring/fairRegister/kri tutti 200.
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
e3e4aae1e4
commit
dbc1784955
@@ -406,4 +406,68 @@ class AuditController extends BaseController
|
||||
header('Content-Disposition: attachment; filename="nis2_audit_certified_' . date('Y-m-d') . '.json"');
|
||||
$this->jsonSuccess($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/audit/controlsMonitoring
|
||||
* Continuous Control Monitoring (P1): stato/freschezza dei controlli
|
||||
* alimentato dalle evidenze automatiche. Versione JWT per la UI.
|
||||
*/
|
||||
public function controlsMonitoring(): void
|
||||
{
|
||||
$this->requireOrgAccess();
|
||||
$orgId = $this->getCurrentOrgId();
|
||||
|
||||
try {
|
||||
Database::query(
|
||||
"UPDATE compliance_controls cc
|
||||
LEFT JOIN (
|
||||
SELECT t.control_code, t.valid_until
|
||||
FROM control_evidence_auto t
|
||||
JOIN (SELECT control_code, MAX(collected_at) mx FROM control_evidence_auto
|
||||
WHERE organization_id = ? GROUP BY control_code) m
|
||||
ON m.control_code = t.control_code AND m.mx = t.collected_at
|
||||
WHERE t.organization_id = ?
|
||||
) last ON last.control_code = cc.control_code
|
||||
SET cc.monitoring_status = 'stale'
|
||||
WHERE cc.organization_id = ?
|
||||
AND cc.monitoring_status NOT IN ('not_monitored')
|
||||
AND last.valid_until IS NOT NULL AND last.valid_until < NOW()",
|
||||
[$orgId, $orgId, $orgId]
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
error_log('[CCM] ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$rows = Database::fetchAll(
|
||||
'SELECT control_code, title, status, monitoring_status, last_checked_at, freshness_days, implementation_percentage
|
||||
FROM compliance_controls WHERE organization_id = ? ORDER BY control_code',
|
||||
[$orgId]
|
||||
);
|
||||
|
||||
$summary = ['healthy' => 0, 'warning' => 0, 'stale' => 0, 'failing' => 0, 'not_monitored' => 0];
|
||||
foreach ($rows as $r) {
|
||||
$ms = $r['monitoring_status'] ?? 'not_monitored';
|
||||
if (isset($summary[$ms])) $summary[$ms]++;
|
||||
}
|
||||
$monitored = count($rows) - $summary['not_monitored'];
|
||||
|
||||
$recent = [];
|
||||
try {
|
||||
$recent = Database::fetchAll(
|
||||
'SELECT control_code, source, source_system, status, summary, collected_at, valid_until
|
||||
FROM control_evidence_auto WHERE organization_id = ?
|
||||
ORDER BY collected_at DESC LIMIT 20',
|
||||
[$orgId]
|
||||
);
|
||||
} catch (Throwable $e) { /* ignore */ }
|
||||
|
||||
$this->jsonSuccess([
|
||||
'total_controls' => count($rows),
|
||||
'monitored' => $monitored,
|
||||
'coverage_percent' => count($rows) ? (int) round($monitored * 100 / count($rows)) : 0,
|
||||
'summary' => $summary,
|
||||
'controls' => $rows,
|
||||
'recent_evidence' => $recent,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user