resolve api keys at the websocket doors too

there were four doors, not two. the ws upgrade in server.tsx and the
vault notifications socket each verified the jwt themselves, so a key
that worked against /api would have 401'd on cliamp — signed in and can
play audio would have been two different questions for the music app.

both now call resolveAuthToken. verified: owner key upgrades cliamp
(101), bogus key 401, member key 403 on terminal exactly as their jwt
is.

reset-password and verify-token deliberately keep verify() — they read
a purpose-scoped reset token and a key must not be spendable as one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 10:40:04 +00:00
co-authored by Claude Opus 5
parent ae54df7c30
commit ae275ee607
3 changed files with 14 additions and 7 deletions
+6 -2
View File
@@ -3,7 +3,7 @@ import type { ServerWebSocket } from 'bun';
import { serve } from 'bun';
import { honoServer, PROTECTED_API_PREFIXES, UNPROTECTED_API_PREFIXES } from './servers/hono';
import { assertCapabilityTotality } from './servers/capabilities/totality';
import { verify } from './servers/jwt';
import { resolveAuthToken } from './servers/auth-token';
import { isWsProviderAllowed } from './servers/capabilities/authorize';
import { isTokenBlacklisted } from 'officerdb';
import { terminalWebsocket } from './servers/api/terminal/websocket';
@@ -158,7 +158,11 @@ async function upgradeWs(
if (!token) return new Response('Unauthorized', { status: 401 });
try {
const user = await verify(token);
// Same resolver as the two HTTP doors, so a key that works against /api works here too — a music app
// holding one needs cliamp and cliamp-audio, and a socket that only understood JWTs would have made
// "signed in" and "can play audio" two different questions. `jti` is absent on a key, so the
// blacklist below simply does not apply to one; its revocation is a column, checked in the lookup.
const user = await resolveAuthToken(token);
if (!user) return new Response('Unauthorized', { status: 401 });
if (user.jti) {