# error-codes _(no submodules)_ ## Purpose Stable error-code registry for `@suaveplan/api-plugin-payment`. Every failure path in the plugin raises a `PaymentPluginError` that carries one of 15 `PAYMENT_PLUGIN.*` codes. The registry gives consumers a small, well-documented enum to programmatically branch on without inspecting human-readable messages — exactly the contract every other `@suaveplan/api-plugin-*` package follows. The module also exports the `PaymentPluginError` class, which extends `SuaveplanError` so `instanceof PaymentPluginError` narrows `code` to the typed enum at the call site. The class preserves the supplied code on the discriminant `pluginCode` field for compatibility with downstream error handlers that match on a package-specific property name (the auth plugin uses `authCode`, the openapi plugin uses `openapiCode` — this package uses `pluginCode`). ## Features - 15 namespaced codes under `PAYMENT_PLUGIN.` covering input validation, ownership/anti-enumeration, provider failures, webhook signature/timestamp, idempotency conflict, state-machine, amount/currency mismatch, refund-exceeds-captured, configuration, and service-registry plumbing. - Typed `PaymentPluginErrorContext` carrying `statusCode`, `intentId`, `ownerId`, `missing[]`, `prefix`, `currency`, `expectedCurrency` for diagnostic plumbing. - `PaymentPluginError` discriminant class with `pluginCode` and the standard `SuaveplanError` cause-chain, `toJSON`, `toProblemJSON`, and OTel span-event hooks. ## Usage: Basic ```ts import { PAYMENT_PLUGIN_CODES, PaymentPluginError, } from "@suaveplan/api-plugin-payment"; throw new PaymentPluginError( PAYMENT_PLUGIN_CODES.NOT_FOUND, 'Payment intent "abc" not found', { context: { statusCode: 404, intentId: "abc" } } ); ``` ## Usage: Advanced ```ts try { await service.captureIntent({ id, ownerId, amount }); } catch (err) { if (err instanceof PaymentPluginError) { switch (err.pluginCode) { case PAYMENT_PLUGIN_CODES.NOT_FOUND: return c.json({ error: "not_found" }, 404); case PAYMENT_PLUGIN_CODES.CURRENCY_MISMATCH: case PAYMENT_PLUGIN_CODES.AMOUNT_MISMATCH: return c.json({ error: err.pluginCode }, 422); case PAYMENT_PLUGIN_CODES.IDEMPOTENCY_CONFLICT: return c.json({ error: "conflict" }, 409); } } throw err; } ``` ## API Reference - `PAYMENT_PLUGIN_CODES` — `defineCodes("PAYMENT_PLUGIN", [...])` const-object. - `PaymentPluginErrorCode` — union of the 15 `PAYMENT_PLUGIN.*` strings. - `PaymentPluginErrorContext` — optional discriminant fields carried alongside the base `SuaveplanError` context. - `PaymentPluginError extends SuaveplanError` — `pluginCode: PaymentPluginErrorCode`. ## Implementation Notes The 15-code count matches the proposal's spec delta. Removing a code (because no production call site currently uses it) is banned by `AGENTS.md §2c` — codes are part of the public API contract and unused-looking codes get wired into call sites that didn't exist yet (e.g. `PROVIDER_NOT_CONFIGURED` covers a programmatic mis-wire pattern callers do hit during initial integration). The conformance test in `api-plugin-payment.spec-conformance.test.ts` proves every code is reachable from a non-test call site.