Skip to content

Commit 4ce0007

Browse files
authored
Define Recovery Installer artifact build lane
Adds Recovery/Installer artifact build lane design, dry-run ArtifactBuildLaneResult fixture, Makefile JSON validation, and repo maturity metadata updates. This is docs/fixtures/validation only and introduces no host mutation, boot-entry mutation, disk writes, installer execution, rollback execution, kexec behavior, Secure Enclave calls, or release publication. Closes #18.
1 parent 3f7779f commit 4ce0007

4 files changed

Lines changed: 331 additions & 1 deletion

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ validate:
77
examples/m2-recovery-installer/recovery-installer.example.json
88
python -m json.tool examples/apple-silicon-evidence/raw-apple-silicon-evidence.example.json > /dev/null
99
python -m json.tool examples/apple-silicon-evidence/normalized-boot-evidence.example.json > /dev/null
10+
python -m json.tool examples/artifact-build-lane/recovery-installer-build-result.example.json > /dev/null
1011
PYTHONPATH=src python -m sourceos_boot.cli adapt-nlboot \
1112
--manifest examples/nlboot/manifest.json \
1213
--token examples/nlboot/token.json \
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Recovery/Installer Artifact Build Lane
2+
3+
This document defines the **artifact build lane** for SourceOS Recovery/Installer
4+
artifacts. It covers the required artifact classes, build pipeline stages, SBOM and
5+
provenance references, and how the lane output feeds into the `BootReleaseSet` packaging
6+
flow.
7+
8+
> **Scope**: Documentation and dry-run fixtures only. No host mutation, disk writes,
9+
> boot-entry creation, installer execution, artifact publishing, or tagged-release
10+
> creation is performed. Real Apple Silicon boot-entry mutation, installer disk writes,
11+
> rollback execution, and kexec are explicitly out of scope.
12+
13+
## Background
14+
15+
A "build lane" is the CI/CD pipeline segment responsible for producing a verified,
16+
content-addressed set of artifacts for one target surface. The Recovery/Installer lane
17+
produces everything needed to fill the `spec.artifacts` array of a
18+
`BootReleaseSet` with `channels: ["recovery", "installer"]`.
19+
20+
The lane is distinct from the *packaging* step (documented in
21+
[`M2_RECOVERY_INSTALLER_PACKAGING.md`](M2_RECOVERY_INSTALLER_PACKAGING.md)) that
22+
assembles a `BootReleaseSet` from lane outputs. The build lane runs first; packaging
23+
runs after lane artifacts are verified.
24+
25+
## NLBoot release-candidate status
26+
27+
The lane references the NLBoot safe planner (SociOS-Linux/nlboot) at
28+
**release-candidate** status. No tagged release has been published. The SBOM proof for
29+
NLBoot RC artifacts is in progress; this lane tracks that status via the
30+
`nlbootRef.status` and `sbomStatus` fields in the build-result fixture. Do not invent
31+
release URLs or checksums.
32+
33+
## Required artifact classes
34+
35+
The Recovery/Installer lane must produce exactly the following artifact classes. Each
36+
class is content-addressed (SHA-256), carries an SBOM reference, and carries a
37+
provenance reference.
38+
39+
| Class | Role field | Description |
40+
|---|---|---|
41+
| `bootstrap-payload` | `bootloader` | First-stage loader chain (m1n1 → U-Boot for M2; UEFI stub for generic targets). Bootstraps the recovery kernel. |
42+
| `recovery-payload` | `recovery-image` | Compressed recovery root filesystem image. Contains repair tooling and rollback scripts. |
43+
| `installer-payload` | `installer-data` | Installer data bundle (Asahi-style JSON + asset pack for M2; EFI layout descriptor for UEFI targets). |
44+
| `recovery-kernel` | `kernel` | Recovery-mode Linux kernel image. |
45+
| `recovery-initrd` | `initrd` | Recovery initramfs. Contains early userspace for the recovery environment. |
46+
| `manifest` | `manifest` | Signed artifact manifest listing all artifact digests for this build result. |
47+
| `checksums` | `other` | Detached checksum file (`SHA256SUMS`) over all lane artifacts. |
48+
| `sbom-reference` | `other` | SPDX or CycloneDX SBOM document reference for the full artifact set. |
49+
| `provenance-reference` | `other` | SLSA / in-toto provenance bundle reference for the full artifact set. |
50+
51+
### Platform notes
52+
53+
- **M2 / Apple Silicon** is the first-class proof target. The `bootstrap-payload` is the
54+
m1n1 + U-Boot chain required by the Asahi boot picker.
55+
- **uefi-x86_64 / uefi-aarch64** use a UEFI stub bootloader instead of m1n1. The
56+
`installer-payload` becomes a UEFI-layout descriptor rather than an Asahi-style JSON
57+
pack.
58+
- **generic-arm64** uses U-Boot directly; the `bootstrap-payload` is a U-Boot binary.
59+
60+
The `platforms` field in the build-result fixture lists all targets a given lane run
61+
covers.
62+
63+
## Build pipeline stages
64+
65+
```
66+
1. Source fetch
67+
└─ Fetch pinned source refs for kernel, initrd, m1n1, U-Boot, recovery rootfs,
68+
installer data. Verify against NLBoot RC manifest hashes (execute=false).
69+
70+
2. Artifact build [dry-run in fixtures; not executed]
71+
├─ build bootstrap-payload (m1n1 + U-Boot chain / UEFI stub)
72+
├─ build recovery-kernel (Linux kernel, recovery config)
73+
├─ build recovery-initrd (initramfs, recovery userspace)
74+
├─ build recovery-payload (recovery rootfs image)
75+
└─ build installer-payload (Asahi installer JSON pack / UEFI layout)
76+
77+
3. Manifest assembly
78+
└─ Compute SHA-256 over each artifact → write manifest.json + SHA256SUMS
79+
80+
4. SBOM generation [status: pending for NLBoot RC]
81+
└─ Generate SPDX/CycloneDX SBOM over build graph → sbom-reference artifact
82+
83+
5. Provenance attestation
84+
└─ Emit SLSA Build L2 + in-toto attestation → provenance-reference artifact
85+
86+
6. Signing
87+
└─ Sigstore/cosign sign manifest.json → sigstore bundle reference
88+
89+
7. Output
90+
└─ Produce ArtifactBuildLaneResult (dry-run fixture: recovery-installer-build-result.example.json)
91+
└─ Feed artifact URIs + SHA-256 digests into BootReleaseSet packaging step
92+
```
93+
94+
All pipeline stages are side-effect-free in dry-run mode (`dryRun: true`,
95+
`execute: false`). No artifacts are uploaded or published from a dry-run invocation.
96+
97+
## Checksums and content addressing
98+
99+
Each artifact in the lane output carries a `sha256` field. The `checksums` artifact
100+
(`SHA256SUMS`) is a detached file that duplicates all digests in a standard format,
101+
suitable for offline verification. Content-addressed URIs use the digest as part of the
102+
path (e.g., `https://example.invalid/…/<sha256>/filename`).
103+
104+
> **Note**: In dry-run fixtures, all SHA-256 values are placeholder zeros. Real digests
105+
> will be produced by the build system.
106+
107+
## SBOM references
108+
109+
Each artifact carries an `sbomRef` field pointing to an SPDX or CycloneDX SBOM
110+
document. The lane also produces a top-level `sbomRef` covering the entire artifact set.
111+
SBOM documents are not embedded in the build-result fixture; they are referenced by URI.
112+
113+
SBOM proof for NLBoot RC is in progress. Until it is complete, `sbomStatus` in the
114+
fixture is `"pending"`.
115+
116+
## Provenance references
117+
118+
Each artifact carries a `provenanceRef` field pointing to an SLSA / in-toto attestation
119+
bundle. The lane also emits a top-level `provenanceRef` for the full build. Provenance
120+
bundles are not embedded in the build-result fixture; they are referenced by URI.
121+
122+
## Dry-run fixture
123+
124+
`examples/artifact-build-lane/recovery-installer-build-result.example.json` — a
125+
minimal valid `ArtifactBuildLaneResult` dry-run fixture for the Recovery/Installer lane.
126+
This fixture is syntax-checked by `make validate`.
127+
128+
## Output → BootReleaseSet mapping
129+
130+
Lane output feeds the packaging step (see
131+
[`M2_RECOVERY_INSTALLER_PACKAGING.md`](M2_RECOVERY_INSTALLER_PACKAGING.md)):
132+
133+
| Lane artifact class | BootReleaseSet field |
134+
|---|---|
135+
| `bootstrap-payload` | `spec.artifacts[role=bootloader]` |
136+
| `recovery-kernel` | `spec.artifacts[role=kernel]` |
137+
| `recovery-initrd` | `spec.artifacts[role=initrd]` |
138+
| `recovery-payload` | `spec.artifacts[role=recovery-image]` |
139+
| `installer-payload` | `spec.artifacts[role=installer-data]` |
140+
| `manifest` | `spec.artifacts[role=manifest]` |
141+
| `checksums` / `sbom-reference` / `provenance-reference` | `spec.artifacts[role=other]` |
142+
| `provenanceRef` (top-level) | `spec.provenance` |
143+
| `sigstoreBundleRef` | `spec.signature.bundleRef` |
144+
145+
## Known gaps
146+
147+
- Real artifact build execution is not implemented; all digests in fixtures are
148+
placeholder zeros.
149+
- SBOM proof for NLBoot RC is pending; `sbomStatus` is `"pending"` in fixtures.
150+
- Sigstore signing of lane artifacts is not yet automated; `sigstoreBundleRef` in
151+
fixtures is a placeholder reference.
152+
- Artifact content-addressed cache upload and SHA-256 fetch verification are not yet
153+
implemented.
154+
- UEFI and generic-arm64 PAL notes are stubs; M2 is the only fully specified target for
155+
this milestone.
156+
157+
## References
158+
159+
- [`M2_RECOVERY_INSTALLER_PACKAGING.md`](M2_RECOVERY_INSTALLER_PACKAGING.md) — packaging step that consumes lane output
160+
- [`NLBOOT_INTEGRATION.md`](NLBOOT_INTEGRATION.md) — nlboot adapter integration guide
161+
- [`APPLE_SILICON_EVIDENCE_NORMALIZATION.md`](APPLE_SILICON_EVIDENCE_NORMALIZATION.md) — evidence normalization design
162+
- [`WORLD_CLASS_TARGETS.md`](WORLD_CLASS_TARGETS.md) — implementation roadmap
163+
- [`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
164+
- [`SourceOS-Linux/sourceos-spec`](https://github.com/SourceOS-Linux/sourceos-spec) — canonical BootReleaseSet and ReleaseSet schemas (referenced, not duplicated)
165+
- [`SociOS-Linux/nlboot`](https://github.com/SociOS-Linux/nlboot) — upstream safe planner (release-candidate; no tagged release yet)
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
{
2+
"apiVersion": "sourceos.dev/v1",
3+
"kind": "ArtifactBuildLaneResult",
4+
"_dryRun": true,
5+
"_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.",
6+
"metadata": {
7+
"name": "sourceos-recovery-installer-build-lane-demo",
8+
"version": "0.1.0",
9+
"createdAt": "2026-05-01T00:00:00Z",
10+
"lane": "recovery-installer",
11+
"labels": {
12+
"platform": "apple-silicon",
13+
"stage": "dry-run",
14+
"entry-type": "recovery-installer"
15+
}
16+
},
17+
"spec": {
18+
"dryRun": true,
19+
"execute": false,
20+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
21+
"nlbootRef": {
22+
"repository": "SociOS-Linux/nlboot",
23+
"status": "release-candidate",
24+
"note": "No tagged release published. SBOM proof in progress. Adapter consumes nlboot safe plan with execute=false."
25+
},
26+
"sbomStatus": "pending",
27+
"artifacts": [
28+
{
29+
"class": "bootstrap-payload",
30+
"name": "sourceos-m2-bootstrap",
31+
"description": "First-stage loader chain: m1n1 + U-Boot for M2 Apple Silicon.",
32+
"role": "bootloader",
33+
"platforms": ["apple-silicon"],
34+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/bootstrap.bin",
35+
"sha256": "0000000000000000000000000000000000000000000000000000000000000031",
36+
"sizeBytes": 0,
37+
"contentType": "application/octet-stream",
38+
"sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/bootstrap.spdx.json",
39+
"provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/bootstrap.intoto.jsonl"
40+
},
41+
{
42+
"class": "recovery-kernel",
43+
"name": "sourceos-m2-recovery-kernel",
44+
"description": "Recovery-mode Linux kernel image.",
45+
"role": "kernel",
46+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
47+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-kernel",
48+
"sha256": "0000000000000000000000000000000000000000000000000000000000000032",
49+
"sizeBytes": 0,
50+
"contentType": "application/octet-stream",
51+
"sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-kernel.spdx.json",
52+
"provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-kernel.intoto.jsonl"
53+
},
54+
{
55+
"class": "recovery-initrd",
56+
"name": "sourceos-m2-recovery-initrd",
57+
"description": "Recovery initramfs containing early userspace for the recovery environment.",
58+
"role": "initrd",
59+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
60+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-initrd.img",
61+
"sha256": "0000000000000000000000000000000000000000000000000000000000000033",
62+
"sizeBytes": 0,
63+
"contentType": "application/octet-stream",
64+
"sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-initrd.spdx.json",
65+
"provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery-initrd.intoto.jsonl"
66+
},
67+
{
68+
"class": "recovery-payload",
69+
"name": "sourceos-m2-recovery-image",
70+
"description": "Compressed recovery root filesystem image containing repair tooling and rollback scripts.",
71+
"role": "recovery-image",
72+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
73+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/recovery.img",
74+
"sha256": "0000000000000000000000000000000000000000000000000000000000000034",
75+
"sizeBytes": 0,
76+
"contentType": "application/octet-stream",
77+
"sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery.spdx.json",
78+
"provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/recovery.intoto.jsonl"
79+
},
80+
{
81+
"class": "installer-payload",
82+
"name": "sourceos-m2-installer-data",
83+
"description": "Installer data bundle: Asahi-style JSON + asset pack for M2; UEFI layout descriptor for generic targets.",
84+
"role": "installer-data",
85+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
86+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/installer-data.json",
87+
"sha256": "0000000000000000000000000000000000000000000000000000000000000035",
88+
"sizeBytes": 0,
89+
"contentType": "application/json",
90+
"sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/installer-data.spdx.json",
91+
"provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/installer-data.intoto.jsonl"
92+
},
93+
{
94+
"class": "manifest",
95+
"name": "sourceos-m2-build-manifest",
96+
"description": "Signed artifact manifest listing all lane artifact digests for this build result.",
97+
"role": "manifest",
98+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
99+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/manifest.json",
100+
"sha256": "0000000000000000000000000000000000000000000000000000000000000036",
101+
"sizeBytes": 0,
102+
"contentType": "application/json",
103+
"sbomRef": null,
104+
"provenanceRef": null
105+
},
106+
{
107+
"class": "checksums",
108+
"name": "sourceos-m2-sha256sums",
109+
"description": "Detached SHA256SUMS file over all lane artifacts for offline verification.",
110+
"role": "other",
111+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
112+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/SHA256SUMS",
113+
"sha256": "0000000000000000000000000000000000000000000000000000000000000037",
114+
"sizeBytes": 0,
115+
"contentType": "text/plain",
116+
"sbomRef": null,
117+
"provenanceRef": null
118+
},
119+
{
120+
"class": "sbom-reference",
121+
"name": "sourceos-m2-sbom",
122+
"description": "SPDX SBOM document covering the full artifact set produced by this build lane.",
123+
"role": "other",
124+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
125+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.spdx.json",
126+
"sha256": "0000000000000000000000000000000000000000000000000000000000000038",
127+
"sizeBytes": 0,
128+
"contentType": "application/spdx+json",
129+
"sbomRef": null,
130+
"provenanceRef": null
131+
},
132+
{
133+
"class": "provenance-reference",
134+
"name": "sourceos-m2-provenance",
135+
"description": "SLSA Build L2 + in-toto provenance bundle covering the full artifact set.",
136+
"role": "other",
137+
"platforms": ["apple-silicon", "uefi-x86_64", "generic-arm64"],
138+
"uri": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.intoto.jsonl",
139+
"sha256": "0000000000000000000000000000000000000000000000000000000000000039",
140+
"sizeBytes": 0,
141+
"contentType": "application/json",
142+
"sbomRef": null,
143+
"provenanceRef": null
144+
}
145+
],
146+
"provenance": {
147+
"builderId": "sourceos-recovery-installer-lane-demo-builder",
148+
"sourceRefs": [
149+
"git:SourceOS-Linux/sourceos-boot#main",
150+
"git:SociOS-Linux/nlboot#release-candidate"
151+
],
152+
"attestations": ["slsa", "in-toto"],
153+
"provenanceRef": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.intoto.jsonl"
154+
},
155+
"sbomRef": "https://example.invalid/build/sourceos/m2/0.1.0/sourceos-m2-recovery-installer.spdx.json",
156+
"sigstoreBundleRef": "sigstore-bundle-sourceos-m2-recovery-installer-lane-demo",
157+
"manifestDigest": "sha256:0000000000000000000000000000000000000000000000000000000000000036"
158+
}
159+
}

repo.maturity.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ maturity:
1818
- docs/M2_RECOVERY_INSTALLER_PACKAGING.md defines packaging responsibilities, required inputs, and evidence model for both M2 entry types.
1919
- src/sourceos_boot/adapter.py implements the nlboot-to-BootReleaseSet adapter.
2020
- src/sourceos_boot/control_plane.py implements the control-plane boot plan builder.
21-
- make validate exercises schema validation, new M2 fixtures, and the nlboot adapter CLI path.
21+
- make validate exercises schema validation, M2 fixtures, nlboot adapter CLI path, and the new artifact-build-lane fixture.
2222
- python -m pytest passes all tests.
2323
- docs/APPLE_SILICON_EVIDENCE_NORMALIZATION.md defines the normalization design for AppleSiliconAdapterEvidence into BootEvidence/BootProofRecord.
2424
- examples/apple-silicon-evidence/raw-apple-silicon-evidence.example.json is a dry-run raw AppleSiliconAdapterEvidence fixture.
2525
- examples/apple-silicon-evidence/normalized-boot-evidence.example.json is a dry-run normalized BootEvidence fixture showing the output of normalise_apple_silicon_evidence().
26+
- 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.
27+
- 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.
2628
validation:
2729
commands:
2830
- make validate
@@ -54,3 +56,6 @@ nextActions:
5456
- Add artifact digest verification and content-addressed cache path.
5557
- Emit evidence records from the boot/recovery execution boundary.
5658
- Wire M2 packaging adapter to produce platform entrypoint descriptors from BootReleaseSet.
59+
- Complete SBOM proof for NLBoot RC artifacts (sbomStatus is currently pending in artifact-build-lane fixture).
60+
- Automate Sigstore/cosign signing of artifact-build-lane manifest once NLBoot RC is stable.
61+
- Wire artifact-build-lane output into BootReleaseSet packaging step (spec.artifacts population from lane result).

0 commit comments

Comments
 (0)