From 5a8b279b740b9ab21558e0ddd8a6489c913c2008 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:31:32 +0000 Subject: [PATCH 1/2] Initial plan From e81c77938a75aed9cef466a13efa931ab0d72709 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 16:36:09 +0000 Subject: [PATCH 2/2] feat: define Recovery/Installer artifact build lane (docs, fixture, Makefile, maturity) Agent-Logs-Url: https://github.com/SourceOS-Linux/sourceos-boot/sessions/1a77e58b-4506-4868-bda3-ee919e150a5a Co-authored-by: mdheller <21163552+mdheller@users.noreply.github.com> --- Makefile | 1 + .../RECOVERY_INSTALLER_ARTIFACT_BUILD_LANE.md | 165 ++++++++++++++++++ ...covery-installer-build-result.example.json | 159 +++++++++++++++++ repo.maturity.yaml | 7 +- 4 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 docs/RECOVERY_INSTALLER_ARTIFACT_BUILD_LANE.md create mode 100644 examples/artifact-build-lane/recovery-installer-build-result.example.json diff --git a/Makefile b/Makefile index 0d50201..cf8fdb7 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ validate: examples/m2-recovery-installer/recovery-installer.example.json python -m json.tool examples/apple-silicon-evidence/raw-apple-silicon-evidence.example.json > /dev/null python -m json.tool examples/apple-silicon-evidence/normalized-boot-evidence.example.json > /dev/null + python -m json.tool examples/artifact-build-lane/recovery-installer-build-result.example.json > /dev/null PYTHONPATH=src python -m sourceos_boot.cli adapt-nlboot \ --manifest examples/nlboot/manifest.json \ --token examples/nlboot/token.json \ diff --git a/docs/RECOVERY_INSTALLER_ARTIFACT_BUILD_LANE.md b/docs/RECOVERY_INSTALLER_ARTIFACT_BUILD_LANE.md new file mode 100644 index 0000000..d7e6075 --- /dev/null +++ b/docs/RECOVERY_INSTALLER_ARTIFACT_BUILD_LANE.md @@ -0,0 +1,165 @@ +# Recovery/Installer Artifact Build Lane + +This document defines the **artifact build lane** for SourceOS Recovery/Installer +artifacts. It covers the required artifact classes, build pipeline stages, SBOM and +provenance references, and how the lane output feeds into the `BootReleaseSet` packaging +flow. + +> **Scope**: Documentation and dry-run fixtures only. No host mutation, disk writes, +> boot-entry creation, installer execution, artifact publishing, or tagged-release +> creation is performed. Real Apple Silicon boot-entry mutation, installer disk writes, +> rollback execution, and kexec are explicitly out of scope. + +## Background + +A "build lane" is the CI/CD pipeline segment responsible for producing a verified, +content-addressed set of artifacts for one target surface. The Recovery/Installer lane +produces everything needed to fill the `spec.artifacts` array of a +`BootReleaseSet` with `channels: ["recovery", "installer"]`. + +The lane is distinct from the *packaging* step (documented in +[`M2_RECOVERY_INSTALLER_PACKAGING.md`](M2_RECOVERY_INSTALLER_PACKAGING.md)) that +assembles a `BootReleaseSet` from lane outputs. The build lane runs first; packaging +runs after lane artifacts are verified. + +## NLBoot release-candidate status + +The lane references the NLBoot safe planner (SociOS-Linux/nlboot) at +**release-candidate** status. No tagged release has been published. The SBOM proof for +NLBoot RC artifacts is in progress; this lane tracks that status via the +`nlbootRef.status` and `sbomStatus` fields in the build-result fixture. Do not invent +release URLs or checksums. + +## Required artifact classes + +The Recovery/Installer lane must produce exactly the following artifact classes. Each +class is content-addressed (SHA-256), carries an SBOM reference, and carries a +provenance reference. + +| Class | Role field | Description | +|---|---|---| +| `bootstrap-payload` | `bootloader` | First-stage loader chain (m1n1 → U-Boot for M2; UEFI stub for generic targets). Bootstraps the recovery kernel. | +| `recovery-payload` | `recovery-image` | Compressed recovery root filesystem image. Contains repair tooling and rollback scripts. | +| `installer-payload` | `installer-data` | Installer data bundle (Asahi-style JSON + asset pack for M2; EFI layout descriptor for UEFI targets). | +| `recovery-kernel` | `kernel` | Recovery-mode Linux kernel image. | +| `recovery-initrd` | `initrd` | Recovery initramfs. Contains early userspace for the recovery environment. | +| `manifest` | `manifest` | Signed artifact manifest listing all artifact digests for this build result. | +| `checksums` | `other` | Detached checksum file (`SHA256SUMS`) over all lane artifacts. | +| `sbom-reference` | `other` | SPDX or CycloneDX SBOM document reference for the full artifact set. | +| `provenance-reference` | `other` | SLSA / in-toto provenance bundle reference for the full artifact set. | + +### Platform notes + +- **M2 / Apple Silicon** is the first-class proof target. The `bootstrap-payload` is the + m1n1 + U-Boot chain required by the Asahi boot picker. +- **uefi-x86_64 / uefi-aarch64** use a UEFI stub bootloader instead of m1n1. The + `installer-payload` becomes a UEFI-layout descriptor rather than an Asahi-style JSON + pack. +- **generic-arm64** uses U-Boot directly; the `bootstrap-payload` is a U-Boot binary. + +The `platforms` field in the build-result fixture lists all targets a given lane run +covers. + +## Build pipeline stages + +``` +1. Source fetch + └─ Fetch pinned source refs for kernel, initrd, m1n1, U-Boot, recovery rootfs, + installer data. Verify against NLBoot RC manifest hashes (execute=false). + +2. Artifact build [dry-run in fixtures; not executed] + ├─ build bootstrap-payload (m1n1 + U-Boot chain / UEFI stub) + ├─ build recovery-kernel (Linux kernel, recovery config) + ├─ build recovery-initrd (initramfs, recovery userspace) + ├─ build recovery-payload (recovery rootfs image) + └─ build installer-payload (Asahi installer JSON pack / UEFI layout) + +3. Manifest assembly + └─ Compute SHA-256 over each artifact → write manifest.json + SHA256SUMS + +4. SBOM generation [status: pending for NLBoot RC] + └─ Generate SPDX/CycloneDX SBOM over build graph → sbom-reference artifact + +5. Provenance attestation + └─ Emit SLSA Build L2 + in-toto attestation → provenance-reference artifact + +6. Signing + └─ Sigstore/cosign sign manifest.json → sigstore bundle reference + +7. Output + └─ Produce ArtifactBuildLaneResult (dry-run fixture: recovery-installer-build-result.example.json) + └─ Feed artifact URIs + SHA-256 digests into BootReleaseSet packaging step +``` + +All pipeline stages are side-effect-free in dry-run mode (`dryRun: true`, +`execute: false`). No artifacts are uploaded or published from a dry-run invocation. + +## Checksums and content addressing + +Each artifact in the lane output carries a `sha256` field. The `checksums` artifact +(`SHA256SUMS`) is a detached file that duplicates all digests in a standard format, +suitable for offline verification. Content-addressed URIs use the digest as part of the +path (e.g., `https://example.invalid/…//filename`). + +> **Note**: In dry-run fixtures, all SHA-256 values are placeholder zeros. Real digests +> will be produced by the build system. + +## SBOM references + +Each artifact carries an `sbomRef` field pointing to an SPDX or CycloneDX SBOM +document. The lane also produces a top-level `sbomRef` covering the entire artifact set. +SBOM documents are not embedded in the build-result fixture; they are referenced by URI. + +SBOM proof for NLBoot RC is in progress. Until it is complete, `sbomStatus` in the +fixture is `"pending"`. + +## Provenance references + +Each artifact carries a `provenanceRef` field pointing to an SLSA / in-toto attestation +bundle. The lane also emits a top-level `provenanceRef` for the full build. Provenance +bundles are not embedded in the build-result fixture; they are referenced by URI. + +## Dry-run fixture + +`examples/artifact-build-lane/recovery-installer-build-result.example.json` — a +minimal valid `ArtifactBuildLaneResult` dry-run fixture for the Recovery/Installer lane. +This fixture is syntax-checked by `make validate`. + +## Output → BootReleaseSet mapping + +Lane output feeds the packaging step (see +[`M2_RECOVERY_INSTALLER_PACKAGING.md`](M2_RECOVERY_INSTALLER_PACKAGING.md)): + +| Lane artifact class | BootReleaseSet field | +|---|---| +| `bootstrap-payload` | `spec.artifacts[role=bootloader]` | +| `recovery-kernel` | `spec.artifacts[role=kernel]` | +| `recovery-initrd` | `spec.artifacts[role=initrd]` | +| `recovery-payload` | `spec.artifacts[role=recovery-image]` | +| `installer-payload` | `spec.artifacts[role=installer-data]` | +| `manifest` | `spec.artifacts[role=manifest]` | +| `checksums` / `sbom-reference` / `provenance-reference` | `spec.artifacts[role=other]` | +| `provenanceRef` (top-level) | `spec.provenance` | +| `sigstoreBundleRef` | `spec.signature.bundleRef` | + +## Known gaps + +- Real artifact build execution is not implemented; all digests in fixtures are + placeholder zeros. +- SBOM proof for NLBoot RC is pending; `sbomStatus` is `"pending"` in fixtures. +- Sigstore signing of lane artifacts is not yet automated; `sigstoreBundleRef` in + fixtures is a placeholder reference. +- Artifact content-addressed cache upload and SHA-256 fetch verification are not yet + implemented. +- UEFI and generic-arm64 PAL notes are stubs; M2 is the only fully specified target for + this milestone. + +## References + +- [`M2_RECOVERY_INSTALLER_PACKAGING.md`](M2_RECOVERY_INSTALLER_PACKAGING.md) — packaging step that consumes lane output +- [`NLBOOT_INTEGRATION.md`](NLBOOT_INTEGRATION.md) — nlboot adapter integration guide +- [`APPLE_SILICON_EVIDENCE_NORMALIZATION.md`](APPLE_SILICON_EVIDENCE_NORMALIZATION.md) — evidence normalization design +- [`WORLD_CLASS_TARGETS.md`](WORLD_CLASS_TARGETS.md) — implementation roadmap +- [`examples/artifact-build-lane/recovery-installer-build-result.example.json`](../examples/artifact-build-lane/recovery-installer-build-result.example.json) — dry-run build-result fixture +- [`SourceOS-Linux/sourceos-spec`](https://github.com/SourceOS-Linux/sourceos-spec) — canonical BootReleaseSet and ReleaseSet schemas (referenced, not duplicated) +- [`SociOS-Linux/nlboot`](https://github.com/SociOS-Linux/nlboot) — upstream safe planner (release-candidate; no tagged release yet) diff --git a/examples/artifact-build-lane/recovery-installer-build-result.example.json b/examples/artifact-build-lane/recovery-installer-build-result.example.json new file mode 100644 index 0000000..d793d9b --- /dev/null +++ b/examples/artifact-build-lane/recovery-installer-build-result.example.json @@ -0,0 +1,159 @@ +{ + "apiVersion": "sourceos.dev/v1", + "kind": "ArtifactBuildLaneResult", + "_dryRun": true, + "_comment": "Dry-run fixture only. No artifact build, upload, signing, or publishing is performed. All SHA-256 values are placeholder zeros. SBOM proof for NLBoot RC is pending.", + "metadata": { + "name": "sourceos-recovery-installer-build-lane-demo", + "version": "0.1.0", + "createdAt": "2026-05-01T00:00:00Z", + "lane": "recovery-installer", + "labels": { + "platform": "apple-silicon", + "stage": "dry-run", + "entry-type": "recovery-installer" + } + }, + "spec": { + "dryRun": true, + "execute": false, + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "nlbootRef": { + "repository": "SociOS-Linux/nlboot", + "status": "release-candidate", + "note": "No tagged release published. SBOM proof in progress. Adapter consumes nlboot safe plan with execute=false." + }, + "sbomStatus": "pending", + "artifacts": [ + { + "class": "bootstrap-payload", + "name": "sourceos-m2-bootstrap", + "description": "First-stage loader chain: m1n1 + U-Boot for M2 Apple Silicon.", + "role": "bootloader", + "platforms": ["apple-silicon"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/bootstrap.bin", + "sha256": "0000000000000000000000000000000000000000000000000000000000000031", + "sizeBytes": 0, + "contentType": "application/octet-stream", + "sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/bootstrap.spdx.json", + "provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/bootstrap.intoto.jsonl" + }, + { + "class": "recovery-kernel", + "name": "sourceos-m2-recovery-kernel", + "description": "Recovery-mode Linux kernel image.", + "role": "kernel", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-kernel", + "sha256": "0000000000000000000000000000000000000000000000000000000000000032", + "sizeBytes": 0, + "contentType": "application/octet-stream", + "sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-kernel.spdx.json", + "provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-kernel.intoto.jsonl" + }, + { + "class": "recovery-initrd", + "name": "sourceos-m2-recovery-initrd", + "description": "Recovery initramfs containing early userspace for the recovery environment.", + "role": "initrd", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-initrd.img", + "sha256": "0000000000000000000000000000000000000000000000000000000000000033", + "sizeBytes": 0, + "contentType": "application/octet-stream", + "sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-initrd.spdx.json", + "provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-initrd.intoto.jsonl" + }, + { + "class": "recovery-payload", + "name": "sourceos-m2-recovery-image", + "description": "Compressed recovery root filesystem image containing repair tooling and rollback scripts.", + "role": "recovery-image", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/recovery.img", + "sha256": "0000000000000000000000000000000000000000000000000000000000000034", + "sizeBytes": 0, + "contentType": "application/octet-stream", + "sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery.spdx.json", + "provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery.intoto.jsonl" + }, + { + "class": "installer-payload", + "name": "sourceos-m2-installer-data", + "description": "Installer data bundle: Asahi-style JSON + asset pack for M2; UEFI layout descriptor for generic targets.", + "role": "installer-data", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/installer-data.json", + "sha256": "0000000000000000000000000000000000000000000000000000000000000035", + "sizeBytes": 0, + "contentType": "application/json", + "sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/installer-data.spdx.json", + "provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/installer-data.intoto.jsonl" + }, + { + "class": "manifest", + "name": "sourceos-m2-build-manifest", + "description": "Signed artifact manifest listing all lane artifact digests for this build result.", + "role": "manifest", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/manifest.json", + "sha256": "0000000000000000000000000000000000000000000000000000000000000036", + "sizeBytes": 0, + "contentType": "application/json", + "sbomRef": null, + "provenanceRef": null + }, + { + "class": "checksums", + "name": "sourceos-m2-sha256sums", + "description": "Detached SHA256SUMS file over all lane artifacts for offline verification.", + "role": "other", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/SHA256SUMS", + "sha256": "0000000000000000000000000000000000000000000000000000000000000037", + "sizeBytes": 0, + "contentType": "text/plain", + "sbomRef": null, + "provenanceRef": null + }, + { + "class": "sbom-reference", + "name": "sourceos-m2-sbom", + "description": "SPDX SBOM document covering the full artifact set produced by this build lane.", + "role": "other", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.spdx.json", + "sha256": "0000000000000000000000000000000000000000000000000000000000000038", + "sizeBytes": 0, + "contentType": "application/spdx+json", + "sbomRef": null, + "provenanceRef": null + }, + { + "class": "provenance-reference", + "name": "sourceos-m2-provenance", + "description": "SLSA Build L2 + in-toto provenance bundle covering the full artifact set.", + "role": "other", + "platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"], + "uri": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.intoto.jsonl", + "sha256": "0000000000000000000000000000000000000000000000000000000000000039", + "sizeBytes": 0, + "contentType": "application/json", + "sbomRef": null, + "provenanceRef": null + } + ], + "provenance": { + "builderId": "sourceos-recovery-installer-lane-demo-builder", + "sourceRefs": [ + "git:SourceOS-Linux/sourceos-boot#main", + "git:SociOS-Linux/nlboot#release-candidate" + ], + "attestations": ["slsa", "in-toto"], + "provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.intoto.jsonl" + }, + "sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.spdx.json", + "sigstoreBundleRef": "sigstore-bundle-sourceos-m2-recovery-installer-lane-demo", + "manifestDigest": "sha256:0000000000000000000000000000000000000000000000000000000000000036" + } +} diff --git a/repo.maturity.yaml b/repo.maturity.yaml index 6113026..5a3f0ee 100644 --- a/repo.maturity.yaml +++ b/repo.maturity.yaml @@ -18,11 +18,13 @@ maturity: - docs/M2_RECOVERY_INSTALLER_PACKAGING.md defines packaging responsibilities, required inputs, and evidence model for both M2 entry types. - src/sourceos_boot/adapter.py implements the nlboot-to-BootReleaseSet adapter. - src/sourceos_boot/control_plane.py implements the control-plane boot plan builder. - - make validate exercises schema validation, new M2 fixtures, and the nlboot adapter CLI path. + - make validate exercises schema validation, M2 fixtures, nlboot adapter CLI path, and the new artifact-build-lane fixture. - python -m pytest passes all tests. - docs/APPLE_SILICON_EVIDENCE_NORMALIZATION.md defines the normalization design for AppleSiliconAdapterEvidence into BootEvidence/BootProofRecord. - examples/apple-silicon-evidence/raw-apple-silicon-evidence.example.json is a dry-run raw AppleSiliconAdapterEvidence fixture. - examples/apple-silicon-evidence/normalized-boot-evidence.example.json is a dry-run normalized BootEvidence fixture showing the output of normalise_apple_silicon_evidence(). + - docs/RECOVERY_INSTALLER_ARTIFACT_BUILD_LANE.md defines the artifact build lane for Recovery/Installer artifacts, including all required artifact classes, pipeline stages, SBOM/provenance references, and NLBoot RC status. + - examples/artifact-build-lane/recovery-installer-build-result.example.json is a dry-run ArtifactBuildLaneResult fixture covering bootstrap-payload, recovery-payload, installer-payload, manifest, checksums, sbom-reference, and provenance-reference artifact classes across M2 and generic platform targets. validation: commands: - make validate @@ -54,3 +56,6 @@ nextActions: - Add artifact digest verification and content-addressed cache path. - Emit evidence records from the boot/recovery execution boundary. - Wire M2 packaging adapter to produce platform entrypoint descriptors from BootReleaseSet. + - Complete SBOM proof for NLBoot RC artifacts (sbomStatus is currently pending in artifact-build-lane fixture). + - Automate Sigstore/cosign signing of artifact-build-lane manifest once NLBoot RC is stable. + - Wire artifact-build-lane output into BootReleaseSet packaging step (spec.artifacts population from lane result).