daemon split (5/5): document the service composition

Phase 5 of the daemon god-struct refactor. Code motion landed in
phases 1-4; this commit retells the architecture so the docs match
the structure.

ARCHITECTURE.md loses the "deferred v0.2 project" hedge about
splitting services. The Composition section now describes the four
services (HostNetwork, ImageService, WorkspaceService, VMService)
that own behaviour, the consumer-defined seam pattern for
cross-service calls, and the lazy-init getter pattern that keeps
existing test literals compiling.

doc.go inventories which methods live on which service, and the
lock-ordering section gains the service prefixes (e.g.
VMService.vmLocks instead of bare vmLocks) so readers don't have to
guess which type owns which mutex.

No code changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-20 20:58:53 -03:00
parent 466a7c30c4
commit 0cfd8a5451
No known key found for this signature in database
GPG key ID: 33112E6833C34679
2 changed files with 180 additions and 131 deletions

View file

@ -1,76 +1,74 @@
// Package daemon hosts the Banger daemon process.
//
// The daemon exposes a JSON-RPC endpoint over a Unix socket. It owns VM
// lifecycle, image management, host networking bootstrap, and state
// persistence via internal/store.
// The daemon exposes a JSON-RPC endpoint over a Unix socket. The
// *Daemon type is a thin composition root: it holds shared
// infrastructure (store, runner, logger, layout, config, listener)
// plus pointers to four focused services and forwards RPCs to them.
//
// The package is organised into cohesive groups. Pure stateless helpers for
// each group have been lifted into subpackages; orchestrator methods
// (Daemon receivers) stay here and compose them.
// Services:
//
// Subpackages:
// *HostNetwork Bridge / tap pool / NAT / DNS / firecracker
// process / DM snapshots / vsock readiness.
// Owns tapPool and vmDNS.
// *ImageService Register / promote / delete / pull (bundle +
// OCI) / kernel catalog / managed-seed refresh.
// Owns imageOpsMu.
// *WorkspaceService workspace.prepare / workspace.export + the
// per-VM authorised-key and git-identity sync
// that runs at start. Owns workspaceLocks.
// *VMService VM lifecycle (create/start/stop/restart/kill/
// delete/set), stats, ports, preflight. Owns
// vmLocks, createVMMu, createOps, handles.
//
// internal/daemon/opstate Generic Registry[T AsyncOp] for async
// operations (VM create).
// Subpackages (stateless helpers):
//
// internal/daemon/opstate Generic Registry[T AsyncOp].
// internal/daemon/dmsnap Device-mapper COW snapshot lifecycle.
// internal/daemon/fcproc Firecracker process helpers: bridge/tap,
// binary resolution, PID lookup, wait/kill.
// internal/daemon/imagemgr Image subsystem helpers: path validation,
// artifact staging, guest provisioning script
// generator, metadata.
// internal/daemon/workspace Workspace helpers: git repo inspection,
// shallow copy prep, guest-side import,
// finalize script generation, shell quoting.
// internal/daemon/fcproc Firecracker process helpers.
// internal/daemon/imagemgr Image subsystem helpers.
// internal/daemon/workspace Workspace helpers.
//
// VM lifecycle (in this package):
// File inventory:
//
// vm_create.go CreateVM and create-time disk provisioning
// vm_lifecycle.go Start/Stop/Restart/Kill/Delete
// vm_set.go SetVM mutation
// vm_stats.go stats, health, ping, stale reaper
// vm_disk.go system overlay, work disk provisioning
// vm_authsync.go per-VM authorized_key, git identity, auth file sync
// vm_create_ops.go async begin/status/cancel (uses opstate.Registry)
// vm_locks.go vmLockSet: per-VM mutex set
// vm.go fcproc forwarders, DNS helpers, small utilities
// capabilities.go pluggable capability hooks executed at VM start
// preflight.go prereq validation for VM start
// snapshot.go dmsnap forwarders + dmSnapshotHandles type alias
// ports.go port forwarding inspection
// daemon.go Composition root, Open/Close/Serve, dispatch,
// reconcile orchestrator, backgroundLoop.
// host_network.go HostNetwork struct + constructor.
// image_service.go ImageService struct + constructor + FindImage.
// workspace_service.go WorkspaceService struct + constructor.
// vm_service.go VMService struct + constructor + FindVM,
// TouchVM, withVMLock* family, lockVMID.
//
// Image management (in this package):
// nat.go, dns_routing.go, tap_pool.go, snapshot.go HostNetwork methods.
// images.go, images_pull.go, image_seed.go, kernels.go ImageService methods.
// workspace.go, vm_authsync.go WorkspaceService methods.
// vm_lifecycle.go, vm_create.go, vm_create_ops.go,
// vm_stats.go, vm_set.go, vm_disk.go, vm_handles.go,
// ports.go, preflight.go VMService methods.
//
// images.go register, promote, delete, find, list
// images_pull.go image pull: catalog (bundle) + OCI paths
// image_seed.go managed work-seed SSH fingerprint refresh
//
// Guest interaction (in this package):
//
// guest_ssh.go guestSSHClient, dialGuest, waitForGuestSSH
// ssh_client_config.go daemon-managed SSH client key material
// workspace.go ExportVMWorkspace, PrepareVMWorkspace
//
// Host bootstrap (in this package):
//
// nat.go NAT prereq registration
// dns_routing.go systemd-resolved per-interface routing
// tap_pool.go TAP interface pool (state in tapPool type)
//
// Core (in this package):
//
// daemon.go Daemon struct, Open/Close/Serve, dispatch
// doctor.go host diagnostics
// logger.go slog configuration
// runtime_assets.go paths to bundled companion binaries
// vm.go Cross-service constants, rebuildDNS /
// cleanupRuntime / generateName (*VMService),
// and small stateless utilities.
// capabilities.go Pluggable capability hooks executed at VM
// start. Hook methods take *Daemon; VMService
// reaches them through a capabilityHooks seam.
// vm_locks.go vmLockSet primitive.
// guest_ssh.go guestSSHClient, dialGuest, waitForGuestSSH.
// ssh_client_config.go Daemon-managed SSH client key material.
// doctor.go Host diagnostics.
// logger.go slog configuration.
// runtime_assets.go Companion-binary paths.
//
// Lock ordering:
//
// vmLocks[id] → workspaceLocks[id] → {createVMMu, imageOpsMu} → subsystem-local locks
// VMService.vmLocks[id] → WorkspaceService.workspaceLocks[id]
// → {VMService.createVMMu, ImageService.imageOpsMu}
// → subsystem-local locks
//
// vmLocks[id] is held across entire lifecycle ops (start/stop/delete/set),
// not just a validation window — callers that want to avoid blocking
// lifecycle on slow guest I/O must explicitly split off to
// workspaceLocks[id] the way workspace.prepare does. Subsystem-local
// locks (tapPool.mu, opstate.Registry mu) are leaves and do not contend
// with each other. See ARCHITECTURE.md for details.
// vmLocks[id] and workspaceLocks[id] are NEVER held at the same
// time. workspace.prepare acquires vmLocks[id] only long enough to
// validate VM state, releases it, then acquires workspaceLocks[id]
// for the slow guest I/O phase. Lifecycle ops (start/stop/delete/
// set) hold vmLocks[id] across the whole flow. Subsystem-local
// locks (tapPool.mu, opstate.Registry mu, handleCache.mu) are
// leaves. See ARCHITECTURE.md for details.
package daemon