st-agent-worker/TODO.md
2026-09-24 21:02:53 -07:00

82 lines
3.6 KiB
Markdown

# TODO
Ordered roughly by importance. Items near the top either caused real
failures already or block going live.
## 1. Deletions never propagate — weekly full resync and prune
`_since` returns records ST considers *updated*. A deleted user is not
returned at all, so their row stays in `people` forever. This has already
caused two failed runs: once with a deleted rep chosen as `reps[0]` (45
identical 404s), once with a deleted member failing mid-run.
started := time.Now().Unix()
users, _ := client.ListUsers(ctx, 0) // full pull, ~176 requests
store.UpsertPeople(users, eligible)
store.PruneStale(started) // DELETE FROM people WHERE synced_at < ?
store.SetLastSync(started)
Guards:
- Only prune after a `since=0` pass. A delta pass refreshes a handful of
rows and would delete everything else.
- Refuse to prune if it would remove more than a few percent of the table.
A bug that silently empties the cache takes out every reconcile until
someone notices.
## 3. Small fixes, one commit
- **`failed` in the reconcile summary.** Run 10 logged
`0 assigned, 0 skipped` after 45 failures. A wholly failed run is
currently indistinguishable from an empty one.
- **Verify the agent before the loop.** One `GetUser(agent)` at the top
of `reconcile`; abort with a clear message rather than failing once per
member.
- **Prune a member's cache row on a 404 from `AssignAgent`.** Reactive
and self-healing: a stale row fails once instead of on every future run
of that department.
- **Live `IsRep` check in the handler.** Chapter and department come from
a live `GetUser`, but nothing checks whether the person is still a rep.
Someone whose flag was removed can still trigger a full reconcile.
## 4. Before going live
- **`VACUUM INTO` on a timer.** Volume snapshots of a live WAL database
are not safe to restore. The skip log is the only thing here that
cannot be regenerated.
## 5. Deferred design decisions
- **Nightly sweep.** Without it, a rep who steps down keeps their
assignments and their replacement inherits nobody. Members added after
their department's rep signed up also stay unassigned until something
triggers that department again. Rep replacement was described as
frequent, so this matters more than the member-churn case.
- **Schema migrations.** `CREATE TABLE IF NOT EXISTS` does not add
columns to an existing table. Changing the schema currently means
deleting the database and re-syncing, which will not be an option in
production.
- **License.** AGPLv3 if the goal is that other associations running a
modified copy must share changes; Apache-2.0 if the goal is that they
actually adopt it. Check first whether this is yours to license given
it is faculty association work.
## 6. Open questions for ST support
- Do a deleted or demoted rep's agent assignments stay active? This
decides whether departing reps permanently strand their members under
fill-only. Untested: the assignments observed as inactive were
deactivated by hand.
- `DELETE /agent_assignments/{id}` returns 404 on a row that
`GET /agent_assignments/{id}` returns fine. Either the path takes
something else or the handler is broken.
## 7. README corrections
- Work List rows are materialized by an ST job running on the half hour.
A new rep sees an empty list for up to 30 minutes after their
assignments are written. Confirmed: rows appeared exactly at :30. Worth
saying in whatever onboarding message reps get, or they will report it
as broken.
- Remove any claim that deleting a person deactivates their assignments.
That was done manually and the actual behaviour is unknown.