You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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)
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.
Fetch code: clone/pull (or validate local path), checkout branch, resolve commit, compute SRI hash of the module package, store commit, last_checked.
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).
Discover capabilities: call module “describe”/manifest export to get capabilities list + schemas + policy + adapter type.
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.
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.
Enable module: set Module.enabled=true only if steps 2–5 succeed.
Boot / Server Start
Load enabled modules list: SELECT * FROM Module WHERE enabled=true.
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).
Load enabled bindings: SELECT * FROM Module_Binding WHERE enabled=true AND id_garden=?.
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
Build dispatch index: pre-index bindings by id_garden and id_domain_target for fast ancestor matching.
Per-request (HTTP adapter dispatch)
Resolve request to Domain chain (already your plan).
Collect candidate bindings: those targeting root or any ancestor (and recursive rules).
Filter by methods if present.
Choose winner by specificity depth, then priority, else error.
Dispatch to module capability handler, enforce policy.
Server validates immediately (as above) and rejects invalid rows (or accepts but marks disabled with a “config error” flag—needs a column/table).
Hot-reload binding index in memory (no module code reload required).
Update Module (pull new version)
Freeze routing: keep serving with current in-memory registry while updating, or flip module to enabled=false temporarily (safer but disruptive).
Fetch new code: pull, checkout new commit, compute new SRI.
Re-discover capabilities in isolation; compare with previous capability set.
DB migration step (module-owned):
module provides migrations (idempotent) and runs them via the constrained DB user.
module must not drop other modules’ objects.
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).
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.
What to keep vs reset on update
Module_Bindingrows (user intent/config).Module_Capability) to match new code.Remove / Disable Module
Module.enabled=false; keep bindings but ignore them (or auto-disable all bindings for that module).If you want, I can propose the minimal DB additions to fully support this flow (a
Module_Capabilitytable + a smallModule_Check/Module_Errortable), keeping request-time overhead near-zero.Add / Install Module (first time)
Modulewithrepository,slug, setenabled=false, store intendedbranch(or default),commitempty/placeholder,last_checked=now.branch, resolvecommit, compute SRI hash of the module package, storecommit,last_checked.enabled=falseand persist an error status in logs (and ideally a futureModule_Checktable).Module_Capabilitytable (not yet in schema) keyed by(module_slug, capability_slug)withadapter,enabled,deprecated,version,policy, and actioninput/outputschemas.Module_Bindingtemplate row for UI convenience.Module.enabled=trueonly if steps 2–5 succeed.Boot / Server Start
SELECT * FROM Module WHERE enabled=true.Module_Capability; orSELECT * FROM Module_Binding WHERE enabled=true AND id_garden=?.slug_moduleexists and module enabledslug_capabilityexists and hasadapter=HTTPwhen binding adapter is HTTPmethodsis set, validate values are known HTTP methodsid_gardenandid_domain_targetfor fast ancestor matching.Per-request (HTTP adapter dispatch)
Domainchain (already your plan).recursiverules).methodsif present.priority, else error.When a user adds/edits bindings
Module_Binding(enabled/disabled, target, recursive, methods, priority, adapter, module/capability slugs).Update Module (pull new version)
enabled=falsetemporarily (safer but disruptive).Module_Capabilityrows; mark removed capabilities asdeprecated=trueorenabled=false(don’t hard-delete unless you want strict behavior).Module.commit,last_checked.G