feat(scheduler): periodic action-SHA verification (24h cadence)#400
Merged
Merged
Conversation
Wires `mix hypatia.verify_action_shas` (#399) into LearningScheduler so it runs as a daily auto-audit, not just when someone manually invokes it. Completes the auto-defense story alongside the static `:known_fake_action_sha` rule (#397) — fake-SHA hallucinations get caught either at scan time (rule) or at the next periodic audit (this). ## Cadence 24h via mtime check on the verifier's cache file (`data/verified-action-shas.json`). The mix task maintains the cache itself, so subsequent runs are seconds (only checks new pins) — cheap enough that running daily costs almost nothing. ## Isolation Spawned as a `System.cmd` subprocess from `Task.start`, NOT inline in the GenServer: - The mix task `exit({:shutdown, 2})` on fakes-found would crash the LearningScheduler if run in-process; subprocess isolates that. - `Task.start` (not `Task.async`) — fire-and-forget, no result waited on, the learning cycle doesn't block on a 5-minute gh-api walk. - Exception in the verification path is logged but never bubbles up. ## Logging - Clean (zero fakes): info-level confirmation - Fakes found (exit 2): warning with clipped output sample - Other exit codes: warning with stderr clip ## What's complete now Together with #397 (static rule) + #399 (mix task), this closes the auto- defense story: - New fake at scan time → static rule catches it instantly - New fake out-of-scan → daily LearningScheduler audit catches it within 24h - Cache makes the daily audit cheap (~5 sec warm) - No manual intervention required for ongoing protection Provenance: closes the "hypatia is a waste of time" concern raised during the 2026-05-30 snifs#30 / fake-SHA arc.
🔍 Hypatia Security ScanFindings: 103 issues detected
View findings[
{
"reason": "Action urin 21 JRE\n uses: actions/setup-java@be666c2fcd27 needs attention",
"type": "unpinned_action",
"file": "verify-proofs.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in ci.yml",
"type": "missing_timeout_minutes",
"file": "ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in clusterfuzzlite.yml",
"type": "missing_timeout_minutes",
"file": "clusterfuzzlite.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
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
Wires
mix hypatia.verify_action_shas(#399) intoLearningSchedulerso it runs as a daily auto-audit, not just on manual invocation. Completes the auto-defense story alongside:known_fake_action_shastatic rule (#397).How fake SHAs get caught now
:known_fake_action_sharule (#397)mix hypatia.verify_action_shas(#399)Design
Cadence
24h via mtime check on the verifier's cache file (
data/verified-action-shas.json). Subsequent runs are ~5 sec (only checks new pins) — cheap enough that daily costs nothing meaningful.Isolation
Spawned as
System.cmdsubprocess viaTask.start, NOT inline in the GenServer:exit({:shutdown, 2})on fakes-found would crashLearningSchedulerif run in-process. Subprocess isolates that.Task.start(notTask.async) — fire-and-forget; the learning cycle never waits on the gh-api walk.Logging
What's complete now
The auto-defense story is closed:
Provenance
Closes the "hypatia is a waste of time" concern raised during the 2026-05-30 snifs#30 / fake-SHA arc.
Test plan
action_sha_verify_stale?returns true)