Skip to content
Closed
2 changes: 1 addition & 1 deletion .github/workflows/acquisition-readiness-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:

- name: upload acquisition artifacts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: acquisition-readiness-audit
path: artifacts/acquisition-readiness/**/*
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ jobs:

- name: Upload durable deployment and rollback evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-deployment-evidence-production-${{ steps.release.outputs.tag }}
path: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/hourly-commercial-readiness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ jobs:

- name: upload scheduler activation evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: scheduler-activation-evidence
path: artifacts/operations/hourly-scheduler-activation.json
Expand Down Expand Up @@ -199,7 +199,7 @@ jobs:

- name: upload main governance audit
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: main-governance-audit
path: artifacts/governance/main-governance-audit.json
Expand All @@ -208,7 +208,7 @@ jobs:

- name: upload loop report
if: always() && steps.loop.outcome != 'skipped'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: commercial-readiness-loop-report
path: artifacts/commercial-readiness/hourly-loop-report.json
Expand All @@ -217,7 +217,7 @@ jobs:

- name: upload no-PR commercial-readiness evidence
if: always() && steps.loop.outputs.remaining_open_pull_request_count == '0'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: no-pr-commercial-readiness-evidence
path: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/readiness-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:

- name: upload readiness artifacts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: saleable-readiness-audit
path: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release-evidence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ jobs:

- name: Upload bounded sterile release materialization
id: materialization_bundle
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-release-materialization-${{ needs.verify_release.outputs.tag }}
path: |
Expand Down Expand Up @@ -404,7 +404,7 @@ jobs:

- name: Upload bounded release publication bundle
id: release_bundle
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-release-evidence-${{ needs.materialize_release.outputs.tag }}
path: |
Expand Down Expand Up @@ -647,7 +647,7 @@ jobs:

- name: Upload durable publication receipt
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-release-publication-${{ needs.attest_release.outputs.tag }}
path: ${{ runner.temp }}/release-publication/
Expand Down
5 changes: 4 additions & 1 deletion test/acquisition-readiness-scan-toolchain-integrity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ describe("acquisition-readiness workflow supply-chain integrity", () => {
"uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
);
expect(workflow).toContain(
"uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2",
"uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1",
);
expect(workflow).not.toContain(
"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02",
);
expect(workflow).not.toMatch(
/uses:\s+actions\/(?:checkout|setup-node|upload-artifact)@v\d+/,
Expand Down
5 changes: 4 additions & 1 deletion test/readiness-scan-toolchain-integrity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ describe("saleable-readiness workflow supply-chain integrity", () => {
"uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
);
expect(workflow).toContain(
"uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2",
"uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1",
);
expect(workflow).not.toContain(
"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02",
);
expect(workflow).not.toMatch(/uses:\s+actions\/(?:checkout|setup-node|upload-artifact)@v\d+/);
});
Expand Down
28 changes: 28 additions & 0 deletions test/upload-artifact-node24-integrity.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";

const uploadArtifactPin =
"actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1";
const deprecatedUploadArtifactPin =
"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02";
const supportedWorkflowPaths = [
".github/workflows/acquisition-readiness-scan.yml",
".github/workflows/cd.yml",
".github/workflows/central-review.yml",
".github/workflows/hourly-commercial-readiness.yml",
".github/workflows/hourly-product-development.yml",
".github/workflows/maintainer-app-readiness.yml",
".github/workflows/readiness-scan.yml",
".github/workflows/release-evidence.yml",
] as const;

describe("upload-artifact Node 24 supply-chain contract", () => {
for (const workflowPath of supportedWorkflowPaths) {
it(`${workflowPath} pins the reviewed Node 24 upload action`, () => {
const workflow = readFileSync(workflowPath, "utf8");
expect(workflow).toContain(uploadArtifactPin);

Check failure on line 23 in test/upload-artifact-node24-integrity.test.ts

View workflow job for this annotation

GitHub Actions / verify

test/upload-artifact-node24-integrity.test.ts > upload-artifact Node 24 supply-chain contract > .github/workflows/maintainer-app-readiness.yml pins the reviewed Node 24 upload action

AssertionError: expected 'name: maintainer-app-readiness\nrun-n…' to contain 'actions/upload-artifact@043fb46d1a93c…' - Expected + Received - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + name: maintainer-app-readiness + run-name: Noema Maintainer App pre-activation audit + + on: + # repository_dispatch is evaluated only from the default branch. A caller + # cannot select unreviewed workflow code for these privileged token mints. + repository_dispatch: + types: [maintainer-app-readiness] + + concurrency: + group: noema-maintainer-app-readiness + cancel-in-progress: true + + # GITHUB_TOKEN is used only by the trusted checkout. Audit API calls use the + # repository-scoped Maintainer token; the Reviewer token is never exposed to a + # script and supplies only authenticated App slug/installation identity output. + permissions: + contents: read + + jobs: + preflight: + name: maintainer-app-pre-activation-audit + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + steps: + - name: checkout event-bound default-branch commit + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + # For repository_dispatch, github.sha is the default-branch commit + # bound when the event was created. Do not re-resolve a moving branch. + ref: ${{ github.sha }} + persist-credentials: false + + - name: mint repository-scoped Maintainer App token + id: maintainer_app + continue-on-error: true + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ vars.NOEMA_MAINTAINER_APP_CLIENT_ID }} + private-key: ${{ secrets.NOEMA_MAINTAINER_APP_PRIVATE_KEY }} + owner: ContextualWisdomLab + repositories: noema + permission-actions: read + permission-checks: read + permission-contents: write + permission-metadata: read + permission-pull-requests: write + permission-statuses: read + + - name: mint repository-scoped Reviewer App identity token + id: reviewer_app + continue-on-error: true + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ vars.NOEMA_GITHUB_APP_CLIENT_ID }} + private-key: ${{ secrets.NOEMA_GITHUB_APP_PRIVATE_KEY }} + owner: ContextualWisdomLab + repositories: noema + permission-metadata: read + + - name: setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "24.19.0" + + - name: verify Node.js runtime + shell: bash + run: | + set -euo pipefail + test "$(node --version)" = "v24.19.0" + + - name: audit active main governance + id: governance + continue-on-error: true + env: + GH_TOKEN: ${{ steps.maintainer_app.outputs.token }} + NOEMA_GOVERNANCE_AUDIT_PATH: ${{ runner.temp }}/noema-maintainer-app-readiness/main-governance-audit.json + run: node scripts/main-governance-audit.mjs + + - name: audit effective Maintainer App identity and access + id: readiness + if: always() + continue-on-error: true + env: + DELEGATED_MAINTAINER_TOKEN: ${{ steps.maintainer_app.outputs.token }} + NOEMA_MAINTAINER_APP_SLUG: ${{ steps.maintainer_app.outputs.app-slug }} + NOEMA_MAINTAINER_INSTALLATION_ID: ${{ steps.maintainer_app.outputs.installation-id }} + NOEMA_REVIEWER_APP_SLUG: ${{ steps.reviewer_app.outputs.app-slug }} + NOEMA_REVIEWER_INSTALLATION_ID: ${{ steps.reviewer_app.outputs.installation-id }} + NOEMA_REVIEWER_LOGIN: ${{ vars.NOEMA_REVIEWER_LOGIN }} + NOEMA_MAINTENANCE_ENABLED: ${{ vars.NOEMA_MAINTENANCE_ENABLED }

Check failure on line 23 in test/upload-artifact-node24-integrity.test.ts

View workflow job for this annotation

GitHub Actions / verify

test/upload-artifact-node24-integrity.test.ts > upload-artifact Node 24 supply-chain contract > .github/workflows/hourly-product-development.yml pins the reviewed Node 24 upload action

AssertionError: expected 'name: Hourly NVIDIA NIM Product Devel…' to contain 'actions/upload-artifact@043fb46d1a93c…' - Expected + Received - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + name: Hourly NVIDIA NIM Product Development + + on: + workflow_dispatch: + inputs: + dry_run: + description: Evaluate the gate and task contract without running OpenCode + required: false + default: false + type: boolean + schedule: + - cron: "47 * * * *" + + concurrency: + group: hourly-nim-product-development-${{ github.repository }} + cancel-in-progress: false + + permissions: + contents: read + + env: + DEFAULT_BRANCH: main + OPENCODE_VERSION: "1.17.13" + OPENCODE_SHA256: 157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348 + OPENCODE_MODEL_CANDIDATES: >- + nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5 + nvidia-nim/nvidia/nemotron-3-super-120b-a12b + nvidia-nim/deepseek-ai/deepseek-v4-pro + # Three candidate budgets and two inter-candidate cleanup reinstalls fit in 55 minutes. + OPENCODE_RUN_TIMEOUT_SECONDS: "900" + OPENCODE_KILL_GRACE_SECONDS: "30" + DEPENDENCY_REINSTALL_TIMEOUT_SECONDS: "60" + DEPENDENCY_REINSTALL_KILL_GRACE_SECONDS: "10" + MAX_CHANGED_FILES: "40" + MAX_DIFF_BYTES: "500000" + MAX_PR_TITLE_BYTES: "120" + MAX_PR_BODY_BYTES: "20000" + + jobs: + propose_product_increment: + if: github.repository == 'ContextualWisdomLab/noema' + runs-on: ubuntu-latest + timeout-minutes: 55 + permissions: + contents: read + pull-requests: read + outputs: + dispatch: ${{ steps.gate.outputs.dispatch }} + reason: ${{ steps.gate.outputs.reason }} + has_changes: ${{ steps.proposal.outputs.has_changes }} + base_sha: ${{ steps.base.outputs.base_sha }} + patch_sha256: ${{ steps.proposal.outputs.patch_sha256 }} + changed_files: ${{ steps.proposal.outputs.changed_files }} + diff_bytes: ${{ steps.proposal.outputs.diff_bytes }} + artifact_id: ${{ steps.upload_proposal.outputs.artifact-id }} + artifact_digest: ${{ steps.upload_proposal.outputs.artifact-digest }} + env: + DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false }} + steps: + - name: Enforce zero-open-PR single-flight gate + id: gate + shell: bash + env: + GH_TOKEN: ${{ github.token }} + NIM_CONFIGURED: ${{ secrets.NVIDIA_NIM_API_KEY != '' }} + MAINTAINER_APP_CLIENT_ID_CONFIGURED: ${{ vars.NOEMA_MAINTAINER_APP_CLIENT_ID != '' }} + MAINTAINER_APP_PRIVATE_KEY_CONFIGURED: ${{ secrets.NOEMA_MAINTAINER_APP_PRIVATE_KEY != '' }} + run: | + set -euo pipefail + + if ! open_prs="$( + gh pr list \ + --repo "$GITHUB_REPOSITORY" \ + --state open \ + --limit 1 \ + --json number,url + )"; then + { + echo "dispatch=false" + echo "reason=pull_request_inventory_unavailable" + } >>"$GITHUB_OUTPUT" + echo "Pull-request inventory was unavailable; development failed closed." \ + >>"$GITHUB_STEP_SUMMARY" + exit 0 + fi + + if [ "$(jq 'length' <<<"$open_prs")" -gt 0 ]; then + { + echo "dispatch=false" + echo "reason=open_pull_request" + } >>"$GITHUB_OUTPUT" + echo "An open pull request exists; exact-head PR governance owns this hour." \ + >>"$GITHUB_STEP_SUMMARY" + exit 0 + fi + + if [ "$NIM_CONFIGURED" != "true" ] && [ "$DRY_RUN" != "true" ]; then + { + echo "dispatch=false" + echo "reason=nim_api_key_unavailable" + } >>"$GITHUB_OUTPUT" + echo "Autonomous development is disabled because the dedicated NVIDIA NIM secret is unavailable." \ + >>"$GITHUB_STEP_SUMMARY" +

Check failure on line 23 in test/upload-artifact-node24-integrity.test.ts

View workflow job for this annotation

GitHub Actions / verify

test/upload-artifact-node24-integrity.test.ts > upload-artifact Node 24 supply-chain contract > .github/workflows/central-review.yml pins the reviewed Node 24 upload action

AssertionError: expected 'name: central-review\nrun-name: >-\n …' to contain 'actions/upload-artifact@043fb46d1a93c…' - Expected + Received - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + name: central-review + run-name: >- + Noema central review ${{ github.event.client_payload.target_repository }}#${{ + github.event.client_payload.pr_number }}@${{ github.event.client_payload.pr_head_sha }} + + on: + # repository_dispatch is evaluated only from the default branch. Keeping the + # privileged entrypoint here prevents a caller from selecting branch workflow + # code before the Noema App key and model credentials are bound. + repository_dispatch: + types: [noema-review] + + concurrency: + group: >- + noema-central-review-${{ github.event.client_payload.target_repository }}-${{ + github.event.client_payload.pr_number }} + cancel-in-progress: true + + permissions: + contents: read + + jobs: + collect_evidence: + name: noema-evidence-collection + runs-on: ubuntu-latest + timeout-minutes: 180 + permissions: + contents: read + outputs: + repository_name: ${{ steps.target.outputs.repository_name }} + head_sha: ${{ steps.target.outputs.head_sha }} + env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + TARGET_REPOSITORY: ${{ github.event.client_payload.target_repository || '' }} + PR_NUMBER: ${{ github.event.client_payload.pr_number || '' }} + EXPECTED_HEAD_SHA: ${{ github.event.client_payload.pr_head_sha || '' }} + NOEMA_CODEGRAPH_SANDBOX_SOURCE_IMAGE: gcr.io/distroless/nodejs24-debian13:nonroot + steps: + - name: Validate target repository identifier + id: target + run: | + set -euo pipefail + if ! [[ "$TARGET_REPOSITORY" =~ ^ContextualWisdomLab/[A-Za-z0-9_.-]+$ ]] || + ! [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]] || + ! [[ "$EXPECTED_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]]; then + echo "::error::Noema dispatch requires a ContextualWisdomLab repository, positive PR number, and full expected head SHA." + exit 1 + fi + repository_name="${TARGET_REPOSITORY#*/}" + printf 'repository_name=%s\nhead_sha=%s\n' "$repository_name" "$EXPECTED_HEAD_SHA" >>"$GITHUB_OUTPUT" + + - name: Mint read-only repository-scoped Noema App token + id: noema_read_app + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ vars.NOEMA_GITHUB_APP_CLIENT_ID }} + private-key: ${{ secrets.NOEMA_GITHUB_APP_PRIVATE_KEY }} + owner: ContextualWisdomLab + repositories: ${{ steps.target.outputs.repository_name }} + permission-actions: read + permission-checks: read + permission-contents: read + permission-metadata: read + permission-pull-requests: read + permission-security-events: read + permission-statuses: read + permission-vulnerability-alerts: read + + - name: Bind dispatch to live organization PR head + env: + GH_TOKEN: ${{ steps.noema_read_app.outputs.token }} + run: | + set -euo pipefail + pr_json="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")" + state="$(jq -r '.state // empty' <<<"$pr_json")" + live_head="$(jq -r '.head.sha // empty' <<<"$pr_json")" + head_repo="$(jq -r '.head.repo.full_name // empty' <<<"$pr_json")" + base_repo="$(jq -r '.base.repo.full_name // empty' <<<"$pr_json")" + if [ "$state" != "open" ] || + [ "$live_head" != "$EXPECTED_HEAD_SHA" ] || + [ "$head_repo" != "$TARGET_REPOSITORY" ] || + [ "$base_repo" != "$TARGET_REPOSITORY" ]; then + printf '::error::Noema dispatch metadata is stale or untrusted: state=%s expected_head=%s live_head=%s head_repo=%s base_repo=%s.\n' \ + "${state:-missing}" "$EXPECTED_HEAD_SHA" "${live_hea
expect(workflow).not.toContain(deprecatedUploadArtifactPin);
expect(workflow).not.toMatch(/uses:\s+actions\/upload-artifact@v\d+/);
});
}
});
Loading