MainsKeeper Product & System Guide Edition 0.2.3

Reference

Interface catalog

Component boundaries with status labels. Illustrative JSON appears in Chapter 5. Logical boundaries are below. Sequence diagrams for enroll and replay: enrollment and replay.

Enrollment

Accepted behavior · Proposed wire
Purpose
Bind a newly installed collector to an account/site and issue credentials.
Producer → consumer
Collector CLI / firmware → Dashboard + enrollment service
Direction / transport
Collector initiates; operator approves. Transport: HTTPS or equivalent (Proposed)
Identity / ownership
Short enrollment code; collector device identity; site id
Minimum information
Code, platform, discovered sources, requested roles
Timing / freshness
Code TTL (design: 10 min); approval before first contact
Success / failure / retry
Approved → credential; expired/denied/offline variants; re-enroll keeps history
Auth / credentials
Credential never in URL/CLI logs; local after approval
Versioning
Additive enrollment protocol versions (Open)
Sequence diagram: operator enrolls collector bw-pi-01, approves short code WDJB-MJHT, and the collector stores a credential on check-in. First contact and the first UPS reading are later, separate events.

Enrollment sequence

Takeaway: Approval, first contact, and the first UPS reading are three events. The code WDJB-MJHT is a synthetic example from the design, not a live credential.

Telemetry upload

Proposed wire · Accepted semantics
Purpose
Deliver observations and heartbeats for durable history and current state.
Producer → consumer
Collector → Ingestion service
Direction / transport
Collector push. Transport: HTTPS batches (Proposed)
Identity / ownership
collectorId + sequence / dedupe keys
Minimum information
observedAt, readings, heartbeats, optional events
Timing / freshness
Reporting interval vs heartbeat independent; replay allowed
Success / failure / retry
Ack advances cursor; 401 revoked; 503 retry; duplicates idempotent
Auth / credentials
Collector credential; UPS secrets not included
Versioning
schema id in payload (illustrative)
Sequence diagram: UPS observations stay in the collector buffer while the WAN is down, then replay with the original observation time. Ingestion acknowledges a prefix, writes history at that time, and does not raise a fresh alert for the old condition.

Replay and acknowledgement sequence

Takeaway: Replay updates history at observation time. A missing heartbeat does not prove a power failure. Scraping current metrics does not perform this exchange.

Desired configuration

Accepted ownership model
Purpose
Distribute dashboard-managed settings to collectors.
Producer → consumer
Dashboard → Collector (on check-in)
Direction / transport
Pull on check-in / contact. Transport: With telemetry session (Proposed)
Identity / ownership
collectorId + config keys
Minimum information
desired values for site, roles, intervals, connectivity targets
Timing / freshness
Applied at next check-in; asleep/lost stay pending
Success / failure / retry
applied | failed(reason) | waiting
Auth / credentials
Dashboard auth for operators; collector auth for pull
Versioning
key-level compatibility

Local source secrets

Accepted
Purpose
Store NUT/SNMP credentials for source tests and reads.
Producer → consumer
Operator on collector → Local secret store
Direction / transport
Local only. Transport: OS keychain / secrets.d / DPAPI / device page
Identity / ownership
source id
Minimum information
secret material never uploaded
Timing / freshness
Required before successful network test
Success / failure / retry
Configured / Missing / Rejected reflected to dashboard
Auth / credentials
No dashboard delivery channel
Versioning
n/a

Current-state & history query

Proposed
Purpose
Serve fleet UI and CLI status from stored evidence.
Producer → consumer
Query API → Dashboard / CLI
Direction / transport
Request/response. Transport: HTTPS (Proposed)
Identity / ownership
account + site/ups/collector ids
Minimum information
latest readings, freshness, unknown spans, incidents
Timing / freshness
Freshness badges; history by observation time
Success / failure / retry
Standard read errors; never fabricate gaps
Auth / credentials
Operator session (Proposed provider)
Versioning
API versioning Open

Notification delivery

Proposed
Purpose
Deliver declared incidents and Assurance reminders.
Producer → consumer
Incident / notify service → Email, push, other channels
Direction / transport
Outbound. Transport: Channel-specific (Proposed)
Identity / ownership
incident id / rule id
Minimum information
severity, evidence summary, deep link
Timing / freshness
After declare; retries on failure
Success / failure / retry
Delivery log; reminder dedupe; snooze ≠ resolve
Auth / credentials
Channel credentials server-side
Versioning
template versioning

Metrics scrape (standalone path)

Proposed
Purpose
Expose current-state gauges for Prometheus.
Producer → consumer
Collector metrics endpoint → Prometheus
Direction / transport
Pull scrape. Transport: HTTP /metrics (Proposed)
Identity / ownership
collector instance labels
Minimum information
current gauges only — not historical gap fill
Timing / freshness
Scrape interval ≠ durable retention
Success / failure / retry
Stale metrics on silence; no replay via scrape
Auth / credentials
Network ACL / scrape auth Open
Versioning
metric name stability

Assurance evidence & findings

Accepted rules · Proposed API
Purpose
Record evidence and resolve protection findings.
Producer → consumer
Operators / collectors / UPS reports → Assurance module
Direction / transport
Mixed write paths. Transport: API + UI (Proposed wire; Accepted rules)
Identity / ownership
batteryInstallationId, evidence ids
Minimum information
source, occurrence, outcome, load, duration bounds
Timing / freshness
Age from occurrence; policy windows
Success / failure / retry
Guarded resolve requiring documentation
Auth / credentials
Operator auth; no hardware write
Versioning
policy document version

Logical boundaries inside the running path

These cuts explain ownership. They are not an instruction to deploy a process per box. An MVP can keep the adapter inside the collector, and ingestion, storage, and evaluation in one service. Hardware secrets still do not move.

UPS protocol ↔ adapter

Accepted behavior · Proposed packaging
Purpose
Turn a USB-HID, NUT, or SNMP read into a normalized observation. No control command crosses this line.
Producer → consumer
UPS firmware → adapter inside the collector or probe.
Direction / transport
Adapter requests a status read. The UPS returns readings or a timeout. Transport is the device protocol, not the MainsKeeper API.
Identity / ownership
Source identity: namespace, protocol, host, port, and NUT name where the protocol has one. The adapter does not own the UPS asset id.
Minimum information
Observation time, power state, and any reported fields. Unsupported and not-reported stay distinct. Missing is not 0.
Timing / freshness
The collector’s reporting interval. A timeout becomes UPS communication lost only after the accepted 2 minutes, and only while the collector itself is reporting.
Success / failure / retry
A read either normalizes or is recorded as a communication failure. The adapter does not retry by issuing a self-test. ESP32 does not speak the full NUT stack.
Auth / credentials
Network secrets stay in the collector’s local store. The adapter may use them. It does not upload them.
Versioning
Which UPS models answer is an open validation list, especially on ESP32. See d7.
Contract
§2 monitoring only · §18.1 source identity

Adapter ↔ collector

Accepted responsibility · same process on a host
Purpose
Hand the collector one observation, or a clear communication failure, without the collector speaking USB or SNMP itself.
Producer → consumer
Adapter → collector scheduler. The collector asks. The adapter answers.
Direction / transport
In-process on host collectors. On ESP32 the same responsibility is firmware, not a second service. Transport inside the process is Open.
Identity / ownership
Collector owns cadence, roles, and which source is active. Adapter owns the protocol details.
Minimum information
Source id, observation time, normalized fields, support flags.
Timing / freshness
Independent of heartbeat. A quiet UPS is not a missed heartbeat.
Success / failure / retry
The collector records the result and decides whether to sample again. The adapter does not upload and does not evaluate incidents.
Auth / credentials
None of its own. It uses the local secret the collector already holds.
Versioning
Normalized field names should stay stable even if a protocol library changes. The field list is Proposed.
Contract
§2 · Figure 5

Collector ↔ local durable buffer

Accepted need · Proposed retirement rule
Purpose
Keep observations that ingestion has not durably accepted, including across a collector restart on a host.
Producer → consumer
Collector writes. Collector reads the unacked span back for upload. The server never writes this store.
Direction / transport
Local disk, or flash on a probe. Engine is Open except that browser storage in the prototype is not it.
Identity / ownership
Collector owns the bytes. Sequence numbers are per collector.
Minimum information
Observation time, source, payload, sequence. Receipt time does not exist yet.
Timing / freshness
Append before the upload attempt, so a crash between sample and send does not drop the row.
Success / failure / retry
Overflow drops the oldest span and must surface a gap. Those rows are gone. Do not invent them at reconnect.
Auth / credentials
UPS secrets are a different local store. They are not rows in the telemetry buffer.
Versioning
When a local row may be deleted: only after the acknowledgement cursor covers it. That rule is Proposed. ESP32 capacity figures stay illustrative (d7).
Contract
§15.4 · Walkthrough 09:20 · Figure 8

Ingestion ↔ durable storage

Proposed wire · Open engine
Purpose
Make an accepted batch survive independently of the collector, at observation time, without collapsing current state and history into one blob.
Producer → consumer
Ingestion writes. Queries, evaluation, and Assurance read. See the next boundary.
Direction / transport
In-process or a database call. Not specified. Choosing a database is d2.
Identity / ownership
Account, collector, source, UPS asset, and battery installation stay distinct keys.
Minimum information
Observation time, receipt time, sequence, payload, and a gap marker when a span was dropped.
Timing / freshness
Durable accept is the point the acknowledgement cursor may move. Until that write succeeds, the collector must keep the rows.
Success / failure / retry
A duplicate sequence does not create a second history row (idempotency). A failed write does not ack. Replay and live ingest share this rule.
Auth / credentials
The collector credential was already checked before this write. UPS secrets are absent.
Versioning
Schema ids in examples are illustrative. Retention of raw history versus Assurance is a separate open window.
Contract
§15.4 · §18.3 · Figure 13

Stored observations ↔ evaluation and queries

Accepted rules · Proposed call shape
Purpose
Let the dashboard, CLI, and incident rules read one stored record without sampling the UPS again.
Producer → consumer
Storage → current-state query, history query, incident evaluation, and Battery Assurance. Evaluation → notification only after declare.
Direction / transport
Read path. May be the same process as ingestion. Transport is Open.
Identity / ownership
Queries do not create observations. Evaluation does not rewrite history to hide a gap.
Minimum information
Latest reading and its age, unknown spans, incident timestamps, and installation-scoped evidence.
Timing / freshness
Freshness uses the accepted cadence rule (§18.4), not a universal 60 seconds. Current and last known stay labelled.
Success / failure / retry
A missing id is not found, never a substituted neighbor. Evaluation declares, recovers, and resolves from evidence rules. Acknowledgement is not an input to recovery.
Auth / credentials
Operator session for dashboard and CLI. That provider is d3. Evaluation itself is not an operator action.
Versioning
Changing storage engines must not merge “reads” with “powers,” or contact age with UPS reading age.
Contract
§15.2–§15.3 · Figure 5 · Figure 11
Normal telemetry sequence from UPS read through local append, upload, and acknowledgement.

Telemetry sequence (Figure 7)

Takeaway: The same drawing as Chapter 4. Append happens before upload. Acknowledgement is what makes the prefix durable.