/** * Commerce Mandate Records Extension Schema * * Extension namespace: `org.peacprotocol/commerce-mandate` * Record type URIs: 7 (one per event kind; see COMMERCE_MANDATE_TYPE_URIS) * * Records observations of commerce-lifecycle events (mandate / authorization / * capture / void / refund / settlement / budget) scoped to a mandate. 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 authorize payments, process payments, settle funds, enforce mandates, * compute payment finality, evaluate budgets, validate payment rails, or * vouch for the legal validity of any commerce decision. Commerce decisions * are reported by the caller; the record describes what the caller observed. * * No-inline-payment-data invariant (grammar-based, not heuristic-based): * - 20 forbidden top-level keys reject with * `commerce.mandate.inline_payment_data_blocked` (card number, PAN, CVV, * token, API key, private key, bearer token, connection string, etc.) * - All `*_ref` fields validated by the `OpaqueRefSchema` grammar * - Per-event-kind required fields enforced via discriminated union * * Finality-synthesis boundary: * - `settlement_state` is REJECTED on `commerce-authorization-observed` * records with `commerce.mandate.finality_synthesis_blocked`. * Authorization is not settlement; PEAC does not allow a caller to * synthesize settlement finality from an authorization event. * * Money-boundary invariant: * - All amount fields use a non-negative wrapper around the shared * `AmountMinorStringSchema` (base-10 integer string). JS `number`, * decimals, empty strings, and negative amounts are rejected. Bounded * length prevents precision loss. Refund semantics are reported via * `commerce-refund-observed`; settlement reversal is reported via * `commerce-settlement-observed` with `settlement_state = 'reversed'`. * * Scheme identifier rules: * - `scheme_id` (bounded ASCII / URI-like grammar) and `scheme_ref` * (OpaqueRefSchema) are mutually exclusive; setting both rejects with * `commerce.mandate.scheme_conflict`. * * Validation returns the structured error contract: * `{ ok: true, value }` or `{ ok: false, errors: [{ code, path?, message }] }`. */ import { z } from 'zod'; export declare const COMMERCE_MANDATE_EXTENSION_KEY: "org.peacprotocol/commerce-mandate"; /** All 7 commerce-mandate record type URIs (one per event kind). */ export declare const COMMERCE_MANDATE_TYPE_URIS: readonly ["org.peacprotocol/commerce-mandate-observed", "org.peacprotocol/commerce-authorization-observed", "org.peacprotocol/commerce-capture-observed", "org.peacprotocol/commerce-void-observed", "org.peacprotocol/commerce-refund-observed", "org.peacprotocol/commerce-settlement-observed", "org.peacprotocol/commerce-budget-observed"]; export type CommerceMandateTypeUri = (typeof COMMERCE_MANDATE_TYPE_URIS)[number]; /** * Event-kind discriminator literal values. Each `event_kind` corresponds * 1:1 with a type URI in `COMMERCE_MANDATE_TYPE_URIS` (drop the * `org.peacprotocol/` prefix from the URI to get the event_kind). */ declare const EVENT_KINDS: readonly ["commerce-mandate-observed", "commerce-authorization-observed", "commerce-capture-observed", "commerce-void-observed", "commerce-refund-observed", "commerce-settlement-observed", "commerce-budget-observed"]; export type CommerceMandateEventKind = (typeof EVENT_KINDS)[number]; /** Stable error codes for `validateCommerceMandate` and `validateCommerceMandateForType`. */ export declare const COMMERCE_MANDATE_ERROR_CODES: { readonly inlinePaymentDataBlocked: "commerce.mandate.inline_payment_data_blocked"; readonly unknownField: "commerce.mandate.unknown_field"; readonly opaqueRefGrammarViolation: "commerce.mandate.opaque_ref_grammar_violation"; readonly refMustBeString: "commerce.mandate.ref_must_be_string"; readonly missingRequiredField: "commerce.mandate.missing_required_field"; readonly invalidEventKind: "commerce.mandate.invalid_event_kind"; readonly invalidAmountMinor: "commerce.mandate.invalid_amount_minor"; readonly invalidCurrency: "commerce.mandate.invalid_currency"; readonly invalidObservedAt: "commerce.mandate.invalid_observed_at"; readonly invalidDigest: "commerce.mandate.invalid_digest"; readonly invalidSettlementState: "commerce.mandate.invalid_settlement_state"; readonly finalitySynthesisBlocked: "commerce.mandate.finality_synthesis_blocked"; readonly invalidSchemeId: "commerce.mandate.invalid_scheme_id"; readonly schemeConflict: "commerce.mandate.scheme_conflict"; readonly typeUriUnknown: "commerce.mandate.type_uri_unknown"; readonly typeEventKindMismatch: "commerce.mandate.type_event_kind_mismatch"; }; /** * Closed-enum of forbidden top-level keys. These represent classes of raw * payment-data fields that must not appear at the extension top level. Any * of these keys at the top level rejects with * `commerce.mandate.inline_payment_data_blocked`. */ export declare const COMMERCE_MANDATE_FORBIDDEN_PAYMENT_DATA_KEYS: readonly ["card_number", "pan", "cvv", "cvc", "expiry_date", "card_holder_name", "billing_address", "shipping_address", "token", "raw_token", "bearer_token", "api_key", "secret", "private_key", "private_key_pem", "credential", "password", "connection_string", "iban", "bank_account"]; /** * The full commerce mandate record (discriminated by `event_kind`). * * Pre-flight checks (forbidden top-level keys, ref-must-be-string, * settlement_state on non-settlement variants, scheme conflict) run inside * `validateCommerceMandate` before the discriminated union parse so callers * see stable codes rather than generic Zod diagnostics. */ export declare const CommerceMandateSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ merchant_ref: z.ZodString; payer_ref: z.ZodString; max_amount_minor: z.ZodOptional; currency: z.ZodOptional; expires_at: z.ZodOptional; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-mandate-observed">; }, z.core.$strict>, z.ZodObject<{ authorization_ref: z.ZodString; amount_minor: z.ZodString; currency: z.ZodString; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-authorization-observed">; }, z.core.$strict>, z.ZodObject<{ authorization_ref: z.ZodString; capture_ref: z.ZodString; amount_minor: z.ZodString; currency: z.ZodString; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-capture-observed">; }, z.core.$strict>, z.ZodObject<{ authorization_ref: z.ZodString; void_ref: z.ZodString; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-void-observed">; }, z.core.$strict>, z.ZodObject<{ refund_ref: z.ZodString; amount_minor: z.ZodString; currency: z.ZodString; capture_ref: z.ZodOptional; authorization_ref: z.ZodOptional; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-refund-observed">; }, z.core.$strict>, z.ZodObject<{ settlement_ref: z.ZodString; amount_minor: z.ZodString; currency: z.ZodString; settlement_state: z.ZodEnum<{ pending: "pending"; partial: "partial"; failed: "failed"; completed: "completed"; reversed: "reversed"; }>; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-settlement-observed">; }, z.core.$strict>, z.ZodObject<{ budget_ref: z.ZodString; amount_minor: z.ZodOptional; currency: z.ZodOptional; caller_ref: z.ZodOptional; policy_ref: z.ZodOptional; policy_digest: z.ZodOptional; upstream_artifact_ref: z.ZodOptional; upstream_artifact_digest: z.ZodOptional; parent_ref: z.ZodOptional; scheme_id: z.ZodOptional; scheme_ref: z.ZodOptional; mandate_ref: z.ZodString; observed_at: z.ZodString; event_kind: z.ZodLiteral<"commerce-budget-observed">; }, z.core.$strict>], "event_kind">; export type CommerceMandate = z.infer; export interface CommerceMandateValidationError { code: string; path?: string; message: string; } export type CommerceMandateValidationResult = { ok: true; value: CommerceMandate; } | { ok: false; errors: CommerceMandateValidationError[]; }; /** * Validate a commerce mandate 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. settlement_state present on non-settlement variant -> finality_synthesis_blocked * 8. scheme_id + scheme_ref both present -> scheme_conflict * 9. Zod schema parse with priority-mapped stable codes */ export declare function validateCommerceMandate(data: unknown): CommerceMandateValidationResult; /** * Validate a commerce mandate 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, * `commerce.mandate.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 validateCommerceMandateForType(typeUri: string, data: unknown): CommerceMandateValidationResult; export {}; //# sourceMappingURL=commerce-mandate.d.ts.map