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,189 @@
|
||||
# Task 005: Repair Parts Tracking
|
||||
|
||||
## Status
|
||||
Design specification. Not yet implemented.
|
||||
|
||||
## Objective
|
||||
Allow authorized operators to record parts installed, removed, or consumed
|
||||
during a repair while preserving immutable history and leaving room for a later
|
||||
spare-parts inventory system.
|
||||
|
||||
## Product Intent
|
||||
A technician should be able to determine what parts were installed, removed, or
|
||||
consumed; their quantity and identifying serial number where relevant; any
|
||||
concise notes; and the authoritative actor and timestamp.
|
||||
|
||||
## Scope
|
||||
- proposed focused repair-part read and action APIs
|
||||
- proposed capability-based permissions
|
||||
- a deliberately small part type and action vocabulary
|
||||
- part type, action, quantity, optional serial number, and notes
|
||||
- serialized component identifiers where applicable
|
||||
- explicit void/correction rather than physical deletion
|
||||
- immutable repair events
|
||||
- migration, constraints, tests, and documentation
|
||||
|
||||
## Out of Scope
|
||||
Purchasing, suppliers, pricing, invoices, warehouse transfers, reorder automation, warranties, RMA, full inventory, generalized bill of materials, bulk import, automatic stock deduction, photos, work orders, and control-board identity replacement.
|
||||
|
||||
Task 004 remains authoritative for control-board identity and MAC changes.
|
||||
Task 005 must not accept `control_board` as a generic part type or update
|
||||
`miners.control_board_sn`, `miners.current_mac`, or
|
||||
`miner_network_identities`.
|
||||
|
||||
## API
|
||||
Proposed routes:
|
||||
|
||||
```http
|
||||
GET /api/repairs/{repair_id}/parts
|
||||
POST /api/repairs/{repair_id}/parts
|
||||
POST /api/repairs/{repair_id}/parts/{repair_part_id}/void
|
||||
```
|
||||
|
||||
Do not physically delete authoritative entries.
|
||||
|
||||
## Permissions
|
||||
The proposed authorization model is:
|
||||
|
||||
- use implemented `repairs.read` for the read route
|
||||
- introduce `repairs.parts.manage` for add and void actions
|
||||
|
||||
Grant the proposed write permission to Admin, Manager, and Technician. Do not
|
||||
grant it to Read Only. `repairs.parts.manage` does not exist yet and must be
|
||||
introduced by the Task 005 migration. The router checks capabilities rather than
|
||||
role names.
|
||||
|
||||
## Add Request
|
||||
```json
|
||||
{
|
||||
"part_type": "fan",
|
||||
"action": "installed",
|
||||
"quantity": 1,
|
||||
"serial_number": null,
|
||||
"notes": "Replacement fan installed."
|
||||
}
|
||||
```
|
||||
|
||||
## Initial Vocabulary
|
||||
Proposed part types:
|
||||
|
||||
- `fan`
|
||||
- `power_supply`
|
||||
- `hashboard`
|
||||
- `cable`
|
||||
- `consumable`
|
||||
- `other`
|
||||
|
||||
Proposed actions:
|
||||
|
||||
- `installed`
|
||||
- `removed`
|
||||
- `consumed`
|
||||
|
||||
Task 005 does not model source inventory, stock movement, return destination,
|
||||
condition, or disposition. Those concepts require a later inventory decision
|
||||
and must not be approximated with overlapping action/value combinations here.
|
||||
Use notes for concise context that is not authoritative structured inventory
|
||||
data.
|
||||
|
||||
## Quantity Rules
|
||||
- quantity greater than zero
|
||||
- integer quantities for this task
|
||||
- serialized components normally quantity 1
|
||||
- consumables may exceed 1
|
||||
- voiding does not create a negative entry or reverse inventory; it marks the
|
||||
original record void
|
||||
|
||||
## Repair State Rules
|
||||
- add entries only while the repair is active
|
||||
- void entries only while the repair is active
|
||||
- read entries and void state after completion
|
||||
- completed repairs remain read-only
|
||||
- no unrestricted editing in any repair state
|
||||
|
||||
## Data Model
|
||||
Proposed table: `repair_parts`. No such table currently exists. The legacy
|
||||
`/api/repairs/parts-summary` route summarizes generic maintenance-event data and
|
||||
is not an implementation of this model.
|
||||
|
||||
Potential fields:
|
||||
- UUID
|
||||
- repair UUID
|
||||
- part type
|
||||
- action
|
||||
- quantity
|
||||
- serial number
|
||||
- notes
|
||||
- recorded actor and timestamp
|
||||
- void actor, timestamp, and reason
|
||||
- related event UUID
|
||||
|
||||
Entries are never physically deleted. A void changes only the one-way void
|
||||
metadata. It must not edit the original part type, action, quantity, serial
|
||||
number, notes, recording actor, or recording timestamp. The void reason is
|
||||
required; void actor and timestamp come from authentication and the server.
|
||||
|
||||
## Constraints
|
||||
- quantity > 0
|
||||
- void fields all-null or all-present
|
||||
- void timestamp after recorded timestamp
|
||||
- actor and recorded timestamp required
|
||||
- valid constrained values and combinations
|
||||
- serialized entries with a serial number have quantity 1
|
||||
|
||||
## Events
|
||||
Proposed types:
|
||||
- `REPAIR_PART_RECORDED`
|
||||
- `REPAIR_PART_VOIDED`
|
||||
|
||||
The events are immutable history; the table is the queryable projection.
|
||||
|
||||
## Atomicity
|
||||
Adding a part and appending its event occur in one transaction. Voiding and appending the void event occur in one transaction.
|
||||
|
||||
Voiding must lock the repair-part row and succeed only when its void fields are
|
||||
still null. Concurrent void requests must produce one success and one conflict,
|
||||
with exactly one `REPAIR_PART_VOIDED` event.
|
||||
|
||||
## Architecture
|
||||
Preserve `Router -> Service -> Repository -> PostgreSQL`. No generic parts CRUD, router SQL, or physical deletion.
|
||||
|
||||
## Tests
|
||||
Cover:
|
||||
- authorization
|
||||
- serialized and consumable entries
|
||||
- removed part
|
||||
- list chronology
|
||||
- read after completion
|
||||
- explicit void
|
||||
- invalid quantities and combinations
|
||||
- control-board part rejection
|
||||
- add to completed repair
|
||||
- already-voided conflict
|
||||
- cross-repair entry conflict
|
||||
- concurrent void
|
||||
- rollback on event failure
|
||||
- direct constraints
|
||||
- Tasks 001-004 regressions
|
||||
- migration lifecycle and full backend suite
|
||||
|
||||
## Migration
|
||||
Create the focused table, add permissions and event constraints, add justified indexes, preserve legacy truth, and refuse destructive downgrade when authoritative Task 005 history exists.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Parts can be recorded against an active repair.
|
||||
2. Historical entries remain readable.
|
||||
3. Entries are never physically deleted.
|
||||
4. Voids are explicit and audited.
|
||||
5. Actor and timestamps are authoritative.
|
||||
6. Writes and events are atomic.
|
||||
7. Values and quantities are constrained.
|
||||
8. No warehouse or purchasing system is introduced.
|
||||
9. Task 004 remains authoritative for control-board identity changes.
|
||||
10. No commit or push is performed.
|
||||
|
||||
## Completion Report
|
||||
Report files, migration, routes, permissions, schema, constraints, events, tests, migration lifecycle, architecture audit, limitations, and final status.
|
||||
|
||||
Do not commit.
|
||||
Do not push.
|
||||
Reference in new issue
Block a user