export type DeclineReason = 'rule' | 'invariant'; /** * The specific boundary a declined write crossed, when the backend can name it * (e.g. a spend cap: `{ type:'rollingSum', field:'amount', cap:1000, * windowSeconds:86400, current:950, attempted:200 }`). */ export interface DeclineBoundary { type: string; field?: string; /** Stable reason when one boundary type has multiple rejection modes. */ cause?: 'cap_exceeded' | 'append_only_update' | 'append_only_delete'; cap?: number | string; windowSeconds?: number; current?: number | string; attempted?: number | string; [key: string]: unknown; } /** * A structured, render-ready explanation of a declined write. `provenAtDeploy` * marks that the crossed boundary was proven to hold against every input at * deploy — the fact the hosted decline card leans on. */ export interface BoundedDecline { verdict: 'declined'; /** 'invariant' (a proven cap/conservation/isolation boundary) or 'rule' (an auth/policy rule). */ reason: DeclineReason | string; /** Invariant name, present when `reason === 'invariant'`. */ invariant?: string; collection?: string; op?: string; boundary?: DeclineBoundary; /** Human-readable, render-ready explanation. */ message: string; /** True when the crossed boundary was proven to hold at deploy. */ provenAtDeploy?: boolean; [key: string]: unknown; } /** The window event the hosted widget listens to for rendering a decline card. */ export declare const DECLINE_EVENT_NAME = "bounded:decline"; /** * Normalize a server rejection body into a structured `BoundedDecline`, or * `null` when the rejection is not a policy/invariant decline. * * Prefers a backend-sent `decline` object verbatim; otherwise synthesizes a * minimal `{ verdict, reason, invariant?, message }` from the legacy envelope * (`verdict` / `reason` / `code` / `invariant`). Only strong signals count — * a bare 403/409 with no policy marker is left alone (returns `null`). */ export declare function deriveDecline(body: any, status?: number): BoundedDecline | null; /** * In a browser, dispatch a `bounded:decline` CustomEvent for the surfaced * decline. Fire-and-forget: guarded for non-browser/SSR (no `window`/ * `CustomEvent`), never throws, and never delays the rejection it accompanies. */ export declare function dispatchDeclineEvent(decline: BoundedDecline, appId?: string): void; /** * A rejected write that violated a proven policy rule or invariant. Thrown by * the data-plane write paths (set/setMany/update/delete) in place of a bare * Error, and attached (as `.decline`) to live-intent rejections. * * Back-compatible: the full server envelope (code/status/statusCode/requestId/ * ...) is copied onto the instance, so existing `catch` handlers keep working; * new code reads `.decline`. Detect it with `err.name === 'BoundedDeclineError'` * or the bundle-copy-safe `err.isBoundedDecline === true`. */ export declare class BoundedDeclineError extends Error { /** Stable discriminant that survives multiple bundled SDK copies (no `instanceof`). */ isBoundedDecline: true; decline: BoundedDecline; code?: string; status?: number; statusCode?: number; requestId?: string; constructor(decline: BoundedDecline, envelope?: Record); }