Domain model¶
The domain describes a build without depending on FastAPI, Typer, SQLAlchemy, Git, or Docker. Its types are the shared contract used by the API, CLI, dashboard, and adapters.
classDiagram
class Build {
id
status
modules
created_at
expires_at
host_port
preview_url
version
}
class RepositoryRevision {
name
requested_ref
commit_sha
checkout_path
addons_priority
}
class StageResult {
name
status
duration_seconds
exit_code
log_path
summary
}
Build "1" *-- "1..10" RepositoryRevision
Build "1" *-- "0..*" StageResult
Entities¶
| Entity | Responsibility |
|---|---|
Build |
Identity, lifecycle, timings, isolated resources, modules, revisions, and results. |
RepositoryRevision |
Allowed alias, requested ref, resolved SHA, checkout, and addon priority. |
StageResult |
Immutable stage result with timing, exit code, log, and summary. |
CleanupResult |
Builds examined, destroyed, and failed during cleanup or recovery. |
PurgeResult |
Audits and workspaces examined, purged, and failed during retention. |
Build.version provides optimistic locking: an update succeeds only when the stored version
matches the version read by the process.
States and transitions¶
stateDiagram-v2
[*] --> NEW
NEW --> CHECKING_OUT
CHECKING_OUT --> PREPARING
PREPARING --> INSTALLING
INSTALLING --> TESTING
TESTING --> STARTING
STARTING --> RUNNING
RUNNING --> EXPIRED
EXPIRED --> DESTROYING
DESTROYING --> DESTROYED
DESTROYED --> DESTROYED: idempotent destruction
NEW, execution states, and RUNNING may transition to FAILED. Every state except DESTROYING
and DESTROYED may transition to DESTROYING. A transition outside these rules raises
InvalidTransitionError.
Stage results use PENDING, RUNNING, SUCCESS, FAILED, and SKIPPED. The current pipeline
mainly persists final SUCCESS or FAILED results; the other values leave room for future
evolution.
Boundary validation¶
| Input | Main rule |
|---|---|
| Alias | Starts with a lowercase letter; only lowercase letters, digits, _, and -. |
| Git ref | At most 200 characters; rejects .., //, @{, \, controls, and unsafe prefixes. |
| Module | Lowercase letters, digits, and _; at most 128 characters and no duplicates. |
| Repositories | Between 1 and 10, with no duplicate aliases. |
| Modules | Between 1 and 100. |
| TTL | Between 300 and 604,800 seconds. |
Pydantic rejects extra fields. The legacy repository + ref selection remains supported, but it
cannot be mixed with repositories.
Domain errors¶
All controlled errors derive from MiniRunbotError. Categories distinguish missing resources,
invalid transitions, concurrency conflicts, unsafe paths, configuration, Git, and runtime errors.
RuntimeOperationError can carry an exit_code and log_path; the manager copies them into the
failed result without exposing arbitrary paths to clients.