feat: module system — registry, middleware, and discovery endpoint #102

Merged
forbes merged 7 commits from feat-module-system into main 2026-02-14 20:05:43 +00:00
Owner

Implements the backend foundation for the module system (docs/MODULES.md).

Migration (#94):

  • settings_overrides table for admin UI config persistence
  • module_state table for per-module enabled/disabled state

Module registry (#96):

  • 10 modules: 3 required (core, schemas, storage), 7 optional
  • Dependency validation: dag→jobs→auth, odoo→auth
  • 14 unit tests covering default state, toggling, dependency chains

Config loader (#95):

  • Three-tier precedence: YAML defaults → DB overrides → env vars
  • Backward compat: auth.enabled and odoo.enabled still work
  • New modules: YAML section for explicit toggles

Server wiring:

  • Registry created and loaded at startup, passed to Server
  • Job/runner sweeper goroutines only started when jobs module enabled
  • Module states logged at startup

RequireModule middleware (#98):

  • Returns 404 with {"error":"module '<id>' is not enabled"}
  • Wraps: projects, audit, odoo, jobs, job-definitions, runners, runner API, dag
  • DAG routes extracted into dedicated sub-route with module gate

Public discovery endpoint (#97):

  • GET /api/modules — no auth required
  • Returns all modules with enabled state, metadata, dependencies
  • Includes public config for auth (provider flags, OIDC issuer) and freecad (URI scheme)
  • Server version and read-only mode

Closes #94, Closes #95, Closes #96, Closes #97, Closes #98

Implements the backend foundation for the module system (docs/MODULES.md). **Migration (#94):** - `settings_overrides` table for admin UI config persistence - `module_state` table for per-module enabled/disabled state **Module registry (#96):** - 10 modules: 3 required (core, schemas, storage), 7 optional - Dependency validation: dag→jobs→auth, odoo→auth - 14 unit tests covering default state, toggling, dependency chains **Config loader (#95):** - Three-tier precedence: YAML defaults → DB overrides → env vars - Backward compat: `auth.enabled` and `odoo.enabled` still work - New `modules:` YAML section for explicit toggles **Server wiring:** - Registry created and loaded at startup, passed to Server - Job/runner sweeper goroutines only started when jobs module enabled - Module states logged at startup **RequireModule middleware (#98):** - Returns 404 with `{"error":"module '<id>' is not enabled"}` - Wraps: projects, audit, odoo, jobs, job-definitions, runners, runner API, dag - DAG routes extracted into dedicated sub-route with module gate **Public discovery endpoint (#97):** - `GET /api/modules` — no auth required - Returns all modules with enabled state, metadata, dependencies - Includes public config for auth (provider flags, OIDC issuer) and freecad (URI scheme) - Server version and read-only mode Closes #94, Closes #95, Closes #96, Closes #97, Closes #98
forbes added 7 commits 2026-02-14 20:03:27 +00:00
Add migration 016 with two tables for the module system:
- settings_overrides: dotted-path config overrides set via admin UI
- module_state: per-module enabled/disabled state

Update testutil.TruncateAll to include new tables.

Ref #94
In-memory registry for 10 modules (3 required, 7 optional).
SetEnabled validates dependency chains: cannot enable a module
whose dependencies are disabled, cannot disable a module that
others depend on.

9 unit tests covering default state, toggling, dependency
validation, and error cases.

Ref #96
Add ModulesConfig and ModuleToggle types to config.go for explicit
module enable/disable in YAML.

Add LoadState() that merges state from three sources:
1. Backward-compat YAML fields (auth.enabled, odoo.enabled)
2. Explicit modules.* YAML toggles (override compat)
3. Database module_state table (highest precedence)

Validates dependency chain after loading. 5 loader tests.

Ref #95
Add modules.Registry and config.Config fields to Server struct.
Create registry in main.go, load state from YAML+DB, log all
module states at startup.

Conditionally start job/runner sweeper goroutines only when the
jobs module is enabled.

Update all 5 test files to pass registry to NewServer.

Ref #95, #96
Add RequireModule middleware that returns 404 with
{"error":"module '<id>' is not enabled"} when a module is disabled.

Wrap route groups:
- projects → RequireModule("projects")
- audit → RequireModule("audit")
- integrations/odoo → RequireModule("odoo")
- jobs, job-definitions, runners → RequireModule("jobs")
- /api/runner (runner-facing) → RequireModule("jobs")
- dag → RequireModule("dag") (extracted into sub-route)

Ref #98
Add HandleGetModules returning module state, metadata, and
public config (auth providers, Create URI scheme). No auth
required — clients call this pre-login.

Register at /api/modules before the auth middleware.

Ref #97
forbes merged commit e20252a993 into main 2026-02-14 20:05:43 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/silo#102