stela ops usage fixes roles propagation and timoeut, one account to support multi tenants, migrations consolidation, search to support documentation, doctor and open api vector db search
This commit is contained in:
114
devops/compose/postgres-init/05-policy-exceptions-schema.sql
Normal file
114
devops/compose/postgres-init/05-policy-exceptions-schema.sql
Normal file
@@ -0,0 +1,114 @@
|
||||
-- Policy exceptions schema bootstrap for compose environments.
|
||||
-- Ensures exception endpoints can start against a clean database.
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS policy;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS policy.recheck_policies (
|
||||
policy_id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
conditions JSONB NOT NULL,
|
||||
default_action TEXT NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_recheck_policies_tenant
|
||||
ON policy.recheck_policies (tenant_id, is_active);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS policy.exceptions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
rule_pattern TEXT,
|
||||
resource_pattern TEXT,
|
||||
artifact_pattern TEXT,
|
||||
project_id TEXT,
|
||||
reason TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('proposed', 'approved', 'active', 'expired', 'revoked')),
|
||||
expires_at TIMESTAMPTZ,
|
||||
approved_by TEXT,
|
||||
approved_at TIMESTAMPTZ,
|
||||
revoked_by TEXT,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
metadata JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_by TEXT,
|
||||
exception_id TEXT NOT NULL UNIQUE,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
type TEXT NOT NULL DEFAULT 'policy' CHECK (type IN ('vulnerability', 'policy', 'unknown', 'component')),
|
||||
artifact_digest TEXT,
|
||||
purl_pattern TEXT,
|
||||
vulnerability_id TEXT,
|
||||
policy_rule_id TEXT,
|
||||
environments TEXT[] NOT NULL DEFAULT '{}',
|
||||
owner_id TEXT,
|
||||
requester_id TEXT,
|
||||
approver_ids TEXT[] NOT NULL DEFAULT '{}',
|
||||
reason_code TEXT DEFAULT 'other' CHECK (reason_code IN (
|
||||
'false_positive',
|
||||
'accepted_risk',
|
||||
'compensating_control',
|
||||
'test_only',
|
||||
'vendor_not_affected',
|
||||
'scheduled_fix',
|
||||
'deprecation_in_progress',
|
||||
'runtime_mitigation',
|
||||
'network_isolation',
|
||||
'other'
|
||||
)),
|
||||
rationale TEXT,
|
||||
evidence_refs JSONB NOT NULL DEFAULT '[]',
|
||||
compensating_controls JSONB NOT NULL DEFAULT '[]',
|
||||
ticket_ref TEXT,
|
||||
recheck_policy_id TEXT REFERENCES policy.recheck_policies(policy_id),
|
||||
last_recheck_result JSONB,
|
||||
last_recheck_at TIMESTAMPTZ,
|
||||
UNIQUE (tenant_id, name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_tenant ON policy.exceptions(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_status ON policy.exceptions(tenant_id, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_expires ON policy.exceptions(expires_at) WHERE status = 'active';
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_project ON policy.exceptions(tenant_id, project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_vuln_id ON policy.exceptions(vulnerability_id) WHERE vulnerability_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_purl ON policy.exceptions(purl_pattern) WHERE purl_pattern IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_artifact ON policy.exceptions(artifact_digest) WHERE artifact_digest IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_policy_rule ON policy.exceptions(policy_rule_id) WHERE policy_rule_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_owner ON policy.exceptions(owner_id) WHERE owner_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_exceptions_recheck_policy ON policy.exceptions(tenant_id, recheck_policy_id) WHERE recheck_policy_id IS NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS policy.exception_events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
exception_id TEXT NOT NULL REFERENCES policy.exceptions(exception_id) ON DELETE CASCADE,
|
||||
sequence_number INTEGER NOT NULL,
|
||||
event_type TEXT NOT NULL CHECK (event_type IN (
|
||||
'created',
|
||||
'updated',
|
||||
'approved',
|
||||
'activated',
|
||||
'extended',
|
||||
'revoked',
|
||||
'expired',
|
||||
'evidence_attached',
|
||||
'compensating_control_added',
|
||||
'rejected'
|
||||
)),
|
||||
actor_id TEXT NOT NULL,
|
||||
occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
previous_status TEXT,
|
||||
new_status TEXT NOT NULL,
|
||||
new_version INTEGER NOT NULL,
|
||||
description TEXT,
|
||||
details JSONB NOT NULL DEFAULT '{}',
|
||||
client_info TEXT,
|
||||
UNIQUE (exception_id, sequence_number)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_exception_events_exception ON policy.exception_events(exception_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_exception_events_time ON policy.exception_events USING BRIN (occurred_at);
|
||||
Reference in New Issue
Block a user