feat(controls): Mandanten-Suppression — per-tenant Applicability-Override
Geteilte Schicht für alle Surfaces (Workspace-Anwälte, Cyber-Risiko-Projekt,
Admin): ein Mandant markiert ein Control als "nicht anwendbar" → in seinen
Use-Case-Ansichten (und künftig Repo-Scans) ausgeblendet.
- Migration 156: compliance.control_suppressions (PK tenant_id+control_uuid),
reversibel (active + reverted_*), auditierbar (actor/reason/created_at).
[migration-approved]
- Service control_suppression: suppress/revert/list_suppressions +
suppressed_control_uuids (geteilter Filter).
- Routes: GET/POST /v1/controls/suppressions + POST .../{uuid}/revert (X-Tenant-ID).
- controls_for_use_case: optionaler X-Tenant-ID + include_suppressed; suppressed
per Default versteckt (nie gelöscht), suppressed_count, suppressed-Flag pro
Control. Agenten/CRA ohne Tenant unberührt.
- Tests: Request-Validierung + import-safety (E2E-Zyklus gegen macmini bewiesen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
-- Migration 156: control_suppressions — per-tenant Applicability-Override.
|
||||
-- Ein Mandant markiert ein Control als "unbrauchbar / nicht anwendbar" -> es
|
||||
-- wird in seinen Use-Case-Ansichten (und künftig Repo-Scans) ausgeblendet.
|
||||
-- REVERSIBEL (active=false + reverted_*, Zeile bleibt) und AUDIT-tauglich
|
||||
-- (actor + reason + created_at beantworten "warum nicht geprüft?"). PER-TENANT.
|
||||
-- Composite PK (tenant_id, control_uuid) = genau eine aktuelle Zeile je
|
||||
-- Mandant+Control; Re-Suppress reaktiviert. Additiv, idempotent. [migration-approved]
|
||||
|
||||
SET search_path TO compliance, public;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = 'compliance'
|
||||
AND table_name = 'canonical_controls') THEN
|
||||
|
||||
CREATE TABLE IF NOT EXISTS control_suppressions (
|
||||
tenant_id UUID NOT NULL,
|
||||
control_uuid UUID NOT NULL
|
||||
REFERENCES canonical_controls(id) ON DELETE CASCADE,
|
||||
reason TEXT,
|
||||
actor VARCHAR(120),
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
reverted_at TIMESTAMPTZ,
|
||||
reverted_by VARCHAR(120),
|
||||
revert_reason TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (tenant_id, control_uuid)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ctrl_suppr_tenant_active
|
||||
ON control_suppressions(tenant_id, active);
|
||||
|
||||
END IF;
|
||||
END $$;
|
||||
Reference in New Issue
Block a user