← All docs

Reliability Matrix - what happens when the enforcement plane fails

Mergen sits in front of your agents' commands and edits, so what it does when it breaks is part of what it promises. This page lists every way the gate can fail and what happens in each case. It is generated from the same table mergen doctor --security shows, so it says what the product does, and every row names the test that proves it.

Live in-product

GET /coverage/reliability (JSON, or &format=html) and mergen doctor --security surface the LIVE posture of this machine: the availability mode, policy integrity, pending default rules, every active gate-weakening setting with its warning, and this matrix. Read-only. An operator can see the posture rather than assume it.

overallPosture is deliberately three-valued. A stock install reports advisory, not hardened: several defaults (fail-open availability on a machine no organization manages, the passthrough free cap, the advise shell gate) run and log but do not block. Only an install where every axis actually blocks or reverts reports hardened.

The governing invariant

A failure of the plane may preserve or strengthen enforcement, but must never silently weaken it.

Stated precisely, because the stronger phrasing this doc used to carry ("no failure yields execution by breaking") is no longer true by default and has not been since 2026-09-19:

  • On the daemon seam, unconditionally: verdictForFailure has no branch that returns PASS. A failure can only BLOCK or HOLD.
  • On the client seam (gate-check): a gate that times out, or answers with an error other than 502/503/504, blocks in every mode, and an organization-managed machine always fails closed. On any other machine MERGEN_GATE_AVAILABILITY_MODE=fail-closed blocks too. The default is fail-open: on a machine no organization manages, when nothing is answering (connection refused or dropped, or a 502/503/504), the tool call proceeds unevaluated.

A genuine BLOCK verdict is never an availability question - it is enforced in either mode. The availability setting governs only the "we could not decide" case.

The executable spine is reliability-conformance.test.ts, which asserts this across both seams and pins the default so a silent regression is caught.

The matrix

Failure Behavior Invariant Proven by
Gate/daemon unreachable organization-managed machine -> BLOCK, whatever is set locally. Otherwise fail-open (default) -> ALLOW unevaluated; fail-closed -> BLOCK Enforcement authority is local. Availability is a configured choice, not a silent one, and an organization's machines never fail open reliability-conformance.test.ts, gate-exit-codes.test.ts, org-managed-fail-closed.test.ts
Hook timeout (gate running, no answer in time) BLOCK in every mode: a running gate that has not answered may be holding the call for a person (Cursor failClosed also denies on timeout) A timeout is not an absent gate gate-exit-codes.test.ts, cursor-option-b.test.ts
Gate answers with an error (401, 413, 429, 500) BLOCK in every mode, naming the way out An error status is not an absent gate gate-error-status-fail-open.test.ts
Connection dropped, or 502/503/504 from a router whose worker is gone treated as unreachable: organization-managed -> BLOCK; otherwise fail-open (default) -> ALLOW; fail-closed -> BLOCK Only "nothing is answering" takes the availability path reliability-conformance.test.ts, gate-error-status-fail-open.test.ts
Unparseable hook payload organization-managed -> BLOCK; otherwise fail-open (default) -> ALLOW; fail-closed -> BLOCK. A payload that cannot be read is a no-decision outcome, so it follows the availability mode rather than being independently blocked Never guess a verdict - an unreadable payload is never given one reliability-conformance.test.ts, gate-check-cli-harness.test.ts
Deliberate stop, then run organization-managed -> BLOCK. Otherwise fail-open (default): ALLOWs unevaluated (bypass reopened 2026-09-19); fail-closed: BLOCK An agent that can stop the runtime can bypass the gate under fail-open on an unmanaged machine. Set fail-closed where that is unacceptable reliability-conformance.test.ts, org-managed-fail-closed.test.ts
Parser (L1) crash / hang HOLD; reproducible poison-pill -> BLOCK; never PASS B-FAILMODE monotonic - no failure condition returns PASS gated-fail-mode.test.ts, gated-l1-client.test.ts, reliability-conformance.test.ts
Daemon L0 / IPC failure BLOCK; never fall back to TCP/user-level B-VERDICT-AUTH - an unverifiable peer or socket is a boundary breach gated-fail-mode.test.ts, gated-ipc-e2e.test.ts
Bad / corrupt / tampered policy last-known-good snapshot, never DEFAULT-weaken; else BLOCK. A stripped/downgraded hard-safety rule is restored on load unless the policy is signed with an ENV-ONLY key (an on-disk-key signature is tamper evidence, not admin authorization) Integrity failure never yields a weaker policy gated-l0-core.test.ts, policy-integrity-blunder.test.ts, immutable-rule-reinjection.test.ts
Policy predates a shipped hard-safety rule the rule is delivered on load at every authority - a signature cannot carry intent about a rule that did not exist when it was signed. Editable seed rules are offered, not auto-applied (mergen policy sync-seeds) The hard-safety floor is the same on an upgraded install as on a fresh one policy-seed-delivery.test.ts, immutable-rule-reinjection.test.ts
Network / cloud outage no effect - verdict is local & synchronous Enforcement authority is always local; cloud is telemetry only architectural-invariants.test.ts
Approval (HITL) backend outage HOLD stays held; restart denies, never auto-approves A delivery failure never auto-approves hitl-hold-restart-deny.test.ts, hitl-delivery.test.ts
Audit store tampered detected only when HMAC signing key is configured (hash-chained ledger); otherwise casual-tamper evidence only Tamper-evident, not silently mutable audit-integrity.test.ts, audit-integrity-surface.test.ts, action-ledger-prune-integrity.test.ts
Free-tier cap hit passthrough (default): past 1,000 protected actions a month on Free, enforcement pauses. Nothing is evaluated, hard-safety BLOCKs included, until the month resets or the plan is upgraded. protect: every action is still evaluated and enforced. Paid plans have no cap The one place billing disables safety, by product decision, and it is stated rather than implied free-cap-passthrough.test.ts, plan-agnostic-security.test.ts

The two-command bypass, stated plainly

Under the default fail-open, on a machine no organization manages, an agent with shell access can run:

mergen-server stop && <anything>

and the second command executes unevaluated. This is a deliberate product decision (2026-09-19) favouring availability on a developer's own machine over blocking when the runtime is down - a background daemon being unreachable should not brick every Bash call. It is named here rather than buried because a security control's known bypass belongs in its own documentation.

The fix is one setting:

MERGEN_GATE_AVAILABILITY_MODE=fail-closed

Recommended for shared machines, CI, and any deployment where the agent is less trusted than the developer running it. The stronger posture also removes the incentive to induce a gate failure: when breaking the gate stops work rather than unlocking it, there is nothing to gain by breaking it.

Recovery (two-tier, sanctioned + audited)

  • User-tier - resolve holds (approve/deny/cancel), inspect (doctor, status), and restart the user-level server. Recovery commands are an exact-match allowlist that short-circuits the gate, so a wedged gate never strands its own recovery (recovery-commands.test.ts).
  • Privileged-tier - restarting or repairing the root daemon needs elevation (sudo systemctl restart mergen-gated / mergen interception repair), documented and audited. A same-uid process cannot revive it; that is the point.

Evidence layer - which policy, version, identity and context decided

Every durable DecisionRecord carries the policy version (sha256 of the active policy content) plus rule/controlId, the runtimeId that reached the verdict, the identity (actor, agentId), the context (workspaceId, surface), and the requested vs effective verdict with projectionReason (the cross-surface projection trail). Provenance is stamped at each store's write choke point, not threaded per call (activity-provenance.test.ts).

Honest residual

  • fail-open is the default on a machine no organization manages, and it is a real allow path. See the bypass section above. fail-closed is one environment variable away and is the recommended posture for shared, CI, and lower-trust deployments.
  • Audit head-sealing is off unless MERGEN_AUDIT_SECRET is set. The hash chain detects a targeted row edit either way; without an env-supplied key, an adversary who rewrites the whole table can produce a fresh, internally consistent chain.
  • Policy authority defaults to tamper-evident, not authoritative. Without MERGEN_POLICY_SIGNING_SECRET, the policy is signed with the on-disk ~/.mergen/secret, which the governed agent can read - so the signature proves the file was not corrupted, not that an administrator authorized it.
  • Windows is the least-verified tier. Ownership/ACL checks fail closed there by design; the privileged paths are verified on POSIX (see the per-OS live-verification runbooks).
  • Live end-to-end for the privileged daemon and managed interception is a rooted-host runbook lane, not CI. The unit conformance here proves the logic; the runbooks prove the wiring.

Last updated October 31, 2026