docs(website): Phase 2 PR 9 — the modules mount, and Phase 2 complete

Records the last Phase 2 PR and closes the phase.

Amends §2.5: the mount is a bind mount of ./modules, not the named volume the
section reached for by analogy with uploads. Hand-placing a module directory is
a supported install in that same section, and a named volume routes it through
`docker cp` — the least discoverable mechanism Docker offers, for the one
install path an operator without the admin panel has.

Two things the build settled that the plan had not considered, both silent
failures rather than errors: the directory has to be tracked, because Docker
recreates a missing bind-mount source as root-owned and the container is uid
1000; and .dockerignore has to exclude it, because COPY . . would otherwise bake
a builder's checked-out module into every image — and Docker seeds a fresh named
volume from image contents, so it could have surfaced on a deployment that never
installed it.

MODULE_API §4.1 gains the concrete Compose values and states outright that a
missing modules directory is not an error, which the loader has always done and
the contract never said.

Website side: RunicGateway/website#136.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-11 00:50:17 -05:00
parent d66ee832c5
commit 8a7b099c2d
2 changed files with 63 additions and 5 deletions

View File

@@ -703,7 +703,13 @@ half needs rethinking before Phase 2 builds on it.
`app.js` scans `modules/*/module.json` with `fs.readdirSync` at require time and mounts what it
finds (`MODULE_SYSTEM.md` §1.12). The database is not consulted. `MODULES_DIR` defaults to
`<repo>/modules` and is overridable by env for tests and for the Docker volume mount.
`<repo>/modules` and is overridable by env for tests and for the Docker mount. Under Compose it is
set to `/app/modules`, where `./modules` is bind-mounted read-write (`MODULE_SYSTEM.md` §2.5); the
image itself carries that directory empty and owned by the container user, and `.dockerignore`
excludes any local one so a module can never be baked in.
**A missing modules directory is not an error.** The scan catches and returns, because "no modules
installed" is the normal state of bare core and the loader must not make the mount mandatory to boot.
**The trigger is one explicit call, and there is no lazy self-scan** (§7.6). `app.js` calls