S10 — Admission Gates
Rate limiting and quality gates applied before events enter the consensus protocol.
Rate limits (token bucket per epoch)
| Intent | Base rate | Rep bonus | Max | Cooldown |
|---|---|---|---|---|
| CreateCommitment | 5/epoch | +log2(rep) | 20 | — |
| AcceptCommitment | 3/epoch | +log2(rep) | 10 | — |
| OpenDispute | 3/epoch | — | — | 24h |
| FileAppeal | 1/dispute | — | — | — |
Epoch = 24 hours. No burst allowed for critical intents. Token bucket refills at epoch boundary.
Reputation check
Cached once per epoch per identity. Prevents race conditions where reputation changes mid-epoch affect admission decisions.
Stake
Required stake is frozen at admission and released at finalization. Lower reputation → higher stake requirement. Stake is slashed on proven fraud.
Quality gates
- Minimum description length for commitments
- Acceptance criteria must be explicitly defined
- Structured fields validated against schema
VRF audit
5% of all admitted events are selected for deeper verification via verifiable random function. Audit checks: full rule engine evaluation, cross-reference with related events, arbiter panel review. Audit probability range: 5-20% depending on event type and submitter reputation.
Implementation Status
Runtime: Implemented in Phoenix Python (projects/peer-to-peer/src/); not yet ported to Colibri Node.js
Verified against source: 2026-04-06
| Claim | Status | Notes |
|---|---|---|
| Token bucket per epoch | Implemented | aal.py TokenBucket class with rate_per_epoch, capacity, per-epoch refill. Buckets keyed by tenant:fork_id. |
| CreateCommitment 5/epoch base, +log2(rep), max 20 | Partial | Base=5 matches. Rep modifier uses log2(sqrt(rep)+1) (quadratic weighting added per spec-12), not plain log2(rep). Burst cap=10 in code vs max=20 in this spec. |
| AcceptCommitment 3/epoch, +log2(rep), max 10 | Partial | Base=3 matches. Burst=6 in code vs max=10 in this spec. Rep modifier includes sqrt weighting not mentioned here. |
| OpenDispute 3/epoch, 24h cooldown | Partial | Base=3 matches, critical=True (no burst). Cooldown field exists but set to 0 in code; the 24h cooldown is defined above (line 11) but not yet wired into intent_policies. |
| FileAppeal 1/dispute | Implemented | Base=1, burst=1, critical=True in code. Matches spec. |
| Epoch = 24 hours | Spec-only | Epoch semantics defined above (line 14) but epoch duration not hardcoded in aal.py; callers pass current_epoch as an integer. |
| No burst for critical intents | Implemented | capacity = base when policy["critical"] is True. Matches for OpenDispute, FileAppeal, CreateProposal. |
| Reputation cached once per epoch | Spec-only | No epoch-level reputation caching in aal.py. Reputation is passed per call. |
| Stake frozen at admission, slashed on fraud | Spec-only | No stake logic in AAL code. Stake operations are referenced in state_machine.py TransitionConsequences but not gated at admission. |
| Quality gates (min description, acceptance criteria, schema) | Spec-only | No payload validation in aal.py. Quality gates defined above (lines 26-29) but not implemented in AAL code. |
| VRF audit 5-20% selection | Partial | audit_rate_bp defaults to 2000 (20%). Selection is via force_audit flag from orchestrator rather than inline VRF. vrf.py implements ECVRF for arbiter selection, not for audit sampling. |
| Abuse detection (10x limit breach) | Implemented | abuse_counters triggers at base * 10 with -5% Reputation Penalty message. |
| Fork-scoped rate limits | Implemented | Buckets keyed by tenant_id:fork_id per S10 design for Sybil isolation. |
| Dev mode bypass | Implemented | dev_mode=True bypasses rate limits/cooldowns, logs simulated triggers. Not in this spec but present in code. |