-- 009: first-class video assets and their processing lifecycle CREATE TABLE video_assets ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), workspace_id uuid NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, storage_key text NOT NULL, mime_type text NOT NULL, size_bytes bigint NOT NULL, width int, height int, duration_ms int, frame_rate numeric, codec text, audio_codec text, thumbnail_key text, created_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE video_processing_jobs ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), workspace_id uuid NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, video_asset_id uuid NOT NULL REFERENCES video_assets(id) ON DELETE CASCADE, state text NOT NULL CHECK (state IN ('queued', 'probing', 'transcoding', 'complete', 'failed')), progress_percent int NOT NULL DEFAULT 0, output_key text, error text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX video_assets_workspace_created ON video_assets (workspace_id, created_at DESC, id DESC); CREATE INDEX video_processing_jobs_asset_created ON video_processing_jobs (video_asset_id, created_at DESC); CREATE TRIGGER trg_video_asset_ws_immutable BEFORE UPDATE ON video_assets FOR EACH ROW EXECUTE FUNCTION reject_workspace_change(); CREATE TRIGGER trg_video_job_ws_immutable BEFORE UPDATE ON video_processing_jobs FOR EACH ROW EXECUTE FUNCTION reject_workspace_change(); ALTER TABLE video_assets ENABLE ROW LEVEL SECURITY; ALTER TABLE video_processing_jobs ENABLE ROW LEVEL SECURITY; ALTER TABLE video_assets FORCE ROW LEVEL SECURITY; ALTER TABLE video_processing_jobs FORCE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation ON video_assets USING (workspace_id = NULLIF(current_setting('app.workspace_id', true), '')::uuid) WITH CHECK (workspace_id = NULLIF(current_setting('app.workspace_id', true), '')::uuid); CREATE POLICY tenant_isolation ON video_processing_jobs USING (workspace_id = NULLIF(current_setting('app.workspace_id', true), '')::uuid) WITH CHECK (workspace_id = NULLIF(current_setting('app.workspace_id', true), '')::uuid); GRANT SELECT, INSERT, UPDATE, DELETE ON video_assets, video_processing_jobs TO sp_app;