import type { Request, Response } from "express"; /** * v2.2.0 reactive dashboard — WebSocket push + /api/snapshot refetch. * Vanilla JS, no build step, no dependencies. Mounted at GET / + /dashboard. * * Info-disclosure policy for `snapshotApi` (v2.2.0, supersedes the v2.1 * Phase 4d note that used to live here): * - agents: `AgentWithStatus` (`toAgentWithStatus` in db.ts) strips * `token_hash` and exposes `has_token: boolean`. NEVER surfaces the * bcrypt hash or any raw token. * - webhooks: the HMAC `secret` IS NOT THE ONLY CREDENTIAL. A webhook `url` * for an incoming-hook service (Slack/Discord/…) IS itself a credential — * possession of the string is enough to post as the operator, so an * unauthenticated caller reading it ACQUIRES that power (ADR-0006: power * from identity, never network position; who AUTHORED the value is * irrelevant). This comment's prior version redacted only the field NAMED * `secret`, declared webhooks handled, and shipped the credential in the * adjacent `url` — field-name-as-proxy, the birthplace of this leak. By * classification: `has_secret` (bool) + `event` (WebhookEventEnum, a * declared set) are structural and exposed; the raw HMAC `secret` never is; * the `url` is reduced to its `url_host` for an unauthenticated caller (full * `url` only when authenticated); and the free-text `filter` is excluded. * - messages / tasks: an AUTHENTICATED caller (verified dashboard secret) gets * the full rows — raw `content` / `description` / `result` (ciphertext only * IF a keyring is configured; PLAINTEXT otherwise, since at-rest encryption * is opt-in) plus decrypted `*_preview` fields. An UNAUTHENTICATED caller * gets an ALLOWLISTED metadata view (see `*_PUBLIC_FIELDS`) with NO content * column of any kind — shipping the raw column would leak plaintext by * default. ADR-0006 (2026-07-25) corrects the prior v2.2.0 note twice over: * it claimed any caller reaching the preview "could already call * get_messages for the same content" (FALSE — get_messages is scoped to the * caller's OWN token-bound inbox, never another agent's), AND it assumed the * raw column was safe because "encrypted" (FALSE by default). Location is * not a principal: unauthenticated → `restricted`, and `restricted` means * the content is genuinely absent from the body, not merely un-previewed. * - webhook_delivery_log with its `error_text` is NOT returned by * snapshotApi. If a future change adds it, redact internal-looking * paths + IPs before surfacing. */ export declare function renderDashboard(_req: Request, res: Response): void; /** * v2.1 Phase 4b.3: keyring info API. * * Returns { current, known_key_ids, legacy_key_id, legacy_row_counts }. * NEVER returns the raw key material. Counts are across all 5 encrypted * columns and only include rows that still carry a legacy (enc1:) prefix * — the signal operators need to see rotation progress without exposing * the actual keys. */ export declare function keyringApi(_req: Request, res: Response): void; /** * JSON API for the dashboard — returns a snapshot of relay state. * GET /api/snapshot * * The body carries absolute timestamps only and NO server-now, so it is stable * between substantive changes; a strong ETag over it + server-now in the `Date` * header give a working If-None-Match / 304 contract (server-now rides the 304, * which has no body). See the body-construction comment below. */ export declare function snapshotApi(req: Request, res: Response): void; //# sourceMappingURL=dashboard.d.ts.map