Skip to content

System overview

paperboard is a multi-repo microservices platform. We chose this structure deliberately: each service owns its schema, its release lifecycle, and its scaling profile independently. The coupling between services is explicit (gRPC contracts in paper-board/proto) rather than implicit (shared database tables). This made early phases faster to ship and will make Phase 6+ hardening tractable.

flowchart LR
subgraph ext["External"]
client{{"Browser / CLI / MCP"}}
anthropic{{"Anthropic API"}}
s3{{"S3"}}
payment{{"Payment provider"}}
end
subgraph control["Control plane"]
gateway["gateway\nPhase 7"]
identity["identity\nPhase 2 ✅"]
platform["platform\nPhase 4"]
billing["billing\nPhase 5"]
end
subgraph data["Data plane"]
agents["agents\nPhase 1.1 ✅"]
runtime["runtime\nPhase 3 ✅"]
end
subgraph sandbox["Sandbox tier"]
compute["compute\nPhase 3 ✅"]
end
subgraph support["Supporting"]
sdk[("sdk")]
proto[("proto")]
infra[("infra")]
frontend[("frontend")]
cli[("cli")]
end
subgraph storage["Persistence"]
pg[("Postgres\nschema-per-service")]
redis[("Redis\nPhase 4+")]
pvc[("PVC / S3\nworkspace")]
end
client --> gateway
gateway --> identity
gateway --> agents
gateway --> billing
agents --> runtime
agents --> anthropic
runtime --> compute
compute --> s3
compute --> pvc
agents --> pg
identity --> pg
billing --> pg
platform --> pg
platform --> redis
billing --> payment
classDef controlPlane fill:#10b981,stroke:#047857,color:#fff
classDef dataPlane fill:#3b82f6,stroke:#1d4ed8,color:#fff
classDef sandbox fill:#f97316,stroke:#c2410c,color:#fff
classDef external fill:#ef4444,stroke:#b91c1c,color:#fff
classDef persistence fill:#6b7280,stroke:#374151,color:#fff
class gateway,identity,platform,billing controlPlane
class agents,runtime dataPlane
class compute sandbox
class client,anthropic,s3,payment external
class pg,redis,pvc,sdk,proto,infra,frontend,cli persistence

The color coding carries semantic meaning throughout all paperboard diagrams:

ColorRoleServices
GreenControl planegateway, identity, platform, billing
BlueData planeagents, runtime
OrangeSandbox tiercompute (gVisor boundary)
RedExternalAnthropic API, payment provider, S3, clients
GrayPersistencePostgres, Redis, PVC, sdk, proto, infra

The control plane services own configuration, identity, billing state, and orchestration. They are stateful (each owns a Postgres schema) and change infrequently relative to the data plane.

identity (Phase 2 ✅) manages who is allowed to do what. It owns user accounts, organizations (tenants), RBAC roles, JWT signing keys, MFA, API keys, and invitation flows. Every other service trusts identity’s JWT claims; they do not re-verify signatures.

platform (Phase 4) is the cross-cutting event hub. It owns the audit log, incidents, notifications, webhooks, and onboarding events. From Phase 4+, platform is the first consumer of usage events emitted by compute — it aggregates metering data that billing later reads.

billing (Phase 5) owns subscriptions, pricing rates, and the payment abstraction layer. We chose to keep billing as a single cohesive context rather than split it into separate subscription-service and payment-service because the coupling between pricing rules and payment provider state is tight enough that splitting would create more coordination overhead than it saves.

gateway (Phase 7) is the public API entry point. It centralizes JWT verification, rate limiting (Redis), and idempotency middleware. Phases 1–6 handle auth per-service; Phase 7 moves it here. We deferred gateway because centralization before the auth contracts stabilize creates churn.

agents (Phase 1.1 ✅) is the product itself from the user’s perspective. It owns agent definitions and versions, sessions (the event store), budget reservations, memory collections (pgvector in Phase 5+), and artifact metadata. When a user sends a message, agents receives it, dispatches to the Anthropic API for LLM inference, and streams the response back via SSE.

runtime (Phase 3 ✅) is the per-tenant execution pod. It is stateless — it holds no persistent state of its own. Its role is to receive a prompt from agents, fetch the agent definition, and dispatch the actual code execution down to compute. One runtime pod per (org_id, image_digest) tuple at steady state.

compute (Phase 3 ✅) runs code in gVisor-isolated pods. It is the security boundary: anything a user’s agent does that touches the file system or network happens inside a gVisor sandbox. After execution, compute emits usage events (pod-seconds, tool-calls, workspace-minutes) and flushes workspace state to S3 via the workspace bridge sidecar.

sdk (paper-board/sdk) is the shared Go library. It ships log, obs (OTel), auth/middleware, migrator, and shared errors. It is MIT-licensed (open core) and SemVer-disciplined.

proto (paper-board/proto) is the single source of truth for all gRPC and HTTP contracts. buf generate produces Go + TypeScript clients. Consuming services bump the proto dependency to pick up contract changes.

infra (paper-board/infra) holds the Helm umbrella chart, per-service subcharts, Terraform, and Kubernetes manifests. The Helm chart version mirrors the service version.

We build in vertical slices per ADR-0015. The key structural decision driving the phase order: paperboard’s revenue model is compute markup, not token markup. This means metering infrastructure had to land in Phase 3 (not Phase 8 as originally planned) and the billing engine in Phase 5.

flowchart TD
p10["Phase 1.0 ✅\nsdk · proto · infra"]
p11["Phase 1.1 ✅\nagents minimal"]
p2["Phase 2 ✅\nidentity"]
p3["Phase 3 ✅\nruntime · compute\nmetering hooks"]
p4["Phase 4 — next\nplatform · MVP-0 launch\nfirst sellable milestone"]
p5["Phase 5\nPayment · MCP harness"]
p6["Phase 6\nhardening · KVKK"]
p7["Phase 7\ngateway · RBAC full"]
p8["Phase 8\nsource-available · self-host"]
p9["Phase 9\npaperclip-equivalent"]
p10_f["Phase 10\nmarketplace · agent teams"]
p10 --> p11 --> p2 --> p3 --> p4 --> p5 --> p6 --> p7 --> p8 --> p9 --> p10_f
classDef controlPlane fill:#10b981,stroke:#047857,color:#fff
classDef dataPlane fill:#3b82f6,stroke:#1d4ed8,color:#fff
classDef sandbox fill:#f97316,stroke:#c2410c,color:#fff
classDef external fill:#ef4444,stroke:#b91c1c,color:#fff
classDef persistence fill:#6b7280,stroke:#374151,color:#fff
class p10,p11,p2,p3 controlPlane
class p4,p5 dataPlane
class p6,p7 sandbox
class p8,p9,p10_f persistence

Phase 4 is the first sellable milestone (MVP-0): platform + audit + onboarding + one agent template + BYO API key + manual email invoice.

The major cross-cutting decisions are recorded as ADRs:

ADRDecision
0001Multi-repo (12 repos, each with its own go.mod)
0002Schema-per-service (single Postgres cluster)
0003No cross-schema FK — UUID-by-reference only
0004Shared migrator SDK
0005REST public + gRPC internal
0015MVP-first phase ordering (amends ADR-0014)

See the full Decisions index for all ADRs.