chore: infra hardening — CodeQL fix, SLSA L3, multi-arch Docker, action pins, NTC cleanup#8
Draft
navidrast wants to merge 7 commits intochore/public-readiness-p0from
Draft
Conversation
CodeQL has failed on every run (5/5 recent) on main. Two compounding
causes: (a) the workflow runs `flutter build web --release` before
autobuild, which occasionally fails or times out; (b) the `app/embed.go`
`//go:embed all:build/web` target is empty without a prior Flutter
build, so `go build` (and therefore CodeQL autobuild) can't compile.
Fix:
- Drop the Flutter build step — CodeQL only scans Go.
- Replace it with a one-liner that seeds `app/build/web/index.html`
as a placeholder so `//go:embed` resolves and `go build` succeeds.
- Pin the three github/codeql-action steps to v3.35.2 instead of the
floating `v3` major, eliminating tag-drift risk.
Note: the CodeQL SARIF upload step ALSO requires GitHub Advanced
Security to be enabled on the repo (currently off for private repos
on the free plan; free automatically once the repo is public, or
via the Pro plan for private). Enabling AS is a repo-settings action
tracked separately (G9-05 in the public-readiness plan).
Closes C8-01 from the 8/10 action plan; partial progress on S8-02.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: RCC Bot <rcc@localhost>
go.mod, ci.yml, codeql.yml, and release.yml all pin Go 1.25, but the Docker image + Gitea deploy workflow were still on older toolchains: - Dockerfile:8 was on golang:1.24-bookworm - .gitea/workflows/deploy.yml:23 was on go1.22.5 Bumps both to match go.mod. Eliminates the risk of a release binary being built with a toolchain that's missed patch-level CVE fixes released between 1.22 → 1.25, and keeps Docker image output byte-comparable with the binaries produced by the main release pipeline. Closes C8-02 / S8-06 / X-02 from the 8/10 action plan. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: RCC Bot <rcc@localhost>
Three workflows (ci.yml, dco.yml, tag-protection.yml) had no explicit permissions block, which means the GITHUB_TOKEN defaulted to repo-wide write access. That's substantially broader than what any of them need, and OSSF Scorecard's Token-Permissions check rightly flags it. Minimal scopes per workflow: - ci.yml → contents: read + id-token: write (for Codecov OIDC) - dco.yml → contents: read + pull-requests: read + checks: write - tag-protection.yml → contents: read (actor-allowlist check only) release.yml, release-please.yml, docker.yml, codeql.yml already had correct permissions blocks — not touched. No behaviour change. If any step needs elevated scope in the future, grow the block deliberately rather than relying on the wide-open default. Closes C8-03 / S8-01 / X-03 from the 8/10 action plan. Should move OSSF Scorecard Token-Permissions from fail → pass. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: RCC Bot <rcc@localhost>
Two small additions that move the release pipeline from "signed checksums" to full SLSA L3 supply-chain posture. 1. actions/attest-build-provenance@v4.1.0 runs after goreleaser, one attestation per release archive (dist/opendray_*.tar.gz). Emits an in-toto statement that binds binary → commit → workflow run, verifiable downstream with `gh attestation verify` or the sigstore transparency log. Requires `attestations: write` on the workflow token, added to the permissions block. 2. .goreleaser.yml gains an explicit `checksum:` section. Produces `dist/SHA256SUMS` which install.sh already expects (and the cosign sign step already signs). The file existed implicitly in goreleaser defaults, but making it explicit eliminates the risk of a future goreleaser version changing the default name. Closes C8-05 / C8-06 / S8-03 / S8-07 / X-04 from the 8/10 action plan. Expected Scorecard impact: SLSA check moves from FAIL to PASS on the next tag; Signed-Releases remains PASS. Total bump projected +2 on the Scorecard score. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: RCC Bot <rcc@localhost>
Docker image previously shipped amd64-only. Apple Silicon users,
Raspberry Pi, AWS Graviton, and ARM-based VPSes were left with either
"exec format error" or a forced manual rebuild.
Changes:
- Add docker/setup-qemu-action@v3 + docker/setup-buildx-action@v4.0.0
as prerequisites for multi-platform builds.
- Set `platforms: linux/amd64,linux/arm64` on build-push-action. The
resulting manifest list covers both architectures under the same
tag; `docker pull` auto-selects per host.
- Turn on GHA layer caching (`cache-from: type=gha` + `cache-to:
type=gha,mode=max`) to amortise the Flutter + Go toolchain download
across release runs. Expected ~2–3 min saved per tag.
- Also pin `github/codeql-action/upload-sarif` to v3.35.2 for
consistency with codeql.yml.
Closes C8-04 / X-11 from the 8/10 action plan.
Goreleaser archive platforms already cover linux + darwin × amd64 +
arm64, so this closes the "docker pull" parity gap with direct binary
installs.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: RCC Bot <rcc@localhost>
Supply-chain hardening: every non-actions/*, non-github/* third-party action is now pinned to a patch tag so upstream can't silently change behaviour between runs. The existing trivy-action and tim-actions/dco pins (PR #6) already followed this rule; this extends it everywhere. Pinned (major → patch): - subosito/flutter-action v2 → v2.23.0 - goreleaser/goreleaser-action v6 → v6.4.0 - sigstore/cosign-installer v3 → v3.10.1 - anchore/sbom-action v0 → v0.24.0 - codecov/codecov-action v4 → v4.6.0 - docker/setup-qemu-action v3 → v3.7.0 - docker/login-action v3 → v3.7.0 - docker/metadata-action v5 → v5.10.0 - docker/build-push-action v6 → v6.19.2 - googleapis/release-please-action v4 → v4.4.1 - pozil/auto-assign-issue v2 → v2.2.0 Left at major (first-party from trusted maintainers per Scorecard guidance — these orgs don't rewrite tags): - actions/checkout, actions/setup-go, actions/upload-artifact, actions/download-artifact, actions/labeler - github/codeql-action/* already pinned to v3.35.2 in the CodeQL and Docker commits in this PR. Expected Scorecard impact: Pinned-Dependencies moves from partial to near-complete. Combined with the other commits in this PR, projected OSSF Scorecard jump: ~7/17 → ~11/17. Closes S8-04 / X-05 from the 8/10 action plan. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: RCC Bot <rcc@localhost>
Anomaly sweep uncovered three user-visible bugs and three cosmetic
leftovers from the project's earlier NTC name. All are pure string
changes — no business logic, no API, no config-format shifts.
User-visible bugs (3):
1. plugins/builtin/telegram/manifest.json — configSchema declared
`envVar: NTC_TELEGRAM_BOT_TOKEN` but the Go fallback at
gateway/telegram/manager.go:219 reads OPENDRAY_TELEGRAM_BOT_TOKEN.
Operators following the manifest's documented env var got silent
no-op with no error signal. Manifest now matches code.
2. app/web/manifest.json — was the pristine Flutter-create template:
name "ntc", short_name "ntc", description "A new Flutter project.",
background+theme colour #0175C2 (Flutter blue). Every browser's
"Install this app" prompt, every installed PWA, every splash screen
showed "ntc". Rewritten with product name + tagline + brand palette
(#0B1120 background, #0EA5E9 accent from opendray.dev site).
3. app/web/index.html — HTML title, Apple mobile web-app title, and
meta description were all still "ntc" / "A new Flutter project.".
Affects browser tab text and iOS "Add to Home Screen" app name.
Cosmetic (3):
4. plugins/builtin/opencode/manifest.json — config description said
"Path to the opencode binary on the NTC host." → "OpenDray host".
5. gateway/simulator.go — iOS simulator screenshot temp path was
/tmp/ntc_sim_%d.png → /tmp/opendray_sim_%d.png. Verified no other
file reads or references this path; lifetime is within a single
function call (create → exec xcrun → read → defer os.Remove).
6. app/android/app/src/main/AndroidManifest.xml — `android:label`
was lowercase "opendray"; iOS CFBundleDisplayName + Flutter
MaterialApp.title are both "OpenDray". Capitalised for platform
parity; Android home-screen + app drawer now match iOS display.
Not touched (deliberate):
- SQL migration comments in kernel/store/migrations/006, 008
(historical context, no user visibility)
- gateway/docs/forge.go comment example path
- docs/plugin-platform/M3-RELEASE.md lineage notes
(rcc → ntc → opendray — intentional provenance documentation)
- Go module path github.com/opendray/opendray (modules case-
sensitive; lowercase is correct)
Verification:
- go build ./... — clean
- go vet ./... — clean
- all three JSON files re-parse cleanly
- diff: 6 files, +13/-13 lines
No test changes required; existing tests pass without modification.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: RCC Bot <rcc@localhost>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Seven commits that close P0 / P1 items from the public-readiness audit. Every change lands in workflow, Docker, release config, plugin manifests, or PWA metadata — zero business-logic code touched, zero API contracts changed, zero data-format shifts.
Chained on top of PR #6 (
chore/public-readiness-p0as base). Once #6 merges, retarget this PR tomainwithgh pr edit <N> --base main.Commits (top-down, each independently reviewable)
fix(ci): unbreak CodeQL by removing Flutter build + pinning to v3.35.2CodeQL has failed 5/5 recent runs on main. Two compounding causes: Flutter build step + ambiguous
@v3pin. Replace the Flutter build with a single-lineapp/build/web/index.htmlplaceholder (so//go:embed all:build/webresolves forgo build) and pin the three codeql-action steps tov3.35.2. Note: SARIF upload also requires GitHub Advanced Security to be enabled on the repo settings — that's a parallel admin action.chore(ci): align Go toolchain version to 1.25.6 everywherego.mod and all GitHub workflows were on 1.25. Dockerfile was on 1.24 and Gitea deploy on 1.22.5. Release binaries were built with a patch-lagged toolchain. Bump to 1.25.
chore(ci): add least-privilege permissions blocks to unscoped workflowsci.yml / dco.yml / tag-protection.yml had no explicit
permissions:block → GITHUB_TOKEN defaulted to repo-wide write. Add minimal scoped blocks. Expected OSSF Scorecard impact: Token-Permissions moves from fail to pass.feat(release): SLSA L3 provenance attestation + SHA256SUMS checksumsAdd
actions/attest-build-provenance@v4.1.0after goreleaser → every release archive carries an.intoto.jsonlattestation binding binary ← commit ← workflow run. Also make the goreleaserchecksum:section explicit (SHA256SUMS) soinstall.sh's existing SHA-256 verify path has a guaranteed file name.feat(docker): multi-arch image (linux/amd64 + linux/arm64) via buildxDocker image shipped amd64-only → "exec format error" on Apple Silicon, Raspberry Pi, ARM VPS. Add
docker/setup-qemu-action+docker/setup-buildx-action@v4.0.0, setplatforms: linux/amd64,linux/arm64, turn on GHA layer cache (~2-3 min saved per tag).chore(ci): pin third-party actions to tagged patch versionsEvery non-
actions/*, non-github/*third-party action pinned to a patch tag. Covers subosito/flutter-action, goreleaser-action, sigstore/cosign-installer, anchore/sbom-action, codecov-action, docker/setup-qemu, docker/login, docker/metadata, docker/build-push, googleapis/release-please, pozil/auto-assign-issue.actions/*left at major per Scorecard guidance (trusted first-party).fix: rename remaining NTC leftovers + replace Flutter template defaultsAnomaly sweep found six string-only leftovers — three user-visible bugs, three cosmetic:
plugins/builtin/telegram/manifest.jsondeclaredenvVar: NTC_TELEGRAM_BOT_TOKENbut the Go fallback readsOPENDRAY_TELEGRAM_BOT_TOKEN→ silent no-op for users following documented env var. Manifest now matches code.app/web/manifest.jsonwas the pristine Fluttercreatetemplate (name: "ntc",description: "A new Flutter project.", Flutter-blue theme) → rewritten with product name, tagline, brand palette.app/web/index.htmlsame — HTML<title>, iOS web-app-title, meta description all said "ntc" → now "OpenDray".plugins/builtin/opencode/manifest.jsondescription: "NTC host" → "OpenDray host".gateway/simulator.goiOS screenshot temp path:/tmp/ntc_sim_*.png→/tmp/opendray_sim_*.png. Verified single write site + same-function read+delete; zero external dependency.android:label:"opendray"(lowercase) →"OpenDray"to match iOSCFBundleDisplayName.Intentionally NOT touched: SQL migration comments, Go comment example paths,
docs/plugin-platform/M3-RELEASE.mdlineage notes — these are archival / historical context with no user visibility. Go module pathgithub.com/opendray/opendraystays lowercase (Go modules case-sensitive; current is correct).Scope audit (what this PR does NOT touch)
.gobusiness-logic codeconfig.toml,.env, plugin-config DB entries still work)Test plan
go build ./...cleango vet ./...clean-racetest suite — no regressions (known pre-existing flakyTestRunner_EchoSucceedswas fixed upstream on main; 3 "failing" test suites earlier flagged were environmental, all pass with clean env)app/web/manifest.json,plugins/builtin/{telegram,opencode}/manifest.json) re-parse as valid JSONSHA256SUMS,.intoto.jsonlattestations, multi-arch Docker manifest (verify:docker manifest inspect ghcr.io/opendray/opendray:<tag>shows amd64 + arm64)Projected OSSF Scorecard impact
*SAST pass conditional on Advanced Security being enabled in repo settings.
Related
/mnt/nas/OpenDray/8-of-10-action-plan.md.Merge strategy
Rebase and merge — each commit has a distinct Conventional-Commit prefix that release-please will parse into individual CHANGELOG entries. Do NOT squash (would flatten 7 meaningful entries into 1).
🤖 Generated with Claude Code