Monkey 1.2: daily-budget evolution stages, Telegram remote control, signed auto-updates, screensaver fixes, grace-period cap - #5
Merged
Conversation
Two bots, strictly separated: Monkey's bot can only ask /status, the friend's bot can also top up time, pause and resume - from anywhere, without the master password ever leaving the PC. The relay is a single Cloudflare Worker (cloud/worker.js) each user deploys into their own free account; the repository ships no credentials. The service reports its state every 30 seconds (and on every change and at shutdown) and picks up queued commands. Because the daily top-up is fully predictable, the worker answers exactly even while the PC is off, and the friend's commands wait in a queue until the next start. Security: the PC authenticates to the worker with a generated sync secret (stored DPAPI-encrypted on the PC, as a secret on the worker); Telegram webhooks carry per-bot secret tokens; chats must pair once via a one-time code (hashed at rest, 5 tries, 10 minutes). Bot tokens pass through the PC once during setup and are kept only by the worker. Remote commands are limited to add/pause/resume, are re-validated by the service and deduplicated against replays. The control panel gains a General/Telegram tab switch; everything stays off until configured. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XNyzACDtEMNqWXFdeeHSE
The service checks the project's latest release every six hours and installs a newer version by itself. No master password is involved, because the mechanism can only move one way: every release carries an update.json manifest signed with the project's ECDSA P-256 update key, and the matching public key is baked into the installed service. No valid signature, no update - so not even someone who controls the network (or plants a root certificate) can feed the guard a doctored 'new version', which would otherwise be the cheapest bypass of the whole tool. Only strictly newer versions are accepted (no downgrade replays), the installer is staged in the SYSTEM-only data folder and checked against the signed hash before it runs. The new installer gains a silent 'update' mode that just swaps the program files: watchdog paused, service stopped, old binaries renamed aside, new ones extracted, service restarted. Balance, password and settings stay untouched. A still-running agent keeps working from the renamed file and restarts itself once it sees the new service version (guarded against restart loops by comparing with the file on disk). Auto-update ships enabled and can be turned off in the settings. Dormant until a maintainer generates a key (tools/new-update-key.ps1), commits the public half and stores the private half as the GitHub Actions secret UPDATE_SIGNING_KEY - the release workflow then signs every release automatically. The repository itself stays free of any secrets. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XNyzACDtEMNqWXFdeeHSE
The clock only paused when Windows itself had started the screensaver - SPI_GETSCREENSAVERRUNNING is the sole signal the agent checked. Two real-world cases slipped through: a screensaver launched by hand (shortcut or hotkey running a .scr directly) never sets that flag, and modern Windows often runs no screensaver at all but simply switches the display off. In both cases the timer kept eating the balance. Detection now has three layers in the agent: the official query, the 'Screen-saver' desktop Windows creates for system-started savers (its mere existence - even access-denied - means one is running), and the foreground window's process image ending in .scr for manual launches. On top of that the agent subscribes to GUID_CONSOLE_DISPLAY_STATE power notifications and reports 'display off' in its heartbeat; the service treats that like a running screensaver under the same setting, and the agent syncs immediately on the on/off edge instead of waiting for the next two-second tick. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XNyzACDtEMNqWXFdeeHSE
The emergency window after signing in with an empty balance (120 s by default) could be milked: sign out, sign back in, collect another two minutes, repeat forever. The ordinary 90-second grace had the same hole via lock/unlock, since leaving the session resets the running grace and returning started a fresh one. The service now counts every grace it grants while the balance is empty - persisted immediately, so a hard reboot doesn't forget it. The first three come in full length; from the fourth on there are only ten seconds before sign-out, enough to see it coming and nothing more. As soon as the balance is positive again (daily allowance, master password, or a friend's Telegram top-up) the counter drops back to zero and the emergency window works normally again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XNyzACDtEMNqWXFdeeHSE
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XNyzACDtEMNqWXFdeeHSE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's in here
Monkey evolution now follows the daily allowance. The stage picture was tied to fifths of the balance cap, so days of genuine saving often changed nothing on screen. Now each stage is one saved daily allowance: one day's grant is the small monkey, two saved allowances the second picture, up to stage 5 at five. Manual top-ups still reset the savings — only time from daily grants grows the monkey.
Optional Telegram remote control — works even while the PC is off. Two bots, strictly separated: Monkey's bot answers
/status; the friend's bot can also/add,/pauseand/resumefrom anywhere, without the master password ever leaving the PC. The relay is a single Cloudflare Worker (cloud/worker.js) each user deploys into their own free account — the repository ships no credentials. The worker projects the balance exactly while the PC is off (daily accrual is deterministic) and queues the friend's commands until the next start. Every path is authenticated: sync secret (DPAPI-encrypted at rest) for the PC, per-bot webhook secrets for Telegram, one-time pairing codes (hashed, 5 tries, 10 minutes) for chats. Remote commands are limited to add/pause/resume, re-validated by the service, and deduplicated against replays. New General/Telegram tab switch in the control panel.Self-update from signed releases — no password, no reinstall. The service checks the latest GitHub release every six hours and installs newer versions by itself. Safe without a password because it only moves one way: each release carries an
update.jsonmanifest signed with the project's ECDSA P-256 key (public half baked into the service), so not even a network-controlling admin can feed the guard a doctored build; downgrades are rejected. The installer gains a silentupdatemode that swaps binaries and restarts the service; balance, password and settings survive untouched, and a running agent restarts itself once it sees the new service version. Dormant until a maintainer runstools/new-update-key.ps1, commits the public key and stores the private half as theUPDATE_SIGNING_KEYActions secret — the release workflow then signs every release automatically.Screensaver detection fixed. The clock kept running for manually launched screensavers (a
.scrstarted via shortcut/hotkey never sets the system flag) and when modern Windows simply switches the display off instead of running a saver. Detection now has three layers (official query,Screen-saverdesktop probe, foreground.scrprocess) plus display-off tracking viaGUID_CONSOLE_DISPLAY_STATEpower notifications, all under the existing pause setting.Empty-balance grace periods capped. The 120-second emergency window after signing in with an empty balance could be milked by signing in repeatedly — and the ordinary 90-second grace had the same hole via lock/unlock. Every grace granted while the balance is empty is now counted (persisted immediately, so a hard reboot doesn't forget): three come in full length, from the fourth on it's 10 seconds to sign-out. Any top-up resets the counter, so the emergency window keeps serving its real purpose.
Version bumped to 1.2.0.
Notes for review
🤖 Generated with Claude Code
https://claude.ai/code/session_012XNyzACDtEMNqWXFdeeHSE
Generated by Claude Code