docs: extract best-effort oneshot service contract + matrix-avatar (#718 batch 6)

Two new sections housing rationale that was inline in
`harness-base.nix`:

- `docs/conventions.md::Best-effort oneshot services` — shape
  contract shared by `tea-login`, `forge-avatar-sync`, and
  `matrix-avatar-sync`: always exit 0, no `set -e`, skip silently
  on missing prerequisites, wired to multi-user.target,
  re-runnable. Plus the artefact-under-agent-home + service-stays-
  root posture and the operator-visible-via-journalctl trade-off.

- `docs/persistence.md::matrix-avatar-sync` — the two-step `media
  upload` → `set avatar_url` matrix-spec dance + why
  `RemainAfterExit = false` (so the `.path` watcher's re-fire on
  token appearance actually re-executes the unit).

In-code comments trim to one-liner purpose + pointers; the script
bodies stay (they're the actual implementation) but their inline
`#` rationale comments collapse where the docs cover them.

`description = ''…''` blocks (operator-facing options docs)
preserved per iris #718.

`nix flake check` clean; `nix fmt` clean.
This commit is contained in:
atlas 2026-05-31 15:50:25 +02:00 committed by mara
commit a043c61828
3 changed files with 94 additions and 56 deletions

View file

@ -259,3 +259,25 @@ restart. The `.path` unit makes the appearance of the token re-fire
the service so the daemon comes alive in the same boot cycle as
provisioning. `matrix-avatar-sync.path` uses the same pattern for
the icon-upload oneshot.
### matrix-avatar-sync (two-step media + profile dance)
Mirrors the forge-avatar oneshot's shape (`docs/conventions.md::
Best-effort oneshot services`) but differs in protocol: matrix
avatars are a two-step `POST /media/r0/upload` → `PUT
/profile/<user_id>/avatar_url` dance, both authenticated by the
`access_token` written by `hive-c0re::matrix::ensure_user_for` to
`<state>/matrix-token`.
Triggered by EITHER boot (`wantedBy = multi-user.target`) OR the
sibling `matrix-avatar-sync.path` firing on token appearance. Both
paths re-run the oneshot idempotently — running the avatar set
twice is harmless.
Critically: **`RemainAfterExit = false`** (not the more common
`true` for oneshots). systemd treats `RemainAfterExit = true`
oneshots as "still running" after the first exit, so the second
trigger from the `.path` watcher becomes a no-op. Setting it to
`false` lets re-fires actually re-execute. The trade-off is the
service unit shows `inactive (dead)` between fires — visible in
`journalctl` but harmless; the `.path` unit drives the lifecycle.