# ADR 0001: Govern as a Modular Monolith

Status: Accepted

Date: 2026-07-29

## Context

The application is deployed on a LAN NAS as one Docker container with a Python HTTP process,
SQLite, a build-free browser client, scheduled refresh work, external market providers, and
LLM features. Product breadth has grown, while routing, persistence, frontend state, and CSS
remain concentrated in a few large files.

The system may later become internet-facing, gain more features, replace SQLite, or move jobs
to workers. It does not currently have load or team boundaries that justify distributed
services.

## Decision

Retain one deployable application and introduce strict internal modules, ports, adapters,
feature registries, data contracts, repository contracts, and regression gates.

The deployment remains:

```text
one image + one application process + one persistent data volume + port 8765
```

Internal code moves toward:

```text
delivery -> application services -> ports -> infrastructure
```

Compatibility facades permit incremental migration. No feature is rewritten solely to match
the target directory structure.

## Consequences

### Positive

- Current NAS deployment stays simple.
- Refactoring can proceed in reversible stages.
- Feature ownership and account boundaries become visible.
- Data, database, LLM, and job adapters can be replaced later.
- A measured hotspot can be extracted without first untangling business logic.

### Costs

- The transition temporarily contains old and new entrypoints.
- Boundary tests and registries require ongoing maintenance.
- A single process remains a capacity and fault-isolation limit until infrastructure is
  deliberately extracted.

## Rejected Alternatives

### Immediate microservices

Rejected because they add network contracts, service discovery, deployment coordination,
distributed tracing, and failure modes before load requires them.

### Full framework rewrite

Rejected because replacing the HTTP and frontend frameworks while moving boundaries would
combine structural and behavioral risk.

### Continue patching flat modules

Rejected because current file size, direct provider creation, global page state, and CSS
override layers already make regressions difficult to isolate.

## Revisit Conditions

Reconsider service extraction when one module has independently measured scaling needs,
requires a separate availability boundary, or needs an independent release lifecycle.
