Files
ten31-database/docs/handoffs/add-intake-bot-to-spark-control.md
T
Keysat b470ea2659 Containerize the Matrix intake bot as a managed service (restart: unless-stopped)
Turn the bot from a bare nohup process (silently dies on a Spark reboot) into a docker-compose service. Dockerfile bundles backend/matrix_intake + the stdlib backend/ingest Spark client it reuses; .env is mounted read-only at runtime, never baked. The existing repo-root .dockerignore (shared with the s9pk build) already keeps data/ and .env out of context. Also adds a handoff doc for wiring a spark-control dashboard card in a later session.
2026-06-17 20:10:16 -05:00

66 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Handoff: add the Matrix intake bot as a spark-control dashboard card
**Do this work in the `spark-control` repo (`~/Projects/spark-control`), in a separate session.**
This repo (ten31-database) only owns the bot + its container; the dashboard card is driven
entirely by spark-control code. Prereq (DONE 2026-06-17): the bot already runs as a docker
container named **`matrix-intake`** on the Spark (`spark-32d0`, user `modelo`), via
`docker-compose.yml` at this repo's root. spark-control reaches it over the **same SSH channel it
already uses for `matrix-bridge`** (`modelo@spark-32d0`) — no new key/host needed.
The card is a near-exact clone of the existing `matrix-bridge` card. Mirror that, with **three
deltas** (below). File paths/line numbers are from the 2026-06-17 review; reconfirm against the
current code.
## Deltas from matrix-bridge (do NOT copy these blindly)
1. **Branch is `main`, not `master`.** The Update button runs `git reset --hard origin/<branch>`
— it MUST be `main` for ten31-database, or Update silently resets to the wrong/empty ref.
2. **Project dir is `/home/modelo/ten31-database`** (the CRM monorepo clone), not `~/matrix-intake`.
3. **Coupling caveat:** because the bot lives in the CRM monorepo, the Update one-liner does
`git reset --hard origin/main` on the **whole CRM clone**. Safe today (`.env` is gitignored,
the clone has no needed local edits), but this is exactly the blast-radius smell that motivates
eventually extracting the bot to its own repo (logged in ten31-database `ROADMAP.md`). If that
extraction happens first, point dir/branch/remote at the new repo instead.
## Edits in spark-control (mirror the matrix-bridge wiring)
1. **`image/app/config.py`** (matrix-bridge entry ~lines 99111): add `matrix_intake_host`
(default `spark2_host`), `matrix_intake_user`, `matrix_intake_container` (default
`"matrix-intake"`), `matrix_intake_dir` (default `"/home/modelo/ten31-database"`),
`matrix_intake_branch` (default **`"main"`**), each with a `MATRIX_INTAKE_*` env fallback.
2. **`image/app/services.py`** (matrix-bridge ServiceDef ~lines 95102): add a
`"matrix-intake": ServiceDef(name="matrix-intake", kind="bot", host=…, user=…,
container=…, port=0)` entry. `port=0` → judged by docker state alone (no HTTP probe), same as
matrix-bridge.
3. **`image/app/matrix_intake.py`** (new): copy `matrix_bridge.py`, rename
`matrix_bridge``matrix_intake` throughout. The Update command (`build_update_command`) must
produce: `cd /home/modelo/ten31-database && git fetch origin && git reset --hard origin/main &&
docker compose up -d --build`.
4. **`image/app/server.py`**: (a) add `"matrix-intake"` to the `service_action` whitelist
(~line 621); (b) `from .matrix_intake import MatrixIntakeManager` + instantiate
`matrix_intake = MatrixIntakeManager(settings)` (~line 47); (c) add the 4 endpoints mirroring
matrix-bridge: `POST /api/matrix-intake/update`, `GET …/update/{job_id}`,
`GET …/update/{job_id}/stream`, `GET /api/matrix-intake/logs`.
5. **`image/app/static/app.js`** — THE RISKY EDIT. The Update/View-logs handlers are hardcoded to
matrix-bridge (`data-mb-update`, `onMatrixBridgeUpdate`, `/api/matrix-bridge/...`). Generalize
them to dispatch by the card's bot name (e.g. read `name` off the card, call
`/api/<name>/update` and `/api/<name>/logs`). Start/Stop/Restart are already generic. **Regression-check
that the existing matrix-bridge card still updates + tails logs after this change.**
6. **`package/startos/fileModels/sparkConfig.yaml.ts`** (~lines 2732): add
`matrix_intake_user: z.string().catch('')`.
7. **`package/startos/main.ts`** (~line 68): inject `MATRIX_INTAKE_USER: cfg.matrix_intake_user`.
8. **(optional) `package/startos/actions/configureSparks.ts`**: add the intake-bot SSH-user field
to the form.
## Deploy + ops
- spark-control is itself an s9pk: **bump its version, rebuild, reinstall** per spark-control's own
packaging docs (don't forget — same "0.4.x ignores same-version" rule).
- One-time: run **Configure Sparks** → set the intake bot's SSH user to `modelo` (same as
matrix-bridge → key already authorized). The card appears once the `matrix-intake` container
exists and the user is set; it hides itself if the container is absent or the user is blank.
- Status pill = `docker inspect matrix-intake .State.Status` (running→Healthy). No Matrix-liveness
check — a running-but-silent bot still shows Healthy (same limitation as matrix-bridge).
## Done when
The dashboard shows a `matrix-intake` card alongside `matrix-bridge` with a Healthy pill and
working Update / Start / Restart / Stop / View-logs buttons — and the matrix-bridge card is
unregressed.