# cellos-core

The typed-authority kernel and CloudEvent vocabulary shared by every CellOS
control-plane crate. No I/O — only data, ports, and pure validators.

## What it is

`cellos-core` owns the *domain language* of CellOS: execution-cell specs,
the four typed-authority variants (Observed / Proven / Imposed / Declared),
the CloudEvent envelopes the rest of the system reads and writes, and the
port traits (`CellBackend`, `EventSink`, `SecretBroker`, `ExportSink`,
`InferenceBroker`) that every host backend, sink, and broker implements.

It sits at L1 of the layer model — beneath the supervisor, the server, the
projector, and the Cortex bridge. Every crate that touches a spec, a
CloudEvent, or an authority claim depends on this crate; nothing in this
crate depends on tokio, axum, hickory, nats, reqwest, or any other I/O
substrate. The lib-level docstring (`src/lib.rs:1`) states the invariant
plainly: "no network, filesystem, or host syscalls here."

What `cellos-core` deliberately does NOT do:

- It does not run cells (that is `cellos-supervisor`).
- It does not serve HTTP or WebSocket (that is `cellos-server`).
- It does not project state from a JetStream stream (that is
  `cellos-projector`).
- It does not bridge to Cortex (that is `cellos-cortex`).
- It does not perform DNS resolution, TLS termination, or any other
  dataplane work — the spec types describe those policies; the supervisor
  enforces them.

The binding doctrine is ADR-0005 (typed authority model), ADR-0006
(in-VM observability and the `DeclaredAuthority` evidence form), ADR-0009
(Cortex doctrine → CellOS authority mapping), ADR-0010 (formation
authority invariant), and ADR-0014 (formation CloudEvent state model).

## Public API surface

The crate re-exports a deliberately wide flat surface from `src/lib.rs`.
Group by purpose:

### Typed authority (ADR-0005, ADR-0006)

- `authority::ObservedAuthority` — host-observed evidence (SNI, Host,
  H2 `:authority`). `src/authority/validator.rs:571`.
- `authority::ProvenAuthority` — cryptographic proof carrier (TLS-CT,
  DNSSEC, signed token). `src/authority/validator.rs:663`.
- `authority::ImposedAuthority` — supervisor-imposed interception (e.g.
  policy-driven SNI rewrite). `src/authority/validator.rs:749`.
- `authority::DeclaredAuthority` — guest-declared evidence from
  `cellos-telemetry` over vsock; tier-1 ceiling. `src/authority/validator.rs:821`.
- `authority::AuthorityDerivation`, `AppliedRule`, `Rule`, `RuleClass`,
  `EpistemicStatus`, `BindingStatus`, `ValidationError` — the Authority
  Derivation Graph (ADG) shape and its validator errors.
- `authority::derivation_result::validate_authority_derivation` /
  `AuthorityValidationResult` — typed validator result for admission-side
  callers. `src/authority/derivation_result.rs:43`.
- `authority::declared::validate_declared_authority_surface` /
  `DeclaredAuthoritySurface` — F2 host-side subset check for in-VM
  declarations.
- `AuthorityDerivationToken` (in `types.rs:1360`) — the wire token an
  ExecutionCell carries to bind its emissions to a derivation.
- `verify_authority_derivation` / `enforce_derivation_scope_policy` —
  the supervisor's admission-side verifiers.

### CloudEvent vocabulary (`src/events.rs`)

- `CloudEventV1` — the v1.0 CloudEvents envelope (`types.rs:1265`).
- One `*_data_v1` builder per event family — e.g.
  `lifecycle_started_data_v1`, `lifecycle_destroyed_data_v1`,
  `identity_materialized_data_v1`, `observability_network_policy_data_v1`,
  `dns_query_data_v1`, `keyset_verified_data_v1`,
  `homeostasis_signal_data_v1`, `compliance_summary_data_v1`,
  `evidence_bundle_emitted_data_v1`.
- One `cloud_event_v1_*` builder per event family — assembles the
  envelope + data into a complete `CloudEventV1`.
- Typed enums for event payloads: `LifecycleTerminalState`,
  `LifecycleReason`, `LifecycleDestroyOutcome`,
  `LifecycleResidueClass`, `IdentityFailureOperation`, `ResidueClass`.
- `Provenance`, `SubjectUrn`, `cell_subject_urn` — the subject-URN
  contract every event carries.
- Trust-plane constants: `TRUST_PLANE_BUILTIN_KEYSET_ID`,
  `TRUST_PLANE_BUILTIN_RESOLVER_KID`, `TRUST_PLANE_BUILTIN_L7_KID`,
  `TRUST_PLANE_AGGREGATE_EGRESS_FQDN`.

### Spec model (`src/types.rs`)

- `ExecutionCellDocument` / `ExecutionCellSpec` — the top-level spec
  shape supervised by `cellos-supervisor`.
- `RunSpec`, `RunLimits`, `RunCpuMax`, `EgressRule`, `Correlation`,
  `Ingress`, `GitIngress`, `OciImageIngress`, `EnvironmentSpec`,
  `PlacementSpec`, `PolicyRef`, `WorkloadIdentity`,
  `WorkloadIdentityKind`, `Lifetime`, `SecretDeliveryMode`.
- DNS / authority types: `AuthorityBundle`, `DnsAuthority`,
  `DnsResolver`, `DnsResolverDnssecPolicy`, `DnsResolverProtocol`,
  `DnsQueryType`, `DnsRefreshPolicy`, `DnsRefreshStrategy`,
  `DnsRebindingPolicy`, `CdnAuthority`, `CdnProvider`.
- Telemetry: `TelemetrySpec`, `TelemetryChannel`.
- Export targets: `ExportTarget`, `S3ExportTarget`, `HttpExportTarget`,
  `ExportChannels`, `ExportReceipt`, `ExportArtifact`,
  `ExportArtifactMetadata`, `ExportReceiptTargetKind`.
- Inference shapes: `InferenceMessage`, `InferenceRequest`,
  `InferenceResponse`, `InferenceRole`.
- Trust keyset: `SignedTrustKeysetEnvelope`, `TrustKeysetSignature`.
- Spec hashing: `canonical_spec_hash`.

### Policy (`src/policy.rs`)

- `PolicyPackDocument`, `PolicyPackSpec`, `PolicyRules`,
  `PolicyViolation` — the spec-admission rules.
- `validate_policy_pack_document`, `validate_spec_against_policy`,
  `check_policy_pack_version_compatibility`,
  `spec_matches_placement_scope`.
- `AuthorizationPolicyDocument`, `AuthorizationPolicy`,
  `validate_authorization_policy` — the RBAC shape (ADR-0007).
- Constants `MIN_SUPPORTED_POLICY_PACK_VERSION`,
  `POLICY_ALLOW_DOWNGRADE_ENV`.

### Ports (`src/ports.rs`) — the L1 traits

- `CellBackend` — what `cellos-host-*` crates implement.
- `EventSink` — what `cellos-sink-*` crates implement.
- `SecretBroker` — what `cellos-broker-*` crates implement.
- `ExportSink` — what `cellos-export-*` crates implement.
- `InferenceBroker` — local LLM brokers (kept out of cellos-lite).
- `NoopEventSink`, `NoopExportSink`, `NoopInferenceBroker`,
  `NoopSecretBroker` — wired defaults for tests and fail-closed
  configurations.
- `CellHandle`, `TeardownReport`, `RuntimeSecretLeaseRequest` — values
  exchanged across the port traits.

### Spec / trust validation (`src/spec_validation.rs`, `src/trust_keys.rs`)

- `validate_execution_cell_document`, `verify_authority_derivation`,
  `verify_signed_trust_keyset_envelope`,
  `verify_signed_trust_keyset_chain`,
  `validate_tenant_id_for_subject_token`,
  `enforce_derivation_scope_policy`.
- `SignedEventEnvelopeV1`, `sign_event_ed25519`,
  `sign_event_hmac_sha256`, `verify_signed_event_envelope`,
  `canonical_event_signing_payload`, `parse_trust_verify_keys`,
  `load_trust_verify_keys_file`.

### State projection (`src/state_projection.rs`)

- `CellStateProjection` — the apply-and-snapshot machine consumed by
  `cellos-projector`.
- `CellStateSnapshot`, `ProjectionCurrentState`,
  `ProjectionLifecycleStage`, `ProjectionIdentityStage`,
  `ProjectionExportStage`, `ExportProjectionRecord`.

### Errors and helpers

- `CellosError` — the crate's `thiserror` error enum (`src/error.rs:5`).
- `sanitize_cgroup_leaf_segment` (`src/cgroup_id.rs`),
  `redact_url_credentials_for_logs`, `redact_url_if_echoed_in_text`
  (`src/redaction.rs`).
- `hostname_allowlist` (module) — host-name policy matching primitives.

## Architecture / how it works

`cellos-core` is organised as a single flat crate that exposes its
modules through a wide re-export surface from `lib.rs`. The shape is
deliberately a *vocabulary*, not a framework: each module is independent
and pure, and the crate has no `#[tokio::main]`, no `async fn`s outside
trait definitions, and no I/O beyond `serde_json` and Ed25519/HMAC
crypto primitives.

```
                   ┌───────────────────────────────┐
                   │            cellos-core         │
                   │       (vocabulary, ports)      │
                   └────────────────┬───────────────┘
                                    │
       ┌──────────────┬─────────────┼─────────────┬──────────────┐
       ▼              ▼             ▼             ▼              ▼
  cellos-server  cellos-       cellos-       cellos-        cellos-host-*
                 supervisor    projector     cortex
                                    │
                                    └─►  CellStateProjection
                                         consumes CloudEventV1
```

The authority module enforces six structural invariants on every typed
authority instance at construction time — see the doc-comment at
`src/authority/mod.rs:60`. The validator is pure: it takes plain values,
returns `Result`. There is no global state, no thread-local config, no
I/O.

The CloudEvent vocabulary in `src/events.rs` is intentionally flat: each
event family has a `*_data_v1` function that builds the typed `data`
payload (returning `Result<Value, serde_json::Error>` where the payload
can fail to serialize), and a `cloud_event_v1_*` function that wraps it
in the envelope with `Provenance`, `SubjectUrn`, and the canonical
`type` string. Producers (supervisor, projector, cortex bridge) call
these directly; the strings are not constructed elsewhere.

## Configuration

`cellos-core` does no I/O of its own, but it defines the env-var contract
that callers honour:

| Env var | Effect |
|---|---|
| `POLICY_ALLOW_DOWNGRADE_ENV` (`CELLOS_POLICY_ALLOW_DOWNGRADE`) | When set truthy, callers of `check_policy_pack_version_compatibility` may downgrade pack version on apply. |

The crate also exposes a `cellos-lite` constraint: it must not pull in
local LLM / on-device inference dependencies (see `deny.toml` and the
top-of-`lib.rs` note).

## Examples

Build the `data` payload for a `cell.lifecycle.v1.started` event from a
typed spec, then wrap it in a `CloudEventV1`:

```rust
use cellos_core::{lifecycle_started_data_v1, CloudEventV1};
use cellos_core::types::ExecutionCellSpec;

# fn demo(spec: &ExecutionCellSpec) -> Result<(), Box<dyn std::error::Error>> {
let data = lifecycle_started_data_v1(
    spec,
    /* cell_id                  = */ "cell-abc123",
    /* run_id                   = */ Some("run-2026-05-16-001"),
    /* derivation_verified      = */ Some(true),
    /* role_root                = */ Some("ops"),
    /* parent_run_id            = */ None,
    /* spec_hash                = */ Some("sha256:..."),
    /* kernel_digest_sha256     = */ None,
    /* rootfs_digest_sha256     = */ None,
    /* firecracker_digest_sha256 = */ None,
)?;

let event = CloudEventV1 {
    specversion:     "1.0".into(),
    id:              uuid::Uuid::new_v4().to_string(),
    source:          "//cellos/supervisor".into(),
    ty:              "dev.cellos.events.cell.lifecycle.v1.started".into(),
    datacontenttype: Some("application/json".into()),
    data:            Some(data),
    time:            Some(chrono::Utc::now().to_rfc3339()),
    traceparent:     None,
};
# Ok(()) }
```

Build a typed `ObservedAuthority` — the constructor runs the validator
and enforces the §14 type-class envelope:

```rust
use cellos_core::authority::{
    AppliedRule, AuthorityDerivation, AuthorityInput, AuthorityInputType,
    AuthorityOutput, BindingStatus, EpistemicStatus, ObservedAuthority,
    Rule, RuleClass,
};

let derivation = AuthorityDerivation {
    inputs: vec![AuthorityInput {
        input_type:      AuthorityInputType::Sni,
        value:           "api.example.com".into(),
        confidence:      0.95,
        source_event_id: None,
    }],
    rules_applied: vec![AppliedRule {
        rule:  Rule::RawSniObserved,
        class: RuleClass::RawObservation,
    }],
    output: AuthorityOutput {
        tier:             2,
        confidence:       0.95,
        epistemic_status: EpistemicStatus::DirectObservation,
        binding_status:   BindingStatus::NotApplicable,
    },
};

let observed = ObservedAuthority::try_new(derivation)?;
println!("tier={} confidence={}", observed.output().tier, observed.output().confidence);
# Ok::<(), cellos_core::authority::ValidationError>(())
```

Verify against `src/authority/validator.rs` for the current field names
before copying.

## Testing

This crate is pure; tests are fast and have no external dependencies.

```bash
cargo test -p cellos-core
```

Property tests for the §9 non-inflation invariants live under
`crates/cellos-core/src/authority/tests.rs` and run as part of the
default `cargo test` invocation. No `#[ignore]` tests, no broker
required.

## Related crates

- [`cellos-supervisor`](../cellos-supervisor/README.md) — consumes
  `ExecutionCellDocument`, emits CloudEvents built here.
- [`cellos-server`](../cellos-server/README.md) — admits formation
  specs, replays `CELLOS_EVENTS` through `CellStateProjection`.
- [`cellos-projector`](../cellos-projector/README.md) — builds
  `CellStateSnapshot`s from a JSONL CloudEvent log.
- [`cellos-cortex`](../cellos-cortex/README.md) — translates Cortex
  ContextPacks into `ExecutionCellDocument`s, emits ledger entries from
  `CloudEventV1`s.
- `cellos-host-*` crates — implement `CellBackend` from `ports.rs`.
- `cellos-sink-*` crates — implement `EventSink` from `ports.rs`.

## ADRs

- [ADR-0005](../../docs/adr/0005-tls-termination-design.md) — typed
  authority model (the four variants and the ADG).
- [ADR-0006](../../docs/adr/0006-in-vm-observability-runner-evidence.md)
  — `DeclaredAuthority`, the guest-side evidence form.
- [ADR-0007](../../docs/adr/0007-rbac-secret-ref-admission.md) —
  authorization policy shape and `validate_authorization_policy`.
- [ADR-0009](../../docs/adr/0009-cortex-doctrine-to-cellos-authority-mapping.md)
  — doctrine → authority mapping; consumed by `cellos-cortex`.
- [ADR-0010](../../docs/adr/0010-formation-authority-invariant.md) —
  formation authority invariant (enforced via spec validators here).
- [ADR-0014](../../docs/adr/0014-formation-cloudevent-state-model.md) —
  formation CloudEvent state model.
