ADR-015: Rate and blast-radius defaults¶
- Status: Accepted (mechanism); numeric defaults remain provisional pending disposable-lab evidence
- Date: 2026-08-08
- Accepted: 2026-08-08 — the atomic, store-backed containment
mechanism is implemented as
rate_policy.py(Phase 2) and accepted; the specific numeric defaults below remain explicitly provisional, unchanged by this status correction, pending Phase 4 lab evidence.
Context¶
Authorization (policy, confirmation) answers "is this mutation allowed";
it does not bound how much damage a single authorized-but-misbehaving
caller could cause by repeatedly exercising an approved capability. No
rate or concurrency containment exists in the codebase today beyond the
structural one-EXECUTING-per-target guarantee already provided by the
target reservation table.
Options considered¶
| Option | Strengths | Costs |
|---|---|---|
| No additional limits beyond target reservation | Simplest | A caller could still rapidly cycle prepare/execute across many different targets, or retry aggressively after every terminal outcome; insufficient containment |
| Atomic store-backed counters at per-target/per-capability/global scope, conservative starting defaults (recommended) | Reuses existing transactional pattern; defaults are explicitly provisional | Adds schema/complexity; wrong defaults could be either too strict (blocks legitimate use) or too loose (insufficient containment) until lab-validated |
| Externally-configured rate-limiting middleware/proxy | Decouples rate policy from the store | Would sit outside the atomic transaction boundary that gates state transitions, reintroducing exactly the check-then-act race this system otherwise avoids everywhere else; rejected |
Recommendation¶
Atomic, store-backed counters (per-target, per-capability, global) with
conservative starting defaults, explicitly marked provisional pending
disposable-lab evidence: global concurrent in-flight = 1, outstanding
PREPARED per target = 1, target cooldown = 60 seconds, reconciliation
lockout threshold = 3 simultaneous RECONCILIATION contracts. Full
specification:
rate_blast_radius_policy.md.
Self-challenge¶
"Is global concurrency of 1 too restrictive to be useful — won't this make the system feel broken if two unrelated, safe mutations can't run simultaneously?" — For the first capability, yes, this is intentionally restrictive, and that is the point: there is no throughput requirement yet that justifies the added concurrency-interaction risk, and every additional simultaneous in-flight mutation multiplies the state space a reviewer must reason about for crash/interleaving correctness. Loosening this is cheap later (a config change, once lab evidence and production experience justify it) — starting loose and tightening after an incident is the wrong order for a system whose entire purpose is avoiding uncontained mutation.
"Why pick 3 as the reconciliation lockout threshold instead of 1 (any reconciliation halts everything) or a higher number?" — 1 was considered and rejected as likely too sensitive for a first deployment — a single ambiguous network blip (e.g., one timeout) would halt the entire system, which creates pressure to work around the safety mechanism rather than respect it. A higher threshold (5+) was rejected as too tolerant of what should be a rare event for a well-behaved capability. 3 is a judgment call, explicitly not derived from data — hence "pending lab validation" in this ADR's status, not a final number.
Consequences¶
Positive¶
- Bounds damage even from a fully authorized, repeatedly-invoked caller.
- Provisional-by-design framing means the numbers can be tightened or loosened based on real lab evidence rather than being treated as load-bearing decisions made without data.
Negative¶
- Very restrictive defaults may require deliberate loosening before the system is useful for anything beyond single-operation testing — intentional friction, but real friction nonetheless.
- Adds a new schema table and two new checkpoints to review/test.
Future migration path¶
Numeric defaults should be revisited explicitly after
disposable_lab_execution_model.md's harness produces evidence (timing
of legitimate operations, frequency of ambiguous outcomes under realistic
fault injection) — this ADR's numbers are a lab starting point, not a
production commitment, and the roadmap should not treat them as settled
until that evidence exists.