Skip to content

feat(linux): TablePro accounts and usage data - #4053

Merged
datlechin merged 20 commits into
mainfrom
feat/linux-licensing
Nov 6, 2026
Merged

datlechin merged 20 commits into
mainfrom
feat/linux-licensing

Conversation

@datlechin

@datlechin datlechin commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Summary

  • core/crates/account (tablepro-account): TablePro accounts over /v2, as tablepro-cloud's docs/design/clients.md specifies for Linux and macOS has them since feat(account): TablePro accounts replace license keys on macOS (M16) #4045. OAuth with PKCE and a 127.0.0.1:0 loopback redirect, the progenitor /v2 client from the vendored document, Ed25519 entitlement checks against the vendored vectors, the Shared-rules refresh schedule, POST /v2/devices, the feature gate by code. No GUI and no platform service: the keyring, the browser, the machine-ID file and the OAuth client come in from the app (core ADR 0016).
  • Machine ID: the doc's HMAC-SHA256 of /etc/machine-id keyed with app.tablepro.TablePro, read by tablepro-linux-platform, with D-Bus's copy as the fallback Flatpak itself binds.
  • Preferences > Account: plan, the ten paid features (all "In TablePro for macOS", nothing gated), devices with Remove, the device limit dialog, teams, offline files, Buy a License. Refresh token in the keyring (Linux ADR 0038).
  • Usage data: posthog-rs with the clients.md events, only in a build with -Dposthog_key, on by default as on macOS (maintainer, 2026-11-05) with no question at launch; Preferences > General > Privacy > Share Usage Data turns it off and nothing more leaves. The Linux release reads the repository variable POSTHOG_PROJECT_KEY (public by design), as release.yml now does for macOS, and passes it through the vendor tarball (Linux ADR 0039).
  • License ask: on the Mac's days, as a toast with Buy a License, since the GNOME HIG forbids an unprompted dialog.
  • A sign-in that comes back after a later one or a sign-out is revoked, not adopted; one without a refresh token replaces nothing; cancel stops only the browser wait; protocol errors carry no answer body.
  • The access token expires on the wall clock, so a sleep longer than its 15 minutes does not leave a dead token in use, and a 401 drops it. An event queued behind a slow PostHog request when the switch goes off stays unsent once it is on again, and a dropped $identify goes out then.
  • A lapsed entitlement on disk reads back as it was, so it still says who has paid; signed_in_after_the_entitlement_expired_a_file_of_another_account_is_still_refused and a_kept_entitlement_that_expired_restores_as_expired expect it.
  • README privacy, the metainfo's privacy agreement and OARS rating, troubleshooting and storage say it is on by default, exactly what is sent, to whom and how to turn it off. core.yml checks and tests tablepro-account on Windows and macOS.
  • Carried over from the unpublished m17/accounts branch, onto the shared core layout.
  • /v2 already answers in production (the cutover switched nginx on 2026-11-04).

Test plan

  • tablepro-account: unit tests, the entitlement vectors, a late browser sign-in after a sign-out, a sign-in without a refresh token, a retry after a failed post-registration refresh, a refresh after a 401, a refresh that came due during a sleep, redacted protocol errors.
  • tablepro: usage data goes by default and nothing leaves once it is turned off, through the app's own wiring with a key, and a build without a key has none; the account page (sign-in, sign-out, reload on show, device limit, offline file), the first query counted through the history service, the license ask schedule, the Privacy switch on by default, no license ask for an account over the device limit, a second sign-in after a cancel, a sign-in over an offline file, a device removal whose check fails, events queued while the switch goes off and on.
  • tablepro-linux-platform: the GSettings keys, the keyring item, the machine-ID file fallback.
  • CI's fast, Docker, packaging and core jobs.

Deliberately not fixed here

  • Signed out, an imported offline file has no Remove of its own; it goes when another file or a sign-in replaces it, or with a sign-out. A local Remove needs a core call that never opens the keyring (Linux ADR 0038).
  • Over the device limit, a refresh that fails on the network or a 429 replaces the limit with a failed check: the device chooser closes and activation stops re-checking until Try Again or the hourly retry. Keeping both states at once needs its own design in AccountStatus, and nothing is gated on Linux yet.

Screenshots

Built with a placeholder PostHog key, so the Privacy group shows.

Light Dark
Before: Preferences Before, light Before, dark
After: Preferences > Account Account page, light Account page, dark
After: General > Privacy Privacy group, light Privacy group, dark

Needs the maintainer

  • The repository variable POSTHOG_PROJECT_KEY exists (2026-11-05). Both releases read it; the secret of the same name can go now.
  • tablepro-cloud's clients.md Linux section is updated (TableProApp/cloud#2, then TableProApp/cloud#3 for on by default, both merged).

@datlechin

Copy link
Copy Markdown
Member Author

clients.md update in the private tablepro-cloud repository: TableProApp/cloud#2.

@datlechin datlechin changed the title feat(linux): TablePro accounts and opt-in usage data feat(linux): TablePro accounts and usage data Nov 5, 2026
# Conflicts:
#	core/docs/decisions/README.md
#	linux/ROADMAP.md
#	linux/docs/decisions/README.md
# Conflicts:
#	.github/workflows/linux-packages.yml
#	.github/workflows/release-linux.yml
#	Cargo.lock
#	linux/README.md
#	linux/build-aux/debian/copyright
#	linux/data/licenses/third-party.json
#	linux/docs/decisions/README.md
#	linux/docs/releasing.md
# Conflicts:
#	core/docs/decisions/README.md
@datlechin
datlechin merged commit 8777b61 into main Nov 6, 2026
1 of 4 checks passed
@datlechin
datlechin deleted the feat/linux-licensing branch November 6, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant