373 lines
13 KiB
Markdown
373 lines
13 KiB
Markdown
# MinerOps Architecture & Product Decisions
|
|
|
|
This document records long-lived engineering and product decisions for
|
|
MinerOps. Each record explains the context, the chosen approach, and its
|
|
consequences so future work can preserve intent rather than infer it from code.
|
|
|
|
Decisions may evolve as operational evidence changes. Replacing or reversing a
|
|
decision should be deliberate and documented in a later record. Existing
|
|
records should remain available as history rather than being silently rewritten.
|
|
|
|
---
|
|
|
|
# ADR-0001
|
|
|
|
**Title:** MinerOps is self-hosted first.
|
|
|
|
## Context
|
|
|
|
Mining operations depend on local equipment, segmented networks, and
|
|
operational records that may need to remain under direct organizational control.
|
|
Requiring a hosted service would make availability, data access, and subscription
|
|
terms dependencies of core operations.
|
|
|
|
External services can still provide useful integrations. The question is
|
|
whether they are optional participants or mandatory owners of the operational
|
|
record.
|
|
|
|
## Decision
|
|
|
|
MinerOps is self-hosted first. Operators control the deployment and retain
|
|
ownership of their operational data. Core use must not require a mandatory SaaS
|
|
subscription or transfer the authoritative record to a hosted provider.
|
|
|
|
Remote access and integrations are allowed when the operator chooses them. They
|
|
must not change the self-hosted deployment into a secondary cache of a required
|
|
external service.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Operators can place MinerOps near local mining networks, retain
|
|
control of data and availability, and use it in restricted environments.
|
|
|
|
**Tradeoffs:** Operators are responsible for deployment, updates, backups, and
|
|
recovery. Optional hosted integrations must be designed so loss of the
|
|
integration does not remove ownership of the core record.
|
|
|
|
---
|
|
|
|
# ADR-0002
|
|
|
|
**Title:** Assets use durable internal identity.
|
|
|
|
## Context
|
|
|
|
A miner's observable properties change during normal operations. IP addresses
|
|
change, network interfaces and control boards are replaced, equipment moves,
|
|
and operator-facing labels may be corrected. None of those changes should make
|
|
the asset appear to be a different historical object by default.
|
|
|
|
Operators also need a practical label that can be printed, scanned, and used in
|
|
conversation without exposing an internal database key.
|
|
|
|
## Decision
|
|
|
|
Every miner asset has an immutable internal UUID. That UUID is the durable
|
|
identity used for relationships and history.
|
|
|
|
The Asset ID is the operator-facing identifier. It is unique within a MinerOps
|
|
installation and can be managed independently of mutable network values. IP
|
|
addresses, MAC addresses, hardware serials, and location are attributes or
|
|
associations of the asset, not substitutes for its internal identity.
|
|
|
|
Hardware replacement does not automatically create a new asset identity. The
|
|
correct outcome depends on whether the operation represents repair of the same
|
|
asset or introduction of a genuinely different asset, and that distinction must
|
|
be explicit.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Records can remain connected through network changes, movement,
|
|
and component replacement. Internal relationships do not depend on a mutable or
|
|
human-entered value.
|
|
|
|
**Tradeoffs:** Imports, discovery, and repair workflows must resolve observations
|
|
to an existing UUID or deliberately create a new asset. Duplicate resolution
|
|
cannot safely rely on IP or MAC alone.
|
|
|
|
---
|
|
|
|
# ADR-0003
|
|
|
|
**Title:** Network identity is not asset identity.
|
|
|
|
## Context
|
|
|
|
Discovery observes devices through IP addresses, MAC addresses, hostnames, and
|
|
protocol responses. These values are useful for finding and communicating with
|
|
a miner, but they can change because of DHCP, network reconfiguration, control
|
|
board replacement, or data correction.
|
|
|
|
Treating the latest network observation as the asset identity loses continuity
|
|
and can attach history to the wrong equipment.
|
|
|
|
## Decision
|
|
|
|
Network identities are associated with durable assets. Current IP and MAC values
|
|
represent the latest known network state, while meaningful prior associations
|
|
should remain available as history.
|
|
|
|
Discovery proposes or updates associations; it does not redefine the asset
|
|
solely because an address changed. Ambiguous matches require a deliberate
|
|
identity workflow rather than silent merging or replacement.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Discovery can remain useful without erasing asset continuity.
|
|
Operators can understand address changes and component replacement in historical
|
|
context.
|
|
|
|
**Tradeoffs:** Matching requires more information and explicit conflict handling.
|
|
Some observations cannot be attached automatically, and network history adds
|
|
records that must be maintained and presented clearly.
|
|
|
|
---
|
|
|
|
# ADR-0004
|
|
|
|
**Title:** Business logic belongs in services.
|
|
|
|
## Context
|
|
|
|
When business rules are implemented in HTTP handlers, they become coupled to a
|
|
transport and are difficult to reuse or test. When they are placed in database
|
|
code, persistence concerns become mixed with product decisions.
|
|
|
|
MinerOps has existing integrated routes that predate the current domain
|
|
boundaries. Copying that structure would continue the coupling.
|
|
|
|
## Decision
|
|
|
|
Domain services own normalization, business validation, decisions, state-change
|
|
rules, and use-case orchestration. Routers handle HTTP concerns and call
|
|
services. Repositories persist the outcomes requested by services.
|
|
|
|
Services raise domain errors and return domain results. They do not depend on
|
|
FastAPI requests, responses, decorators, or status codes. The Inventory service
|
|
is the current reference for this separation.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Business behavior can be tested without HTTP or a real database,
|
|
used by more than one adapter, and maintained in one explicit location.
|
|
|
|
**Tradeoffs:** Features require an additional boundary and clear input and output
|
|
contracts. Poorly chosen service responsibilities can become overly broad, so
|
|
service ownership must follow domain use cases rather than convenience.
|
|
|
|
---
|
|
|
|
# ADR-0005
|
|
|
|
**Title:** Persistence is isolated behind repositories.
|
|
|
|
## Context
|
|
|
|
SQL embedded in routes or services couples product behavior to schema details,
|
|
connection handling, and a specific database driver. Repeated queries also make
|
|
ownership unclear and allow filtering or transaction behavior to diverge.
|
|
|
|
Tests need a boundary where service behavior can substitute persistence and
|
|
where database behavior can be verified independently.
|
|
|
|
## Decision
|
|
|
|
Each domain isolates its database access behind repositories. Repositories own
|
|
SQL, database-facing filtering and ordering, connection and transaction
|
|
mechanics, and persistence mapping.
|
|
|
|
Routers and services do not issue SQL. A domain owns persistence for its records,
|
|
and another domain does not bypass that ownership by importing its repository
|
|
to perform unrelated writes.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** SQL has explicit ownership, service tests can use substitutes,
|
|
repository tests can target real database behavior, and persistence changes have
|
|
a defined boundary.
|
|
|
|
**Tradeoffs:** Repository interfaces must be maintained, and cross-domain read
|
|
requirements need deliberate query ownership. A repository is not an excuse to
|
|
hide business rules in database code.
|
|
|
|
---
|
|
|
|
# ADR-0006
|
|
|
|
**Title:** Database schema changes use Alembic.
|
|
|
|
## Context
|
|
|
|
Persistent schema must be reproducible across new installations, existing
|
|
deployments, tests, and recovery environments. Runtime table creation makes
|
|
schema state depend on which application paths have executed and is difficult
|
|
to review or reverse.
|
|
|
|
The existing application contains legacy runtime schema creation for
|
|
compatibility, but the repository now has a versioned Alembic migration chain
|
|
and focused migration tests.
|
|
|
|
## Decision
|
|
|
|
New persistent schema changes are made through explicit, versioned Alembic
|
|
migrations. A migration documents upgrade behavior, treatment of existing data,
|
|
constraints and indexes, and a downgrade path where it is safe and meaningful.
|
|
|
|
New code must not create or alter persistent tables at application runtime.
|
|
Legacy runtime schema behavior is an existing compatibility condition, not a
|
|
pattern for new work.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Schema state is reviewable, reproducible, testable, and ordered.
|
|
Deployments and disposable tests can reach the same known schema from an empty
|
|
or existing database.
|
|
|
|
**Tradeoffs:** Schema work requires migration design and validation before the
|
|
application can use it. Some destructive downgrades cannot preserve all data and
|
|
must be documented explicitly.
|
|
|
|
---
|
|
|
|
# ADR-0007
|
|
|
|
**Title:** Operational history is preserved.
|
|
|
|
## Context
|
|
|
|
The current value of an asset does not explain how it arrived there. Repairs,
|
|
movement, lifecycle changes, network identity changes, component replacement,
|
|
and operator actions all affect operational understanding.
|
|
|
|
Overwriting important changes may simplify the current record but removes the
|
|
context technicians and managers need to diagnose problems and trust the
|
|
system.
|
|
|
|
## Decision
|
|
|
|
MinerOps preserves meaningful operational history. Current state remains easy
|
|
to identify, while important repairs, movement, lifecycle events, identity
|
|
associations, and audited actions remain traceable with time and context.
|
|
|
|
Corrections must not silently destroy history that remains operationally
|
|
relevant. Retention policy may summarize high-volume observations, but durable
|
|
asset, repair, movement, lifecycle, and audit meaning is preserved.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Operators can understand an asset across its lifecycle, technicians
|
|
can review prior work, and changes can be audited and explained.
|
|
|
|
**Tradeoffs:** Historical data requires storage, retention policy, and interfaces
|
|
that distinguish current state from prior state. Corrections and privacy or
|
|
retention requirements need deliberate handling.
|
|
|
|
---
|
|
|
|
# ADR-0008
|
|
|
|
**Title:** Safety takes precedence over convenience.
|
|
|
|
## Context
|
|
|
|
MinerOps can coordinate actions that interrupt individual miners or affect a
|
|
large part of a fleet. A fast or convenient action can create substantial
|
|
operational impact when its target, scope, timing, or authorization is wrong.
|
|
|
|
Bulk operations and automation increase this risk because one request may affect
|
|
many devices without individual review.
|
|
|
|
## Decision
|
|
|
|
Potentially disruptive actions favor safety over minimum interaction. Product
|
|
workflows enforce permissions, communicate target and scope, require clear
|
|
confirmation where appropriate, and leave an audit trail.
|
|
|
|
Broad actions should support safeguards such as preview or dry-run behavior,
|
|
staggering, limits, expiry, and awareness of maintenance or intentionally
|
|
offline state when those safeguards apply. Development and new installations
|
|
use safe defaults.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Operators receive clearer intent and accountability, accidental
|
|
fleet-wide disruption is less likely, and actions can be investigated after the
|
|
fact.
|
|
|
|
**Tradeoffs:** Some operations require more steps and may complete more slowly.
|
|
Safety behavior adds product and test complexity and must be maintained rather
|
|
than bypassed for convenience.
|
|
|
|
---
|
|
|
|
# ADR-0009
|
|
|
|
**Title:** Progressive complexity.
|
|
|
|
## Context
|
|
|
|
Mining operations vary from small fleets with simple inventory needs to
|
|
multi-site organizations with detailed infrastructure, automation, and role
|
|
requirements. Requiring every installation to configure the largest possible
|
|
model would make basic workflows difficult to adopt and maintain.
|
|
|
|
At the same time, limiting the product to the smallest deployment would prevent
|
|
larger operators from representing their real work.
|
|
|
|
## Decision
|
|
|
|
MinerOps exposes useful basic workflows without requiring every advanced
|
|
capability. Operators can begin with the records and structure they need, then
|
|
adopt additional location depth, monitoring, automation, integrations, and
|
|
organizational controls as their operation requires them.
|
|
|
|
Advanced features remain coherent extensions of the same operational record.
|
|
They do not create a separate product mode or make basic asset and repair work
|
|
dependent on unrelated configuration.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Small deployments can gain value with less setup, while larger
|
|
deployments have room to model additional complexity without abandoning the
|
|
same system of record.
|
|
|
|
**Tradeoffs:** Defaults and optional states must be designed carefully. Features
|
|
must work when advanced context is absent, which increases the number of valid
|
|
configurations that testing must cover.
|
|
|
|
---
|
|
|
|
# ADR-0010
|
|
|
|
**Title:** Architecture evolves incrementally.
|
|
|
|
## Context
|
|
|
|
MinerOps contains working early-stage software alongside newer domain
|
|
boundaries. Replacing the application in one rewrite would put existing
|
|
workflows, data compatibility, and validation at unnecessary risk.
|
|
|
|
Leaving all existing responsibilities in integrated modules would also make new
|
|
features harder to test and maintain.
|
|
|
|
## Decision
|
|
|
|
Architecture improves incrementally. New domain code follows the established
|
|
router, service, and repository boundaries. Existing behavior moves behind
|
|
those boundaries in small, reviewable changes that preserve working software
|
|
and include compatibility validation.
|
|
|
|
A new boundary is introduced when it clarifies ownership or testability, not
|
|
merely to rename or relocate code. Existing integrated code is context to
|
|
preserve, not a template to duplicate.
|
|
|
|
## Consequences
|
|
|
|
**Benefits:** Architectural quality improves while the application remains
|
|
usable. Smaller changes are easier to review, test, diagnose, and reverse.
|
|
|
|
**Tradeoffs:** The repository will contain transitional patterns for a period of
|
|
time. Contributors must understand which code represents current rules and
|
|
which code remains for compatibility, and some temporary duplication may need
|
|
careful removal after migration.
|