-- 0014_items_public_fields.sql -- -- Phase 4d: public-listing fields so flexsiebels.de (and any future public -- consumer) can render m's portfolio from projax directly via the MCP -- surface. projax becomes the single source of truth for "which projects -- are public, and what should the public copy say about them?" -- -- Five additive, default-safe columns: -- public — single boolean toggle; 95% of items stay false -- public_description — public-facing prose (markdown), free of internal -- notes that live in content_md -- public_live_url — production/demo URL if the project has one -- public_source_url — repo URL if m wants to expose the source -- public_screenshots — ordered list of image URLs; projax stores -- pointers, never bytes (PER discipline §"Out of -- scope (permanent — 2026-05-17)") -- -- The partial index speeds up the "give me everything public" query that -- flexsiebels and the optional /tree filter chip will issue. We keep it -- partial because the predicate is highly selective (only public rows). -- items_unified picks the new columns up automatically via SELECT *. ALTER TABLE projax.items ADD COLUMN IF NOT EXISTS public boolean NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS public_description text NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS public_live_url text NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS public_source_url text NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS public_screenshots text[] NOT NULL DEFAULT '{}'; CREATE INDEX IF NOT EXISTS items_public_idx ON projax.items (public) WHERE public = true; -- items_unified is the canonical read shape every web/MCP code path uses. -- The five new columns have to flow through it, otherwise Item.* writes -- silently drop on read. DROP+CREATE because Postgres won't append columns -- to an existing view via CREATE OR REPLACE. DROP VIEW IF EXISTS projax.items_unified; CREATE VIEW projax.items_unified AS SELECT i.id, i.kind, i.title, i.slug, i.paths, i.parent_ids, i.content_md, i.aliases, i.metadata, i.status, i.pinned, i.archived, i.start_time, i.end_time, 'projax'::text AS source, (SELECT l.ref_id FROM projax.item_links l WHERE l.item_id = i.id AND l.ref_type = 'mai-project' LIMIT 1) AS source_ref_id, i.tags, i.management, i.public, i.public_description, i.public_live_url, i.public_source_url, i.public_screenshots, i.created_at, i.updated_at FROM projax.items i WHERE i.deleted_at IS NULL; DO $own$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'projax_admin') THEN EXECUTE 'ALTER VIEW projax.items_unified OWNER TO projax_admin'; EXECUTE 'GRANT SELECT ON projax.items_unified TO projax_admin'; END IF; END $own$;