/** * Gateway Export Records Extension Schema * * Extension namespace: `org.peacprotocol/gateway-export` * Record type URIs: 8 (see GATEWAY_EXPORT_TYPE_URIS) * * Records caller-reported observations of payment-gateway / facilitator * settlement-recovery events. The caller observed the event; the caller's * issuer is the signer-of-record. PEAC provides the record format, * validation, and signing path. PEAC does not settle transactions, route * payments, contact gateways, verify on-chain state, monitor settlements, * enforce recovery policy, or resolve settlement disputes. Recovery * decisions are reported by the caller; the record describes what the * caller observed. * * Trigger-vs-state invariant: * Gateway Export Records define 8 PEAC receipt-type URIs. Seven * correspond to observed settlement/recovery states: pending, confirmed, * unresolved, polling, confirmed_late, failed, and failed_orphaned. One * URI, gateway-facilitator-timeout-observed, records the * facilitator-timeout trigger event itself. PEAC does NOT introduce a * new settlement state; it records an observable gateway boundary * signal that may precede unresolved recovery. * * This profile is a 7-state settlement/recovery model plus one * PEAC timeout-trigger observation. It is not an 8-state gateway * state machine. Upstream payment-facilitator state-machine designs * are cited as informative references; PEAC schema names, error codes, * type URIs, and normative text stay PEAC-neutral. * * Single-canonical-money-field invariant: * The base `amount_minor` field (AmountMinorStringSchema) is the only * monetary field on a gateway-export record. When the caller-reported * EIP-3009-style four-tuple references (payer_ref / pay_to_ref / * nonce_ref) are present, `amount_minor` represents the four-tuple * value component. No separate `value_minor` field is defined; records * carrying a `value_minor` key reject with `gateway.export.unknown_field` * via the strict variant schema (NOT via the no-inline-payment-data * invariant; `value_minor` is a rejected alternate money-field name, * not raw payment data, so it should not borrow the * `inline_payment_data_blocked` diagnostic). * * No-inline-payment-data invariant (grammar-based, not heuristic-based): * - 19 forbidden top-level keys reject with * `gateway.export.inline_payment_data_blocked` (raw transaction * payload, raw nonce values, EIP-3009 payer/payTo, payment payloads, * authorization values, card / token / credential material). * - All `*_ref` fields validated by the `OpaqueRefSchema` grammar. * * Money-boundary invariant: * - `amount_minor` (when present) uses the shared `AmountMinorStringSchema` * grammar (bounded base-10 integer string) wrapped in a Gateway Export * non-negative profile constraint (`NonNegativeAmountMinorStringSchema`). * JS `number`, decimals, empty strings, comma-formatted values, AND * negative values are all rejected with * `gateway.export.invalid_amount_minor`. Bounded length prevents * precision loss above `Number.MAX_SAFE_INTEGER`. Gateway-export * `amount_minor` is caller-reported payment value evidence (not * refund-delta semantics), so the non-negative constraint applies * uniformly across every event variant; refund / void / failure * outcomes are captured by the event_kind discriminator, not by * amount sign. * * Timeout-profile invariant: * - `timeout_profile` is a closed enum aligned with upstream * environment profiles: `datacenter` / `east_africa_3g` / * `west_africa_3g` / `custom`. * - `timeout_profile` values are caller-reported profile labels. PEAC * does NOT infer geography, network quality, settlement finality, * or settlement guarantees from these labels. The geographic-sounding * labels (`east_africa_3g`, `west_africa_3g`) are upstream-aligned * identifiers, not geographic claims; PEAC records what the caller * reported, not where the call originated. * - When `timeout_profile = 'custom'`, the record MUST include all three * timing fields `facilitator_timeout_ms`, `poll_interval_ms`, and * `max_poll_window_ms`. Missing any timing field rejects with * `gateway.export.missing_required_field`. * * Polling-strategy invariant: * - `polling_strategy` is a PEAC-defined OBSERVER-scope categorical * descriptor of caller-reported polling behavior. It is NOT an * upstream enum; upstream models express polling as an interval + * window pattern, not a named-strategy enum. * * Validation returns the structured error contract: * `{ ok: true, value }` or `{ ok: false, errors: [{ code, path?, message }] }`. */ import { z } from 'zod'; export declare const GATEWAY_EXPORT_EXTENSION_KEY: "org.peacprotocol/gateway-export"; /** All 8 gateway-export record type URIs (one per event kind). */ export declare const GATEWAY_EXPORT_TYPE_URIS: readonly ["org.peacprotocol/gateway-payment-submitted-observed", "org.peacprotocol/gateway-facilitator-timeout-observed", "org.peacprotocol/gateway-settlement-unresolved-observed", "org.peacprotocol/gateway-settlement-polling-observed", "org.peacprotocol/gateway-settlement-confirmed-observed", "org.peacprotocol/gateway-settlement-confirmed-late-observed", "org.peacprotocol/gateway-settlement-failed-observed", "org.peacprotocol/gateway-settlement-failed-orphaned-observed"]; export type GatewayExportTypeUri = (typeof GATEWAY_EXPORT_TYPE_URIS)[number]; /** * Event-kind discriminator literal values. Each `event_kind` corresponds * 1:1 with a type URI in `GATEWAY_EXPORT_TYPE_URIS` (drop the * `org.peacprotocol/` prefix from the URI to get the event_kind). */ declare const EVENT_KINDS: readonly ["gateway-payment-submitted-observed", "gateway-facilitator-timeout-observed", "gateway-settlement-unresolved-observed", "gateway-settlement-polling-observed", "gateway-settlement-confirmed-observed", "gateway-settlement-confirmed-late-observed", "gateway-settlement-failed-observed", "gateway-settlement-failed-orphaned-observed"]; export type GatewayExportEventKind = (typeof EVENT_KINDS)[number]; /** Stable error codes for `validateGatewayExport` and `validateGatewayExportForType`. */ export declare const GATEWAY_EXPORT_ERROR_CODES: { readonly invalidPayload: "gateway.export.invalid_payload"; readonly inlinePaymentDataBlocked: "gateway.export.inline_payment_data_blocked"; readonly unknownField: "gateway.export.unknown_field"; readonly opaqueRefGrammarViolation: "gateway.export.opaque_ref_grammar_violation"; readonly refMustBeString: "gateway.export.ref_must_be_string"; readonly missingRequiredField: "gateway.export.missing_required_field"; readonly invalidEventKind: "gateway.export.invalid_event_kind"; readonly invalidObservedAt: "gateway.export.invalid_observed_at"; readonly invalidAmountMinor: "gateway.export.invalid_amount_minor"; readonly invalidDigest: "gateway.export.invalid_digest"; readonly invalidTimeoutProfile: "gateway.export.invalid_timeout_profile"; readonly invalidPollingStrategy: "gateway.export.invalid_polling_strategy"; readonly invalidPollCount: "gateway.export.invalid_poll_count"; readonly invalidCheckCount: "gateway.export.invalid_check_count"; readonly invalidDeadlineExceededMs: "gateway.export.invalid_deadline_exceeded_ms"; readonly invalidDelayMs: "gateway.export.invalid_delay_ms"; readonly invalidValidBeforeUnixSeconds: "gateway.export.invalid_valid_before_unix_seconds"; readonly invalidFacilitatorTimeoutMs: "gateway.export.invalid_facilitator_timeout_ms"; readonly invalidPollIntervalMs: "gateway.export.invalid_poll_interval_ms"; readonly invalidMaxPollWindowMs: "gateway.export.invalid_max_poll_window_ms"; readonly fieldTooLarge: "gateway.export.field_too_large"; readonly typeUriUnknown: "gateway.export.type_uri_unknown"; readonly typeEventKindMismatch: "gateway.export.type_event_kind_mismatch"; }; /** * Closed-enum of forbidden top-level keys. These represent classes of * raw payment-data / EIP-3009-style four-tuple raw values that must not * appear at the extension top level. Any of these keys at the top level * rejects with `gateway.export.inline_payment_data_blocked`. * * Note: `value_minor` is NOT in this list. It is rejected as * `gateway.export.unknown_field` via the strict variant schema, because * `value_minor` is a rejected alternate money-field name (the single * canonical money field is `amount_minor`), not raw payment data; * routing it through `inline_payment_data_blocked` would muddy the * public error semantics. */ export declare const GATEWAY_EXPORT_FORBIDDEN_PAYMENT_DATA_KEYS: readonly ["transaction_data", "raw_tx", "tx_hash_value", "nonce", "raw_nonce", "payer", "pay_to", "payTo", "payment_payload", "authorization", "authorization_payload", "card_number", "pan", "cvv", "token", "bearer_token", "api_key", "private_key", "credential"]; /** * The full gateway-export record (discriminated by `event_kind`). * * Pre-flight checks (forbidden top-level keys, ref-must-be-string, * amount string-only, event_kind presence/value, missing required * fields, custom timeout requires three timing fields) run inside * `validateGatewayExport` before the discriminated union parse so * callers see stable codes rather than generic Zod diagnostics. */ export declare const GatewayExportSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ submitted_at: z.ZodString; timeout_deadline: z.ZodOptional; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-payment-submitted-observed">; }, z.core.$strict>, z.ZodObject<{ timeout_at: z.ZodString; timeout_profile: z.ZodEnum<{ custom: "custom"; datacenter: "datacenter"; east_africa_3g: "east_africa_3g"; west_africa_3g: "west_africa_3g"; }>; deadline_exceeded_ms: z.ZodOptional; facilitator_timeout_ms: z.ZodOptional; poll_interval_ms: z.ZodOptional; max_poll_window_ms: z.ZodOptional; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-facilitator-timeout-observed">; }, z.core.$strict>, z.ZodObject<{ last_checked_at: z.ZodString; check_count: z.ZodNumber; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-settlement-unresolved-observed">; }, z.core.$strict>, z.ZodObject<{ poll_count: z.ZodNumber; polling_strategy: z.ZodEnum<{ unknown: "unknown"; exponential: "exponential"; linear: "linear"; immediate: "immediate"; webhook: "webhook"; }>; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-settlement-polling-observed">; }, z.core.$strict>, z.ZodObject<{ confirmed_at: z.ZodString; settlement_ref: z.ZodString; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-settlement-confirmed-observed">; }, z.core.$strict>, z.ZodObject<{ confirmed_at: z.ZodString; settlement_ref: z.ZodString; delay_ms: z.ZodNumber; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-settlement-confirmed-late-observed">; }, z.core.$strict>, z.ZodObject<{ final_state: z.ZodString; failure_reason_ref: z.ZodOptional; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-settlement-failed-observed">; }, z.core.$strict>, z.ZodObject<{ last_known_state: z.ZodString; chain_ref: z.ZodOptional; facilitator_ref: z.ZodOptional; amount_minor: z.ZodOptional; asset: z.ZodOptional; network: z.ZodOptional; tx_ref: z.ZodOptional; nonce_ref: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; caller_ref: z.ZodOptional; parent_ref: z.ZodOptional; valid_before_unix_seconds: z.ZodOptional; payer_ref: z.ZodOptional; pay_to_ref: z.ZodOptional; gateway_ref: z.ZodString; payment_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"gateway-settlement-failed-orphaned-observed">; }, z.core.$strict>], "event_kind">; export type GatewayExport = z.infer; export interface GatewayExportValidationError { code: string; path?: string; message: string; } export type GatewayExportValidationResult = { ok: true; value: GatewayExport; } | { ok: false; errors: GatewayExportValidationError[]; }; /** * Validate a gateway-export payload. * * Pre-flight order: * 1. Forbidden top-level payment-data keys -> inline_payment_data_blocked * 2. Ref fields must be strings when present -> ref_must_be_string * 3. Amount fields must be strings (not numbers) when present -> invalid_amount_minor * 4. event_kind presence/value -> missing_required_field / invalid_event_kind * 5. observed_at presence -> missing_required_field * 6. Per-kind required fields -> missing_required_field * 7. custom timeout_profile requires three timing fields -> missing_required_field * 8. Zod schema parse with priority-mapped stable codes */ export declare function validateGatewayExport(data: unknown): GatewayExportValidationResult; /** * Validate a gateway-export payload AND assert that its `event_kind` * agrees with the caller-supplied type URI. * * The type URI and `event_kind` have a 1:1 relationship: the * `event_kind` value is always `org.peacprotocol/` stripped * of its prefix, i.e. `typeUri.slice('org.peacprotocol/'.length)`. If * they disagree, `gateway.export.type_event_kind_mismatch` is returned * in addition to (or instead of) any schema-level errors. * * Use this helper when the type URI comes from the wire-record envelope * and needs to be verified against the extension payload. */ export declare function validateGatewayExportForType(typeUri: string, data: unknown): GatewayExportValidationResult; export {}; //# sourceMappingURL=gateway-export.d.ts.map