agentjob.ioHandbook
Architecture Decision Records

ADR-0005: Modules as packages bound by one contract and unlocked by entitlements

Every module, first-party or third-party, exports a ModuleManifest; the registry is the single source of what loads, tables live only in packages/database, and entitlements gate access.

ADR-0005: Modules as packages bound by one contract and unlocked by entitlements

  • Date: 2026-09-18
  • Status: Proposed (seed — awaiting the owner's approval)
  • Deciders: the owner, Claude (seed)
  • Tags: domain strategy

Context

To prevent fragmentation there must be exactly one way to add a feature, and the Marketplace itself must be a natural extension of the internal modules.

Decision

Every module (first-party or third-party) exports a ModuleManifest (packages/core/src/module-contract.ts) that declares: identity, requirements, entitlements, routes, settings schema, and events. The job, webhook, Copilot-tool, sector-hook and marketplace fields were removed in ADR-0010, which narrowed the contract to what a loaded module actually uses.

  • modules/registry (@repo/module-registry) is the single source of what gets loaded.
  • Tables are defined in packages/database only; no module owns a private schema.
  • An entitlement unlocks a module; both the plan and an add-on are sources of entitlements.

Consequences

  • Positive — adding a module means adding a package without touching the core; the Marketplace works by the same mechanism.
  • Negative — the strictness may feel excessive for a small team at the start.
  • Revenue impact (SAR / month, confidence) — R4 (Marketplace) is only possible with this contract (≈ 18,000 at 1,000 merchants, low confidence).

Rejected alternatives

  • Features built directly into the core: reintroduces fragmentation and blocks the Marketplace.
  • Plugins in a different language or runtime: premature security complexity.

References

On this page