diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 359abe94b..4942cd2a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -382,6 +382,8 @@ jobs: PGDATABASE: buzz run: | ./bin/pgschema apply --file schema/schema.sql --auto-approve + docker exec -i -e PGPASSWORD=buzz_dev buzz-postgres \ + psql -U buzz -d buzz -v ON_ERROR_STOP=1 < scripts/attach-schema-partitions.sql docker exec -e PGPASSWORD=buzz_dev buzz-postgres \ psql -U buzz -d buzz -qtA -c " INSERT INTO communities (id, host) @@ -513,6 +515,8 @@ jobs: PGDATABASE: buzz run: | ./bin/pgschema apply --file schema/schema.sql --auto-approve + docker exec -i -e PGPASSWORD=buzz_dev buzz-postgres \ + psql -U buzz -d buzz -v ON_ERROR_STOP=1 < scripts/attach-schema-partitions.sql docker exec -e PGPASSWORD=buzz_dev buzz-postgres \ psql -U buzz -d buzz -qtA -c " INSERT INTO communities (id, host) diff --git a/schema/schema.sql b/schema/schema.sql index c59cd8755..3040a79d1 100644 --- a/schema/schema.sql +++ b/schema/schema.sql @@ -203,7 +203,14 @@ CREATE TABLE events ( -- community-leading btree filters BitmapAnd-ed with the GIN probe, so the -- GIN index itself stays the minimal `GIN (search_tsv)` (Max's caveat: -- avoid btree_gin unless EXPLAIN proves it buys something). - search_tsv TSVECTOR GENERATED ALWAYS AS (to_tsvector('simple', content)) STORED, + -- Privacy: encrypted/private routing wrappers must never be discoverable + -- through NIP-50 full-text search. NULL tsvector never matches `@@`. + -- Keep in sync with migrations/0001_initial_schema.sql. + search_tsv TSVECTOR GENERATED ALWAYS AS ( + CASE WHEN kind IN (1059, 30300, 30622) THEN NULL::tsvector + ELSE to_tsvector('simple', content) + END + ) STORED, sig BYTEA NOT NULL, received_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), channel_id UUID, diff --git a/scripts/attach-schema-partitions.sql b/scripts/attach-schema-partitions.sql new file mode 100644 index 000000000..de9e94011 --- /dev/null +++ b/scripts/attach-schema-partitions.sql @@ -0,0 +1,137 @@ +-- Attach partition child tables after pgschema apply. +-- +-- pgschema currently emits existing partition children as standalone CREATE TABLE +-- statements when applying schema/schema.sql in CI. The tables exist, but they +-- are not attached to their partitioned parents, so inserts into events or +-- delivery_log fail with "no partition of relation ... found for row". Keep this +-- idempotent: raw psql/schema.sql already attaches these partitions, while +-- pgschema-created schemas need this repair step. + +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p_past'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p_past + FOR VALUES FROM (MINVALUE) TO ('2026-01-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p2026_01'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p2026_01 + FOR VALUES FROM ('2026-01-01') TO ('2026-02-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p2026_02'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p2026_02 + FOR VALUES FROM ('2026-02-01') TO ('2026-03-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p2026_03'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p2026_03 + FOR VALUES FROM ('2026-03-01') TO ('2026-04-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p2026_04'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p2026_04 + FOR VALUES FROM ('2026-04-01') TO ('2026-05-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p2026_05'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p2026_05 + FOR VALUES FROM ('2026-05-01') TO ('2026-06-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p2026_06'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p2026_06 + FOR VALUES FROM ('2026-06-01') TO ('2026-07-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'events'::regclass + AND inhrelid = 'events_p_future'::regclass + ) THEN + ALTER TABLE events ATTACH PARTITION events_p_future + FOR VALUES FROM ('2026-07-01') TO (MAXVALUE); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'delivery_log'::regclass + AND inhrelid = 'delivery_log_p_past'::regclass + ) THEN + ALTER TABLE delivery_log ATTACH PARTITION delivery_log_p_past + FOR VALUES FROM (MINVALUE) TO ('2026-03-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'delivery_log'::regclass + AND inhrelid = 'delivery_log_p2026_03'::regclass + ) THEN + ALTER TABLE delivery_log ATTACH PARTITION delivery_log_p2026_03 + FOR VALUES FROM ('2026-03-01') TO ('2026-04-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'delivery_log'::regclass + AND inhrelid = 'delivery_log_p2026_04'::regclass + ) THEN + ALTER TABLE delivery_log ATTACH PARTITION delivery_log_p2026_04 + FOR VALUES FROM ('2026-04-01') TO ('2026-05-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'delivery_log'::regclass + AND inhrelid = 'delivery_log_p2026_05'::regclass + ) THEN + ALTER TABLE delivery_log ATTACH PARTITION delivery_log_p2026_05 + FOR VALUES FROM ('2026-05-01') TO ('2026-06-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'delivery_log'::regclass + AND inhrelid = 'delivery_log_p2026_06'::regclass + ) THEN + ALTER TABLE delivery_log ATTACH PARTITION delivery_log_p2026_06 + FOR VALUES FROM ('2026-06-01') TO ('2026-07-01'); + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_inherits + WHERE inhparent = 'delivery_log'::regclass + AND inhrelid = 'delivery_log_p_future'::regclass + ) THEN + ALTER TABLE delivery_log ATTACH PARTITION delivery_log_p_future + FOR VALUES FROM ('2026-07-01') TO (MAXVALUE); + END IF; +END $$; diff --git a/scripts/start-relay-for-tests.sh b/scripts/start-relay-for-tests.sh index 7dfb1b6da..c752cd5c8 100755 --- a/scripts/start-relay-for-tests.sh +++ b/scripts/start-relay-for-tests.sh @@ -90,6 +90,8 @@ export PGPASSWORD=buzz_dev export PGDATABASE=buzz ./bin/pgschema apply --file schema/schema.sql --auto-approve +docker exec -i -e PGPASSWORD="${PGPASSWORD}" buzz-postgres \ + psql -U "${PGUSER}" -d "${PGDATABASE}" -v ON_ERROR_STOP=1 < scripts/attach-schema-partitions.sql ok "Schema applied" # ── Seed the deployment community ────────────────────────────────────────────