Files
git.stella-ops.org/devops/compose/postgres-init/16-release-full-schema.sql
master 24be2f2268 chore(devops): dotnet release image + compose/bootstrap stabilization
Sprint SPRINT_20260417_024_DevOps_dotnet_release_image_stabilization.

- Dockerfile.platform + Dockerfile.dotnet-service adjustments for
  deterministic layer ordering and cache-friendly publish.
- devops/release/components.json updates.
- devops/compose: .env, README, legacy + stella-services docker-compose,
  stellaops env example, postgres-init 04/04b/15/16 authority + release
  schemas, setup.bootstrap.local.yaml.
- Gitea build_release.py script.
- scripts/register-local-integrations.ps1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:43:23 +03:00

134 lines
4.9 KiB
PL/PgSQL

-- Release module full schema bootstrap for local dev compose.
-- Includes schemas, tenants, integration hub, environments, release management,
-- workflow, promotion, deployment, agents, trust/signing, and read models.
-- All statements are idempotent (IF NOT EXISTS / ON CONFLICT).
-- Shared tenants (required by release.integrations FK)
CREATE SCHEMA IF NOT EXISTS shared;
CREATE TABLE IF NOT EXISTS shared.tenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
display_name TEXT,
is_default BOOLEAN NOT NULL DEFAULT false,
status TEXT NOT NULL DEFAULT 'active',
settings JSONB NOT NULL DEFAULT '{}',
metadata JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX IF NOT EXISTS uq_shared_tenants_single_default
ON shared.tenants (is_default)
WHERE is_default;
-- Seed the generic default tenant required by release/shared foreign keys.
INSERT INTO shared.tenants (tenant_id, name, display_name, is_default, status)
VALUES ('default', 'Default', 'Default Tenant', true, 'active')
ON CONFLICT (tenant_id) DO UPDATE
SET name = EXCLUDED.name,
display_name = EXCLUDED.display_name,
is_default = EXCLUDED.is_default,
status = EXCLUDED.status;
-- Release schemas
CREATE SCHEMA IF NOT EXISTS release;
CREATE SCHEMA IF NOT EXISTS release_app;
-- Helper function for updated_at triggers
CREATE OR REPLACE FUNCTION release.update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Tenant isolation function
CREATE OR REPLACE FUNCTION release_app.require_current_tenant()
RETURNS UUID
LANGUAGE plpgsql STABLE SECURITY DEFINER
AS $$
DECLARE
v_tenant TEXT;
BEGIN
v_tenant := current_setting('app.tenant_id', true);
IF v_tenant IS NULL OR v_tenant = '' THEN
RAISE EXCEPTION 'app.tenant_id session variable not set';
END IF;
RETURN v_tenant::UUID;
END;
$$;
-- Analytics schema
CREATE SCHEMA IF NOT EXISTS analytics;
-- ── Regions (bootstrap fallback for release.regions) ──
CREATE TABLE IF NOT EXISTS release.regions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES shared.tenants(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
display_name VARCHAR(255) NOT NULL,
description TEXT,
crypto_profile VARCHAR(50) NOT NULL DEFAULT 'international',
sort_order INT NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','decommissioning','archived')),
metadata JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID,
UNIQUE(tenant_id, name)
);
-- ── Infrastructure Bindings (bootstrap fallback) ──
CREATE TABLE IF NOT EXISTS release.infrastructure_bindings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES shared.tenants(id) ON DELETE CASCADE,
integration_id UUID,
scope_type TEXT NOT NULL CHECK (scope_type IN ('tenant','region','environment')),
scope_id UUID,
binding_role TEXT NOT NULL CHECK (binding_role IN ('registry','vault','settings_store')),
priority INT NOT NULL DEFAULT 0,
config_overrides JSONB NOT NULL DEFAULT '{}',
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID
);
-- ── Topology Point Status (bootstrap fallback) ──
CREATE TABLE IF NOT EXISTS release.topology_point_status (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
target_id UUID,
gate_name TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('pending','pass','fail','skip')),
message TEXT,
details JSONB NOT NULL DEFAULT '{}',
checked_at TIMESTAMPTZ,
duration_ms INT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- ── Pending Deletions (bootstrap fallback) ──
CREATE TABLE IF NOT EXISTS release.pending_deletions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
entity_type TEXT NOT NULL CHECK (entity_type IN ('tenant','region','environment','target','agent','integration')),
entity_id UUID NOT NULL,
entity_name TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('pending','confirmed','executing','completed','cancelled')),
cool_off_hours INT NOT NULL,
cool_off_expires_at TIMESTAMPTZ NOT NULL,
cascade_summary JSONB NOT NULL DEFAULT '{}',
reason TEXT,
requested_by UUID NOT NULL,
requested_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
confirmed_by UUID,
confirmed_at TIMESTAMPTZ,
executed_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);