t-paliad-340 — B0 of edison's 7-slice train (PRD §7.1). DB-only: schema + RLS land, dev-only test route exercises the surface, no user-facing change. B1 wires the actual builder UI on top. Migration 157 (additive on the legacy mig-145 scenarios table — 0 rows in prod, safe to relax): - paliad.scenarios gets owner_id / status / origin_project_id / promoted_project_id / stichtag / notes. spec drops NOT NULL and the scenarios_unique_per_scope constraint drops (the builder allows multiple scratch + Unbenanntes Szenario rows per user). - New tables: scenario_proceedings, scenario_events, scenario_shares. - paliad.projects.origin_scenario_id for the promote-to-project audit trail (the FK lands now; the wizard ships in B5). - paliad.can_see_scenario(uuid) STABLE SECURITY DEFINER helper covering owner / share / global_admin / two legacy paths. - Replacement RLS on scenarios + RLS on the three new tables; legacy service + handlers stay live and unchanged. PRD §5.1 deviations called out in the migration header: - proceeding_type_id is integer (live schema), not uuid (PRD draft). - FK target is paliad.users, matching the rest of paliad's schema. Go surface: - ScenarioBuilderService — list/create/get-deep/patch scenarios, add/patch/delete proceedings, add/patch/delete events, add/delete shares. Writes wrap in transactions with set_config( paliad.audit_reason, ..., true) per event_choice_service.go pattern. - /api/builder/scenarios/* — handlers register under a builder/ prefix so the legacy /api/scenarios surface still works. - /dev/scenario-builder — single-page HTML form gated to PaliadinOwnerEmail, exercises the B0 surface without Postman. - Live-DB integration test (TEST_DATABASE_URL gated) covers create + list + deep-get + share + visibility negatives + patch. Audit-first: every DDL block ran clean via BEGIN/ROLLBACK against the live DB before commit; end-to-end sanity (insert chain + CHECK constraints + CASCADE-on-delete) verified via the Supabase MCP. bun build clean. go vet + go test -short ./... green.
95 lines
3.9 KiB
PL/PgSQL
95 lines
3.9 KiB
PL/PgSQL
-- 157_scenario_builder_foundation — down
|
|
--
|
|
-- Rolls back mig 157 in reverse order. Down files are reference material
|
|
-- (not auto-applied); operator recovery path is:
|
|
--
|
|
-- psql ... < 157_scenario_builder_foundation.down.sql
|
|
-- DELETE FROM paliad.applied_migrations WHERE version = 157;
|
|
--
|
|
-- This restores the legacy paliad.scenarios shape from mig 145 — the
|
|
-- builder columns and the three sibling tables are dropped wholesale.
|
|
-- Any builder data in the dropped tables is lost (the tables CASCADE to
|
|
-- their children, and DROP TABLE doesn't keep a backup).
|
|
|
|
BEGIN;
|
|
|
|
SELECT set_config(
|
|
'paliad.audit_reason',
|
|
'mig 157 rollback: tear down Scenario builder foundation (t-paliad-340)',
|
|
true
|
|
);
|
|
|
|
-- 8. updated_at triggers
|
|
DROP TRIGGER IF EXISTS scenario_events_touch_updated_at_trg ON paliad.scenario_events;
|
|
DROP TRIGGER IF EXISTS scenario_proceedings_touch_updated_at_trg ON paliad.scenario_proceedings;
|
|
|
|
-- 7. RLS — drop new policies + restore legacy four
|
|
DROP POLICY IF EXISTS scenario_shares_mutate ON paliad.scenario_shares;
|
|
DROP POLICY IF EXISTS scenario_shares_select ON paliad.scenario_shares;
|
|
DROP POLICY IF EXISTS scenario_events_mutate ON paliad.scenario_events;
|
|
DROP POLICY IF EXISTS scenario_events_select ON paliad.scenario_events;
|
|
DROP POLICY IF EXISTS scenario_proceedings_mutate ON paliad.scenario_proceedings;
|
|
DROP POLICY IF EXISTS scenario_proceedings_select ON paliad.scenario_proceedings;
|
|
DROP POLICY IF EXISTS scenarios_owner_mutate ON paliad.scenarios;
|
|
DROP POLICY IF EXISTS scenarios_select ON paliad.scenarios;
|
|
|
|
-- Restore the four mig-145 policies verbatim.
|
|
CREATE POLICY scenarios_project_select ON paliad.scenarios
|
|
FOR SELECT
|
|
USING (project_id IS NOT NULL AND paliad.can_see_project(project_id));
|
|
|
|
CREATE POLICY scenarios_project_mutate ON paliad.scenarios
|
|
FOR ALL
|
|
USING (project_id IS NOT NULL AND paliad.can_see_project(project_id))
|
|
WITH CHECK (project_id IS NOT NULL AND paliad.can_see_project(project_id));
|
|
|
|
CREATE POLICY scenarios_abstract_select ON paliad.scenarios
|
|
FOR SELECT
|
|
USING (project_id IS NULL AND created_by = auth.uid());
|
|
|
|
CREATE POLICY scenarios_abstract_mutate ON paliad.scenarios
|
|
FOR ALL
|
|
USING (project_id IS NULL AND created_by = auth.uid())
|
|
WITH CHECK (project_id IS NULL AND created_by = auth.uid());
|
|
|
|
-- 6. helper function
|
|
DROP FUNCTION IF EXISTS paliad.can_see_scenario(uuid);
|
|
|
|
-- 5. paliad.projects.origin_scenario_id
|
|
DROP INDEX IF EXISTS paliad.projects_origin_scenario_idx;
|
|
ALTER TABLE paliad.projects DROP COLUMN IF EXISTS origin_scenario_id;
|
|
|
|
-- 4. paliad.scenario_shares
|
|
DROP TABLE IF EXISTS paliad.scenario_shares;
|
|
|
|
-- 3. paliad.scenario_events
|
|
DROP TABLE IF EXISTS paliad.scenario_events;
|
|
|
|
-- 2. paliad.scenario_proceedings
|
|
DROP TABLE IF EXISTS paliad.scenario_proceedings;
|
|
|
|
-- 1. paliad.scenarios — restore mig-145 shape
|
|
DROP INDEX IF EXISTS paliad.scenarios_updated_idx;
|
|
DROP INDEX IF EXISTS paliad.scenarios_owner_status_idx;
|
|
|
|
-- Restore the unique constraint mig 145 had.
|
|
ALTER TABLE paliad.scenarios
|
|
ADD CONSTRAINT scenarios_unique_per_scope
|
|
UNIQUE NULLS NOT DISTINCT (project_id, created_by, name);
|
|
|
|
-- spec was NOT NULL in mig 145. Restore that — but only after backfilling
|
|
-- any NULL specs the builder might have created (none in legacy paths;
|
|
-- only builder rows have NULL spec, and those are dropped together with
|
|
-- the builder schema if a real rollback is needed).
|
|
UPDATE paliad.scenarios SET spec = '{}'::jsonb WHERE spec IS NULL;
|
|
ALTER TABLE paliad.scenarios ALTER COLUMN spec SET NOT NULL;
|
|
|
|
ALTER TABLE paliad.scenarios DROP COLUMN IF EXISTS notes;
|
|
ALTER TABLE paliad.scenarios DROP COLUMN IF EXISTS stichtag;
|
|
ALTER TABLE paliad.scenarios DROP COLUMN IF EXISTS promoted_project_id;
|
|
ALTER TABLE paliad.scenarios DROP COLUMN IF EXISTS origin_project_id;
|
|
ALTER TABLE paliad.scenarios DROP COLUMN IF EXISTS status;
|
|
ALTER TABLE paliad.scenarios DROP COLUMN IF EXISTS owner_id;
|
|
|
|
COMMIT;
|