feat: the heartbeat response carries what the worker's platforms earned - #242
Conversation
MkDocs builds every file in docs_dir whether or not it appears in nav, so three agent scratch files were live on the public site despite being in no menu: https://geiserx.github.io/CashPilot/GOAL/ -> HTTP 200 https://geiserx.github.io/CashPilot/AUTOPILOT-WORKLOG/ -> HTTP 200 Between them they published this project's internal planning verbatim, quoted the maintainer directly, and printed a real Mysterium node identity address, which links this public repository to a specific earning node. `mkdocs build --strict` does NOT catch this. validation.nav.omitted_files defaults to `info` and --strict only promotes `warn` to an error, so the orphans are reported and the build stays green. Exclusion has to be explicit. Verified by building the site: 64 pages, all three excluded, homepage and guides intact. Removing the block makes all three reappear.
Excluding them from the built site stopped the publication; it left them tracked, so the next agent run would commit fresh content straight back into a public repository. docs/GOAL.md and docs/AUTOPILOT-WORKLOG.md are now untracked (kept on disk) and all three are gitignored. The guard covers both directions: excluded from the site AND absent from the index. NOTE, and it is not solved by this commit: both files have been tracked since e631e3a, so their content -- including a real Mysterium node identity address -- is in this public repository's HISTORY. Untracking stops it growing. Removing what is already there needs a history rewrite, which is the maintainer's call.
The Android client is named CashPilot and shows no money at all -- grep for earning|balance|payout across its source returns nothing. It makes exactly one HTTP call, POST /api/workers/heartbeat, and never reads anything back. It cannot simply call an earnings endpoint: every one of them goes through _require_auth_api, which needs a user session. A per-worker key cannot read any of them, and handing a phone an owner-level credential so it can render a number would be a bad trade. So the figures ride back on the one call the worker is already authenticated for. THE HONESTY CONSTRAINT SHAPES THE PAYLOAD. Earnings are collected per PLATFORM from the provider's account and cannot be attributed to a device: if two machines run Grass, the provider reports one balance and nothing can split it. The response therefore never claims a device earned anything. It reports what the platforms on that device earned, and flags every platform running on more than one worker so a client can say so too. Absent stays absent. A platform with no reading is null, never 0.0; the total sums only what is known and is null when nothing is; and the whole key is OMITTED rather than sent empty, so a client can tell unknown from nothing. A database failure returns None rather than raising -- the heartbeat is how a fleet stays alive and must never fail on a display nicety.
|
Warning Review limit reached
Next review available in: 14 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #242 +/- ##
=======================================
Coverage 95.39% 95.40%
=======================================
Files 47 47
Lines 6127 6155 +28
=======================================
+ Hits 5845 5872 +27
- Misses 282 283 +1
🚀 New features to boost your workflow:
|
…ed (#242) * fix: stop publishing agent working files on the public docs site MkDocs builds every file in docs_dir whether or not it appears in nav, so three agent scratch files were live on the public site despite being in no menu: https://geiserx.github.io/CashPilot/GOAL/ -> HTTP 200 https://geiserx.github.io/CashPilot/AUTOPILOT-WORKLOG/ -> HTTP 200 Between them they published this project's internal planning verbatim, quoted the maintainer directly, and printed a real Mysterium node identity address, which links this public repository to a specific earning node. `mkdocs build --strict` does NOT catch this. validation.nav.omitted_files defaults to `info` and --strict only promotes `warn` to an error, so the orphans are reported and the build stays green. Exclusion has to be explicit. Verified by building the site: 64 pages, all three excluded, homepage and guides intact. Removing the block makes all three reappear. * fix: never commit the agent working files either Excluding them from the built site stopped the publication; it left them tracked, so the next agent run would commit fresh content straight back into a public repository. docs/GOAL.md and docs/AUTOPILOT-WORKLOG.md are now untracked (kept on disk) and all three are gitignored. The guard covers both directions: excluded from the site AND absent from the index. NOTE, and it is not solved by this commit: both files have been tracked since 607b19b, so their content -- including a real Mysterium node identity address -- is in this public repository's HISTORY. Untracking stops it growing. Removing what is already there needs a history rewrite, which is the maintainer's call. * feat: the heartbeat response carries what the worker's platforms earned The Android client is named CashPilot and shows no money at all -- grep for earning|balance|payout across its source returns nothing. It makes exactly one HTTP call, POST /api/workers/heartbeat, and never reads anything back. It cannot simply call an earnings endpoint: every one of them goes through _require_auth_api, which needs a user session. A per-worker key cannot read any of them, and handing a phone an owner-level credential so it can render a number would be a bad trade. So the figures ride back on the one call the worker is already authenticated for. THE HONESTY CONSTRAINT SHAPES THE PAYLOAD. Earnings are collected per PLATFORM from the provider's account and cannot be attributed to a device: if two machines run Grass, the provider reports one balance and nothing can split it. The response therefore never claims a device earned anything. It reports what the platforms on that device earned, and flags every platform running on more than one worker so a client can say so too. Absent stays absent. A platform with no reading is null, never 0.0; the total sums only what is known and is null when nothing is; and the whole key is OMITTED rather than sent empty, so a client can tell unknown from nothing. A database failure returns None rather than raising -- the heartbeat is how a fleet stays alive and must never fail on a display nicety.
Server half of
CashPilot-android-35t(P1). The client half follows in the Android repo.The problem
The Android app is called CashPilot and shows no money at all.
grep -riE "earning|balance|payout"across its source returns nothing. It makes exactly one HTTP call —POST /api/workers/heartbeat— and never reads anything back.It can't just call an earnings endpoint. Every one goes through
_require_auth_api, which requires a user session; a per-worker key reads none of them. The alternative — giving a phone an owner-level credential so it can render a number — is a bad trade.So the figures ride back on the one call the worker is already authenticated for. No new credential, no new auth model, and the phone already polls.
The honesty constraint, which shaped the payload
Earnings are collected per platform, from the provider's account. They cannot be attributed to a device: if two machines both run Grass, the provider reports one balance and nothing can split it.
So this never says "this device earned X." It says "the platforms this device is running earned X on your account", and flags every platform running on more than one worker:
Three deliberate choices, each with a control proving it:
null, never0.0. Absent means nothing was ever collected — usually no collector, or credentials never entered.nullwhen nothing is. A total that treats unknown as zero is the same lie in aggregate.{}— so a client can tell unknown from nothing earned.A database failure returns
Nonerather than raising. The heartbeat is how a fleet stays alive; it must never fail over a display nicety.Evidence
15 tests. Five negative controls, all caught — and they target the honesty properties specifically, because those are the ones a well-meaning future edit would quietly remove:
0.0There is also a test asserting no key in the payload contains "device" — a guard against someone later adding a
device_usdfield that would be a fabrication by construction.Source verified byte-identical after every revert.
Gates:
ruffclean, all four browser-free harnesses PASS, 3308 passed, 95.44% coverage.