docs(website): settle what core publishes about an installed module #131

Merged
whitlocktech merged 1 commits from docs/module-public-endpoint into main 2026-08-11 03:16:25 +00:00
Member

Phase 2, PR 6 of MODULE_SYSTEM.md §2.7 — the docs half of GET /api/v1/public/modules. Pairs with the website PR on branch feature/module-public-endpoint.

What changed

MODULE_API.md §2.9 — the normative shape. Four fields (id, name, version, capabilities) in the loader's scan order, and what is deliberately absent is the design:

  • Only started modules appear. A disabled or startup_failed module is absent, which is the same answer §4.4 already gives for its routes and its nav — a client renders a site without that capability rather than one advertising a capability that 503s.
  • No state, failure_stage or failure_reason. Where a module broke is admin-screen detail, and the reason is an exception string from inside core.
  • No client chunk URL. htmlShell injects the <script type="module"> per started module (§3.1.3), so the browser is handed the tag, not a URL to fetch.
  • An empty array is a real answer; the §7.6 guard is a 500, never [], because a caller cannot tell an empty list from a mis-ordered boot.

It also records why the endpoint owns the /modules prefix rather than sitting in the root-mounted site router — the loader's collision probe skips root-mounted layers, so a route declared there would be invisible to it.

MODULE_API.md §6.7 — an amendment. MODULE_SYSTEM.md §2.6 step 4 said the SPA reads this endpoint "to learn what to load". Step 3 of that same list had already answered loading a different way, and §3.1.3 is the normative version. The endpoint feature-detects; nothing waits on an API round trip to start loading. §2.6 step 4 now says so, and Part 6's intro no longer claims a fixed count of amendments.

MODULE_SYSTEM.md §2.7 — progress and an honest exit criterion. The phase criterion was "routes.manifest.json diff is zero lines"; PR 6 necessarily adds a URL. Restated: no existing URL moves, and PR 6 is the single deliberate addition in Phase 2 — every other PR still produces a zero-line diff. Status line updated: the design is in implementation, not unimplemented.

BACKEND_DESIGN.md — the route in the /public table, the router in the §2 folder map, and the published api-route-inventory.json mirror refreshed to 228 public routes (the prose count was stale at 226).

Decisions

All four settled with the org lead before implementation; all four the recommended option.

Decision Settled
Payload + states { modules: [...] }, started only, no state field
Where the route lives Its own /modules capability router
Client chunk URL Omitted — htmlShell injects the tag
Gating No siteMode, DB-free

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

🤖 Generated with Claude Code

https://claude.ai/code/session_018ocYxQWk3EhZe5gWRJXFU8

Phase 2, **PR 6** of `MODULE_SYSTEM.md` §2.7 — the docs half of `GET /api/v1/public/modules`. Pairs with the website PR on branch `feature/module-public-endpoint`. ## What changed **`MODULE_API.md` §2.9 — the normative shape.** Four fields (`id`, `name`, `version`, `capabilities`) in the loader's scan order, and what is deliberately absent is the design: - **Only `started` modules appear.** A `disabled` or `startup_failed` module is *absent*, which is the same answer §4.4 already gives for its routes and its nav — a client renders a site without that capability rather than one advertising a capability that 503s. - **No `state`, `failure_stage` or `failure_reason`.** Where a module broke is admin-screen detail, and the reason is an exception string from inside core. - **No `client` chunk URL.** `htmlShell` injects the `<script type="module">` per started module (§3.1.3), so the browser is handed the tag, not a URL to fetch. - **An empty array is a real answer**; the §7.6 guard is a **500**, never `[]`, because a caller cannot tell an empty list from a mis-ordered boot. It also records why the endpoint owns the `/modules` prefix rather than sitting in the root-mounted site router — the loader's collision probe skips root-mounted layers, so a route declared there would be invisible to it. **`MODULE_API.md` §6.7 — an amendment.** `MODULE_SYSTEM.md` §2.6 step 4 said the SPA reads this endpoint "to learn what to load". Step 3 of that same list had already answered loading a different way, and §3.1.3 is the normative version. The endpoint **feature-detects**; nothing waits on an API round trip to start loading. §2.6 step 4 now says so, and Part 6's intro no longer claims a fixed count of amendments. **`MODULE_SYSTEM.md` §2.7 — progress and an honest exit criterion.** The phase criterion was "`routes.manifest.json` diff is zero lines"; PR 6 necessarily *adds* a URL. Restated: **no existing URL moves**, and PR 6 is the single deliberate addition in Phase 2 — every other PR still produces a zero-line diff. Status line updated: the design is in implementation, not unimplemented. **`BACKEND_DESIGN.md`** — the route in the `/public` table, the router in the §2 folder map, and the published `api-route-inventory.json` mirror refreshed to **228** public routes (the prose count was stale at 226). ## Decisions All four settled with the org lead before implementation; all four the recommended option. | Decision | Settled | |---|---| | Payload + states | `{ modules: [...] }`, `started` only, no state field | | Where the route lives | Its own `/modules` capability router | | Client chunk URL | Omitted — `htmlShell` injects the tag | | Gating | No `siteMode`, DB-free | --- - [x] AI-assisted: written with Claude Code (Claude Opus 5) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018ocYxQWk3EhZe5gWRJXFU8
wtclaude added 1 commit 2026-08-11 03:04:25 +00:00
Phase 2, PR 6 of MODULE_SYSTEM.md 2.7 — GET /api/v1/public/modules.

MODULE_API.md gains 2.9, the normative shape: four fields (id, name, version,
capabilities) in scan order, and what is deliberately absent. Only started
modules appear, so a disabled or failed one is absent exactly as 4.4 already
leaves its routes and nav; no state, failure_stage or failure_reason reaches an
anonymous caller; no client chunk URL, because htmlShell hands the browser the
tag; an empty array is a real answer, but the 7.6 guard is a 500 and never [].
Also records why it owns the /modules prefix rather than sitting in the
root-mounted site router, where the loader's collision probe could not see it.

6.7 amends MODULE_SYSTEM 2.6 step 4, which said the SPA reads the endpoint "to
learn what to load" — step 3 of the same list had already answered loading a
different way, and 3.1.3 is the normative version. The endpoint feature-detects.
2.6 step 4 now says so, and Part 6's intro no longer claims a fixed count of
amendments.

MODULE_SYSTEM.md 2.7 records PR 6 and restates the phase exit criterion
honestly: no EXISTING URL moves, and PR 6 is the single deliberate addition in
Phase 2. Status line updated — the design is in implementation, not unimplemented.

BACKEND_DESIGN.md documents the route in the /public table and the router in the
folder map, and the published api-route-inventory.json mirror is refreshed to
228 public routes (the prose count was stale at 226).

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit fdede79909 into main 2026-08-11 03:16:25 +00:00
whitlocktech deleted branch docs/module-public-endpoint 2026-08-11 03:16:25 +00:00
Sign in to join this conversation.
No description provided.