Commit Graph
5 Commits
Author SHA1 Message Date
saphidandClaude Opus 5.5 3f0f09b138 Contact email: don't block Save on a slow send; redact reports still in flight
Second review follow-ups:
- Saving returns once the choice is stored; a send already under way picks up
  the newest change, or the background retry is woken.
- A problem report still being sent when its address is removed is logged as
  <removed>, checked under the same lock the removal holds.
- The prompt re-checks the privacy notice after fetching its state.
- docs/privacy.md: offline contact changes are sent later by themselves; the
  prompt never follows straight after the privacy notice.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 10:29:17 +10:00
saphidandClaude Opus 5.5 b8ed53f2ff Contact email: newest choice wins by rev, removal wipes the local log
Review follow-ups:
- Each contact_consent event carries a rev that goes up with every change,
  sends are serialized, and `contacts` picks every field from the highest
  rev per copy, so a withdrawal can't lose to an earlier event sent in the
  same second or with a skewed clock.
- Removing the address also replaces it with <removed> in the local
  sent log (earlier contact events and problem reports).
- The prompt is rechecked when the Frame connects, not only at page load.
- No thanks hides the bar only once the dismissal is saved.
- docs/privacy.md: say that the analytics switches don't block a report or
  contact change the person sends deliberately.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 10:22:45 +10:00
saphidandClaude Opus 5.5 19a0d0af18 Ask for an optional contact email, with separate update and follow-up consent
Problem reports arrive with no way to reply. People can now leave an email
address with two separate opt-ins: occasional update notices, and follow-up
questions from the maintainer.

- ui/frame_contact.py keeps the address and choices locally and sends each
  change privately to PostHog as a contact_consent event under its own random
  contact id; removing the address sends a withdrawal without it. Changes made
  offline wait and are retried.
- A one-time, dismissible prompt appears after the Frame first connects; No
  thanks and showing it once are both remembered.
- Privacy & updates gains a Contact email section to add, change or remove it.
- The report form's contact field now goes with a report only when "may
  contact me with follow-up questions" is ticked (contact_followup).
- frame_report.py contacts [updates|followup] lists who agreed to what,
  using the newest event per copy.
- docs/privacy.md says what is collected, why, where and how to remove it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 10:15:53 +10:00
saphidandClaude Opus 5.5 f076527722 Send analytics to the existing PostHog project; make bug reports private
- Analytics go to the maintainer's PostHog US project 343535, tagged
  $lib = frame-control. Every event carries $ip 0.0.0.0, since PostHog
  stores the sender's address otherwise (checked live), including events
  queued by earlier versions.
- Report a problem sends a private problem_report event to PostHog instead
  of a public GitHub issue, with its own random id so a contact address
  can't be linked to analytics. The dialog asks how to reach the person and
  shows a reference. Maintainers read reports on the PostHog dashboard or
  with `python3 ui/frame_report.py inbox`.
- Community sync pages by timestamp in UTC: PostHog refuses OFFSET for
  personal API keys.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:14:36 +10:00
saphidandClaude Opus 5.5 9eeca79b5d Analytics, self-update and Report a problem
- Anonymous PostHog analytics (ui/frame_telemetry.py): usage on by default
  after a first-run notice; compatibility results and error details opt-in,
  offered together by the notice's "Share more to help fix problems" button.
  Random id, no person profiles or GeoIP, scrubbed text, an offline outbox,
  and "Show what's been sent" in the new Privacy panel. Inert without a
  project key, from a source checkout, or with DO_NOT_TRACK=1.
- APK installs now record install_failed when the APK itself won't install,
  and offer a 20-second test after installing. Opted-in reports reach the
  shared database through PostHog and `frame_compat_db.py sync`.
- The desktop app updates itself from published releases (app/updater.js):
  update.json from releases/latest/download, SHA-256 checked, no downgrades;
  macOS bundle swap, Windows NSIS, Linux AppImage, otherwise the release page.
  scripts/publish-release.sh publishes a tested draft with its manifest.
- Report a problem (header button, Privacy panel, Help menu) files a GitHub
  issue through the website's feedback API, with a previewed, scrubbed
  diagnostics snapshot; activity and logs only when asked for.

Reviewed by GPT-6 Astra (xhigh, read-only) three times; all findings fixed.
Docs: docs/privacy.md, docs/releasing.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:34:21 +10:00