From 011b59a72fbc7fd63bbea94228ad15b95abf48b6 Mon Sep 17 00:00:00 2001 From: Thales Maciel Date: Tue, 21 Apr 2026 15:59:39 -0300 Subject: [PATCH] daemon split (8/8): document capability decoupling + wireServices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update ARCHITECTURE.md's Composition section to reflect the finished split: capabilities carry explicit service-pointer fields, nothing reaches *Daemon at dispatch time, and wireServices(d) is the single entry point that builds services + capabilities eagerly (from Open in production, from tests after constructing &Daemon{...} literals). Removes the paragraph admitting capability→*Daemon coupling and the lazy-init getters justification, neither of which applies anymore. Co-Authored-By: Claude Opus 4.7 (1M context) --- internal/daemon/ARCHITECTURE.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/internal/daemon/ARCHITECTURE.md b/internal/daemon/ARCHITECTURE.md index 7fafabe..709ad65 100644 --- a/internal/daemon/ARCHITECTURE.md +++ b/internal/daemon/ARCHITECTURE.md @@ -41,15 +41,20 @@ consumer-defined seams: declaring a function-typed interface for every call would balloon the surface for no win — services are unexported, so package-external code can never reach them. -- Capability hooks still take `*Daemon` as their receiver argument, - but `VMService` calls into them through a `capabilityHooks` struct - (function-typed bag) populated at construction. The service has no - `*Daemon` pointer. +- Capability hooks do not take `*Daemon`. Each capability is a struct + with explicit service-pointer fields (`workDiskCapability{vm, ws, + store, defaultImageName}`, `dnsCapability{net}`, `natCapability{vm, + net, logger}`) populated at wiring time. `VMService` invokes them + through a `capabilityHooks` struct (function-typed bag) populated at + construction; neither the service nor any capability has a `*Daemon` + pointer. -Lazy-init getters (`d.hostNet()`, `d.imageSvc()`, `d.workspaceSvc()`, -`d.vmSvc()`) let existing test literals (`&Daemon{store: db, runner: r}`) -keep working — the getter constructs the service from whatever is on -the `Daemon` if nothing was pre-wired. +Services + capabilities are built eagerly by `wireServices(d)`, called +once from `Daemon.Open` after the composition root's infrastructure is +populated, and once per test that constructs a `&Daemon{...}` literal. +Tests that want to stub a particular service or the capability list +assign the field before calling `wireServices` — the helper is +idempotent and skips anything already set. ## Service state