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

# Architecture

> Components, data flow, trust boundaries, and the threat model.

## Components

```mermaid theme={null}
flowchart TB
    Browser[Browser]

    subgraph CP[Control plane]
        App[TanStack Start on Bun]
        Ctrl[Workspace controller]
    end

    DB[(PostgreSQL)]
    Provider[Model provider]

    subgraph WS[Per-user workspace]
        Daemon[r5dchat daemon]
        Home[(Home PVC)]
    end

    Browser -->|session cookie| App
    App --> DB
    App -->|encrypted credentials| Provider
    App -->|bearer token| Daemon
    Ctrl -->|Kubernetes API| WS
    Daemon --> Home
```

The **control plane** is a TanStack Start application on Bun. It owns identity,
encrypted model configuration, durable conversation state, model streaming, and
Kubernetes reconciliation. **PostgreSQL** is authoritative for users, chats,
messages, workspace intent, and audit history.

Each user maps to one deterministic Service, `Recreate` Deployment, identity
Secret, and retained `ReadWriteOnce` PVC. The Deployment scales between zero and
one, and the complete PVC mounts at `/home/r5d` with no `subPath`. Inside the
pod, `r5dchat daemon` exposes a private authenticated HTTP protocol for
filesystem, search, and process operations.

**The browser only ever calls the control plane.**

## The workspace image

A general-purpose Debian environment containing Bun, Node.js and npm, Python
with pip and venv, native build tools, Git and GitHub tooling, common database
clients, and plotting and data libraries. Media tooling includes FFmpeg and
ffprobe, ImageMagick, libvips, ExifTool, image optimizers, Tesseract, and broad
fonts. Document tooling includes LibreOffice headless, Recoll and Xapian,
Pandoc, Poppler, qpdf, Ghostscript, and Python office libraries.

Recoll performs incremental ranked discovery across document contents;
AnyDoc converts a selected Office or PDF document to Markdown on demand.

<Card title="Image contents in detail" icon="docker" href="/install/images">
  The full toolchain and how to build your own variant.
</Card>

## Trust boundaries

* Browser sessions may access only records owned by the authenticated user.
* A per-workspace random bearer identity maps to exactly one user. It is mounted
  from a Secret and never displayed to users or models.
* Tenant containers receive no Kubernetes service-account token, host path,
  runtime socket, or privileged capability.
* UI file APIs are confined to canonical paths below the home directory. Agent
  tools intentionally operate anywhere inside the container.
* Provider and web-research secrets are AES-256-GCM encrypted with the
  installation key and stay in the control plane.
* Public provider URLs reject credential-bearing URLs, unsafe redirects,
  link-local, metadata, and private destinations, and non-HTTPS by default.

<Warning>
  Root in an unprivileged container is not a complete sandbox for hostile code.
  Production operators serving untrusted tenants should add Kata or gVisor, Pod
  Security admission, NetworkPolicy, quotas, isolated node pools, image policy,
  and monitoring.
</Warning>

<Card title="Full security model" icon="shield-halved" href="/operate/security">
  Hardening checklist and multi-tenancy guidance.
</Card>

## Lifecycle

Chat, file, upload, preview, and process activity starts a workspace and updates
its lease and activity record. An idle reconciler scales the Deployment to zero
only after all active leases finish. The Service, Secret, and PVC remain.

Explicit purge is a separate, deliberately audited administrator action, because
PVC deletion is destructive and irreversible.

<Card title="Lifecycle operations" icon="arrows-rotate" href="/operate/workspaces">
  Inspecting, resizing, and removing workspaces.
</Card>

## Conversations and fresh context

A conversation owns one ordered message stream. Starting fresh context appends a
flagged system prompt to that same stream: provider context begins at the latest
flag while the durable transcript remains complete.

The flagged prompt tells the agent to begin with
`r5dchat conversation overview <conversation-id>`, inspect selected details with
`r5dchat conversation turn <conversation-id> <turn-id>`, or fall back to
`r5dchat conversation read <conversation-id>` for the full transcript. The CLI
uses workspace identity, and the server re-checks user ownership before
returning Markdown or JSON.

## Backup and recovery

Back up PostgreSQL and `SETTINGS_ENCRYPTION_KEY` as one recovery unit. Snapshot
user PVCs according to storage-provider policy. Retain `BETTER_AUTH_SECRET` to
preserve active sessions.

Losing the settings key makes encrypted provider and OIDC credentials
unreadable. Replacing it is not a rotation procedure, because existing data is
not re-encrypted.

## Uninstall and upgrade

The bundled database uses a retained StatefulSet PVC. Dynamic user PVCs carry
keep semantics and are not owned by transient Deployments. Back up before
upgrades, run migrations once, and test restore procedures.

Uninstalling compute does not mean deleting tenant data.
