# Architecture

## Status

Hayva is an early orchestration platform with three runnable FastAPI services (`core-api`,
`ai-agent`, and `computer-agent`), a React/TypeScript product interface, Nginx, and development
containers for PostgreSQL with pgvector and Redis. Core owns identity, workspace authorization,
policy, approvals, durable execution/computer state, idempotency, and append-only audit evidence.
AI Agent owns typed model planning. The computer control plane now models one dedicated, persistent
virtual computer per runtime agent, while Computer Agent owns browser automation inside that guest.
The Computer control room, browser actions, live JPEG frames, human
takeover, pause/resume/stop, manual recovery, and global emergency stop are implemented initial
product capabilities.

Migrations and browser runtime tests have been exercised locally, including real Chromium. The
authentication lifecycle now includes encrypted TOTP MFA/recovery, reset, password/session rotation,
idle expiry, and device revocation. Core-to-Computer calls carry Ed25519-signed 45-second scoped
capabilities, and a production maintenance loop reconciles expired leases, approvals, artifacts, and
idempotency records. The Compose stack and PostgreSQL-only grants have not been run on this
workstation because Docker is unavailable. A durable job queue, browser-profile encryption,
controlled host egress, production observability, integrations, and target-host release evidence
remain. The VM provider gateway and built-in OS templates are deliberately `unconfigured` until an
operator supplies a real KVM/libvirt, Proxmox, or cloud-backed provisioner and verified template
references. Browser containers are not represented as virtual computers. Production release is blocked.

## Architectural decision: one private virtual computer per runtime agent

Every active runtime agent must reference exactly one first-class `Computer`. A computer owns its OS
template, virtual CPU, memory, persistent disk, guest privilege, start policy, network policy,
snapshots, metrics, and its single private browser profile. An agent can be created without a computer
only as a disabled non-runtime record; server-side activation requires a stable, provider-verified
computer resource and rejects missing, transitional, unconfigured, failed, or destroyed computers.

`ComputerProvisioningService` is the only application component that invokes `ComputeProvider`.
Provider calls use durable workspace-scoped operations and idempotency keys, then query provider
state for verification. Missing provider credentials or image references produce `blocked` and
`unconfigured`; ambiguous transport outcomes produce `unknown`/`recovering`. They never produce
simulated success.

The initial provider adapter calls a restricted authenticated provisioning gateway. That gateway,
not an LLM and not a guest, owns access to libvirt/Proxmox/cloud APIs. Guest VMs never receive the
libvirt socket, Docker socket, host credentials, platform database/Redis credentials, backup keys,
or another guest's network or disk. Root/Administrator means root/Administrator inside the guest only.

## Architectural decision: modular monolith first

The initial control plane will be a modular monolith in `core-api`. Identity, workspaces, RBAC,
policy, approvals, agents, executions, integrations, CRM, tasks, scheduling, and audit are logical
modules with explicit interfaces but share one deployment and one PostgreSQL database. This keeps
transactions and operations understandable while the domain is changing.

Only workloads with a real isolation or runtime boundary become separate services:

- `ai-agent`: implemented initial model-provider boundary, typed tool registry, and tool planning;
  later phases add execution orchestration and synthesis.
- `computer-agent`: implemented isolated Playwright/Chromium sessions, persistent profiles,
  DOM-first actions, visual frames, fencing, and explicit recovery.
- `voice-worker`: realtime telephony work when voice is implemented.
- `web`: the implemented setup/login/dashboard, Agent Studio, and Computer control room.

AI Agent, Computer Agent, and Web exist; Voice Worker remains a target boundary. New services
require a measured scaling, security, dependency, or fault-isolation reason. Splitting CRUD modules
into network services by default is not permitted.

## Runtime topology

The current Compose topology is Nginx -> Web/Core API -> AI Agent/Computer Agent. A separately
deployed, operator-controlled hypervisor gateway is a new trust boundary reached only by Core when
configured. The application stack separates edge,
application, data, AI-egress, and browser-egress networks.
The gateway routes `/api/v1/*` and liveness to Core API and all product routes to the static web
service. Nginx cannot reach PostgreSQL or Redis; PostgreSQL and Redis are not host-published. The local Nginx
port binds only to `127.0.0.1:8080`. `/health` is liveness; `/health/readiness` gates routing on
PostgreSQL and Redis and is blocked at the edge together with other detailed health routes. The AI
Agent has no data-network attachment or database credential; Core reaches it with a file-mounted
service token, and its only outbound network is for model-provider calls. Computer Agent has no
database/data-network access. Core reaches it with a separate file-mounted token; it receives a
persistent profile volume and a distinct browser-egress attachment.

Current and target responsibilities:

| Component | Owns | Does not own |
| --- | --- | --- |
| Nginx | TLS termination, edge limits, proxying | authorization, business policy |
| Web | setup, login, dashboard, Agent Studio, Computer control room, honest connection state | authorization, provider/browser execution |
| Core API | identity, authorization, policy, approvals, authoritative execution and computer records, leases, idempotency, audit | model inference or Chromium process ownership |
| PostgreSQL | authoritative durable state, outbox, audit records, vectors | ephemeral locks or queue delivery |
| Redis | queues, cache, distributed locks, short-lived coordination | authoritative business state |
| AI Agent | typed provider abstraction, registered tool contracts, structured plan requests | final authorization, tool execution, or direct database ownership |
| Compute provider gateway | VM clone/lifecycle/snapshot/resize/status/metrics over KVM, Proxmox, or a cloud API | agent logic, user authorization, prompts, or platform data |
| Agent computer VM | one agent's full Linux/Windows guest OS, disk, applications, files, browser, and daemon | host/hypervisor access, other agent computers, platform secrets |
| Computer Agent | browser actions, frames, artifacts, human input, and runtime fencing inside the assigned computer | VM provisioning, policy decisions, workspace database access, or credential disclosure APIs |

## Domain modules

All workspace-owned operations cross the same enforcement sequence:

1. authenticate the actor;
2. resolve active workspace membership;
3. authorize the named permission;
4. evaluate autonomy, risk, and approval policy;
5. persist the execution/action intent and idempotency key;
6. dispatch through an outbox after commit;
7. execute and verify the result;
8. append an audit event.

The execution API applies steps 1–3 to execution creation, persists the planning intent, asks the
isolated AI service for a typed plan, then reauthorizes each proposed tool against Core-owned
metadata before persisting pending steps. Its first runtime executes only two low-risk read tools,
with a second authorization/argument check, dependency ordering, timeouts, durable verified
checkpoints, cancellation checks, and audit events. It does not yet use a queue, synthesize a model
answer, recover interrupted runs, or support side-effecting actions.

The computer API applies the full boundary to browser actions. Core validates the trusted tool
contract, intersects human and agent authority, evaluates risk/autonomy, binds approvals to exact
payload hashes, requires a workspace-scoped idempotency key, and persists actions/checkpoints before
dispatch. The worker executes only the requested typed action under the current fencing token and
returns observation/verification evidence. Human takeover fences AI control; return-to-AI snapshots
and re-observes under a fresh lease. Recovery is explicit and reopens the same persistent profile.
This computer path is synchronous today; the outbox/Redis queue does not yet dispatch browser jobs.

Runtime agents are now authoritative workspace records rather than prompt labels. Each current
configuration has version records, explicit permission/tool grants, autonomy, schedule,
budget/limit fields, lifecycle state, and manager/escalation links. New executions select the active
default or requested agent and use only the actor/agent/tool intersection. Delegations persist the
intersection of source agent, target agent, and actor authority but are not yet dispatched.
Workspace model profiles provide owner-controlled routing metadata without storing credentials.
Agent references are validated within the workspace, and Core passes the resolved model identifier
to the isolated AI service only when it creates an authorized planning request.

## Ownership and isolation

Every tenant-owned aggregate carries `workspace_id`. Requests must derive workspace context from an
authenticated membership, never trust an arbitrary client-provided workspace identifier, and never
hard-code a user or workspace. Repository queries and unique constraints must include workspace
scope. Cross-workspace administration is not an implicit capability.

The initial product may have one owner, but the data and authorization model is multi-workspace.
Browser profiles, disks, snapshots, files, memory, credentials, integrations, queues, and execution
history must be isolated by workspace and AI computer. Direct agent-to-agent VM entry/networking is
off by default; coordination crosses the audited platform event boundary.

## Events and reliability

PostgreSQL is the source of truth. A transactional outbox records domain events in the same
transaction as state changes. Workers publish/process events asynchronously through Redis. Consumers
must be idempotent and record deduplication state. Redis loss may delay work but must not erase an
accepted action.

External writes use a stable action/execution identifier, an idempotency key, explicit lifecycle
states, and post-action verification. Uncertain outcomes remain `unknown` or `verification_failed`;
they are never reported as successful and are not blindly retried.

## Security boundaries

- The Core API is the policy decision point; workers receive authenticated typed commands plus a
  monotonically increasing fencing token, never raw browser cookies through the API.
- Provider secrets are file-mounted and withheld from product responses. Browser cookies reside in
  isolated persistent profile volumes, but volume encryption/key management is not yet implemented.
- Human pause, takeover, permission revocation, and emergency stop override queued or active AI work.
- VM lifecycle is Core-authorized, idempotent, audited, provider-verified, and subject to workspace
  count/running/CPU/RAM/disk quotas.
- Browser and desktop control are exclusive per computer session via a distributed lease with
  fencing tokens.
- Web content and integration data are untrusted input, not executable agent instructions.
- Every external side effect requires authorization, auditability, idempotency, and verification.

## Service contracts

External clients use versioned HTTP under `/api/v1` once those routes exist. Internal services use
versioned HTTP commands for synchronous decisions and versioned domain events for asynchronous work.
Contracts include `request_id`, `workspace_id`, `actor`, `execution_id`, schema version, and trace
metadata. Internal callers authenticate with service identity; network placement alone is not trust.

Breaking contract changes require a new API/event version and a migration period. Shared database
access by future services is prohibited: each service accesses authoritative records through the
owning module's contract, except workers embedded in the Core API deployment.

## Evolution gates

A module may be extracted only after its ownership, API, event contract, failure behavior, and
operational benefit are documented. Production readiness additionally requires a Docker/PostgreSQL
evidence run, least-privilege database roles, encrypted browser storage, controlled browser egress,
backups/restoration, monitoring/alerts, TLS/host hardening, and a reviewed security test campaign.
The current repository has not reached that gate.
