# Manifest and Service Startup

The manifest is the boot package and init configuration. It names embedded
binaries, the single kernel-launched init process, kernel boot parameters, and
the init-owned service graph used by focused executor manifests.


## Current Behavior

`tools/mkmanifest` requires the repo-pinned CUE compiler, evaluates
`system.cue`, embeds declared binaries, validates binary references and the
init-owned authority graph under `initConfig`, serializes `SystemManifest`, and
places `manifest.bin` into the ISO. The kernel receives that file as the single
Limine module. The diagram below is intentionally large: it separates the
default init-owned boot path from the focused spawn-proof path.

```mermaid
flowchart TD
    Cue[system.cue or system-spawn.cue] --> Mkmanifest[tools/mkmanifest]
    Binaries[release userspace binaries] --> Mkmanifest
    Mkmanifest --> Manifest[manifest.bin SystemManifest]
    Manifest --> Limine[Limine boot module]
    Limine --> Kernel[kernel parse and validate]
    Kernel --> InitCaps[init CapTable and CapSet page]
    InitCaps --> Init[enter initConfig.init process]
    Init --> ShellPath[default system.cue: spawn shell/remote CapSet gateway/services]
    Init --> SpawnPath[focused system-spawn.cue: standalone init executor]
    SpawnPath --> BootPackage[BootPackage.readManifest chunks]
    BootPackage --> Plan[capos-config ManifestBootstrapPlan validation]
    SpawnPath --> Spawner[ProcessSpawner.spawn]
    Spawner --> Children[init-spawned child processes]
```

The default manifest starts only `initConfig.init` from the kernel, and that
process is now the standalone `init` ELF. Init receives the bootstrap authority
needed to read BootPackage, validate `initConfig.services`, spawn the
foreground shell, remote-session CapSet gateway, resident chat service, and
other default services, then wait according to the manifest policy. The shell
is an init-started service; it receives terminal, credential-store,
session-manager, audit-log, and authority-broker caps, mints its own anonymous
`UserSession`, and waits for an explicit `login` or `setup` command before
upgrading. It never holds BootPackage or broad ProcessSpawner authority.

Focused shell-led manifests such as `system-smoke.cue` and `system-shell.cue`
still put `capos-shell` directly in `initConfig.init` for narrow login/shell
proofs. That compatibility path is tracked by the run-target/init-policy
backlog and should not be confused with the default `system.cue` boot path.

The focused `system-spawn.cue` manifest still puts the standalone `init` ELF in
`initConfig.init`.
There, init receives `ProcessSpawner`, a read-only `BootPackage` cap, and
Console. It reads bounded manifest chunks into a metadata-only
`capos-config::ManifestBootstrapPlan`, validates binary references, authority
graph structure, exports, cap sources, and interface IDs, then spawns the
focused smoke services. Low-level spawn grants still model receiver selectors
for hostile and compatibility proofs, but normal shell `client @...` grants
omit selector syntax and preserve delegated client endpoint identity. Raw
parent-capability grants must preserve the source hold metadata,
endpoint-client grants may mint selectors only from an endpoint owner or a
`ProcessSpawner`-returned parent endpoint facet without widening it to server
authority, and kernel-source Endpoint, FrameAllocator, VirtualMemory, Timer,
ThreadControl, ThreadSpawner, and EntropySource grants mint fresh child-local
caps without receiver selectors. QEMU-only PersistentStore grants mount the
root store through the same child-local kernel-source path when a focused proof
manifest names that source. Endpoint kernel grants also return parent-side
client facets as `ProcessSpawner` result caps so init can wire later
service-sourced imports without ever holding child endpoint owner caps.

`mkmanifest cue-to-capnp` is the adjacent general conversion path for
CUE-authored data that should not become part of `SystemManifest`. It evaluates
the input with the same pinned CUE compiler, package mode, tag injection, and
`CAPOS_CUE_TAGS` handling as the manifest path, then passes the exported JSON
to the pinned Cap'n Proto compiler through `capnp convert json:binary`. The
caller supplies the `.capnp` schema file, root struct type, output path, and
optional Cap'n Proto import paths. This is schema-aware serialization for data
messages rooted at arbitrary specified structs; it is not a live capability or
interface-object serialization path.

## Design

Manifest validation has three layers:

- Kernel bootstrap references: binary names are unique, `initConfig.init.binary`
  resolves, referenced payloads are non-empty, and init kernel cap sources match
  their expected interface IDs.
- Init-owned binary references: `initConfig.services[*].binary` references
  resolve before the executor spawns children.
- Init-owned authority graph: service names, cap names, export names, and
  service-sourced references are unique and resolvable; re-exporting
  service-sourced caps is rejected.
- Init-owned cap sources: expected interface IDs match kernel sources or
  declared service exports.

Kernel startup now resolves only `initConfig.init.caps`. Init performs service
execution in two userspace passes. The preflight pass walks
`initConfig.services` in manifest order, resolves kernel and service-sourced
caps against init grants and prior exports, and rejects an unstartable graph
before spawning children. The spawn
pass grants caps in declaration order, records declared exports, keeps owned
parent client facets for exported child endpoints, and attenuates endpoint
exports to client-only facets for importers. After every child is spawned, init
drops and flushes those parent facets before waiting on children; a dropped init
facet therefore cannot owner-cancel queued, pending, or in-flight child endpoint
state.

## Invariants

- The manifest is schema data plus an init config tree, not shell script or
  ambient namespace.
- Omitted cap sources fail closed.
- Cap names within one service are unique and are the names userspace sees in
  CapSet.
- Service exports must name caps declared by the same service.
- Service-sourced imports must reference a declared service export.
- Endpoint exports to importers must be attenuated to client-only facets.
- Init must not hold endpoint owner caps for child-local manifest endpoints.
- `expectedInterfaceId` checks compatibility; it is not the authority selector.
- Legacy receiver metadata travels with cap-table hold edges and endpoint
  invocation metadata. Spawn-time client endpoint minting may carry the
  requested child selector only from owner or trusted parent endpoint result
  sources instead of copying the parent's hold selector. Client facets received
  through ordinary spawn grants are not selector-minting authority for later
  spawns. Caller-selected endpoint badges are transitional compatibility state;
  session-bound invocation context plus broker-granted service roots/facets is
  the target shared-service authority model.

## Code Map

- `schema/capos.capnp` - `SystemManifest`, `NamedBlob`, `SystemConfig`,
  `KernelCapSource`, and generic `CueValue` storage for `initConfig`.
- `capos-config/src/manifest.rs` - manifest structs, `initConfig` CUE parsing,
  capnp encode/decode, metadata-only `ManifestBootstrapPlan`, and schema-version
  storage.
- `capos-config/src/validation.rs` - kernel bootstrap, init-owned graph,
  binary-reference, and capability-source validation policy.
- `tools/mkmanifest/src/lib.rs` and `tools/mkmanifest/src/main.rs` - host-side
  manifest build pipeline, binary embedding, and general CUE-to-Cap'n Proto
  data-message conversion.
- `kernel/src/main.rs` - kernel manifest module parse and validation.
- `kernel/src/cap/mod.rs` - bootstrap cap creation and CapSet entry
  construction for init.
- `kernel/src/cap/boot_package.rs` - read-only manifest-size and chunked
  manifest-read capability.
- `kernel/src/cap/process_spawner.rs` - init-callable spawn path for packaged
  boot binaries.
- `capos-rt/src/client.rs` - typed BootPackage and ProcessSpawner clients.
- `init/src/main.rs` - BootPackage manifest reader, graph preflight, generic
  spawn loop, hostile spawn checks, and child waits.
- `system.cue` and `system-spawn.cue` - default init-owned login/service graph
  and focused init-owned spawn manifests using `initConfig`.

## Validation

- `cargo test-config` validates manifest decode, CUE conversion, graph checks,
  source checks, and binary reference checks.
- `cargo test-mkmanifest` validates host-side manifest conversion, embedded
  binary handling, pinned CUE path/version checks, pinned Cap'n Proto
  path/version checks, and schema-aware JSON-to-binary conversion through
  `capnp convert` when `CAPOS_CAPNP` is available.
- `make run-smoke` validates the focused shell-led scripted login manifest:
  single `capos-shell` init boot from `system-smoke.cue`, failed-auth
  redaction, successful password auth, broker-issued shell launch, terminal
  isolation, and clean halt.
- `make run` is the operator-facing interactive boot path with the terminal
  UART on stdio and console/debug output logged separately.
- `make run-spawn` validates the narrower `system-spawn.cue` graph: the kernel
  boot-launches only standalone `init`, init validates BootPackage metadata,
  ProcessSpawner launches each focused child service, grants Timer to the
  timer smokes, and init waits for them.
- `make generated-code-check` validates schema-generated Rust stays in sync.

## Open Work

- The run-target/init-policy backlog still needs to migrate remaining focused
  shell-led manifests or preserve them as explicit exceptions, then add a
  manifest-loader or mkmanifest guard against accidental non-`init` default
  boot graphs.
- Service object identity migration still needs to retire caller-selected
  endpoint badge syntax from normal manifest paths. Normal shell paths already
  reject explicit client-grant selector syntax; low-level hostile fixtures and
  manifest-scoped non-identity encodings such as TCP listen ports remain
  separate cases.
