Tactical Media Broadcast Hub — initial release

Self-hosted multi-platform broadcast newsroom for activist collectives:
publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style
column wall with hostile-content-safe rendering, live control room with Auto
Director, bridged chat governance with polls and quorum, distributed sandboxed
transcode workers, encrypted content-addressed archive, monthly analytics.

MIT licensed. See README.md and docs/.
This commit is contained in:
glass beadian 2026-10-10 11:56:42 +00:00
commit aa5e262f3a
880 changed files with 111042 additions and 0 deletions

View file

@ -0,0 +1,52 @@
-- 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;