Commit graph

104 commits

Author SHA1 Message Date
dae302bd18 brand: process-not-platform manifesto on the landing
Hero strip (ES/EN): 'Not a platform. A process.' / 'Decide together.
Publish anywhere. Forget nothing.' / 'What they delete, we archive. What
they silence, we broadcast.' Footer line: 'Not a product. A process.
Built by collectives, for collectives.'
2026-10-13 16:44:59 +00:00
a3cf150494 brand: unclip sidebar wordmark, styled dark 404, human files error, Element brand text
From the brand review: the sidebar truncated 'Tactical Media Broadcast Hub'
on eleven desktop routes; unknown routes rendered a stock white Next.js 404;
solo users saw the raw 'groupid must be a UUID' validation text on Files;
Element's config brand string still read 'OccupyMedia Hub'.
2026-10-13 16:25:48 +00:00
11f75e945e revert: matrix-sso to the JWT broker flow; tuwunel migrated to [global] profile
tuwunel's login/get_token demands device-bound UIA completed with
org.matrix.login.jwt — the AS-impersonation shortcut cannot mint login
tokens. The [global] profile migration activates [global.jwt] (register_user
+ JWT UIA), so the original flow works: JWT login (auto-registers
@hub_<user>) -> get_token with JWT UIA -> logout broker device.
2026-10-13 16:13:51 +00:00
af93176bbe ops: tuwunel loads appservice registrations via TUWUNEL_APPSERVICE_DIR
Inline [appservice.*] tables drop the namespaces field (registration then
fails M_EXCLUSIVE for every AS user). The env var points tuwunel at the
/appservices mount (telegram + hub YAMLs, both with namespaces).
2026-10-13 16:05:48 +00:00
189cb41a09 ops: pin shared Temporal publishing queue; pass MATRIX_SSO_AS_TOKEN/HS_TOKEN to api
W1's governance sim found approved publishes never executing: the api starts
workflows on tmbh-publishing while the 3-day-old scheduler image consumed the
old superposter-publishing default. Pin TEMPORAL_TASK_QUEUE on both services.
2026-10-13 15:35:49 +00:00
4a0d398a76 fix: Matrix SSO via dedicated hub appservice (AS register + get_token impersonation)
The live tuwunel does not offer m.login.jwt (the jwt.* flat config keys were
inert), so the JWT broker flow could never work. Pivot: appservice.hub owns
the exclusive hub_* namespace on the homeserver; POST /matrix/session now
registers @hub_<username> with the as_token and mints a single-use
m.login.token via login/get_token (?user_id= impersonation). Optional
MATRIX_SSO_HS_TOKEN authenticates inbound appservice transactions, acked by
the new MatrixAppserviceController sink. Response shape unchanged.
2026-10-13 15:29:16 +00:00
fe5f2403d6 feat: in-app Chat (Matrix JWT SSO) + Drive (embedded oCIS)
- api: matrix-sso module (tuwunel jwt -> login/get_token), POST /matrix/session, GET /matrix/identity, drive controller
- web: /chat full-height Element view, /files Library+Drive tabs, embedded-app frame component
- edge: /hub-sso.html handshake route (origin-pinned CSP), X-Frame-Options strip on files
- oCIS: csp.yaml frame-ancestors app.occupymedia.cc
- server config still required: tuwunel [global.jwt], MATRIX_SSO_JWT_SECRET, oCIS restart
2026-10-13 14:57:07 +00:00
a2aa70c961 edge: social.occupymedia.cc vhost — Mastodon web :3030 + streaming :4040 (CT-host LAN bind, websocket upgrade, 80m uploads) 2026-10-13 14:34:06 +00:00
8cc1c3b634 Login: drop AuthProvider dependency so /login exports statically 2026-10-13 13:18:23 +00:00
22f9e12141 Login: bare sign-in page at /login; Telegram bridge connection guide 2026-10-13 09:49:57 +00:00
d313ce0bec Onboarding: wide hero banner (mark left, system name right) on black 2026-10-13 08:23:52 +00:00
27fd68c8df Landing: Enter -> login door, /login deep-link (signin mode), /signup register; onboarding scroll fix 2026-10-13 08:13:33 +00:00
f98fca45d0 oCIS upload: drain to buffer + explicit content-length (reva rejects chunked PUTs) 2026-10-13 05:47:19 +00:00
c918fb984e group-files test: expect the hub-groups root MKCOL before the per-group folder 2026-10-13 05:37:15 +00:00
dec505b83e oCIS: create the hub-groups root before the per-group folder (409 on missing parent) 2026-10-13 05:34:10 +00:00
cbbe713dea 032: accept bare room IDs (tuwunel 1.9.4 mints and serves them without :server) 2026-10-12 23:10:59 +00:00
fd09967851 Provisioner: retry onboarding posts (fresh-room forward-extremities race), degrade non-fatally 2026-10-12 22:57:00 +00:00
27a7b72984 Provisioner: normalize bare room IDs to full !id:server form (tuwunel returns localpart) 2026-10-12 22:47:48 +00:00
e3a6e9da97 Share with collective: fix union narrowing in open-room result handling 2026-10-12 22:35:32 +00:00
df54cb9b9e Provisioner: never list the room creator in power-level users (spec rejects it) 2026-10-12 21:46:55 +00:00
6ea605c87e Edge: hub-branded oCIS theme + assets for files.occupymedia.cc, both ingress paths; brand assets mount 2026-10-12 18:22:05 +00:00
b984d6842f Files: mobile upload button, no-collective empty state; nav chat/approvals icons 2026-10-12 18:02:56 +00:00
3f61d11072 /signup: stable account-creation door (redirects to register-mode onboarding) 2026-10-12 16:32:05 +00:00
2a3a1d79a1 P1 flow fix: register makes a solo user by default, collective creation is an opt-in flag, post-login menu for collective-less accounts 2026-10-12 16:19:08 +00:00
2665f43cc4 Sidebar: full icon set (new chat + approvals marks), Files/Chat elevated, settings wheel 2026-10-12 16:12:10 +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
07d2df8c53 Docs: cloud hosting requirements + migration runbook (measured sizing) 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
ac969f05c9 Chat client hosted at chat.occupymedia.cc: Element + API on one host, hub welcome page 2026-10-12 13:16:45 +00:00
39dcf7a8b8 Edge: chat root redirects to branded client, serve matrix well-known; onboarding hero full-bleed on black 2026-10-12 12:55:05 +00:00
699b9412c1 Phase B: encrypted archive export bundles (age), power-level-gated export command, encryption-state linter 2026-10-12 12:46:56 +00:00
a7ad1f059f Design: open room default-on with opt-out at collective creation 2026-10-12 11:26:33 +00:00
92f318de7c Design: account tiers, contribution policy disclosure, Telegram open-room access 2026-10-12 10:28:43 +00:00
2ee5c55de1 Design: collectives architecture (participation landing, room matrix, subcollectives, diffusion) 2026-10-12 09:42:16 +00:00
e6a78a0805 Hub nav: Chat tab (branded self-hosted Element at element.occupymedia.cc) 2026-10-12 09:13:37 +00:00
7ea0b1e137 Phase two: archive origin facet, redaction-aware reads, share revocation on redaction
- group-files: origin filter facet; GET /files/:id returns 410 for unavailable
  rows after the ACL recheck; fix latent group_members.status filter and unbound
  workspace parameter that would 500 listFiles
- archive-bot: markRedacted revokes live group_file_shares rows in-transaction
- new live-DB integration suite for the archive index surface
2026-10-11 21:44:23 +00:00
7cea73dc0d Edge: tailscale0 relay exemption, CT320 transit hop, files/office/intake host parity 2026-10-11 21:36:20 +00:00
83e34aa343 Switch chat CT to tuwunel 1.9.4 with R2 media provider 2026-10-11 21:09:51 +00:00
b1b2a07b3d Pass FILES_OCID_* WebDAV credentials into the api container 2026-10-11 16:25:48 +00:00
2cb77ae6b4 Harden archive bot for production; exempt container egress in edge firewall
- archive_sync_state keyed by room per migration 029 (drop synthetic id cursor)
- putStaging buffers the stream and sends content-length (oCIS rejects chunked)
- mimeClass passthrough from sniffed payload
- edge-firewall: RETURN docker-bridge ingress before the CF-range catch-all so
  container egress (Matrix/R2/platform) survives the 80/443 source filter
- files scaffold: keep the ocdav data-gateway hop on-loopback
2026-10-11 16:12:43 +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
688a2ce996 Enable basic-auth WebDAV on the oCIS proxy (machine access for api/bot)
The group-files api and the archive bot authenticate to oCIS WebDAV with
basic credentials (admin until a dedicated service user exists). The proxy
is LAN-published only; no WAN forward exists.
2026-10-11 08:49:27 +00:00
777c67f7a3 Expand video-AI architecture doc to the full research report
281-line version with the person-identity DDL sketch, per-model license
audit table, VRAM/cost budget, GDPR Art. 9 analysis, and all primary-source
citations — replaces the 53-line executive summary.
2026-10-11 08:29:30 +00:00
d58db63fe6 Add group cloud: files index api, web UI, archive sync bot
The Telegram-like group file contract (packages/core shared-files.ts) becomes
a working subsystem, built in three parallel tracks:

API (NestJS): migration 029 group_files (chat_media_archive metadata-only
index with partial replay-unique + RLS, group_file_shares with sha256 token
persistence, archive_sync_state/outbox durable-claim seam incl. a unique
claim_key index), group-files module (list/search with cursor pagination,
direct upload ≤20 MiB streamed+hashed to oCIS WebDAV, download with ACL +
retention rechecks, share links with expiry, retention modes incl.
legalHold) — RBAC group-membership authz + audit chain events.

Web: Files section per group — group picker, drag-drop upload (20 MiB cap),
search + MIME/origin filters, cursor pagination, download via authenticated
blob fetch, share dialog with expiry + shown-once token, admin retention
dialog; bilingual EN/ES (wiki i18n pattern); nav sidebar/palette/bottom-nav
wiring; MIME classes aligned to the DB CHECK (document/other).

Archive bot (apps/archive-bot): plain sync-loop Matrix bot mirroring
attachments from explicitly-mapped unencrypted archive rooms — raw /sync
with durable since-cursor, outbox-claimed ingestion (hash-verified stream,
no temp files), magic-byte MIME sniffing, safe-name normalization, WebDAV
upload, indexed + replied with link, redaction→unavailable; health endpoint;
Dockerfile. Tests 74/74, typecheck clean across api/web/bot.
2026-10-11 08:21:11 +00:00
eb1b60f67d Add video-AI architecture research (transcription, diarization, faces, GDPR)
Research: use PeerTube
native transcription (core since 6.2, whisper-ctranslate2, remote runners on
GPU nodes; large-v3-turbo MIT via model_path); pyannote community-1
diarization (CC-BY-4.0, clean); WhisperX fusion.

Face recognition license audit: NO accurate open FR model has clean weights
(InsightFace/SCRFD non-commercial, yolo-face GPL, AdaFace unstated) —
posture is detection+tracking+blur by default; identity matching opt-in,
human-review-gated, collective decision + DPIA required (Art. 9 biometric
data; automated FR over non-consenting third parties effectively unlawful).

DB DDL sketch: persons/person_face_embeddings/video_face_detections/
transcript_segments/video_speaker_person/identity_audit with review gating,
visibility tiers, erasure workflow.
2026-10-11 07:55:01 +00:00
6cdffa60b2 Track the files scaffold; sync deployed oCIS compose requirements
infra/occupymedia/files/ was gitignored in phase one ('nothing deployed');
the oCIS deployment is now live, and the storage doc + DEPLOY.md link to its
runbook. Track the secret-free scaffold (compose.yml, csp.yaml, README,
tuwunel example, .env.example); keep only .env + secrets/ ignored.

compose.yml carries the deployment-proven fixes: ocis runs as user 1000 with
OCIS_CONFIG_DIR=/etc/ocis and HOME=/var/lib/ocis (source-built images do not
inherit the official image's conventions), and 9200/9980 publish on the LAN
for the CT150 tunnel connector.
2026-10-11 07:51:59 +00:00
fc5f94400f Add content-search architecture research (group cloud indexing)
Research: Tika full-text
via 3 oCIS env vars (phase 1); bge-m3 on TEI + pgvector halfvec/HNSW in the
existing Postgres with Postgres FTS + RRF hybrid (phase 2); Docling tier for
scanned PDFs; NATS event subscription (UploadReady et al) + nightly PROPFIND
reconciliation for change propagation. jina-v3 excluded (non-commercial).
Bilingual EN+ES eval set flagged as mandatory before freezing models.
2026-10-11 06:25:19 +00:00