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

# Pod Tools — Terminal, Logs & Files

> Browser-based shell, log streaming, and file transfer into any container — over the same primitives kubectl uses, with no agent in the pod, gated at every layer.

Autopilot's dashboard can open an interactive **terminal**, stream **logs**, and browse or
transfer **files** for any pod — directly in the browser. Each rides the same Kubernetes
primitive the equivalent `kubectl` command uses (`pods/exec`, `pods/log`), driven by the
controller's own ServiceAccount. **There is no SSH, no keys, and no agent in your
containers**; it works identically on GKE and EKS.

These are the most privileged dashboard capabilities — a shell into a customer container is
the sharpest of them — so they are **off by default and gated at every layer**.

<Warning>
  Every pod tool is **double-keyed**: live only when its feature flag is on **and**
  `auth.enabled=true`. The flag alone is inert, so a public-but-unauthenticated dashboard can
  never serve a shell, a log stream, or a file browse.
</Warning>

## The three tools

<CardGroup cols={3}>
  <Card title="Terminal" icon="terminal">
    An xterm.js shell into a container over a WebSocket — the same primitive as `kubectl exec -it`. Read-only (view) mode available.
  </Card>

  <Card title="Logs" icon="scroll-text">
    Live log streaming — single pod or a **merged, color-coded, time-ordered** view across every replica. Includes previous-container (crash) logs and in-container **file** tailing.
  </Card>

  <Card title="Files" icon="folder">
    Browse a container's filesystem, download a file or directory (as a tar), and upload a file into it — the same primitive as `kubectl cp`.
  </Card>
</CardGroup>

They open from one unified **⚙ Tools** menu on the namespace, workload, and pod-detail pages —
scoped to the whole namespace, a workload's replicas, or a single pod.

## Security model

Every tool enforces the same chain, in order, on every request:

1. **Double-key** — the feature flag **and** `auth.enabled`.
2. **Admin only** — a viewer can never open a tool, regardless of method.
3. **Protected namespaces hard-denied** — `kube-system`, `kube-public`, `gmp-system`, and the controller's own namespace are never reachable.
4. **Namespace scope** — a namespace-scoped admin only reaches their granted namespaces.
5. **Same-origin enforced** — the session cookie rides WebSocket connections the browser doesn't same-origin-check, so the server verifies `Origin` itself.
6. **Fully audited** — every open/close/deny writes a typed audit event (surfaced in the [Access Events](/operations/access-control) feed), and a durable record lands in Cloud Logging.
7. **Bounded** — idle and max-duration timeouts, per-user and per-cluster session caps.

**RBAC is conditional.** The `pods/exec` ClusterRole rule is rendered by Helm *only* when the
terminal is enabled — so on a cluster with it off, the capability is absent at the IAM layer,
not merely gated in code.

## Session recording (compliance)

When the terminal is enabled, sessions are recorded to **asciinema (`.cast`)** by default and
played back in the dashboard — the compliance story of no un-recorded admin shells. Recording
is controlled at runtime by `PodResizePolicy.spec.terminalRecording.enabled` (set false to run
un-recorded); the storage PVC and retention are Helm-configured. A namespace-scoped admin only
sees and plays recordings for their granted namespaces.

The **Terminal Recordings** page (in the Operations navigation group) lists every recording
with sortable columns and filters, and plays each back inline.

## File mode for logs

`pods/log` only sees a container's stdout/stderr. Tenant apps often write to files the
Kubernetes logging API can't reach (`/tmp/error.log`, an app log). **File mode** tails those by
exec-ing `tail -F` inside the container and feeding the output through the same viewer — so
follow, search, level-filter, and the merged multi-pod view all work on an in-container file.
A path picker auto-discovers common log locations and lets you browse to any path. Because it
uses `pods/exec`, file mode is gated on the **terminal** double-key, not merely logs.

## Enabling the tools

| Capability              | Helm value                                                    | Default             | RBAC                                  |
| ----------------------- | ------------------------------------------------------------- | ------------------- | ------------------------------------- |
| Terminal (exec)         | `dashboard.terminal.enabled`                                  | off                 | conditional `pods/exec`               |
| Session recording       | `dashboard.terminal.recording.pvc.enabled` (+ runtime toggle) | on when terminal on | —                                     |
| Logs                    | `dashboard.logs.enabled`                                      | off                 | none new (`pods/log` already granted) |
| Files (browse/download) | `dashboard.files.enabled`                                     | off                 | reuses terminal's `pods/exec`         |
| File upload             | `dashboard.files.uploadEnabled`                               | off                 | —                                     |

All require `auth.enabled=true` to actually serve.

<Note>
  A truly shell-less (distroless / no-`tar`/`cat`/`ls`) container can't be browsed or given a
  terminal — the exec surfaces the container's own diagnostic inline rather than hanging.
</Note>
