Skip to content

Module protocol integration. #3

Description

@BeyondMagic

What to keep vs reset on update

  • Keep:
    • Module_Binding rows (user intent/config).
    • Module-owned data tables and rows (user content/data).
  • Update:
    • Persisted capability definitions (Module_Capability) to match new code.
    • Module SRI/commit metadata.
  • Don’t automatically drop:
    • Any tables/rows. Deletions should be explicit migrations, ideally opt-in and reversible.

Remove / Disable Module

  • Disable:
    • set Module.enabled=false; keep bindings but ignore them (or auto-disable all bindings for that module).
  • Uninstall (destructive):
    • remove module code checkout.
    • optionally delete module-owned DB objects via a module-provided “uninstall” migration; otherwise leave data intact.

If you want, I can propose the minimal DB additions to fully support this flow (a Module_Capability table + a small Module_Check/Module_Error table), keeping request-time overhead near-zero.


  • Save bun SQL (load environment variables, then clear them so they cannot be accessed by any module).

Add / Install Module (first time)

  1. Create Module row: insert into schema.dbml Module with repository, slug, set enabled=false, store intended branch (or default), commit empty/placeholder, last_checked=now.
  2. Fetch code: clone/pull (or validate local path), checkout branch, resolve commit, compute SRI hash of the module package, store commit, last_checked.
  3. Load module metadata safely: load the module entrypoint in an isolated runtime, catch errors; on failure keep enabled=false and persist an error status in logs (and ideally a future Module_Check table).
  4. Discover capabilities: call module “describe”/manifest export to get capabilities list + schemas + policy + adapter type.
  5. Persist capabilities (recommended): upsert a Module_Capability table (not yet in schema) keyed by (module_slug, capability_slug) with adapter, enabled, deprecated, version, policy, and action input/output schemas.
  6. Create default bindings: do not auto-bind to user routes. Optionally insert zero bindings; or create one disabled Module_Binding template row for UI convenience.
  7. Enable module: set Module.enabled=true only if steps 2–5 succeed.

Boot / Server Start

  1. Load enabled modules list: SELECT * FROM Module WHERE enabled=true.
  2. Warm capability registry: for each enabled module, either:
  • Fast path: load persisted capabilities from Module_Capability; or
  • Source of truth is code: re-discover capabilities from module code each boot (slower, but simplest).
  1. Load enabled bindings: SELECT * FROM Module_Binding WHERE enabled=true AND id_garden=?.
  2. Validate bindings against registry:
  • slug_module exists and module enabled
  • slug_capability exists and has adapter=HTTP when binding adapter is HTTP
  • if methods is set, validate values are known HTTP methods
  • detect binding conflicts (same specificity + same priority tie) and surface as config error
  1. Build dispatch index: pre-index bindings by id_garden and id_domain_target for fast ancestor matching.

Per-request (HTTP adapter dispatch)

  1. Resolve request to Domain chain (already your plan).
  2. Collect candidate bindings: those targeting root or any ancestor (and recursive rules).
  3. Filter by methods if present.
  4. Choose winner by specificity depth, then priority, else error.
  5. Dispatch to module capability handler, enforce policy.

When a user adds/edits bindings

  1. UI writes rows in Module_Binding (enabled/disabled, target, recursive, methods, priority, adapter, module/capability slugs).
  2. Server validates immediately (as above) and rejects invalid rows (or accepts but marks disabled with a “config error” flag—needs a column/table).
  3. Hot-reload binding index in memory (no module code reload required).

Update Module (pull new version)

  1. Freeze routing: keep serving with current in-memory registry while updating, or flip module to enabled=false temporarily (safer but disruptive).
  2. Fetch new code: pull, checkout new commit, compute new SRI.
  3. Re-discover capabilities in isolation; compare with previous capability set.
  4. DB migration step (module-owned):
  • module provides migrations (idempotent) and runs them via the constrained DB user.
  • module must not drop other modules’ objects.
  1. Persist new capabilities: upsert Module_Capability rows; mark removed capabilities as deprecated=true or enabled=false (don’t hard-delete unless you want strict behavior).
  2. Revalidate existing bindings:
  • Keep bindings rows as-is.
  • Any binding pointing to a missing/now-incompatible capability becomes disabled (or “broken”) until user fixes it.
  1. Swap live registry: atomically replace module runtime + capability registry; update Module.commit, last_checked.G

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

featNew feature for the user, not a new feature for build script.refactorRefactoring production code, eg. renaming a variable.researchFurther information is requested

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions