Files
werkator/docs/adrs/0009-2026-09-01.multi-repo-instance.md
mhoennigandClaude Fable 5 ff3aa61eca ADR 0009: one Werkator instance serves a set of repositories
Records the tenet revision and its shape: instance registry and
instance keys in ~/.werkator.yml (one instance per OS user), optional
repo defaults in an explicit defaults: block merged below every repo's
own layers, repo config unchanged in each repository, registry-wins
precedence, basename repo names. Rejected: a federation dashboard over
single-repo instances (keeps N services), and the status quo.
Konzept/AGENTS architecture wording changes only when the
implementation lands; the decision list carries 0009 now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 14:15:15 +02:00

61 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# One Werkator Instance Serves a Set of Repositories
**Status:**
- proposed: 2026-09-01
- accepted: 2026-09-01
- rejected: -
- superseded: -
**Decision [accepted]:** The founding tenet "one instance per repository" is revised to "one instance per repository *set*": a Werkator instance aggregates self-contained repositories listed in an instance registry, sharing one service, one port, one UI, one watcher schedule, and one global executor cap.
Implementation is planned as `docs/plan/22-multi-repo.md`; this ADR records the decision and its shape, not the code.
## Context and Problem Statement
"One instance per repository" (docs/Werkator-Konzept.md) does not scale even to two repositories on a Hostsharing Managed Webspace: building Werkbaum next to Werkator on mih34 would need a second service, a second assigned port, a second tunnel or domain, a second UI and metrics page.
Every repository multiplies operations while the instance-level resources could be shared.
### Technical Background
Everything repository-specific already lives inside the repository or is keyed by it: machine config with secrets, build results, auto-build slots, worktrees, and buildenvs under `.git/werkator/`; the artifact store under a per-repo key.
An instance can therefore aggregate repositories without absorbing their state — adding or removing a repository is a registry entry, never a data migration, and single-repo mode stays the degenerate case (a registry of one, implicitly the current working directory).
## Considered Options
* One instance per repository set (registry + aggregation) — chosen
* A federation dashboard proxying several single-repo instances
* Status quo: one instance, one repository
### One Instance per Repository Set
Good:
- One service, port, UI, tunnel/domain, metrics page for any number of repositories.
- Repositories stay self-contained; per-repo secrets, history, and pinning semantics are untouched.
- Global concurrency control across all repositories.
Bad:
- The repo dimension must be threaded through executor pools, watcher cycle, routes, and UI — the largest refactor since the rewrite (mitigated by a behavior-preserving `RepoContext` session first).
- Instance-level and repo-level configuration must be split cleanly (see below).
### Federation Dashboard over Single-Repo Instances
Rejected: less invasive, but it keeps N services, N ports, and N tunnels — it solves only the UI aggregation, not the operations burden that motivated the change.
### Status Quo
Rejected: on a webspace, ports and domains are the scarce, manually assigned resource; per-repository services do not scale there.
## Decision Outcome
One instance per repository set, with the configuration split decided 2026-09-01:
- **Instance config** lives in `~/.werkator.yml` in the home directory of the user running the instance — one instance per OS user, matching the platform model. It carries `server.*` (port, domain/public base URL, nginx), the repository registry, the control token, the global `executor.maxConcurrent`, and the watcher schedule. The file name stays `.werkator.yml` in all three locations; the location carries the meaning.
- **Repo defaults** may live in the home file, but only in an explicit `defaults:` block, merged *below* every repository's own layers (home defaults → committed project config → repo machine config → branch layer); pinning semantics are unchanged. Accepted cost: secrets may then live in two places.
- **Repo config** stays in each repository: the committed `.werkator.yml` and the machine config in its `.git/werkator/`.
- Instance keys found in a repo's machine config are ignored with a warning naming both files once a home config exists — never merged silently.
- When a home config with a registry exists, `werkator server` serves the registry regardless of the current directory; without one it serves the current directory exactly as before.
- Repository names (routes, UI) default to the directory basename, are overridable per registry entry, and duplicates abort the start loudly.
Consequences: `docs/Werkator-Konzept.md` and AGENTS.md change their wording when the implementation lands (plan step 22 sessions BD); until then this ADR documents the target and the existing behavior remains accurate.