# AWP FOSS Minimalism Decision Pass

**Date:** 2026-08-19  
**Status:** Accepted planning input  
**Purpose:** Re-run the unresolved FOSS/provider choices using a stronger minimalism rule: choose the smallest dependency that removes meaningful recurring code, prefer standards/libraries/native platform primitives over services/controllers, and keep optional portability where it is nearly free.

## 1. Decision rule

The new default is:

```text
standard > library > native platform primitive > single binary > controller/operator > service stack
```

That ordering is not absolute. A larger dependency is justified when it removes a larger, riskier subsystem that AWP would otherwise have to own.

For every candidate:

```text
1. Does AWP actually need the capability now?
   no  -> do not install it.

2. Is the capability product semantics?
   yes -> AWP owns it; do not outsource the model.

3. Does Node/Postgres/Kubernetes already provide enough mechanics?
   yes -> use the native primitive.

4. Can a small library or protocol remove the remaining code?
   yes -> prefer it over a service/controller.

5. Would a larger provider delete a genuinely difficult subsystem?
   yes -> adopt it behind an AWP interface.

6. Can the choice preserve cheap portability?
   yes -> prefer Web Standards, PostgreSQL, S3, OCI, Kubernetes APIs, CloudEvents and other portable boundaries.
```

The goal is not dependency-count minimalism at any cost. The goal is **minimum total system complexity**.

## 2. Decisions promoted by this pass

### HTTP transport: Hono

**Decision: ADOPT Hono.**

Hono is small, TypeScript-first, MIT licensed, Web-Standards based, and supports Node plus multiple edge/serverless runtimes. AWP only needs the HTTP layer to provide routing, middleware, validation integration, streaming and transport concerns around an application/domain core. Fastify's richer plugin encapsulation and server lifecycle are useful capabilities, but AWP does not currently need them and they create a second architectural framework beside AWP's own Modules.

Cloudflare portability is a bonus, not the reason for the choice.

### Durable control-plane workflows: DBOS

**Decision: ADOPT DBOS as `DurableWorkflowProvider`. Do not adopt Hatchet as the baseline.**

DBOS is an MIT TypeScript library that stores durable workflow checkpoints/queues in PostgreSQL and requires no separate orchestration server. That fits the modular-monolith control plane and the already-selected PostgreSQL dependency.

Hatchet is capable, but self-hosting introduces a separate control plane/server and workers, with PostgreSQL and optional RabbitMQ. Its queue/routing/dashboard features are valuable at larger orchestration scale, but AWP does not currently need enough of them to justify another service authority.

DBOS Conductor is **not** a baseline AWP dependency. If future horizontal-HA/operations requirements cannot be met cleanly by the AWP deployment model plus DBOS library/Postgres, re-evaluate the provider boundary rather than silently introducing another control plane.

### Domain lifecycle modeling: typed AWP transitions, no XState

**Decision: DO NOT use XState for authoritative backend lifecycle state.**

XState is zero-dependency and capable, including persistence, but it introduces an actor/statechart model and its own persisted snapshot semantics. AWP's authoritative state already must live transactionally in PostgreSQL with explicit commands, guards, events and audit.

Use small typed transition tables/functions owned by each AWP domain Module. XState remains acceptable for isolated UI state only if a concrete UI interaction later benefits from it.

### Workspace execution: native Kubernetes first

**Decision: native Pod/PVC/ServiceAccount/NetworkPolicy is the baseline `WorkspaceProvider`. Do not install Kubernetes Agent Sandbox initially.**

Agent Sandbox is unusually well matched to AWP and now provides Sandbox/SandboxClaim/SandboxTemplate/SandboxWarmPool abstractions, but it is still an additional CRD/controller layer over primitives AWP already requires. Its API has also undergone alpha-to-beta migration.

Add it only if measured workspace startup/warm-pool/hibernation complexity becomes material. AWP's Workspace model must remain independent either way.

### Runtime isolation: gVisor for untrusted AgentRuns

**Decision: use native runc/containerd for trusted control-plane workloads; use gVisor `RuntimeClass` as the preferred isolation profile for untrusted AgentRun workloads on supported nodes.**

Kubernetes `RuntimeClass` makes this a per-pod choice. gVisor is specifically designed to isolate untrusted code without the full VM machinery required by Kata Containers. It has compatibility and I/O/network overhead trade-offs, so AWP keeps a policy-controlled native fallback for workloads that fail compatibility checks. Kata is reserved for customers/threat models that explicitly require VM-backed isolation.

### Agent interoperability: ACP

**Decision: ADOPT Agent Client Protocol as the preferred generic `AgentProvider` wire protocol where an agent supports it.**

ACP is Apache-2.0 and intentionally defines a lean JSON-RPC interoperability boundary between coding agents and clients. Native provider adapters remain allowed for capabilities ACP cannot represent. Do not force all agents through a lowest-common-denominator path.

### Coding-agent factory: Fabro

**Decision: ADOPT Fabro as the primary `FactoryProvider`.**

Fabro is MIT licensed, distributed as a single Rust binary with no language runtime requirement, provides agent/command/human workflow graphs, REST/SSE, cancellation/resume/checkpoint behavior, and supports API/CLI/ACP agent backends. This is exactly the kind of external dependency that earns its place: one small executable can delete a large custom multi-agent workflow subsystem.

AWP still owns `FactoryRun`, `AgentRun`, policy, approvals, relationships and lifecycle meaning.

### PostgreSQL operations

**Decision: PostgreSQL is the product dependency; CloudNativePG is not a core dependency.**

AWP connects through a normal PostgreSQL contract. Prefer an external/managed PostgreSQL service for production when available. This makes deployment portable across K3s, VMs and public clouds and keeps the AWP chart small.

For customers requiring fully self-hosted production PostgreSQL on Kubernetes, CloudNativePG plus its current Barman Cloud Plugin architecture is the preferred optional deployment profile. Do not make every AWP installation run a database operator.

### Object storage

**Decision: external S3-compatible storage is the default `ObjectStoreProvider`; do not bundle an object-store service by default.**

For a self-contained installation that requires local object storage, SeaweedFS is the preferred small permissive option because it is Apache-2.0 and its single `weed` binary can expose an S3 endpoint in `mini` mode. AWP must depend only on the explicitly tested S3 subset it requires, not assume full AWS S3 behavior.

### Kubernetes networking and policy

**Decision: keep native K3s/Kubernetes primitives.**

No baseline Cilium/Hubble. No baseline Kyverno. No service mesh. Use Flannel, kube-router NetworkPolicy, PSA, VAP/CEL, RBAC and explicit security contexts. Add a controller only after a concrete requirement cannot be expressed cleanly enough with native primitives.

### CI execution

**Decision: ARC-managed GitHub Actions runners on K3s are baseline from day 1; Dagger is not baseline.**

GitHub Actions is the initial CI provider because existing repositories already express CI in project-owned workflows and the product requires centralized K3s-hosted runners rather than independently maintained runner daemons on each machine. Actions Runner Controller earns its controller/operator cost because it removes that recurring runner registration, lifecycle, scaling and cleanup burden across the cluster.

ARC owns runner scale-set mechanics and ephemeral runner pod lifecycle. AWP owns CIExecution/CIResult semantics, policy, correlation, progression and operator UX. Project-native `.github/workflows/*` remain authoritative provider input. AWP may execute preflight/ad-hoc checks in AgentRun workspaces, but it does not create a second competing CI system.

Dagger remains project-native only when a repository already uses it.

### Work-management semantics

**Decision: no external Scrum/Kanban/Scrumban semantics library.**

These semantics are AWP product behavior: WorkItem lifecycle, WIP policy, pull/start rules, cadence, review/release policy and customization. Outsourcing them would either leak another product model into AWP or save very little code.

Keep the model as small typed policy/data structures. Continue using Pragmatic Drag and Drop only for board interaction mechanics.

### Operational charts

**Decision: ADOPT Chart.js, not ECharts, as the default charting library.**

Chart.js is MIT, simple, mature and tree-shakeable. AWP needs ordinary operational time-series/bar/doughnut-style visualization much more than it needs a large visualization platform. Use Chart.js directly behind AWP chart components rather than adding another React wrapper by default.

Every critical chart still needs a textual/table equivalent for accessibility and operational comprehension.

### Telemetry

**Decision: OpenTelemetry API/SDK/export boundary is required; OpenTelemetry Collector and persistent telemetry backends are optional deployment infrastructure, not baseline services.**

AWP business events and audit live in AWP/PostgreSQL. Structured process logs go to stdout/stderr. Metrics/traces use OTel-compatible instrumentation and can export directly to a configured endpoint. Add a Collector only when routing, batching, transformation or multi-backend fan-out is actually required.

Do not bundle Prometheus + Jaeger + a log database merely to claim observability.

### Feature flags / activation policy

**Decision: no OpenFeature baseline.**

AWP owns typed activation/landing policy directly. Add an OpenFeature adapter only if external feature-flag providers become a real integration requirement.

### Secrets in Git

**Decision: default policy is no secrets in Git, including encrypted secret payloads.**

SOPS + age is an opt-in project policy only. This is smaller and safer than introducing a Git secret workflow for every project.

### Release preparation

**Decision: project-native first; no default release-management service/library.**

If a repository already uses Changesets, Release Please, semantic-release or project scripts, AWP invokes/adapts them. Otherwise AWP needs only a small built-in release-preparation path around explicit version/tag/changelog policy. AWP `Release` remains authoritative.

### External event interoperability

**Decision: use CloudEvents as the generic external event envelope; do not make CDEvents a core dependency.**

CloudEvents is a graduated CNCF standard with a stable generic event envelope. CDEvents adds a CI/CD-specific vocabulary and is useful at integration boundaries, but AWP already owns richer internal delivery semantics. Add a CDEvents adapter only when a provider/customer requires it.

### Incident diagnosis

**Decision: no HolmesGPT baseline.**

AWP already has ModelGateway/agents and deterministic Resolver mechanics. Use the existing AI/provider layer for optional diagnosis and keep resolver actions explicit and auditable. Add a dedicated diagnostic provider only if a real incident corpus proves it removes substantial custom work.

### Kubernetes deployment/CD

**Decision: baseline Kubernetes deployment uses Helm-rendered manifests plus Kubernetes Server-Side Apply and AWP-owned health/rollback orchestration. Flux is not a baseline dependency.**

Server-Side Apply is stable Kubernetes functionality and already provides declarative field ownership/conflict detection. Flux introduces several controllers and CRDs in order to continuously reconcile Git/OCI/Helm sources.

Add Flux only for projects/customers that explicitly require continuous GitOps reconciliation independent of the AWP control plane. Flagger remains conditional on an actual progressive-delivery requirement.

### Self-hosted registry

**Decision: GHCR first; zot is the selected self-hosted registry if one is required.**

zot is Apache-2.0 and focuses narrowly on the OCI Distribution Specification. Harbor is reserved for enterprise requirements that justify its larger feature/operations surface.

### External secrets

**Decision: no OpenBao/ESO baseline.**

If a customer already has an external cloud/vault secret authority, add an External Secrets Operator adapter to synchronize it. Add OpenBao only when AWP must provide a self-hosted dynamic secret authority itself.

### Tenant isolation

**Decision: namespace/RBAC/network/runtime isolation first; no vCluster baseline.**

vCluster is only added when a real tenant threat/compatibility requirement proves namespace-level Kubernetes isolation insufficient.

### Cloud/IaC provisioning

**Decision: if AWP later owns cloud infrastructure provisioning, prefer OpenTofu CLI as the first provider; do not introduce Crossplane by default.**

OpenTofu is a CLI/provider graph around declarative infrastructure and can run as a controlled AWP operation. Crossplane adds a persistent Kubernetes control-plane/controller model. The latter is only justified if continuous infrastructure reconciliation through Kubernetes becomes an explicit product requirement.

## 3. Resulting small baseline

The intentionally small baseline is now:

```text
APPLICATION
  TypeScript / Node / ESM
  Hono
  PostgreSQL + Drizzle
  DBOS library

UI
  React + Astryx
  Pragmatic Drag and Drop
  React Flow
  Chart.js

EXECUTION
  K3s / Kubernetes
  native Pod/PVC workspace provider
  gVisor RuntimeClass for untrusted AgentRuns
  Dev Container standard/CLI
  Fabro
  ACP

DELIVERY / EVIDENCE
  GitHub Actions
  ARC runner scale sets on K3s
  ephemeral CI runner pods
  project-native preflight commands in AWP workspaces where useful
  Helm + Server-Side Apply
  Trivy
  Cosign
  ORAS
  CloudEvents at external boundaries

STORAGE / SERVICES
  external PostgreSQL preferred for production
  external S3-compatible object store
  GHCR

OBSERVABILITY
  durable AWP business events/audit in Postgres
  structured logs
  OpenTelemetry SDK/export boundary
```

Everything else is conditional infrastructure.

## 4. Why this is more portable without becoming "serverless architecture"

This plan does not try to make AWP run wholly on Cloudflare or another serverless platform. That would conflict with the execution plane's Kubernetes, filesystems, agent processes, workspaces and build tooling.

It does, however, avoid gratuitous coupling:

```text
HTTP          Web Standards / Hono
state         PostgreSQL
objects       S3-compatible API
artifacts     OCI
execution     Kubernetes API
agent wire    ACP where possible
external evt CloudEvents
IaC           OpenTofu when required
```

That means a future deployment can move the web/API/control-plane process to a VM, container service, managed Kubernetes or partially serverless edge without first undoing unnecessary framework/controller assumptions.

## 5. Primary-source evidence checked in this pass

The pass was verified against current primary documentation/repositories for:

- Hono Web-Standards/multi-runtime architecture and MIT license.
- DBOS TypeScript durable workflows, PostgreSQL-only core architecture and MIT license; Conductor production recommendation noted separately.
- Hatchet self-host control-plane components.
- XState v5 persistence/TypeScript model and zero-dependency package.
- Kubernetes Agent Sandbox current Sandbox/Claim/Template/WarmPool APIs and v1alpha1-to-v1beta1 migration.
- Kubernetes RuntimeClass.
- gVisor Kubernetes/containerd integration, production security/performance guidance and compatibility model.
- Kata Containers RuntimeClass/VM deployment requirements.
- Agent Client Protocol specification/TypeScript SDK and Apache-2.0 licensing.
- Fabro workflow/agent architecture, ACP support, REST/SSE API, single-binary distribution and MIT license.
- CloudNativePG current CNPG-I/Barman Cloud Plugin backup architecture.
- PostgreSQL native base backup/WAL/PITR facilities.
- Kubernetes Server-Side Apply.
- Flux controller/component architecture.
- Dagger engine/module architecture.
- GitHub Actions Runner Controller architecture.
- Chart.js tree-shaking and MIT licensing.
- CloudEvents and CDEvents specifications.
- SeaweedFS S3/`weed mini` path and Apache-2.0 licensing.
- zot OCI registry and Apache-2.0 licensing.
- OpenTofu CLI/provider model.

This file records the reasoning pass. Binding dispositions live in `AWP-FOSS-DECISIONS.md` and consuming implementation gates live in `STEP-0-PREPARATION-DEPENDENCIES.md`.