/** * `PRE_GENERATION_REFUSAL_CODES` — the closed registry of refusal codes * (ggui#786). * * A **pre-generation refusal** is a deployment declining a call BEFORE * it does any work: no state read, nothing committed, no model spend. * (The call has already passed the SDK's check against the declared * `inputSchema`; the claim is nothing READ, not nothing validated.) * It is a third outcome, not a failure — a failure describes work * that ran and did not produce a result. The wire shape * of a refused render lives in `../schemas/mcp.ts` * (`renderRefusalSchema`); this file owns the NAMES. * * ## Why one file * * The registry is the anti-drift mechanism: one `code` namespace across * every surface a deployment can refuse on, so two names can never mean * the same state and one name can never mean two. Emitters read a row * from here; they never mint a code literal of their own. A code that * is not in this file fails the wire enum at the transport, loudly — a * bug, never a wire state. * * ## The rules every row obeys * * - **Name the STATE, not the verb.** `subscription_exists`, not * `cannot_create_subscription`: the same state may refuse more than * one action later, and the code must not encode which. * - **One state, one code.** Two codes never share a name; one code MAY * list several `surfaces` when a single state surfaces in more than * one place (`billing_mode_anomaly`). * - **`retry` is defined from the CALLER's side.** `after-fix` — a * named party can act and the SAME call then succeeds; `next-period` * — time restores it at the next period boundary; `later` — * unbounded time (transient unavailability); `never` — no action by * the caller restores the call under this identity. * - **`fixBy` names WHO acts.** REQUIRED on every `after-fix` row; * PERMITTED on a `later` row (naming the operator who restores a * surface that is transiently unavailable); FORBIDDEN on * `next-period` and `never` — time restores the first and nothing * restores the second, so naming a party would be a lie about who * can act. **An agent MUST NOT auto-retry an `after-fix` refusal * whose `fixBy` is not `caller`** — otherwise "retry after fix" * would mean "perform someone else's billing or policy decision on * their behalf". `caller` is the only value an agent may act on * itself. * - **`emitter` is named.** A row whose emitter is unrecorded is the * drift the registry exists to prevent. * * ## Reading this file as a self-hoster * * Every `description` here ships to npm, and the render-gate subset * reaches an agent as JSON-Schema metadata through `tools/list`. The * wording is therefore written from the DEPLOYMENT-POLICY perspective * ("the allowance this deployment configured for the app is * exhausted"), never from an operator's internal vocabulary. A * deployment that configures none of these policies emits none of these * codes; the registry is the vocabulary, not a mandate. */ /** * The surfaces a refusal code may be emitted on. * * - `render-gate` — the pre-generation gate on the render/mutation * tools. These are the only codes that can appear in a refused * tool result's `refusal.code`. * - `owner-api` — an app owner's own billing mutations. * - `provisioning-api` — a tenant provisioning an app on behalf of * its own users. * - `mcp-endpoint` — the per-app MCP endpoint's authorization, on * any JSON-RPC request (`initialize` included). The refusal rides * the JSON-RPC error object's `data.refusal` (HTTP 403, error code * `-32003` `APP_NOT_FOUND`, message `App not found` — ggui#836); only the codes listed * here are ever typed there, and an authorization failure that is * NOT one of them stays a bare 403 by contract, so a client can * never learn which of the untyped arms it hit. */ export declare const REFUSAL_SURFACES: readonly ["render-gate", "owner-api", "provisioning-api", "mcp-endpoint"]; /** One member of {@link REFUSAL_SURFACES}. */ export type RefusalSurface = (typeof REFUSAL_SURFACES)[number]; /** The closed `retry` vocabulary — see the file header for semantics. */ export declare const REFUSAL_RETRIES: readonly ["after-fix", "next-period", "later", "never"]; /** One member of {@link REFUSAL_RETRIES}. */ export type RefusalRetry = (typeof REFUSAL_RETRIES)[number]; /** * Who can act on an `after-fix` refusal. Only `caller` is the agent * itself — see the no-auto-retry rule in the file header. */ export declare const REFUSAL_FIX_BY: readonly ["caller", "owner", "tenant", "operator"]; /** One member of {@link REFUSAL_FIX_BY}. */ export type RefusalFixBy = (typeof REFUSAL_FIX_BY)[number]; declare const REFUSAL_ROWS: { readonly unsupported_provider: { readonly code: "unsupported_provider"; readonly surfaces: readonly ["render-gate"]; readonly retry: "after-fix"; readonly fixBy: "owner"; readonly emitter: "a deployment's generation gate, provider arm"; readonly description: "The provider behind the requested model is not one this deployment can fund for the app. The app owner picks a funded provider or configures the app with its own credentials."; }; readonly insufficient_credit: { readonly code: "insufficient_credit"; readonly surfaces: readonly ["render-gate"]; readonly retry: "after-fix"; readonly fixBy: "owner"; readonly emitter: "a deployment's generation gate, balance arm"; readonly description: "The balance this deployment funds the render from is at or below zero — pool or BYOK lane alike — so nothing renders under it. The owner adds credit, after which the same call succeeds."; }; readonly hard_cap_exceeded: { readonly code: "hard_cap_exceeded"; readonly surfaces: readonly ["render-gate"]; readonly retry: "next-period"; readonly emitter: "a deployment's generation gate, cap arm"; readonly description: "The app reached the hard ceiling this deployment set for the current period. Nothing the caller or the owner does lifts it before the period rolls over."; }; readonly model_not_allowed: { readonly code: "model_not_allowed"; readonly surfaces: readonly ["render-gate"]; readonly retry: "after-fix"; readonly fixBy: "caller"; readonly emitter: "a deployment's generation gate, model arm"; readonly description: "The requested model is not one this account has been granted on this deployment. The caller picks a granted model and retries with the same handshakeId — the one render-gate state an agent may act on itself."; }; readonly managed_default_cap_exceeded: { readonly code: "managed_default_cap_exceeded"; readonly surfaces: readonly ["render-gate"]; readonly retry: "after-fix"; readonly fixBy: "tenant"; readonly emitter: "a deployment's generation gate, delegated-policy arm"; readonly description: "The app is running on the default ceiling because the tenant that provisioned it has declared no policy of its own, and that ceiling is reached. The tenant declares an explicit policy for the app."; }; readonly app_policy_missing: { readonly code: "app_policy_missing"; readonly surfaces: readonly ["render-gate"]; readonly retry: "after-fix"; readonly fixBy: "tenant"; readonly emitter: "a deployment's generation gate, delegated-policy arm"; readonly description: "The app exists but carries no policy yet — the window between provisioning it and declaring what it may spend. The tenant declares the policy."; }; readonly billing_mode_anomaly: { readonly code: "billing_mode_anomaly"; readonly surfaces: readonly ["provisioning-api", "render-gate"]; readonly retry: "never"; readonly emitter: "a deployment's provisioning guard and its generation gate, reading the same record"; readonly description: "The app record declares a funding mode this deployment does not recognise, or declares none at all. The value is reported as read and never coerced — an unreadable record is not a policy."; }; readonly issuer_rate_limited: { readonly code: "issuer_rate_limited"; readonly surfaces: readonly ["render-gate"]; readonly retry: "later"; readonly emitter: "the per-issuer render-rate cap's denial"; readonly description: "Calls arriving under this issuing identity are over the rate this deployment allows. Time restores it; retry shortly."; }; readonly app_rate_limited: { readonly code: "app_rate_limited"; readonly surfaces: readonly ["render-gate"]; readonly retry: "later"; readonly emitter: "the per-app render-rate cap's denial"; readonly description: "This app is rendering faster than the rate this deployment allows it. The cap is the app’s own, not the issuing identity’s — the two are separate states with separate codes. Time restores it; retry shortly."; }; readonly app_deprovisioned: { readonly code: "app_deprovisioned"; readonly surfaces: readonly ["render-gate", "mcp-endpoint"]; readonly retry: "never"; readonly emitter: "the generation gate's owner-claim check, before any reservation or metering"; readonly description: "The app record has no owner claim any more — either the claim was removed, or the record names no issuing tenant at all. A record with no owner cannot be funded, so nothing renders under it and no caller action restores it."; }; readonly billing_path_missing: { readonly code: "billing_path_missing"; readonly surfaces: readonly ["render-gate"]; readonly retry: "after-fix"; readonly fixBy: "owner"; readonly emitter: "the generation gate's fall-through arm: a non-playground identity that resolves to no billing path (not a managed app, not a credit holder)"; readonly description: "The caller has no billing subject on this deployment, so nothing renders under it. The owner provisions one — a managed policy, or credit. Unlike `billing_mode_anomaly` — an app record that exists and declares a funding mode this deployment cannot read — no record arm applies here: there is simply no subject to bill. A deployment MAY suppress this refusal by operator override; that switch is deployment policy, not a wire state."; }; readonly checkout_unavailable: { readonly code: "checkout_unavailable"; readonly surfaces: readonly ["owner-api"]; readonly retry: "later"; readonly fixBy: "operator"; readonly emitter: "a deployment's owner billing mutations"; readonly description: "The surface that adds credit (a top-up) is unavailable on this deployment right now — unconfigured, or its provider is down. Only the operator can restore it."; }; readonly owner_ref_mismatch: { readonly code: "owner_ref_mismatch"; readonly surfaces: readonly ["provisioning-api"]; readonly retry: "after-fix"; readonly fixBy: "tenant"; readonly emitter: "a deployment's provisioning guard"; readonly description: "The owner reference the caller supplied is not the one recorded on this app. The refusal names the route and the app, never the recorded reference. The tenant re-derives the reference and retries."; }; readonly policy_version_stale: { readonly code: "policy_version_stale"; readonly surfaces: readonly ["provisioning-api"]; readonly retry: "after-fix"; readonly fixBy: "tenant"; readonly emitter: "a deployment's provisioning guard, policy-write arm"; readonly description: "The policy write carries a version older than the one stored, so it would overwrite a newer decision. The refusal reports the stored version; the tenant re-derives from it and writes again."; }; }; /** A refusal code = a registry key. Derived; never a second list. */ export type RefusalCode = keyof typeof REFUSAL_ROWS; /** * A registry row, as consumers read it. Normalized (not the literal * row union) so `PRE_GENERATION_REFUSAL_CODES[code]` for any * {@link RefusalCode} exposes `fixBy` as `RefusalFixBy | undefined` * rather than a union in which some rows lack the property. The * literal rows above still derive {@link RefusalCode}, enforce * `code === key`, and enforce the retry/fixBy pairing. */ export interface RefusalRow { readonly code: RefusalCode; readonly surfaces: readonly RefusalSurface[]; readonly retry: RefusalRetry; readonly fixBy?: RefusalFixBy; readonly emitter: string; readonly description: string; } /** The registry consumers read. */ export declare const PRE_GENERATION_REFUSAL_CODES: Readonly>; /** * The SAME registry object with its per-key literal types kept * (ggui#889): `PRE_GENERATION_REFUSAL_ROWS.app_rate_limited.code` is * `'app_rate_limited'`, its `retry` is `'later'`. The normalized view * above erases those literals so `fixBy` reads uniformly; a producer * that must satisfy a wire enum from a row (the registry-purity pin * forbids the literal in source) reads it here — no parse, no literal. */ export declare const PRE_GENERATION_REFUSAL_ROWS: typeof REFUSAL_ROWS; /** * The codes on one surface, derived type-level from the literal rows' * `surfaces` tuples. A runtime `.filter()` cannot narrow a type, so the * union is computed here and the tuple below is proved complete * against it. */ type CodesOnSurface = { [K in RefusalCode]: S extends (typeof REFUSAL_ROWS)[K]['surfaces'][number] ? K : never; }[RefusalCode]; /** * A code that can appear in a refused tool result's `refusal.code` — * i.e. one whose `surfaces` include `render-gate`. Derived, so an * owner-api or provisioning-api code is not even expressible on the * render wire. */ export type PreGenerationRefusalCode = CodesOnSurface<'render-gate'>; /** * A code that can appear in a per-app MCP endpoint refusal's * `error.data.refusal.code` — i.e. one whose `surfaces` include * `mcp-endpoint` (ggui#825). Derived, so a render-gate-only code is not * expressible on the transport wire. */ export type McpEndpointRefusalCode = CodesOnSurface<'mcp-endpoint'>; /** * Every render-gate code, as the literal tuple the wire enum * (`renderRefusalSchema.code`) is built from. Order is the registry's. */ export declare const RENDER_GATE_REFUSAL_CODES: readonly ["unsupported_provider", "insufficient_credit", "hard_cap_exceeded", "model_not_allowed", "managed_default_cap_exceeded", "app_policy_missing", "billing_mode_anomaly", "billing_path_missing", "issuer_rate_limited", "app_rate_limited", "app_deprovisioned"]; /** * Every mcp-endpoint code, as the literal tuple the transport wire enum * (`transportRefusalSchema.code`) is built from — the refusals a per-app * MCP endpoint's authorization types on `error.data.refusal` * (ggui#825). Order is the registry's. */ export declare const MCP_ENDPOINT_REFUSAL_CODES: readonly ["app_deprovisioned"]; /** * A code an owner-API billing mutation may refuse with — i.e. one whose * `surfaces` include `owner-api`. Derived, so a render-gate code is not * expressible on an owner-API refusal. Registry v11 (ggui#960): the * plan-era owner-api rows retired with the plan model; one owner billing * surface remains — adding credit. */ export type OwnerApiRefusalCode = CodesOnSurface<'owner-api'>; /** * Every owner-api code, as the literal tuple a backend's owner-API * refusal helper types its `code` from (ggui#960). Order is the * registry's. */ export declare const OWNER_API_REFUSAL_CODES: readonly ["checkout_unavailable"]; export {}; //# sourceMappingURL=refusal-codes.d.ts.map