CEPA: A Consensus-Governed Plugin Architecture Explained in 8 Concepts
The problem of fork spaghetti, elementary premises, facts, actions, instigations, and notifications — everything sustaining CEPA (Consensus-Driven Evolutionary Plugin Architecture), reduced to a vocabulary of 8 words. And how this turned into real code on the BEAM, inside JusrisOS.
The Problem We Are Solving
Companies selling software to multiple clients in the same market niche face a classic dilemma:
- Over-standardize -> the product fails to meet each client's specific variations.
- Over-customize -> every client becomes a divergent fork, leading to duplicated bugs, scattered logic, and expensive synchronization.
The result is uniquely customized fork spaghetti: fast point-in-time delivery at the cost of chronic codebase fragmentation.
CEPA solves this via a third path: an architecture delivering the speed of an exclusive fork at the edge alongside the stability of a single product at the center — organizing functionalities into orders of plugins and governing system evolution through consensus.
Elementary Premises
Before writing any code, we establish the core axioms of the model:
- An invariant nucleus (Kernel Core) and a disposable edge exist. The center does not change on a whim; the edge changes at will.
- Isolation is not human discipline — it is a build property. The compiler, not the team's good intentions, guarantees the edge never contaminates the center.
- Promotion is governed by consensus and data, not opinion. An edge variation ascends to the center only when it proves stability and reusability.
- The local device is the primary source of truth. The system operates offline; a master node reconciles conflicts later.
These four premises form the baseline contract for everything that follows.
The Model's Vocabulary (Minimal Ontology)
We reduce the entire architecture to 8 concepts. Using them, we can describe everything from plugin activation to data conflict resolution.
1. Attribute
Every observable state in the system. A plugin has order, maturity, and activation status; an aggregate has a version and timestamp; a node has online/offline status.
Attribute := (name, value, timestamp)
Example: (order, "2nd"), (maturity, 0.814), (sync_status, :offline)
2. Condition
A boolean predicate over attributes — free of side effects.
Condition := attributes -> {true, false}
Examples: Stability S(P) >= lambda * r^2 (promotion gate)
current_wip + reservations >= limit (WIP limit)
now >= sla_deadline_date (SLA breach)
3. Rule
The stable association "condition(s) => action(s)". This is where decision-making resides.
Rule := {conditions, actions}
Examples: {stable and reused by N clients} => {promote to 1st order}
{cross-boundary call} => {compilation error}
{conflict detected} => {apply resolution strategy}
4. Action
The triggered side effect: promote, activate/deactivate, dispatch event, synchronize, resolve.
Action in {promote, activate, dispatch, synchronize, resolve, notify}
5. Attribute Notification
"Attribute X changed to value V". This is the heartbeat keeping the system reactive.
Examples: Event "v1.crm:customer_registered"
{:mnesia_change, :cards_cache, record}
6. Condition Notification
"Condition C crossed the threshold" — representing the state transition rather than a static value evaluation.
Examples: "wip_limit_reached" (false -> true)
"node status" (offline -> online)
7. Rule Notification
"Rule R triggered" — an audit trail of an executed decision.
Examples: "plugin promoted to 1st order"
"conflict resolved via master_wins"
8. Notification Engine / Action Manager
The component that subscribes to notifications, evaluates conditions, triggers rules, and dispatches actions. In CEPA, this encompasses the entire microkernel runtime: AppManager, HookRegistry, SyncEngine, ConflictResolver, RulesSupervisor — along with the phased compiler acting as the build-time engine.
Facts
A fact represents current state: the complete set of attributes and their values.
In CEPA, the primary facts are:
- Order hierarchy — where each plugin resides: Kernel Core (r = 0), 1st order, 2nd order (edge), or 3rd order (experimental).
- Maturity — the index rho in [0, 1] for each plugin (test coverage, error rate, reuse metrics).
- Activation and consent state — active and consented plugins per tenant.
- Sync queue — the pending outbox state on each local node.
In JusrisOS, these facts live in ETS (AppManager), Mnesia (plugin_activation, plugin_consents, outbox), and local SQLite — avoiding expensive query reconstruction on hot paths.
Actions
Actions represent the operational verbs of the architecture:
| Action | JusrisOS Mechanism |
|---|---|
| Promote (2nd -> 1st order) |
git cherry-pick/PR from fork to core, after passing mix precommit
|
| Activate/deactivate plugin |
AppManager.install_with_dependencies/1 + deactivate_plugin/1
|
| Dispatch event |
Event.new/3 -> HookRegistry.dispatch/1
|
| Synchronize |
SyncEngine -> :rpc.call(master, :process_sync_event)
|
| Resolve conflict |
ConflictResolver (master_wins / LWW / branch_merge) |
| Enforce boundary |
mix compile --warnings-as-errors (compilation error) |
The golden rule: an action is always a side effect separated from state. A compiler blocking a boundary violation does not "fix" the code; a SyncEngine performing synchronization does not rewrite the local transaction.
Instigations
An instigation is an operational trigger that wakes up the engine. CEPA defines four primary classes:
-
Attribute change — a versioned domain event (
v1.crm:customer_registered) or cache write ({:mnesia_change, ...}). - Condition transition — a promotion gate crossing threshold S(P) >= lambda * r^2, or WIP hitting capacity.
-
Exact temporal trigger —
SlaTimerNodeschedulingProcess.send_after/3down to the millisecond;SyncEngineutilizing exponential backoff on reconnect. - Consensus decision — the Law of Consensus deliberating and instigating an upstream promotion.
Key principle: no engine polls the environment. All processes remain suspended until instigation occurs.
Notifications
CEPA differentiates three notification tiers, establishing structural auditability:
| Tier | Target Question | CEPA Implementation |
|---|---|---|
| Attribute | "What changed?" | Versioned event, cache update |
| Condition | "Which threshold was crossed?" | Promotion gate reached, SLA breach, WIP capacity hit |
| Rule | "Which decision was taken?" | Promotion approved, conflict resolved, plugin activated |
Delivery channels are split by operational context:
-
Personal notification (
JusrisOs.Notifications) — targeted directly tousers:{id}:notifications. -
Operational alert (
JusrisOs.Alerts) — system-wide visibility routed to/dashboard/alerts.
Distinguishing between "what changed", "which threshold was crossed", and "which decision was made" provides algorithmic due process: every automated decision preserves provenance and an execution trail.
Modeling the Architecture in Elixir/BEAM
These 8 concepts are not an external framework — they are native OTP primitives combined deterministically.
| Concept | JusrisOS Implementation |
|---|---|
| Fact | ETS (AppManager) + Mnesia + GenServer state |
| Rule | Rule nodes (WipRuleNode, SlaTimerNode) + ConflictResolver strategies + @callback behavior |
| Engine / Manager |
AppManager + RulesSupervisor (DynamicSupervisor) + SyncEngine + HookRegistry
|
| Attribute Notification |
Event/EventContract + MnesiaCache
|
| Rule Notification |
HookRegistry.dispatch/1 + Phoenix.PubSub
|
| Action |
AppManager.activate/deactivate, SyncEngine.flush, ConflictResolver
|
| Isolation |
Mix.Tasks.Compile.Phased + :boundary (enforced at build time) |
The end-to-end architecture lifecycle:
Edge (2nd order) — client customization without touching the core
│ Attribute Notification: versioned event / cache write
▼
Engine (AppManager + HookRegistry + SyncEngine + RulesSupervisor)
│ evaluates Conditions (stability, WIP, SLA, conflict)
▼
Rule triggers
│ Actions
├──► promote (upstream) — consensus governance
├──► dispatch event — decoupled communication
├──► synchronize / resolve — local-first → master reconciler node
└──► notify (personal / dashboard)
The phased compiler (Mix.Tasks.Compile.Phased) operates as the build-time engine: Phase 1 compiles the isolated Core (the edge does not yet exist), Phase 2 compiles plugins in parallel, and Phase 3 re-checks the Core with loaded plugins. Consequently, a 2nd-order plugin cannot leak function signatures into the Kernel — isolation is a mathematical build property, not an informal developer guideline.
Current System State
The model is implemented and running in JusrisOS:
-
Shared-nothing microkernel —
Support->Kernel->Pluginswith compile-time:boundaryenforcement. -
Phased compiler —
Mix.Tasks.Compile.Phased(isolated Core + parallel plugins + re-checking pass). -
Versioned event-driven core —
Event+EventContract+HookRegistry+Snapshot/Projection. -
Local-first — SQLite (
LocalRepo) + Mnesia + transactional outbox pattern. -
Master reconciler node —
SyncEngine+ domain-specificConflictResolver(master_wins,LWW,branch_merge, 3-way AST merge). - Rule Engine (NOP) — WIP and SLA tracked as stateful runtime processes on demand.
The 8-concept ontology provides a clean framework for formal evaluation:
-
Formalization — promotion decisions are expressed mathematically (S(P) >= lambda * r^2); runtime invariants can be modeled in LTL/CTL (
G(offline -> F flushed),AG(not corrupted_core)). - Governance as non-monotonic logic — the Law of Consensus functions as a revisionable default theory: plugins can be retracted from promotion queues as new operational facts emerge.
- Mechanized verification — the "phase isolation theorem" (the Core exhibits no compile-time dependencies on the edge) can be formally proved using assistant environments like Lean, Coq, or Isabelle.
- Geometric mapping — the Platform Hypersphere maps maturity (r), domain (theta), and tenant (phi) into spherical coordinates, expressing "distance to core" as a measurable metric.
Why It Matters
This 8-word vocabulary is a formal structural blueprint for extensible, long-lived software systems:
- Attribute / Condition / Rule / Action = the syntactic dimension (state representations and executable transitions).
- Attribute / Condition / Rule Notifications = the temporal dimension (event timing and state propagation).
- Notification Engine / Action Manager = the operational dimension (observation, orchestration, and execution).
CEPA functions as a notification engine at architectural scale: the edge emits attribute notifications, the engine evaluates conditions, rules execute actions, and consensus mechanisms govern which edge extensions ascend to the core.
When building multi-tenant systems without resorting to codebase forks, the design principle remains straightforward: define your 8 core concepts before implementing the first plugin. The rest follows from there.
Top comments (0)