feat(db): add project personas and skills tables
CI / build-and-test (push) Failing after 1m52s

* Introduce project_personas table with foreign keys to projects and agent_personas
* Add project_skills table with foreign key to projects and agent_skills
* Include override boolean field in agent_persona_skills and project_skills
* Update schema and migration files to reflect new tables and fields
* Enhance CORS handling to reflect request origin
This commit is contained in:
2026-07-04 23:45:51 +02:00
parent 1adf50e3db
commit c179e014ad
69 changed files with 1329 additions and 184 deletions
+369 -1
View File
@@ -33,6 +33,13 @@ CREATE SEQUENCE IF NOT EXISTS public.identity_agent_persona_skills_id
START 1
CACHE 1;
CREATE SEQUENCE IF NOT EXISTS public.identity_project_personas_id
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
CREATE SEQUENCE IF NOT EXISTS public.identity_agent_persona_guardrails_id
INCREMENT 1
MINVALUE 1
@@ -75,7 +82,7 @@ CREATE SEQUENCE IF NOT EXISTS public.identity_arc_stage_parts_id
START 1
CACHE 1;
CREATE SEQUENCE IF NOT EXISTS public.identity_persona_arc_id
CREATE SEQUENCE IF NOT EXISTS public.identity_persona_arc_persona_id
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
@@ -247,10 +254,19 @@ CREATE TABLE IF NOT EXISTS public.agent_persona_parts (
CREATE TABLE IF NOT EXISTS public.agent_persona_skills (
id bigserial NOT NULL,
override boolean NOT NULL DEFAULT false,
persona_id bigint NOT NULL,
skill_id bigint NOT NULL
);
CREATE TABLE IF NOT EXISTS public.project_personas (
created_at timestamptz NOT NULL DEFAULT now(),
id bigserial NOT NULL,
is_default boolean NOT NULL DEFAULT false,
persona_id bigint NOT NULL,
project_id bigint NOT NULL
);
CREATE TABLE IF NOT EXISTS public.agent_persona_guardrails (
guardrail_id bigint NOT NULL,
id bigserial NOT NULL,
@@ -496,6 +512,7 @@ CREATE TABLE IF NOT EXISTS public.agent_guardrails (
CREATE TABLE IF NOT EXISTS public.project_skills (
created_at timestamptz NOT NULL DEFAULT now(),
id bigserial NOT NULL,
override boolean NOT NULL DEFAULT false,
project_id bigint NOT NULL,
skill_id bigint NOT NULL
);
@@ -872,6 +889,19 @@ BEGIN
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'agent_persona_skills'
AND column_name = 'override'
) THEN
ALTER TABLE public.agent_persona_skills ADD COLUMN override boolean NOT NULL DEFAULT false;
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
@@ -898,6 +928,71 @@ BEGIN
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND column_name = 'created_at'
) THEN
ALTER TABLE public.project_personas ADD COLUMN created_at timestamptz NOT NULL DEFAULT now();
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND column_name = 'id'
) THEN
ALTER TABLE public.project_personas ADD COLUMN id bigserial NOT NULL;
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND column_name = 'is_default'
) THEN
ALTER TABLE public.project_personas ADD COLUMN is_default boolean NOT NULL DEFAULT false;
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND column_name = 'persona_id'
) THEN
ALTER TABLE public.project_personas ADD COLUMN persona_id bigint NOT NULL;
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND column_name = 'project_id'
) THEN
ALTER TABLE public.project_personas ADD COLUMN project_id bigint NOT NULL;
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
@@ -3173,6 +3268,19 @@ BEGIN
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_skills'
AND column_name = 'override'
) THEN
ALTER TABLE public.project_skills ADD COLUMN override boolean NOT NULL DEFAULT false;
END IF;
END;
$$;
DO $$
BEGIN
IF NOT EXISTS (
@@ -3896,6 +4004,29 @@ BEGIN
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'agent_persona_skills'
AND a.attname = 'override'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['boolean']) THEN
ALTER TABLE public.agent_persona_skills
ALTER COLUMN override TYPE boolean USING override::boolean;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
@@ -3942,6 +4073,121 @@ BEGIN
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'project_personas'
AND a.attname = 'created_at'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['timestamptz', 'timestamp with time zone']) THEN
ALTER TABLE public.project_personas
ALTER COLUMN created_at TYPE timestamptz USING created_at::timestamptz;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'project_personas'
AND a.attname = 'id'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['bigint']) THEN
ALTER TABLE public.project_personas
ALTER COLUMN id TYPE bigint USING id::bigint;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'project_personas'
AND a.attname = 'is_default'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['boolean']) THEN
ALTER TABLE public.project_personas
ALTER COLUMN is_default TYPE boolean USING is_default::boolean;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'project_personas'
AND a.attname = 'persona_id'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['bigint']) THEN
ALTER TABLE public.project_personas
ALTER COLUMN persona_id TYPE bigint USING persona_id::bigint;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'project_personas'
AND a.attname = 'project_id'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['bigint']) THEN
ALTER TABLE public.project_personas
ALTER COLUMN project_id TYPE bigint USING project_id::bigint;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
@@ -7967,6 +8213,29 @@ BEGIN
END;
$$;
DO $$
DECLARE
current_type text;
BEGIN
SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
INTO current_type
FROM pg_attribute a
JOIN pg_class t ON t.oid = a.attrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
WHERE n.nspname = 'public'
AND t.relname = 'project_skills'
AND a.attname = 'override'
AND a.attnum > 0
AND NOT a.attisdropped;
IF current_type IS NOT NULL
AND current_type <> ALL(ARRAY['boolean']) THEN
ALTER TABLE public.project_skills
ALTER COLUMN override TYPE boolean USING override::boolean;
END IF;
END;
$$;
DO $$
DECLARE
current_type text;
@@ -8282,6 +8551,50 @@ BEGIN
END;
$$;
DO $$
DECLARE
current_pk_name text;
current_pk_matches boolean := false;
BEGIN
SELECT tc.constraint_name,
COALESCE(
ARRAY(
SELECT a.attname::text
FROM pg_constraint c
JOIN pg_class t ON t.oid = c.conrelid
JOIN pg_namespace n ON n.oid = t.relnamespace
JOIN unnest(c.conkey) WITH ORDINALITY AS cols(attnum, ord)
ON TRUE
JOIN pg_attribute a
ON a.attrelid = t.oid
AND a.attnum = cols.attnum
WHERE c.contype = 'p'
AND n.nspname = 'public'
AND t.relname = 'project_personas'
ORDER BY cols.ord
),
ARRAY[]::text[]
) = ARRAY['id']
INTO current_pk_name, current_pk_matches
FROM information_schema.table_constraints tc
WHERE tc.table_schema = 'public'
AND tc.table_name = 'project_personas'
AND tc.constraint_type = 'PRIMARY KEY';
IF current_pk_name IS NOT NULL
AND NOT current_pk_matches
AND current_pk_name IN ('project_personas_pkey', 'public_project_personas_pkey') THEN
EXECUTE 'ALTER TABLE public.project_personas DROP CONSTRAINT ' || quote_ident(current_pk_name) || ' CASCADE';
END IF;
-- Add the desired primary key only when no matching primary key already exists.
IF current_pk_name IS NULL
OR (NOT current_pk_matches AND current_pk_name IN ('project_personas_pkey', 'public_project_personas_pkey')) THEN
ALTER TABLE public.project_personas ADD CONSTRAINT pk_public_project_personas PRIMARY KEY (id);
END IF;
END;
$$;
DO $$
DECLARE
current_pk_name text;
@@ -9389,6 +9702,9 @@ CREATE INDEX IF NOT EXISTS idx_agent_persona_parts_persona_id_part_id
CREATE INDEX IF NOT EXISTS idx_agent_persona_skills_persona_id_skill_id
ON public.agent_persona_skills USING btree (persona_id, skill_id);
CREATE INDEX IF NOT EXISTS idx_project_personas_project_id_persona_id
ON public.project_personas USING btree (project_id, persona_id);
CREATE INDEX IF NOT EXISTS idx_arc_stage_parts_stage_id_part_id
ON public.arc_stage_parts USING btree (stage_id, part_id);
@@ -9772,6 +10088,38 @@ BEGIN
END IF;
END;
$$;DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.table_constraints
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND constraint_name = 'fk_project_personas_persona_id'
) THEN
ALTER TABLE public.project_personas
ADD CONSTRAINT fk_project_personas_persona_id
FOREIGN KEY (persona_id)
REFERENCES public.agent_personas (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
END IF;
END;
$$;DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.table_constraints
WHERE table_schema = 'public'
AND table_name = 'project_personas'
AND constraint_name = 'fk_project_personas_project_id'
) THEN
ALTER TABLE public.project_personas
ADD CONSTRAINT fk_project_personas_project_id
FOREIGN KEY (project_id)
REFERENCES public.projects (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
END IF;
END;
$$;DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.table_constraints
@@ -10425,6 +10773,25 @@ BEGIN
END;
$$;
DO $$
DECLARE
m_cnt bigint;
BEGIN
IF EXISTS (
SELECT 1 FROM pg_class c
INNER JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'identity_project_personas_id'
AND n.nspname = 'public'
AND c.relkind = 'S'
) THEN
SELECT COALESCE(MAX(id), 0) + 1
FROM public.project_personas
INTO m_cnt;
PERFORM setval('public.identity_project_personas_id'::regclass, m_cnt);
END IF;
END;
$$;
DO $$
DECLARE
m_cnt bigint;
BEGIN
@@ -10927,5 +11294,6 @@ $$;