> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Session contracts

> Canonical session, runtime, keep-alive, and commit-boundary contracts.

This page is the canonical settled-state contract for session and runtime behavior.

## Ownership model

Meerkat has one canonical semantic path:

* **the runtime control plane** (`MeerkatMachine` in `meerkat-runtime`) owns `keep_alive`, Queue/Steer routing, comms drain lifecycle, external-event admission, and request/turn commit semantics; runtime-backed surfaces reach those semantics only by lowering into it
* **`SessionService`** is the substrate lifecycle seam used by those surfaces
* **`EphemeralSessionService` / `build_ephemeral_service`** remain valid for testing, embedded use, and WASM internals, but they are not the primary product path and do not own runtime semantics

The runtime-backed path is:

```text theme={null}
Surface -> MeerkatMachine -> SessionService -> AgentFactory::build_agent()
```

The runtime-backed build contract has an explicit binding seam:

* runtime-backed surfaces should call `MeerkatMachine::prepare_bindings(session_id)`
* those bindings flow into `SessionBuildOptions.runtime_build_mode = RuntimeBuildMode::SessionOwned(bindings)`
* standalone / embedded / test-only builds should opt into `RuntimeBuildMode::StandaloneEphemeral` explicitly instead of relying on silent fallback

`SessionRuntimeBindings` is the epoch-local runtime handle for a session. It carries:

* `session_id`
* `epoch_id`
* the canonical `OpsLifecycleRegistry`
* shared consumer cursor state used for recovery-safe completion visibility

This keeps one owner for runtime semantics:

* `PersistentRuntimeDriver::recover()` owns input/runtime/control recovery
* `MeerkatMachine` owns session entry recovery (`ops_lifecycle`, `epoch_id`, cursor state)

Direct substrate usage is intentionally narrower:

* Queue-only turns
* no runtime-owned `keep_alive`
* no Steer/render-metadata semantics
* no runtime ingress/admission ownership

## Agent construction contract

Agent construction is centralized in `AgentFactory::build_agent()`.

* Surfaces pass per-request build data in-band via `CreateSessionRequest.build` (`SessionBuildOptions`).
* No out-of-band staging lock is used.
* `FactoryAgentBuilder` maps `SessionBuildOptions` to `AgentBuildConfig`.
* For runtime-backed builds, `SessionBuildOptions.runtime_build_mode` should carry `RuntimeBuildMode::SessionOwned(bindings)` from `prepare_bindings()`.
* For standalone/testing/embedded builds, prefer `RuntimeBuildMode::StandaloneEphemeral` explicitly.
* Session metadata persists realm context and durable session identity:
  * `realm_id`
  * `instance_id`
  * `backend`
  * `config_generation`
  * durable LLM identity
  * `keep_alive`
  * visible comms identity metadata such as `comms_name` and `peer_meta`

## Session lifecycle and turn semantics

### create\_session

`create_session(req)` builds the agent and optionally runs the first turn.

* Returns `RunResult` with `session_id`.
* `InitialTurnPolicy::RunImmediately` executes the first turn inline (default).
* `InitialTurnPolicy::Defer` registers the session without running a turn.

Create has a commit boundary:

* **pre-commit failure**: side-effect free; no committed session identity
* **post-commit first-turn failure**: return session identity and keep the session resumable

Committed create failure must not be silently rewritten to “cancelled” or cleaned up as unpublished work.

### start\_turn

`start_turn(id, req)` executes a new turn on an existing session.

* At most one in-flight turn per session.
* Concurrent attempts return `SESSION_BUSY`.
* Committed success must not be rewritten to cancellation.
* Runtime-backed surfaces may hot-swap supported live settings on an existing session where the surface contract says that is allowed.

<Warning>
  The runtime may coalesce multiple queued `Steer` inputs into one agent turn.
  Admission remains durable per input, but there is no promise of one model call
  per input. Applications that require one side effect per admitted input must
  iterate the durable input records deterministically in a tool or host-owned
  worker. Do not rely on the model to notice and act once for every item in a
  batched prompt.
</Warning>

### Ordered System messages

`system_prompt` on `StartTurnRequest` appends one ordinary `System` message at
that turn boundary. System messages are repeatable and may appear anywhere in
the transcript; an update never replaces row zero or rewrites an earlier
message.

There is no separate prompt identity or host-injection ledger. Materialization
and resume preserve the transcript byte-for-byte and never infer a System
message from current host configuration. A host that wants to add an
instruction supplies it on the admitted turn, where it becomes one new ordered
System event.

Compaction retains every System message in relative order. Provider adapters
preserve each System at its exact position where the wire accepts ordinary
`role=system` messages. A provider with only a top-level instruction field
cannot silently hoist or merge later System rows: its request projection
returns a typed error while the ordered row remains valid durable history.
Provider capability never changes, rejects, or rewrites the durable Session
itself.

### interrupt

`interrupt(id)` cancels an in-flight turn.

* If no turn is running: `SESSION_NOT_RUNNING`.

### read and list

* `read(id)` and `list(query)` are non-blocking with respect to in-flight turns.
* Persistent services can include durable sessions from the realm backend.
* Presence in `list()` is not the same as “live session exists”; runtime-owned seams must answer liveness.

### read\_history

`read_history(id, query)` returns the last committed transcript snapshot for a session.

* Messages are returned oldest-to-newest.
* `offset` and `limit` apply from the start of the full transcript.
* Active sessions do not expose in-flight partial output through history reads.
* Archived sessions remain readable on persistent backends; the ephemeral service rejects archived history reads with `SESSION_PERSISTENCE_DISABLED`.

### archive

* The canonical `SessionDocumentMachine` owns the `session_lifecycle_terminal` fact for ALL profiles; shells realize its verdict, they never decide it.
* Realization order is fail-closed: durable document commit first, runtime retire second. `RuntimeState::Retired` is the runtime realization of the same verdict, so the resurrection window is unrepresentable.
* If runtime retirement fails after the document commits `Archived`, the durable terminal remains authoritative: reads, resumes, and turns stay rejected while a repeated archive command follows the generated convergence transition and retires the residual runtime.
* Archived sessions are excluded from `list()` and rejected for further reads/turns (`SESSION_NOT_FOUND` on persistent services; the ephemeral service serves a final in-memory view).
* Committed transcript history remains readable via `read_history` on persistent backends.

## Keep-alive contract

`keep_alive` is a runtime/session concept, not an old “host mode” execution path.

Rules:

* **create / run** omitted => default `false`
* **continue / resume** omitted => inherit persisted session intent
* explicit `keep_alive` override is a session/runtime mutation once validated
* invalid `keep_alive` + comms configuration is rejected before any stateful work
* once validated, an explicit `keep_alive` mutation may commit independently of turn success

`keep_alive=true` requires usable comms identity/config on the surfaces that expose it.

## External events

External events are queue-only runtime-backed inputs.

* they are admitted into runtime ingress
* they do not invent a second direct execution path
* “turn-boundary inbox draining” is not the primary mental model for the current runtime-backed design

## Event delivery and durable projection

Live delivery and durable evidence use separate lanes:

* Ordinary session subscribers read a 256-entry broadcast. If a subscriber
  falls behind, it receives a synthetic `StreamTruncated` event with
  `reason.kind = "stream_lagged"` and the exact `reason.dropped` count, then
  continues with retained events. The marker reports a gap in that subscriber's
  live view; it is not a canonical durable-log event.
* A persistent session whose host installs event projection has one internal
  dedicated projector stream backed by an unbounded MPSC queue. Built-in
  realm-backed persistence installs it; custom hosts must call the projection
  composition seam explicitly. Event publication shares the same envelope with
  the live lane, but projector latency does not block live subscribers or
  depend on broadcast retention. The runtime emits a rate-limited degraded
  warning when the queue reaches 1,024 entries and records its high-water mark.
* The projector asynchronously appends each envelope to the durable event audit
  log before updating derived `.rkat/` materialized files. UI-ring lag does not
  drop projector input, but EventStore projection is still best-effort derived
  state. The `RuntimeStore`/backend carrier remains session authority;
  `SessionStore` rows and EventStore are component/content and projection seams.

A durable audit-log append failure latches an
`EventProjectionHalted` fault, records a durable projection-halt marker when
possible, stops before appending later events across the sequence hole, and
makes replay and later resume fail closed. It does not roll back or fail the
already-committed turn. Clients that see live
`stream_truncated` reconcile from `events/list_since`, a current snapshot, or
ATIF export.

## Explicit override semantics

Where the surface supports omission vs explicit override, these are distinct facts:

* omit / inherit
* disable / false
* set / concrete value

When all three meanings matter, the wire/API must preserve that distinction. Typed optional fields and override masks are preferred over default-value folklore. Concretely: `SystemPromptOverride` (`Inherit` / `Set` / `Disable`) is the canonical wire+persisted carrier for the per-request system-prompt fact, and per-turn provider parameters travel as the typed `ProviderParamsOverride`, not a raw JSON bag.

## Realm contract

Sessions are realm-scoped.

* Same `realm_id` plus the same physical provider/root: shared visibility and
  config context.
* Different `realm_id`: strict isolation.
* Backend is pinned per realm via `realm_manifest.json` (manifest format 2
  adds `provider` and `ephemeral_domains`; readers refuse formats newer than
  they support instead of silently ignoring fields, and realms pinned to an
  external storage provider refuse built-in disk opens typed).
* State roots resolve realm-id-first across the project-local and
  user-global candidates; a realm materialized under both is a typed
  split-brain refusal (see `rkat storage doctor`).
* First materialization of a fresh realm reserves across the candidate set
  resolved by that invocation before writing the manifest. Processes using
  the same multi-root set converge; surfaces probing different sets do not.
  Use one explicit root or matching server context for cross-surface starts.
* A fresh prompt-first CLI run or `rkat help` whose workspace-derived realm
  cannot open may isolate storage into a newly generated durable SQLite realm
  under the same resolved state root. No historical session from the failed
  realm is loaded into the fresh run, and the compatibility bridge is never
  invoked automatically. An ordinary supported initialization or migration
  may have completed before a later store refused. The original workspace
  config and auth/tool policy still govern the run. Explicit realms, isolated
  runs, resumes, and session commands never take this fallback. Historical
  session access requires the explicit fenced pre-0.8.10 bridge; there is no
  in-memory compatibility fallback.

## Mob-member role continuity

A durable mob member normally resumes only when its stored and requested role
match. Mob ID, member `AgentIdentity`, bridge `session_id`, and transcript are
fixed identity facts; a profile edit alone cannot reinterpret the stored
member as a different role.

Trusted in-process hosts have one explicit migration seam. An exact
`MemberLaunchMode::Resume` may carry `resume_from_role` naming the stored
predecessor role for that request. Admission proves that the stored and current
`comms_name` and `MobMemberBinding` refer to the same mob and member. An absent
declaration returns `MemberRoleMigrationRequired`; the wrong predecessor or a
contradictory identity returns `MemberRoleMigrationRejected`.

Role migration is cold and one-shot. The exact session must have no live actor,
the declaration is consumed rather than persisted as standing permission, and
successful materialization restamps the current role into durable comms
metadata while preserving the same session and transcript. There is no
implicit rollback; a later role change requires a new exact cold migration.

This seam is deliberately private. Public CLI, REST, JSON-RPC, MCP, generated
SDK spawn requests, helpers, and standing profiles cannot set
`resume_from_role`. The private member-host materialization protocol carries it
only as part of the trusted remote-host resume path.

## Compaction contract

Compaction is optional and non-fatal.

* Triggered by token thresholds and turn guards.
* On failure, emits `CompactionFailed` and continues with uncompacted history.
* Compaction usage counts toward run budgets.

## Durability

### Ephemeral mode

No durability across process restart.

### Persistent mode

Durability follows the selected realm storage provider and its declarations
for the seven owned domains. The built-in persistent realm backends are
`sqlite` and `jsonl`; an external `RealmStorageProvider` may supply other
persistent stores, but it must declare every domain and may not silently
substitute memory for one declared durable. Both built-in persistent backends
mount a SQLite runtime companion for runtime authority:
`sqlite` realms keep the `runtime_*` tables inside `sessions.sqlite3`, and
`jsonl` realms carry a dedicated `runtime.sqlite3` alongside the JSONL session
documents. Queued inputs, run-boundary receipts, ops snapshots, and
auth-lease/OAuth-flow authority are durable under both backends.
The `memory` backend is explicit ephemeral storage and does not survive process
restart.

* Completed turns are persisted.
* Crash during an in-flight turn loses at most the work the intra-turn
  persistence hook had not yet written; any durable tail it did write is
  preserved and recovered (see below), never discarded.
* SQLite-backed realms are the default persistent mode and support normal same-realm multi-process workflows.

Persistent session metadata is the source of truth for resumed durable session behavior unless an interactive surface supplies an explicit typed override.

### Domain document and store authority

The current Session envelope is version 3 and contains domain state only. It
does not authenticate itself and does not carry a persistence token. A
deserialized `Session` cannot authorize a write, migration, or recovery
operation.

The selected store profile issues the physical authority:

* **WholeBlob** — `session_id`, monotonic store revision, and SHA-256 of the
  exact serialized row.
* **HeadCanonical** — `session_id`, monotonic store revision, the committed
  boundary head, and its exact head token. The boundary head binds the
  message-row, rewrite, graph, component, and metadata prefixes.

RuntimeStore also maintains a small catalog entry in the same atomic boundary
as physical authority. The catalog can answer listing and lifecycle discovery,
but cannot carry a transcript, graph, component body, or serialized Session.
It is not a second session document.

Meerkat 0.8.11 accepts durable state from 0.8.10 only through the one-time
released-state importer. An exact released v2 document with the historical
embedded proof is checked once by the frozen 0.8.10 verifier. An unstamped
released document is accepted only when the same store transaction proves the
released physical schema and exact source row or blob identity. Either path
strips the historical proof fields and installs current store-issued authority;
ordinary v3 reads never enter the importer, and no current write emits the old
fields.

State older than 0.8.10 in a SQLite realm is admitted only through the explicit
offline command `rkat ... storage migrate --apply --bridge-pre-0-8-10`.
JSONL and memory realms are rejected before any database is mutated. This is a
frozen, fail-closed pre-floor importer: under the realm maintenance fence it
authenticates supported historical schema before installing current
representation and authority. Ordinary store opens and v3 reads remain strict
and never enter the bridge. Catalog authentication is per domain and row
admission is per record: a row the current typed contract cannot represent
without loss is left byte-identical on disk and reported, rather than costing
the realm every other row. The maintenance transaction preserves input rows -
including their ingress payloads, whatever lifecycle state they reached -
without scheduling or replaying them. A later session activation follows normal
recovery, which applies this binary's ordinary terminal-payload retirement to
rows it writes itself.

### Durable-tail recovery

The intra-turn persistence hook writes a provisional physical successor
outside the runtime boundary transaction. Every successful write returns an
explicit `RunCheckpointReceipt`. Receipts are scoped to one session, committed
base, and run; `candidate_sequence` starts at one and advances contiguously.
An exact retry may return the same receipt, while the next candidate must
present and succeed the preceding receipt. A stale, divergent, or
out-of-sequence candidate fails closed.

WholeBlob encodes, hashes, and writes each candidate once. HeadCanonical
applies one sealed prepared delta and returns the exact resulting physical
revision and head token. The actor retains only the latest successful receipt;
an uncertain outcome or failed acknowledgement terminates the actor and
requires durable reload. At the final boundary the store promotes that exact
candidate. It does not construct a second document or replay the delta.

A crash or shutdown race can still leave a durable transcript tail — up to and
including a fully completed turn — whose runtime boundary commit never landed.
Durable is not the same as runtime-committed, and neither view is silently
preferred: a cold read drives a typed, machine-owned read-source decision
(serve the committed runtime snapshot, serve the committed store head,
recovery required, or quarantine) instead of a shell comparison.

The recovery rule is never-discard: every store-proven durable descendant of
the committed authority is preserved.

* A completed tail (single run, `EndTurn` terminal, structurally coherent) is
  committed as a recovered run boundary in one atomic store transaction:
  recovered snapshot, boundary receipt, and input terminalization land
  together, so exactly-once holds and the delivery layer never re-runs a
  recovered turn.
* An interrupted tail is closed as interrupted: content preserved, a typed
  recovery notice appended, the original run terminalized — never requeued.
* Anything else — including any tail carrying a dangling `tool_use` — is held
  intact for reconciliation. A dangling call proves intent, not execution;
  its external side effect may already have fired, so recovery never closes
  it with synthetic results.

A committed strict descendant wins over a stale live runtime snapshot
regardless of local actor liveness, and projection convergence requires
intra-turn row provenance, so two committed sibling documents can never
overwrite each other. Read-triggered recovery runs under an exclusive
per-session fence, re-observes the head under it, and converges idempotently
when a competing process wins the commit; a recovery that already landed is
refused rather than committed twice.

While a session is held or quarantined, its content is retained intact and
resume fails typed rather than with internal-error prose:

* `SESSION_DURABLE_TAIL_HELD_FOR_RECOVERY` — the durable tail exists but
  machine-authorized recovery has not promoted it yet; it awaits
  reconciliation.
* `SESSION_DURABLE_TAIL_RECOVERY_REFUSED` — machine-authorized recovery was
  refused by conflicting persisted runtime facts (another live runtime, or
  boundary receipts that already cover or contradict the tail); retry after
  the conflicting runtime quiesces.
* `SESSION_DURABLE_EVIDENCE_QUARANTINED` — the durable evidence is forked or
  unverifiable; the session is quarantined from resume.

All three carry the typed `durable_resume_hold` structured payload so callers
can distinguish the hold class without parsing messages. Ownership of the
pipeline (SessionDocumentMachine classifies, MeerkatMachine authorizes,
RuntimeStore realizes) is documented in
[Machine Authority](/reference/machine-authority#durable-tail-recovery-ownership).

### Storage mechanics (schema ledger, fence, durability classes)

Every SQLite file in a realm carries a `meerkat_schema(domain, version)`
migration ledger; stores bring their domain up to date at open under a
pinned concurrent-open protocol, and a file whose ledger is ahead of the
binary refuses typed (`SchemaFromTheFuture`) — a rollback candidate fails
certification cleanly instead of crash-looping. Each database also has a
sibling `<file>.mfence` lock file: store operations hold a shared
per-operation guard, and offline maintenance (`rkat storage migrate`) takes
the exclusive side after in-flight operations drain. Backup artifacts
written by maintenance use the registered `*.pre-<version>-<timestamp>`
naming that `rkat storage doctor` inventories and `rkat storage prune`
owns.

<Warning>
  Recent session-envelope upgrades are one-way once a newer binary writes the
  session. Before upgrading a durable realm, snapshot every durable store and
  keep that snapshot with the prior binary. Rolling the binary back after new
  writes can leave those sessions unreadable to the older release; a code-only
  rollback is not a supported recovery plan.
</Warning>

Every store slot a realm composes carries a machine-readable durability
class (`durable` / `rebuildable_cache` / `scratch`) and its resolution.
Declarations are complete by construction: a storage provider must declare
exactly one class for each of the seven domains (`sessions`, `runtime`,
`schedule`, `workgraph`, `jobs`, `blobs`, `artifacts`), so no slot dodges the rule
by omission. A durable slot resolving to a non-persistent store without the
realm manifest declaring that domain ephemeral is a startup error. A provider's
typed `DeclaredEphemeral` resolution is already an explicit declaration and
does not need a duplicate manifest entry. Neither path permits a silent
in-memory fallback. Deployment tooling can rely on the classes (for
example, cloning only durable domains between state generations).

### Session storage layout (0.7.25+): head-canonical strands

Since 0.7.25 the SQLite session store persists sessions incrementally: the
transcript lives in append-only `session_strand_messages` rows, rewrite
history in `session_rewrites`, and a single `session_heads` row per session
carries the canonical metadata, message count, and CAS token. Saving a long
session appends O(delta) rows instead of rewriting a monolithic document.

The canonical-representation rule, per session: **if a `session_heads` row
exists, the head representation is canonical**. A released 0.8.10 blob, if
present, is consumed only by the one-time activation importer and is never a
fallback authority for a current head. Sessions created in HeadCanonical mode
may have no meaningful `sessions` blob row at all.

<Warning>
  Downstream tooling that reads `sessions.session_json` via direct SQL sees
  empty or stale content for sessions written by 0.7.25+ binaries — silently,
  because the column still exists. Raw table reads were never a supported
  surface; use one of the typed read paths instead:

  * `SessionStore::load` — full canonical session document.
  * `SessionStore::load_meta` — metadata-only projection (no transcript
    deserialization); `list` for filtered metadata.
  * The wire surfaces (`session/read`, `session/list`, REST equivalents).

  For forensic tooling that must read the raw database, the canonical shape is:
  resolve the `session_heads` row for the session, then read
  `session_strand_messages` rows for `(session_id, head.strand)` ordered by
  `seq` over `0..head.message_count`. Anything else is internal representation
  and may change without notice.
</Warning>

### Range-read capability probes (`load_canonical_head` / `load_rewrite_commits`)

`IncrementalSessionStore` carries two additive read verbs that expose the
head-canonical representation to future O(page) history reads:

* **`load_canonical_head`** returns the persisted head row ONLY when
  head+rows are the session's canonical durable representation. Unlike
  a full materializing load, it answers `None` for absent and non-canonical
  rows and never reads a WholeBlob body. `Some` promises the row is the
  persisted head itself and that `load_messages` over `head.strand`
  page-serves exactly the rows the head covers.
* **`load_rewrite_commits`** returns the ADOPTED rewrite commits
  (`idx < head.rewrite_count`), oldest first, without materializing retained
  revision bodies. It must always equal `load_rewrites`' commits, in order —
  including the empty set while a recorded rewrite is not yet adopted.

Both verbs have conservative defaults (`None`; derive from `load_rewrites`),
so every existing store — including delegating wrappers that do not forward
them — degrades to the whole-load path, never to a refusal. The conformance
suite pins the contract conditionally: a store answering `None` for every
canonical-head probe is fully conformant; a store answering `Some` must serve
the persisted row and page-exact strand reads, and delegating wrappers must
forward both verbs (`capability_discovery` chapter).

Service reads trust only the store-selected profile and its issued authority.
`read_history`, `read_transcript_revision`, and
`list_transcript_revisions` may materialize the required domain view from the
canonical rows, but a materialized `Session` never becomes write authority.

### Durable runtime lifecycle vocabulary (`runtime_states`)

The runtime companion persists one lifecycle row per runtime. The full
`runtime_state` vocabulary, with polling guidance:

| State          | Meaning                                                                                                                                             | Busy?       |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `initializing` | First state after creation.                                                                                                                         | No          |
| `idle`         | No executor attached, ready to accept input.                                                                                                        | No          |
| `attached`     | Executor attached, runtime loop alive, waiting for input.                                                                                           | No          |
| `running`      | A run is in progress.                                                                                                                               | **Yes**     |
| `retired`      | Draining: no new input accepted, existing work finishes.                                                                                            | Transiently |
| `stopped`      | Stopped by runtime control. Non-terminal but quiescent: no work executes until the machine-owned revival re-admits the session on resume (0.7.24+). | **No**      |
| `destroyed`    | Terminal.                                                                                                                                           | No          |

Busy-detection loops must treat `stopped` and `destroyed` as not-busy:
`stopped` means nothing is executing and nothing will execute without an
explicit resume, so polling it as "busy" hangs until an external timeout.

Prefer the typed status surfaces over raw row reads: since 0.7.25,
`session/input_status` answers from durable state
without requiring a live runtime registration, so a fresh host process
reports truthful terminal outcomes (`Ok`/`NotFound`) for work finished
before a restart.

## Config concurrency contract

Config runtime uses generation CAS.

* `config/get` returns current `generation`.
* `config/set` and `config/patch` can specify `expected_generation`.
* Mismatches fail deterministically with generation conflict.

## Data governance

<Warning>
  No automatic sensitive-data redaction is applied to session content or tool payloads.
  Encrypt storage at rest externally if required by your environment.
</Warning>

## Request-only turn context

`transient_turn_context` is non-empty runtime-input text, not Session state.
Whitespace is significant and its exact text bytes remain on a pending input
so cold recovery can retry the same turn, then retire with that terminal input
payload. During the active logical turn, Meerkat projects the caller context
first and any runtime-admitted steers after it, each as a distinct temporary
user-channel injected-context message immediately before the exact admitted
conversational user message in each foreground provider request. They are never
System messages, transcript appends, rewrite records, compaction input, or
extraction input.

Deferred creation cannot carry this context because no runtime input exists
yet; attach it to the eventual turn instead. The browser/WASM standalone live
surface does not expose this durable runtime-input feature.

## See also

* [Architecture](/reference/architecture)
* [Design philosophy](/reference/design-philosophy)
* [Realms](/concepts/realms)
* [Sessions](/concepts/sessions)
* [Capability matrix](/reference/capability-matrix)
