browser relay: multi-session override, stale session recovery, better error feedback
- relay accepts new extension connections by closing old one (last wins, code 4000) - extension recognizes code 4000 and stops auto-reconnect (shows "replaced" badge) - fix ping interval race where old WS close handler killed new connection's pings - retry CDP commands on "Session with given id not found" by re-attaching debugger - describeError() maps known errors to user-friendly badge tooltips - persisted relay tokens restored on server start - user-scoped token salts, token regeneration/deletion endpoints - extension download endpoint, integrations UI for browser relay setup - browser relay env vars passed to pi-bridge sandboxes - browser screen layout with chat panel and prompt prefix Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,20 +8,31 @@ if (!JWT_SECRET) {
|
||||
throw new Error('JWT_SECRET is required for browser relay auth');
|
||||
}
|
||||
|
||||
export function deriveRelayToken(userId: number, port: number): string {
|
||||
export function deriveRelayToken(userId: number, port: number, salt: string): string {
|
||||
return createHmac('sha256', JWT_SECRET!)
|
||||
.update(`${RELAY_TOKEN_CONTEXT}:${port}:${userId}`)
|
||||
.update(`${RELAY_TOKEN_CONTEXT}:${port}:${userId}:${salt}`)
|
||||
.digest('hex');
|
||||
}
|
||||
|
||||
const tokenToUser = new Map<string, number>();
|
||||
|
||||
export function registerUserToken(userId: number, port: number): string {
|
||||
const token = deriveRelayToken(userId, port);
|
||||
export function registerUserToken(userId: number, port: number, salt: string): string {
|
||||
const token = deriveRelayToken(userId, port, salt);
|
||||
tokenToUser.set(token, userId);
|
||||
return token;
|
||||
}
|
||||
|
||||
export function unregisterUserToken(token: string): void {
|
||||
tokenToUser.delete(token);
|
||||
}
|
||||
|
||||
export function restoreUserTokens(entries: Array<{ userId: number; salt: string }>, port: number): void {
|
||||
for (const { userId, salt } of entries) {
|
||||
const token = deriveRelayToken(userId, port, salt);
|
||||
tokenToUser.set(token, userId);
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveUserFromToken(token: string): number | null {
|
||||
return tokenToUser.get(token) ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user