docs(website): where the module state machine lives, and how boot treats it #125

Merged
whitlocktech merged 1 commits from docs/module-state-machine into main 2026-08-10 19:02:50 +00:00
Member

The documentation half of Phase 2, PR 1 of the module system — code is RunicGateway/website#128.

§2.4 named the five states and stopped there. This records the two things the implementation had to settle, and one thing worth stating explicitly because it is easy to assume the opposite.

MODULE_SYSTEM.md §2.4 — three additions

Where the states live. One installed_modules row per module, with the machine in a single state column carrying all five values, rather than a policy flag beside a runtime one. Plus what else the row carries: the admin-screen metadata, the recorded failure stage and reason, and the install provenance (source/sha256, both null for a directory placed on the volume by hand, which stays supported).

The row is a record, never the source of truth for what is mounted. The loader scans the filesystem at require time, before the database is reachable (API §4.1). What the row decides is whether a mounted module answers, not whether it is there — which is also why routes.manifest.json can be generated against a dead database.

disabled is the only state a boot leaves alone. Every boot resets each non-disabled row to enabled, clearing any recorded failure, and the load that follows writes that boot's outcome. Three consequences, spelled out because each is a behaviour someone will otherwise be surprised by:

  • a startup_failed module is retried on every restart, so an operator who fixes the cause needs no admin-panel visit — at the cost of a deterministically broken module re-recording its failure each boot;
  • a running module can never show a stale reason;
  • disabling is an operator decision, not an outcome, so it survives restarts — and a re-install or upgrade leaves state alone in both directions.

BACKEND_DESIGN.md §3

installed_modules gains an entry alongside the other tables: the column list, the failure stages, and the two paragraphs above in short form.

Also

§2.7 gains a progress marker for Phase 2 — PR 1 done, 2–9 to go.


  • AI-assisted: written with Claude Code (Claude Opus 5)

🤖 Generated with Claude Code

The documentation half of Phase 2, PR 1 of the module system — code is RunicGateway/website#128. §2.4 named the five states and stopped there. This records the two things the implementation had to settle, and one thing worth stating explicitly because it is easy to assume the opposite. ## `MODULE_SYSTEM.md` §2.4 — three additions **Where the states live.** One `installed_modules` row per module, with the machine in a single `state` column carrying all five values, rather than a policy flag beside a runtime one. Plus what else the row carries: the admin-screen metadata, the recorded failure stage and reason, and the install provenance (`source`/`sha256`, both null for a directory placed on the volume by hand, which stays supported). **The row is a record, never the source of truth for what is mounted.** The loader scans the filesystem at require time, before the database is reachable (API §4.1). What the row decides is whether a mounted module *answers*, not whether it is there — which is also why `routes.manifest.json` can be generated against a dead database. **`disabled` is the only state a boot leaves alone.** Every boot resets each non-disabled row to `enabled`, clearing any recorded failure, and the load that follows writes that boot's outcome. Three consequences, spelled out because each is a behaviour someone will otherwise be surprised by: - a `startup_failed` module is **retried on every restart**, so an operator who fixes the cause needs no admin-panel visit — at the cost of a deterministically broken module re-recording its failure each boot; - a running module can never show a stale reason; - disabling is an operator *decision*, not an outcome, so it survives restarts — and a re-install or upgrade leaves `state` alone in both directions. ## `BACKEND_DESIGN.md` §3 `installed_modules` gains an entry alongside the other tables: the column list, the failure stages, and the two paragraphs above in short form. ## Also §2.7 gains a progress marker for Phase 2 — PR 1 done, 2–9 to go. --- - [x] AI-assisted: written with Claude Code (Claude Opus 5) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-08-10 11:37:01 +00:00
Phase 2 PR 1 of the module system records two things 2.4 left open: the
states are stored in one `state` column rather than a policy flag beside a
runtime one, and every boot recomputes the outcome states while leaving
`disabled` alone.

That second rule is the one with consequences worth writing down -- a
startup_failed module is retried on every restart, so an operator who fixes
the cause needs no admin-panel visit; a running module can never display a
stale failure reason; and disabling, the one operator decision rather than
outcome, survives restarts. Also states what the row does NOT decide: the
loader scans the filesystem before the database is reachable, so the URL
surface is a property of the volume, which is what keeps
routes.manifest.json generatable against a dead database.

BACKEND_DESIGN.md 3 gains the installed_modules columns alongside the other
tables.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit b5277d827c into main 2026-08-10 19:02:50 +00:00
whitlocktech deleted branch docs/module-state-machine 2026-08-10 19:02:51 +00:00
Sign in to join this conversation.
No description provided.