privacy: apply the FRE-354 verdict corrections to the /privacy replacement

FRE-354 ruled the page 'verified after corrections — do not apply as it
stands'. This applies all of them, plus the two copy decisions the verdict
delegated to the CMO (fuller iPhone paragraph; full (c) block with the
LAN/tailnet sentence and the matching section-3 clause).

- (b) no macOS username (sendDefaultPii sets the IP only), session pings
  named; still the always-on form: no release tag contains FRE-355's
  opt-in merge (6e74b261; v0.15.0 predates it), so the page stays true on
  the build users run. Contingency swap owed with the first release that
  ships FRE-355.
- (a) device-name sentence corrected (no activations UI exists); fail-open
  scoped to trial/status, activation needs a connection once.
- (c) relay qualified as the default path; relay sees IDs/names/platforms;
  direct LAN/tailnet pairing sentence added.
- (j) 'not a cloud service' instead of two absolutes FRE-322 flagged;
  tailnet path named.
- iPhone companion paragraph added (TestFlight beta is in users' hands,
  same Sentry config, push token disclosed). Push-token evidence row
  recorded for FRE-333's inventory.
- Opening, section heading ('What leaves your devices') and section 3
  ('content', not all traffic) per the verdict; Last Updated bumped.
- Draft evidence table and contingency warning rewritten per the verdict
  (the old warning named a username Sentry never sends).

Suite on this tree: 441 pass / 3 skip / 53 fail / 2 errors — failure and
error sets byte-identical to clean master d44133f (458/3/53/2; the delta
is master's remote-claims.test.ts, 17 passing tests this branch's base
predates). Local only; the push is the sponsor's (card 392a8465).
This commit is contained in:
fixture
2026-11-04 14:50:41 +00:00
parent bb6cf27821
commit 4d6550f0d1
3 changed files with 180 additions and 120 deletions

View File

@@ -1,8 +1,8 @@
diff --git a/src/routes/nook/privacy.tsx b/src/routes/nook/privacy.tsx
index da0cc1d..f357ded 100644
index da0cc1d..b6d6a27 100644
--- a/src/routes/nook/privacy.tsx
+++ b/src/routes/nook/privacy.tsx
@@ -1,9 +1,17 @@
@@ -1,9 +1,25 @@
/**
* The Nook privacy policy — `nook.freno.me/privacy`.
*
@@ -14,36 +14,46 @@ index da0cc1d..f357ded 100644
+ * destinations, file:line evidence per row. When the app's egress changes,
+ * this page changes in the same commit — not later.
+ *
+ * The crash-reporting paragraph below describes the build that ships today:
+ * The crash-reporting paragraph below describes the build users run today:
+ * Sentry starts unconditionally in `Sources/NookApp/main.swift:272-279`, with
+ * `sendDefaultPii = true`, and there is no off switch in Settings. If an
+ * opt-in setting ships, paragraph (b) is replaced by the shorter form held in
+ * `marketing/drafts/privacy-page.md` §"Contingency" in the same commit that
+ * makes it true.
+ * `sendDefaultPii = true`, and there is no off switch in Settings. The opt-in
+ * build change is merged on The-Nook master (FRE-355, 6e74b261) but no release
+ * tag carries it yet, so the page must keep the always-on form until the first
+ * release that contains it — then paragraph (b) is replaced by the shorter
+ * form held in `marketing/drafts/privacy-page.md` §"Contingency" in the same
+ * commit that makes it true.
+ *
+ * Corrected against the CTO's /privacy verdict (FRE-354): no macOS username
+ * from Sentry (sendDefaultPii sets the IP only), session pings named, (a)
+ * fail-open scoped, (c) relay-path qualified with the direct-pair sentence,
+ * (j) "not a cloud service" with the tailnet path, the iPhone paragraph added
+ * (TestFlight beta is in users' hands), and section 3 says "content".
*/
import { buildMainSiteUrl } from "~/lib/subdomain-url";
import { PageHead } from "~/components/PageHead";
@@ -21,39 +29,118 @@ export default function NookPrivacyPolicy() {
@@ -21,39 +37,137 @@ export default function NookPrivacyPolicy() {
<SubdomainHeader />
<div class="min-h-screen px-[8vw] py-[10vh]">
<div class="py-4 text-xl">The Nook&apos;s Privacy Policy</div>
- <div class="py-2">Last Updated: August 26, 2026</div>
+ <div class="py-2">Last Updated: October 29, 2026</div>
+ <div class="py-2">Last Updated: November 4, 2026</div>
<div class="py-2">
- Welcome to The Nook (&apos;We&apos;, &apos;Us&apos;, &apos;Our&apos;).
- Your privacy is important to us. This policy explains what we collect,
- why, and how it is handled. The app itself runs locally on your device
- and sends only the minimal data required for trial and licensing.
+ The Nook runs on your Mac. Your prompts, your code and your agent
+ sessions are processed on your device. This page lists every
+ connection the app makes over the network, what each one sends, and
+ The Nook runs on your Mac, and the iPhone and Apple Watch companion
+ is in TestFlight beta. Your prompts, your code and your agent
+ sessions are processed on your own devices. This page lists every
+ connection the apps make over the internet — and the local-network
+ and tailnet paths the phone can use — what each one sends, and
+ whether you can turn it off.
</div>
<ol>
<div class="py-2">
<div class="pb-2 text-lg">
- <span class="-ml-4 pr-2">1.</span> Data We Collect
+ <span class="-ml-4 pr-2">1.</span> What leaves your Mac
+ <span class="-ml-4 pr-2">1.</span> What leaves your devices
</div>
<div class="pl-4">
<div class="pb-2">
@@ -57,37 +67,44 @@ index da0cc1d..f357ded 100644
+ hardware UUID and device name to our licensing server
+ (freno.me). The UUID enforces the 14-day trial and the 3-device
+ activation limit and stops a trial being reset by reinstalling
+ the app; the device name is so you can recognize the Mac among
+ your activations. While you are on the trial, this is sent at
+ each launch. Once you are licensed, each launch re-checks only
+ that your key has not been revoked. Deactivating a Mac sends the
+ license key and that Mac&apos;s UUID. If you add an email during
+ the trial, that request carries the email and the UUID, and it
+ is sent once. All of these calls fail open: with no connection,
+ the app keeps working, because license verification itself is
+ offline.
+ the app; the device name is stored with the activation so the
+ Mac can be identified in your license records. While you are on
+ the trial, this is sent at each launch. Once you are licensed,
+ each launch re-checks only that your key has not been revoked.
+ Deactivating a Mac sends the license key and that Mac&apos;s
+ UUID. If you add an email during the trial, that request
+ carries the email and the UUID, and it is sent once. The trial
+ and status checks fail open: with no connection, an unexpired
+ trial or a stored license keeps working, because license
+ verification itself is offline. Activating a new license needs
+ a connection once.
+ </div>
+ <div class="pb-2">
+ <div class="-ml-6">(b) Crash and error reporting:</div> Crash
+ reports, error events, hang reports and performance traces are
+ sent to Sentry, our crash-reporting processor, and this is on
+ for every launch in this version — there is no setting that
+ turns it off. Each report carries the app version, the macOS
+ version, the Mac model and what the app was doing when it
+ failed, and Sentry also receives your IP address and your macOS
+ username. Reports never include your prompts, your code or your
+ reports, error events, hang reports, session pings, and
+ performance traces are sent to Sentry, our crash-reporting
+ processor, and this is on for every launch in this version —
+ there is no setting that turns it off. Each report carries the
+ app version, the macOS version, the Mac model and what the app
+ was doing when it failed, and Sentry also receives your IP
+ address. Reports never include your prompts, your code or your
+ session content.
+ </div>
+ <div class="pb-2">
+ <div class="-ml-6">(c) Phone connection:</div> The phone
+ connection ships off and is yours to enable. When you turn it
+ on, your Mac registers with our relay (nook-relay.freno.me)
+ using a random install ID, and a licensed Mac presents its
+ license key once at registration. Everything your Mac and your
+ phone then exchange — session updates, approvals, replies — is
+ encrypted end-to-end: the relay routes it and cannot read it.
+ The relay can see which devices are connected, when, and how
+ much traffic they exchange.
+ connection ships off and is yours to enable. With the default
+ relay path, turning it on registers your Mac with our relay
+ (nook-relay.freno.me) using a random install ID, and a licensed
+ Mac presents its license key once at registration. Everything
+ your Mac and your phone then exchange — session updates,
+ approvals, replies — is encrypted end-to-end: the relay routes
+ it and cannot read it. On the relay path, the relay can see
+ which devices are connected — their IDs, names and platforms —
+ when, and how much traffic they exchange.
+ </div>
+ <div class="pb-2">
+ You can also pair over your LAN or tailnet instead; those paths
+ carry the same sealed traffic and do not use the relay.
+ </div>
+ <div class="pb-2">
+ <div class="-ml-6">(d) Weather:</div> If you add the Weather
@@ -122,11 +139,8 @@ index da0cc1d..f357ded 100644
+ <div class="pb-2">
+ <div class="-ml-6">(g) Changelog:</div> Opening Settings ›
+ Changelog fetches the release notes from freno.me.
</div>
<div class="pb-2">
- <div class="-ml-6">(b) Device name:</div> The Nook sends your
- Mac&apos;s name so you can recognize the device in your license
- activations. It is not used for any other purpose.
+ </div>
+ <div class="pb-2">
+ <div class="-ml-6">(h) Bug reports:</div> only what you choose
+ to send. If you write a bug report, you decide what it says.
+ Bug reports also include a machine snapshot — macOS version, Mac
@@ -135,9 +149,9 @@ index da0cc1d..f357ded 100644
+ optional contact email is used only to reply to you.
</div>
<div class="pb-2">
- <div class="-ml-6">(c) Email:</div> The email you provide at
- checkout is used to deliver your license key and to look up your
- order.
- <div class="-ml-6">(b) Device name:</div> The Nook sends your
- Mac&apos;s name so you can recognize the device in your license
- activations. It is not used for any other purpose.
+ <div class="-ml-6">(i) Your email and payment:</div> The email
+ you give at checkout delivers your license key and looks up your
+ order. An email you add during the trial is used for one
@@ -145,23 +159,36 @@ index da0cc1d..f357ded 100644
+ Stripe; we never see or store your card details.
</div>
<div class="pb-2">
- <div class="-ml-6">(c) Email:</div> The email you provide at
- checkout is used to deliver your license key and to look up your
- order.
+ <div class="-ml-6">(j) What does not leave your Mac:</div> The
+ hook and the bridge that connect your agents to The Nook are
+ not a cloud service: the hook dials the bridge on your Mac, and
+ the bridge only listens. Two paths carry agent data across the
+ network, and both are switched on by you: if you add a remote
+ machine, the hook on that machine dials this Mac over SSH or
+ your tailnet; and if you use the phone connection, the session
+ updates, approvals and replies described in (c) travel through
+ the relay, sealed end to end. The privileged helper that
+ controls fans and charging has no networking code at all.
</div>
<div class="pb-2">
- <div class="-ml-6">(d) Payment:</div> Payments are processed by
- Stripe. We never see or store your card details.
+ <div class="-ml-6">(j) What does not leave your Mac:</div> The
+ hook and the bridge that connect your agents to The Nook talk to
+ nothing but your Mac — the hook dials the local bridge socket,
+ and the bridge only listens. Two paths carry agent data across
+ the network, and both are switched on by you: if you add a
+ remote machine, the hook on that machine dials this Mac over
+ SSH; and if you use the phone connection, the session updates,
+ approvals and replies described in (c) travel through the relay,
+ sealed end to end.
+ The privileged helper that controls fans and charging has no
+ networking code at all.
+ <div class="-ml-6">The iPhone companion.</div> The iPhone and
+ Apple Watch app is in TestFlight beta. It runs the same Sentry
+ reporting: the app version, iOS version, iPhone model, session
+ pings and your IP address, with the same no-off-switch. Those
+ reports never include your prompts, code or session content.
+ Its other network traffic is the phone connection in (c) — the
+ relay, or a direct LAN/tailnet link — plus, if you allow
+ notifications, the push token it gives the relay so Apple can
+ deliver them.
</div>
</div>
</div>
@@ -63,9 +150,11 @@ export default function NookPrivacyPolicy() {
@@ -63,9 +177,11 @@ export default function NookPrivacyPolicy() {
<span class="-ml-4 pr-2">2.</span> How We Use It
</div>
<div class="pb-2 pl-4">
@@ -176,7 +203,7 @@ index da0cc1d..f357ded 100644
</div>
</div>
@@ -74,9 +163,11 @@ export default function NookPrivacyPolicy() {
@@ -74,9 +190,13 @@ export default function NookPrivacyPolicy() {
<span class="-ml-4 pr-2">3.</span> Data Security
</div>
<div class="pb-2 pl-4">
@@ -184,10 +211,12 @@ index da0cc1d..f357ded 100644
- to our servers uses TLS. Your license key is stored in the macOS
- Keychain on your Mac.
+ License keys are signed and verified with Ed25519 and stored in
+ the macOS Keychain. Phone traffic is encrypted end-to-end with
+ keys your own devices generate at pairing; our relay holds no key
+ that can read it. Every connection described on this page uses
+ TLS.
+ the macOS Keychain. The session content your Mac and phone
+ exchange is encrypted end-to-end with keys your devices generate
+ at pairing; our relay holds no key that can read it, though it
+ can read the routing metadata described in (c). Every internet
+ connection described on this page uses TLS; the direct
+ LAN/tailnet paths use the same end-to-end encryption.
</div>
</div>