143 lines
5.8 KiB
Markdown
143 lines
5.8 KiB
Markdown
# MinerOps Coding Standards
|
|
|
|
## Purpose
|
|
|
|
This document defines the engineering conventions for MinerOps. Task specifications may add feature-specific requirements, but they should not weaken these standards without an explicit architectural decision.
|
|
|
|
## Core Principles
|
|
|
|
1. Prefer explicit domain operations over generic CRUD.
|
|
2. Preserve operational history.
|
|
3. Enforce critical invariants in PostgreSQL.
|
|
4. Keep operations atomic.
|
|
5. Separate network identity from durable asset identity.
|
|
6. Use server-controlled timestamps and authenticated actor identities.
|
|
7. Design for self-hosted deployment and safe recovery.
|
|
8. Prefer clear, maintainable code over clever abstractions.
|
|
9. Keep each implementation task focused and reviewable.
|
|
10. Treat safety as more important than convenience for actions affecting miners.
|
|
|
|
## Layered Architecture
|
|
|
|
```text
|
|
Router
|
|
-> Service
|
|
-> Repository
|
|
-> PostgreSQL
|
|
```
|
|
|
|
### Router
|
|
|
|
Routers may define HTTP routes, validate requests, enforce authentication and permissions, and serialize responses.
|
|
|
|
Routers must not contain SQL, manage transactions, implement domain decisions, import database drivers directly, or bypass the service layer.
|
|
|
|
### Service
|
|
|
|
Services implement domain workflows, coordinate repositories, enforce domain rules, and raise domain exceptions.
|
|
|
|
Services must not import FastAPI, raise HTTP-specific exceptions, contain raw SQL, or trust actor identity supplied in request bodies.
|
|
|
|
### Repository
|
|
|
|
Repositories own database queries, row locking, persistence details, and PostgreSQL-specific integrity behavior.
|
|
|
|
Repositories must not import FastAPI, make permission decisions, define HTTP behavior, or commit independently inside a larger service transaction.
|
|
|
|
## Domain Operations
|
|
|
|
Use explicit operations such as:
|
|
|
|
```http
|
|
POST /api/repairs
|
|
POST /api/repairs/{repair_id}/complete
|
|
POST /api/miners/{miner_id}/move
|
|
POST /api/miners/{miner_id}/replace-control-board
|
|
```
|
|
|
|
Only `POST /api/repairs` is implemented by the modular Repairs domain today.
|
|
The other routes are illustrative names for possible future explicit workflows,
|
|
not existing API contracts.
|
|
|
|
Avoid broad mutable CRUD endpoints when the request represents a meaningful operational event.
|
|
|
|
## Transactions and Concurrency
|
|
|
|
Any workflow that changes multiple authoritative records must execute atomically.
|
|
|
|
Use row locks and database constraints when concurrent requests could violate an invariant. Do not rely only on pre-insert application checks when PostgreSQL can enforce the rule.
|
|
|
|
## Database Integrity
|
|
|
|
Use constraints for uniqueness, valid state combinations, referential integrity, one-active-record rules, event-sequence integrity, and actor/timestamp requirements.
|
|
|
|
Operational history should generally use `RESTRICT` rather than disappearing through cascades.
|
|
|
|
Every migration must support upgrade, safe downgrade or explicit refusal, previous-head testing, re-upgrade, and empty-database-through-head validation. A downgrade must never invent historical values.
|
|
|
|
## Identity
|
|
|
|
A miner's durable identity must not depend on its current IP address, MAC address, control board, hostname, or location.
|
|
|
|
Network identifiers are observations or replaceable hardware attributes and must retain history.
|
|
|
|
Actor identity must come from the authenticated principal, never an authoritative request-body field.
|
|
|
|
## Time
|
|
|
|
Use timezone-aware timestamps. Authoritative operational timestamps are server- or database-controlled. Never use timestamp order as a substitute for an explicit event sequence.
|
|
|
|
## Immutable Operational History
|
|
|
|
Timeline and audit events are append-only. Once written, an event is never edited, deleted, reordered, or silently replaced. Corrections are new events.
|
|
|
|
Sequenced domain timeline events should include an event UUID, parent UUID,
|
|
sequence, event type, actor UUID, timestamp, and structured JSON payload.
|
|
|
|
## API Design
|
|
|
|
- Use UUID types for UUID fields.
|
|
- Use constrained domain values.
|
|
- Use 404 for missing resources, 409 for state conflicts, 422 for invalid input, and established project behavior for 401 and 403.
|
|
- Do not expose internal fields without a product requirement.
|
|
- Keep routes focused.
|
|
- Protect existing static routes when introducing parameter routes.
|
|
|
|
## Permissions
|
|
|
|
Permissions describe capabilities, not roles. Implemented examples include
|
|
`repairs.read` and `repairs.create`. Names such as `repairs.complete` and
|
|
`miners.move` illustrate possible future capabilities and are not currently
|
|
registered permissions.
|
|
|
|
Every protected route requires unauthenticated, unauthorized, and authorized-role tests. Read-only roles may view history but may not perform actions.
|
|
|
|
## Testing and Validation
|
|
|
|
Feature work should cover happy paths, validation, permissions, missing records, conflicts, rollback, concurrency where relevant, constraints, migrations, route compatibility, and architecture boundaries.
|
|
|
|
Unless a task says otherwise, run:
|
|
|
|
- Python compilation
|
|
- shell syntax validation
|
|
- focused tests
|
|
- relevant regression suites
|
|
- migration upgrade, downgrade, re-upgrade, and empty database
|
|
- disposable development baseline
|
|
- router SQL/driver/transaction audit
|
|
- service/repository FastAPI audit
|
|
- route-count audit
|
|
- `git diff --check`
|
|
|
|
## Security
|
|
|
|
Never commit credentials, tokens, environment files, dumps, private configuration, caches, or local database data. Do not log secrets. Apply least privilege and preserve audit history for sensitive actions.
|
|
|
|
## Documentation
|
|
|
|
Every implementation task should have a version-controlled specification under `docs/tasks/`. Update roadmaps only after validation passes. Add an ADR only for a genuinely new architectural principle.
|
|
|
|
## Review Checklist
|
|
|
|
Before approval, confirm scope, transaction boundaries, database invariants, actor attribution, timestamps, immutable history, permissions, migrations, regressions, route behavior, performance risks, and the reviewed file set.
|