privacy: fire the contingency — swap (b) and the iPhone paragraph to the opt-in form
v0.15.1 (2026-11-04) is the first release tag containing FRE-355's merge 6e74b261, and the live appcast serves v0.15.2. The page's own Contingency made the always-on (b) conditional on no release shipping FRE-355; that condition no longer holds, so the always-on text would be false on the build the page deploys with. Swap applied with two corrections against the pre-written contingency text, both measured in the shipped starter (Sources/NookApp/main.swift, CrashReporting.onTracesSampleRate): - session pings and performance traces (0.1) still flow while enabled, so they are named — the contingency's own completeness warning; - sendDefaultPii = false means no IP is attached, so the swap text's 'Sentry also receives your IP address' is dropped, not kept. iPhone paragraph corrected the same way (iOS gates identically: ios/AgentNookMobile/App.swift startIfEnabled, SettingsView default off). Last Updated -> November 6, 2026. privacy-page.patch regenerated (c1c498e..branch); draft sequencing/evidence rows updated.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# `/privacy` — replacement copy, FRE-354 corrections applied 2026-11-04
|
||||
|
||||
**Status:** applied on branch `faq/from-objections-2026-10-29` (commit after `bb6cf27`), per the CTO's FRE-354 verdict — "apply the corrections above and the page is signed." The two copy decisions the verdict delegated to the CMO are taken: the **fuller iPhone paragraph** (its push-token evidence row is recorded in the evidence table below and routed to FRE-333's owner to append to the signed inventory), and the **full (c) block with the LAN/tailnet sentence**, which pulls the corresponding Section 3 clause in. Nothing here is published; the sponsor's merge + push on card [`392a8465`](/FRE/issues/FRE-326#interaction-392a8465) is still the deploy step.
|
||||
**Sequencing fact this application rests on:** no The-Nook release tag contains FRE-355's merge (`6e74b261`; newest tag `v0.15.0` predates it), so every build in users' hands still starts Sentry unconditionally — paragraph (b) keeps the always-on form, and the *Contingency* swap is owed in the same commit that first ships FRE-355 in a release.
|
||||
**Sequencing fact, updated 2026-11-06:** the contingency has **fired**. `v0.15.1` (tagged 2026-11-04, first tag containing FRE-355's merge `6e74b261`) and `v0.15.2` are live on the appcast (`freno.me/api/TheNook/appcast.xml`, newest item 0.15.2). Shipped behaviour when enabled: crash/error reports, session pings (`enableAutoSessionTracking` untouched), traces at 0.1, and **no IP attached** (`sendDefaultPii = false`). Paragraph (b) and the iPhone paragraph are therefore swapped to the opt-in form in this commit, with two corrections against the pre-written swap text: pings and traces are named (the contingency's own completeness warning), and the IP sentence is dropped rather than kept. Builds before `v0.15.1` started Sentry on every launch with no off switch; the page describes the current release.
|
||||
**Patch:** `marketing/drafts/privacy-page.patch` — applies cleanly to `c1c498e` (`git apply --check`, verified 2026-10-29; parse-checked with esbuild, not the site suite).
|
||||
**Evidence base:** [FRE-333 `egress-inventory`](/FRE/issues/FRE-333#document-egress-inventory) rev 1, eleven destinations, file:line per row, read at `The-Nook` `3c3ba7ee`; and the same document's §G, which proposed a page text. This patch is the §G text **corrected against the inventory** — the differences are listed below, each with the row that forces it.
|
||||
**Why this exists:** [FRE-326](/FRE/issues/FRE-326) + [FRE-334](/FRE/issues/FRE-334#document-decision) recorded option A — the privacy claim is withdrawn everywhere, and no privacy claim returns until the inventory exists, `/privacy` matches it, the CTO verifies both, and the sponsor approves the replacement copy. The inventory landed on 2026-10-29. This is the page half.
|
||||
@@ -12,14 +12,14 @@
|
||||
| Audience | Someone deciding whether to pay $10 for a tool that reads their prompts. They read this page *before* the FAQ. |
|
||||
| Channel | `nook.freno.me/privacy`, one page |
|
||||
| Owner | CMO (copy + commit), CTO (verification), sponsor (approval of the replacement copy), Chief of Staff (publish switch) |
|
||||
| Date | Prepared 2026-10-29. Applied 2026-11-04 on the branch with the FRE-354 corrections; `Last Updated` on the page reads the apply date (November 4, 2026) — re-check it against the actual deploy date at push. Not a public date. |
|
||||
| Date | Prepared 2026-10-29. Applied 2026-11-04 on the branch with the FRE-354 corrections; the contingency (b)/iPhone swap applied 2026-11-06. `Last Updated` on the page now reads November 6, 2026 — re-check it against the actual deploy date at push. Not a public date. |
|
||||
| What has to be true before it ships | 1) CTO signs the page against `The-Nook` HEAD, paragraph by paragraph — [FRE-354](/FRE/issues/FRE-354), due 2026-11-02. 2) Sponsor accepts the replacement copy. 3) The Sentry paragraph matches the build being deployed — see *Contingency*. 4) It deploys in the same push as the FAQ withdrawal; a page that discloses Sentry next to a FAQ that still says "anonymous usage telemetry" is worse than either alone. |
|
||||
|
||||
## What changed against the live page
|
||||
|
||||
The live page (fetched 2026-10-29T09:2xZ and again 09:4xZ, HTTP 200, `Last Updated: August 26, 2026`, unchanged) says the app "runs locally on your device and sends only the minimal data required for trial and licensing" and lists four things. Against the inventory that is wrong in two directions: it **omits** Sentry (crash reports with IP address, every launch, no off switch), the relay and its install ID, the licence key crossing to the relay, sealed phone payloads, weather coordinates going to the relay *and* to Apple, the GeoIP third parties, the speed test, the changelog fetch, bug-report contents and update checks. It also calls the hardware UUID "masked", which the code contradicts — it sends the raw `IOPlatformUUID`.
|
||||
|
||||
The replacement is organised by *connection*, not by *data type*, because that is how a reader checks it: eleven rows in the inventory, ten of them reachable from the page, one (Sentry) prominent because it is the only one with no off switch.
|
||||
The replacement is organised by *connection*, not by *data type*, because that is how a reader checks it: eleven rows in the inventory, ten of them reachable from the page, one (Sentry) prominent because it is the only one a reader can turn off entirely and still miss in older builds. On the current release (`v0.15.1`+) it is opt-in and off by default; see *Contingency*.
|
||||
|
||||
## Differences from FRE-333 §G, and what forces each
|
||||
|
||||
@@ -31,7 +31,7 @@ The replacement is organised by *connection*, not by *data type*, because that i
|
||||
| 2 | (d) Weather: relay registration implied only with Phone | (d) adds that Weather registers **even with Phone off, and on a licensed Mac that registration presents the license key** | §A.3 + §D.2. `SidecarController.weather()` routes through the same `keystore.relayCredential(licenseKey:)` as the phone path (`SidecarController.swift:269-279`, `SidecarRelayAPI.swift:298-312`). §G under-disclosed it. |
|
||||
| 3 | (a) trial/activate/status only | (a) adds `/deactivate` (key + UUID) and the trial email (email + UUID, sent once) | §A.2, `/D.4`. §G omitted both endpoints. |
|
||||
| 4 | (i) "The email you give at trial start or checkout delivers your license key" | (i) checkout delivers the key; a trial email is one reminder before the trial ends | `LicenseService.submitTrialEmail` + `OnboardingExtrasStep` say the trial email is an expiry reminder; the key is issued at purchase. §G's sentence promised a key that the trial email does not deliver. |
|
||||
| 5 | (b) Sentry: opt-in, "off unless you turn it on" | (b) describes the build users run today: on every launch, no off switch, IP address; the opt-in form is the *Contingency* swap | The patch must be true on the build it deploys with. See *Contingency* for the sequence call. FRE-354 removed the username: `sendDefaultPii` sets the IP only. |
|
||||
| 5 | (b) Sentry: opt-in, "off unless you turn it on" | (b) is the opt-in form, applied 2026-11-06: off unless enabled in Settings, and it names session pings and the trace sample; **no IP sentence** | The contingency fired with `v0.15.1`. Corrections against the pre-written swap text: pings/traces named because they still flow when enabled; IP dropped because `sendDefaultPii = false` in the shipped starter. |
|
||||
| 6 | No (j) | (j) carries the CTO's FRE-322 §2 code fact, with the remote-machine exception | Not required for truth; it is the one favourable sentence, and the CTO may decline it. Delete the block if he does. |
|
||||
|
||||
Two facts the inventory corrected and the page does not repeat wrongly: Sparkle's automatic checks are **off by default** here (`UpdateManager` owns the schedule; FRE-322 §2.4 said "on by default" and is stale on this row), and the UUID is **raw, not masked**.
|
||||
@@ -41,7 +41,7 @@ Two facts the inventory corrected and the page does not repeat wrongly: Sparkle'
|
||||
| Paragraph | What it now says | Evidence at `3c3ba7ee` |
|
||||
|---|---|---|
|
||||
| (a) Licensing/trial | raw UUID + device name; every launch while trialing; key-only once licensed; deactivate sends key + UUID; trial email sends email + UUID once; trial/status fail open, activation needs a connection once | `LicenseService.swift:300-313` (`/trial`), `:271-284` (`/status`), `:247-262` (`/activate`), `:286-302` (`/deactivate`), `:219-231` (`/trial-email`) |
|
||||
| (b) Crash reporting | on for every launch, **no off switch**; carries IP address, plus session pings and a per-install Sentry ID; no username | `Sources/NookApp/main.swift:272-279` — `sendDefaultPii = true`, `tracesSampleRate = 1.0`, no preference gates it |
|
||||
| (b) Crash reporting | opt-in, **off by default**; when enabled: crash/error reports, session pings, traces at 0.1; **no IP attached**; no prompts or code | `Sources/NookApp/main.swift` `startIfEnabled` — `sendDefaultPii = false` (`policy.sendDefaultPii`), `tracesSampleRate = 0.1` while on (`CrashReporting.onTracesSampleRate`); `CrashReporting.registerDefaults` pins `enabledKey: false`; evidence read 2026-11-06 |
|
||||
| (c) Phone relay | off by default; relay is the default path, LAN/tailnet direct pairing available; install ID + license key at registration; sealed payloads; relay sees device IDs/names/platforms, timing and volume, not content | `SidecarRelayAPI.swift:144-153`, `SidecarPayload.swift:484-490`, `RemoteEndpoint.swift:14-24`, `docs/sidecar-frames.md` (sealing), inventory §B |
|
||||
| (d) Weather | 0.1° grid snapped **on the Mac**; registers with the relay even with the phone off, licence key included on a licensed Mac; Apple sees place lookups and position | `WeatherForecast.swift:25-30`, `SidecarController.swift:269-279`, `SidecarRelayAPI.swift:298-312`, `WeatherLocation.swift:14-77`, `:89-143` |
|
||||
| (e) Network panel | third-party IP lookup sees your IP; speed test uploads zeros only | `NetworkInfoService.swift:82,276`, `SpeedTest.swift:10-11,36` |
|
||||
@@ -54,6 +54,8 @@ Two facts the inventory corrected and the page does not repeat wrongly: Sparkle'
|
||||
|
||||
## Contingency — the Sentry paragraph is the only one that moves
|
||||
|
||||
**FIRED 2026-11-06 — applied on the branch.** `v0.15.1` is the first release containing FRE-355 and is live on the appcast. The swap below was applied with the corrections recorded in the sequencing paragraph at the top of this document (pings and traces named; IP sentence dropped). The original text is kept for the record:
|
||||
|
||||
(b) as committed describes today's build. The inventory's recommendation (§E.1) is an opt-in setting, default off, dropping `sendDefaultPii` and cutting `tracesSampleRate`, on Mac **and** iOS. If that ships, (b) is replaced in the same commit that changes the behaviour:
|
||||
|
||||
> **(b) Crash and error reporting — off unless you turn it on.** If you enable crash reporting in Settings, The Nook sends crash and error reports to Sentry, our crash-reporting processor. Reports include the app version, macOS version, Mac model and what the app was doing when it failed, and Sentry also receives your IP address. They never include your prompts or code.
|
||||
|
||||
Reference in New Issue
Block a user