feat: model poisoning detection and BFT ensemble voting#1
Merged
Conversation
- Add Ed25519 artifact trust chain (ModelArtifact.verify_chain) - Add sign_metrics() for post-training artifact signing - Replace simple average with BFT trimmed-mean voting in RiskScorer - Add detect_label_poisoning() with training abort and alert report - Add annotation HMAC-SHA256 integrity (annotation_queue.py) - Add CI grep check: verify_chain must follow every joblib.load - Add docs/security.md with threat model and key rotation procedure - Update README Security section - Add tests: test_persistence, test_model_inference, test_model_training, test_annotation_queue (74 passing) Closes Ledger-Lenz#42
Anichris-koded
pushed a commit
that referenced
this pull request
Jun 20, 2026
- Added --dry-run argument to skip DB persist and on-chain submission - Updated README.md with the new flag - Added tests to cover the dry-run functionality
Anichris-koded
pushed a commit
that referenced
this pull request
Jun 20, 2026
feat: Add --dry-run flag to run_pipeline.py (#1)
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
Implements issue Ledger-Lenz#42 in full — hardens the LedgerLens inference stack against model poisoning, artifact substitution, and ensemble manipulation.
Changes
Artifact Integrity (Ed25519 trust chain)
ModelArtifact.verify_chain()— 4-step chain: SHA-256, Ed25519 signature, key fingerprint, training data SHA-256sign_metrics()— signsmetrics.jsonafter every training runRiskScorer._load_models()callsverify_chainimmediately after everyjoblib.loadBFT Ensemble Voting
bft_divergence_detected_total) when|max-min| > BFT_SCORE_DIVERGENCE_THRESHOLDconsensus_failureresponse (score=100, confidence=0) when <BFT_MIN_CONSENSUSmodels agreeTraining Data Provenance
sha256_dataframe()— deterministic SHA-256 of row-sorted input parquetdetect_label_poisoning()— aborts training and writesreports/poisoning_alert_{timestamp}.jsonwhen wash-trade ratio shifts > 15%Annotation Queue Integrity
wallet|label|annotator_id|annotated_atkeyed byANNOTATION_HMAC_SECRETexport_labelled()verifies every HMAC, logs WARNING and excludes tampered entriesCI + Docs
verify_chainfollows everyjoblib.loadindetection/docs/security.md— threat model, key generation, rotation procedureTesting
Definition of Done
verify_chainraisesModelIntegrityErrorfor all 4 failure typesdetect_label_poisoningreturns True when ratio shifts > 15%metrics.jsonMODEL_SIGNING_PRIVATE_KEY_PATHandANNOTATION_HMAC_SECRETdocumented in.env.exampleverify_chaincalled on every model load path + CI grep checkdocs/security.mdmerged alongside codeRiskScorer.scoreby defaultCloses Ledger-Lenz#42