/** * Shared `authorize`-hook runner. * * Both the method dispatcher (`dispatcher.ts`) and the worker-side aux routes * (`server/auxiliary-routes.ts`) let an author deny a call by throwing from an * `authorize` hook. They MUST agree on the wire semantics: an already-typed * `AuthorizationDeniedError` passes through unchanged (so callers can attach * hints), and any other thrown error is wrapped into `AuthorizationDeniedError` * (→ `PERMISSION_DENIED` / HTTP 403). Centralised here so the two call sites * cannot drift — previously the aux routes awaited `authorize` directly, so a * plain `Error` thrown to deny leaked out as a 500 instead of a 403. */ import { AuthorizationDeniedError } from './errors.js' export async function runAuthorize( hook: (ctx: C) => void | Promise, ctx: C, ): Promise { try { await hook(ctx) } catch (err) { if (err instanceof AuthorizationDeniedError) throw err throw new AuthorizationDeniedError( err instanceof Error ? err.message : 'Authorization denied', err, ) } }