Files
minerops/docs/tasks/002-repair-timeline.md

4.9 KiB

Task 002: Repair Timeline

Objective

Add read-only APIs for viewing one repair and its immutable timeline.

Scope

Add exactly these two endpoints:

GET /api/repairs/{repair_id}
GET /api/repairs/{repair_id}/events

Do not add any other repair endpoints.

Permissions

Add:

repairs.read

Grant it to Admin, Manager, Technician, and Read Only. Existing repairs.create access remains unchanged.

Architecture

Preserve:

Router -> Service -> Repository -> PostgreSQL

Routers contain no SQL or transaction logic. Services contain no FastAPI dependencies. Repositories contain no FastAPI imports. Reads must not modify data.

GET /api/repairs/{repair_id}

Return:

{
  "repair_id": "uuid",
  "miner_id": "uuid",
  "miner_asset_id": "string",
  "status": "OPEN",
  "reason": "INSPECTION",
  "opened_at": "timestamp",
  "opened_by": {
    "user_id": "uuid",
    "display_name": "string"
  },
  "closed_at": null,
  "closed_by": null,
  "miner_lifecycle": "in_repair",
  "latest_event_sequence": 2
}

Requirements:

  • Return 404 when the repair does not exist.
  • Return the current miner lifecycle.
  • Resolve actor identity using existing user conventions.
  • Obtain latest_event_sequence from authoritative event data.
  • Do not infer missing history or expose internal-only fields.

GET /api/repairs/{repair_id}/events

Return:

{
  "repair_id": "uuid",
  "events": [
    {
      "event_id": "uuid",
      "sequence": 1,
      "event_type": "REPAIR_STARTED",
      "actor": {
        "user_id": "uuid",
        "display_name": "string"
      },
      "occurred_at": "timestamp",
      "payload": {
        "reason": "INSPECTION",
        "from_lifecycle": "active",
        "to_lifecycle": "in_repair"
      }
    }
  ]
}

Requirements:

  • Return 404 when the repair does not exist.
  • Return all events ordered strictly by database sequence ascending.
  • Do not order only by timestamp.
  • Preserve payload as structured JSON.
  • Avoid N+1 actor lookups.

Timeline Invariants

Events are immutable. This task must not add support for editing, deleting, replacing, or reordering timeline events. Corrections must be represented by new events.

Models and Validation

  • Use UUID types for identifiers.
  • Use timezone-aware datetime types.
  • Reuse existing constrained status, reason, lifecycle, and event types where practical.
  • Represent payloads as structured JSON, not serialized strings.
  • Avoid exposing unexpected internal fields.

Repository Requirements

Add focused read methods for repair detail and ordered repair events. Queries should include miner asset ID, current lifecycle, actor display data, and latest event sequence. Do not add broad list or search methods.

Service Requirements

The service must validate existence, coordinate repository reads, map missing repairs to the domain-standard not-found exception, and contain no SQL or FastAPI dependencies.

Router Requirements

Expose exactly the two routes in this specification, require repairs.read, follow existing exception patterns, and contain no SQL, commits, or transaction management.

Migration

Create the next Alembic revision only if required to add repairs.read and role assignments. Preserve existing permissions and provide a complete downgrade. Do not alter repair tables unless a material incompatibility is found; report that conflict before deviating.

Tests

Cover at least:

  • 401 unauthenticated
  • 403 unauthorized
  • Read Only can read detail and events
  • Admin, Manager, and Technician can read
  • repairs.create behavior remains unchanged
  • existing repair detail
  • missing repair 404
  • asset ID, lifecycle, actor, nullable closed fields, and latest sequence
  • sequence ordering even when timestamps are equal or non-monotonic
  • structured JSON payload
  • actor data
  • explicit empty-timeline behavior
  • Begin Repair regression
  • Inventory regression
  • migration upgrade, downgrade, re-upgrade, and empty database through head
  • exactly two new routes
  • architecture audits

Validation

Run:

  • Python compilation
  • shell syntax validation
  • focused timeline tests
  • existing Begin Repair tests
  • inventory regression tests
  • migration validation
  • disposable development baseline
  • router SQL/driver/transaction audit
  • service/repository FastAPI audit
  • exact route-count audit
  • git diff --check

Documentation

Update docs/ROADMAP.md only after implementation and validation pass. Do not add an ADR unless a genuinely new architectural decision is required.

Explicitly Out of Scope

Do not implement repair listing, search, pagination, adding or editing notes, deleting events, completion, return to service, cancellation, assignment, diagnostics, parts, photos, control-board replacement, generic CRUD, or UI changes.

Completion Report

Report files created and modified, migration revision if any, routes, permission changes, tests and validation, and final git status --short.

Do not commit. Do not push.