CHAPTER 04 · 3 min read

Architecture

How Forge realizes the Domain Model.

Domain ConceptArchitectural RealizationBuilderHuman user, agent, service principalGoalGoal record, planning context, task contextCapabilityAPI-exposed platform operationResourceDurable state objectEventImmutable event recordPolicyPolicy engine rulePermissionAuthorization relationship
Every domain concept maps to a specific architectural realization. The Capability row (ember) is the primary action boundary — it is the only way behavior happens.
Builder InterfaceCLI · UI · SDK · AgentCapability APIPOST /capabilities/:slugCapability Runtimevalidate → permission → policy → execute → auditImplementationBazel · Jest · Kubernetes · OpenAI …Resource StoreEvent Stream
The Forge architecture stack. Builders enter at the top; the Capability API is the only boundary through which behavior flows. Implementations are replaceable; the core is stable.

Development Environment

Forge — Development Environment The ./forge CLI drives the control-plane API; the control plane runs build / test / lint in Docker (Docker-out-of-Docker). Host machine · Docker Desktop (arm64) Builder / agent runs ./forge build = ./forge CLI (thin HTTP client) Forge Control Plane container · forge-control-plane image Fastify API :3717 · tsx · Docker CLI runtime: validate → policy → execute → audit Host Docker daemon /var/run/docker.sock Ephemeral container web · node:22-slim npm run build|test|lint --rm --no-deps (skips db) 1 2 3 4 5 ./app — app source bind-mounted, host ≡ container path .forge — state Resources + Events (JSON/JSONL) bind mount Call path — forge build --app <n> (test / lint are identical with npm run test|lint) 1 Builder runs ./forge build → the CLI sends POST /capabilities/build to the control-plane API (:3717). 2 The control plane (build-npm Implementation) runs docker compose run --rm --no-deps -T web npm run build on the host daemon via the mounted socket (DooD). 3 The daemon spins an ephemeral web container (node:22) with ./app bind-mounted; the build runs there and exits. 4 Output + exit code stream back; the control plane records a Build Resource and a BuildSucceeded/Failed Event in .forge. 5 The CLI renders a compact JSON result to the Builder. DEV-ONLY: the control-plane image bundles developer dependencies — Docker CLI, tsx, and the build/test/lint toolchain. Postgres/Redis are started only for forge dev, not for build/test/lint.
Forge development environment — control plane and sidecar layout in local development. Sourced from forge vvendored docs.

Production Environment

Forge — Production Environment (target) Data-plane call path: scheduled jobs & notifications. No build / test / lint here — those are dev-only (control plane). Production deployment Forge Data Plane runtime slim image — NO dev deps Schedulerrecurring / one-shot jobs (C2) Secretsencrypted store + runtime injection (C5) Event logemit / query domain facts (C3) Notificationsconditions → produce & deliver (C4) App (web) — production production build · next start exposes /api/cron/* · /api/health reads secrets ← process.env runs the work, emits events → domain logic stays here (streaks, goals…) Postgres data-plane persistence (app state) Notification delivery push / email / webhook End user (may be away / asleep) 1 2 POST /api/cron/… 3 read / write state 4 emit events 5 produce & deliver async inject at boot Absent here: build / test / lint, the ./forge CLI, and Docker-out-of-Docker — all dev-only (control plane). Call path — a scheduled job that notifies (e.g. “you’re about to break your streak”) 1 The data-plane scheduler fires on cadence (cron / interval) — with no user present. 2 It calls back into the app: POST /api/cron/… (e.g. habits-finalize, reminders). The app must be reachable + running. 3 The app reads/writes Postgres and computes what changed (domain logic stays in the app). 4 The app emits domain events to the data-plane event log (facts). 5 The notifications capability turns conditions over events/state into notifications and delivers them — reaching the user asynchronously, even while away. Setup: secrets (C5) are injected into the app’s process.env at boot from the encrypted store — the app just reads env; the scheduler/events/notifications live in the data plane. DESIGN DECISION (next) — how is the data plane packaged & deployed? (a) sidecar beside each app · (b) standalone shared service · (c) embedded library — plus a slim prod image (no dev deps) and a deploy pipeline.
Forge production environment — control plane, sidecar, and application container layout in production. Sourced from forge docs.

Forge Architecture

Architecture explains how Forge realizes the Domain Model.

The Domain Model defines the problem language.

Architecture defines the solution structure.

Do not mix them.

Architectural Center

Forge realizes the Domain Model through this architecture:

Builder Interface
    ↓
Capability API
    ↓
Capability Runtime
    ↓
Implementation
    ↓
Resource Store
    ↓
Event Stream

Domain to Architecture Mapping

Domain ConceptArchitectural Realization
BuilderHuman user, agent, service principal
GoalGoal record, planning context, task context
CapabilityAPI-exposed platform operation
ResourceDurable state object
EventImmutable event record
PolicyPolicy engine rule
PermissionAuthorization relationship

Capabilities

Capabilities are the architectural boundary for behavior.

Every meaningful action in Forge is modeled as a Capability.

Examples:

  • Build
  • Test
  • Deploy
  • Evaluate
  • Search
  • Analyze
  • Plan
  • Generate

Capabilities are stable contracts.

They hide Implementations.

Implementations

An Implementation performs a Capability using specific technology.

Examples:

  • Bazel implementation of Build
  • Buck2 implementation of Build
  • Jest implementation of Test
  • Playwright implementation of Test
  • Kubernetes implementation of Deploy
  • OpenAI implementation of Generate
  • Anthropic implementation of Analyze

Implementations are replaceable.

Implementations do not define the Builder experience.

Plugins

A Plugin packages one or more Implementations.

Plugins exist at technology boundaries.

Use Plugins for:

  • build systems
  • test frameworks
  • deployment targets
  • model providers
  • source control providers
  • identity providers
  • runtime providers

Do not use Plugins for business logic.

Do not use Plugins for speculative abstraction.

Do not create a Plugin unless technology changes.

Resources

Resources are the durable state model of Forge.

Every Resource has:

  • identity
  • type
  • state
  • lifecycle
  • relationships
  • ownership
  • permissions
  • history
  • Events

Resources do not call Plugins.

Resources do not own behavior.

Capabilities create or modify Resources.

Events

Events are the history of Forge.

Events are emitted when Resources change or meaningful platform facts occur.

Events enable:

  • observability
  • automation
  • replay
  • auditing
  • agent awareness
  • integration

Events are facts, not commands.

Policies and Permissions

Policies decide whether something is allowed.

Permissions decide whether a Builder may act.

Policy and permission checks happen before Capability execution and may also occur during Resource transitions.

Workflow Composition

A Workflow is architectural composition.

It is not a domain primitive.

A Workflow composes Capabilities to satisfy a Goal.

Example:

Plan
  → Build
  → Test
  → Evaluate
  → Deploy
  → Observe

Workflow composition should be explicit.

Do not hide critical behavior in Plugins.

The Core

The Forge core owns:

  • Capability routing
  • Resource lifecycle
  • Event publication
  • Policy evaluation
  • Permission checks
  • Implementation selection
  • workflow composition
  • auditability

The core should be boring.

The core should be stable.

The core should not know the details of Bazel, Kubernetes, OpenAI, or any other provider.

Architecture Rule

Capabilities expose behavior. Resources represent state. Implementations perform work. Plugins package implementations. Events record facts. Policies govern. Permissions authorize.

When architecture becomes unclear, return to this sentence.