/** * Admin / console HTTP surface: a mountable Hono sub-app over a * `SyncularAdmin`. JSON endpoints mirror the admin surface; a single static * HTML page (zero framework, no build step) at `GET /` renders them. * Hosts mount it through `createSyncularHono({ admin })` or * `createWorkersFetchHandler({ admin })`; this module is their shared * implementation. * * The auth seam is REQUIRED. There is NO default-open admin: the factory * refuses to mount without a host-provided `authorize` guard (it throws at * construction). Every request runs the guard first; a falsy result is a * 401. Admin is a privileged surface (it reads every partition's clients, * rows, commits, scope activity, and reactions) and authorization is * entirely the host's and mandatory. The operator actions (`POST` routes) * additionally require `authorizeActions`; without it they answer 403. */ import { type SyncularAdmin, type SyncularErrorHandler, type SyncularErrorMapper } from '@syncular/server'; import { Hono } from 'hono'; export interface AdminAuthContext { /** * The partition the request targets: `?partition=`, else the only * partition of the deployment. Empty for the page without `?partition=` * and for `GET /partitions`, which spans every partition. */ readonly partition: string; readonly request: Request; } /** The console guards, shared by the Hono and Workers `admin` options. */ export interface SyncularAdminGuards { /** * REQUIRED host guard. Return `true` (or a truthy value) to allow the * request, a falsy value to reject it with 401. Runs before every admin * endpoint, including the HTML page. There is no default — omitting it * throws, by design (no default-open admin). */ readonly authorize: (ctx: AdminAuthContext) => boolean | Promise; /** * Guard for the operator actions (retry a dead-lettered reaction, prune, * revoke a lease), run after `authorize`. A falsy result answers 403 * `sync.forbidden`. Omitted ⇒ every action answers 403 and `GET /info` * reports `actions: false`. */ readonly authorizeActions?: (ctx: AdminAuthContext) => boolean | Promise; } /** @internal The adapters' route options; hosts use their `admin` option. */ export interface SyncularAdminRoutesOptions extends SyncularAdminGuards { /** * Serve every partition-scoped request elsewhere once the guards pass. * The page and `GET /partitions` stay local. The Workers adapter forwards * to the partition's Durable Object, whose event ring sees that * partition's sync rounds. */ readonly forward?: (request: Request, target: { readonly partition: string; readonly actions: boolean; }) => Promise; /** * Host error reporting: receives every exception that is not a * `SyncError`, which answers 500 `sync.internal_error` (§10.2). */ readonly onError?: SyncularErrorHandler; /** * Optional synchronous mapper (§10.2) for those exceptions; return a catalog * `SyncError` to answer with it, or `undefined` for `sync.internal_error`. */ readonly mapError?: SyncularErrorMapper; } /** * @internal Build the admin sub-app the adapters mount. Throws if * `authorize` is missing — admin never mounts default-open. */ export declare function createSyncularAdminRoutes(admin: SyncularAdmin, options: SyncularAdminRoutesOptions): Hono<{ Variables: { partition: string; }; }>;