Conversation
Postgres relay state (hashed bearer secrets, single-use consumption, per-account caps), the Pocket-facing setup/sign-in/reauth/burrows routes with the self-host Relay's shapes and error strings, the ADMIN_EMAIL entitlement on every Burrow-authenticated request, Pocket at the relay root under its own policy, and Pocket using the account id its Relay answers instead of 'owner'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes on the Hosted Relay: per-address limits on every unauthenticated route that reaches Postgres, entitlement rechecked with each session or Burrow token in one lookup, a dead setup token restored without evicting a live one, headers classified on the decoded path, one asset fetch per Pocket deep link, no /api/hello, and Pocket's passkey named "Dormouse Pocket (<host>)". Registration and sign-in checks now live once in remote-lib-common for both Relays; capped inserts take four round trips and an hourly cron sweeps expiry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Burrow asks relay.dormouse.sh for a code, the person approves it at hosted.dormouse.sh/enroll with a recent login, and the Burrow's poll redeems the approval once, atomically, as a Burrow owned by the approver. The account page lists enrolled computers with Remove. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes: the device code carries its own expiry and the user code is an HMAC of it under RELAY_ENROLL_SECRET, so no unauthenticated route writes a row; approval stores the only row, and poll redeems it atomically. Remove deletes the Burrow row; Burrow-side response guards move to the desktop stage; the cookie gate no longer needs the login's age outside approval; and /enroll takes a new fragment without reloading the account page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deploying mouseterm with
|
| Latest commit: |
2746583
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://bd3b6100.mouseterm.pages.dev |
| Branch Preview URL: | https://remote-network-hosted-relay.mouseterm.pages.dev |
Miniflare counts each limit in fixed 60 s windows, so a test sending exactly the limit then expecting 429 failed when a window rolled over mid-test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dormouse-bot
left a comment
There was a problem hiding this comment.
Draft feedback on work in progress, not a merge verdict. Mark the PR ready when you want the full review.
The PR moves pocketContentSecurityPolicy from relay/src/app.ts into remote-lib-common/src/remote/relay-common.ts. It updates the pointers in pocket-app.md and security-hosted.md, but docs/specs/terminal-escapes.md still says pocketContentSecurityPolicy in relay/src/app.ts in its CSP Source of truth: line. That file still imports the function, so spec-lint's path check passes, but the pointer now leads to a caller rather than to the definition.
The Postgres suite drives the shared test harness, which imports the built package; the Hosted verify job ran it before anything had built it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dormouse-bot
left a comment
There was a problem hiding this comment.
No findings on the diff. I'm holding the approval only because of the Argos checks: argos/storybook-chromium and argos/storybook-webkit each report 33 changed snapshots awaiting a decision. #867 (this PR's base) and #869 report the same 33, and this PR touches no Storybook component, so the diffs most likely come from the base branch. Accepting them in Argos (or on #867) clears the gate.
Second of the Hosted persistent stack, on #867. It adds the multi-tenant Relay's HTTP half (saas-multitenant in
docs/specs/relay.md). Sockets (Durable Objects) are the next PR, and push the one after.Relay on
relay.dormouse.sh:API_ROUTES, request/response shapes, and error strings as the self-host Relay, so Pocket and the Burrow need no Hosted special case. The account id on the wire is the Hosted user id; Pocket now uses the id its Relay answered instead of hard-coding'owner'.002_relay.sql):ADMIN_EMAIL. It is rechecked on every session and Burrow-token use, with one lookup.remote-lib-common, shared by both Relays.Device-code enrollment:
POST /api/burrow/enroll/begin, which stores nothing: the device code carries its own expiry, and the user code is an HMAC of the device code underRELAY_ENROLL_SECRET.hosted.dormouse.sh/enroll(recent login, exact Origin, admin, per-account limit). Approval is the only row written.The account page lists enrolled computers, with Remove (which deletes the row). The desktop half is the client-integration PR.
Operator step before production:
wrangler secret put RELAY_ENROLL_SECRET --config wrangler.relay.jsonc(production preflight requires it).Test plan
pnpm testgreen; Hosted Docker suite 94/94 (Postgres route tests: tenant isolation, racing polls, forged device codes, recent-login refusal, removal cascade)./enrolldriven locally withdor agent-browseragainstdor tool hosted, before the begin-stores-nothing rework.curl -X POST <relay>/api/burrow/enroll/begin -d '{"origin":"<relay>"}', then poll it and see the computer listed.Local note:
dor tool hostedfails at start with "Applied migration changed or missing: 002_relay.sql" in a worktree whose dev database predates the in-place migration edit; drop that worktree'spgstencil_devdatabase to reset it.🤖 Generated with Claude Code