Repository navigation
Sell Switchify PC: licence keys, 30-day trial, locked state #1217
Description
Switchify PC becomes a paid product. A deal requires PC to be a purchase, with keys the partner can hand out. Commercial terms retained; activation policy updated with owner approval on 2026-10-31:
- €100 (EUR) one-time purchase per computer.
- Unpaid installs get a full trial for a 30 days, then scanning and mobile control lock until a key is entered. Settings, Account and the licence page stay usable.
- Internet is required for first activation on one computer. No Switchify account is required. The app checks at launch and daily while running; each successful check grants up to 30 days offline. A verified refund/dispute revocation stops access on the next successful check. Network failures preserve the existing signed allowance until expiry. Warn at 7, 3 and 1 days remaining. Explicit transfers may replace a computer, capped at two takeovers per rolling 30 days.
- Purchase channels: registered partner batch credentials and Stripe checkout, both using the existing signed purchase-key format. Purchase keys are reusable credentials; they cannot grant paid access without a device-bound signed allowance in the shipping build. No live checkout or v1.4.0 release until coordinated activation/fulfilment and native checks are proven.
Scoped work (one PR each, stacked where dependent):
- Key format and offline verifier in Rust (Ed25519 signature over a canonical payload: licence id, product, issued date, optional expiry, seat count), with public key embedded and compatibility tests.
- Offline key generator tool under
tools/licence-keygenthat writes batches to CSV; private key never in the repo. - Trial and licence state: first-run date and redeemed key stored in app data and the keyring, reported in
AppState, with a locked reason the scanning runtime and the Android control path both honour. - Licence page in Settings: trial days left, enter key, status, remove key. Tray and status wording.
- The original offline-only policy is superseded by the approved online-activation work below. Historical sandbox/dev builds used perpetual SWPC1-only access; do not ship that access path as the paid release.
- Docs site and website: replace "free and open source" and "PC control comes free" wording with pricing, trial and key instructions; licence page keeps AGPL notice.
- Partner handover: how to generate and deliver a batch, how to revoke.
Implementation PRs (reviewed; boxes above stay open until merged):
- Define offline licence keys and partner batch generator #1229: signed key format, Rust verifier and offline batch issuer (issue Define offline licence keys and partner batch generator #1228).
- Add offline trial, licence entry and Rust access enforcement #1231: trial, storage, licence UI, gated input, recovery and docs (issue Add offline trial, licence entry and Rust access enforcement #1230); stacked on Define offline licence keys and partner batch generator #1229.
- switchifyapp/switchify-supabase#9: Stripe verified purchase ledger and retryable email outbox (backend issue switchifyapp/switchify-supabase#8).
The parent-feature-branch contributor rule was merged first in #1227, before these implementation branches were created.
Before selling: configure and back up the production signing key; trust only its public key in the paid desktop build; choose/verify a transactional email sender; run the full local Supabase pgTAP suite and sandbox purchase-to-offline-activation flow; manually validate native switch recovery/expiry on both platforms; confirm Stripe identity review is complete. The code and PRs do not deploy services or publish checkout.
Still to confirm separately: whether the partner needs a multi-computer site licence and the Certum certificate product. The project remains AGPL.
Progress 2026-10-30: #1229 and #1231 merged (PC main 208c16a); switchify-supabase#9, #11 and #13 merged, migrations applied and both functions deployed to production with the signing key, test mode and the delivery scheduler configured. Production issuer pc-2026-1 is set as the PC release build's trust anchor. Remaining before selling: Stripe price, webhook and identity review; Resend sender and key; sandbox purchase-to-offline-activation proof; native device checks; website and docs wording with the checkout link.
Approved activation work (2026-10-31), all on v1.4.0:
- switchifyapp/switchify-supabase#16 — private installation, replay and transfer ledger (PR switchifyapp/switchify-supabase#18).
- switchifyapp/switchify-supabase#17 — signed activation service and bounded offline leases (PR switchifyapp/switchify-supabase#19, stacked on chore: add Windows packaging and smoke checklist #18).
- Verify device-bound signed licence leases and terminal responses #1238 — Rust lease/status verifier and shared compatibility fixture (PR Verify signed device licence allowances and terminal replies #1240).
- Activate one computer and renew a 30-day offline licence allowance #1239 — installation identity, record migration, renewal, input cleanup/recovery UI and site/privacy wording (PR Activate one computer and renew a 30-day offline allowance #1241, stacked on Verify signed device licence allowances and terminal replies #1240).
- Coordinated TEST backend deployment: activation migrations, separate protected lease signer, activation endpoint and updated delivery email.
- Deployed sandbox service proof: purchase, delivery outbox sent, activation, renewal, replay, seat conflict, two transfers and limit, deactivation, full refund and verified signed revocation.
- Installed Windows/Parallels activation, outage and offline relaunch proof; developer test build is ready, but guest UI input is blocked.
- Native Keychain locked/unavailable checks; held-switch expiry and recovery with physical hardware (pending: owner confirms no switch available).
- Live Stripe scoped key, one-off EUR 100 price and exact four-event webhook configured; Supabase fulfilment switched to live.
- Confirm live Stripe identity/compliance readiness and final rollout gates, then enable the paused live Payment Link.
- Use the configured live licence checkout #1245 merged for the live app URL, exact opener scope and PC licence guide.
- Finish website marketing buy link/wording.
Release remains HELD by owner. No version bump, tag or RC. No merge of these activation PRs without a new explicit merge instruction. Back up pc-2026-1-signing.pem from the physical Windows PC; any new lease signer also needs protected backup.
- Move native CI off the retiring macOS 14 runner #1242 / PR Move native CI to the supported macOS 15 runner #1243 — migrate native CI execution to macOS 15 ARM64 after the scheduled macOS 14 brownout; retain required check names. Infrastructure parent of Verify signed device licence allowances and terminal replies #1240 → Activate one computer and renew a 30-day offline allowance #1241.
Owner authorized merge and pull of the activation stack on 2026-10-31. CI prerequisite #1243 and backend ledger switchifyapp/switchify-supabase#18 merged. Child PRs are rebased onto main and awaiting fresh CI; no deployment, version bump, tag or release is authorized.
Backend activation PRs #18/#19 are merged and switchify-supabase main pulled at a0fe956. PC CI prerequisite #1243 is merged and PC main pulled at b5f3c54. PC #1240 is rebased to main at 0c4cc99, independently reviewed with unchanged tree, awaiting fresh native CI; owner authorization to merge #1240 then rebase/merge #1241 remains active. No production deployment or release.
PC verifier #1240 merged at 3aff7dc. Final app integration #1241 is rebased onto main at ecc7c38, independently reviewed with no findings and an unchanged tree, waiting for its fresh native CI before the already-authorized merge and pull. Production deployment and v1.4.0 release remain held.
Merge/pull complete 2026-10-31: backend #18/#19 and PC #1243/#1240/#1241 merged in dependency order after required CI and independent latest-head review. Clean local main matches origin/main in both repositories: PC 8b73c66, backend a0fe956. Package version remains 1.3.0; v1.4.0 remains HELD. No activation deployment, production migration, version bump, tag or release was performed. Still pending: lease signer configuration/coordinated TEST deployment, installed-app sandbox/native Keychain and hardware checks, live Stripe configuration, website buy link and final go-live documentation.
TEST rollout 2026-10-31: owner authorized final deployment/test steps. Applied migrations 20261031140000/20261031141000; activation function v1 and delivery v7 active. Fresh Sandbox checkout produced one licence/one sent delivery; full EUR 100 test refund succeeded and ledger revoked. Verified deployed outcomes: licensed, replay, seat_taken, deactivated, takeover_limited, revoked. New Windows developer test executable built successfully from PC main 8b73c66 with both public-key maps. Parallels view refresh restored the current desktop image but guest clicks/keys still have no effect; the previous app remains running, so new-build activation/offline relaunch and credential-store checks stay pending. Latest inbox/provider delivery confirmation and exact new function log lines also remain pending (existing read token lacks log access). Physical hardware checks remain pending by owner instruction. Release remains HELD; Stripe remains TEST. Both main worktrees remain clean. Back up both the original purchase signer on physical Windows and the separate lease signer on this Mac.
Live setup 2026-10-31 (owner explicitly authorized): scoped live key created with approval and saved securely; reused existing live product/price/link, promotions off; configured four-event live webhook and switched Supabase fulfilment secrets to live without redeployment. Invalid signature rejected; signed non-purchase probe acknowledged and logged ignored. No real payment or licence issued. Live Payment Link is PAUSED pending the held release; old test link/webhook paused to avoid test purchases against the live handler. App/docs PR #1245 targets main on v1.4.0, independent latest-head review passed and all local checks passed; CI running, no merge instruction for this new PR. Native/hardware, live account readiness, marketing website and release gates remain open. Back up both signing keys from their respective machines.
Additional rollout evidence: signed-in dashboards now confirm the 16:08:51 sandbox checkout.session.completed: issued log, 16:09:01 worker sent 1, and Resend Delivered at 16:09 for the latest licence email, including the .licence attachment and online-activation/30-day allowance wording. This resolves the earlier provider-status and exact-function-log evidence gaps; native checks are still pending.
Owner-authorized merge/pull complete: #1245 merged after all required CI and independent review; clean local PC main matches origin/main at ca21459. Issue #1244 closed on v1.4.0. Release remains HELD and the live Payment Link stays paused; no version bump, tag, RC or release. Native/hardware and remaining go-live gates keep this epic open.
Readiness fixes requested 2026-10-31 (not yet merged):
- Bind cached licences to the OS installation and harden offline rollback handling #1246 / PR Bind cached licences to OS credentials and harden offline rollback #1248 — bind cached paid access to the actual OS installation credential; authenticate checkpoints, preserve newer paid-time watermarks, use monotonic running time and mirror terminal states. Independent review and all five required CI checks passed on 73e2b4d; ready and unmerged.
- Distinguish unverifiable activation requests from network failures #1247 / PR Fix guidance for unverifiable licence activation requests #1249 — distinguish unverifiable activation requests from outages without changing the existing allowance; stacked on Bind cached licences to OS credentials and harden offline rollback #1248. All local checks, independent review and all eight CI checks passed on a8f440d; ready and unmerged.
Threat-model limits are documented in docs/licensing-cache.md: an offline client cannot guarantee time across full OS credential-store/file/clock restoration or durable revocation when every persistence store fails. Installed-app and physical-switch acceptance remains pending. Release remains held and live checkout paused.
Owner-authorized merge/pull 2026-10-31: #1248 merged at a3b9744 and pulled into clean local main. #1249 rebased/retargeted to main at 94b5662 with unchanged tree and fresh independent review passed; awaiting refreshed CI before its authorized merge/pull. Release held and checkout paused.
Merge/pull complete 2026-10-31: #1248 and #1249 merged in dependency order after independent latest-head review and required CI. Clean local main matches origin/main at 62c11e4. Issues #1246/#1247 closed on v1.4.0. No version bump, tag, RC, release, deployment or checkout change. Native acceptance and remaining go-live gates keep this epic open.
macOS Parallels acceptance started 2026-10-31 on main 62c11e4 with signed development bundle and validated production public build configuration. PASS: offline trial startup shows 30 days on Home and Licence page; offline process restart retains the same trial first_run. PARTIAL: denied native Keychain prompt and app/settings stayed usable; mirror healing awaits owner unlocking the guest login Keychain. Paid activation/offline restart remains pending because earlier sandbox purchases were refunded. Guest network and saved switch settings restored. This is VM development-build evidence, not release-artifact or physical-hardware acceptance. Release held; checkout paused.
Activity