7.0 KiB
7.0 KiB
oko — Matrix storage backend + dev homeserver (session log)
Date: 2026-09-05 Author: opencode session (big-pickle)
Objective
Replace the oko coordinator's backend storage (previously MySQL + local filesystem)
with Matrix: every clip is stored in a Matrix room as an m.video event, with its
metadata posted as an m.text reply directly beneath the video event. A real
development homeserver (Conduit) was provisioned on the FreeBSD VPS magbot.online
so the system is usable end-to-end.
Final routing rules (agreed behavior)
| criteria | outcome |
|---|---|
| no motion | not stored (dropped before decode/encode) |
| motion, no detections | clips room only (+ view room, caption only) |
| motion + detections | clips room and detections room (+ view room, caption only) |
Every motion clip is also posted to a third view room (-view-room): the
same uploaded mxc:// media as an m.video event whose body is a one-line
human caption (<source> · <n> frames · <fps> fps · motion <n>%) and no JSON
metadata reply, so a human can browse clips without scrolling through JSON.
Livestreaming is explicitly out of scope.
Coordinator rewrite (Matrix backend)
coordinator/matrix.go(new)matrixStoretype wrappingmautrix.Client(maunium.net/go/mautrix v0.29.0).newMatrixStore:Whoamiself-check to fail fast on bad token; both room IDs must start with!(validated at startup).postClip: uploads a single encode (UploadBytesWithName) to get onemxc://URL, then sends them.videoevent and a metadatam.textreply withm.in_reply_topointing at the video event. Both rooms reference the same MXC.routeTargets: the routing truth table (no motion -> nil; motion -> clips room; motion+detections -> clips room + detections room).hasDetections: true when any frame has non-empty detections.clipJSON/buildClipMetadata: metadata body shape (see schema below).
coordinator/main.go- New flags:
-listen,-passphrase,-matrix-homeserver,-matrix-user,-matrix-token-file(orOKO_MATRIX_TOKENenv),-clips-room,-detections-room,-view-room(third room, minimal caption only).- Removed
-storage,-db-*,-keepalive-url-era MySQL/filesystem writes. - Token is read from a file or env — never from argv (audit #10).
- No-motion clips dropped before decode/encode; retained
computeFPS, temp-file MP4 encode, TCP ingest, passphrase decrypt.
- Removed
- Metadata
m.textbody (pretty-printed JSON), shown in the live rooms:source_data,width,height,channels,gocv_image_type,frame_count,fps,timestamps,guids,detections(per-frame map: title/version/…), plusmotion_percent.
terp change
terp/main.go: removed the "no classifier detections -> drop" branch; all motion clips are now forwarded to the coordinator (required so motion-without-DaemonSet clips reach Matrix).terp/terp_test.go: updated four tests for the new forwarding behavior.- Note:
terp/terpcommitted binary was rebuilt to match source (tracked, modified).
Tests
coordinator/matrix_test.go(new):TestRouteTargets,TestHasDetections,TestBuildClipMetadata.coordinator/coordinator_test.go: rewritten; keepscomputeFPStests; removed replaced filesystem/MySQL tests.- All pass:
go build,go vet,go test ./...incoordinatorandterp.
Config / repo wiring
config.yaml: coord1 node now points at the real homeserver/rooms.run-stack.sh: env-overridable defaultsOKO_MATRIX_HS,OKO_MATRIX_USER,OKO_MATRIX_TOKEN_FILE,OKO_CLIPS_ROOM,OKO_DETECTIONS_ROOM..gitignore: addedmatrix.token,*.token,logs/,storage/.matrix.credentials.example: redacted template (real creds live on the VPS and in a local 0600 file — see below).
Dev Matrix homeserver (Conduit) on magbot.online
- FreeBSD 14.2 VPS, 1 CPU / ~1 GB RAM / ~70 GB free; SSH as
nolan(no passwordless sudo, root SSH denied) -> everything installed user-space. nolan's shell is fish: run remote logic via script files:sh /path/script.sh.- Conduit 0.10.13 + rocksdb/gflags/snappy extracted to
/home/nolan/matrixroot; binary needsLD_LIBRARY_PATH=/home/nolan/matrixroot/usr/local/lib. - Config:
/home/nolan/conduit/conduit.toml(server_name magbot.online, port 8008, rocksdb, max_request_size 100MB, registration now DISABLED, federation off). - Runtime/DB/log:
/home/nolan/conduit/{data,conduit.log}. - Start script:
/home/nolan/start-conduit.sh(sets LD_LIBRARY_PATH + CONDUIT_CONFIG, nohup).@rebootautostart installed innolancrontab. - Accounts: bot
@okobot:magbot.online(used by coordinator), viewer@nolan:magbot.online(joined both rooms). Bot access token -> repomatrix.token(0600, gitignored). - Rooms: clips
!mSnSuG3WTmoTfN6lvNHjFsbwFoMeEXlk4xFRmbg824k(#oko-clips:magbot.online), detections!bAkHwtJ5FhfXpEsUFesllGshMejkgKwSQeAPJ8muOq0(#oko-detections:magbot.online). Both private, nolan invited+joined. - Real credentials stored (0600): VPS
/home/nolan/oko-matrix-credentials.txtand local/tmp/opencode/oko-matrix-credentials.txt. - Reachable over plain HTTP on :8008; no TLS yet (later: nginx reverse proxy on magbot.online, which already runs nginx).
End-to-end verification (live)
curlclient API + register (token-based) worked before registration was locked; unprivileged register now returnsM_FORBIDDEN.- mautrix path health-checked against the live server with a throwaway client
(
/tmp/opencode/matrixtest): Whoami, media upload ->mxc://,m.videoevent, metadata reply withm.in_reply_toall OK; viewer sync/timeline fetch confirmed. - Ran the real
coordinatorbinary against the live homeserver with synthetic gob clips (/tmp/opencode/clipsender):- motion only -> clip stored in clips room only.
- motion + person detection -> stored in clips room AND detections room.
- Viewer
@nolanretrieved both events + metadata replies.
Operational notes / TODOs
- Smoke/test clips remain in both rooms (Conduit client API returns
M_UNRECOGNIZEDfor redaction) — clean up via an admin tool when convenient. - Conduit has no TLS; enable nginx reverse proxy (or tailscale) before deploying to real cameras. Federation currently off.
terp/terptracked binary was back in sync with source (rebuilt; modified).- Local
config.yamlplaceholders were replaced with live values; the livestream side-channel (livestream-cache module + runCam livestream glue) and its config schema were removed entirely;config.example.yamlnow documents the clip pipeline schema. - No live
OKO_TEST_MATRIX-gated e2e test was added to the Go test suite; the live path was validated manually as described above. - Coordinator not currently running as a service on the dev box — start via
./run-stack.sh(or manually) when cameras are attached.