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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Thi
## [Unreleased]

### Added
- NLBoot object schemas: `NLBootPlan`, `ArtifactCacheRecord`, `BootProofRecord`, `AppleSiliconAdapterEvidence` with canonical examples and validation (`tools/validate_nlboot_examples.py`)
- Compression Commons: `CompressionEvaluation` schema and canonical example (`examples/compressionevaluation.json`)
- Truth Plane: `TruthSurface` and `DeltaSurface` schemas + canonical examples (`examples/truth_surface.json`, `examples/delta_surface.json`)
- Control-plane: `IncidentEvent` schema for incident lifecycle events
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
.PHONY: validate validate-control-plane-examples
.PHONY: validate validate-control-plane-examples validate-nlboot-examples

validate: validate-control-plane-examples
validate: validate-control-plane-examples validate-nlboot-examples
@echo "OK: validate"

validate-control-plane-examples:
python3 -m pip install --user jsonschema >/dev/null
python3 tools/validate_control_plane_examples.py

validate-nlboot-examples:
python3 -m pip install --user jsonschema >/dev/null
python3 tools/validate_nlboot_examples.py
68 changes: 68 additions & 0 deletions docs/adr/0011-nlboot-object-schemas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# ADR-0011: NLBoot Object Schemas

**Date:** 2026-04-30
**Status:** `Accepted`
**Deciders:** SourceOS-Linux/sourceos-spec maintainers

---

## Context

The NLBoot system orchestrates Linux boot on Apple Silicon (Asahi) and generic UEFI targets. It manages ordered boot stages, locally cached artifacts, per-boot integrity proofs, and Apple Silicon–specific adapter evidence.

Without canonical object schemas in this repository, downstream repos risk inventing overlapping structures for boot plans, artifact caching, proof reporting, and Apple Silicon adapter state. The `SourceOS-Linux/sourceos-spec` repository is the normative home for machine-readable contracts consumed by NLBoot, sourceos-boot, Sociosphere, and control-plane surfaces.

## Decision

Introduce four new top-level schemas in the Boot / NLBoot family:

| Schema | URN prefix | Purpose |
|--------|-----------|---------|
| `NLBootPlan` | `urn:srcos:nlboot-plan:` | Ordered boot stage plan for a target device |
| `ArtifactCacheRecord` | `urn:srcos:artifact-cache:` | Content-addressed local artifact cache entry |
| `BootProofRecord` | `urn:srcos:boot-proof:` | Immutable per-boot integrity proof with stage verdicts |
| `AppleSiliconAdapterEvidence` | `urn:srcos:as-adapter-evidence:` | Asahi-compatible Apple Silicon adapter evidence |

All four schemas follow the standard v2 conventions: `$id` under `https://schemas.srcos.ai/v2/`, `additionalProperties: false`, required `id`/`type`/`specVersion` discriminators, and `description` on every property.

### Scope of this repository

This repository owns:
- canonical JSON Schema definitions for the four types
- conforming example payloads
- validation tooling (`tools/validate_nlboot_examples.py`)

This repository does not own:
- NLBoot runtime boot executor implementation (`SociOS-Linux/nlboot`)
- Apple Silicon boot-chain implementation (`SociOS-Linux/asahi-u-boot`, `SociOS-Linux/asahi-installer`)
- transport bindings or RPC protocol definitions

## Alternatives considered

| Alternative | Reason not chosen |
|-------------|------------------|
| Add schemas inside `schemas/control-plane/` | NLBoot objects are boot-plane contracts, not legacy control-plane objects; they belong at the top level |
| Single merged `NLBootEvidence` schema covering all four concerns | Each concern has distinct required fields and lifecycle; splitting keeps schemas compact and independently consumable |
| Re-use existing `AttestationEvidence` for Apple Silicon evidence | `AttestationEvidence` models TPM/IMA measured-boot evidence; Apple Silicon adapter evidence captures Asahi-specific boot picker and m1n1/U-Boot state that does not fit that model |

## Consequences

### Positive

- downstream repos can reference canonical URN-typed NLBoot objects without re-inventing structure
- boot plan, artifact cache, and proof record objects are independently versioned and independently consumable
- Apple Silicon adapter evidence is first-class and auditable, not embedded in ad hoc implementation logs
- all four schemas are immediately validated by `make validate-nlboot-examples`

### Constraints

- schemas are intentionally minimal at introduction; fields may be added additively in follow-on PRs
- proof reporting endpoint binding (`policyDecisionRef`, `evidenceRefs`) is normative contract only; enforcement belongs in runtime repos

## References

- Issue: SourceOS-Linux/sourceos-spec — "Agent task: add NLBoot object schemas"
- ADR-0008: Local-first release and enrollment contract family
- ADR-2026-04: Contract vs Bootstrap Boundaries
- `schemas/BootSurface.json` — related boot-surface schema
- `schemas/AttestationEvidence.json` — measured-boot attestation evidence
4 changes: 4 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ These examples illustrate the shared object family used by SourceOS artifact bui
| `access_profile.json` | AccessProfile | Access profile for SourceOS build operators and agentplane executor obligations |
| `agreement.json` | Agreement | Default personal-data agreement |
| `agent_session.json` | AgentSession | An executor session running the obfuscation workflow |
| `apple_silicon_adapter_evidence.json` | AppleSiliconAdapterEvidence | Apple Silicon adapter evidence for an M2 device running SourceOS via Asahi |
| `artifact_cache_record.json` | ArtifactCacheRecord | Cached Linux kernel artifact for the M2 demo device |
| `asset.json` | PhysicalAsset | Lakehouse asset for curated health observations |
| `boot_proof_record.json` | BootProofRecord | Verified boot proof for SourceOS M2 device via NLBoot Asahi path |
| `boot_release_set.json` | BootReleaseSet | SourceOS Recovery Environment boot artifact set for secure recovery/provisioning |
| `build_request.json` | BuildRequest | SourceOS Workstation build request with agentplane and Katello refs |
| `capability_token.json` | CapabilityToken | Access token scoped to the health dataset export operation |
Expand All @@ -157,6 +160,7 @@ These examples illustrate the shared object family used by SourceOS artifact bui
| `glossary.json` | GlossaryTerm | Glossary term for "Date of Birth" |
| `mapping.json` | MappingSpec | A field mapping between two dataset fields |
| `memory_entry.json` | MemoryEntry | A learned memory entry from an agent session |
| `nlboot_plan.json` | NLBootPlan | NLBoot boot plan for SourceOS M2 demo device via Asahi path |
| `offer.json` | Offer | FogCompute provider offer |
| `overlay_bundle.json` | OverlayBundle | Customer branding overlay applied to the workstation flavor |
| `policy.json` | Policy | Health export must be obfuscated |
Expand Down
21 changes: 21 additions & 0 deletions examples/apple_silicon_adapter_evidence.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"id": "urn:srcos:as-adapter-evidence:m2-adapter-2026-04-30",
"type": "AppleSiliconAdapterEvidence",
"specVersion": "2.0.0",
"deviceRef": "urn:srcos:asset:fedora-asahi-m2",
"capturedAt": "2026-04-30T09:55:00Z",
"chipModel": "M2",
"boardId": "J413AP",
"securityPolicy": "reduced-security",
"localBootStatus": "ok",
"adapterVersion": "0.4.0",
"m1n1Version": "1.4.6",
"uBootVersion": "2024.01-asahi-4",
"bootChainHashes": {
"m1n1": "sha256:7a38f2d1e4b9c3a5d6e8f0b2c4a6d8e0f2b4c6a8d0e2f4b6c8a0d2e4f6b8c0a2",
"u-boot": "sha256:2b4d6f8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f"
},
"bootPickerEntryRef": "urn:srcos:boot-entry:m2-demo-sourceos-asahi-installer",
"installerDataRef": "urn:srcos:artifact:m2-demo-asahi-installer-data-sha256-3f9c1f44",
"notes": "Apple Silicon adapter evidence for M2 MacBook Air running SourceOS via Asahi path."
}
15 changes: 15 additions & 0 deletions examples/artifact_cache_record.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"id": "urn:srcos:artifact-cache:kernel-sha256-0f3b6d7f",
"type": "ArtifactCacheRecord",
"specVersion": "2.0.0",
"artifactKind": "kernel",
"contentHash": "sha256:0f3b6d7f1e2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c",
"status": "cached",
"cachedAt": "2026-04-29T18:00:00Z",
"platform": "apple-silicon-asahi",
"sourceUrl": "https://cdn.asahilinux.org/m2/kernel-6.8.0-asahi-20240415.tar.gz",
"sourceRef": "urn:srcos:boot-release-set:m2-demo-recovery-2026-04-26",
"sizeBytes": 12582912,
"expiresAt": "2026-07-29T18:00:00Z",
"notes": "Linux kernel 6.8 with Apple Silicon patches for the M2 demo device."
}
45 changes: 45 additions & 0 deletions examples/boot_proof_record.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"id": "urn:srcos:boot-proof:m2-sourceos-boot-2026-04-30",
"type": "BootProofRecord",
"specVersion": "2.0.0",
"bootPlanRef": "urn:srcos:nlboot-plan:m2-sourceos-main-2026-04-30",
"deviceRef": "urn:srcos:asset:fedora-asahi-m2",
"outcome": "success",
"bootedAt": "2026-04-30T10:00:00Z",
"stageProofs": [
{
"stageName": "m1n1",
"artifactRef": "urn:srcos:artifact-cache:m1n1-sha256-7a38f2d1",
"contentHash": "sha256:7a38f2d1e4b9c3a5d6e8f0b2c4a6d8e0f2b4c6a8d0e2f4b6c8a0d2e4f6b8c0a2",
"verdict": "verified",
"notes": null
},
{
"stageName": "u-boot",
"artifactRef": "urn:srcos:artifact-cache:uboot-sha256-2b4d6f8a",
"contentHash": "sha256:2b4d6f8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f",
"verdict": "verified",
"notes": null
},
{
"stageName": "kernel",
"artifactRef": "urn:srcos:artifact-cache:kernel-sha256-0f3b6d7f",
"contentHash": "sha256:0f3b6d7f1e2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c",
"verdict": "verified",
"notes": null
},
{
"stageName": "initrd",
"artifactRef": "urn:srcos:artifact-cache:initrd-sha256-08f4c82e",
"contentHash": "sha256:08f4c82e9d0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
"verdict": "verified",
"notes": null
}
],
"evidenceRefs": [
"urn:srcos:attestation:m2-boot-evidence-2026-04-30"
],
"policyDecisionRef": "urn:srcos:decision:boot-m2-demo-v1-2026-04-30",
"signature": null,
"notes": "Successful verified boot of SourceOS on M2 demo device via NLBoot Asahi path."
}
43 changes: 43 additions & 0 deletions examples/nlboot_plan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"id": "urn:srcos:nlboot-plan:m2-sourceos-main-2026-04-30",
"type": "NLBootPlan",
"specVersion": "2.0.0",
"targetDeviceRef": "urn:srcos:asset:fedora-asahi-m2",
"platform": "apple-silicon-asahi",
"status": "active",
"stages": [
{
"name": "m1n1",
"artifactRef": "urn:srcos:artifact-cache:m1n1-sha256-7a38f2d1",
"contentHash": "sha256:7a38f2d1e4b9c3a5d6e8f0b2c4a6d8e0f2b4c6a8d0e2f4b6c8a0d2e4f6b8c0a2",
"verificationRequired": true,
"notes": "Primary Apple Silicon stage-1 bootloader"
},
{
"name": "u-boot",
"artifactRef": "urn:srcos:artifact-cache:uboot-sha256-2b4d6f8a",
"contentHash": "sha256:2b4d6f8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f6b8a0c2e4f",
"verificationRequired": true,
"notes": "U-Boot stage for EFI handoff"
},
{
"name": "kernel",
"artifactRef": "urn:srcos:artifact-cache:kernel-sha256-0f3b6d7f",
"contentHash": "sha256:0f3b6d7f1e2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c",
"verificationRequired": true,
"notes": "Linux kernel with Apple Silicon patches"
},
{
"name": "initrd",
"artifactRef": "urn:srcos:artifact-cache:initrd-sha256-08f4c82e",
"contentHash": "sha256:08f4c82e9d0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
"verificationRequired": true,
"notes": "Initial ramdisk for early userspace"
}
],
"bootReleaseSetRef": "urn:srcos:boot-release-set:m2-demo-recovery-2026-04-26",
"policyRef": "urn:srcos:policy:boot-recovery-m2-demo-v1",
"activatedAt": "2026-04-30T10:00:00Z",
"createdAt": "2026-04-30T09:00:00Z",
"notes": "Main boot plan for SourceOS M2 demo device using Asahi Linux path."
}
110 changes: 110 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ tags:
description: Workflows, runs, and provenance records
- name: Collaboration
description: Comments and ratings
- name: Boot
description: NLBoot plans, artifact cache, proof records, and Apple Silicon adapter evidence

components:
securitySchemes:
Expand Down Expand Up @@ -524,3 +526,111 @@ paths:
description: Request body is valid JSON but fails schema validation.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }


/v2/nlboot-plans:
post:
operationId: upsertNLBootPlan
summary: Upsert an NLBootPlan
description: Creates or updates an NLBoot boot plan describing ordered boot stages, artifact refs, and verification policy for a target device. Idempotent on `id`.
tags: [Boot]
requestBody:
required: true
content:
application/json:
schema: { $ref: './schemas/NLBootPlan.json' }
responses:
'200':
description: NLBootPlan created or updated successfully.
'400':
description: Request body is malformed JSON.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'401':
description: Missing or invalid authentication token.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'403':
description: Authenticated subject is not permitted to upsert boot plans.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'422':
description: Request body is valid JSON but fails schema validation.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }

/v2/artifact-cache-records:
post:
operationId: upsertArtifactCacheRecord
summary: Upsert an ArtifactCacheRecord
description: Creates or updates a content-addressed cache entry for a locally-stored NLBoot artifact. Idempotent on `id`.
tags: [Boot]
requestBody:
required: true
content:
application/json:
schema: { $ref: './schemas/ArtifactCacheRecord.json' }
responses:
'200':
description: ArtifactCacheRecord created or updated successfully.
'400':
description: Request body is malformed JSON.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'401':
description: Missing or invalid authentication token.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'403':
description: Authenticated subject is not permitted to upsert artifact cache records.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'422':
description: Request body is valid JSON but fails schema validation.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }

/v2/boot-proof-records:
post:
operationId: recordBootProof
summary: Record a BootProofRecord
description: Persists an immutable boot integrity proof record with per-stage verdicts and attestation evidence refs. Idempotent on `id`.
tags: [Boot]
requestBody:
required: true
content:
application/json:
schema: { $ref: './schemas/BootProofRecord.json' }
responses:
'200':
description: BootProofRecord persisted successfully.
'400':
description: Request body is malformed JSON.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'401':
description: Missing or invalid authentication token.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'403':
description: Authenticated subject is not permitted to record boot proofs.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'422':
description: Request body is valid JSON but fails schema validation.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }

/v2/apple-silicon-adapter-evidence:
post:
operationId: recordAppleSiliconAdapterEvidence
summary: Record AppleSiliconAdapterEvidence
description: Persists evidence collected by the Asahi-compatible Apple Silicon boot adapter, capturing chip identity, security policy, and boot-chain hashes. Idempotent on `id`.
tags: [Boot]
requestBody:
required: true
content:
application/json:
schema: { $ref: './schemas/AppleSiliconAdapterEvidence.json' }
responses:
'200':
description: AppleSiliconAdapterEvidence persisted successfully.
'400':
description: Request body is malformed JSON.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'401':
description: Missing or invalid authentication token.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'403':
description: Authenticated subject is not permitted to record Apple Silicon adapter evidence.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
'422':
description: Request body is valid JSON but fails schema validation.
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
Loading