Files
nexu-io-open-design/PRIVACY.md
NJUHua 18edd90d31 feat(amr): forward Open Design device id to AMR for cross-product account linking (#4310)
* feat(amr): forward Open Design device id to AMR for cross-product account linking

To link an Open Design install to the AMR account a user registers after the
handoff (so paid AMR users can be traced back to Open Design), pass the Open
Design device id (installation/anonymous id) on the AMR handoff URL as
`od_device_id`. This gives AMR a stable, direct join key rather than relying
only on the one-shot entry id.

- `attributedAmrUrl` takes an optional `deviceId`; emits `od_device_id` only
  when provided.
- The ChatPane recharge handoff passes the device id ONLY when the user has
  opted into metrics (`telemetry.metrics === true`); otherwise it is omitted.
  AMR is Open Design's own official model service, so this is a same-owner
  cross-product link, but it still respects the telemetry opt-in. The handoff
  already opens with `noreferrer`, so the URL is not leaked via Referer.
- PRIVACY.md: add an "Open Design AMR" section disclosing that AMR is Open
  Design's official first-party model service and that information may be shared
  between the two same-owner products to provide and improve the experience.

Surface area: UI (handoff behavior) + docs (PRIVACY.md). No new capability or
CLI surface; analytics-forwarding + disclosure only.

* fix(amr): forward the canonical telemetry device id, not the bootstrap UUID

Review (nettee, elihahah666 — CHANGES_REQUESTED): the handoff sourced
od_device_id from analytics.anonymousId, which is the mount-time getAnonymousId()
bootstrap UUID — not the id telemetry keys on. Once /api/analytics/config
resolves, applyIdentity(installationId) re-registers device_id=installationId
for PostHog/Langfuse, and the two diverge before hydration and after a
Delete-my-data installationId rotation. AMR would then store a join key that
never matches the telemetry device id, weakening the cross-product link this
change exists to strengthen.

Extract amrHandoffDeviceId() which returns the canonical resolved device id
(getResolvedDeviceId(), = installationId once hydrated) when metrics consent is
on, falling back to config.installationId, never the bootstrap UUID; null
otherwise. Use it from the ChatPane recharge handoff and unit-test the gating:
consent off → null; consent on → resolved id; resolved not hydrated → falls back
to installationId; neither → null.

* fix(amr): prefer the freshly rotated installationId in the handoff device id

Review (nettee — non_blocking follow-up): amrHandoffDeviceId() preferred
resolvedDeviceId over installationId, but resolvedDeviceId is a module global in
the analytics client that only updates later, when the App-level setIdentity
effect runs applyIdentity(). config.installationId, by contrast, is the fresh
source-of-truth in the current render. During a Delete-my-data rotation the new
installationId is live while resolvedDeviceId still holds the deleted id until
that effect runs, so the handoff could forward the stale pre-rotation id and
break the exact cross-product join this helper exists to preserve.

Flip the precedence to installationId ?? resolvedDeviceId ?? null. In steady
state the two agree (the client seeds resolvedDeviceId from cfg.installationId),
so PostHog/Langfuse parity is unchanged; neither input is the mount-time
bootstrap UUID, so this does not regress the earlier fix. Extend the helper test
matrix with a rotation case where the two ids differ and assert the fresh
installationId wins.

---------

Co-authored-by: Mason <jinmeihong0201@gmail.com>
2026-06-16 03:54:54 +00:00

3.5 KiB
Raw Blame History

Privacy

This page describes what data the Open Design desktop and web app collects, when it collects it, and how you stay in control. It documents the behavior shipped in the app — the same controls live under Settings → Privacy.

Open Design is local-first. Your projects, generated files, and BYOK API keys stay on your machine. The app works fully offline; nothing in this page applies unless you explicitly turn telemetry on.

Telemetry is opt-in

Usage telemetry is off by default. On first run the app shows a privacy consent banner asking you to make a choice — it never starts sending anything before you do. You can change your decision at any time under Settings → Privacy, where each category below has its own toggle.

What is collected when you opt in

When telemetry is enabled, the app may send the following to the Open Design team. Each category is independently controllable in Settings.

  • Anonymous metrics — run counts, token usage, error rate, and duration. No prompts and no project data.
  • Conversation and tool content — your prompts, assistant responses, tool inputs, and tool outputs (truncated before send). API keys, tokens, JWTs, emails, IP addresses, and credit-card numbers are stripped automatically before anything leaves your machine.
  • Project artifacts manifest — filenames, types, and sizes of generated files. The contents of those files are never sent.

What is never collected

  • The contents of your generated artifact files.
  • Your BYOK API keys, tokens, or other secrets — these are redacted before send and are never part of telemetry.
  • Anything at all while telemetry is turned off.

How telemetry is sent

Redacted telemetry batches are sent to a Cloudflare Worker relay operated by the Open Design team, which forwards them to Langfuse for analysis. The relay holds the Langfuse write credentials server-side, so packaged clients only ever ship a public relay URL — no secret keys. If the relay is unavailable the app retries quietly and keeps working; telemetry never blocks your workflow.

Your anonymous ID

When telemetry is enabled the app generates a random, opaque installation ID so related events can be grouped. It is not tied to your name, email, or account, and it carries no personal information.

Deleting your data

Settings → Privacy → Delete my data rotates your anonymous ID and stops sending. Telemetry already received ages out under the team's retention policy.

Bring your own key

Open Design is BYOK at every layer. The API keys you configure for coding agents and model providers are stored locally and used only to talk to those providers directly. They are never sent to the Open Design team.

Open Design AMR

“Open Design AMR” is Open Designs official, first-party model service. Because the two are part of the same product family operated by the same team, we may share information between them as needed to provide, connect, and improve the combined experience — for example, to recognize that you arrived from Open Design, to help you get set up, and to keep the products working well together. This sharing is between our own products, not with unrelated third parties, and any data involved still follows the controls described on this page.

Changes to this page

This document tracks the data handling of the shipped app. When the telemetry behavior changes, this page is updated alongside it. For questions, open a GitHub Discussion.