Beta releases, private monitoring and feedback

September 16, 2026 · View on GitHub

The desktop and service implement these flows. They are disabled in contributor builds and are not a claim that signing, production infrastructure or email is live. Use RELEASE-AUTOMATION.md for publication and SERVER-LAUNCH.md for resource provisioning and recovery.

Release channels

Keep ongoing development on master, prereleases on beta and production releases on stable. Use the release-cut process to select snapshots without interrupting development. Ready release commits trigger Store release for Windows and Cloud release for Mac/Linux when their gates are enabled. Rehearsals cannot be published. Beta-to-stable promotion requires a stable build with stable metadata and a higher numeric version.

Store builds receive updates through Microsoft Store; tester flight enrollment controls beta delivery. The feed configuration and channel selector below apply to direct installers only, with the endpoint examples describing the legacy R2 path. Use Cloud configuration for active Mac/Linux release feeds.

Both feeds use the same trusted updater key and app identity. Numeric versions must increase: a user leaving beta waits until the stable feed offers a higher version. Settings → Updates & support persists the selection in the native profile. A channel change clears the offered update and is blocked during checking/installation; the native install command also rechecks the chosen channel and version. The telemetry channel comes from the installed binary, not the selected feed.

Candidate configuration uses these trusted build inputs (never renderer-controlled):

InputPurpose
STABLE_UPDATE_ENDPOINTHTTPS URL ending /updates/stable/latest.json
BETA_UPDATE_ENDPOINTHTTPS URL ending /updates/beta/latest.json
COMMUNITY_SERVICE_URLOptional HTTPS origin for native telemetry and feedback

The hosted candidate workflow supplies both update URLs. Set its COMMUNITY_SERVICE_URL repository variable only after service acceptance. Point both beta and stable clients at the same accepted service if you want one dashboard to compare them; release artifacts remain isolated in staging/production feeds. Forks can supply their own endpoints. Rehearsals strip community endpoints and channel switching, so they cannot accidentally send real usage data.

Server deployment follows beta → staging and manual master → production. If using Cloudflare native Builds, change the staging build's watched production branch to beta; the marketing website continues to track master. Do not enable both native Builds and the GitHub server deployment job for the same environment.

What monitoring means

The dashboard separates app opens, view visits, operation results, observed task states and fixed error categories. Filter by receipt day, binary version, binary channel and OS when comparing releases. Task states include an allowlisted agent and task/Chat workflow; older reports retain unknown dimensions.

Operation results cover task launch/retry/stop, verification, outcome review, previews, recovery, Chat, queues, integration, schedules, knowledge, MCP connections, worktrees, agent setup and Ask Jackalope. The closed command inventory lives in apps/desktop/src/lib/telemetry.ts; operation-telemetry.ts maps explicit commands and semantic results. Polling and draft autosaves are excluded. Accepted means a native acknowledgement: a queued message or accepted launch has not necessarily finished execution. Failed checks/probes, blocked integration, canceled recovery dialogs and applied merges with incomplete cleanup have distinct results.

Error categories distinguish history read/write, discovery, checkpoint, verification execution, failed checks, updates, task failures, page rendering, unhandled JavaScript errors/rejections and failed operations. Operation errors carry the fixed operation name; caught page-rendering errors carry the fixed page category. These are triage signals, not exception traces or evidence that every failed task is an application bug. One failure can contribute to both task/error and operation counts; do not sum them as independent incidents.

Use operation results to compare activity and failures among participating clients. Use view visits to identify discoverability, and task states to distinguish agents and workflows needing investigation. Inspect voluntarily submitted feedback to reproduce problems. Reports cannot measure unique people, individual retention, per-user conversion funnels, exact crash-free rates, latency or all native failures. Do not divide independent task transitions into a completion rate: observation can miss intermediate states, starts/completions can fall in different receipt windows, and opted-out/offline clients are absent. Public ingestion cannot authenticate an open-source client; rate limits and quotas do not make counts authoritative.

Before any upload, desktop onboarding presents the usage-sharing disclosure. Usage defaults on with a one-click continue-without-sharing choice, as recorded in BACKEND.md. Existing saved opt-outs are preserved. Native preferences are authoritative. Turning sharing off clears the in-memory queue and cancels native requests; already transmitted bytes cannot be recalled. Error categories have a separate control under usage sharing. There is no disk spool or replay of old history. The queue holds up to 50 events, sends up to 50 at once and retries twice with backoff. Each event retains its own retry budget when new events join a retrying batch. Local execution never waits for the network. Hiding a window requests a best-effort flush; short sessions, queue overflow, process exits and outages may lose counts. Initial/restored history is not replayed as new work. Task observation belongs to the main window; Chat popouts report their own operations without another app-open event. Privacy changes notify all open windows and native preferences gate delivery. Operation outcome counts, including failed results, are usage; the additional diagnostic error categories require the separate error-sharing choice.

No installation/account/device IDs, prompts, code, paths, command output, raw errors or stacks are accepted. The server atomically increments daily totals and saves only an event UUID/hash/expiry receipt for retry deduplication. Default retention is 30 days; daily buckets expire at UTC day boundaries. Legacy v1 event rows expire through the old cleanup path; v1 ingestion returns 410. D1/application logs exclude raw IPs and headers. Cloudflare still processes network addresses and login identities: configure edge, security, Access and backup retention separately. Do not claim that transport infrastructure never sees identifying data.

Private dashboard configuration

Provision a Cloudflare Access self-hosted application covering the service's /admin and every /admin/* path. Permit only the owner's verified email with an appropriate identity provider. Restrict the origin's alternate hostnames as well; the Worker independently verifies the signed assertion, exact issuer/audience and owner email, so an unprotected workers.dev URL cannot bypass the application check. Protect only admin paths: desktop ingestion and updater downloads do not use browser Access.

Set deployment configuration, never app source:

Worker variableValue
ADMIN_EMAILSole permitted owner email
ACCESS_ISSUERhttps://YOUR-TEAM.cloudflareaccess.com
ACCESS_AUDAccess application's audience tag
INGESTION_ENABLEDtrue only after migration and acceptance
FEEDBACK_EMAIL_ENABLEDtrue only after sender setup
FEEDBACK_EMAIL_FROMAddress on an onboarded sending domain
FEEDBACK_EMAIL_TOPrivate inbox recipient

For generated deployment config, use STAGING_ or PRODUCTION_ prefixes on those environment variables. apps/server/scripts/community-config.mjs validates/copies them into that environment; native Builds and GitHub deployment use the same helper. Generated deployment configuration omits the email binding while sending is disabled. Keep RATE_SECRET in Worker secrets and resource IDs in private deployment settings. An unset admin identity/issuer/audience fails closed. Public configuration uses blank admin values and disabled ingestion/email; it contains no owner's login address.

Open /admin through Access. The overview shows account totals, retained new feedback, onboarding follow-ups, latest account-email warnings and service configuration. Follow-up links open the matching people filters. Account totals exclude revoked access; desktop connection is a first-sign-in milestone, not current activity or task completion. The shared navigation separates people, audience preferences, product-note drafts, service setup, usage and feedback. Usage provides 7/30-day filters, daily UTC app-open counts, operation outcomes, task states by agent/workflow and channel/version/OS comparisons. Partial results are labeled and must not be used as complete totals. The paginated feedback inbox supports new/reviewing/planned/closed states. Refresh controls update each view explicitly. Writes require a same-origin request in addition to the verified JWT. Responses are uncached, framed pages are blocked, and submitted text is never rendered as HTML. If the aggregate result limit is reached, the page labels results partial and asks for narrower filters. Missing/expired login shows an error; there is no public bypass.

Feedback and notification email

Settings → Updates & support offers bug, feature and idea submissions. The user reviews their message and optional four task counters before Send. Version, binary channel and OS are attached by the native host. Telemetry opt-out does not disable feedback. No email identity is automatically attached; include contact details voluntarily to request a reply. Written feedback may contain personal information, so it is separate from anonymous metrics and retained privately for 90 days by default.

Acceptance is HTTP 202 only after D1 persistence. Retries reuse the same report UUID and body; editing after a failed attempt creates a new UUID. A lost acknowledgement followed by an edit can therefore create a second report. Closing the form does not persist an unsent draft. The dashboard is the inbox of record.

Cloudflare Email Service needs an onboarded sending domain and its DNS records before enabling mail. Configure the binding's allowed destination through the helper. A saved report queues email independently; the request's background task tries delivery, and the five-minute cron retries with a lease and backoff, up to five attempts. Provider failures never discard feedback. The dashboard displays delivery state. After resolving a persistent delivery fault, an operator can reset email_attempts=0, email_next=0, email_state='pending' for a confirmed report ID in private D1. Delivery is at least once: a process failure after send but before acknowledgement may duplicate email. Use the report UUID to recognize it. Mail copies and Cloudflare backups have separate retention from D1; handle deletions in all of them. Do not forward private reports into public issues automatically.

Activation acceptance

  • Apply all pending service migrations to staging, then validate /readyz schema 2, quotas and cron.
  • Deploy ingestion/dashboard schema extensions before a desktop that emits them. Existing v2 clients remain accepted; an older server rejects an entire batch containing an unknown event or field. The operation/task dimensions use the existing aggregate table and need no additional migration.
  • Configure Access issuer/audience/owner. Test owner login, another account, expired sessions and direct alternate-host requests; only the owner may read or change data.
  • Onboard a sender, enable a verified recipient, and submit one deliberate test report. Verify dashboard persistence, email arrival, retry behavior and cleanup. Local tests mock email and do not establish real deliverability.
  • With an isolated installed beta, inspect traffic before disclosure, after opt-out, after restart and during outages. Confirm no content/identifiers and correct installed channel. Test feedback with telemetry disabled and an uncertain acknowledgement.
  • In that installed trial, compare a known sequence of task launch, failed check, Chat send, merge and cleanup results with dashboard counts. Retry an identical batch, restore old history and open a Chat popout; none should duplicate task starts. Change privacy choices while both windows are open. Include native process termination separately; renderer observations are not a crash collector.
  • Install a signed stable → beta update, switch back and wait for a higher stable version. Test both installer formats, tampered signatures and active-task guards.
  • Configure budget alerts, service health checks and quota/expiry backlog monitoring. Review edge/Access/email/backup retention and publish accurate privacy language.
  • Enable the reporting URL for reviewed candidates only after those checks pass.

Local unit, native and browser-fixture tests cover code behavior; they do not complete these hosted, installed-app or delivery gates.