Logs the full output of the 9-agent deep-dive run on 2026-05-05 to
docs/research/2026-05-05-agent-wave/. Pulls every actionable finding
into one indexed location so v0.5.32 planning has a paper trail.
Files:
docs/research/2026-05-05-agent-wave/README.md — index
docs/research/2026-05-05-agent-wave/01-...real-hardware.md — Plymouth + LUKS edge cases
docs/research/2026-05-05-agent-wave/02-...firstboot-ux.md — SDDM + first-boot UX
docs/research/2026-05-05-agent-wave/03-...spike-plan.md — bootc-image-builder 1-week spike
docs/research/2026-05-05-agent-wave/04-...tier-2.md — AppArmor + nftables + audit + homed
docs/research/2026-05-05-agent-wave/05-...launch.md — threat model + v0.7 launch checklist
docs/research/2026-05-05-agent-wave/06-...log-capture.md — virtio-9p host-share for anaconda logs
docs/research/2026-05-05-agent-wave/07-...skel-branding.md — /etc/skel gap audit
docs/research/2026-05-05-agent-wave/08-...ci-hardening.md — SHA-pin actions + SBOM + SLSA L3
docs/research/2026-05-05-agent-wave/09-...failure-modes.md — real-hardware pessimistic audit
Plus the prior linter-applied:
docs/ROADMAP.md — Lessons learned section, v0.5.32 active block,
v0.6 promotion of veilor-postinstall + veilor-doctor,
v0.7 bootc spike scheduled
docs/THREAT-MODEL.md — drafted by Agent 5; in/out scope, comparison
matrix, v0.7 launch checklist
Top blockers identified for v0.5.32 (cross-cited in README):
1. Suspend/resume wifi death (kernel.modules_disabled=1)
2. veilor-firstboot.service WantedBy=graphical.target
3. kernel-upgrade grub drift
4. USBGuard hash-rules problem (already learned on onyx)
5. firewalld blocks tailscale0
6. /etc/skel/ empty
7. virtio-9p log capture replaces broken virtio-serial path
Wave + verifier pattern (per ROADMAP lessons learned #4) validated:
9 parallel agents on distinct topics produced converging blocker
list. The same pattern landed v0.5.31 four-bug fix from the prior
4-agent verification wave on v0.5.30 outcome.
131 lines
4.7 KiB
Markdown
131 lines
4.7 KiB
Markdown
# Build-iso CI hardening
|
|
|
|
**Agent 8 of 9-agent wave, 2026-05-05.**
|
|
|
|
## State of play
|
|
|
|
- Workflows: `build-iso.yml`, `lint.yml`, `Release Checksums` (auto)
|
|
- Secrets/variables: **none configured** — only ambient `GITHUB_TOKEN`
|
|
- Repo: private, MIT, no Pages, no Dependabot, no branch protection
|
|
(Pro-gated until public flip)
|
|
- Container: `registry.fedoraproject.org/fedora:43` (tag, not digest)
|
|
- Actions: `actions/checkout@v4`, `addnab/docker-run-action@v3`,
|
|
`softprops/action-gh-release@v2`, `ludeeus/action-shellcheck@master`
|
|
— **all unpinned to SHA**
|
|
- gum download: pinned by SHA256 ✓
|
|
- Kickstart repos: `releases/43/Everything` + `updates/43/Everything`
|
|
— **both rolling**, byte-different daily
|
|
|
|
## Top 5 immediate (S effort, ship in v0.5.32)
|
|
|
|
| # | Item | Why |
|
|
|---|------|-----|
|
|
| 1 | Pin all actions to commit SHA + add `.github/dependabot.yml` for `github-actions` | Supply-chain — `@master` on shellcheck is live-takeover vector; v3/v4 tags are mutable |
|
|
| 2 | Pin Fedora container to digest (`registry.fedoraproject.org/fedora:43@sha256:...`) | One-line change; eliminates "container drift" repro class |
|
|
| 3 | Add `permissions:` block at workflow level (`contents: read` default), override per-job | `contents: write` is workflow-wide; least-privilege the lint job |
|
|
| 4 | Generate SBOM via `anchore/sbom-action`, attach to release | Free, ~30 lines, journalist-readable |
|
|
| 5 | Add `actions/attest-build-provenance@v2` for SLSA L3 attestation on ISO + parts | Free, GH-native, `id-token: write` only |
|
|
|
|
## v0.4 release-eng roadmap (confirmed/added)
|
|
|
|
- **Confirmed:** Sigstore/cosign signing of ISOs (already in roadmap)
|
|
- **Add:** Fedora compose-ID pinning per release tag — switch
|
|
`--baseurl` to
|
|
`kojipkgs.fedoraproject.org/compose/branched/Fedora-43-...n.X/compose/Everything/x86_64/os/`
|
|
for stable releases (rolling for `ci-latest`)
|
|
- **Add:** Reproducible-Builds.org diffoscope job comparing 2
|
|
sequential builds of same SHA — gate on byte-equality
|
|
- **Add:** `harden-runner` (StepSecurity) audit-mode pass to enumerate
|
|
egress; promote to block-mode in v0.5
|
|
- **Add:** When repo flips public (v0.7), enable secret scanning + push
|
|
protection + private vuln reporting + branch protection (require ≥1
|
|
review, status checks: lint + ksvalidate + build, no force-push)
|
|
- **Add:** OIDC `id-token: write` only in tag-release job (not on
|
|
`main` push) — keysless cosign signing scoped to release events
|
|
|
|
## YAML diffs
|
|
|
|
### 1. Workflow-level permissions + per-job override
|
|
|
|
```yaml
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
build:
|
|
permissions:
|
|
contents: write # gh-release
|
|
id-token: write # cosign keyless + attestation
|
|
attestations: write
|
|
```
|
|
|
|
### 2. SHA-pin actions
|
|
|
|
```yaml
|
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
|
- uses: addnab/docker-run-action@4f65375b03d588f307b7a3b0a8bb50f8b58a85b9 # v3
|
|
- uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
|
|
```
|
|
|
|
(SHAs to be re-checked at apply-time; dependabot keeps them current)
|
|
|
|
### 3. Pin Fedora digest
|
|
|
|
```yaml
|
|
image: registry.fedoraproject.org/fedora:43@sha256:<DIGEST>
|
|
```
|
|
|
|
Capture once via `skopeo inspect --raw
|
|
docker://registry.fedoraproject.org/fedora:43 | jq -r .config.digest`
|
|
and bump on each releasever bump.
|
|
|
|
### 4. SBOM + attestation + cosign
|
|
|
|
```yaml
|
|
- name: Install cosign
|
|
uses: sigstore/cosign-installer@d7d6e07a3ddf0f9a4f8b3b9e3f1d1a5ce8e9b5b3 # v3.7.0
|
|
|
|
- name: Sign ISO parts (keyless)
|
|
if: github.event_name == 'release'
|
|
run: |
|
|
cd build/out
|
|
for f in *.part-*; do cosign sign-blob --yes "$f" \
|
|
--output-signature "$f.sig" --output-certificate "$f.pem"; done
|
|
|
|
- name: Generate SBOM (SPDX)
|
|
uses: anchore/sbom-action@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.17.4
|
|
with:
|
|
path: build/out
|
|
format: spdx-json
|
|
output-file: build/out/veilor-os.spdx.json
|
|
|
|
- name: Build provenance attestation
|
|
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # v2.1.0
|
|
with:
|
|
subject-path: 'build/out/*.part-*'
|
|
```
|
|
|
|
### 5. New `.github/dependabot.yml`
|
|
|
|
```yaml
|
|
version: 2
|
|
updates:
|
|
- package-ecosystem: "github-actions"
|
|
directory: "/"
|
|
schedule: { interval: "weekly" }
|
|
groups:
|
|
actions: { patterns: ["*"] }
|
|
```
|
|
|
|
### 6. Timeout
|
|
|
|
Keep at 90min. Largest observed runs ~70min; trimming would
|
|
false-fail Fedora-mirror-slow days. **No change.**
|
|
|
|
## Q&A
|
|
|
|
- **Secrets in use:** none. Only ambient `GITHUB_TOKEN`. Once public,
|
|
enable secret scanning + push protection (free for public repos).
|
|
- **Pages:** not deployed from this repo. Docs site out-of-scope here.
|
|
- **Dependency review:** only `gum` fetched out-of-band — already
|
|
SHA256-pinned. Add `actions/dependency-review-action` on PRs once public.
|