Security: oracle heartbeat gate + one-shot override audit (#398) - #466
Open
oyebolarotimi269-ai wants to merge 2 commits into
Open
Conversation
… override audit (TevaLabs#398) Enforce an always-on heartbeat health gate before any state mutation in both `resolve_round` and `resolve_round_multi`. This ensures a stale or offline oracle cannot bypass the admin override by racing the nonce consumption path. Changes: - Add `_enforce_heartbeat_health` that blocks settlement when: - No heartbeat has been recorded - Status is offline (2) The function is placed before nonce consumption to prevent race conditions. - Add `OracleHeartbeatUnhealthy` error variant (79) for clear rejection. - Add `_consume_hb_override` that atomically clears `override_armed` on next resolve, enforcing one-shot semantics. - Emit `hb_arm_ovr` event when admin arms the override, and `hb_override` event when it is consumed. - Rename stale `hoverride` event topic to `hb_override` for consistency. - Add `_enforce_heartbeat_health` call in `resolve_round_multi` for parity with the single-oracle `resolve_round` path. - Add public contract alias wrappers: `arm_oracle_heartbeat_override`, `is_oracle_heartbeat_override_armed`, `set_oracle_heartbeat_strict_mode`, `get_oracle_heartbeat_strict_mode`, `set_oracle_heartbeat_grace`, `get_oracle_heartbeat_grace`. - Fix duplicate import lines in test file. Security tests: - `test_heartbeat_offline_blocks_resolve` — offline heartbeat blocks settlement - `test_heartbeat_none_blocks_resolve` — missing heartbeat blocks settlement - `test_heartbeat_override_allows_resolve` — armed override recovers - `test_heartbeat_override_cleared_after_use` — override is one-shot - `test_heartbeat_override_emits_event` — consume emits `hb_override` - `test_arm_heartbeat_override_emits_event` — arm emits `hb_arm_ovr` - `test_heartbeat_stale_within_grace_strict_blocks_resolve` — strict mode - `test_heartbeat_degraded_fresh_strict_blocks_resolve` — strict mode - `test_heartbeat_grace_config` — grace period settable/queryable - `test_heartbeat_strict_mode_config` — strict mode settable/queryable Closes TevaLabs#398 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
oyebolarotimi269-ai
force-pushed
the
security/oracle-heartbeat-gate-one-shot-override-audit
branch
from
August 27, 2026 12:20
6ef6ee8 to
3f8f3f5
Compare
…ve_round The ? operator without a trailing ; caused a syntax error, preventing the entire crate from compiling and failing all CI jobs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an always-on heartbeat health gate for settlement that blocks resolution when the oracle heartbeat is unhealthy, and audits the admin override to enforce strict one-shot semantics with full event coverage.
Motivation
Heartbeat unhealthy blocks settlement; admin override is a high-privilege bypass. This PR audits the single-use semantics, emits events for arm + consume, and adds negative tests for the offline heartbeat blocking and override recovery paths.
Issue: Closes #398
What Changed
New: Always-on heartbeat health gate (
_enforce_heartbeat_health)A new function
_enforce_heartbeat_healthis placed before any state mutation (nonce consumption) in bothresolve_roundandresolve_round_multi. This ensures a stale or offline oracle cannot race the admin override path.It returns
OracleHeartbeatUnhealthywhen:Staleness and degraded status are enforced separately by the strict-mode check later in
resolve_round(which handles grace periods and override consumption).One-shot override semantics
If the admin override is armed, it is consumed atomically on the next resolve and settlement proceeds. The
override_armedflag is set tofalseby_consume_hb_override— one shot only.Events
(oracle, arm_ovr)(oracle, hb_arm_ovr)(oracle, hb_override)The stale
hoverridetopic was renamed tohb_overridefor consistency.Contract aliases
New public wrappers added for external integrators:
arm_oracle_heartbeat_overrideis_oracle_heartbeat_override_armedset_oracle_heartbeat_strict_mode/get_oracle_heartbeat_strict_modeset_oracle_heartbeat_grace/get_oracle_heartbeat_graceError variant
OracleHeartbeatUnhealthy = 79— clear rejection code for the always-on gate.Acceptance Criteria
_consume_hb_overrideclears flag atomicallyhb_arm_ovron arm,hb_overrideon consumetest_heartbeat_offline_blocks_resolve,test_heartbeat_none_blocks_resolvetest_heartbeat_override_allows_resolveFiles Changed
contracts/src/admin.rsarm_oracle_deviation_overrideandarm_hb_overrideeventscontracts/src/settlement.rs_enforce_heartbeat_health, call in both resolve paths, renamehoverride→hb_overridecontracts/src/errors.rsOracleHeartbeatUnhealthy = 79contracts/src/contract.rscontracts/src/tests/security.rsSecurity Tests Added
Design Note