# Security Architecture

## Status

This document defines the required security baseline and notes implemented subsets. It is not a
production-security attestation; controls remain unverified until linked to code, tests, deployment
evidence, and `PRODUCTION_CHECKLIST.md`.

## Security objectives

- Keep workspace data, credentials, browser sessions, and files isolated.
- Ensure only authenticated and authorized actors can read data or cause actions.
- Prevent an LLM or untrusted content from bypassing deterministic policy checks.
- Make external actions attributable, idempotent, interruptible, and auditable.
- Minimize collected data and make retention, export, and deletion enforceable.
- Recover safely without repeating uncertain real-world side effects.

## Trust boundaries and protected assets

Trust boundaries exist between the public client and gateway, application and
workers, LLM providers, integrations, browser runtime, data stores, and operators.
Web pages, messages, email, attachments, model output, webhook payloads, and tool
results are untrusted input.

Critical assets include password and MFA material, session tokens, OAuth tokens,
API and webhook keys, browser profiles and cookies, message and call content,
files, memories and embeddings, approval records, and audit logs.

## Authentication

- Bootstrap the first owner exactly once, then permanently disable bootstrap.
- Hash passwords with Argon2id using reviewed parameters.
- Use secure, HttpOnly, SameSite cookies, CSRF protection, session rotation, idle
  and absolute expiry, device history, logout-all, and reset token expiry.
- Support TOTP or WebAuthn MFA with protected recovery codes.
- Rate-limit authentication and recovery without enabling account enumeration.
- Hash internal API keys, display them once, and support scopes, expiry, rotation,
  revocation, and last-used records.

Current implemented subset: file-mounted operator bootstrap capability plus a locked one-time
installation state, Argon2 passwords, generic login failure, dummy-hash timing equalization, Redis
source limiting and invalid-account counters that do not block a correct password, hashed
session/CSRF tokens, Secure cookies in production mode, active membership checks, CSRF
logout/logout-all, encrypted RFC 6238 TOTP with replay rejection and one-use recovery codes,
operator-assisted single-use reset, absolute/idle expiry, session rotation/revocation, and append-
only login/audit evidence. The production TLS overlay is defined. Target-host TLS/auth abuse and
recovery drills remain release blockers.

## Authorization and workspace isolation

Authorization is deny-by-default and server-side. Every owned record must carry a
workspace identifier; user ID 1 or implicit global ownership is prohibited.
Permissions must be checked at HTTP, WebSocket, queue, tool, file, integration,
delegation, and browser-control boundaries. Jobs must reauthorize at execution.

Initial roles are Owner, Administrator, Assistant Manager, Human Assistant,
Viewer, and Developer. Roles are collections of granular permissions, not trusted
shortcuts. Tests must cover horizontal and vertical privilege escalation, IDOR,
cross-workspace access, stale permissions, and revoked sessions.

## AI and external-action safety

Model output never invokes integrations directly. The trusted execution path is:

1. Parse into a typed, allowlisted action.
2. Resolve actor, workspace, agent, resource, recipient, and permissions.
3. Apply deterministic policy, autonomy, risk, budget, and contact constraints.
4. Bind any approval to the canonical payload hash, actor, scope, and expiry.
5. Execute with an idempotency key and current-state preconditions.
6. Verify the external result and write an audit event.

High-risk financial, security, destructive, confidential-sharing, and account
actions require explicit approval. “Always allow similar” must produce a narrow,
visible, revocable policy and cannot widen platform safety boundaries. Emergency
stop is enforced before every side effect at the application layer.

Current implemented subset: the isolated AI service accepts only a file-mounted service token,
uses schema-constrained Responses output with provider storage disabled, and exposes two low-risk
Core read tools. Core derives the allowlist from current workspace membership and reauthorizes every
returned step against Core-owned permission/risk/write metadata. Raw workspace/user identifiers are
replaced by a one-way safety identifier in provider input. Missing provider credentials create an
audited, durable `blocked` execution.

The separate computer path exposes a Core-owned registry of DOM-first browser tools. Read actions
may run within effective authority; write actions at the default agent autonomy require approval.
Core validates arguments, intersects actor permissions with current agent permissions/tools, binds
approvals to the canonical raw payload hash, requires idempotency keys, redacts persisted arguments
and results, and records verification/checkpoints/audit evidence. The exact raw approval payload is
retained only in the current browser UI process and must be re-proposed after a reload. This is an
initial browser-control implementation, not a general authorization grant format for every worker.

Runtime agents cannot grant themselves authority. Create/update validates known permissions against
the current human actor, requires every tool's permission, and rejects unknown tools. Planning and
execution both intersect actor permissions with the selected active agent's current permission/tool
grants. Manager/escalation references are workspace scoped and manager cycles are rejected;
delegations are restricted to the actor/source/target intersection and are audit logged.
Model-profile administration is workspace scoped, permission checked, CSRF protected, and audited.
Profiles store routing metadata only; provider credentials remain file-mounted deployment secrets.
Agents cannot reference missing, disabled, or cross-workspace model profiles.

## Prompt injection and SSRF

Content retrieved from browsers, email, messages, files, webhooks, and tools is
data, never authority. Planner, policy engine, and executor remain separate.

Outbound URL handling must allow only expected protocols, validate parsed hosts
and resolved addresses before connection and after every redirect, and block
loopback, private, link-local, multicast, metadata, Docker, and internal service
addresses. Defend against alternate IP encodings and DNS rebinding. Enforce
response size, timeout, redirect, and egress limits. Browser research must retain
source provenance and must not execute instructions found in source content.

The current Computer Agent allows HTTP/S navigation only, rejects credentials in URLs, checks DNS
answers and redirects against loopback/private/link-local/multicast/reserved/metadata ranges, and
blocks service workers, WebSockets, and downloads. This application guard reduces SSRF exposure but
cannot eliminate DNS time-of-check/time-of-use races by itself. Production still requires enforced
host/network egress policy and adversarial rebinding validation.

## Secrets and encryption

- Never commit secrets or place them in source, images, prompts, logs, or test data.
- Prefer a managed secret store. If credentials are stored in the database, use
  envelope encryption with per-workspace data keys and a key-encryption key kept
  outside the database.
- Version and rotate keys; audit secret reads and writes; redact secrets after save.
- Store OAuth tokens with minimum scopes and support disconnect and revocation.
- Encrypt backups with separately controlled keys and test restoration.

## Virtual-computer and browser isolation

Every active runtime agent owns one dedicated full guest OS. Containers and Chromium profiles are
not accepted as the sole isolation boundary for an agent that can receive root/Administrator
privilege. Production agent computers must be separate KVM/libvirt, Proxmox, or cloud VMs with
independent persistent disks, network policy, browser state, files, applications, and snapshots.

Only Core may call the configured hypervisor provisioning gateway, through typed, authenticated,
idempotent operations. LLMs and guests never receive hypervisor credentials, `/var/run/docker.sock`,
the libvirt socket, host SSH/root credentials, platform database/Redis credentials, infrastructure
secrets, backup access, or another computer's control endpoint. The default network policy allows
controlled internet and the narrow platform API path while blocking LAN, host-management, and
other-agent networks. A database constraint prevents enabling host-management access through the
product policy record.

VM lifecycle operations are stored before dispatch and verified with a provider status read.
Unconfigured providers/templates remain `blocked`; ambiguous provider failures remain `unknown`
with the computer in `recovering`. Destruction and snapshot restoration require an authorized human's
explicit confirmation in addition to `computer.control`/approval authority. Workspace quotas bound
computer count, concurrently active machines, per-VM CPU, RAM, and disk.

Each persisted computer profile is workspace-owned and maps to a randomized storage key. Computer
profiles are one-to-one with the agent and its VM; a runtime session rejects any profile/agent/VM
mismatch and requires the VM to be running. Computer Agent runs non-root, has no database
network/credential, uses one active persistent Chromium context per profile, and exposes no public
CDP/VNC/noVNC/Docker endpoint. Core stores exclusive controller
leases with expiry and monotonically increasing fencing tokens. Human takeover invalidates the AI
fence; only the active human actor can send input or pause; return-to-AI requires a snapshot,
re-observation, and fresh fence. Workspace emergency stop is durable in Core, fences active
controllers, attempts worker stop, and reports verified versus unverified outcomes. Resume never
automatically restarts sessions.

Internal service authentication and fencing are implemented. Every Computer worker operation uses
an Ed25519-signed, audience/key/scope/request-bound capability lasting no more than 45 seconds, with
workspace/session/fence claims where applicable. Browser profile volumes are isolated but not
encrypted. Live view currently polls
JPEG frames through Core rather than using a revocation-aware WebSocket/WebRTC channel. Downloads,
uploads, clipboard integration, service workers, and WebSockets are disabled rather than safely
implemented. Screenshot artifacts use workspace/session path containment, SHA-256 and size
verification, short retention metadata, and restrictive response headers.

## Containers and networking

Only the gateway publishes HTTP/HTTPS. Services run as non-root with read-only
root filesystems where possible, dropped capabilities, `no-new-privileges`,
resource limits, health checks, and pinned images. Never mount the Docker socket.
Use separated edge, application, data, and browser networks with least-privilege
database roles and controlled browser egress.

The current AI container runs non-root with a read-only root filesystem, dropped capabilities, no
host port, and no data-network/database access. It is attached to the app network for authenticated
Core calls and to an egress network for provider access. Provider-level egress restriction,
service-token rotation/revocation records, and workload identity remain production work.

The current Computer Agent container remains a browser-runtime implementation and is not claimed as
a full virtual computer. It is non-root, read-only, capability-dropped, resource-limited,
not host-published, and configured with `no-new-privileges` plus the Playwright project seccomp
profile. Browser profiles and artifacts use dedicated volumes. Compose hardening has only been
statically tested locally; Docker runtime and host egress enforcement remain unverified.
The real VM provider gateway, guest control daemon, encrypted per-VM storage, and host/guest escape
campaign remain production blockers.

## Webhooks, APIs, and realtime

Verify webhook signatures over raw request bytes using constant-time comparison,
provider-specific secrets, timestamp tolerance, and replay storage. Validate
schemas and enforce size and rate limits. Authenticate WebSocket handshakes,
authorize every subscription and control message, validate origins, limit message
size/rate, and ensure revocation terminates existing capabilities.

## Audit and logging

Audit events are append-only and tamper-evident, with separate write/read/delete
privileges. Record request, execution, and action IDs; time; workspace; human,
agent, and service actor; policy and approval decision; canonical payload hash;
result; verification state; and safe before/after metadata. Agents cannot edit or
delete audit records.

Application logs are structured and redacted. Do not log cookies, authorization
headers, credentials, full webhook bodies, browser profiles, or sensitive message
and screenshot content by default. Public health endpoints reveal minimal detail.

The foundation migration adds database triggers that reject audit/login updates and deletes, and
audit entries form a per-workspace hash chain. Compose now separates the migration and runtime
PostgreSQL identities and applies post-migration grants that revoke runtime DDL and security-evidence
mutation. Those grants remain unverified until exercised against a live production-like PostgreSQL.

## Privacy and retention

Define conservative defaults for messages, screenshots, files, recordings,
transcripts, execution traces, and memories. Recording requires applicable consent.
Deletion and export must cover derived data and embeddings. Sensitive credentials
must not enter embeddings. Cleanup jobs are audited and respect backup retention.

## Required verification

Security work is incomplete without automated negative authorization tests, SSRF
tests, adversarial prompt/tool tests, approval tamper and replay tests, webhook
signature/replay tests, duplicate-action crash recovery, takeover race tests,
secret scanning, dependency/container/IaC scanning, exposed-port inspection, and a
documented backup restoration exercise.
