Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
enaboapps
marked this pull request as ready for review
October 28, 2026 13:16
6 tasks
An install that was already expired at launch treated the first tick as a fresh expiry, so every start ran the platform disconnect-all (forcing Bluetooth to Advertising while the adapter may still be initialising) and raised the settings window, including hidden login starts. Seed the observer from the current state so cleanup only runs on a real change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The home notice rendered the licence message on every screen whenever licensing was configured, so paid users saw a permanent licence banner. Limit it to trial, expired and unavailable states. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The paragraph about pausing automatic button scanning had landed under the credits section after the word-prediction note. Move it next to the recovery mode description it belongs to. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
allowed() ran a full Ed25519 verification and JSON parse on every scanning tick, switch action and dispatch. Cache the deadline computed by view(), which already runs at launch, once a second from publish, and after a key is redeemed or removed, and read the cached value instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The one-minute last-seen checkpoint wrote the keychain record for the life of the app. The file alone carries the clock-rollback guard, so keep the checkpoint on the file and refresh the keychain mirror only at launch and when a key is entered or removed. A keychain warning now stays visible until the next keychain write succeeds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A first run with no licence file and an unavailable keychain produced no record, which locked the app with a request to unlock the keychain and restart. Nothing readable says the trial already ran, so start it and keep the storage warning. The next launch with the keychain available reconciles to the earliest recorded first run, so an older trial still wins. An unreadable file still fails closed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Independent review follow-ups: the per-minute checkpoint retries the keychain write only while a storage warning is set, so a keychain that was locked at launch heals without a relaunch; the cached access deadline starts closed until open() seeds it; tests cover an unreadable file with an intact keychain record and the file-only save path; the operations doc states the fresh-trial path when the keychain record is unreadable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The checkpoint heal wrote this session's record over whatever the keychain already held, so a trial started while the keychain was locked could replace an earlier trial or a newer removal once it unlocked. Read and merge the keychain record first. Failed keychain retries now back off from one minute to about an hour so a locked macOS keychain is not prompted every minute. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A checkpoint minute that skipped the keychain retry still cleared the storage warning and reset the backoff, so a locked keychain was retried once and then never healed. Factor the checkpoint transition into a pure helper on Data: a file failure sets the warning, a keychain failure schedules the next retry, and only a successful keychain retry clears the warning. A test walks the backoff schedule. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Redeeming or removing a key set the storage warning directly and left any scheduled keychain retry in place, so a later file-write warning could linger for up to an hour. Route both through the checkpoint transition so a successful keychain write clears the backoff. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch was successfully deployed
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.
Adds separate local/keychain trial and licence records, a 30-day trial for licensing-enabled builds, Settings → Licence entry/import/removal, paste-and-activate, and local-switch recovery confined to the licence page. Rust gates local scanning, dwell clicking and authenticated Android input while preserving pairing, account and settings access. Expiry cleans up active input and updates tray/status messages. Public issuer configuration is supplied at build time; production signing secrets are never embedded.
Closes #1230. Part of #1217. Parent PR: #1229; this PR targets its feature branch and must be retargeted after that parent merges.
Validation: Node.js 24 / Rust 1.97.1; npm lint, npm test (316 UI + 21 Node tests), npm build, docs-site build, cargo fmt/clippy and cargo test (850 unit + 8 integration passed; 4 environment-dependent ignored). Native hardware, paid build configuration and real switch recovery still need manual validation before shipping.
Independent review: no remaining actionable findings at latest head
95060e9639d9de0f23051ad3d1849da2433a9b14. Expiry cleanup observations run only on the main thread; authenticated release-only commands remain available; manual focus/input pauses automatic recovery scanning without losing the key draft.Final CI: all applicable checks passed at
95060e9639d9de0f23051ad3d1849da2433a9b14, including macOS app/DMG, Windows NSIS installer/package verification, packaged prediction/neural checks, frontend tests/build and dependency audit. Feature remains unmerged and production deployment is out of scope for this PR.Review follow-up (head
e3e2120c)Independent review of the stack found no issues in #1229 and the following in this PR, each fixed in its own commit: launch-time expiry cleanup ran on every start of an expired install (window raised on hidden login starts, Bluetooth state forced to Advertising); the home licence notice stayed visible for licensed users; the recovery-scanning docs paragraph had landed under credits; "1 days left";
allowed()re-verified the signature on every scanning tick (now reads a cached deadline refreshed byview()); the per-minute checkpoint rewrote the keychain for the life of the app (now file-only, retrying the keychain only while a storage warning is set); a fresh install with an unavailable keychain locked instead of starting its trial;build.rsdeclaresrerun-if-env-changedfor the public key configuration.A second independent review of the fixes raised four hardening points, addressed in
74496dcd,9ae08a34,913bbb67ande3e2120c: keychain self-heal on checkpoint (merging the stored keychain record first, with exponential backoff while the keychain stays locked), access cache starts closed until seeded, two more tests, and a plain statement of the fresh-trial path indocs/licensing.md.Validation at
e3e2120con Windows: npm lint, npm test (317 UI + 21 Node), npm build, docs site build, cargo fmt --check, cargo clippy -D warnings, cargo test (861 unit + 8 integration passed; 5 environment-dependent ignored).