Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 149 additions & 11 deletions .github/workflows/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,169 @@
= GitHub Workflows — what runs, and why some look duplicated

This directory holds the repo's CI/CD. A few workflows *look* like they overlap
but are deliberately distinct — documented here so the apparent duplication is
not "tidied away" into a real coverage gap.
but are deliberately distinct — documented here so apparent duplication is not
"tidied away" into a real coverage gap.

== Hypatia runs in two places (on purpose)

* `hypatia-scan.yml` — the **standalone security scan** (push / PR / weekly).
Independent; this is the repo's own Hypatia coverage.
* `static-analysis-gate.yml` -> `hypatia-scan` job — runs Hypatia as part of the
**gate**, then the `deposit-findings` job hands the results to the
**gitbot-fleet learning** pipeline. This job is also a *required status check*.
**gate**, then the `deposit-findings` job hands results to the gitbot-fleet
learning pipeline. Its live required-check status needs owner verification.

Same tool, two different consumers (security scan vs fleet learning). Removing
either loses real function — keep both.
Same tool, two consumers. Removing either loses real function — keep both.

== Secret scanning is single-sourced

`secret-scanner.yml` calls the standards reusable (gitleaks + a Rust-secrets
check). An inline TruffleHog job was removed: the reusable deliberately retired
TruffleHog as redundant with gitleaks, so re-adding it was duplicated work, not
extra coverage.
`secret-scanner.yml` calls the standards reusable, which runs gitleaks, a Rust
secret check, and a shell secret check. Its `scan` job preserves the required
GitHub Actions context `scan / gitleaks` (app ID `15368`). TruffleHog was
removed from the reusable as redundant; do not re-add an overlapping scan
without identifying coverage it supplies.

The runs through PR #48 head `f6e6731` failed before any jobs were created.
The https://github.com/hyperpolymath/vocarium/actions/runs/41199621947[run annotation]
says the called workflow was not found. `hyperpolymath/standards` redirects to
`metadatastician/standards`, but GitHub Actions does not follow redirects for
reusable workflows. After the owner permitted the canonical name at the old
commit, the next run created the required context but all three scanning jobs
failed at setup: the old reusable's *own* lockfile records the checkout ref as
its commit SHA, which GitHub rejects as an invalid lockfile pin. The caller's
successful lock verification does not cover the remote reusable's dependencies.

The caller now pins a newer standards commit with checkout's lock ref recorded
as `v7.0.1` against the same checkout SHA. The newer reusable needs only
`contents: read`, has no secret expressions, gates both a working-tree and a
git-history scan, and fetches its estate baseline at the reusable's pinned SHA
rather than `main`. Its baseline includes upstream allowlist rules, and deleted
AsciiDoc content is not covered by the separate AsciiDoc working-tree pass.
The repository's Actions allowlist must permit the *new exact pin* as well.
The https://github.com/hyperpolymath/vocarium/actions/runs/41220900235[first run]
using it was rejected by the effective Actions policy; recheck the saved pattern
and allow time for settings to propagate. A real hosted run must confirm the
canonical reference, upstream lock, and actual scans work; `merge_group` is
wired in preparation for a later queue canary, not yet proven.

The same retired `hyperpolymath/standards` owner appears in other reusable
callers (`governance`, `hypatia-scan`, `mirror`, `rust-ci`, and `scorecard`).
Those workflows need separate review and hosted verification; fixing the
secret scanner does not repair them.

== SonarCloud: automatic analysis only

The project is `hyperpolymath_vocarium` in organization `hyperpolymath`.
On 2026-10-31 the public
https://sonarcloud.io/api/settings/values?component=hyperpolymath_vocarium&keys=sonar.autoscan.enabled,sonar.project.monorepo.enabled[project settings]
reported `sonar.autoscan.enabled=true` and monorepo mode disabled. The official
GitHub app is `sonarqubecloud` (app ID `12526`). SonarCloud documents automatic
analysis for the default branch and PRs, including forks:
https://docs.sonarsource.com/sonarqube-cloud/analyzing-source-code/automatic-analysis[automatic analysis] and
https://docs.sonarsource.com/sonarqube-cloud/analyzing-source-code/ci-based-analysis/github-actions-for-sonarcloud[fork PRs].

The official check for PR #47, commit
`748cf83de60de9cc9b968d38c187a7330183b2e2`, was
https://github.com/hyperpolymath/vocarium/runs/124289772397[124289772397]:
`SonarCloud Code Analysis`, success, zero new issues. The separate Actions
scanner https://github.com/hyperpolymath/vocarium/actions/runs/41121896614/job/124289694405[124289694405]
failed with exit 3 and a missing-`SONAR_TOKEN` warning; its complete final
scanner error was not retrieved. These are duplicate *attempts/reporting*, not
proof that two analyses completed or that the scanner failed due to findings.
The official app also analyzed `main` commit
`297bdd98156f621ee95aa57e20290fbe948a7027` while the Actions scanner had a
startup failure. Real findings must not be ignored: the official gate on
https://github.com/hyperpolymath/vocarium/runs/117203725307[an earlier main commit]
failed its new-code security rating; the 2026-10-27 main analysis reported
21 vulnerabilities, independently of the PR #47 result.

[cols="2,3,3",options="header"]
|===
| Event | Route in `sonarqube.yml` | Coverage / review boundary

| PR targeting `main` (including forks)
| The `SonarQube` Actions job verifies the official app's exact *PR head* SHA;
it never receives a scanner secret or checks out PR code.
| Same-repository PRs are observed. SonarCloud documents fork support, but
no vocarium fork PR canary has been observed. The verifier fails closed if
the result or permission is absent; qualify a real fork before rollout.

| Push to `main`
| Verify the official app's exact push SHA.
| Observed on main, including independent success and failure results.

| Other branches and manual dispatch
| No trigger or CI scanner.
| The owner selected `main` only and retired the legacy manual / non-main
route. A dispatch would not itself trigger a fresh automatic analysis.

| Merge queue (`merge_group`)
| No trigger, as before.
| Neither a synthetic merge-group analysis nor its official receipt has been
qualified. Do not substitute a PR-head result or a skipped/success job for
the queue SHA; qualify an actual queue candidate before requiring this check.
|===

The pinned `cicd-suite` verifier checks the latest official app check for the
exact SHA and rejects missing, pending, skipped, stale, wrong-app, and failing
results. The consumer also checks the official receipt's project and PR/main
URL, preventing a successful result for a different Sonar project or PR from
being substituted. Its start time must be strictly after the PR update or push
event timestamp, with a valid completion at or after its start; missing
timestamps and same-second starts fail closed. This prevents an older same-SHA
check, including one still running, from passing before a new check appears.
GitHub timestamps have only second precision and do not prove which base
revision or server-side configuration Sonar analyzed; a check that starts too
close to the event may need a fresh analysis and workflow rerun. Neither check
proves rules, coverage, current base-branch analysis, or entitlement. A new run
on the same SHA can supersede a prior result; a newer pending run is not a pass.
The five-minute wait is bounded and an unavailable result fails rather than
launching an extra scanner or becoming green.

`sonar-project.properties` is retained as dormant CI-scanner configuration.
Automatic analysis ignores it; its exclusions are *not* evidence of the active
automatic-analysis scope. Review the SonarCloud project settings and actual
findings before changing scope. In particular, do not copy those exclusions into
`.sonarcloud.properties` merely to make a check pass. Automatic analysis does
not import coverage or external reports. SonarCloud explicitly
https://docs.sonarsource.com/sonarqube-cloud/analyzing-source-code/ci-based-analysis/overview-of-integrated-cis[does not support simultaneous automatic and CI-based analysis]
of the same project. If CI analysis is ever reintroduced, first choose a
compatible analysis method and confirm main/PR coverage is not lost. Do not
enable a privileged `pull_request_target` scan of untrusted PR code.

=== Rollout, branch protection, and organization / queue plan

* The Actions job keeps its existing `SonarQube` context and the official
`SonarCloud Code Analysis` app check remains separate. The visible active
rules for `main` required `scan / gitleaks` (GitHub Actions app `15368`),
not a Sonar context, on 2026-10-31. The branch-protection API returned 403,
so the owner must also inspect any classic/organization protection and
app-bound required contexts before merging or changing them. The checked-in
`.github/settings.yml` declares other contexts and is not proof of live state.
* Before qualifying forks, open a real fork PR against `main` containing this
candidate workflow. Confirm that both the official check and `SonarQube`
refer to the fork PR's exact head SHA and this project, without a secret;
push a second commit and confirm the older success cannot satisfy it.
Record the check IDs. Repeat when project permissions or analysis mode change.
* GitHub's native https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue[merge queue]
is available for organization-owned public repositories. `hyperpolymath/vocarium`
is currently user-owned. The owner prefers a future organization move; this
PR does not transfer the repository or enable a queue. Plan the organization,
access policies, GitHub Apps, branch rules, and project migration separately.
The verifier deliberately binds `GITHUB_REPOSITORY` to `hyperpolymath/vocarium`:
after any transfer, update and retest that binding and the Sonar project/app
identity rather than assuming old receipts or project keys remain valid.
* Before enabling a queue, verify all required check identities and run a real
`merge_group` canary. Confirm `scan / gitleaks` checks out and scans the exact
synthetic SHA with a completed, non-skipped result. The trigger alone is not
evidence. If a Sonar context is required for queue candidates, first obtain
an appropriately scoped analysis and official receipt for the exact queue
SHA, or explicitly review a different analysis design; the current automatic
route has not been qualified for merge groups.

== SAST tools are complementary, not redundant

* `codeql.yml` — CodeQL (matrix defaults to `actions`; every repo has workflows).
* `sonarqube.yml` — SonarCloud (shell / JS surface; see `sonar-project.properties`).
* `sonarqube.yml` — verifies SonarCloud automatic analysis for main / PRs.
* `static-analysis-gate.yml` — panic-attack + Hypatia gate (see above).

Each targets a different language/surface; together they cover what no single
Expand Down
21 changes: 14 additions & 7 deletions .github/workflows/actions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ workflows:
- 'actions/checkout@v7.0.1'
'.github/workflows/rust-ci.yml': []
'.github/workflows/scorecard.yml': []
'.github/workflows/secret-scanner.yml': []
'.github/workflows/secret-scanner.yml':
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
'.github/workflows/security-policy.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/sonarqube.yml':
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'actions/checkout@v7.0.1'
- 'sonarsource/sonarqube-scan-action@v8.2.1'
- 'hyperpolymath/cicd-suite@4404c3c0474e17753fe7689f3485c02890aac113'
'.github/workflows/static-analysis-gate.yml':
- 'actions/checkout@v7.0.1'
- 'actions/download-artifact@v8.0.2'
Expand All @@ -76,6 +78,11 @@ dependencies:
commit: 'sha1-508db95dd578ae2727ebd6217d5ba78e4fbda05d'
owner_id: 44036562
repo_id: 760701061
'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1':
ref: 'v7.0.1'
commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1'
owner_id: 44036562
repo_id: 197814629
'actions/checkout@v7.0.1':
ref: 'v7.0.1'
commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1'
Expand Down Expand Up @@ -128,6 +135,11 @@ dependencies:
commit: 'sha1-6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee'
owner_id: 9919
repo_id: 259445878
'hyperpolymath/cicd-suite@4404c3c0474e17753fe7689f3485c02890aac113':
ref: 'main'
commit: 'sha1-4404c3c0474e17753fe7689f3485c02890aac113'
owner_id: 6759885
repo_id: 1326697643
'mlugg/setup-zig@v2.2.1':
ref: 'v2.2.1'
commit: 'sha1-d1434d08867e3ee9daa34448df10607b98908d29'
Expand All @@ -143,8 +155,3 @@ dependencies:
commit: 'sha1-efb35369e0ad2afab669f228072c1b0d510eae64'
owner_id: 2242
repo_id: 204253808
'sonarsource/sonarqube-scan-action@v8.2.1':
ref: 'v8.2.1'
commit: 'sha1-22918119ff8e1ca75a623e15c8296b6ea4fbe28f'
owner_id: 545988
repo_id: 366408409
35 changes: 21 additions & 14 deletions .github/workflows/secret-scanner.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
# This workflow is managed by gh actions-lock.
# SPDX-License-Identifier: MPL-2.0
# This workflow is managed by gh actions-lock.
name: Secret Scanner
on:
pull_request:
push:
branches: [main]
# Preparation only: a real merge-group canary is required before rollout.
merge_group:
types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: read
contents: read
# Single secret scanner. The standards reusable runs gitleaks (+ a Rust-secrets
# check). An inline TruffleHog job previously lived here, but the reusable
# DELIBERATELY retired TruffleHog as redundant (gitleaks gives sufficient
# coverage at lower cost — see the reusable's header). Re-adding it was
# duplicated work, not extra coverage, so it has been removed. See
# .github/workflows/README.adoc.
permissions: {}
jobs:
# Preserve the required GitHub Actions context `scan / gitleaks`.
# The old owner redirects, which Actions does not support for reusables.
# The old commit's own lock rejects checkout at job setup; this newer pin has
# a valid checkout lock and retains gating scans, including full git history.
scan:
permissions:
contents: read
pull-requests: write
actions: read
uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@84355587cb2a1f86e6882de83514a32db2646e7a
secrets: inherit
uses: metadatastician/standards/.github/workflows/secret-scanner-reusable.yml@8d1a2aab4211493cf42f147f2080f024605797dc
scanner-contract:
name: Secret scanner contract tests
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Test required context and event wiring
run: bash tests/workflows/secret_scanner_test.sh
Loading
Loading