Skip to content

FractalOps Canonical Architecture

FractalOps is a four-repository system assembled and deployed through Kubernetes. The architecture favors stack-native capabilities, explicit ownership, and one durable path per outcome.

RepositoryOwnsMust not own
ContractOpenAPI, events, shared schemasRuntime policy or deployment
BackendDomain behavior, application flows, adapters, Supabase migrationsUI source or Kubernetes topology
FrontendPortal and desktop UIBackend policy or deployment pins
AssemblyImmutable repository/image pins, Kubernetes composition, docs, integrated proofSibling implementation internals

Contract changes land first, backend/frontend consumers second, and Assembly pins last. Cross-repository tests use public contracts and immutable artifacts.

flowchart TB
  edge["Cloudflare / protected ingress"] --> identity["Dex-first OIDC"]
  identity --> api["FractalOps API"]
  api --> temporal["Temporal"]
  temporal --> worker["FractalOps worker"]
  worker --> daytona["Daytona project workspace"]
  daytona --> agents["Provider processes"]
  agents --> mcp["ContextForge MCP/A2A gateway"]
  mcp --> authz["SpiceDB"]
  api --> supabase["Supabase on CNPG"]
  supabase --> seaweed["SeaweedFS durable storage"]
  assembly["Argo CD + Assembly pins"] --> api
  assembly --> worker

The API accepts commands and serves projections. Temporal owns durable cadence, retries, and timeouts. The worker calls Studio execution directly; Studio launches and observes provider processes through Daytona. No internal agent-server or duplicate orchestration queue sits between Temporal and Studio.

Agent identity is independent from provider process identity. The target invariant is one Daytona sandbox per project, eight durable profiles, and at most four concurrent provider processes. A Codex process may hand the same profile to Claude without changing its worktree, mailbox, context, or authorization subject.

  • Studio owns run/session lifecycle and mailbox state.
  • Agent Execution owns profile, lease, takeover, and provider policy.
  • Armory compiles required skills and MCP capabilities.
  • ContextForge authenticates and routes MCP/A2A traffic and emits telemetry.
  • SpiceDB authorizes the stable profile subject.
  • Bubblewrap and cgroup v2 contain one fenced provider generation.

See Agent Execution and ADR-0011.

Self-hosted Supabase is the application data stack. PostgreSQL runs on CNPG; durable object storage uses SeaweedFS. Backend migrations under supabase/migrations are the schema authority. Runtime create_all, Alembic, and parallel standalone PostgreSQL stacks are prohibited.

Dex handles standard OIDC federation. Special SCIM or FractalOps connector behavior may use a dedicated adapter, but must not fork common OIDC logic. OpenBao stores secret values; Git contains only references and public configuration.

Assembly CUE is the environment SSOT and renders Helm values. Argo CD reconciles immutable pins. Each independently scaled process may have its own Deployment, but a separate deployment is not a license to duplicate domain orchestration.

OCI builds run only on the Kubernetes BuildKit plane. Release evidence must connect:

source commit -> BuildKit result -> OCI digest -> Assembly pin -> live imageID

Host-local Docker builds and mutable production tags are invalid evidence.

  • Domain code depends on domain concepts, never Kubernetes or vendor SDKs.
  • Application slices coordinate outcomes through narrow ports.
  • Adapters translate Daytona, Supabase, Temporal, ContextForge, and other native APIs.
  • Interfaces expose HTTP, workers, and operator projections without owning policy.
  • Tests are colocated with the smallest behavior owner.
  • Thin facades, pass-through queues, duplicated state machines, and compatibility aliases require an active removal plan.

Headlamp is the primary live observation surface. Repository state describes desired state; completion requires live workload, image digest, route, event, and resource evidence.

High-risk AgentSquad releases are canary-first and require one-sandbox topology, generation fencing, takeover, authorization denial, roster delivery, and 24-hour leak-free soak evidence. Rollback uses the previously pinned digest and never rebuilds an image locally.