Architecture - HULKs/labello GitHub Wiki
Architecture
Labello separates pure workflow policy, filesystem transactions, HTTP access, and UI state. Runtime procedures are in operations.
Dependency direction
Internal dependencies are intentionally acyclic:
| Crate | Internal dependencies |
|---|---|
labello-domain |
None |
labello-storage |
labello-domain |
labello-inference |
labello-domain |
labello-client |
labello-domain; labello-inference on WASM |
labello-api |
labello-client, labello-domain, labello-storage |
labello-ui |
labello-client, labello-domain |
labello-server |
labello-api, labello-domain, labello-storage, labello-inference |
labello-wasm |
labello-domain, labello-ui |
Domain code cannot depend on HTTP, filesystems, browser APIs, or UI types. Storage cannot depend on client or API transport types. The executable apps compose existing crates rather than own workflow policy.
Domain
labello-domain owns shared identifiers, persisted event/state shapes, pure
validation, replay, and workflow transition policy.
state/exhaustively replays the event log intoImageState.task/,review/, andmigration/own pure transition and digest policy.- versioned wire types and upcasting remain separate from current in-memory models.
Domain policy answers whether a transition is valid and what it means. It does not authorize an HTTP actor, acquire a lock, or write an event.
Storage
DatasetRepository is the filesystem capability facade used by API and
storage workflows. repository/ owns layout, validated paths, config/index
I/O, event append/load, replayed caches, snapshots, artifact migration, locks,
and cache lifecycle. Repository clones share one process-local parsed image
index; save_images_index serializes durable publication with replacement of
that cached value.
Assignment modules own storage transaction policy:
load and authorize
-> acquire the per-image process-local lock
-> reload exact current state
-> validate and simulate the complete event batch
-> append events
-> replay/update the rebuildable cache
-> invalidate derived caches
review_history owns the shared process-local previous-review projection,
bounded initialization, sequence-aware observations, and reviewer/task commit
guards. Assignment transactions and offline synchronization publish observations
at the durable event boundary. Image-index membership changes invalidate the projection;
explicit repair invalidates the projection. The assignment reopening transaction
uses this projection only for the cross-image latest-review check and validates
the target image exactly.
Per-image events.jsonl remains authoritative. state.json and statistics are
derived caches. The complete on-disk authority, compatibility, and repair
contract is documented in persistence.md.
ImportService is the import capability facade. Its modules separately own
job limits and recovery, source registration/sealing, profile parsing,
intermediate representation, semantic validation, planning, build,
verification, no-replace publication, and durable API control records. See
the dataset import documentation.
Client and API
LabelloApi remains a closed compatibility facade assembled from capability
traits. DTOs, HTTP implementations, and demo implementations are grouped by
dataset/import, workflow, administration, and authentication capabilities.
Transport DTOs do not become storage or domain policy types.
The API owns the external trust boundary:
- route and body-limit assembly;
- session, CSRF, CORS, OAuth, and dataset-role authorization;
- validation and conversion of untrusted transport inputs;
- orchestration of domain policy and storage transactions;
- safe response and error mapping.
API import handlers do not perform raw durable control-file I/O. They use the
storage-owned import control store through ImportService.
The deployment-readiness handler is a narrow API trust boundary. It reports the compiled release identity and performs non-mutating dataset-root and authentication-store probes. It does not own deployment, backup, rollback, or service-control policy.
The maintained route, authorization, transport, error, and compatibility
reference is api.md.
Release and deployment tooling
tools/labello-deploy is an operational Rust tool outside the product crate
dependency chain. It owns the guest-level deployment transaction, including
the host lock, durable journal, release and configuration generations, full
data backup, readiness admission, rollback, and boot recovery. Product storage
does not call it, and it does not reach into storage-private artifacts. It
treats the complete configured datasetsRoot as one opaque backup unit.
The release and deploy workflows package and attest artifacts, then call the
tool through the read-only verify-release command and the transactional
receive and status commands. They do not reproduce its release-inventory or
mutation policy. Systemd user services and Caddy are adapters at the process
and network boundaries. See deployment.md.
UI
LabelloApp is the egui composition root. It owns explicit runtime, auth,
dataset, admin, import, and work state; it does not dereference implicitly to
workflow state.
Closed UiCommand and UiMessage enums form the async boundary. Request IDs,
epochs, stale-response rejection, rollback, and assignment-reservation release
are centralized before feature reducers run. Rendering, canvas mechanics, and
browser persistence are separated by their existing behavior boundaries.
Browser persistence is a recoverable convenience cache and never authoritative
workflow state. See ui-ownership.md.
Public facades
The following facades are intentional:
DatasetRepository: required across storage workflows and by the API;ImportService: required by import routes and startup recovery;LabelloApi: required by UI runtime substitution and HTTP/demo clients;- crate-root domain/client/storage exports: established public paths covered by contract tests.
Remove a facade only when repository-wide caller search, downstream API review, and contract tests show it has no compatibility purpose. Do not add parallel generic repository, dependency-injection, event-bus, reducer-registry, workflow-engine, or client-side domain-model frameworks without a separately demonstrated need.
Detailed ownership references
Prelabel execution
labello-inference owns image preprocessing, the supported YOLO tensor contract,
shared decoding and native ONNX execution. labello-storage::prelabel owns
managed acquisition, durable derived results, runs, signing and reset generations
through an injected runner. The server app provides the bounded child-process
runner; API maintenance prepares work from each workflow's administrator-selected
configuration. Unseen work refreshes under that configuration while displayed and
started work keeps its captured hints and provenance.
The browser consumes prepared work items and submits accepted suggestions; it has no inference worker, model delivery or personal configuration. Pure IoU policy stays in the domain. API acceptance verifies signed evidence before the assignment transaction commits provenance. Historical browser-reported evidence remains readable without being treated as server execution.