Repository navigation
Conversation
… a relay exists The energy report waited for an independent relay that does not exist, so no box sent one and stats.ftw.energy showed no energy. A build without a relay now posts it to https://cloud.ftw.energy/v1/energy, as the fleet report goes to /v1/fleet since 8 November: every box that shares reports (Fredrik, 12 November 2026). The body is the same padded inner request the gateway would open, unsealed. FTW Cloud sees the address while the request is open and keeps neither the address nor the report. Settings says where it goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de9073ba0d
ℹ️ 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".
| "Until then it goes straight to FTW Cloud, which sees the address while " + | ||
| "the request is open and keeps neither the address nor the report. With " + |
There was a problem hiding this comment.
Qualify the unlinkability claim for direct delivery
In the default build without a relay, this paragraph still promises that the energy and fleet reports “cannot be matched,” even though both now reach FTW Cloud with the household's source address visible. Separate random send times do not prevent correlation by address, as the new amendment explicitly acknowledges in docs/adr/0008-ftw-cloud.md:442–444. Saying that the address is not retained does not make correlation technically impossible. Qualify the earlier promise and disclose this temporary limitation beside the statistics switch so owners are not given a privacy guarantee that the new delivery path cannot provide.
Useful? React with 👍 / 👎.
miravoss26
left a comment
There was a problem hiding this comment.
Core sends the daily energy report straight to statsrelay.DirectURL (cloud.ftw.energy/v1/energy) when the build pins no relay, instead of sending nothing. Same padded inner request, unsealed as message/bhttp, only a 204 counts, no retry, no redirect.
Code reads clean: Default() falls back to NewDirect only when Pinned() is nil, redirect refusal is shared, Relay() is empty when direct so Settings can tell the cases apart, and the response body is size-limited. No secrets, no new dependency, one new host (cloud.ftw.energy, which the fleet report already uses).
- Needs a human decision (already flagged in your ADR amendment): this removes the relay's separation of address from content. Until a relay exists, Sourceful could match an energy report to a fleet report by address + time, and the protection is a rule in code, not a mechanism. The PR states it plainly, which is the right way to do it. It also changes behaviour: every box that shares now sends, where before none did. Fredrik's call per the description, so I'm only marking it.
- CI:
webis red on "carries none of the old fixed chart hues", which none of the files here touch (fleet.jsonly changes strings).go test + vetis the aggregate gate failing because of that. Worth checking whether it's red on main too. - Order: ftw-cloud#61 must be deployed before a beta carries this, as you note (404 = a lost day).
Go side is safe from my read; merge waits on the red web check and the privacy sign-off above.
Problem
stats.ftw.energy shows no energy. The daily energy report (
go/internal/energyreport) may only leave through an independent OHTTP relay, andstatsrelay.RelayURLandGatewayKeyare empty. So no box has ever sent one. The fleet report had the same problem until #1989 (8 November): every box that shares now sends it straight to/v1/fleet.Fredrik decided on 12 November 2026 that the energy report does the same.
Change
statsrelay.Default()is the pinned relay when this build has one, and otherwise a direct client forstatsrelay.DirectURL(https://cloud.ftw.energy/v1/energy, a compile-time var likeRelayURL).reportwire.Request, 1,536 bytes) unsealed, asmessage/bhttp, and believes only a 204. Same random id per report, same UTC send day, no retry, no redirect.energyreportusesDefault(). Nothing else about it changes: the same one statistics answer, the same partner rule, the same 1–12 hour window after the day closes, a day with a gap still skipped.endpoint;relaystays the relay only. Settings → FTW app → Anonymous statistics says the report goes straight to FTW Cloud, that Cloud sees the address while the request is open, and that it keeps neither the address nor the report.docs/architecture.mdanddocs/protocol-cloud.mdsay the same in a line.Once a release pins a relay, both reports go through it, as before.
Pair
POST /v1/energy. Merge and deploy it before a beta carries this. Before that deploy the box gets a 404 and loses that day; nothing else breaks.Changeset
minor: boxes start sending a report they did not send before, which owners see in Settings. Fredrik approves a minor in the PR.Evidence
New tests:
TestWithoutARelayAReportGoesStraightToFTWCloud(default goes to/v1/energywith no relay pinned; body padded to 1,536 bytes;message/bhttp; a 400, a plain 200 and a redirect all count as failed),TestWithoutARelayTheReportGoesStraightToFTWCloud(box to fake Cloud, the day is remembered) and the settings line tests.make verifypasses locally. The first run hit a port clash ingo/internal/ocpp(TestUnsupportedBootTriggerLeavesIdentityUnknown, "address already in use"), a package this PR does not touch; it passed three times alone and the second full run was green.The Settings line was checked in a browser: the real
web/settings/tabs/fleet.jsrendered with a stubbed/api/fleet-ping, showing "Sent straight to FTW Cloud at https://cloud.ftw.energy/v1/energy, once a day, 1 to 12 hours after the UTC day ends."🤖 Generated with Claude Code