docs: add repair domain design documents
This commit is contained in:
1 parent
f2b736b08e
commit
62c91a2c3e
4 files changed
+778
No files matched your search
@@ -0,0 +1,156 @@
|
||||
# MinerOps API Style Guide
|
||||
|
||||
## Purpose
|
||||
Keep MinerOps APIs explicit, consistent, auditable, and aligned with the domain architecture. Implemented conventions and approved task specifications take precedence.
|
||||
|
||||
## Principles
|
||||
1. Prefer domain commands over generic CRUD.
|
||||
2. Use nouns for resources and explicit action routes for operational commands.
|
||||
3. Keep writes focused and atomic.
|
||||
4. Return truthful domain representations.
|
||||
5. Separate authentication, permission, validation, domain logic, and persistence.
|
||||
6. Preserve static-route compatibility.
|
||||
7. Do not expose database structure as the public API.
|
||||
|
||||
## Current and Proposed Examples
|
||||
Implemented modular repair routes:
|
||||
|
||||
```http
|
||||
POST /api/repairs
|
||||
GET /api/repairs/{repair_id}
|
||||
GET /api/repairs/{repair_id}/events
|
||||
POST /api/repairs/{repair_id}/complete
|
||||
```
|
||||
|
||||
Relevant legacy compatibility routes include:
|
||||
|
||||
```http
|
||||
GET /api/repairs/queue
|
||||
GET /api/repairs/parts-summary
|
||||
POST /api/miners/{miner_id}/change-mac
|
||||
```
|
||||
|
||||
These integrated routes predate the modular domain conventions and are not
|
||||
models for new code.
|
||||
|
||||
Proposed by Task 004, not implemented:
|
||||
|
||||
```http
|
||||
POST /api/miners/{miner_id}/replace-control-board
|
||||
```
|
||||
|
||||
Good:
|
||||
```http
|
||||
POST /api/repairs/{repair_id}/complete
|
||||
```
|
||||
|
||||
Avoid:
|
||||
```http
|
||||
PATCH /api/repairs/{repair_id}
|
||||
{"status":"completed"}
|
||||
```
|
||||
|
||||
## Methods
|
||||
- GET is read-only.
|
||||
- POST creates a resource or invokes an explicit command.
|
||||
- PATCH is limited to non-operational metadata when partial update semantics are
|
||||
appropriate.
|
||||
- Meaningful operational changes use explicit commands rather than generic PUT,
|
||||
PATCH, or DELETE routes.
|
||||
- Historical records are corrected with explicit append-only or void workflows,
|
||||
not physical deletion.
|
||||
|
||||
## Status Codes
|
||||
- 200: successful read or command with response
|
||||
- 201: created resource
|
||||
- 204: success with no useful response
|
||||
- 401: unauthenticated
|
||||
- 403: lacks permission
|
||||
- 404: resource missing
|
||||
- 409: valid request conflicts with domain state
|
||||
- 422: request validation failure
|
||||
|
||||
## Identifiers
|
||||
Use typed UUIDs for authoritative entity identifiers. Do not expose sequential database IDs as public identity.
|
||||
|
||||
## Time and Actors
|
||||
Use timezone-aware ISO 8601 timestamps. Authoritative timestamps and actor IDs are server controlled. Never accept client-supplied event actor, event timestamp, completion timestamp, or sequence.
|
||||
|
||||
## Permissions
|
||||
Implemented modular repair capabilities are:
|
||||
|
||||
- `repairs.read`
|
||||
- `repairs.create`
|
||||
- `repairs.complete`
|
||||
|
||||
Task 004 proposes `miners.replace_control_board`; it is not registered today.
|
||||
Do not duplicate role logic in routers.
|
||||
|
||||
## Request Models
|
||||
Use constrained types, normalize whitespace, reject unknown values, enforce length limits, avoid persistence-only fields, and never accept arbitrary client event payloads.
|
||||
|
||||
## Response Models
|
||||
The modular Inventory and Repairs APIs use typed success envelopes containing
|
||||
`data`, `meta`, and `error`. Expose useful domain state, not secrets or unrelated
|
||||
nested data. Preserve null when historical truth is unknown.
|
||||
|
||||
## Errors
|
||||
The application does not yet have one uniform typed error envelope. Modular
|
||||
routes currently use FastAPI validation responses and `HTTPException` detail
|
||||
responses while translating domain exceptions to 404, 409, or 422 as
|
||||
appropriate. New routes must follow the established behavior of their domain
|
||||
and must not leak SQL or driver errors. Repositories do not raise HTTP
|
||||
exceptions. Services do not import FastAPI.
|
||||
|
||||
## Pagination
|
||||
Potentially large collections require a bounded pagination design. The current
|
||||
Inventory collection uses bounded `limit` and `offset`; do not claim cursor
|
||||
pagination until a domain adopts it. The implemented repair timeline returns
|
||||
all events for one repair by explicit Task 002 design. Any later change to that
|
||||
contract requires compatibility review.
|
||||
|
||||
## Filtering
|
||||
Use explicit allowlisted filters and sort fields. Never pass arbitrary column names into queries.
|
||||
|
||||
## Static Routes
|
||||
Register static routes before overlapping UUID routes:
|
||||
```text
|
||||
/api/repairs/queue
|
||||
/api/repairs/parts-summary
|
||||
/api/repairs/{repair_id}
|
||||
```
|
||||
Add route-precedence tests.
|
||||
|
||||
## Idempotency and Concurrency
|
||||
Use database invariants, row locks, affected-row checks, and narrow operation
|
||||
identifiers where demonstrated need exists. Do not add a generalized
|
||||
idempotency platform speculatively.
|
||||
|
||||
The implemented repair workflows prevent duplicate active repairs, duplicate
|
||||
completion, duplicate event sequences, and partial state. Task 004 proposes the
|
||||
additional invariant that concurrent requests cannot assign one normalized MAC
|
||||
to two miners.
|
||||
|
||||
## Events
|
||||
Clients request domain actions, not raw events. The service constructs immutable events.
|
||||
|
||||
## Versioning
|
||||
MinerOps does not currently expose versioned API prefixes. Any incompatible API
|
||||
versioning scheme requires a separate compatibility decision; this guide does
|
||||
not reserve a future path.
|
||||
|
||||
## Route Specification Checklist
|
||||
Every new route should define:
|
||||
- method and path
|
||||
- authentication and permission
|
||||
- request and response
|
||||
- status codes
|
||||
- domain rules
|
||||
- transaction boundary
|
||||
- concurrency behavior
|
||||
- events
|
||||
- tests
|
||||
- out-of-scope items
|
||||
|
||||
## Review Checklist
|
||||
Confirm explicit action choice, status codes, permission, actor and timestamp authority, UUID typing, limits, transaction, concurrency, event construction, route precedence, architecture boundaries, and regressions.
|
||||
@@ -0,0 +1,174 @@
|
||||
# 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.
|
||||
Reference in new issue
Block a user