Skip to content

feat(stats): publish consented installation, capacity and energy totals - #31

Merged
frahlg merged 4 commits into
mainfrom
feat/usage-energy-stats
Oct 17, 2026
Merged

frahlg merged 4 commits into
mainfrom
feat/usage-energy-stats

Conversation

@frahlg

@frahlg frahlg commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

FTW's anonymous daily reports cannot count unique installations or report power and solar energy. Receive signed, separately consented closed-hour stats messages and publish privacy-gated group cells at GET /v1/stats, which stats.ftw.energy polls hourly.

Paired with srcfl/ftw#1693, pinned at protocol commit 6335dbcea60e. The dashboard is srcfl/ftw-webapp#50. Core protocol lands first, then Cloud. This pin overlaps #27's protocol-pin change; whichever lands second must preserve both changes. The paused relay-port PR #14 also touches composition files; this change adds no relay runtime.

Statistics require the exact new policy, random stats id and consent start in the current signed grant. Old policies, partner controllers and pre-consent hours store nothing. The report uses the authenticated connection's home, never a body field. SQLite upserts by home/hour, deletes household rows on signed withdrawal, policy rotation or purge, and prunes at 13 months. No staff route reads those rows. Live readings still stay in memory; the guide names the explicit closed-hour storage exception.

The public view counts installations reporting in the last 24 closed hours, not people or all FTW installations. Capacity uses each home's latest report; energy sums its recorded hours, which may be partial. Missing values are not zero. Cells need at least 20 contributing homes and no home above 30% of a sum. The public JSON contains no home or stats id. It is cached for a minute. A single instance publishes its shard only; this is not a multi-shard total.

Validation: go vet ./..., go test -race ./..., go test -tags ftwclouddev ./... and bash scripts/check-imports.sh pass with the published protocol pin. Regressions cover the signed box path, no phone forwarding, policy/consent window checks, reconnect deduplication, small groups, dominance, unknown values, withdrawal/purge deletion and retention. TestNoRouteReadsAHome includes the new route.

Collection now starts off. Only the exact FTW_CLOUD_STATISTICS_POLICY operator setting advertises the approved policy in signed hello_ok and enables ingestion and public energy cells. Core also refuses to send before that signal. The native client reads readiness and asks for a fresh per-home choice. Withdrawal and retention continue while paused. A disabled /v1/stats is an explicit 503, never a zero-use claim.

The C8 review draft is privacy/project-statistics-dpia.md. It names open decisions about other residents, retention, public differencing, infrastructure access and rights. The updated notice is srcfl/ftw-web#22. No DPIA sign-off or household consent is claimed. The safe rollout keeps collection off until that review is complete.

GET /v1/fleet/public separately exports the existing anonymous daily counts, with at least 10 reports per day and each dimension label. It allows an immediate seven-day estimate of active reporting installations without enabling household hourly collection. Cloud includes imported relay history, so the Worker replaces the archive view instead of adding it. Tests cover paused ingestion, paused withdrawal, signed readiness and small daily cells.

Go growth excluding tests: registry +179 lines, fleet +46, statistics +59, uplink +21, server +16, cmd/ftwcloudd +12; total +333. No new external dependency.

@frahlg
frahlg marked this pull request as ready for review October 17, 2026 14:04
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T14:08:02.548124Z e41b70d Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e41b70db41

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

on := g.Controller == cloudwire.ControllerSourceful && g.StatsPolicy == cloudwire.StatsPolicy &&
len(g.StatsID) == 16 && g.StatsSinceMs > 0 && slices.Contains(g.Purposes, protocol.CloudPurposeStats) &&
slices.Contains(g.Purposes, protocol.CloudPurposeServe)
if !on || !bytes.Equal(old, g.StatsID) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Purge rows when the consent start changes

When a signed grant advances StatsSinceMs while retaining the same statistics ID, this condition preserves all previously stored hours and only updates since_ms. StatisticsView does not filter rows against that value, so hours preceding the current consent start remain publishable. Treat a changed consent start like an ID change, or delete rows older than the new start.

Useful? React with 👍 / 👎.

@frahlg
frahlg merged commit 9a6b07c into main Oct 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant