Gaps fill up, fixes, ui restructuring
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
-- Migration: 045_ReleaseControlBundleLifecycle
|
||||
-- Purpose: Add release-control bundle lifecycle persistence for UI v2 shell contracts.
|
||||
-- Sprint: SPRINT_20260219_008 (BE8-03)
|
||||
|
||||
-- ============================================================================
|
||||
-- Bundle catalog
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.control_bundles (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
slug TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_by TEXT NOT NULL DEFAULT 'system',
|
||||
CONSTRAINT uq_control_bundles_tenant_slug UNIQUE (tenant_id, slug)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundles_tenant_name
|
||||
ON release.control_bundles (tenant_id, name, id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundles_tenant_updated
|
||||
ON release.control_bundles (tenant_id, updated_at DESC, id);
|
||||
|
||||
COMMENT ON TABLE release.control_bundles IS
|
||||
'Release-control bundle identities scoped per tenant.';
|
||||
|
||||
-- ============================================================================
|
||||
-- Immutable bundle versions
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.control_bundle_versions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
bundle_id UUID NOT NULL REFERENCES release.control_bundles(id) ON DELETE CASCADE,
|
||||
version_number INT NOT NULL CHECK (version_number > 0),
|
||||
digest TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'published' CHECK (status IN ('published', 'deprecated')),
|
||||
components_count INT NOT NULL DEFAULT 0,
|
||||
changelog TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
published_at TIMESTAMPTZ,
|
||||
created_by TEXT NOT NULL DEFAULT 'system',
|
||||
CONSTRAINT uq_control_bundle_versions_bundle_version UNIQUE (bundle_id, version_number)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundle_versions_tenant_bundle
|
||||
ON release.control_bundle_versions (tenant_id, bundle_id, version_number DESC, id DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundle_versions_tenant_digest
|
||||
ON release.control_bundle_versions (tenant_id, digest);
|
||||
|
||||
COMMENT ON TABLE release.control_bundle_versions IS
|
||||
'Immutable versions for release-control bundles.';
|
||||
|
||||
-- ============================================================================
|
||||
-- Version components
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.control_bundle_components (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
bundle_id UUID NOT NULL REFERENCES release.control_bundles(id) ON DELETE CASCADE,
|
||||
bundle_version_id UUID NOT NULL REFERENCES release.control_bundle_versions(id) ON DELETE CASCADE,
|
||||
component_version_id TEXT NOT NULL,
|
||||
component_name TEXT NOT NULL,
|
||||
image_digest TEXT NOT NULL,
|
||||
deploy_order INT NOT NULL DEFAULT 0,
|
||||
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_control_bundle_components_unique
|
||||
UNIQUE (bundle_version_id, component_version_id, deploy_order)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundle_components_tenant_version
|
||||
ON release.control_bundle_components (tenant_id, bundle_version_id, deploy_order, component_name, component_version_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundle_components_tenant_bundle
|
||||
ON release.control_bundle_components (tenant_id, bundle_id, bundle_version_id);
|
||||
|
||||
COMMENT ON TABLE release.control_bundle_components IS
|
||||
'Component manifests attached to immutable release-control bundle versions.';
|
||||
|
||||
-- ============================================================================
|
||||
-- Materialization runs
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.control_bundle_materialization_runs (
|
||||
run_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
bundle_id UUID NOT NULL REFERENCES release.control_bundles(id) ON DELETE CASCADE,
|
||||
bundle_version_id UUID NOT NULL REFERENCES release.control_bundle_versions(id) ON DELETE CASCADE,
|
||||
status TEXT NOT NULL DEFAULT 'queued' CHECK (status IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')),
|
||||
target_environment TEXT,
|
||||
reason TEXT,
|
||||
requested_by TEXT NOT NULL DEFAULT 'system',
|
||||
idempotency_key TEXT,
|
||||
requested_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundle_materialization_tenant_version
|
||||
ON release.control_bundle_materialization_runs (tenant_id, bundle_id, bundle_version_id, requested_at DESC, run_id DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_control_bundle_materialization_tenant_status
|
||||
ON release.control_bundle_materialization_runs (tenant_id, status, requested_at DESC);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_control_bundle_materialization_idempotency
|
||||
ON release.control_bundle_materialization_runs (tenant_id, bundle_id, bundle_version_id, idempotency_key)
|
||||
WHERE idempotency_key IS NOT NULL;
|
||||
|
||||
COMMENT ON TABLE release.control_bundle_materialization_runs IS
|
||||
'Auditable materialization runs for release-control bundle versions.';
|
||||
|
||||
-- ============================================================================
|
||||
-- Row level security
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE release.control_bundles ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE release.control_bundle_versions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE release.control_bundle_components ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE release.control_bundle_materialization_runs ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'release'
|
||||
AND tablename = 'control_bundles'
|
||||
AND policyname = 'control_bundles_tenant_isolation') THEN
|
||||
CREATE POLICY control_bundles_tenant_isolation ON release.control_bundles
|
||||
FOR ALL
|
||||
USING (tenant_id = release_app.require_current_tenant())
|
||||
WITH CHECK (tenant_id = release_app.require_current_tenant());
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'release'
|
||||
AND tablename = 'control_bundle_versions'
|
||||
AND policyname = 'control_bundle_versions_tenant_isolation') THEN
|
||||
CREATE POLICY control_bundle_versions_tenant_isolation ON release.control_bundle_versions
|
||||
FOR ALL
|
||||
USING (tenant_id = release_app.require_current_tenant())
|
||||
WITH CHECK (tenant_id = release_app.require_current_tenant());
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'release'
|
||||
AND tablename = 'control_bundle_components'
|
||||
AND policyname = 'control_bundle_components_tenant_isolation') THEN
|
||||
CREATE POLICY control_bundle_components_tenant_isolation ON release.control_bundle_components
|
||||
FOR ALL
|
||||
USING (tenant_id = release_app.require_current_tenant())
|
||||
WITH CHECK (tenant_id = release_app.require_current_tenant());
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'release'
|
||||
AND tablename = 'control_bundle_materialization_runs'
|
||||
AND policyname = 'control_bundle_materialization_runs_tenant_isolation') THEN
|
||||
CREATE POLICY control_bundle_materialization_runs_tenant_isolation ON release.control_bundle_materialization_runs
|
||||
FOR ALL
|
||||
USING (tenant_id = release_app.require_current_tenant())
|
||||
WITH CHECK (tenant_id = release_app.require_current_tenant());
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
-- ============================================================================
|
||||
-- Update triggers
|
||||
-- ============================================================================
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_control_bundles_updated_at ON release.control_bundles;
|
||||
CREATE TRIGGER trg_control_bundles_updated_at
|
||||
BEFORE UPDATE ON release.control_bundles
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION release.update_updated_at_column();
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_control_bundle_materialization_runs_updated_at ON release.control_bundle_materialization_runs;
|
||||
CREATE TRIGGER trg_control_bundle_materialization_runs_updated_at
|
||||
BEFORE UPDATE ON release.control_bundle_materialization_runs
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION release.update_updated_at_column();
|
||||
@@ -0,0 +1,71 @@
|
||||
-- SPRINT_20260219_016 / PACK-ADM-02
|
||||
-- Administration A6 trust and signing owner mutation persistence.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.trust_keys (
|
||||
id uuid PRIMARY KEY,
|
||||
tenant_id uuid NOT NULL,
|
||||
key_alias text NOT NULL,
|
||||
algorithm text NOT NULL,
|
||||
status text NOT NULL,
|
||||
current_version integer NOT NULL DEFAULT 1,
|
||||
metadata_json jsonb NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
created_by text NOT NULL,
|
||||
updated_by text NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_release_trust_keys_tenant_alias
|
||||
ON release.trust_keys (tenant_id, lower(key_alias));
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_release_trust_keys_tenant_status
|
||||
ON release.trust_keys (tenant_id, status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.trust_issuers (
|
||||
id uuid PRIMARY KEY,
|
||||
tenant_id uuid NOT NULL,
|
||||
issuer_name text NOT NULL,
|
||||
issuer_uri text NOT NULL,
|
||||
trust_level text NOT NULL,
|
||||
status text NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
created_by text NOT NULL,
|
||||
updated_by text NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_release_trust_issuers_tenant_uri
|
||||
ON release.trust_issuers (tenant_id, lower(issuer_uri));
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_release_trust_issuers_tenant_status
|
||||
ON release.trust_issuers (tenant_id, status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.trust_certificates (
|
||||
id uuid PRIMARY KEY,
|
||||
tenant_id uuid NOT NULL,
|
||||
key_id uuid NULL REFERENCES release.trust_keys(id) ON DELETE SET NULL,
|
||||
issuer_id uuid NULL REFERENCES release.trust_issuers(id) ON DELETE SET NULL,
|
||||
serial_number text NOT NULL,
|
||||
status text NOT NULL,
|
||||
not_before timestamptz NOT NULL,
|
||||
not_after timestamptz NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
created_by text NOT NULL,
|
||||
updated_by text NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_release_trust_certificates_tenant_serial
|
||||
ON release.trust_certificates (tenant_id, lower(serial_number));
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_release_trust_certificates_tenant_status
|
||||
ON release.trust_certificates (tenant_id, status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS release.trust_transparency_configs (
|
||||
tenant_id uuid PRIMARY KEY,
|
||||
log_url text NOT NULL,
|
||||
witness_url text NULL,
|
||||
enforce_inclusion boolean NOT NULL DEFAULT false,
|
||||
updated_at timestamptz NOT NULL,
|
||||
updated_by text NOT NULL
|
||||
);
|
||||
Reference in New Issue
Block a user