-- Platform context tables (regions, environments, preferences) and release control bundles. -- Required for the global context/filter UI and release management read models. -- Idempotent: uses IF NOT EXISTS and ON CONFLICT. CREATE SCHEMA IF NOT EXISTS platform; CREATE SCHEMA IF NOT EXISTS release; CREATE SCHEMA IF NOT EXISTS release_app; -- Helper function CREATE OR REPLACE FUNCTION release.update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $$ LANGUAGE plpgsql; -- Context regions CREATE TABLE IF NOT EXISTS platform.context_regions ( region_id text PRIMARY KEY, display_name text NOT NULL, sort_order integer NOT NULL, enabled boolean NOT NULL DEFAULT true ); CREATE UNIQUE INDEX IF NOT EXISTS ux_platform_context_regions_sort ON platform.context_regions (sort_order, region_id); -- Context environments CREATE TABLE IF NOT EXISTS platform.context_environments ( environment_id text PRIMARY KEY, region_id text NOT NULL REFERENCES platform.context_regions(region_id) ON DELETE RESTRICT, environment_type text NOT NULL, display_name text NOT NULL, sort_order integer NOT NULL, enabled boolean NOT NULL DEFAULT true ); CREATE INDEX IF NOT EXISTS ix_platform_context_environments_region_sort ON platform.context_environments (region_id, sort_order, environment_id); CREATE INDEX IF NOT EXISTS ix_platform_context_environments_sort ON platform.context_environments (sort_order, region_id, environment_id); -- UI context preferences (per-user filter state) CREATE TABLE IF NOT EXISTS platform.ui_context_preferences ( tenant_id text NOT NULL, actor_id text NOT NULL, regions text[] NOT NULL DEFAULT ARRAY[]::text[], environments text[] NOT NULL DEFAULT ARRAY[]::text[], time_window text NOT NULL DEFAULT '24h', updated_at timestamptz NOT NULL DEFAULT now(), updated_by text NOT NULL DEFAULT 'system', PRIMARY KEY (tenant_id, actor_id) ); CREATE INDEX IF NOT EXISTS ix_platform_ui_context_preferences_updated ON platform.ui_context_preferences (updated_at DESC, tenant_id, actor_id); -- Release control bundles 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); -- Seed demo context data for local development INSERT INTO platform.context_regions (region_id, display_name, sort_order, enabled) VALUES ('us-east', 'US East', 1, true), ('us-west', 'US West', 2, true), ('eu-west', 'EU West', 3, true) ON CONFLICT (region_id) DO NOTHING; INSERT INTO platform.context_environments (environment_id, region_id, environment_type, display_name, sort_order, enabled) VALUES ('dev', 'us-east', 'development', 'Development', 1, true), ('stage', 'us-east', 'staging', 'Staging', 2, true), ('prod-us-east', 'us-east', 'production', 'Production US East', 3, true), ('prod-us-west', 'us-west', 'production', 'Production US West', 4, true), ('prod-eu-west', 'eu-west', 'production', 'Production EU West', 5, true) ON CONFLICT (environment_id) DO NOTHING;