# Module Boundaries

**Status:** Approved target-state baseline  
**First realization:** I0  
**Enforcement:** architecture fitness checks from I0.

## Target State

AWP starts as a modular monolith with explicit deployable and package boundaries. Module ownership follows domain/application/provider separation rather than Hono routes or vendor SDKs.

```text
apps/
  gateway/
  control-plane/
  web/

packages/
  contracts/
  domain/
  application/
  providers/
  adapters/
```

Exact folders may refine as domain modules grow, but dependency direction is binding.

## Invariants From Day 1

```text
gateway -> contracts
web     -> contracts
control -> application + domain + providers + contracts
application -> domain + provider interfaces
domain -> domain only / runtime-neutral shared primitives
adapters -> provider interfaces + SDK/infrastructure libraries

FORBIDDEN
gateway -> DBOS / repositories / Kubernetes / GitHub SDK
domain  -> Hono / React / Kubernetes / GitHub / Fabro / DBOS SDK types
web     -> server repositories/provider SDKs
provider adapter -> mutate unrelated domain state directly
```

Domain code defines policy-free value semantics and lifecycle invariants. Application services orchestrate authorization, repositories, policies and provider interfaces. Adapters translate external mechanics.

## Module Families

The control plane should organize application/domain code around cohesive families rather than one giant package:

```text
projects
planning/work
factory/agents/workspaces
changes/reviews
verification/ci
delivery
cluster
connections/providers
configuration/policy/governance
incidents/communications
```

Cross-family dependencies use explicit application/domain contracts. Avoid convenient bidirectional imports; shared concepts should live in a smaller stable package or communicate by IDs/events/use cases.

## Transport Boundary

Hono route handlers:

1. parse/validate transport DTO;
2. establish caller/gateway context;
3. call application command/query;
4. map result/error to transport contract.

They do not contain lifecycle transition logic, SQL, Kubernetes orchestration or policy implementation.

## Provider Boundary

A provider interface is owned by the AWP capability that needs the mechanics, not by the vendor. For example:

```text
WorkspaceProvider     not KubernetesService
ForgeProvider         not GitHubService
FactoryProvider       not FabroService
DurableWorkflowProvider not DBOSService
CIProvider            not ActionsService
DeploymentProvider    not KubernetesDeploymentService
```

Adapters may expose provider-specific capability descriptors internally, but application/domain APIs remain AWP vocabulary.

## Transaction Boundary

Repositories are invoked through application use cases with explicit transaction/unit-of-work behavior. A module cannot mutate another module's tables as an undocumented shortcut. Cross-domain atomic changes use application-level transaction orchestration and shared outbox/audit behavior.

## Realtime Boundary

Realtime projection modules consume business events/read models. They cannot mutate authoritative lifecycle state by bypassing application commands.

## Architecture Fitness Rules

From I0, dependency-cruiser or an equivalent existing Platform capability enforces at minimum:

- forbidden imports above;
- no circular package dependencies across domain modules;
- adapter packages may depend inward; domain packages may not depend outward;
- gateway/web remain free of control-plane infrastructure packages;
- restricted import of secret-store implementations into execution-facing code.

Rules are version controlled and CI-required.

## Increment Realization

| Increment | Module boundary work |
|---|---|
| I0 | Package/deployable skeleton, dependency rules and architecture CI checks. |
| I1 | Project/work/factory/change/review modules prove boundary discipline. |
| I2–I8 | New modules fit the existing dependency law; no restructuring into microservices just because scope grows. |
| I9 | Service extraction is allowed only by Decision backed by scaling/team/availability evidence. |

## Current Implementation State

No legacy Overdeck module graph is authoritative. Useful mechanics may be ported/adapted only into the new boundaries.

## Deferred Realization

Physical service decomposition, event bus infrastructure and distributed-domain ownership are not target requirements. The modular monolith remains the default unless evidence demands extraction.

## Temporary Dogfood Behavior

A small I0/I1 codebase may place several modules in one package initially only if internal folder/import boundaries and public exports already preserve the target dependency direction. It must not become a permanent grab-bag package.

## Decisions / ADRs

See ADR 0002. Any service extraction or dependency-law relaxation requires a Decision and corresponding fitness-rule update.