feat(drift): add normalizer, chunk assembly, daily digest, Slack interactions, analytics
- Canonical schema normalizer: cross-provider resource type mapping - Chunked report reassembly via Redis (10min TTL, out-of-order safe) - Daily drift digest worker with Slack Block Kit summary - Slack interactive handler: remediate + accept drift actions - Analytics API: drift trends and health summary - 005_drift_features.sql migration (remediations, acceptances, indexes)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
-- 005: Canonical resources, remediations, drift acceptances, analytics indexes
|
||||
|
||||
-- Add canonical_resources JSONB column to drift_reports
|
||||
ALTER TABLE drift_reports ADD COLUMN IF NOT EXISTS canonical_resources JSONB;
|
||||
|
||||
-- Remediations (from Slack interactive actions)
|
||||
CREATE TABLE IF NOT EXISTS remediations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
stack_name TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'completed', 'failed', 'cancelled')),
|
||||
requested_by TEXT NOT NULL,
|
||||
requested_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
completed_at TIMESTAMPTZ
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_remediations_tenant_stack ON remediations(tenant_id, stack_name);
|
||||
|
||||
ALTER TABLE remediations ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY tenant_iso_remediations ON remediations
|
||||
USING (tenant_id::text = current_setting('app.tenant_id', true));
|
||||
|
||||
-- Drift acceptances (from Slack interactive actions)
|
||||
CREATE TABLE IF NOT EXISTS drift_acceptances (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
report_id UUID NOT NULL REFERENCES drift_reports(id) ON DELETE CASCADE,
|
||||
accepted_by TEXT NOT NULL,
|
||||
accepted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
reason TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_drift_acceptances_tenant ON drift_acceptances(tenant_id, report_id);
|
||||
|
||||
ALTER TABLE drift_acceptances ENABLE ROW LEVEL SECURITY;
|
||||
CREATE POLICY tenant_iso_drift_acceptances ON drift_acceptances
|
||||
USING (tenant_id::text = current_setting('app.tenant_id', true));
|
||||
|
||||
-- Indexes for time-series analytics queries
|
||||
CREATE INDEX IF NOT EXISTS idx_drift_reports_tenant_scanned ON drift_reports(tenant_id, scanned_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_drift_reports_score_time ON drift_reports(tenant_id, stack_name, scanned_at DESC, drift_score);
|
||||
Reference in New Issue
Block a user