forked from Mike/freno-dev
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).
235 lines
12 KiB
TypeScript
235 lines
12 KiB
TypeScript
/**
|
||
* The Nook privacy policy — `nook.freno.me/privacy`.
|
||
*
|
||
* 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 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. 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";
|
||
import { EdgeCacheHeaders } from "~/components/EdgeCacheHeaders";
|
||
import SubdomainHeader from "~/components/SubdomainHeader";
|
||
|
||
export default function NookPrivacyPolicy() {
|
||
return (
|
||
<>
|
||
<EdgeCacheHeaders maxAge={300} />
|
||
<PageHead
|
||
title="Privacy Policy"
|
||
description="Privacy policy for The Nook, a coding-agent orchestration and hardware control app."
|
||
/>
|
||
<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: November 4, 2026</div>
|
||
<div class="py-2">
|
||
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> What leaves your devices
|
||
</div>
|
||
<div class="pl-4">
|
||
<div class="pb-2">
|
||
<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:</div> Crash
|
||
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. 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">(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">(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">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>
|
||
|
||
<div class="py-2">
|
||
<div class="pb-2 text-lg">
|
||
<span class="-ml-4 pr-2">2.</span> How We Use It
|
||
</div>
|
||
<div class="pb-2 pl-4">
|
||
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>
|
||
|
||
<div class="py-2">
|
||
<div class="pb-2 text-lg">
|
||
<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 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>
|
||
|
||
<div class="py-2">
|
||
<div class="pb-2 text-lg">
|
||
<span class="-ml-4 pr-2">4.</span> Changes to the Privacy Policy
|
||
</div>
|
||
<div class="pb-2 pl-4">
|
||
We may update this policy periodically. Any changes are posted on
|
||
this page, so please review it from time to time.
|
||
</div>
|
||
</div>
|
||
|
||
<div class="py-2">
|
||
<div class="pb-2 text-lg">
|
||
<span class="-ml-4 pr-2">5.</span> Contact Us
|
||
</div>
|
||
<div class="pb-2 pl-4">
|
||
If you have any questions about this policy, you can contact us{" "}
|
||
<a
|
||
href={buildMainSiteUrl("/contact")}
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
class="text-blue hover-underline-animation"
|
||
>
|
||
here
|
||
</a>
|
||
.
|
||
</div>
|
||
</div>
|
||
</ol>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|