Audit fixes: batch recompute, negative-baseline percentages, key-ring persistence
ci / build-test (push) Successful in 1m17s
ci / build-test (push) Successful in 1m17s
Three defects found reviewing the last few commits. Deriving consumption on ingest made the batch reading endpoint quadratic. A recompute rewrites a meter's entire consumption series, and POST /api/v1/readings ran one per reading -- 500 readings for one meter meant 500 full rewrites. IngestByMeterAsync takes renormalize:false and the endpoint normalizes each touched meter once after the batch. Percentage change divided by a possibly negative baseline. A net-export meter going from -100 to -150 exported half again as much and would have been reported as "+50%", reading as more consumption. A non-positive baseline now reports no basis rather than a confident lie. The data-protection key ring had no persistent home outside Docker Compose. The LXC installer now creates /var/lib/metervault/keys at 0700 -- the app would otherwise create it under the default umask, leaving a key ring world-readable -- and the Unraid template maps it, since without that every UI-entered secret was lost whenever the container was recreated. README documents the variable and the trust boundary: keys on disk protect against leaked database content, not against an attacker who already has the host. Claude-Session: https://claude.ai/code/session_01V6joyergfvVLFEizH1hJLd
This commit is contained in:
@@ -72,12 +72,21 @@ Configuration is via environment variables (`Section__Key` double-underscore map
|
||||
| `MeterVault__ReverseProxyTrust` | `true` to honour `X-Forwarded-User` behind an auth proxy |
|
||||
| `MeterVault__EnableLiveIngestion` | `false` to disable the MQTT/HA workers |
|
||||
| `MeterVault__SeedReferenceData` | `true` to load the bundled demo dataset on first start (idempotent) |
|
||||
| `MeterVault__DataProtectionKeyPath` | Where the key ring for UI-entered connector secrets lives (default `/var/lib/metervault/keys`) |
|
||||
|
||||
The REST API is **closed by default**: with no `ApiKeys` configured and `AllowAnonymousApi` off, it
|
||||
returns 401. Set at least one API key (or open it explicitly for a trusted network).
|
||||
|
||||
Secrets (broker/HA tokens) are **never** stored in the database — endpoint configs hold the *name*
|
||||
of an environment variable, resolved at runtime.
|
||||
Secrets (broker/HA tokens) are **never** stored in the database as plaintext. Each connector picks
|
||||
one of two forms: the *name* of an environment variable, resolved at runtime, or the secret typed
|
||||
into the admin UI and encrypted at rest under the data-protection key ring. Either way a `pg_dump`
|
||||
or JSON export carries nothing usable.
|
||||
|
||||
Keep the key ring on persistent storage outside the app directory — the default
|
||||
`/var/lib/metervault/keys` survives an LXC update, and the Compose file mounts a named volume for it.
|
||||
Lose it and every UI-entered secret must be re-entered. The key ring is on disk, so this protects
|
||||
against leaked database content, not against an attacker who already has the host; that is the same
|
||||
trust boundary an environment variable has.
|
||||
|
||||
## Pushing readings (Home Assistant)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user