CI recovery: gitleaks binary, docker build fixes, missing script guards#123
CI recovery: gitleaks binary, docker build fixes, missing script guards#123cryptoxdog wants to merge 7 commits into
Conversation
Runs the l9-pr-remediation loop against the open PRs (#114, #122) and records the convergence result (blocked — settings-gated) plus a per-job root-cause classification verified against live CI logs. Corrections to the prior handoff: - gitleaks "pin to v2" is invalid: gitleaks.yml is already v2.3.6 and still requires an org license; only a license secret or the binary CLI resolves it. - PR #114's red checks are stale (pre-#121); the SALESFORCE env-contract and audit findings are already fixed on main — it needs a rebase, not a code fix. - Documents six referenced-but-nonexistent local_pr_pipeline/* scripts (the Docs Consistency exit-127 defect), held for an explicit reconstruct decision. No application code changed; no pushes to the PR branches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb
Repo-wide CI gate defects found while running the pr-remediation loop on the
open PRs. None were "registry creds" or SDK-token settings — they are code bugs:
Build & Push Image (docker-build.yml, Dockerfile):
- metadata-action emitted an invalid tag ":-ff0fbce" because
`type=sha,prefix={{branch}}-` resolves {{branch}} to empty on pull_request
events. Use a static `prefix=sha-`.
- The image build runs `pip install ".[dev]"`, which clones the private
constellation-node-sdk (git+https), but the image had no `git` and no token.
Add `git` and pass SDK_TOKEN as a BuildKit secret with a token git-rewrite
that is removed in the same RUN layer (never persisted into the image).
PR Pipeline (pr-pipeline.yml):
- Four steps invoked local_pr_pipeline scripts that do not exist in the repo
(check_compliance_terminology.py, run_pr_select_gates.py,
docs_consistency_local.sh, docs_link_check_local.py), hard-failing the Docs
Consistency and select-gates phases (exit 127). Existence-guard each,
matching the repo's existing advisory pattern; they auto-activate if the
scripts are later added.
Also refreshes Eie_CI_RECOVERY_HANDOFF.md with the corrected root causes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb
gitleaks-action v2/v3 require a GITLEAKS_LICENSE for organization accounts (Quantum-L9), regardless of repo visibility — confirmed against the action's own README. Rather than depend on the license, run the standalone gitleaks binary (pinned v8.21.2) via `gitleaks git . --exit-code 1`. Secret scanning stays a hard blocking gate (SOC 2 CC6.1), is free, needs no secret, and still uploads SARIF to the Security tab. Removes the GITLEAKS_LICENSE dependency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb
PR Size Report
✅ PR size is within recommended limits |
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
…tirely Gate_SDK is now a public repository, so the private-repo credential dance is no longer needed — pip can clone it anonymously. - requirements-ci.txt, pyproject.toml: repoint constellation-node-sdk from the old cryptoxdog org to Quantum-L9/Gate_SDK. - l9-constitution-gate.yml, l9-contract-control.yml: remove the "SDK_TOKEN is required" hard-exit guards and the cryptoxdog-scoped git insteadOf rewrites from all three SDK-installing steps; install anonymously. - Dockerfile: drop the BuildKit sdk_token secret mount + git rewrite; plain anonymous pip install (git still installed for the git+https dependency). - docker-build.yml: remove the now-unused sdk_token build secret. Net effect: the ~10 SDK-dependent gates no longer 403/prompt for credentials, and no org secret is required. The SDK_TOKEN org secret can be deleted. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb
… tag
With the SDK unblocked, the previously-masked gate checks now run and surfaced
two mechanical, pre-existing failures:
- ruff format: app/agents/deal_risk.py, app/score/score_models.py were not
formatted (Lint gate).
- OpenSSF Scorecard: `ossf/scorecard-action@v2` no longer resolves ("unable to
find version v2"); pin to the valid release tag v2.4.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb
| persist-credentials: false | ||
| - name: Run OpenSSF Scorecard | ||
| uses: ossf/scorecard-action@v2 | ||
| uses: ossf/scorecard-action@v2.4.0 |
There was a problem hiding this comment.
Deferred — This is a repo-wide hygiene issue, not one localized to this PR: grep -rE "uses:.*@v[0-9]" .github/workflows/ shows 100 unpinned actions across 18 workflow files. Fixing 2 flagged lines while 98 others remain unpinned would not resolve the underlying Scorecard "score is 0" — that requires a systematic pass (e.g. pin-github-action or stepsecurity-io/secure-workflows) in a dedicated hardening PR. This PR is scoped to CI recovery (gitleaks binary, docker build, missing-script guards) and the ossf/scorecard-action@v2 → @v2.4.0 bump was already a small in-scope hardening step (semver → concrete version). Full SHA pinning is tracked as follow-up.
| - name: Upload SARIF to GitHub Security | ||
| if: always() | ||
| continue-on-error: true | ||
| uses: github/codeql-action/upload-sarif@v4 |
There was a problem hiding this comment.
Deferred — Same rationale as the sibling comment on ci.yml:259. Repo has 100 unpinned actions across 18 workflows; a targeted pin-by-SHA belongs in a dedicated supply-chain hardening PR (systematic tool-driven pass), not a two-line patch that leaves the other 98 unpinned. This PR is scoped to CI recovery (gitleaks action → binary, docker fixes, script guards). The github/codeql-action/upload-sarif@v4 reference was pre-existing on main, not introduced by this PR.
L9 Audit ReviewStatus
Policy
Blocking Findings
Advisory Findings
... truncated 1165 additional findings ... Generated by L9 Audit Engine ( |
…act-bound files The whitespace reformatting on app/agents/deal_risk.py and app/score/score_models.py was outside this PR's stated scope (CI recovery: gitleaks binary, docker fixes, missing script guards) and triggered the Contract-Bound Change Gate because both files are on the bound list. Restoring the main version of these files removes the gate trigger without losing any semantic change (the diff was pure line reflow around the flatcase-ok comment). Signed-off-by: pplx-l9-remediation-bot <pplx-l9-remediation-bot@users.noreply.github.com>
PR Remediation — Cycle 1 (L4 agent)Head SHA (post-cycle): Commit pushed this cycle
Findings classification
Cross-PR interaction with #122 (important for operator)This PR removes Verified via GitHub API:
Local validation (Gate D artifact)CI Gate D not runnable end-to-end locally (pytest coverage gate depends on installing the full private-repo dep tree and the pre-existing Convergence status
Status: converged for this PR's stated scope. Awaiting CI re-run on Agent: L4 PR remediation loop (l9-pr-remediation v2.1.0). 1 commit, 1 push this cycle (per protocol). |
There was a problem hiding this comment.
Pull request overview
This PR aims to unblock and stabilize CI for the Enrichment.Inference.Engine repo by addressing failures related to secret scanning, Docker image build tagging, SDK dependency access, and missing local pipeline scripts referenced by workflows.
Changes:
- Replaces the gitleaks GitHub Action with a pinned standalone
gitleaksCLI download + SARIF upload. - Fixes Docker image tag generation for PR builds by changing the metadata-action SHA tag prefix.
- Adds guards in the PR pipeline workflow so missing
local_pr_pipeline/*scripts don’t hard-fail CI, and updates SDK references fromcryptoxdogtoQuantum-L9.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
requirements-ci.txt |
Repoints constellation-node-sdk to Quantum-L9/Gate_SDK. |
pyproject.toml |
Repoints constellation-node-sdk to Quantum-L9/Gate_SDK (commit-pinned). |
Eie_CI_RECOVERY_HANDOFF.md |
Adds CI recovery handoff documentation and remediation classification. |
Dockerfile |
Installs git to support pip VCS installs during image build. |
.github/workflows/pr-pipeline.yml |
Guards missing local pipeline scripts to avoid exit-127 failures. |
.github/workflows/l9-contract-control.yml |
Removes SDK token enforcement; installs deps assuming public SDK. |
.github/workflows/l9-constitution-gate.yml |
Removes SDK token enforcement; installs deps assuming public SDK. |
.github/workflows/gitleaks.yml |
Switches gitleaks scanning to standalone binary + SARIF upload. |
.github/workflows/docker-build.yml |
Fixes invalid PR SHA tag prefix. |
.github/workflows/ci.yml |
Pins OpenSSF Scorecard action to v2.4.0. |
Comments suppressed due to low confidence (1)
.github/workflows/docker-build.yml:90
- The PR description mentions wiring
SDK_TOKENinto the Docker build as a BuildKit secret for privategit+httpsinstalls, but this workflow's build step does not pass any build secrets. IfQuantum-L9/Gate_SDKis still private in some environments, the image build will continue to fail atpip install. Either update the PR/documentation to reflect that the SDK is now public, or implement the BuildKit secret wiring end-to-end (workflow + Dockerfile).
- name: Build and Push Docker Image
id: build
uses: docker/build-push-action@v7
with:
context: .
| | Code-fixable by this agent | **Build & Push** (invalid tag + no git/token in image) and **Docs Consistency / select-gates / terminology** (missing scripts) — both fixed on `claude/pr-remediation-handoff-0vpwp2` | | ||
| | SDK access | **`Gate_SDK` made public (2026-07-01)** → SDK cloned anonymously; `SDK_TOKEN` no longer needed anywhere. SDK repointed `cryptoxdog` → `Quantum-L9`; token guards/rewrites removed from `l9-*.yml` + Dockerfile. The `SDK_TOKEN` org secret can be deleted. | | ||
| | Secret scanning | `GITLEAKS_LICENSE` no longer needed — swapped to the free binary CLI. | | ||
| | `minimum_safe_next_action` | Set `SDK_TOKEN` + `GITLEAKS_LICENSE` org secrets; merge the code-fix PR; rebase #114 + re-run #122 | |
| **Why blocked, not converged:** the gates that block merge are not defects in any PR diff. | ||
| The dominant blocker is a missing org-secret permission (`SDK_TOKEN` 403) that sinks ~10 jobs | ||
| on every PR. None of it is reachable from code in this repository. |
| # constellation-node-sdk is a public git+https dependency (Quantum-L9/Gate_SDK); | ||
| # pip clones it anonymously — git is required for the git+https install. |
| - name: Upload SARIF to GitHub Security | ||
| if: always() | ||
| continue-on-error: true | ||
| uses: github/codeql-action/upload-sarif@v4 |
| - name: Install control dependencies | ||
| env: | ||
| SDK_TOKEN: ${{ secrets.SDK_TOKEN }} | ||
| run: | | ||
| if [ -z "${SDK_TOKEN}" ]; then | ||
| echo "SDK_TOKEN is required to install private SDK dependencies" | ||
| exit 1 | ||
| fi | ||
| git config --global url."https://x-access-token:${SDK_TOKEN}@github.com/cryptoxdog/".insteadOf "https://github.com/cryptoxdog/" | ||
| # Gate_SDK is a public repo — pip clones it anonymously; no SDK_TOKEN required. | ||
| python -m pip install --upgrade pip | ||
| python -m pip install pyyaml pytest pytest-cov fastapi |
| - name: Install gate dependencies | ||
| env: | ||
| SDK_TOKEN: ${{ secrets.SDK_TOKEN }} | ||
| run: | | ||
| if [ -z "${SDK_TOKEN}" ]; then | ||
| echo "SDK_TOKEN is required to install private SDK dependencies" | ||
| exit 1 | ||
| fi | ||
| git config --global url."https://x-access-token:${SDK_TOKEN}@github.com/cryptoxdog/".insteadOf "https://github.com/cryptoxdog/" | ||
| # Gate_SDK is a public repo — pip clones it anonymously; no SDK_TOKEN required. | ||
| python -m pip install --upgrade pip | ||
| python -m pip install pyyaml pytest pytest-cov fastapi |
| - name: Install test dependencies | ||
| env: | ||
| SDK_TOKEN: ${{ secrets.SDK_TOKEN }} | ||
| run: | | ||
| if [ -z "${SDK_TOKEN}" ]; then | ||
| echo "SDK_TOKEN is required to install private SDK dependencies" | ||
| exit 1 | ||
| fi | ||
| git config --global url."https://x-access-token:${SDK_TOKEN}@github.com/cryptoxdog/".insteadOf "https://github.com/cryptoxdog/" | ||
| # Gate_SDK is a public repo — pip clones it anonymously; no SDK_TOKEN required. | ||
| python -m pip install --upgrade pip | ||
| if [ -f requirements-ci.txt ]; then |
…ndoff doc Resolves the clear, non-design Copilot review findings on #123: - requirements-ci.txt: pin constellation-node-sdk to the same commit SHA as pyproject.toml (was @main) so CI and the app dep set resolve the same SDK revision — removes non-reproducible drift when Gate_SDK's main moves. - Eie_CI_RECOVERY_HANDOFF.md: fix internal contradictions — the minimum_safe_next_action and "blocker" paragraph still said to set SDK_TOKEN / GITLEAKS_LICENSE, contradicting the rows stating both are obsolete (SDK public, gitleaks binary). Now states the current reality: SDK 403 resolved, remaining reds are pre-existing content-gate violations for follow-up PRs. - Dockerfile: make the SDK comment visibility-agnostic (documents the private fallback) instead of asserting public unconditionally. Design-decision items (optional SDK_TOKEN rewrite re-add; gitleaks continue-on-error) intentionally left for maintainer input. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb
Summary
Resolves CI blocking failures on #114 and #122 by replacing the gitleaks action (which requires an org license) with the free binary CLI, fixing docker image build tag generation and SDK token injection, and guarding missing pipeline scripts with advisory fallbacks.
Type of change
Changes
1. Gitleaks: Action → Binary CLI (
.github/workflows/gitleaks.yml)Root cause:
gitleaks-actionv2/v3 require a paid/freeGITLEAKS_LICENSEorg secret for organization accounts (Quantum-L9 is an org), regardless of repo visibility. Pinning the version does not bypass this gate.Fix: Replaced the action with the standalone
gitleaksbinary CLI (v8.21.2), which has no license gate. Remains a hard blocking gate (SOC 2 CC6.1), free, no secret required. SARIF output uploaded to GitHub Security tab.2. Docker Build: Tag and SDK Token (
Dockerfile,.github/workflows/docker-build.yml)Root cause (tag):
docker-build.ymlusedtype=sha,prefix={{branch}}-, which produces an empty{{branch}}on PRs, resulting in the invalid tag:-ff0fbce.Fix: Changed to
prefix=sha-, generating valid tags likesha-ff0fbce.Root cause (SDK token): Private dependency
constellation-node-sdk(git+https) requires authentication in-image duringpip install. Token was not available to the build.Fix:
gitto the base image (Dockerfile).SDK_TOKENas a BuildKit secret (never a build-arg or layer)..gitconfigso the token is not persisted to any layer.docker-build.ymlto pass the secret to the build context.3. Missing Pipeline Scripts: Existence Guards (
.github/workflows/pr-pipeline.yml)Root cause: Four scripts referenced by workflows do not exist:
local_pr_pipeline/check_compliance_terminology.pylocal_pr_pipeline/run_pr_select_gates.pylocal_pr_pipeline/docs_consistency_local.shlocal_pr_pipeline/docs_link_check_local.pyThese cause hard failures (exit 127) on every PR.
Fix: Wrapped each invocation in an existence check (
if [ -f … ]). If the script is missing, the step logs an advisory message and continues. This matches the repo's existing advisory pattern and allows the gate to pass until the scripts are reconstructed or explicitly removed.4. Handoff Documentation (
Eie_CI_RECOVERY_HANDOFF.md)Added comprehensive CI recovery handoff documenting:
Checklist
ruff checkpassesruff formatappliedmypypassespytestpasses locally.env.exampleupdated if new env vars added (N/A)Test Plan
CI gates will re-run on #114 (after rebase) and #122 (after merge). Expected outcomes:
GITLEAKS_LICENSEsecret (https://claude.ai/code/session_018AJUMb2SDtz5iMsQjKSfSb