CTO verdict at FRE-1480: two sentences atdb3e695were false. (b) sendDefaultPii = false does not stop Sentry receiving the connection IP (sentry-cocoa 9.26.1 sets infer_ip = auto for Cocoa; only the Sentry project's Prevent Storing of IP Addresses switch stops it) — the shipped Settings rows already say so. The IP sentence is restored. The iPhone paragraph described an opt-in build no tester has: the build in TestFlight (ios-v0.3.2, 2026-10-22) predates FRE-355 and starts Sentry on every launch with no off switch. The paragraph now says that. Header comment and marketing/drafts/privacy-page.md rows corrected to match (release range narrowed to 0.3.0-0.15.0; evidence rows record the IP and the TestFlight provenance). privacy-page.patch regenerated. Suite: merge tree ofa0e6ff1+ this branch runs the same failure set as cleana0e6ff1(2 junit failures, the known Lineage-redirect environmental pair); the host's env-validation aborts account for the count noise. Zero new failures.
238 lines
14 KiB
Diff
238 lines
14 KiB
Diff
diff --git a/src/routes/nook/privacy.tsx b/src/routes/nook/privacy.tsx
|
||
index da0cc1d..db27d8c 100644
|
||
--- a/src/routes/nook/privacy.tsx
|
||
+++ b/src/routes/nook/privacy.tsx
|
||
@@ -1,9 +1,38 @@
|
||
/**
|
||
* The Nook privacy policy — `nook.freno.me/privacy`.
|
||
*
|
||
- * Reflects the actual data The Nook sends when licensing: a masked hardware
|
||
- * UUID + device name for trial/activation limits, the email used for purchase,
|
||
- * and Stripe payment processing.
|
||
+ * Every statement on this page is traced to the egress inventory at
|
||
+ * `The-Nook` HEAD (FRE-333, `document-egress-inventory`): eleven internet
|
||
+ * destinations, file:line evidence per row. When the app's egress changes,
|
||
+ * this page changes in the same commit — not later.
|
||
+ *
|
||
+ * The crash-reporting paragraphs ((b) and the iPhone companion) describe the
|
||
+ * build users run today: crash reporting is opt-in, off by default, on
|
||
+ * releases v0.15.1 and later — FRE-355 (merge `6e74b261`) first shipped in
|
||
+ * `v0.15.1` (2026-11-04), and the live appcast serves `v0.15.2`. When enabled,
|
||
+ * Sentry receives crash and error reports, session pings, and performance
|
||
+ * traces at a 0.1 sample rate (`tracesSampleRate = 0.1`), and it also receives
|
||
+ * the connection's IP address (`sendDefaultPii = false` is the SDK default and
|
||
+ * does not suppress it — sentry-cocoa 9.26.1 sets `infer_ip = auto` for Cocoa,
|
||
+ * and only the Sentry project's *Prevent Storing of IP Addresses* switch stops
|
||
+ * that; FRE-1480). Releases 0.3.0 through 0.15.0 started Sentry on every
|
||
+ * launch with `sendDefaultPii = true` and no off switch; this page describes
|
||
+ * the current release. The iPhone paragraph describes `ios-v0.3.2`
|
||
+ * (2026-10-22, the build in TestFlight) until an `ios-v*` tag carries
|
||
+ * FRE-355's opt-in code.
|
||
+ *
|
||
+ * The *Contingency* in `marketing/drafts/privacy-page.md` fired with `v0.15.1`
|
||
+ * and is applied in this commit, with two corrections against the pre-written
|
||
+ * swap text: the shipped build still sends session pings and traces while
|
||
+ * enabled, so they are named (the contingency's own completeness warning), and
|
||
+ * the IP sentence is kept — the pre-written swap text already had it, and
|
||
+ * `sendDefaultPii = false` does not stop Sentry receiving the IP (FRE-1480).
|
||
+ *
|
||
+ * 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 +50,139 @@ export default function NookPrivacyPolicy() {
|
||
<SubdomainHeader />
|
||
<div class="min-h-screen px-[8vw] py-[10vh]">
|
||
<div class="py-4 text-xl">The Nook's Privacy Policy</div>
|
||
- <div class="py-2">Last Updated: August 26, 2026</div>
|
||
+ <div class="py-2">Last Updated: November 6, 2026</div>
|
||
<div class="py-2">
|
||
- Welcome to The Nook ('We', 'Us', 'Our').
|
||
- 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, 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 devices
|
||
</div>
|
||
<div class="pl-4">
|
||
<div class="pb-2">
|
||
- <div class="-ml-6">(a) Device hardware UUID:</div> When you start
|
||
- a trial or activate a license, The Nook sends a hardware UUID
|
||
- from your Mac. It is used solely to enforce the 14-day trial and
|
||
- the 3-device activation limit, and to prevent resetting the
|
||
- trial by reinstalling the app.
|
||
+ <div class="-ml-6">(a) Licensing and trial:</div> When you start
|
||
+ a trial or activate a license, The Nook sends your Mac's
|
||
+ 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 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'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 — off unless
|
||
+ you turn it on:</div> Crash reporting is off by default and
|
||
+ runs only if you enable it in Settings. When it is on, The Nook
|
||
+ sends crash reports, error events, hang reports, session pings,
|
||
+ and a sample of performance traces to Sentry, our
|
||
+ crash-reporting processor. Each report carries the app version,
|
||
+ the macOS version, the Mac model and what the app was doing
|
||
+ when it failed. Sentry also receives your IP address. They
|
||
+ 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. 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
|
||
+ module, your Mac asks our relay for forecasts using coordinates
|
||
+ rounded to a 0.1° grid — about 11 km — and the rounding happens
|
||
+ on your Mac before anything is sent. The Weather module
|
||
+ registers with the relay for this even if you never turn on the
|
||
+ phone connection, and on a licensed Mac that registration
|
||
+ presents the license key, exactly as the phone connection's
|
||
+ does. "My Location" asks macOS for your
|
||
+ approximate position, and naming or searching for a place uses
|
||
+ Apple's Maps service, so Apple sees those lookups. Neither
|
||
+ feature sends us your precise location.
|
||
+ </div>
|
||
+ <div class="pb-2">
|
||
+ <div class="-ml-6">(e) The Network panel:</div> While the
|
||
+ Network panel's connection section is on screen, The Nook
|
||
+ asks a third-party IP-lookup service (get.geojs.io, with
|
||
+ ipwho.is as backup) what your public IP address and provider
|
||
+ are — that is how the panel can show them to you. Those services
|
||
+ necessarily see your IP address. The speed-test button measures
|
||
+ against Cloudflare's public speed endpoint and uploads only
|
||
+ zeros, never your data.
|
||
+ </div>
|
||
+ <div class="pb-2">
|
||
+ <div class="-ml-6">(f) Update checks:</div> Automatic update
|
||
+ checks ship off. If you turn them on, or press "Check for
|
||
+ Updates", The Nook fetches the update feed from freno.me
|
||
+ and the request carries your app version. Like every request on
|
||
+ this page, it also arrives from your IP address.
|
||
+ </div>
|
||
+ <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">(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
|
||
+ model, CPU, memory, free disk, locale, and your displays'
|
||
+ names and resolutions — so the problem can be reproduced. The
|
||
+ optional contact email is used only to reply to you.
|
||
</div>
|
||
<div class="pb-2">
|
||
- <div class="-ml-6">(b) Device name:</div> The Nook sends your
|
||
- Mac'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
|
||
+ reminder before the trial ends. Payments are processed by
|
||
+ 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">The iPhone companion.</div> The iPhone and
|
||
+ Apple Watch app is in TestFlight beta. The build in TestFlight
|
||
+ starts Sentry on every launch, with no setting that turns it
|
||
+ off: it sends crash, error and hang reports, session pings,
|
||
+ performance traces, the app version, the iOS version, the
|
||
+ iPhone model and your IP address. 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 +192,11 @@ export default function NookPrivacyPolicy() {
|
||
<span class="-ml-4 pr-2">2.</span> How We Use It
|
||
</div>
|
||
<div class="pb-2 pl-4">
|
||
- Device identifiers, your email, and license records are used only
|
||
- to operate the trial, deliver purchases, and enforce the 3-device
|
||
- license. We do not use them for advertising or sell them to anyone.
|
||
+ Device identifiers, install IDs, your email and license records are
|
||
+ used only to operate the trial and the licenses, to run the relay
|
||
+ and the weather service, to answer bug reports, and to deliver
|
||
+ purchases. We do not use them for advertising and we do not sell
|
||
+ them to anyone.
|
||
</div>
|
||
</div>
|
||
|
||
@@ -74,9 +205,13 @@ export default function NookPrivacyPolicy() {
|
||
<span class="-ml-4 pr-2">3.</span> Data Security
|
||
</div>
|
||
<div class="pb-2 pl-4">
|
||
- License keys are signed and verified with Ed25519. The connection
|
||
- 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. 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>
|
||
|