# Plan: System Configuration Slice 3

## Overview

Slice 3 of the System Configuration and Operator Extensibility track from
`docs/proposals/system-configuration-proposal.md`. Slices 1 and 2 are
landed: the shared `defaults` package exists at `cue/defaults/defaults.cue`
and the repo-root packaged default boot manifest already imports it. Many
focused-proof manifests are migrated onto the defaults package; this plan
finishes migrating the remaining focused-proof variants and tightens the
manifest decoder boundary.

The track is ad-hoc until explicitly selected; treat this plan as
parallel-safe alongside the selected milestone because it edits CUE files
and limited tooling, not kernel core.

## Conflict Surface

Owned by this plan:

- `cue/defaults/defaults.cue` and any new `cue/defaults/*.cue` modules
- `capos-config/` (the manifest decoder/loader and its host tests; Task 3
  tightens the decoder boundary here). Coordinate with the Device Driver
  Foundation plan when DDF Task 5 adds ProcessSpawner/manifest plumbing,
  since DDF declares the same overlap on `capos-config/` and
  `tools/mkmanifest/`. Run the manifest-shape change on a single branch
  at a time so the focused-proof migration and DDF authority caps do not
  race the same loader.
- Repo-root focused-proof manifests:
  `system-spawn.cue`, `system-shell.cue`, `system-terminal.cue`,
  `system-credential.cue`, `system-login.cue`, `system-local-users.cue`,
  `system-login-setup.cue`, `system-network-client.cue`,
  `system-revocable-read.cue`, `system-memoryobject-shared.cue`,
  `system-restricted-shell-launcher.cue`, `system-telnet.cue`,
  `system-chat.cue`. `system-measure.cue` is owned by
  `docs/plans/measure-mode-repair.md` while the regression repair is
  open; migrate it onto the defaults package only after that plan
  closes, and only in a separate batch from this slice.
- `cue.mod/module.cue` (only when the CUE language version changes)
- `tools/mkmanifest/` only when the manifest input shape changes
- `system.local.cue.example`
- `docs/proposals/system-configuration-proposal.md`,
  `docs/configuration.md`

Do not touch from this plan:

- `system.cue` (default boot manifest) outside import-line adjustments
  required by the slice
- `system-paperclips.cue` and `system-adventure.cue` -- demo-owned
  manifests; coordinate via the demo plans
- Kernel-core, capability schema, runtime, scheduler, device manager
- `tools/remote-session-client/` (owned by remote-session plan)

## Validation Commands

- `make fmt-check`
- `cargo test-config`
- `cargo test-mkmanifest`
- `make generated-code-check`
- `make run-smoke`
- `make run-spawn`
- `make run-shell`
- `make run-terminal`

Per-batch QEMU gates -- run the matching `make run-*` target for each
manifest the batch migrated, in addition to the always-on commands above.
Treat any of these as required when the batch touches the corresponding
manifest:

- `make run-credential` for `system-credential.cue`
- `make run-login` for `system-login.cue`
- `make run-login-setup` for `system-login-setup.cue`
- `make run-local-users` for `system-local-users.cue`
- `make run-network-client` for `system-network-client.cue`
- `make run-revocable-read` for `system-revocable-read.cue`
- `make run-memoryobject-shared` for `system-memoryobject-shared.cue`
- `make run-restricted-shell-launcher` for `system-restricted-shell-launcher.cue`
- `make run-telnet` for `system-telnet.cue`
- `make run-chat` for `system-chat.cue`

## Success Criteria

Slice 3 is recorded done when every focused-proof manifest listed above
imports the defaults package, the manifest decoder rejects unknown
top-level fields cleanly, the `make run-*` target for each manifest
remains green, and `docs/proposals/system-configuration-proposal.md`
records the slice closeout with commit hash and minute-precision
timestamp.

### Task 1: Inventory the remaining focused-proof manifests

- [x] Enumerate every repo-root `system-*.cue` manifest, their current
      package status, and the `make run-*` target each one drives.
      Recorded as the Slice-3 manifest inventory table in
      `docs/proposals/system-configuration-proposal.md` at
      `2026-05-03 15:15 UTC`.
- [x] Note which manifests already import the defaults package (Slice 2
      landings) and which still ship without it. The inventory table
      records this per row; only `system-measure.cue` is unimported
      (owned by `docs/plans/measure-mode-repair.md`).
- [x] Capture the migration order: prefer manifests whose `make run-*`
      target is host-runnable in CI before manifests requiring
      operator-driven QEMU runs. Moot for the owned set because every
      focused-proof variant covered by this plan was already packaged
      before slice-3 reopened.

### Task 2: Migrate focused-proof manifests in batches

- [x] Migrate one batch of manifests (5-7 files) onto the defaults
      package per task iteration. Each batch must keep the matching
      `make run-*` target green. Closed `2026-05-03 15:15 UTC`: the
      owned focused-proof set was already packaged in earlier slice-3
      batches (commits `cd716ea2`, `751baf17`, `ebb0323c`,
      `6d397b15`, `069fb408`, `007f3019`, `2090f99b`); no manifest in
      the owned set still needs migration.
- [x] Keep the per-manifest diff small: import the defaults package and
      project only the manifest-specific fields. Each focused-proof
      manifest must keep its own distinct CUE package
      (`package spawn`, `package chat`, `package adventure`, etc.) so
      package-mode `cue export` for the default boot does not merge
      unrelated focused manifests with `system.cue`/`system.local.cue`
      (those use `package capos`). Verified by the inventory table:
      every owned manifest declares a distinct package name.
- [x] Record each batch in `docs/proposals/system-configuration-proposal.md`
      with the manifests covered. Final closeout recorded in the
      Slice-3 inventory table and the proposal status header.

### Task 3: Tighten the manifest decoder boundary

- [x] After every focused-proof manifest is migrated, tighten the
      decoder/loader to reject unknown top-level fields and verify that
      legacy unmigrated layouts now fail closed. Closed
      `2026-05-03 20:22 UTC` at commit `f3d89757`: the
      `SystemManifest` CUE decoder validates the document root
      against `SYSTEM_MANIFEST_ROOT_FIELDS` (`schemaVersion`,
      `binaries`, `initConfig`, `kernelParams`) and returns
      `Error::UnknownField` for any other name.
- [x] Add a `cargo test-config` host test that exercises the rejection
      path so regressions are caught before QEMU runs. Two tests in
      `capos-config/src/manifest.rs` —
      `system_manifest_rejects_unknown_root_field` and
      `system_manifest_accepts_only_known_root_fields` — pin the
      behavior; full `cargo test-config` (348 tests) passes.
- [x] Document the strictness change in
      `docs/proposals/system-configuration-proposal.md` and
      `docs/configuration.md`. Slice-3 Task-3 closeout note added to
      the proposal; `docs/configuration.md` "How the layering works"
      paragraph now documents the typed `unknown field` error and how
      to fix a typo.

### Task 4: Operator overlay worked example refresh

- [x] Refresh `system.local.cue.example` so it covers an operator
      extension that exercises the migrated defaults package without
      needing `tools/mkmanifest` flag changes. Closed
      `2026-05-03 18:51 EEST`: the example now covers every extension
      hook the migrated defaults package exposes — MOTD,
      `consolePasswordVerifierPhc`, `extraAuthorizedSshKeys`,
      `extraSeedAccounts`, `extraResourceProfiles`, `extraBinaries`,
      and `extraServices`. The previous example shipped only the
      first four hooks; `extraBinaries` and `extraServices` (added
      by the defaults package as `list.Concat` extension inputs) and
      `consolePasswordVerifierPhc` (overridable default) were missing.
- [x] Verify the example by copying it to repo-root `system.local.cue`
      (gitignored) and rerunning `make run`. `make run` is
      interactive, so verification ran `make manifest` (default
      `MANIFEST_SOURCE=system.cue`, package mode `--package capos`,
      log `target/manifest-refreshed-example.log`). The package-mode
      rebuild embedded the operator MOTD into `manifest.bin` (3
      services, 12 binaries → 2551416 bytes); rebuilding the same
      target with the overlay absent produced 2553224 bytes,
      confirming the operator MOTD overrode the defaults' default.
      `make run-smoke` was checked but is not a useful overlay
      verification because it builds `manifest-smoke.bin` from
      `system-smoke.cue` in single-file mode (no `--package` flag,
      no sibling-file unification); md5 of `manifest-smoke.bin` was
      identical with and without the overlay. Documented in the
      proposal Slice-3 closeout note.
- [x] Update `docs/configuration.md` to match the refreshed example.
      Added recipes for "Add a binary and an init-launched service"
      and "Override the console password verifier".

### Task 5: Closeout

- [x] Update `docs/proposals/system-configuration-proposal.md` slice 3
      status, mark the migrated manifests, and pin the closeout commit.
      Closed `2026-05-03 21:54 UTC` at commit `a50f610d`: the
      proposal status header, the Slice-3 row in the Migration Plan
      table, and the page `last_reviewed` are stamped with the
      closeout SHA and timestamp.
- [x] Update `WORKPLAN.md`'s System Configuration ad-hoc bullet to
      record Slice 3 done and to flag any successor slice (e.g. richer
      operator overlays) for future selection. Closed
      `2026-05-03 21:54 UTC`: the bullet is now `[x]`, references the
      closeout SHA, names what each task closed, and flags
      `system-measure.cue` (measure-mode-repair plan) and
      `system-paperclips.cue` / `system-adventure.cue` (demo-owned)
      as the residual successor scope.
- [x] Add a `docs/changelog.md` entry referencing the closeout commit.
      Closed `2026-05-03 21:54 UTC`: a single milestone entry "System
      Configuration Slice 3 -- focused-proof migration + manifest
      decoder strictness closed" lists the closure scope, evidence,
      and reproduction commands.
