Repository navigation
Require sign-in to start the desktop trial - #94
Open
leoisadev1 wants to merge 4 commits into
Open
leoisadev1 wants to merge 4 commits into
leoisadev1 wants to merge 4 commits into
Conversation
leoisadev1
force-pushed
the
cnv-56-sign-in-trial
branch
from
October 7, 2026 21:45
b549197 to
3f51e5c
Compare
|
leoisadev1
force-pushed
the
cnv-56-sign-in-trial
branch
2 times, most recently
from
October 7, 2026 22:47
f6dc9fe to
95863d9
Compare
Adds the trials table, POST /api/device/trial and a currentKey RPC that returns a Desktop or Pro key, or a trial key while Pro is trialing. A computer counts as used once any account's trial reached it, and the server keeps only a keyed hash of the app's device hash.
Trial keys expire by today's date and live apart from bought keys, so a trial never replaces one. An old trial file is carried over once, a clock set back pauses the trial until an online check, and packaged builds ignore folder overrides for licensing state.
leoisadev1
force-pushed
the
cnv-56-sign-in-trial
branch
from
October 7, 2026 23:06
95863d9 to
66156a0
Compare
This branch has not been 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.
Summary
The desktop trial needed no account and lived in a date file, so deleting the file, pointing
CONVT_DATA_DIRsomewhere new or adding an OS user gave a fresh trial. Now "Start 7-day trial" signs in through the browser, and convt-billing hands the app a signed trial key: one trial per account and one per computer, checked offline against today's date. Sign-in also installs a Desktop key the account bought, and a Pro subscription in its trial unlocks the app.sequenceDiagram participant App as convt app participant Web as convt.app (web) participant Billing as convt-billing App->>Web: browser sign-in (existing PKCE flow) → device token App->>Web: POST /api/device/license Web->>Billing: currentKey(user) Billing-->>App: Desktop/Pro key, a trial key while Pro is trialing, or null App->>Web: POST /api/device/trial {device_hash} (only if no key converts) Web->>Web: HMAC(DEVICE_HASH_SECRET, device_hash) Web->>Billing: startTrial(user, stored hash) Billing-->>App: plan "trial" key, or 409 device_usedtrialplan in the existing Ed25519 format.updates_untilis the last trial day, judged by today, never by build date. Shipped builds rejectplan:"trial"as malformed, so a trial key can't act as a paid key anywhere, and pasting one is refused.trial_key, filetrial.key), apart fromlicense.key. A trial never replaces a bought key; a key the build has outgrown still runs the older builds it covers, offline, and shows again when the trial ends./api/device/licensesends Desktop and trial keys only to apps that sendaccepts: ["desktop","pro","trial"]. Apps from before this change keep getting the account's Pro key, as they expect.trialing, the app gets a trial key that works through the UTC day the Pro trial ends (an end at exactly midnight keeps the day before), capped at 31 days.trialfile is carried over once with its remaining days, then never read again. Any start up to today counts.CONVT_DATA_DIR,CONVT_CONFIG_DIRandCONVT_LICENSE_STOREfor licensing.Evidence
The "Signed in as" line is blanked in the two green shots so no account name appears. The soft-block shot is from the current head, against a local stub of the device API; Contact us opened
https://convt.app/contact.End to end, with a source build (
CONVT_LICENSE_ENFORCE=1) under Xvfb, this checkout'sdev:web, convt-billing, Postgres and a headless browser sign-in with the seeded test accounts:Free trial: 7 days left.; onetrialsrow; stored hash = HMAC(secret, sent hash)trialsrowconvt license activatestill worksFree trial: 4 days left.; a real PNG→JPEG conversionlast-seen3 days aheadtrialfile from 2 days ago5 days left; file removed; a rewritten file grants nothingThat run predates the later review fixes below; those are covered by the tests.
Tests, all passing on the current head:
cargo test(default members),cargo test -p convt-app(130),cargo test -p convt-license --features client(43 + 3 vectors, including the TS-signed trial vector),bun run rs:checkbun run db:ci(no drift, down file reverses, grants),packages/billingintegration (110; 13 trial tests: one per account, one per computer including one that got another account's trial back, expiry, 6-way races, account deletion,currentKeyrules including an outgrown Desktop key next to a Pro trial and the Pro trial's last day),apps/webunit (121) and integration (60),packages/license(20)bun run check && bun run check-types && bun run build/licenserequest gets no Desktop key; the app sendsaccepts; Start shows next to an outgrown keyNot checked: the macOS Keychain, the Windows Credential Manager and the sandboxed Finder extension (no Linux test path); a packaged build (the
Config::resolvedecision is unit-tested instead). There is notrial_started/trial_expiredtelemetry on main (CNV-55), so none fires.Review: an independent GPT-6.1 Sol review ran four rounds and ended at SHIP. Devin and Greptile findings since then are fixed: a failed key check no longer spends the trial; Start checks for a bought key even when signed in; a trial no longer overwrites a bought key; a computer that got an account's trial back counts as used; the Pro trial key works through the day the Pro trial ends; a legacy trial started after this build's date still carries over; an unreadable credential store can't erase carried-over days; the
#[cfg(unix)]guard is back on the permissions test; older apps keep getting Pro keys from/license; a key another client stored is picked up when renewal keeps it; and the License tab offers Start 7-day trial when a bought key no longer covers this build. Not changed, by design: a client can send any device hash (a soft deterrent in AGPL software), and a successful reply's server time may lowerlast_seenso a clock that once ran ahead can recover.Merge Danger
Door: one-way. Migration
0006_desktop_trialadds thetrialstable anddevices.device_hashand grants convt_billingselect (user_id, device_hash)ondevices(additive; production is forward-only), and released builds will refuse to convert until a user signs in.Blast radius: every packaged desktop and CLI user without a paid key, plus Desktop and Pro renewal. Paid keys still verify offline as before; a user mid-trial keeps their days.
Before deploying, Leo needs to:
DEVICE_HASH_SECRETonconvt-web(wrangler secret put DEVICE_HASH_SECRET, 32+ random characters, e.g.openssl rand -base64 48). Never rotate it once trials exist, or every computer can start a trial again. Until it is set,/api/device/trialanswers 503.bun run db:migrateagainst production, then convt-billing (newstartTrialandcurrentKeyRPCs;currentProKeystays), then convt-web./api/device/trial.trials.user_idis set to null when an account is deleted, so the computer still counts as having had its trial; the row keeps only the keyed hash and dates. A user on a headless machine with only the CLI can't start a trial and needs a paid key.Before release, the terms and privacy pages (owned by #85 and #82) still describe the old trial and need this wording:
Do not merge until
DEVICE_HASH_SECRETis set and the deploy order above is followed.Fixes CNV-56
Created with Claude Opus 5.5 in T3 Code.