How modules work
Two lists must both say yes: the code exists, and the platform was granted it.
Updated
On this page
The registry and the grant
The backend owns a module registry — the single source of truth for what a platform can be granted. Each platform carries a plaintext modules allowlist (it holds no secrets — it is a list of module names we defined), edited from the Super Dashboard. Unknown keys are dropped on save rather than stored, so a value that isn't a real module can never later be misread as a grant.
Some modules declare dependencies (forms depends on records; invoices and websites depend on customers) — a capability that rides another isn't granted in isolation.
Enforcement, twice
- The API gate. Every platform endpoint names its module; a request from a platform without the grant is refused regardless of what the front end shows.
- The front end.
whoamireports the enabled list, and a well-built platform front end derives everything from it: nav links appear only for granted modules, and the matching routes 404 when typed directly. "This platform doesn't have invoices" and "this page doesn't exist" should be indistinguishable from outside.
const { platform } = await dash.whoami();
platform.modules // ["records", "customers", "projects", "websites", …]
The two-list rule
A platform front end ships a registry of modules it knows how to render; the platform's grant decides which of those actually appear. Being in the front-end registry means "this app can draw it", not "this platform has it" — both lists must say yes. That is what lets one front-end codebase serve platforms with very different grants, with no build flags and no forks.