Commit graph

11 commits

Author SHA1 Message Date
3e4fb970c3 fix: Mastodon connector loadAsset/openAsset receive the connection
uploadAll/uploadAsset call the media hooks with (connection, assetId) so
implementations can resolve the workspace; the registry adapter threads
connection.workspaceId into the resolver.
2026-10-15 19:25:16 +00:00
b8115eec09 fix: wire scheduler media resolver into publishing registry
The registry accepted media hooks but nothing supplied them, so Mastodon
media posts failed uploadAll (INVALID_POST attempts). PublishingMediaResolver
in the scheduler resolves workspace-scoped media_assets rows via RLS tenant
context and reads plaintext bytes from S3 with SPENC1 open (S3_KEK), matching
the api's S3Storage frame format.
2026-10-15 18:44:18 +00:00
9e8653aca5 feat: publishing registry media seam (loadAsset/openAsset) + SPENC1 decrypt + multipart transport
The Mastodon connector's uploadAll resolves asset ids via loadAsset/openAsset.
The registry wires these hooks from a mediaResolver that the scheduler injects:
media_assets lookup (workspace-scoped via SET LOCAL) + R2 download + SPENC1
decrypt (extracted from the api's storage into connector-runtime/media.ts).
provider-fetch gains serializeBody for multipart media uploads through the
pinned transport channel.
2026-10-15 16:48:57 +00:00
a6843e904b feat: rich-media publishing chain (repository gate lift + assembly builder + produce store)
publishing-execution: approved posts may carry mediaAssetIds + altTexts.
MAX_MEDIA_ATTACHMENTS = 4 (Mastodon's cap). The old text-only gate is lifted.
assertApprovedMediaShape validates the shapes; the provider-side
mediaIds stay reserved.

media-worker: producer module — pg-store (claim via produce_job_claim
SECURITY DEFINER fn), runner (getObject → filter_complex → putContent →
derived asset), command-builder (normalize, transpose, drawtext, ducking),
s3-storage (SPENC1 decrypt + putContent), env (lane, font). Migration 040:
produce_job_claim + produce_job_workspace definer functions.

produce.ts: scratch dir bootstrap at startup.
2026-10-15 10:07:09 +00:00
6161ac4740 Manual: full participation guide (media/accounts/decisions/safety) + Enter-to-door + provisioner env passthrough 2026-10-12 15:49:25 +00:00
4a7e78b28d Collectives P1: participation landing (ES/EN), group tree, room provisioning APIs
- 030: groups.parent_id tree + kind discriminator + group_rooms mapping
- /collectives module: create/tree/join APIs, MatrixProvisioner (open room
  public+federated, closed room E2EE-at-creation, onboarding room), NullProvisioner
  fail-soft when ARCHIVE_PROVISIONER_* unset
- web root becomes the public participation manual (ES-first + EN toggle,
  three paths: join by invite, start collective, solo account)
- participation manual content in core
2026-10-12 13:53:40 +00:00
c31762b82d connector-facebook: drop ambiguous Response annotations (type-hoisting collision) 2026-10-12 13:53:40 +00:00
23bd4dd5ad Exclude connector-sdk tests from the build typecheck
The docker build (fresh install, container @types resolution) fails on
http.test.ts's enhanced-Response mock (bytes/textStream) — tests are vitest
territory, never part of the dist build.
2026-10-11 11:21:53 +00:00
4bf90ffe25 Complete files UI rewiring to the deployed api surface; expose mimeClass
page.tsx now calls the real backend: GET /files with groupId/name/mimeClass/
cursor/limit (origin filter dropped — the api has no origin param), shares
tracked as ShareCreated (revoke by id), retention mapped to the orthogonal
legalHold model, downloads by item.name, samples reshaped to the wire
contract.

GroupFile gains mimeClass (the indexed coarse class the row icon and the
filter depend on): core contract, service row mapper, parseGroupFile guard,
test fixture, UI types — one vocabulary end to end. parseGroupFile's roomId
becomes null-tolerant to match direct-upload rows (mapping input stays
strict).

Verified: core build clean, api typecheck 0 errors + group-files 22/22,
web typecheck 0 errors.
2026-10-11 11:08:08 +00:00
e7e703c105 Integrate group files: nullable room for uploads, archive class, claim idempotency, upload route
Wires the three parallel group-cloud tracks to one surface and fixes the
seams between them:

- chat_media_archive.room_id becomes nullable (direct web uploads have no
  Matrix room yet — the contract's null-event pattern extends to the room);
  core GroupFile.roomId and ArchiveEntryInput.roomId follow.
- mime_class gains 'archive' (zip) across the 029 CHECK, validation
  MIME_CLASSES and the bot classifier — one vocabulary everywhere.
- registerArchiveEntry claim keys are null-safe for room-less uploads.
- New: POST /files/groups/:groupId/upload — FileInterceptor (20 MiB) streams
  through magic-byte sniffing, library-safe naming, oCIS upload and the
  metadata index, behind group-membership ACL (Owner/Admin bypass).
- safeFileName/sniffMime promoted to packages/core (file-names.ts,
  file-mime.ts) so the bot and the api share one implementation; the bot's
  local modules become re-export shims; @types/node added to core.

Verified: api typecheck clean, group-files 22/22, bot 74/74, web typecheck
clean; 029 re-applied clean on a fresh scratch DB (room_id nullable,
archive class, claim_key unique all confirmed in the catalog).
2026-10-11 10:09:24 +00:00
aa5e262f3a 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/.
2026-10-10 11:56:42 +00:00