nucleic-edge
Cloudflare Worker for Nucleic's cloud edge. See docs/CLOUD_INFRA.md for the full design.
- Phase A (now):
POST /v1/heartbeat— anonymous DAI (daily active installs) heartbeat → Workers Analytics Engine (nucleic_dai). Indexed by a random install UUID, so it counts installs, not users.GET /healthfor a liveness check. - Phase B/C (later): WebSocket relay (Durable Object
Room) + APNS approval push. The relay also writes a true daily-active-user metric (nucleic_relay_dau), indexed byroomId≈ account — see Relay DAU below.
Develop
npm install
npm run typecheck # tsc --noEmit
npm test # vitest — unit tests for the payload validator
npm run check # wrangler deploy --dry-run (bundles, no upload, no auth)
npm run dev # local server at http://localhost:8787
POST smoke test against a local npm run dev:
curl -i -XPOST http://localhost:8787/v1/heartbeat \
-H 'content-type: application/json' \
-d '{"installId":"11111111-2222-3333-4444-555555555555","platform":"macos","osVersion":"26.0","channel":"beta","appVersion":"0.1.0","build":"42","arch":"arm64","locale":"en"}'
# → 204
(AE writes are accepted but not queryable from local dev; verify counts after deploy.)
Provision (one-time, Cloudflare dashboard / API)
-
Ensure the
blakeslee.xyzzone is on this account (theroutescustom domain needs it). -
Deploy:
npm run deploy— provisionsapi.nucleic.blakeslee.xyz+ cert and creates thenucleic_dai(and, once the relay is live,nucleic_relay_dau) dataset on first write. -
Query DAI — daily active installs (AE SQL API), e.g. last 30 days split by platform:
SELECT toStartOfDay(timestamp) AS d, blob1 AS platform, count(DISTINCT index1) AS dai FROM nucleic_dai WHERE timestamp > now() - INTERVAL '30' DAY GROUP BY d, platform ORDER BY d
Blob/index layout (keep in sync with the client + the SQL above)
nucleic_dai — indexed by the anonymous install UUID (counts installs, not users):
| Field | Slot |
|---|---|
installId |
index1 |
platform |
blob1 |
osVersion |
blob2 |
channel |
blob3 |
appVersion |
blob4 |
build |
blob5 |
arch |
blob6 |
locale |
blob7 |
Relay + APNS (Phase B/C)
The relay is E2EE-opaque: binary WebSocket frames are forwarded byte-for-byte and never
inspected (Noise runs end-to-end through it). A separate text control plane carries non-secret
relay metadata. See docs/CLOUD_INFRA.md §2–§3 and §2.1 for the token lifecycle.
Relay DAU
Every admitted /relay connection writes one data point to the nucleic_relay_dau Analytics
Engine dataset, indexed by roomId. Because roomId is derived from the host's static public
key (docs/CLOUD_INFRA.md §2.1), one room ≈ one user/account — so count(DISTINCT index1) is a
true daily-active-user count, unlike nucleic_dai which counts installs. Same-day reconnects
collapse under the DISTINCT.
| Field | Slot | |
|---|---|---|
roomId |
index1 |
user/account identity (host static-key hash) |
role |
blob1 |
host | client |
deviceId |
blob2 |
for "distinct devices per user" slices |
SELECT toStartOfDay(timestamp) AS d, count(DISTINCT index1) AS dau
FROM nucleic_relay_dau
WHERE timestamp > now() - INTERVAL '30' DAY
GROUP BY d
ORDER BY d
Endpoints
| Method & path | Auth | Purpose |
|---|---|---|
GET /relay?t=<connToken> (Upgrade) |
connection token | Join a room's WebSocket |
POST /v1/relay/token |
RELAY_ADMIN_SECRET |
Host mints a 90-day membership token for a paired device |
POST /v1/relay/connect |
membership token (Bearer) | Trade membership → a ~2-min connection token |
POST /v1/relay/revoke |
RELAY_ADMIN_SECRET |
Revoke a device on unpair ({deviceId}) |
POST /v1/push/notify |
RELAY_ADMIN_SECRET |
Out-of-band APNS wake for {deviceId} |
Control-plane frames (text JSON over the room socket):
- phone → relay:
{"t":"register","pushToken":"<hex>","env":"sandbox|production"} - host → relay:
{"t":"wake","deviceId":"<id>"}— pushes only if that device's socket is absent - relay → all:
{"t":"presence","peers":[{deviceId,role}]}
Provision (one-time)
- KV:
wrangler kv namespace create NUCLEIC_RELAY_TOKENSand... NUCLEIC_PUSH_TOKENS; paste the ids intowrangler.jsonc. - Relay secrets:
wrangler secret put RELAY_TOKEN_SECRET(random 32+ bytes),RELAY_ADMIN_SECRET. - APNS: create a
.p8auth key (Apple Developer → Keys, Push enabled), thenwrangler secret put APNS_KEY_P8(paste the PEM),APNS_KEY_ID,APNS_TEAM_ID(L7UDTQ6F5W),APNS_TOPIC(xyz.blakeslee.nucleic.remote),APNS_ENV(sandboxfor TestFlight/dev,productionfor App Store). - Enable Push Notifications on the
xyz.blakeslee.nucleic.remoteApp ID; ship the iOS app withaps-environment. npm run deploy(creates theRoomDO on first deploy).
Smoke test (after deploy)
M=$(curl -s -XPOST https://api.nucleic.blakeslee.xyz/v1/relay/token \
-H "authorization: Bearer $RELAY_ADMIN_SECRET" \
-d '{"roomId":"r1","deviceId":"host1","role":"host"}' | jq -r .token)
C=$(curl -s -XPOST https://api.nucleic.blakeslee.xyz/v1/relay/connect \
-H "authorization: Bearer $M" | jq -r .token)
websocat "wss://relay.nucleic.blakeslee.xyz/relay?t=$C" # then a second client in room r1
APNS delivery must be exercised from the deployed Worker — local
wrangler devcan't do HTTP/2 to Apple (workerd #4841).
Trusted Tester program
The iOS companion ships through TestFlight; rather than hand out the public join link, outside
people apply to become trusted testers (form at website/trusted-tester.html, plus in-app links
in the macOS Remote settings and iOS Settings). Each application is gated behind the owner's
one-click email approval; on approval the owner hand-invites the applicant into the internal
TestFlight group (Apple can't add an outside email to an internal group via API). Source: src/testers.ts.
Endpoints
| Method & path | Auth | Purpose |
|---|---|---|
POST /v1/tester/apply |
open (CORS'd to the site; rate-limited; optional Turnstile) | Site form submits an application → stored pending, owner emailed |
GET /v1/tester/review?id&action&token |
HMAC in the link | Owner clicks Approve/Reject in the email → flips status, renders a page |
- Storage (KV
NUCLEIC_TESTER_APPS):app:<uuid>→ JSON record;email:<addr>dedupe index (a rejected applicant may re-apply);rl:<ip>coarse rate-limit counter. - Review links are stateless HMAC-SHA256 over
"<id>:<action>"(TESTER_APP_SECRET), so only the owner — who receives the email — can act. Approve/Reject is idempotent (safe to re-click). - Owner email uses the
OWNER_EMAILsend_emailbinding, pinned to[email protected], so the Worker can only ever mail the owner. We never email applicants (Apple's TestFlight invite is the applicant-facing mail once the owner adds them).
Provision (one-time)
- KV:
wrangler kv namespace create NUCLEIC_TESTER_APPS; paste the id intowrangler.jsonc. - Secret:
wrangler secret put TESTER_APP_SECRET(random 32+ bytes). - Email: enable Email Routing on the
blakeslee.xyzzone and verify[email protected]as a destination address (one confirmation-link click) so thesend_emailbinding can reach it. Optionallywrangler secret put TESTER_FROM_ADDRESS(defaults to[email protected]). - (Optional) Turnstile: create a widget, add the site key to
website/trusted-tester.html, andwrangler secret put TURNSTILE_SECRET. Without it the form still works (rate-limit + honeypot only). npm run deploy.
Smoke test
curl -i -XPOST https://api.nucleic.blakeslee.xyz/v1/tester/apply \
-H 'content-type: application/json' \
-d '{"firstName":"Ada","lastName":"Lovelace","email":"[email protected]","jobTitle":"Engineer","employer":"AE Ltd","experienceYears":"12","techBackground":"Swift, TS","agentExperience":"Claude Code daily","applePlatform":"iOS 8y","testDevices":"iPhone 15 / iOS 18.1","motivation":"sharp repro bug reports"}'
# → 200 {"ok":true}; the owner receives an email with Approve/Reject links.