175 lines
5.4 KiB
Markdown
175 lines
5.4 KiB
Markdown
# MinerOps Repair Domain Model
|
|
|
|
## Purpose
|
|
This design guide describes repair-domain concepts, relationships, lifecycle, invariants, and operational boundaries. Implemented repository behavior and approved task specifications remain authoritative.
|
|
|
|
## Core Concepts
|
|
|
|
### Miner
|
|
A durable physical mining asset whose identity is independent of IP address, MAC address, control board, hostname, location, and repair state.
|
|
|
|
### Repair
|
|
A bounded operational episode for one miner. It has one start, zero or one completion, immutable timeline events, actors, and timestamps.
|
|
|
|
### Repair Event
|
|
An immutable fact ordered by explicit sequence. Implemented event types are
|
|
`REPAIR_STARTED`, `INITIAL_NOTE`, and `REPAIR_COMPLETED`.
|
|
|
|
### Network Identity History
|
|
`miner_network_identities` associates MAC, IP, and hostname observations with a
|
|
durable miner and identifies current versus historical rows. It is not a
|
|
separate asset identity.
|
|
|
|
### Proposed Component History
|
|
Task 004 proposes preserving control-board replacement details without
|
|
redefining the miner. No dedicated immutable component-history table currently
|
|
exists; the legacy generic maintenance-event table is not the modular repair
|
|
timeline.
|
|
|
|
### Proposed Repair Part Entry
|
|
Task 005 proposes a record of a part installed, removed, or consumed during a
|
|
repair. It is not a warehouse inventory transaction, and no `repair_parts`
|
|
table currently exists.
|
|
|
|
## Relationships
|
|
Current relationships:
|
|
|
|
```text
|
|
Miner -> many Repairs -> ordered Repair Events
|
|
Miner -> Network Identity History
|
|
```
|
|
|
|
Control-board replacement history and repair-part entries are proposed
|
|
extensions, not implemented relationships.
|
|
|
|
## Lifecycle
|
|
|
|
Current miner states relevant to repair:
|
|
- `active`
|
|
- `spare`
|
|
- `in_repair`
|
|
- `retired`
|
|
|
|
Eligible Begin Repair sources:
|
|
- active
|
|
- spare
|
|
|
|
Eligible Return to Service destinations:
|
|
- active
|
|
- spare
|
|
|
|
Terminal:
|
|
- retired
|
|
|
|
The repair schema defines these statuses:
|
|
|
|
- Active: `OPEN`, `IN_PROGRESS`, `WAITING_FOR_PARTS`, `READY_FOR_TEST`
|
|
- Terminal: `COMPLETED`, `CANCELLED`
|
|
|
|
The modular API currently creates repairs as `OPEN` and can complete any active
|
|
repair. It does not provide status-transition or cancellation routes. The
|
|
implemented modular workflow is therefore:
|
|
|
|
```text
|
|
OPEN -> COMPLETED
|
|
```
|
|
|
|
The other active values remain valid schema states for compatibility and later
|
|
explicit workflows. Cancellation or abandonment requires a separate task.
|
|
|
|
## Current Workflow
|
|
```text
|
|
Miner active/spare
|
|
-> Begin Repair
|
|
-> Miner in_repair
|
|
-> Timeline events
|
|
-> Return to Service
|
|
-> Miner active/spare
|
|
-> Repair completed
|
|
```
|
|
|
|
## Invariants
|
|
- replacing a board or MAC must not create a new miner
|
|
- asset-ID and network-identity history must be preserved
|
|
- no more than one active repair per miner is database-enforced
|
|
- modular repair actions require the miner and repair state to agree
|
|
- Return to Service prevents a completed repair from leaving the miner in `in_repair`
|
|
- multi-record transitions are atomic
|
|
- events are append-only and explicitly sequenced
|
|
- actor comes from authentication
|
|
- timestamps are server/database controlled
|
|
- new completions require completion time, actor, and eligible resulting lifecycle
|
|
- legacy unknown values remain unknown rather than fabricated
|
|
|
|
## Transaction Boundaries
|
|
|
|
### Begin Repair
|
|
Lock miner, create repair, transition miner to `in_repair`, append start event.
|
|
|
|
### Return to Service
|
|
Lock miner, lock repair, validate active state, complete repair, transition miner to active/spare, append completion event.
|
|
|
|
### Proposed Control Board Replacement
|
|
Task 004 proposes locking miner, active repair, and network-identity rows;
|
|
validating MAC ownership; updating current projections; and appending one event.
|
|
|
|
### Proposed Repair Part Recording
|
|
Task 005 proposes locking the affected repair or repair-part row, adding or
|
|
voiding the entry, and appending the corresponding event atomically.
|
|
|
|
## Lock Order
|
|
Use:
|
|
```text
|
|
Miner -> Repair -> related rows
|
|
```
|
|
|
|
This aligns workflows and reduces deadlock risk.
|
|
|
|
## Commands vs CRUD
|
|
Implemented explicit commands:
|
|
|
|
- Begin Repair
|
|
- Return to Service
|
|
|
|
Proposed explicit commands:
|
|
|
|
- Replace Control Board
|
|
- Record Repair Part
|
|
- Void Repair Part
|
|
|
|
Avoid generic repair patches for meaningful operations.
|
|
|
|
## Read Models
|
|
Implemented modular reads:
|
|
|
|
- repair detail
|
|
- ordered repair timeline
|
|
|
|
The integrated application also has legacy repair-queue, parts-summary, and
|
|
miner network-identity reads. Those routes are compatibility behavior, not the
|
|
proposed Task 004 or Task 005 read models.
|
|
|
|
Proposed focused reads include repair parts and control-board replacement
|
|
history. Read models do not weaken write invariants.
|
|
|
|
## Permissions
|
|
Implemented permissions:
|
|
|
|
- `repairs.read`
|
|
- `repairs.create`
|
|
- `repairs.complete`
|
|
|
|
Proposed permissions:
|
|
|
|
- `repairs.parts.manage`
|
|
- `miners.replace_control_board`
|
|
|
|
Task 005 reuses `repairs.read` for its proposed read route. Roles receive capabilities;
|
|
endpoints should not hard-code role names when permission checks exist.
|
|
|
|
## Legacy Data
|
|
Preserve truth, allow nullable historical fields where necessary, enforce stronger rules for new or updated rows, use PostgreSQL `NOT VALID` constraints where appropriate, and never backfill invented actors, states, or events.
|
|
|
|
## Future Extensions
|
|
Repair cancellation, diagnosis, work orders, technician assignment, burn-in testing, photos, warranty/RMA, component inventory, and donor-unit tracking should each arrive through explicit tasks.
|