Skip to content
Open
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
61 changes: 61 additions & 0 deletions docs/contract-additions/immutable-node-profiles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Immutable Node Profile Contracts

This contract addition defines the first SourceOS machine-readable surface for immutable Linux node profiles.

## Why this exists

The platform standards layer already defines the general immutable host capability placement grammar. SourceOS needs a contract-native form that downstream implementation repos can validate, render, and emit evidence for.

The key boundary is:

- SourceOS immutable nodes are base substrate profiles.
- Socios capability packs are optional automation commons and must not be required for a base SourceOS node.

## Added schemas

| Schema | Purpose | URN prefix |
|---|---|---|
| `ImmutableNodeProfile.json` | Top-level immutable node profile tying together substrate posture, release refs, host placements, state schemas, validation commands, and optional Socios pack refs. | `urn:srcos:immutable-node-profile:` |
| `HostCapabilityPlacement.json` | Placement declaration for one host capability, service workload, extension, or state root. | `urn:srcos:host-capability-placement:` |
| `NodeStateSchema.json` | Durable state root contract with rollback compatibility and mutability posture. | `urn:srcos:node-state-schema:` |

## Added examples

| Example | Schema |
|---|---|
| `examples/immutablenodeprofile.json` | `schemas/ImmutableNodeProfile.json` |
| `examples/hostcapabilityplacement.json` | `schemas/HostCapabilityPlacement.json` |
| `examples/nodestateschema.json` | `schemas/NodeStateSchema.json` |

## Validation

The focused validator is:

```bash
python3 tools/validate_immutable_node_examples.py
```

A future hygiene pass should wire this into the repository `Makefile` and `schemas/README.md` once the contract slice is accepted.

## Downstream implementation map

| Downstream repo | Expected role |
|---|---|
| `SourceOS-Linux/sourceos-boot` | Consumes boot/release references and coordinates boot/recovery/install/rollback handoff. |
| `SourceOS-Linux/agent-machine` | Renders and validates systemd, Quadlet, state roots, activation decisions, storage receipts, and runtime evidence. |
| `SourceOS-Linux/sourceos-devtools` | Exposes `sourceosctl immutable-node plan|validate|inspect` operator flows. |
| `SocioProphet/agentplane` | Consumes immutable-node activation/runtime evidence and replayable receipts. |
| `SocioProphet/prophet-platform` | Consumes profiles as deployment/FogStack substrate evidence. |
| `SocioProphet/sociosphere` | Registers topology and cross-repo governance edges. |
| `SociOS-Linux/socios` | Optional automation/personalization commons only after explicit enrollment. |

## Non-goals

This tranche does not:

- implement boot execution;
- mutate host state;
- make Socios mandatory;
- replace BootReleaseSet;
- add a production node renderer;
- add CI or Makefile wiring yet.
20 changes: 20 additions & 0 deletions examples/hostcapabilityplacement.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"id": "urn:srcos:host-capability-placement:sourceos-supervisor",
"type": "HostCapabilityPlacement",
"specVersion": "2.2.0",
"name": "SourceOS host supervisor",
"placementClass": "image-baked-host-capability",
"authority": "sourceos-base",
"mandatoryForBaseNode": true,
"requiresEnrollment": false,
"lifecycleCoupling": "host-release",
"pathHints": [
"/usr/libexec/sourceos/supervisor",
"/usr/lib/systemd/system/sourceos-supervisor.service"
],
"evidenceRefs": [
"urn:srcos:release-receipt:sourceos-supervisor-bootstrap"
],
"policyRef": "urn:srcos:policy:immutable-node-host-supervisor",
"notes": "Base SourceOS capability. This is not a Socios enrollment dependency."
}
39 changes: 39 additions & 0 deletions examples/immutablenodeprofile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"id": "urn:srcos:immutable-node-profile:m2-asahi-dev",
"type": "ImmutableNodeProfile",
"specVersion": "2.2.0",
"name": "M2 Asahi SourceOS dev immutable node",
"channel": "m2-asahi-dev",
"substrate": {
"strategy": "bootc-first",
"hostMutationPosture": "staged-updates-only",
"sociosRequired": false
},
"bootReleaseSetRef": "urn:srcos:boot-release-set:m2-asahi-dev",
"releaseSetRef": "urn:srcos:release-set:m2-asahi-dev",
"workstationProfileRef": "urn:srcos:workstation-profile:workstation-v0",
"agentMachineProfileRef": "urn:srcos:agent-machine-profile:m2-asahi-dev",
"hostCapabilityPlacementRefs": [
"urn:srcos:host-capability-placement:sourceos-supervisor"
],
"nodeStateSchemaRefs": [
"urn:srcos:node-state-schema:sourceos-evidence-root"
],
"optionalSociosCapabilityPackRefs": [
"urn:socios:capability-pack:automation-commons-opt-in"
],
"validation": {
"planCommand": "sourceosctl immutable-node plan --profile m2-asahi-dev --dry-run",
"validateCommand": "sourceosctl immutable-node validate --profile m2-asahi-dev",
"inspectCommand": "sourceosctl immutable-node inspect --profile m2-asahi-dev",
"evidenceCommand": "agent-machine release evidence inspect --profile m2-asahi-dev"
},
"policyRefs": [
"urn:srcos:policy:immutable-node-base",
"urn:srcos:policy:socios-opt-in-required"
],
"evidenceRefs": [
"urn:srcos:release-receipt:m2-asahi-dev"
],
"notes": "SourceOS base node profile. Socios pack reference is optional and does not imply enrollment."
}
14 changes: 14 additions & 0 deletions examples/nodestateschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "urn:srcos:node-state-schema:sourceos-evidence-root",
"type": "NodeStateSchema",
"specVersion": "2.2.0",
"name": "SourceOS evidence root",
"rootPath": "/var/lib/sourceos/evidence",
"stateClass": "append-only-evidence",
"schemaRef": "urn:srcos:release-receipt:sourceos-evidence",
"rollbackCompatibility": "required-n-and-n-minus-1",
"mutability": "append-only",
"owner": "agent-machine",
"evidenceRequired": true,
"notes": "Durable evidence root survives host rollback and must preserve reader compatibility."
}
100 changes: 100 additions & 0 deletions schemas/HostCapabilityPlacement.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.srcos.ai/v2/HostCapabilityPlacement.json",
"title": "HostCapabilityPlacement",
"description": "A SourceOS immutable-node placement declaration for one host capability, service workload, extension, or state root.",
"type": "object",
"additionalProperties": false,
"required": [
"id",
"type",
"specVersion",
"name",
"placementClass",
"authority"
],
"properties": {
"id": {
"type": "string",
"pattern": "^urn:srcos:host-capability-placement:",
"description": "Stable URN identifier. Pattern: urn:srcos:host-capability-placement:<local-id>."
},
"type": {
"const": "HostCapabilityPlacement",
"description": "Discriminator constant — always HostCapabilityPlacement."
},
"specVersion": {
"type": "string",
"description": "Spec version of this document, e.g. 2.2.0."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable capability name."
},
"placementClass": {
"type": "string",
"enum": [
"image-baked-host-capability",
"sysext-host-capability",
"confext-policy-config-capability",
"quadlet-bound-service-workload",
"quadlet-floating-service-workload",
"var-state-object"
],
"description": "Canonical placement class inherited from the immutable-node host capability model."
},
"authority": {
"type": "string",
"enum": [
"sourceos-base",
"sourceos-boot",
"agent-machine",
"sourceos-devtools",
"agentplane",
"prophet-platform",
"socios-optional-pack"
],
"description": "Repo or plane class that owns the implementation boundary for this capability."
},
"mandatoryForBaseNode": {
"type": "boolean",
"default": false,
"description": "Whether the capability is required for a base SourceOS immutable node without Socios enrollment."
},
"requiresEnrollment": {
"type": "boolean",
"default": false,
"description": "Whether activation requires opt-in enrollment, Proof-of-Life, or signed intent."
},
"lifecycleCoupling": {
"type": "string",
"enum": [
"host-release",
"extension-release",
"service-release",
"state-schema",
"operator-local"
],
"description": "Primary lifecycle to which this capability is coupled."
},
"pathHints": {
"type": "array",
"items": { "type": "string" },
"description": "Expected implementation paths such as /usr/libexec/sourceos, /usr/share/containers/systemd, /var/lib/sourceos, or /var/lib/socios."
},
"evidenceRefs": {
"type": "array",
"items": { "type": "string" },
"description": "Optional references to evidence records emitted by the capability."
},
"policyRef": {
"type": ["string", "null"],
"description": "Optional policy identifier or URN governing activation or mutation."
},
"notes": {
"type": ["string", "null"],
"description": "Human-readable review notes."
}
}
}
118 changes: 118 additions & 0 deletions schemas/ImmutableNodeProfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.srcos.ai/v2/ImmutableNodeProfile.json",
"title": "ImmutableNodeProfile",
"description": "A SourceOS immutable-node profile tying together boot/release references, host capability placements, durable state schemas, validation entrypoints, and optional Socios capability-pack posture.",
"type": "object",
"additionalProperties": false,
"required": [
"id",
"type",
"specVersion",
"name",
"channel",
"substrate"
],
"properties": {
"id": {
"type": "string",
"pattern": "^urn:srcos:immutable-node-profile:",
"description": "Stable URN identifier. Pattern: urn:srcos:immutable-node-profile:<local-id>."
},
"type": {
"const": "ImmutableNodeProfile",
"description": "Discriminator constant — always ImmutableNodeProfile."
},
"specVersion": {
"type": "string",
"description": "Spec version of this document, e.g. 2.2.0."
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable immutable node profile name."
},
"channel": {
"type": "string",
"minLength": 1,
"description": "Realization channel such as linux-dev, linux-stable, m2-asahi-dev, or fog-node."
},
"substrate": {
"type": "object",
"additionalProperties": false,
"required": ["strategy", "hostMutationPosture", "sociosRequired"],
"properties": {
"strategy": {
"type": "string",
"enum": ["bootc-first", "ostree-compatible", "rpm-ostree", "coreos-assembler", "nixos-adapter", "other"],
"description": "Primary immutable-host realization strategy."
},
"hostMutationPosture": {
"type": "string",
"enum": ["immutable-runtime", "staged-updates-only", "lab-live-mutation-allowed", "unknown"],
"description": "Allowed host mutation posture for this profile."
},
"sociosRequired": {
"const": false,
"description": "Base SourceOS immutable nodes must not require Socios enrollment. Optional Socios packs are modeled separately."
}
}
},
"bootReleaseSetRef": {
"type": ["string", "null"],
"description": "Optional BootReleaseSet or boot/recovery handoff reference."
},
"releaseSetRef": {
"type": ["string", "null"],
"description": "Optional ReleaseSet assignment reference."
},
"workstationProfileRef": {
"type": ["string", "null"],
"description": "Optional WorkstationProfile reference for desktop/workstation realization."
},
"agentMachineProfileRef": {
"type": ["string", "null"],
"description": "Optional Agent Machine or AgentPod profile reference for local runtime realization."
},
"hostCapabilityPlacementRefs": {
"type": "array",
"items": { "type": "string", "pattern": "^urn:srcos:host-capability-placement:" },
"description": "References to HostCapabilityPlacement objects used by this profile."
},
"nodeStateSchemaRefs": {
"type": "array",
"items": { "type": "string", "pattern": "^urn:srcos:node-state-schema:" },
"description": "References to NodeStateSchema objects used by this profile."
},
"optionalSociosCapabilityPackRefs": {
"type": "array",
"items": { "type": "string" },
"description": "Optional Socios capability pack references. Presence does not imply base node dependency or enrollment."
},
"validation": {
"type": "object",
"additionalProperties": false,
"properties": {
"planCommand": { "type": ["string", "null"] },
"validateCommand": { "type": ["string", "null"] },
"inspectCommand": { "type": ["string", "null"] },
"evidenceCommand": { "type": ["string", "null"] }
},
"description": "Operator-facing dry-run, validation, inspection, and evidence entrypoints."
},
"policyRefs": {
"type": "array",
"items": { "type": "string" },
"description": "Policy references that govern activation, mutation, enrollment, or rollback."
},
"evidenceRefs": {
"type": "array",
"items": { "type": "string" },
"description": "Evidence or receipt references expected from this node profile."
},
"notes": {
"type": ["string", "null"],
"description": "Human-readable review notes."
}
}
}
Loading