1010 schedule :
1111 - cron : ' 0 0 * * 0' # Weekly on Sunday
1212 workflow_dispatch :
13-
14- permissions : read-all
13+ # Estate guardrail: cancel superseded runs so re-pushes don't pile up
14+ # queued runs across the estate. Safe here because this workflow only
15+ # performs read-only checks/lint/test/scan with no publish or mutation.
16+ concurrency :
17+ group : ${{ github.workflow }}-${{ github.ref }}
18+ cancel-in-progress : true
19+
20+ permissions :
21+ contents : read
22+ # security-events: read lets the built-in GITHUB_TOKEN query this
23+ # repo's own Dependabot alerts via the Hypatia DependabotAlerts rule
24+ # (DA001-DA004). Without this, `scan_from_path` gets HTTP 403 and
25+ # the rule silently returns no findings.
26+ # See 007-lang/audits/audit-dependabot-automation-gap-2026-04-17.md.
27+ security-events : read
28+ # pull-requests: write lets the advisory "Comment on PR with findings"
29+ # step post its summary. Without it the built-in GITHUB_TOKEN gets
30+ # "Resource not accessible by integration" and (absent continue-on-error)
31+ # hard-fails the scan — exactly what the gate-decoupling design forbids.
32+ pull-requests : write
1533
1634jobs :
1735 scan :
1836 name : Hypatia Neurosymbolic Analysis
1937 runs-on : ubuntu-latest
20- env :
21- # ${{ env.HOME }} is empty in working-directory context (HOME is not in
22- # env unless explicitly set), which makes the directory resolve to "/hypatia"
23- # and the build step fails with "No such file or directory". A job-level env
24- # var is visible to both shell ($HYPATIA_DIR) and Actions expressions
25- # (${{ env.HYPATIA_DIR }}).
26- HYPATIA_DIR : /home/runner/hypatia
2738
2839 steps :
2940 - name : Checkout repository
30- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
41+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3142 with :
3243 fetch-depth : 0 # Full history for better pattern analysis
3344
@@ -39,33 +50,32 @@ jobs:
3950
4051 - name : Clone Hypatia
4152 run : |
42- if [ ! -d "$HYPATIA_DIR " ]; then
43- git clone https://github.com/hyperpolymath/hypatia.git "$HYPATIA_DIR "
53+ if [ ! -d "$HOME/hypatia " ]; then
54+ git clone https://github.com/hyperpolymath/hypatia.git "$HOME/hypatia "
4455 fi
4556
4657 - name : Build Hypatia scanner (if needed)
47- working-directory : ${{ env.HYPATIA_DIR }}
4858 run : |
49- if [ ! -f hypatia-v2 ]; then
50- echo "Building hypatia-v2 scanner..."
59+ cd "$HOME/hypatia"
60+ if [ ! -f hypatia ]; then
61+ echo "Building hypatia scanner..."
5162 mix deps.get
5263 mix escript.build
53- mv hypatia hypatia-v2
5464 fi
5565
5666 - name : Run Hypatia scan
5767 id : scan
58- continue-on-error : true # scanner exits 1 on infra errors; critical findings block via the separate Check step
5968 env :
60- # Hypatia uses Dependabot alerts as one of its signal sources.
61- # Without GITHUB_TOKEN it warns and exits 1. The default GITHUB_TOKEN
62- # has the security_events:read scope needed to query alerts.
69+ # Pass the built-in Actions token through to Hypatia so the
70+ # DependabotAlerts rule can query this repo's own alerts.
71+ # For cross-repo scanning (fleet-coordinator scan-supervised),
72+ # a PAT with `security_events` scope is required instead.
6373 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
6474 run : |
6575 echo "Scanning repository: ${{ github.repository }}"
6676
67- # Run scanner
68- HYPATIA_FORMAT=json "$HYPATIA_DIR /hypatia-cli.sh" scan . > hypatia-findings.json
77+ # Run scanner (exits non-zero when findings exist — suppress to continue)
78+ HYPATIA_FORMAT=json "$HOME /hypatia/hypatia -cli.sh" scan . --exit-zero > hypatia-findings.json || true
6979
7080 # Count findings
7181 FINDING_COUNT=$(jq '. | length' hypatia-findings.json 2>/dev/null || echo 0)
@@ -206,7 +216,12 @@ jobs:
206216
207217 - name : Comment on PR with findings
208218 if : github.event_name == 'pull_request' && steps.scan.outputs.findings_count > 0
209- uses : actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v7
219+ # Advisory only — posting findings as a PR comment must never gate
220+ # the scan (hypatia#213 gate decoupling). Belt-and-braces alongside
221+ # the pull-requests: write permission above: a token/API hiccup or
222+ # a fork PR (read-only token) skips the comment, not the check.
223+ continue-on-error : true
224+ uses : actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7
210225 with :
211226 script : |
212227 const fs = require('fs');
@@ -236,4 +251,4 @@ jobs:
236251 repo: context.repo.repo,
237252 issue_number: context.issue.number,
238253 body: comment
239- });
254+ });
0 commit comments