refactor: establish standalone application boundary

This commit is contained in:
leefer
2026-08-03 21:42:25 +08:00
parent cc5fb8d73e
commit e1e76cd51e
324 changed files with 63090 additions and 44743 deletions
@@ -0,0 +1,75 @@
# 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.