- Implemented tests for RouterConfig, RoutingOptions, StaticInstanceConfig, and RouterConfigOptions to ensure default values are set correctly. - Added tests for RouterConfigProvider to validate configurations and ensure defaults are returned when no file is specified. - Created tests for ConfigValidationResult to check success and error scenarios. - Developed tests for ServiceCollectionExtensions to verify service registration for RouterConfig. - Introduced UdpTransportTests to validate serialization, connection, request-response, and error handling in UDP transport. - Added scripts for signing authority gaps and hashing DevPortal SDK snippets.
221 lines
7.9 KiB
PL/PgSQL
221 lines
7.9 KiB
PL/PgSQL
-- Policy Schema Migration 001: Initial Schema
|
|
-- Creates the policy schema for packs, rules, and risk profiles
|
|
|
|
-- Create schema
|
|
CREATE SCHEMA IF NOT EXISTS policy;
|
|
|
|
-- Packs table (policy pack containers)
|
|
CREATE TABLE IF NOT EXISTS policy.packs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
display_name TEXT,
|
|
description TEXT,
|
|
active_version INT,
|
|
is_builtin BOOLEAN NOT NULL DEFAULT FALSE,
|
|
is_deprecated BOOLEAN NOT NULL DEFAULT FALSE,
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by TEXT,
|
|
UNIQUE(tenant_id, name)
|
|
);
|
|
|
|
CREATE INDEX idx_packs_tenant ON policy.packs(tenant_id);
|
|
CREATE INDEX idx_packs_builtin ON policy.packs(is_builtin);
|
|
|
|
-- Pack versions table (immutable versions)
|
|
CREATE TABLE IF NOT EXISTS policy.pack_versions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
pack_id UUID NOT NULL REFERENCES policy.packs(id) ON DELETE CASCADE,
|
|
version INT NOT NULL,
|
|
description TEXT,
|
|
rules_hash TEXT NOT NULL,
|
|
is_published BOOLEAN NOT NULL DEFAULT FALSE,
|
|
published_at TIMESTAMPTZ,
|
|
published_by TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by TEXT,
|
|
UNIQUE(pack_id, version)
|
|
);
|
|
|
|
CREATE INDEX idx_pack_versions_pack ON policy.pack_versions(pack_id);
|
|
CREATE INDEX idx_pack_versions_published ON policy.pack_versions(pack_id, is_published);
|
|
|
|
-- Rules table (OPA/Rego rules)
|
|
CREATE TABLE IF NOT EXISTS policy.rules (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
pack_version_id UUID NOT NULL REFERENCES policy.pack_versions(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
rule_type TEXT NOT NULL DEFAULT 'rego' CHECK (rule_type IN ('rego', 'json', 'yaml')),
|
|
content TEXT NOT NULL,
|
|
content_hash TEXT NOT NULL,
|
|
severity TEXT NOT NULL DEFAULT 'medium' CHECK (severity IN ('critical', 'high', 'medium', 'low', 'info')),
|
|
category TEXT,
|
|
tags TEXT[] NOT NULL DEFAULT '{}',
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE(pack_version_id, name)
|
|
);
|
|
|
|
CREATE INDEX idx_rules_pack_version ON policy.rules(pack_version_id);
|
|
CREATE INDEX idx_rules_severity ON policy.rules(severity);
|
|
CREATE INDEX idx_rules_category ON policy.rules(category);
|
|
CREATE INDEX idx_rules_tags ON policy.rules USING GIN(tags);
|
|
|
|
-- Risk profiles table
|
|
CREATE TABLE IF NOT EXISTS policy.risk_profiles (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
display_name TEXT,
|
|
description TEXT,
|
|
version INT NOT NULL DEFAULT 1,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
thresholds JSONB NOT NULL DEFAULT '{}',
|
|
scoring_weights JSONB NOT NULL DEFAULT '{}',
|
|
exemptions JSONB NOT NULL DEFAULT '[]',
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
created_by TEXT,
|
|
UNIQUE(tenant_id, name, version)
|
|
);
|
|
|
|
CREATE INDEX idx_risk_profiles_tenant ON policy.risk_profiles(tenant_id);
|
|
CREATE INDEX idx_risk_profiles_active ON policy.risk_profiles(tenant_id, name, is_active)
|
|
WHERE is_active = TRUE;
|
|
|
|
-- Risk profile history (for audit trail)
|
|
CREATE TABLE IF NOT EXISTS policy.risk_profile_history (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
risk_profile_id UUID NOT NULL REFERENCES policy.risk_profiles(id),
|
|
version INT NOT NULL,
|
|
thresholds JSONB NOT NULL,
|
|
scoring_weights JSONB NOT NULL,
|
|
exemptions JSONB NOT NULL,
|
|
changed_by TEXT,
|
|
changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
change_reason TEXT
|
|
);
|
|
|
|
CREATE INDEX idx_risk_profile_history_profile ON policy.risk_profile_history(risk_profile_id);
|
|
|
|
-- Evaluation runs table
|
|
CREATE TABLE IF NOT EXISTS policy.evaluation_runs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id TEXT NOT NULL,
|
|
project_id TEXT,
|
|
artifact_id TEXT,
|
|
pack_id UUID REFERENCES policy.packs(id),
|
|
pack_version INT,
|
|
risk_profile_id UUID REFERENCES policy.risk_profiles(id),
|
|
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running', 'completed', 'failed')),
|
|
result TEXT CHECK (result IN ('pass', 'fail', 'warn', 'error')),
|
|
score NUMERIC(5,2),
|
|
findings_count INT NOT NULL DEFAULT 0,
|
|
critical_count INT NOT NULL DEFAULT 0,
|
|
high_count INT NOT NULL DEFAULT 0,
|
|
medium_count INT NOT NULL DEFAULT 0,
|
|
low_count INT NOT NULL DEFAULT 0,
|
|
input_hash TEXT,
|
|
duration_ms INT,
|
|
error_message TEXT,
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
started_at TIMESTAMPTZ,
|
|
completed_at TIMESTAMPTZ,
|
|
created_by TEXT
|
|
);
|
|
|
|
CREATE INDEX idx_evaluation_runs_tenant ON policy.evaluation_runs(tenant_id);
|
|
CREATE INDEX idx_evaluation_runs_project ON policy.evaluation_runs(tenant_id, project_id);
|
|
CREATE INDEX idx_evaluation_runs_artifact ON policy.evaluation_runs(tenant_id, artifact_id);
|
|
CREATE INDEX idx_evaluation_runs_created ON policy.evaluation_runs(tenant_id, created_at);
|
|
CREATE INDEX idx_evaluation_runs_status ON policy.evaluation_runs(status);
|
|
|
|
-- Explanations table (rule evaluation details)
|
|
CREATE TABLE IF NOT EXISTS policy.explanations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
evaluation_run_id UUID NOT NULL REFERENCES policy.evaluation_runs(id) ON DELETE CASCADE,
|
|
rule_id UUID REFERENCES policy.rules(id),
|
|
rule_name TEXT NOT NULL,
|
|
result TEXT NOT NULL CHECK (result IN ('pass', 'fail', 'skip', 'error')),
|
|
severity TEXT NOT NULL,
|
|
message TEXT,
|
|
details JSONB NOT NULL DEFAULT '{}',
|
|
remediation TEXT,
|
|
resource_path TEXT,
|
|
line_number INT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_explanations_run ON policy.explanations(evaluation_run_id);
|
|
CREATE INDEX idx_explanations_result ON policy.explanations(evaluation_run_id, result);
|
|
|
|
-- Exceptions table (policy exceptions/waivers)
|
|
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 ('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(),
|
|
created_by TEXT,
|
|
UNIQUE(tenant_id, name)
|
|
);
|
|
|
|
CREATE INDEX idx_exceptions_tenant ON policy.exceptions(tenant_id);
|
|
CREATE INDEX idx_exceptions_status ON policy.exceptions(tenant_id, status);
|
|
CREATE INDEX idx_exceptions_expires ON policy.exceptions(expires_at)
|
|
WHERE status = 'active';
|
|
CREATE INDEX idx_exceptions_project ON policy.exceptions(tenant_id, project_id);
|
|
|
|
-- Audit log table
|
|
CREATE TABLE IF NOT EXISTS policy.audit (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
tenant_id TEXT NOT NULL,
|
|
user_id UUID,
|
|
action TEXT NOT NULL,
|
|
resource_type TEXT NOT NULL,
|
|
resource_id TEXT,
|
|
old_value JSONB,
|
|
new_value JSONB,
|
|
correlation_id TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_audit_tenant ON policy.audit(tenant_id);
|
|
CREATE INDEX idx_audit_resource ON policy.audit(resource_type, resource_id);
|
|
CREATE INDEX idx_audit_created ON policy.audit(tenant_id, created_at);
|
|
|
|
-- Update timestamp function
|
|
CREATE OR REPLACE FUNCTION policy.update_updated_at()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Triggers
|
|
CREATE TRIGGER trg_packs_updated_at
|
|
BEFORE UPDATE ON policy.packs
|
|
FOR EACH ROW EXECUTE FUNCTION policy.update_updated_at();
|
|
|
|
CREATE TRIGGER trg_risk_profiles_updated_at
|
|
BEFORE UPDATE ON policy.risk_profiles
|
|
FOR EACH ROW EXECUTE FUNCTION policy.update_updated_at();
|