Skip to content

ci: vendor governance-enforce — this repo was never in the A_BLOCK ruleset - #7

Open
yakimoto wants to merge 7 commits into
mainfrom
ci/vendor-governance-enforce
Open

ci: vendor governance-enforce — this repo was never in the A_BLOCK ruleset#7
yakimoto wants to merge 7 commits into
mainfrom
ci/vendor-governance-enforce

Conversation

@yakimoto

@yakimoto yakimoto commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Adds the governance-enforce A_BLOCK gate (secrets / hardcoded-paths, diff-scoped) to this repo. Part of claude-workstation#1624 E4 T4.9a, following the wave-av/cli#20 pilot.

Why this repo had no secrets scan

The org ruleset governance-a-block-enforce (17901847) requires an enforce check across the fleet. Its scope is an explicit include list of 112 hand-maintained repository names — and every one of them matches wave-*.

The 16 public repos absent from that list are exactly the 16 not named wave-*: .github, adk, api-spec, cli, companion-module-wave, create-wave-app, crest-console, dispatch-edge, examples, mcp-server, obs-wave-plugin, sdk, sdk-python, sdks, vmix-wave-integration, workflow-sdk.

Read the intersection: the repos that publish our npm packages are precisely the repos running with no A_BLOCK secrets scan. Nobody excluded them. A naming convention silently became a security boundary, and it drew the line in the worst possible place.

Why the workflow lands before the ruleset entry

Adding a repo to a required_status_checks ruleset before it emits that check is a permanent deadlock — a required check that never reports can never go green, and every PR on the repo becomes unmergeable. So the order is: vendor the workflow, observe it green, then extend the list. Doing it the intuitive way round would have bricked all sixteen.

This PR is also its own liveness drill. The workflow triggers on pull_request, so it runs on the PR that adds it. If enforce reports green here, the vendored shape works in this repo. If it does not, nothing was required and nothing is blocked — which is the point of this ordering.

Proven before fan-out, not assumed

@wave-av/governance is an internal-visibility package owned by claude-workstation, so whether a public repo's GITHUB_TOKEN can read it was the one real assumption. Rather than fan out on the inference, it was piloted on a single repo first:

wave-av/cli#20 — workflow run 31011943790, conclusion success.

That is the receipt this PR rides on. The shape is copied verbatim from wave-av/wave-moq-edge (public, 12/12 green), which matters because auto-approve.yml fails silently on every public repo — it calls a reusable workflow in the private wave-foundation, and a public repo cannot do that (parse-time failure, zero jobs, no annotation). This workflow calls nothing cross-repo, so that trap does not apply.

Security properties, unchanged from the source:

  • actions SHA-pinned (actions/checkout@df4cb1c, actions/setup-node@48b55a0)
  • persist-credentials: false on checkout
  • least privilege: contents: read + packages: read
  • isolated install into RUNNER_TEMP, --no-save, so nothing touches this repo's dependency tree
  • the .npmrc is written with a literal ${NODE_AUTH_TOKEN} (single-quoted printf) which npm expands at run time — no secret value is ever written to disk or a log
  • both ${{ }} inputs (base.sha, event.before) are routed through env: and read as "$VAR", never interpolated into the script body

Diff-scoped by design: it blocks new violations without failing on legacy debt.

Refs wave-av/claude-workstation#1624.


View with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is enabled.


Note

Low Risk
Adds CI-only governance scanning with read-only permissions and hardened install/execution; no application runtime or data-path changes.

Overview
Adds .github/workflows/governance-enforce.yml, bringing this repo onto the org A_BLOCK path (governance-a-block-enforce expects an enforce job) after it was missing from the hand-maintained wave-*-only ruleset list.

On **PRs and pushes to main/master, the workflow checks out full history, installs @wave-av/governance@0.4.6 into $RUNNER_TEMP (isolated --ignore-scripts install with registry token scoped to that step), and runs enforce.mjs --changed <base> so only new secrets/hardcoded-path violations on the diff fail—not legacy debt.

Hardening baked into the vendored copy: push runs use concurrency keyed by run_id so superseding a push does not leave commits unscanned; diff base falls back through unreachable before / HEAD~1, then the empty tree (not HEAD) when no base exists; actions are SHA-pinned with persist-credentials: false and contents/packages: read.

Do not add this repo to the ruleset until enforce is green here—required checks with no reporter deadlock merges.

Reviewed by Cursor Bugbot for commit f1ac62a. Configure here.

Review in cubic

Note

Add governance enforcement workflow to scan diffs on PRs and pushes to main

Adds governance-enforce.yml, which runs @wave-av/governance@0.4.6 on pull requests, merge groups, and pushes to main/master. The enforcer scans only changed files using a computed diff base; if no valid base is found, it falls back to the empty tree and scans the full repository. Push and merge group runs are not cancelable to ensure no committed ranges are skipped.

Macroscope summarized 7a5d2da.

Summary by CodeRabbit

  • Chores
    • Added automated governance checks for pull requests and changes pushed to the main branches.
    • Scans changes for exposed secrets and hardcoded paths.
    • Uses read-only access and cancels outdated runs to improve workflow safety and efficiency.

@yakimoto yakimoto added the rr:skip-cubic RF.P1 reviewer routing (#1039) label Aug 5, 2026
@cursor

cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_09d5dbaf-9aaa-4ff0-b03a-b423c0cc7b53)

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Governance enforcement

Layer / File(s) Summary
Workflow triggers and permissions
.github/workflows/governance-enforce.yml
The workflow runs for pull requests and pushes to main or master. It uses read-only permissions and cancels superseded runs.
Runner and governance tooling setup
.github/workflows/governance-enforce.yml
The job checks out full history, configures Node.js 22, and installs @wave-av/governance in a temporary directory.
Diff base selection and A_BLOCK enforcement
.github/workflows/governance-enforce.yml
The workflow selects a valid comparison base and runs diff-scoped A_BLOCK checks for secrets and hardcoded paths.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant Git
  participant GovernanceEnforcer
  GitHubActions->>Git: Select pull-request base or push predecessor
  GitHubActions->>Git: Fall back to HEAD~1 or HEAD when needed
  GitHubActions->>GovernanceEnforcer: Run A_BLOCK checks against the selected diff
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the added governance workflow and explains why this repository needs it.
Description check ✅ Passed The description directly explains the governance workflow, its security controls, scan scope, and ruleset rollout order.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/vendor-governance-enforce

Comment @coderabbitai help to get the list of available commands.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 5, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 5, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

Unable to check for correctness in 7a5d2da. This PR adds a security governance workflow with complex diff-base fallback logic. Multiple unresolved review comments raise substantive concerns about authentication failures and edge cases where the security scan may not examine all content as intended.

You can customize Macroscope's approvability policy. Learn more.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread .github/workflows/governance-enforce.yml Outdated
Comment on lines +44 to +48
- name: fetch governance enforcer (isolated install)
run: |
mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
npm install @wave-av/governance@^0.4.4 --no-save --no-audit --no-fund

@devin-ai-integration devin-ai-integration Bot Aug 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 GITHUB_TOKEN authenticating to another repo's GitHub Packages scope

The isolated install authenticates to npm.pkg.github.com with the workflow's GITHUB_TOKEN. That token's package read scope is limited to packages linked to this repository (or packages whose visibility/access grants this repo). If @wave-av/governance is a private package not granted access to wave-av/crest-console, the npm install step will 401 and the gate will fail for every PR. The header notes the pattern was proven on wave-av/cli, but per-package repository access grants are configured per package, so worth confirming for this repo before adding the check to the required-status ruleset.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a deployment verification concern, not a workflow defect: the PR is explicitly its own liveness drill, so the install step running on this PR's CI will prove whether @wave-av/governance grants this repo access before the check is added to the ruleset.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Vendor governance-enforce A_BLOCK diff-scoped gate for secrets/hardcoded paths

⚙️ Configuration changes ✨ Enhancement 🕐 10-20 Minutes

Grey Divider

AI Description

• Add a required-status-check-compatible enforce CI workflow for A_BLOCK governance rules.
• Run diff-scoped scanning (new violations only) on PRs and main/master pushes.
• Fetch @wave-av/governance from GitHub Packages with least-privilege, SHA-pinned actions.
Diagram

graph TD
  EVT["pull_request / push"] --> WF[".github/workflows/governance-enforce.yml"] --> JOB["job: enforce"] --> CK["checkout (no creds)"] --> NODE["setup-node 22"] --> INST["install @wave-av/governance"] --> RUN["run enforce.mjs --changed BASE"]
  INST --> PKG["GitHub Packages (npm)"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Pin @wave-av/governance to an exact version
  • ➕ Eliminates unexpected behavior changes from semver-compatible but breaking releases
  • ➕ Improves auditability/reproducibility for a required check
  • ➖ Requires manual bumps to pick up new rules/fixes
  • ➖ May slow rollout of governance improvements across repos
2. Central reusable workflow (single source of truth)
  • ➕ One place to patch/pin actions, Node versions, and enforcement flags
  • ➕ Consistent rollout across repos without copy/paste drift
  • ➖ Public repos can’t safely depend on private workflow sources; cross-repo reuse can fail at parse-time
  • ➖ Requires additional governance around workflow versioning and access
3. Cache the isolated npm install (actions/cache)
  • ➕ Reduces runtime and load on GitHub Packages
  • ➕ Improves CI latency on frequent PR updates
  • ➖ Adds cache key complexity and potential cache-staleness debugging
  • ➖ Savings may be small given the limited install scope

Recommendation: Current approach is appropriate for safely unblocking ruleset adoption: it is self-contained (no cross-repo reusable workflow dependency), uses least-privilege permissions, and computes a base SHA to keep enforcement diff-scoped. The main improvement worth considering is pinning @wave-av/governance to an exact version once the rollout stabilizes to maximize determinism for a required status check.

Files changed (1) +59 / -0

Other (1) +59 / -0
governance-enforce.ymlAdd A_BLOCK diff-scoped governance enforcement workflow +59/-0

Add A_BLOCK diff-scoped governance enforcement workflow

• Introduces a new GitHub Actions workflow that runs on pull requests and pushes to main/master. It installs @wave-av/governance from GitHub Packages with packages:read and executes the enforcer against the computed base SHA to flag new secrets/hardcoded-path violations.

.github/workflows/governance-enforce.yml

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
@qodo-code-review

qodo-code-review Bot commented Aug 5, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Unpinned enforcer dependency ✓ Resolved 🐞 Bug ⛨ Security
Description
The workflow installs and executes @wave-av/governance using a semver range (^0.4.4), so the
required enforce check can change behavior or start failing without any change in this repo.
Because the installed package is executed, a bad/compromised publish directly impacts CI and
mergeability.
Code

.github/workflows/governance-enforce.yml[R46-48]

+          mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
+          printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
+          npm install @wave-av/governance@^0.4.4 --no-save --no-audit --no-fund
Evidence
The workflow resolves and installs @wave-av/governance with a caret range and immediately runs its
enforce.mjs, making the check’s behavior depend on whatever version happens to be resolved at
runtime.

.github/workflows/governance-enforce.yml[44-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The workflow installs `@wave-av/governance@^0.4.4` at runtime and then executes it. Using a version range makes the required `enforce` check non-deterministic across runs and increases supply-chain blast radius.

### Issue Context
This job is intended to be a stable, required gate. Installing an executable dependency with a semver range (especially `0.x`) can change behavior unexpectedly or break CI.

### Fix Focus Areas
- .github/workflows/governance-enforce.yml[44-59]

### Suggested fix
- Pin to an exact version (e.g. `@wave-av/governance@0.4.4` rather than `^0.4.4`).
- Optionally add defense-in-depth to the install step if compatible (e.g. `--ignore-scripts`), or otherwise ensure the package is only updated intentionally via PRs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Token scope too broad ✓ Resolved 🐞 Bug ⛨ Security
Description
NODE_AUTH_TOKEN is set at the job level, so the read-scoped GITHUB_TOKEN is injected into every step
environment (including actions) even though it is only needed for the npm install step. This
increases the risk of accidental exposure/misuse as steps change over time.
Code

.github/workflows/governance-enforce.yml[R34-35]

+    env:
+      NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Evidence
The token is declared under jobs.enforce.env, applying to every step, while the only direct use is
writing it into .npmrc for the install step; the workflow also documents the token’s intended
limited permissions.

.github/workflows/governance-enforce.yml[23-26]
.github/workflows/governance-enforce.yml[34-48]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`NODE_AUTH_TOKEN` is defined at the job level, so all steps inherit it. The token is only required for the single step that writes `.npmrc` and performs `npm install`.

### Issue Context
The workflow already limits permissions to `contents: read` and `packages: read`, but least-privilege still suggests scoping credentials to the narrowest step possible.

### Fix Focus Areas
- .github/workflows/governance-enforce.yml[23-48]

### Suggested fix
- Remove `jobs.enforce.env.NODE_AUTH_TOKEN`.
- Add `env: NODE_AUTH_TOKEN: ${{ github.token }}` only on the "fetch governance enforcer" step (or only on the specific commands that require it).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ REVIEW.md
Review mode: ⚖️ Balanced: This adds a security-sensitive CI enforcement workflow that installs and executes a package, handles credentials and diff-base selection, and affects repository governance; one focused hunk is not enough to justify extended, nor is it low-risk enough for lite.

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

qodo-code-review[bot]

This comment was marked as resolved.

@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

No findings are within the configured fix scope. To change which findings are fixed, adjust the setting on your Qodo configuration page.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 5, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines +44 to +48
- name: fetch governance enforcer (isolated install)
run: |
mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
npm install @wave-av/governance@^0.4.4 --no-save --no-audit --no-fund

@devin-ai-integration devin-ai-integration Bot Aug 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Fork PRs will fail this gate on package auth

For pull_request events from forks, secrets.GITHUB_TOKEN is issued with read-only scope for the base repo, but organizations frequently see failures reading internal-visibility GitHub Packages from fork-triggered runs. Since this repo is public, fork PRs are plausible, and a failing install step here would hard-fail the job (and, once the ruleset is extended, block those PRs entirely). Worth verifying the fork case explicitly before adding enforce to governance-a-block-enforce, since the wave-av/cli#20 pilot was a same-repo branch PR.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/governance-enforce.yml:
- Around line 27-29: Update the concurrency configuration near the
workflow-level group so push-triggered scans are never canceled by later pushes,
while preserving cancellation for appropriate non-push runs. Use distinct
concurrency groups or disable cancellation for push events, and ensure pending
push runs are not allowed to replace one another in a way that skips changed
revisions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7c76e8b3-56fe-46c9-85e7-2d685ae87e59

📥 Commits

Reviewing files that changed from the base of the PR and between a4676d6 and 2cf27d0.

📒 Files selected for processing (1)
  • .github/workflows/governance-enforce.yml

Comment on lines +27 to +29
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow =="
cat -n .github/workflows/governance-enforce.yml

echo
echo "== references to pushed_before_sha / changed / governance =="
rg -n "PUSH_BEFORE_SHA|push\.before|github\.push|changed|`@wave-av/governance`|governance-enforce" .github/workflows || true

echo
echo "== other checks mentioning diff-only coverage =="
rg -n "DIFF-SCOPED|full-tree|no path rule|SECRET|governance" .github/workflows/_checks.yml || true

Repository: wave-av/crest-console

Length of output: 7280


🌐 Web query:

GitHub Actions concurrency cancel-in-progress previous run in same group cancels

💡 Result:

In GitHub Actions, the behavior of the concurrency setting depends on the configuration of cancel-in-progress and whether you are using the default queuing behavior or the newer, expanded queuing feature [1][2]. At most, one job or workflow run can be in progress within a concurrency group at any given time [1][3]. When a new run is queued for that group, the following happens based on your configuration: 1. Default Behavior (cancel-in-progress: false or unset): If a run is already in progress, the new run enters a pending state [1][3]. If there was a previously pending run in that group, it is automatically canceled and replaced by the newest run [1][3]. This ensures that while only one run is active, there is at most one pending run waiting to take its place [3]. 2. Cancel-in-progress: true: If a run is already in progress, setting cancel-in-progress: true will cause the currently running job or workflow to be canceled immediately [1][3]. The new run then replaces it [1]. 3. Expanded Queuing (queue: max): As of May 2026, you can enable larger queues by setting queue: max [2]. This allows up to 100 pending runs to wait in line sequentially instead of canceling older pending runs [2]. This configuration is incompatible with cancel-in-progress: true and can only be used when cancel-in-progress is set to false (or left unset) [1][2]. Key Considerations: - Concurrency group names are scoped to the repository [1]. If multiple workflows use the same concurrency group name, they will compete for the same slot, potentially canceling each other's pending or in-progress runs [1][3]. To isolate concurrency to a specific workflow, include github.workflow in your group name (e.g., group: ${{ github.workflow }}-${{ github.ref }}) [1][3]. - You can use expressions with cancel-in-progress to dynamically decide whether to cancel runs, such as only canceling on specific branches while allowing others to run to completion [1][4].

Citations:


🌐 Web query:

GitHub Actions workflow push event before SHA documentation

💡 Result:

In a GitHub Actions workflow triggered by a push event, the commit SHA immediately preceding the push is available via the context variable ${{ github.event.before }} [1][2]. When a push event occurs, the GitHub webhook payload includes a before property, which represents the SHA of the most recent commit on the branch prior to the push [1]. You can access this value directly in your workflow file using the github context [3][2]. Key details: - Context Access: Use ${{ github.event.before }} to retrieve the previous SHA [2]. - Initial Pushes: Note that if the push involves a newly created branch or ref, the before SHA may be a default value, such as 0000000000000000000000000000000000000000 [2]. - Comparison: This value is distinct from ${{ github.sha }}, which represents the tip commit of the pushed ref (the "after" state) [3][4]. This functionality is commonly used in workflows that need to calculate the range of commits included in a push, such as for generating changelogs, identifying modified files, or determining the correct fetch-depth for the actions/checkout step [5][2].

Citations:


Security Misconfiguration (CWE-693)

Reachability: External

Keep push scans from being canceled.

If two pushes to main or master run in the same github.workflow-${ github.ref } concurrency group, a later push cancels the earlier run. The completed run then uses only its own PUSH_BEFORE_SHA, so changes from the canceled push can be skipped by --changed "$BASE".

Use a unique concurrency group for push runs, or do not let pushes cancel PR runs; canceling pending runs within the same group still allows one pending run to replace another.

Proposed fix
 concurrency:
-  group: ${{ github.workflow }}-${{ github.ref }}
-  cancel-in-progress: true
+  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
+  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/governance-enforce.yml around lines 27 - 29, Update the
concurrency configuration near the workflow-level group so push-triggered scans
are never canceled by later pushes, while preserving cancellation for
appropriate non-push runs. Use distinct concurrency groups or disable
cancellation for push events, and ensure pending push runs are not allowed to
replace one another in a way that skips changed revisions.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found and verified against the latest diff

Confidence score: 2/5

  • In .github/workflows/governance-enforce.yml, the governance enforcer is effectively floating to the latest 0.4.x on fresh runners, so a future or compromised release could silently change a required security gate and weaken enforcement—pin an exact version (or commit digest) and vendor/lock it for reproducible runs.
  • In .github/workflows/governance-enforce.yml, installing from npm.pkg.github.com with the default GITHUB_TOKEN can fail when package read access is not explicitly granted, which can make this required check flaky or block PRs unexpectedly—grant package read permission for @wave-av/governance (or use a dedicated token with the needed scope).
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/governance-enforce.yml">

<violation number="1" location=".github/workflows/governance-enforce.yml:47">
P2: The install step authenticates to npm.pkg.github.com using the workflow's GITHUB_TOKEN, whose GitHub Packages read scope is limited to packages explicitly granted access to this repository. If @wave-av/governance hasn't been granted per-repo access for wave-av/crest-console, the npm install will fail with a 401 for every run, permanently failing this check. This should be verified for this specific repo before wiring it into the required-status ruleset, since the referenced pilot (wave-av/cli#20) doesn't guarantee the same package access grant exists here.</violation>

<violation number="2" location=".github/workflows/governance-enforce.yml:48">
P1: The enforcer is not actually vendored: every fresh runner resolves the newest 0.4.x release, allowing a later or compromised package release to silently alter or weaken this required security check. Pin an exact package version and verify the dependency lockfile/integrity.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/workflows/governance-enforce.yml Outdated
run: |
mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
npm install @wave-av/governance@^0.4.4 --no-save --no-audit --no-fund

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The enforcer is not actually vendored: every fresh runner resolves the newest 0.4.x release, allowing a later or compromised package release to silently alter or weaken this required security check. Pin an exact package version and verify the dependency lockfile/integrity.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/governance-enforce.yml, line 48:

<comment>The enforcer is not actually vendored: every fresh runner resolves the newest 0.4.x release, allowing a later or compromised package release to silently alter or weaken this required security check. Pin an exact package version and verify the dependency lockfile/integrity.</comment>

<file context>
@@ -0,0 +1,59 @@
+        run: |
+          mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
+          printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
+          npm install @wave-av/governance@^0.4.4 --no-save --no-audit --no-fund
+      - name: A_BLOCK enforce (secrets + hardcoded paths on the diff)
+        env:
</file context>

NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The install step authenticates to npm.pkg.github.com using the workflow's GITHUB_TOKEN, whose GitHub Packages read scope is limited to packages explicitly granted access to this repository. If @wave-av/governance hasn't been granted per-repo access for wave-av/crest-console, the npm install will fail with a 401 for every run, permanently failing this check. This should be verified for this specific repo before wiring it into the required-status ruleset, since the referenced pilot (wave-av/cli#20) doesn't guarantee the same package access grant exists here.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/governance-enforce.yml, line 47:

<comment>The install step authenticates to npm.pkg.github.com using the workflow's GITHUB_TOKEN, whose GitHub Packages read scope is limited to packages explicitly granted access to this repository. If @wave-av/governance hasn't been granted per-repo access for wave-av/crest-console, the npm install will fail with a 401 for every run, permanently failing this check. This should be verified for this specific repo before wiring it into the required-status ruleset, since the referenced pilot (wave-av/cli#20) doesn't guarantee the same package access grant exists here.</comment>

<file context>
@@ -0,0 +1,59 @@
+      - name: fetch governance enforcer (isolated install)
+        run: |
+          mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
+          printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
+          npm install @wave-av/governance@^0.4.4 --no-save --no-audit --no-fund
+      - name: A_BLOCK enforce (secrets + hardcoded paths on the diff)
</file context>

devin-ai-integration[bot]

This comment was marked as resolved.

…othing

Five defects, none of them cosmetic. Refs wave-av/claude-workstation#1747.

1. FAIL-OPEN DIFF BASE. `BASE=$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)`
   — on a root commit `git rev-parse HEAD~1` prints its unresolved argument to stdout AND
   fails, so the `||` branch appends and BASE becomes a two-line string. `git diff` then
   exits 128, and the pinned enforcer turned that into zero files and a green check. Now:
   a reachability-checked base (a force-push can leave `github.event.before` pointing at a
   commit this checkout does not have), and with no resolvable base at all it diffs against
   the EMPTY TREE so the whole repo is scanned rather than nothing.

2. THE PINNED ENFORCER ITSELF FAILED OPEN. `^0.4.4` resolved to 0.4.4, whose file lister is
   `catch { return []; }` — any git error became zero files and rendered as
   `OK[enforce]: 0 changed file(s) scanned — 0 A_BLOCK violations`. A git error and a clean
   diff were byte-identical in the output. The fix had sat unreleased on claude-workstation
   main since 2026-07-29 because no `governance-v*` tag was ever pushed. Released now as
   0.4.6 and pinned exactly here.

3. TOKEN IN SCOPE FOR THE WRONG STEPS. `NODE_AUTH_TOKEN` was job-level, so it was also in
   the environment of the step that executes the downloaded package. Now step-scoped, and
   the .npmrc holding it is removed on exit.

4. INSTALL SCRIPTS RAN WITH THAT TOKEN. `npm install` runs preinstall/postinstall by
   default. Added `--ignore-scripts`.

5. CANCELLED PUSH RUNS WERE SCANNED BY NOBODY. `cancel-in-progress: true` applied to push
   runs, and each push run only diffs its own before..HEAD range — so a cancelled run's
   commits were never examined by anything. Now PR-only.

Also: `timeout-minutes: 10` and `set -euo pipefail`.

Receipt, against a scratch repo whose root commit carries a no-hardcoded-paths violation,
simulating a branch-creation push (`before` = all zeros):
  old logic -> malformed base -> caught error -> [] -> OK, 0 files scanned, PASS
  new logic -> "no diff base resolved ... scanning the whole tree" -> BLOCK, exit 1

Credit where it is due: several of these were found by the review bots on the sibling
vendoring PRs and are folded in here — the step-scoped token, the .npmrc cleanup, the exact
pin, `--ignore-scripts`, the force-push reachability check, `timeout-minutes`, and the
concurrency hole (5), which was crest-console#7's catch and which I had missed entirely.
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_02b21b8d-8f26-47b2-a6a7-f3265d9877c6)

# pointing at a commit this checkout no longer contains.
if [ -z "$BASE" ] || [ "$BASE" = "0000000000000000000000000000000000000000" ] \
|| ! git cat-file -e "$BASE^{commit}" 2>/dev/null; then
BASE="$(git rev-parse --verify --quiet 'HEAD~1' || true)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High workflows/governance-enforce.yml:80

When the supplied base SHA is unreachable (e.g., after a force-push), the fallback sets BASE to HEAD~1, which diffs only the tip commit. For a multi-commit push, earlier commits in the new history are silently skipped, so newly introduced secrets or hardcoded paths pass the gate despite the comment claiming the fallback fails closed. The fix at line 88 already handles an empty BASE by falling back to the empty tree, but this HEAD~1 branch at line 80 never reaches that logic — it sets BASE to a non-empty value and exits the fallback early. Consider resolving to the empty tree here as well, or determining a complete diff range, so no commits are skipped.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @.github/workflows/governance-enforce.yml around line 80:

When the supplied base SHA is unreachable (e.g., after a force-push), the fallback sets `BASE` to `HEAD~1`, which diffs only the tip commit. For a multi-commit push, earlier commits in the new history are silently skipped, so newly introduced secrets or hardcoded paths pass the gate despite the comment claiming the fallback fails closed. The fix at line 88 already handles an *empty* `BASE` by falling back to the empty tree, but this `HEAD~1` branch at line 80 never reaches that logic — it sets `BASE` to a non-empty value and exits the fallback early. Consider resolving to the empty tree here as well, or determining a complete diff range, so no commits are skipped.

Evidence trail:
.github/workflows/governance-enforce.yml:74-93 (f1ac62a); .github/workflows/_checks.yml:75-80,101-108 (f1ac62a); git diff MERGE_BASE REVIEWED_COMMIT -- .github/workflows/governance-enforce.yml

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Open in Devin Review

Comment thread .github/workflows/governance-enforce.yml
Comment on lines +88 to +90
if [ -z "$BASE" ]; then
BASE="$(git hash-object -t tree /dev/null)"
echo "::notice::no diff base resolved (root commit or unreachable before-sha) — scanning the whole tree against the empty tree"

@devin-ai-integration devin-ai-integration Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Empty-tree base depends on how the enforcer diffs

git hash-object -t tree /dev/null yields the well-known empty-tree id, which git resolves in-memory even though the object is not written. That is fine for a two-dot git diff <empty-tree> HEAD, but a three-dot diff (A...HEAD) against a tree id fails because there is no merge base. Since the fail-closed path deliberately routes the whole-tree scan through the diff code path, this fallback only works if enforce.mjs uses a two-dot diff. Verifying this would be worthwhile, since the failure mode is exactly the "reports nothing examined" class the header comment is trying to eliminate.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against the published 0.4.6 source: changedArgs uses the two-argument git diff <base> HEAD form, explicitly documented as chosen because A...HEAD rejects tree objects like the empty tree. Even on a git error the lister fails closed (exit 1), so the silent-pass failure mode cannot occur.

…not HEAD~1

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Open in Devin Review

Comment on lines +26 to +66
permissions:
contents: read
packages: read

# FIX 4 — a cancelled push run's commits were scanned by NOBODY. Every push run diffs only its
# own before..HEAD range, so cancelling run N when run N+1 starts leaves N's commits permanently
# unexamined. PR runs are safe to supersede: each one re-diffs the whole branch against its base.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
enforce:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"
- name: fetch governance enforcer (isolated install)
# FIX 1 — token scoped to THIS STEP. At job level it was also in scope for the step that
# executes the downloaded package, and for anything else the job ever grows.
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
trap 'rm -f "$RUNNER_TEMP/gov/.npmrc"' EXIT
printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
# FIX 2 — --ignore-scripts. npm runs preinstall/install/postinstall by default, so this
# step would execute dependency-authored code with the registry token in its environment.
# FIX 3 — exact pin, and 0.4.6 specifically. `^0.4.4` resolved to 0.4.4, whose file lister
# is `catch { return []; }` — ANY git error became zero files and rendered as
# `OK[enforce]: 0 changed file(s) scanned`. 0.4.6 fails closed on a git error instead.
# A caret is also a standing authorization for whatever is published next; a bump is now
# a visible commit in this file.
npm install @wave-av/governance@0.4.6 --no-save --no-audit --no-fund --ignore-scripts

@devin-ai-integration devin-ai-integration Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Private-package install from a public repo / fork PRs may not authenticate

This repository is public (package.json sets private: false, and .github/workflows/public-repo-guard.yml exists as a publication gate). The install step authenticates to npm.pkg.github.com with secrets.GITHUB_TOKEN and only packages: read. A repo-scoped GITHUB_TOKEN can read a GitHub Packages artifact published by a different repo only if that package has explicitly granted read access to this repo (or is org-internal with the right visibility). For pull_request runs originating from forks the token is further restricted. Worth verifying that @wave-av/governance@0.4.6 is readable here before the org ruleset makes this a required check — otherwise the job fails at install on every PR, which is exactly the permanent-deadlock scenario the header comment warns about.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-ruleset verification concern already covered by the rollout design: this PR is its own liveness drill, and the header plus PR description gate ruleset inclusion on first observing this check green here, so any package-access 401/403 surfaces in this PR's CI before the check can become required.

Comment on lines +89 to +94
if [ -z "$BASE" ]; then
BASE="$(git hash-object -t tree /dev/null)"
echo "::notice::no diff base resolved (root commit or unreachable before-sha) — scanning the whole tree against the empty tree"
fi
echo "diffing against $BASE"
exec node "$ENFORCE" --changed "$BASE"

@devin-ai-integration devin-ai-integration Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Empty-tree fallback assumes the enforcer performs a two-dot diff

git hash-object -t tree /dev/null yields the well-known empty-tree oid, which git special-cases so it resolves even though it was never written to the object database — git diff <empty-tree> HEAD works. However, if enforce.mjs --changed <base> internally uses a three-dot/merge-base diff (git diff base...HEAD), the empty tree has no merge base with HEAD and git errors out. Since 0.4.6 is described as failing closed on git errors, the fallback would turn every unresolvable-base run into a hard failure rather than a whole-tree scan. Confirm which diff form the enforcer uses.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against the published 0.4.6 source: changedArgs uses the two-argument git diff <base> HEAD form, documented as chosen specifically because A...HEAD requires a merge base and rejects tree objects like the empty tree. The fallback performs the intended whole-tree scan.

…l a false pass

Correction to the previous commit on this branch. Refs wave-av/claude-workstation#1747.

That commit replaced the fail-open `BASE=HEAD` with a fallback to `HEAD~1`. `HEAD~1` is
also wrong: it scans exactly ONE commit, so a five-commit push whose base is indeterminate
(branch creation, force-push, unreachable `github.event.before`) examines the last commit
and reports a confident pass on the other four. A narrowed scan reported as a full pass is
the same defect in a quieter costume.

Receipt — scratch repo, five-commit push, violation planted in commit 1:
  HEAD~1 base      -> OK[enforce]: 1 changed file(s) scanned  -> PASS   (never saw it)
  empty-tree base  -> 5 changed file(s) scanned -> BLOCK[enforce]: no-hardcoded-paths, exit 1

Now: with no resolvable base of any kind, diff against git's empty-tree object so every
tracked file reads as added and the whole repo is scanned. Loud, never partial, never empty.

Credit: wave-av/wave-rig's copy on main already had this right, with the reasoning in a
comment ("HEAD~1 would skip earlier commits in a multi-commit push and let a violation
through"). The fan-out copied the broken shape from elsewhere and I did not check the one
repo that had already solved it.

Also from wave-rig: `merge_group` is now a declared trigger and `github.event.merge_group.
base_sha` joins the base chain. None of these repos runs a merge queue today, so the trigger
is inert — but a required check that never reports on an event the repo actually uses is a
permanent deadlock, and this closes that in advance rather than after someone hits it.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines +53 to +70
- name: fetch governance enforcer (isolated install)
# FIX 1 — token scoped to THIS STEP. At job level it was also in scope for the step that
# executes the downloaded package, and for anything else the job ever grows.
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
mkdir -p "$RUNNER_TEMP/gov" && cd "$RUNNER_TEMP/gov"
trap 'rm -f "$RUNNER_TEMP/gov/.npmrc"' EXIT
printf '@wave-av:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}\n' > .npmrc
# FIX 2 — --ignore-scripts. npm runs preinstall/install/postinstall by default, so this
# step would execute dependency-authored code with the registry token in its environment.
# FIX 3 — exact pin, and 0.4.6 specifically. `^0.4.4` resolved to 0.4.4, whose file lister
# is `catch { return []; }` — ANY git error became zero files and rendered as
# `OK[enforce]: 0 changed file(s) scanned`. 0.4.6 fails closed on a git error instead.
# A caret is also a standing authorization for whatever is published next; a bump is now
# a visible commit in this file.
npm install @wave-av/governance@0.4.6 --no-save --no-audit --no-fund --ignore-scripts

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Outside contributors' pull requests will always fail the new check on this public repository

The new gate downloads a private company package using the automatic pull-request token (npm install @wave-av/governance@0.4.6 at .github/workflows/governance-enforce.yml:70), which contributors from outside the organization do not have access to, so their pull requests fail the check for reasons they cannot fix.
Impact: Every pull request opened from a fork of this public, Apache-2.0 repository is blocked by a red required-looking check.

Why the fork token cannot read the org-scoped registry package

The .npmrc written at .github/workflows/governance-enforce.yml:62 points @wave-av at npm.pkg.github.com and authenticates with secrets.GITHUB_TOKEN (.github/workflows/governance-enforce.yml:57). For a pull request originating from a fork, that token is issued for the fork repository and is read-only; GitHub Packages access for an org-private package is granted per-repository, and forks are not on that list, so npm install gets 401/403 and the step exits non-zero under set -euo pipefail.

This repository is explicitly the public open-core client (see README.md and .github/workflows/public-repo-guard.yml, a "pre-publication content gate for WAVE public repos"), so fork pull requests are the expected contribution path. The sibling gates (_checks.yml, public-repo-guard.yml) are deliberately self-contained/vendored and need no private fetch, which is why they work for forks.

Options: gate the job with if: github.event.pull_request.head.repo.fork == false (accepting no scan for fork PRs, plus a push-side scan), or vendor the enforcement script into this repo the way scripts/public-repo-guard/content-policy.sh is vendored.

Prompt for agents
The governance-enforce workflow installs the org-private npm package @wave-av/governance from GitHub Packages using secrets.GITHUB_TOKEN. On this repository (public open-core, per README.md and public-repo-guard.yml) pull requests come from forks, where GITHUB_TOKEN is scoped to the fork and cannot read the wave-av org's private package, so the install step fails and the whole check goes red for external contributors with no way to fix it. Decide on an approach: either skip/soft-report the job for fork PRs (and rely on the push-to-main run for coverage), or vendor the enforcement logic into the repo the way scripts/public-repo-guard/content-policy.sh is vendored so no authenticated fetch is needed. Note the workflow header explicitly says not to make this a required check until it is observed green here.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rr:skip-cubic RF.P1 reviewer routing (#1039)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant