/** * WHO refused a connector delivery — the fact the integration drawer was getting wrong (#841). * * A `connector:` dispatch crosses two authorities before it is over. On the way to * the bytes it calls back into the VERTICAL — opening the bound attachment, invoking the * return-path operation — and that call is checked against the connection's grants. Only once * those pass does anything reach the provider. Both ends refuse by throwing, both throws * landed in the same `lastError` string, and nothing recorded which was which. * * So the drain asked `isTerminalProviderError`, which reads a bare numeric `status` — and * every `SubstratError` carries one from the problem catalog. A `permission denied: * protocol:read` raised inside the vertical answered `true`, and the delivery was journaled * as *"a client error the provider will refuse identically on retry"*. Scrive never saw that * request. The operator went and audited their Scrive account, pressed **Test connection** * (which passes, because the credential is fine), and concluded the platform was broken. * * The classification is structural, in falling order of confidence. Nothing here parses prose * to decide the ORIGIN — only, at the very end, to recover a permission key a vertical too * old to send one has already spelled out in its message. */ import { type PlatformRequestFailure } from '@substrat-run/contracts'; /** * Attribute one failed dispatch. * * 1. **A `ControlPlaneError` is always ours.** It is constructed in exactly one place — when a * call WE made to the vertical's `/internal` surface came back non-2xx — so whatever status * it carries is the vertical's answer to the platform, never the provider's to us. This is * the rule that fixes the reported bug, and it needs nothing from the vertical: a 403 raised * by a deployment that predates this change is still attributed correctly. * 2. **A taxonomy code is ours.** A `SubstratError` thrown in-process by the connector or the * host it runs in — read by shape, so a duplicate package copy or a serialising hop does * not change the answer. * 3. **A bare HTTP status is the provider's.** What is left after the two rules above is an * error a connector raised from a real response: `ScriveApiError` and every future * connector's equivalent, recognised structurally rather than by class. * 4. **Anything else is `unknown`** — a socket that never opened, a bug, a thrown string. Not * `provider`: "we could not tell" must never be printed as somebody's words. */ export declare function attributeFailure(error: unknown): PlatformRequestFailure; /** * The sentence journaled beside a terminal failure, in the voice of whoever actually refused. * * This string is what an operator reads first, and the one it replaces was actively * misleading — it named the provider for a refusal the provider never made. Each branch now * says who refused and what that implies for a retry, and only the `provider` branch quotes * the failure as their answer. */ export declare function terminalFailureNote(failure: PlatformRequestFailure, provider: string): string; //# sourceMappingURL=failure-attribution.d.ts.map