Commit Graph
4 Commits
Author SHA1 Message Date
pastilhasandClaude Opus 5 f063fc0c08 remove origin validation
ALLOW_ANY_ORIGIN, ALLOW_ANY_ORIGIN_MUSIC, and everything they gated. The flag
defaulted to ON, so none of it ran on a real install — what comes out is
documented defence in depth that was already switched off. The file said so
itself: "Both flags and their call sites come out once the tailnet is the
perimeter."

Origin was never authentication here in any case. An app's `officer://<hex>`
origin is chosen by the client, forgeable outside a browser, and extractable from
a shipped binary.

Gone: the two flags, isOriginAllowed, isOriginCheckDisabled, isMusicOriginExempt,
originValidationMiddleware, ORIGIN_RULES and the whole OFFICER_<APP>_ORIGIN
scheme, PUBLIC_URL's origin/host derivation, and origin-validation.test.ts, which
existed only to pin them. CORS now echoes whatever Origin it is given, which is
what every install already did.

What SURVIVES is the reason this needed care. origin-validation.ts held two
unrelated things, and the second was the global authorization gate — a valid
non-owner token reaches only what its role grants, deliberately NOT under the
flag because it is account-based rather than origin-based. Its own comment called
it "the airtight half". Deleting the file wholesale would have deleted
authorization.

So it moves to _middlewares/capability-gate.ts as capabilityGateMiddleware, with
the name matching what it does: nothing in it reads an Origin header any more.
hono.ts mounts it in the same position, ahead of every router.

origin-middleware.ts stays and is untouched — it extracts the Origin for six auth
handlers that log it, and for passkeys. Extraction, not validation.

Also updates every claim that rested on the old model: CLAUDE.md's security
section and repo map, docs/secret-store.md, docs/mobile-api-keys.md, and five
messages in machine-setup's Tailscale section which told the owner to set
ALLOW_ANY_ORIGIN=false when declining a tailnet. That advice is now impossible to
follow, and the honest version is different: with no tailnet the token is the
whole lock, so put a proxy in front and restrict who can reach it.

Not typechecked (empty node_modules, frozen installs). Every changed file parses;
the setup section was run and writes four variables now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 00:15:25 +00:00
pastilhas 9974736587 mobile-api-keys: record what the client actually does now
The client half exists in monorepo-mobile as of f29774a, with OffChat as the
proof of concept, so this document is no longer purely forward-looking. Adds a
section covering what shipped, the two places the advice here was wrong about
the client — one key per app is not possible on mobile (shared-session puts one
credential in front of all nineteen apps), and signout was never the problem,
distress signout was — and two decisions worth a second opinion: clearing the
credential on 401 only, and leaving the traded-in JWT to expire rather than
blacklisting it, because that handler clears vault tokens keyed on the user.
2026-08-08 16:26:06 +00:00
pastilhasandClaude Opus 5 8987898dd7 prettier: mobile-api-keys tables
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 10:44:54 +00:00
pastilhasandClaude Opus 5 555da9a170 api key contract for the mobile developer
docs/mobile-api-keys.md — what the server accepts, what changes in
monorepo-mobile, and the 401-vs-403 distinction, which is the one that
bites: clearing a good key on a 403 turns a member's missing capability
into a logout loop they cannot escape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 10:44:41 +00:00