@wildo-ai/external-connectors-models 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/companion-exports.d.ts.map +1 -1
- package/dist/esm/companion-exports.js.map +1 -1
- package/dist/esm/core/commons.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/commons.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/core/oauth2.enums.d.ts.map +1 -1
- package/dist/esm/core/oauth2.enums.js.map +1 -1
- package/dist/esm/core/operation-classification.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/operation-classification.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/core/operations.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/operations.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/core/security.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/security.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/billing.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/billing.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/document-extraction.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/document-extraction.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/email-inbound.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/email-inbound.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/email.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/email.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/email.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/email.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/embeddings.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/embeddings.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/file-storage.standard-interface.d.ts.map +1 -1
- package/dist/esm/protocols/file-storage.standard-interface.js.map +1 -1
- package/dist/esm/protocols/frontend.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/frontend.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/hooks-capability.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/hooks-capability.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/hooks.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/hooks.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/image.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/image.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/llm.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/llm.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.definitions.d.ts.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.definitions.js.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.schemas.js.map +1 -1
- package/dist/esm/protocols/oauth2.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/oauth2.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts.map +1 -1
- package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.js.map +1 -1
- package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/sms.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/sms.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/sms.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/sms.standard-interface.schemas.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing.standard-interface.schemas.js","sourceRoot":"","sources":["../../../src/protocols/billing.standard-interface.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Standard Billing Interface\n * --------\n * This is the canonical interface that Wildo uses internally for all billing\n * operations. The ETL layer transforms these standard requests into\n * provider-specific API calls (e.g., Stripe, Paddle, LemonSqueezy).\n *\n * Design Principles:\n * 1. Provider-agnostic — works with any billing provider\n * 2. Hosted-first — uses provider-hosted checkout and portals (no PCI scope)\n * 3. Webhook-driven — state changes flow in via webhooks, not polling\n * 4. Scope-agnostic — billing accounts map to any Wildo scope (org, user)\n *\n * @see billing-and-features-system.md §7.1 (Standard Billing Interface)\n */\n\n// ===============================================================\n// Billing Interface Enums (canonical source, re-exported by saas-models)\n// ===============================================================\n\n/**\n * Pricing model for a price entry.\n */\nexport enum PricingModel {\n FLAT = 'flat',\n PER_UNIT = 'per_unit',\n /** Volume pricing (all units at tier price) */\n TIERED = 'tiered',\n /** Incremental (each tier priced independently) */\n GRADUATED = 'graduated',\n /** Price per package of N units */\n PACKAGE = 'package',\n}\n\n/**\n * Billing interval for recurring prices.\n */\nexport enum BillingInterval {\n MONTH = 'month',\n YEAR = 'year',\n}\n\n/**\n * Tax display mode: how prices are displayed (HT vs TTC).\n */\nexport enum TaxDisplayMode {\n /** Price amounts are HT (tax added at checkout) */\n EXCLUSIVE = 'exclusive',\n /** Price amounts are TTC (tax embedded) */\n INCLUSIVE = 'inclusive',\n}\n\n/**\n * How a mid-cycle subscription change is settled.\n *\n * A PROTOCOL vocabulary, and it lives here for the same reason {@link TaxDisplayMode} does: these three\n * values are the wire values a billing provider accepts. It was declared in `@wildo-ai/saas-models`\n * until 2026-09-08 and re-exported the other way round, which is why an authored proration could be\n * resolved by the engine and had no field on the request to travel in — the request contract could not\n * name the type without a package cycle, so the resolved value was sent as provider METADATA and\n * ignored (#516).\n *\n * `@wildo-ai/saas-models` re-exports it, so every existing consumer is unchanged.\n */\nexport enum ProrationBehavior {\n /** Credit the unused time and charge the new price pro rata, settled on the next invoice. */\n CREATE_PRORATIONS = 'create_prorations',\n /** No proration: the change takes effect and the next invoice is the new price in full. */\n NONE = 'none',\n /** Prorate and invoice the difference IMMEDIATELY rather than at the next cycle. */\n ALWAYS_INVOICE = 'always_invoice',\n}\n\n/**\n * How the provider treats a subscription change whose resulting payment does not succeed (#535, decision D6).\n *\n * Wildo applies a confirmed plan change IMMEDIATELY: entitlements move at local completion, and a failed proration\n * payment moves the subscription to `past_due` through the webhook projection, where dunning owns what happens next.\n * The value is DECLARED on every engine-issued change rather than left to the provider's default, so a change of that\n * default can never silently change the semantics.\n *\n * Deliberately a one-member vocabulary. `pending_if_incomplete` (apply only after payment, expire after 23 h) was\n * weighed and rejected in #535; add a member only with a decision that changes D6.\n *\n * spec-cite: https://docs.stripe.com/api/subscriptions/update — `payment_behavior`; the value equals Stripe's wire value,\n * so the Stripe adapter passes it untranslated, as it does `ProrationBehavior`.\n */\nexport enum StandardBilling_SubscriptionPaymentBehavior {\n /** Apply the change now; an unpaid resulting invoice leaves the subscription `past_due`. */\n ALLOW_INCOMPLETE = 'allow_incomplete',\n}\n\n/**\n * What a FAILED provider mutation tells the caller about whether the change took effect (#535, decision D3).\n *\n * The distinction that matters is not the HTTP status but what may be recorded next: a conclusive refusal and a request\n * that never executed may both be recorded as \"no effect\", while an indeterminate outcome must NEVER be — the provider\n * may have applied it, or may still apply it. Only the adapter can read its vendor's error shape, so each adapter\n * classifies (`StandardBilling_Interface.classifyMutationError`) and the engine decides on the class alone.\n *\n * spec-cite: https://docs.stripe.com/error-low-level — \"Network errors\", \"Server errors\", \"Content errors\" (the\n * source of the classes for the Stripe adapter; other adapters map their own vendor's equivalents).\n */\nexport enum StandardBilling_MutationErrorClass {\n /** The provider evaluated the request and refused it (e.g. a declined card, a missing object). No effect. */\n CONCLUSIVE_REJECTION = 'conclusive_rejection',\n /** Refused before execution (rate limit, authentication). No effect; a later attempt must use a NEW idempotency key. */\n NOT_EXECUTED = 'not_executed',\n /** Another request with the same idempotency key is still being processed. The outcome is not known yet. */\n IN_FLIGHT_CONFLICT = 'in_flight_conflict',\n /** Timeout, connection loss, server error, or a failure after the provider answered. The change may have applied. */\n INDETERMINATE = 'indeterminate',\n}\n\n/**\n * Subscription status values (maps to Stripe subscription statuses).\n */\nexport enum SubscriptionStatus {\n ACTIVE = 'active',\n PAST_DUE = 'past_due',\n UNPAID = 'unpaid',\n CANCELLED = 'cancelled',\n /** Stripe: first payment never completed within 23h window */\n INCOMPLETE = 'incomplete',\n INCOMPLETE_EXPIRED = 'incomplete_expired',\n TRIALING = 'trialing',\n PAUSED = 'paused',\n}\n\n/**\n * Invoice lifecycle status, as the PROVIDER reports it.\n *\n * A PROTOCOL vocabulary for the same reason {@link SubscriptionStatus} is one: these are the states\n * a billing provider puts an invoice in, and the adapter's job is to map its own wire values onto\n * them. It was declared in `@wildo-ai/saas-models` until 2026-09-09 and could not be named by this\n * package at all, so `listInvoices` — the read the reconciliation sweep needs — had no way to type\n * the one field the sweep compares.\n *\n * Moved rather than duplicated: a second enum with the same five members would be two sources for\n * one closed vocabulary, which is what `CLAUDE.md` forbids. `@wildo-ai/saas-models` re-exports it\n * exactly as it already re-exports `SubscriptionStatus`, `TaxDisplayMode` and `ProrationBehavior`,\n * so every existing consumer — including the `invoiceRefs` schema, the badge palette and the\n * documentation catalogue — imports the same specifier it always did.\n */\nexport enum InvoiceStatus {\n /** Not finalized: the provider has not issued it for collection and it may still change. */\n DRAFT = 'draft',\n /** Finalized and awaiting payment. */\n OPEN = 'open',\n /** Settled. */\n PAID = 'paid',\n /** Cancelled by the provider or the merchant; never collectable. */\n VOID = 'void',\n /** Written off — payment was attempted and abandoned. */\n UNCOLLECTIBLE = 'uncollectible',\n}\n\n// ===============================================================\n// Standard Billing Event Types\n// ===============================================================\n\n/**\n * Canonical billing events the system cares about.\n * Provider-specific events are mapped to these types by the transformer.\n * Only events that affect local state (features, status) need to be handled.\n */\nexport enum StandardBilling_EventType {\n // Subscription lifecycle (→ feature sync)\n SUBSCRIPTION_CREATED = 'subscription.created',\n SUBSCRIPTION_UPDATED = 'subscription.updated',\n SUBSCRIPTION_DELETED = 'subscription.deleted',\n SUBSCRIPTION_TRIAL_WILL_END = 'subscription.trial_will_end',\n\n // Invoice status (→ billing status tracking, past_due detection)\n INVOICE_PAID = 'invoice.paid',\n INVOICE_PAYMENT_FAILED = 'invoice.payment_failed',\n INVOICE_FINALIZED = 'invoice.finalized',\n\n // Checkout (→ one-off purchase completion for ONE_TIME, CREDIT_PACK, ITEM products)\n CHECKOUT_SESSION_COMPLETED = 'checkout.session.completed',\n\n // Customer (→ billing account sync)\n CUSTOMER_UPDATED = 'customer.updated',\n CUSTOMER_DELETED = 'customer.deleted',\n\n // Coupon (→ no local action; coupons are managed through Wildo's promotion system.\n // Included for logging/audit in case coupons are modified directly on the provider.)\n COUPON_CREATED = 'coupon.created',\n COUPON_UPDATED = 'coupon.updated',\n COUPON_DELETED = 'coupon.deleted',\n\n // Customer discount (→ subscription re-sync to pick up discount changes)\n CUSTOMER_DISCOUNT_CREATED = 'customer.discount.created',\n CUSTOMER_DISCOUNT_UPDATED = 'customer.discount.updated',\n CUSTOMER_DISCOUNT_DELETED = 'customer.discount.deleted',\n\n // Payment method (→ no local action needed; provider manages via Customer Portal.\n // Included for completeness: apps can optionally log these events for audit trails.)\n PAYMENT_METHOD_ATTACHED = 'payment_method.attached',\n PAYMENT_METHOD_DETACHED = 'payment_method.detached',\n}\n\n// ===============================================================\n// Standard Billing Webhook Event\n// ===============================================================\n\n/**\n * Canonical webhook event representation.\n * Provider transformers parse raw webhook payloads into this shape.\n */\nexport interface StandardBilling_WebhookEvent {\n /** Canonical event type */\n type: StandardBilling_EventType;\n /** Provider-assigned event ID (for idempotency) */\n providerEventId: string;\n /** Event payload — shape varies by event type */\n data: Record<string, unknown>;\n /** When the event occurred at the provider */\n createdAt: Date;\n}\n\n// ===============================================================\n// Request/Response Types\n// ===============================================================\n\n// ── Customer ────────────────────────────────────────────────────\n\nexport interface StandardBilling_CreateCustomerRequest {\n /**\n * Descriptive name — the organisation's name for an org-scoped account, the person's display name\n * for a user-scoped one.\n *\n * OPTIONAL, and that is the point (issue #486). It was required, and a caller that could not\n * resolve one therefore had to INVENT it: the engine sent the literal `'Unknown'` for every\n * customer it ever created. A contract that cannot express \"we do not know\" forces every caller to\n * lie, and a fabricated value is worse than an absent one — an operator reading the provider\n * dashboard cannot tell it from a real answer.\n */\n name?: string;\n /**\n * Contact email for invoices and receipts.\n *\n * OPTIONAL for the same reason as `name`, and additionally because **an organisation frequently has\n * no billing email at all**. Sending a natural person's address for an ORGANISATION's customer\n * record would put personal data on a record that is not about a person — the opposite of data\n * minimisation, which asks that personal data be \"adequate, relevant and limited to what is\n * necessary\".\n * spec-cite: GDPR Art. 5(1)(c) — https://gdpr-info.eu/art-5-gdpr/\n *\n * It also makes the later erasure story cheap: an organisation record carrying no individual's\n * identity never has to be visited when that individual exercises their right to erasure, so the\n * obligation to inform recipients of an erasure does not reach it.\n * spec-cite: GDPR Art. 17(2) — https://gdpr-info.eu/art-17-gdpr/\n *\n * Absent is a legitimate value at the provider: Stripe's own customer `email` is optional.\n * spec-cite: N/A — describes the Stripe Customer object's declared optionality in this\n * repository's own words (https://docs.stripe.com/api/customers/object).\n */\n email?: string;\n /** Arbitrary key-value metadata stored on the provider customer */\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateCustomerResponse {\n providerCustomerId: string;\n}\n\n/**\n * Postal address on a provider customer record.\n *\n * Every field is independently clearable (`null`) rather than merely omittable: `undefined` means\n * \"leave whatever the provider already has\", `null` means \"blank it\". Subject erasure needs the\n * second meaning — an address that is silently preserved because the request could only express\n * \"no change\" is personal data surviving an erasure.\n */\nexport interface StandardBilling_CustomerAddress {\n line1?: string | null;\n line2?: string | null;\n city?: string | null;\n state?: string | null;\n postalCode?: string | null;\n /** ISO 3166-1 alpha-2 country code. */\n country?: string | null;\n}\n\nexport interface StandardBilling_UpdateCustomerRequest {\n name?: string;\n email?: string;\n metadata?: Record<string, string>;\n /**\n * Contact phone. `null` clears it at the provider — see {@link StandardBilling_CustomerAddress}\n * for why clearability is expressed separately from omission.\n */\n phone?: string | null;\n /**\n * Billing address. `null` clears the whole address; a partial object clears only the fields it\n * sets to `null` and leaves the rest untouched.\n */\n address?: StandardBilling_CustomerAddress | null;\n}\n\n/**\n * A stored payment instrument attached to a provider customer.\n *\n * Deliberately thin: enough to identify an instrument for detachment and to render a\n * \"•••• 4242\"-style hint, and nothing more. Wildo never handles raw instrument data — that is the\n * whole point of routing users through the provider-hosted portal — so this carries no PAN, no\n * expiry, and no billing details.\n */\nexport interface StandardBilling_PaymentMethodSummary {\n providerPaymentMethodId: string;\n /**\n * Instrument kind as the provider names it (`'card'`, `'sepa_debit'`, `'us_bank_account'`, …).\n * Intentionally an OPEN provider identifier, not a closed Wildo vocabulary: the set differs per\n * provider and grows without our involvement, and nothing in the framework branches on it — it\n * is carried for display and diagnostics only.\n */\n type: string;\n /** Last four digits, when the instrument exposes them. */\n last4?: string;\n}\n\n// ── Product/Price Sync ──────────────────────────────────────────\n\nexport interface StandardBilling_SyncProductRequest {\n /** Internal Wildo product key (stored in metadata for reverse lookup) */\n productKey: string;\n name: string;\n description?: string;\n /** If set, updates existing provider product instead of creating new */\n providerProductId?: string;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_SyncProductResponse {\n providerProductId: string;\n}\n\nexport interface StandardBilling_SyncPriceRequest {\n providerProductId: string;\n model: PricingModel;\n /** Amount in smallest currency unit (cents) */\n amount: number;\n currency: string;\n interval?: BillingInterval;\n /** Multiplier of the recurring interval (3 months = quarterly). Omitted means 1; ignored for one-time prices. */\n intervalCount?: number;\n /** For TIERED/VOLUME pricing models */\n tiers?: Array<{\n upTo: number | null;\n unitAmount: number;\n flatAmount?: number;\n }>;\n /** For PACKAGE pricing */\n packageSize?: number;\n /** Tax behavior */\n taxBehavior?: TaxDisplayMode;\n /** If set, updates existing provider price instead of creating new */\n providerPriceId?: string;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_SyncPriceResponse {\n providerPriceId: string;\n}\n\n// ── Subscription Lifecycle ──────────────────────────────────────\n\nexport interface StandardBilling_CreateSubscriptionRequest {\n providerCustomerId: string;\n items: Array<{\n providerPriceId: string;\n quantity?: number;\n }>;\n trialPeriodDays?: number;\n /** Provider promotion code to apply */\n providerPromotionCodeId?: string;\n /**\n * Ask the provider to compute tax on this purchase (#408, 2026-09-08).\n *\n * Set from the application's `billing.tax.calculationMode`, which is PROVIDER_MANAGED or\n * DISABLED — Wildo never calculates tax locally, so the only question a provider is asked is\n * whether to calculate at all. A provider that cannot compute tax ignores this; one that can and\n * is not configured for the customer's jurisdiction will say so at the call, which is the right\n * place for that failure.\n *\n * Distinct from a price's `taxBehavior`, which says whether a displayed amount INCLUDES tax.\n * That one has always reached the provider; this one decides whether tax is computed.\n */\n automaticTax?: boolean;\n /**\n * Require a payment method up front for a trial (#408, 2026-09-08).\n *\n * Set from the product's `behaviorPolicy.trial.requirePaymentMethod`, which was declared,\n * labelled, rendered on billing screens and passed to no provider call — so a trial declared as\n * requiring a card behaved identically to one that did not. Wonder Todos' enterprise plan\n * (`true`) and professional plan (`false`) were indistinguishable at the provider.\n *\n * Two provider-side consequences follow and a connector should honour both: collect the payment\n * method during checkout, and decide what happens if the trial ends without one.\n */\n requirePaymentMethodForTrial?: boolean;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateSubscriptionResponse {\n providerSubscriptionId: string;\n status: string;\n}\n\n/** Provider-confirmed identities of correlated additions from the same update operation. */\nexport interface StandardBilling_UpdateSubscriptionResponse {\n createdItems: Array<{ clientItemKey: string; providerSubscriptionItemId: string }>;\n}\n\nexport interface StandardBilling_UpdateSubscriptionRequest {\n /**\n * Server-owned identity of one attempted change, reused with the SAME subscription and payload\n * when recovering a lost response. Never generate a new key for a retry. Provider retention is\n * bounded: this does not replace confirmation consumption, freshness checks or reconciliation.\n * This is request transport metadata, not subscription metadata or a browser authoring field.\n */\n idempotencyKey?: string;\n /** Item patches: omitted existing items are retained; an item without an ID is added. */\n items?: Array<{\n /** Provider-side subscription item ID to update. Omit only when adding a new item. */\n providerSubscriptionItemId?: string;\n /** Backend-generated correlation key for an intentional new item; echoed with its created provider ID. */\n clientItemKey?: string;\n providerPriceId: string;\n quantity?: number;\n }>;\n /** Explicit provider-side item IDs to remove. Omitting an item from `items` never removes it. */\n removedProviderSubscriptionItemIds?: string[];\n /** Provider promotion code to apply */\n providerPromotionCodeId?: string;\n /**\n * How the provider settles this mid-cycle change (#516).\n *\n * The engine resolves it from the target product's `upgrade`/`downgrade` behaviour policy and it\n * had nowhere to travel: it was put in `metadata`, a free-form bag the provider does not read, so a\n * product declaring `NONE` for a downgrade was still prorated by the provider's own default. Absent\n * means \"do not send one\" — the provider applies its account default, which is what every\n * subscription update did before this field existed.\n */\n prorationBehavior?: ProrationBehavior;\n /**\n * How the provider treats an unpaid resulting invoice (#535, D6). Absent sends none, so the provider's default\n * applies; the engine's own plan-change dispatch always declares it.\n */\n paymentBehavior?: StandardBilling_SubscriptionPaymentBehavior;\n /** Unix seconds used for proration. Reuse the preview instant when confirming the same change. */\n prorationDate?: number;\n metadata?: Record<string, string>;\n}\n\n/**\n * Hypothetical item patch for an upcoming invoice. Item identity, quantity and proration must match\n * the eventual update; selecting the first provider item can accidentally preview an addon change.\n * Omitted items remain on the subscription. This request never changes the subscription itself.\n */\nexport type StandardBilling_SubscriptionPreviewRequest = Pick<StandardBilling_UpdateSubscriptionRequest,\n 'items' | 'removedProviderSubscriptionItemIds' | 'prorationBehavior' | 'prorationDate'>;\n\n/**\n * Request transport options shared by the subscription mutations that carry no payload of their own.\n *\n * `idempotencyKey` has the same contract as on {@link StandardBilling_UpdateSubscriptionRequest}: a server-owned\n * identity of ONE attempted change, reused with the same subscription and options only to recover a lost response.\n */\nexport interface StandardBilling_SubscriptionMutationOptions {\n idempotencyKey?: string;\n}\n\n/**\n * A plan change deferred to the end of the subscription's current period (#1868).\n *\n * The provider keeps the subscription as it is until the period ends and then moves it onto `items`. Stripe does this with a\n * subscription schedule: one phase holding the current lines until `current_period_end`, a second holding `items`, released\n * afterwards so the subscription runs on without it. The adapter derives the current lines and the period end from the\n * subscription itself, so the change always lands at the renewal of the period it was confirmed in.\n */\nexport interface StandardBilling_SchedulePlanChangeRequest extends StandardBilling_SubscriptionMutationOptions {\n /** Every line the subscription carries from the next period: the new plan and the add-ons that carry over. */\n items: Array<{ providerPriceId: string; quantity: number }>;\n /** How the provider settles the move into the new lines at renewal. Absent sends none. */\n prorationBehavior?: ProrationBehavior;\n /** Written on the schedule, so a later read can name the change that created it (`wildo_mutation`). */\n metadata?: Record<string, string>;\n}\n\n/** The provider's handle on a deferred plan change: what `releaseSubscriptionSchedule` withdraws. */\nexport interface StandardBilling_SchedulePlanChangeResponse {\n providerScheduleId: string;\n}\n\n/** How a schedule is released (#1868). */\nexport interface StandardBilling_ReleaseScheduleOptions extends StandardBilling_SubscriptionMutationOptions {\n /**\n * Release only while the schedule still has a phase AHEAD of the current one — a WITHDRAWAL of a change that has not taken effect. A\n * schedule still managing the subscription with its next phase begun is refused conclusively, nothing sent: releasing it then would\n * keep the subscription on the lines the change moved it to, while the caller believed the change withdrawn. A schedule already\n * released, cancelled or completed succeeds only when the caller's key replays its own earlier release; otherwise it answers an\n * INDETERMINATE failure — it may be this caller's release, so only a read of what the provider bills can say whether the withdrawal\n * happened. Absent, a schedule is released whatever phase it is in, which is\n * how the engine lets go of a schedule whose change has already landed.\n */\n onlyBeforeNextPhase?: boolean;\n}\n\nexport interface StandardBilling_CancelSubscriptionOptions extends StandardBilling_SubscriptionMutationOptions {\n /** If true, subscription remains active until current period ends */\n atPeriodEnd?: boolean;\n}\n\n// ── Read/Sync (Reconciliation) ──────────────────────────────────\n\n/**\n * StandardBilling_SubscriptionData: canonical subscription representation\n * returned by the provider adapter's retrieveSubscription().\n * Used for reconciliation when webhooks may have been missed.\n */\nexport interface StandardBilling_SubscriptionData {\n providerSubscriptionId: string;\n status: SubscriptionStatus;\n currentPeriodStart: Date;\n currentPeriodEnd: Date;\n cancelAtPeriodEnd: boolean;\n /**\n * When the subscription's trial began and ends, if it had one. The provider keeps both after the trial\n * is over, so a subscription that trialed carries them for its whole life, and one that never did\n * carries neither.\n */\n trialStart?: Date;\n trialEnd?: Date;\n /**\n * The schedule the provider holds on this subscription, if any (#1868): how a deferred plan change is kept until renewal.\n * `upcomingPhase` is the phase after the current one — the lines the subscription moves to and when — and is absent once\n * the last phase is current, which for an engine-created schedule means its change has taken effect. `metadata` carries\n * the reference of the engine mutation that created the schedule (`wildo_mutation`), absent on one made elsewhere.\n */\n schedule?: {\n providerScheduleId: string;\n metadata: Record<string, string>;\n upcomingPhase?: { startsAt: Date; items: Array<{ providerPriceId: string; quantity: number }> };\n };\n items: Array<{\n providerSubscriptionItemId: string;\n providerProductId: string;\n providerPriceId: string;\n quantity: number;\n }>;\n /**\n * Every subscription-level discount the provider applies, from coupons and promotion codes, in the order the provider\n * applies them. Absent or empty when none applies, including after the last one has ended.\n *\n * ALL of them, because a subscription can hold several — a referral reward (`addSubscriptionDiscount`) is added BESIDE\n * a promotion the checkout applied — and each is charged (#1948). An adapter that reported only the first would leave\n * the application showing one discount while the customer is billed for two.\n * `duration` is a `PromotionDuration` value: `once`, `repeating` or `forever`.\n */\n discounts?: Array<{\n providerCouponId: string;\n percentOff?: number;\n amountOff?: number;\n currency?: string;\n duration: string;\n durationInMonths?: number;\n end?: Date;\n }>;\n}\n\n/**\n * StandardBilling_InvoicePreview: canonical upcoming invoice from provider.\n * Returned by retrieveUpcomingInvoice() for plan change previews.\n */\nexport interface StandardBilling_InvoicePreview {\n /** Upcoming invoice amount due, in currency minor units; not a promise of an immediate charge. */\n amount: number;\n currency: string;\n lineItems: Array<{\n description: string;\n amount: number;\n quantity: number;\n providerPriceId?: string;\n }>;\n periodStart: Date;\n periodEnd: Date;\n}\n\n/**\n * StandardBilling_InvoiceData: an invoice the provider ALREADY holds.\n *\n * Distinct from {@link StandardBilling_InvoicePreview}, and the distinction is the point: a preview\n * is a hypothetical the provider computes on request and never stores, while this is a record that\n * exists at the provider whether or not Wildo ever heard about it. The second is what a\n * reconciliation sweep needs — a webhook that was never delivered leaves an invoice that exists\n * there and nowhere here, and no amount of previewing finds it.\n *\n * Deliberately thin. It carries what `invoiceRefs` stores and nothing else: line items, tax\n * breakdowns and payment attempts live at the provider, and the customer reaches them through the\n * provider-hosted portal.\n */\nexport interface StandardBilling_InvoiceData {\n providerInvoiceId: string;\n /** The customer the invoice was billed to — the key that maps it back to a local billing account. */\n providerCustomerId: string;\n status: InvoiceStatus;\n /**\n * The invoice TOTAL, in the CURRENCY's smallest unit.\n *\n * The total, not the amount PAID: an invoice's value does not depend on whether it has been\n * settled, and an unpaid invoice recorded at zero is indistinguishable from a zero invoice.\n */\n total: number;\n currency: string;\n hostedInvoiceUrl?: string;\n invoicePdfUrl?: string;\n /** When the provider created the invoice — used to bound how far back a sweep looks. */\n createdAt: Date;\n}\n\n// ── Checkout / Portal (Provider-Hosted UI) ──────────────────────\n\nexport interface StandardBilling_CreateCheckoutSessionRequest {\n providerCustomerId: string;\n lineItems: Array<{\n providerPriceId: string;\n quantity?: number;\n }>;\n /** Checkout mode: 'subscription' for recurring, 'payment' for one-time */\n mode: 'subscription' | 'payment';\n successUrl: string;\n cancelUrl: string;\n /** Allow promotion codes in checkout */\n allowPromotionCodes?: boolean;\n /** Pre-fill promotion code */\n providerPromotionCodeId?: string;\n /** Trial period for subscriptions */\n trialPeriodDays?: number;\n /**\n * Ask the provider to compute tax on this purchase (#408, 2026-09-08).\n *\n * Set from the application's `billing.tax.calculationMode`, which is PROVIDER_MANAGED or\n * DISABLED — Wildo never calculates tax locally, so the only question a provider is asked is\n * whether to calculate at all. A provider that cannot compute tax ignores this; one that can and\n * is not configured for the customer's jurisdiction will say so at the call, which is the right\n * place for that failure.\n *\n * Distinct from a price's `taxBehavior`, which says whether a displayed amount INCLUDES tax.\n * That one has always reached the provider; this one decides whether tax is computed.\n */\n automaticTax?: boolean;\n /**\n * Require a payment method up front for a trial (#408, 2026-09-08).\n *\n * Set from the product's `behaviorPolicy.trial.requirePaymentMethod`, which was declared,\n * labelled, rendered on billing screens and passed to no provider call — so a trial declared as\n * requiring a card behaved identically to one that did not. Wonder Todos' enterprise plan\n * (`true`) and professional plan (`false`) were indistinguishable at the provider.\n *\n * Two provider-side consequences follow and a connector should honour both: collect the payment\n * method during checkout, and decide what happens if the trial ends without one.\n */\n requirePaymentMethodForTrial?: boolean;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateCheckoutSessionResponse {\n /** Redirect URL for the hosted checkout page */\n url: string;\n sessionId: string;\n}\n\nexport interface StandardBilling_CreateCustomerPortalSessionResponse {\n /** Redirect URL for the customer portal */\n url: string;\n}\n\n// ── Usage Reporting (METERED products via Billing Meter Events) ─\n\nexport interface StandardBilling_ReportUsageRequest {\n /** Meter event name (corresponds to the meter's event_name) */\n meterEventName: string;\n /** Provider customer ID (maps to payload.stripe_customer_id in Stripe) */\n providerCustomerId: string;\n /** Usage value to report */\n value: number;\n /** Optional event timestamp */\n timestamp?: Date;\n /** Optional unique event identifier (for idempotency) */\n identifier?: string;\n}\n\n// ── Promotions ──────────────────────────────────────────────────\n\nexport interface StandardBilling_CreateCouponRequest {\n /** Discount amount in smallest currency unit (for fixed discounts) */\n amountOff?: number;\n /** Discount percentage (for percentage discounts) */\n percentOff?: number;\n currency?: string;\n duration: 'once' | 'repeating' | 'forever';\n durationInMonths?: number;\n maxRedemptions?: number;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateCouponResponse {\n providerCouponId: string;\n}\n\nexport interface StandardBilling_CreatePromotionCodeResponse {\n providerPromotionId: string;\n}\n\n/**\n * A percentage discount GIVEN to one subscription — a referral reward (#1802) — rather than redeemed by the\n * customer from a code.\n */\nexport interface StandardBilling_AddSubscriptionDiscountRequest {\n /** Percentage taken off, 1–100. */\n percentOff: number;\n duration: 'once' | 'repeating' | 'forever';\n /** Months, for a `repeating` discount. */\n durationInMonths?: number;\n /**\n * Stable per grant. The adapter derives the provider coupon's identity and its idempotency keys from it, so\n * a repeated call with the same key adds the discount once.\n */\n grantKey: string;\n metadata?: Record<string, string>;\n}\n\n// ===============================================================\n// Standard Billing Interface\n// ===============================================================\n\n/**\n * Provider-agnostic billing interface.\n * Each billing provider (Stripe, Paddle, etc.) implements this interface\n * through a transformer that maps canonical operations to provider SDK calls.\n */\nexport interface StandardBilling_Interface {\n // ── Customer (maps to BillingAccount) ──\n createCustomer(request: StandardBilling_CreateCustomerRequest): Promise<StandardBilling_CreateCustomerResponse>;\n updateCustomer(providerCustomerId: string, request: StandardBilling_UpdateCustomerRequest): Promise<void>;\n /**\n * Hard-delete the provider customer.\n *\n * ⚠️ NOT the subject-erasure path. Erasing a subject ANONYMIZES this customer (blank the personal\n * fields, keep the record) because the financial history hanging off it — invoices, subscriptions,\n * usage — is retained under a legal obligation and must stay attributable to its provider record.\n * Deleting the customer would strand exactly the audit trail retention exists to preserve.\n * Reserve this for a genuine account teardown with no retained history.\n */\n deleteCustomer(providerCustomerId: string): Promise<void>;\n\n // ── Payment instruments ──\n /**\n * Stored payment instruments for a customer. Used by subject erasure to enumerate what must be\n * detached; day-to-day management belongs in the provider-hosted portal.\n */\n listPaymentMethods(providerCustomerId: string): Promise<StandardBilling_PaymentMethodSummary[]>;\n /**\n * Detach an instrument from its customer. Detaching does NOT delete the instrument's transaction\n * history at the provider — it stops future charges and unlinks it from the customer, which is\n * what erasure needs and what the retained invoice record requires.\n */\n detachPaymentMethod(providerPaymentMethodId: string): Promise<void>;\n /**\n * Blank the personal data an instrument carries about whoever paid with it — the cardholder's name,\n * email, phone and billing address — keeping the instrument itself (#869).\n *\n * Detaching does not do this: a detached instrument still exists at the provider with its billing\n * details intact, and on Stripe it can no longer be edited once detached (\"You must save this\n * PaymentMethod to a customer before you can update it\", measured 2026-09-25). So subject erasure\n * calls this BEFORE {@link detachPaymentMethod}. A provider field that cannot be unset stays: Stripe\n * refuses to clear `address.country`, which identifies nobody on its own.\n *\n * The card network data (brand, last four digits, expiry, fingerprint) is the instrument, not contact\n * data, and stays with the retained transaction record it belongs to.\n */\n redactPaymentMethodBillingDetails(providerPaymentMethodId: string): Promise<void>;\n\n // ── Product/Price sync (Wildo → Provider) ──\n syncProduct(request: StandardBilling_SyncProductRequest): Promise<StandardBilling_SyncProductResponse>;\n syncPrice(request: StandardBilling_SyncPriceRequest): Promise<StandardBilling_SyncPriceResponse>;\n /**\n * Whether the provider price a local price is LINKED to still carries the local terms (#1907): active, on the\n * requested product, and equal in amount, currency, cadence, tiers, packaging and tax behaviour.\n *\n * A provider price is immutable, so a link made under an earlier amount convention — or before a catalogue edit —\n * keeps charging the old amount unless something compares the two. The catalogue sync asks this of every linked\n * price and re-syncs one that answers `false`. Answer `false` when the price cannot be read: the caller then\n * creates a correct price rather than keeping a link nobody could check.\n */\n linkedPriceMatches(providerPriceId: string, request: StandardBilling_SyncPriceRequest): Promise<boolean>;\n\n // ── Subscription lifecycle ──\n // NOTE: User-initiated plan changes, cancellation, and payment method management\n // should use createCustomerPortalSession() instead of calling these directly.\n // These methods are for: initial checkout completion, backend-driven upgrades,\n // admin-triggered changes, and webhook-driven updates.\n createSubscription(request: StandardBilling_CreateSubscriptionRequest): Promise<StandardBilling_CreateSubscriptionResponse>;\n updateSubscription(providerSubscriptionId: string, request: StandardBilling_UpdateSubscriptionRequest): Promise<StandardBilling_UpdateSubscriptionResponse>;\n cancelSubscription(providerSubscriptionId: string, options?: StandardBilling_CancelSubscriptionOptions): Promise<void>;\n pauseSubscription(providerSubscriptionId: string): Promise<void>;\n /** Resume paused payment collection; does not undo a scheduled cancellation. */\n resumeSubscription(providerSubscriptionId: string): Promise<void>;\n /** Remove a pending period-end cancellation without changing collection or lifecycle status. */\n removeScheduledCancellation(providerSubscriptionId: string, options?: StandardBilling_SubscriptionMutationOptions): Promise<void>;\n /**\n * Defer a plan change to the end of the current period (#1868). One deferred change at a time: the engine refuses a second\n * while one is pending, and it is withdrawn (`releaseSubscriptionSchedule`) before another is made.\n */\n schedulePlanChange(providerSubscriptionId: string, request: StandardBilling_SchedulePlanChangeRequest): Promise<StandardBilling_SchedulePlanChangeResponse>;\n /**\n * Withdraw a schedule from its subscription, leaving the subscription running as it is now (#1868). Releasing a schedule that is\n * already released succeeds: the state asked for holds — except with `onlyBeforeNextPhase`, where it succeeds only as a replay of the\n * caller's own release and otherwise answers an INDETERMINATE failure, and the caller decides from what the provider bills.\n */\n releaseSubscriptionSchedule(providerScheduleId: string, options?: StandardBilling_ReleaseScheduleOptions): Promise<void>;\n /**\n * Classify an error thrown by `updateSubscription`, `cancelSubscription`, `removeScheduledCancellation`, `schedulePlanChange` or\n * `releaseSubscriptionSchedule` (#535, D3).\n *\n * Must answer {@link StandardBilling_MutationErrorClass.INDETERMINATE} for anything the adapter cannot positively place\n * — including an error the adapter itself threw AFTER the provider answered — because every other class licenses the\n * caller to record that the change did not happen.\n */\n classifyMutationError(error: unknown): StandardBilling_MutationErrorClass;\n\n // ── Read/sync (for reconciliation and upcoming cost preview) ──\n /** On-demand retrieval for reconciliation (if webhook missed) */\n retrieveSubscription(providerSubscriptionId: string): Promise<StandardBilling_SubscriptionData>;\n /** Preview the upcoming invoice for an optional item change; the amount is not necessarily charged immediately. */\n retrieveUpcomingInvoice(providerSubscriptionId: string, request?: StandardBilling_SubscriptionPreviewRequest): Promise<StandardBilling_InvoicePreview>;\n /**\n * Invoices the provider holds for one customer, newest first.\n *\n * The RECOVERY read for {@link StandardBilling_EventType.INVOICE_PAID} and its siblings. Wildo\n * never creates an invoice — every local `invoiceRefs` row exists because a webhook arrived — so a\n * delivery that is lost, or that arrives while the application is down and exhausts the provider's\n * retries, leaves an invoice with no local trace and nothing that could notice. This is the only\n * call that can find one.\n *\n * `limit` bounds one page and an adapter may cap it lower; the sweep asks for a recent window\n * rather than the whole history, because an invoice older than the window has either been\n * reconciled already or is a backlog no single tick should try to drain.\n */\n listInvoices(providerCustomerId: string, options?: { limit?: number }): Promise<StandardBilling_InvoiceData[]>;\n\n // ── Provider-hosted UI (primary user-facing interactions) ──\n /** Hosted checkout page — NO Stripe Elements needed, no PCI scope */\n createCheckoutSession(request: StandardBilling_CreateCheckoutSessionRequest): Promise<StandardBilling_CreateCheckoutSessionResponse>;\n /** Customer portal for: invoices, payment methods, billing address, cancel */\n createCustomerPortalSession(providerCustomerId: string, returnUrl: string): Promise<StandardBilling_CreateCustomerPortalSessionResponse>;\n\n // ── Usage reporting (for METERED products) ──\n reportUsage(request: StandardBilling_ReportUsageRequest): Promise<void>;\n\n // ── Webhooks ──\n /** HTTP header name that carries the webhook signature (e.g., 'stripe-signature') */\n readonly webhookSignatureHeaderName: string;\n verifyWebhookSignature(payload: string | Uint8Array, signature: string, secret: string): boolean;\n /** Parse a raw webhook payload into a canonical event. Returns null for unknown/unhandled event types. */\n parseWebhookEvent(payload: string | Uint8Array): StandardBilling_WebhookEvent | null;\n\n // ── Promotions (synced to provider) ──\n createCoupon(request: StandardBilling_CreateCouponRequest): Promise<StandardBilling_CreateCouponResponse>;\n createPromotionCode(providerCouponId: string, code: string): Promise<StandardBilling_CreatePromotionCodeResponse>;\n /**\n * Add a discount to a subscription, KEEPING any discount it already carries (#1802). Idempotent on\n * `request.grantKey`: a second call with the same key finds its discount already applied and adds nothing.\n */\n addSubscriptionDiscount(providerSubscriptionId: string, request: StandardBilling_AddSubscriptionDiscountRequest): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"billing.standard-interface.schemas.js","sourceRoot":"","sources":["../../../../src/protocols/billing.standard-interface.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Standard Billing Interface\n * --------\n * This is the canonical interface that Wildo uses internally for all billing\n * operations. The ETL layer transforms these standard requests into\n * provider-specific API calls (e.g., Stripe, Paddle, LemonSqueezy).\n *\n * Design Principles:\n * 1. Provider-agnostic — works with any billing provider\n * 2. Hosted-first — uses provider-hosted checkout and portals (no PCI scope)\n * 3. Webhook-driven — state changes flow in via webhooks, not polling\n * 4. Scope-agnostic — billing accounts map to any Wildo scope (org, user)\n *\n * @see billing-and-features-system.md §7.1 (Standard Billing Interface)\n */\n\n// ===============================================================\n// Billing Interface Enums (canonical source, re-exported by saas-models)\n// ===============================================================\n\n/**\n * Pricing model for a price entry.\n */\nexport enum PricingModel {\n FLAT = 'flat',\n PER_UNIT = 'per_unit',\n /** Volume pricing (all units at tier price) */\n TIERED = 'tiered',\n /** Incremental (each tier priced independently) */\n GRADUATED = 'graduated',\n /** Price per package of N units */\n PACKAGE = 'package',\n}\n\n/**\n * Billing interval for recurring prices.\n */\nexport enum BillingInterval {\n MONTH = 'month',\n YEAR = 'year',\n}\n\n/**\n * Tax display mode: how prices are displayed (HT vs TTC).\n */\nexport enum TaxDisplayMode {\n /** Price amounts are HT (tax added at checkout) */\n EXCLUSIVE = 'exclusive',\n /** Price amounts are TTC (tax embedded) */\n INCLUSIVE = 'inclusive',\n}\n\n/**\n * How a mid-cycle subscription change is settled.\n *\n * A PROTOCOL vocabulary, and it lives here for the same reason {@link TaxDisplayMode} does: these three\n * values are the wire values a billing provider accepts. It was declared in `@wildo-ai/saas-models`\n * until 2026-09-08 and re-exported the other way round, which is why an authored proration could be\n * resolved by the engine and had no field on the request to travel in — the request contract could not\n * name the type without a package cycle, so the resolved value was sent as provider METADATA and\n * ignored (#516).\n *\n * `@wildo-ai/saas-models` re-exports it, so every existing consumer is unchanged.\n */\nexport enum ProrationBehavior {\n /** Credit the unused time and charge the new price pro rata, settled on the next invoice. */\n CREATE_PRORATIONS = 'create_prorations',\n /** No proration: the change takes effect and the next invoice is the new price in full. */\n NONE = 'none',\n /** Prorate and invoice the difference IMMEDIATELY rather than at the next cycle. */\n ALWAYS_INVOICE = 'always_invoice',\n}\n\n/**\n * How the provider treats a subscription change whose resulting payment does not succeed (#535, decision D6).\n *\n * Wildo applies a confirmed plan change IMMEDIATELY: entitlements move at local completion, and a failed proration\n * payment moves the subscription to `past_due` through the webhook projection, where dunning owns what happens next.\n * The value is DECLARED on every engine-issued change rather than left to the provider's default, so a change of that\n * default can never silently change the semantics.\n *\n * Deliberately a one-member vocabulary. `pending_if_incomplete` (apply only after payment, expire after 23 h) was\n * weighed and rejected in #535; add a member only with a decision that changes D6.\n *\n * spec-cite: https://docs.stripe.com/api/subscriptions/update — `payment_behavior`; the value equals Stripe's wire value,\n * so the Stripe adapter passes it untranslated, as it does `ProrationBehavior`.\n */\nexport enum StandardBilling_SubscriptionPaymentBehavior {\n /** Apply the change now; an unpaid resulting invoice leaves the subscription `past_due`. */\n ALLOW_INCOMPLETE = 'allow_incomplete',\n}\n\n/**\n * What a FAILED provider mutation tells the caller about whether the change took effect (#535, decision D3).\n *\n * The distinction that matters is not the HTTP status but what may be recorded next: a conclusive refusal and a request\n * that never executed may both be recorded as \"no effect\", while an indeterminate outcome must NEVER be — the provider\n * may have applied it, or may still apply it. Only the adapter can read its vendor's error shape, so each adapter\n * classifies (`StandardBilling_Interface.classifyMutationError`) and the engine decides on the class alone.\n *\n * spec-cite: https://docs.stripe.com/error-low-level — \"Network errors\", \"Server errors\", \"Content errors\" (the\n * source of the classes for the Stripe adapter; other adapters map their own vendor's equivalents).\n */\nexport enum StandardBilling_MutationErrorClass {\n /** The provider evaluated the request and refused it (e.g. a declined card, a missing object). No effect. */\n CONCLUSIVE_REJECTION = 'conclusive_rejection',\n /** Refused before execution (rate limit, authentication). No effect; a later attempt must use a NEW idempotency key. */\n NOT_EXECUTED = 'not_executed',\n /** Another request with the same idempotency key is still being processed. The outcome is not known yet. */\n IN_FLIGHT_CONFLICT = 'in_flight_conflict',\n /** Timeout, connection loss, server error, or a failure after the provider answered. The change may have applied. */\n INDETERMINATE = 'indeterminate',\n}\n\n/**\n * Subscription status values (maps to Stripe subscription statuses).\n */\nexport enum SubscriptionStatus {\n ACTIVE = 'active',\n PAST_DUE = 'past_due',\n UNPAID = 'unpaid',\n CANCELLED = 'cancelled',\n /** Stripe: first payment never completed within 23h window */\n INCOMPLETE = 'incomplete',\n INCOMPLETE_EXPIRED = 'incomplete_expired',\n TRIALING = 'trialing',\n PAUSED = 'paused',\n}\n\n/**\n * Invoice lifecycle status, as the PROVIDER reports it.\n *\n * A PROTOCOL vocabulary for the same reason {@link SubscriptionStatus} is one: these are the states\n * a billing provider puts an invoice in, and the adapter's job is to map its own wire values onto\n * them. It was declared in `@wildo-ai/saas-models` until 2026-09-09 and could not be named by this\n * package at all, so `listInvoices` — the read the reconciliation sweep needs — had no way to type\n * the one field the sweep compares.\n *\n * Moved rather than duplicated: a second enum with the same five members would be two sources for\n * one closed vocabulary, which is what `CLAUDE.md` forbids. `@wildo-ai/saas-models` re-exports it\n * exactly as it already re-exports `SubscriptionStatus`, `TaxDisplayMode` and `ProrationBehavior`,\n * so every existing consumer — including the `invoiceRefs` schema, the badge palette and the\n * documentation catalogue — imports the same specifier it always did.\n */\nexport enum InvoiceStatus {\n /** Not finalized: the provider has not issued it for collection and it may still change. */\n DRAFT = 'draft',\n /** Finalized and awaiting payment. */\n OPEN = 'open',\n /** Settled. */\n PAID = 'paid',\n /** Cancelled by the provider or the merchant; never collectable. */\n VOID = 'void',\n /** Written off — payment was attempted and abandoned. */\n UNCOLLECTIBLE = 'uncollectible',\n}\n\n// ===============================================================\n// Standard Billing Event Types\n// ===============================================================\n\n/**\n * Canonical billing events the system cares about.\n * Provider-specific events are mapped to these types by the transformer.\n * Only events that affect local state (features, status) need to be handled.\n */\nexport enum StandardBilling_EventType {\n // Subscription lifecycle (→ feature sync)\n SUBSCRIPTION_CREATED = 'subscription.created',\n SUBSCRIPTION_UPDATED = 'subscription.updated',\n SUBSCRIPTION_DELETED = 'subscription.deleted',\n SUBSCRIPTION_TRIAL_WILL_END = 'subscription.trial_will_end',\n\n // Invoice status (→ billing status tracking, past_due detection)\n INVOICE_PAID = 'invoice.paid',\n INVOICE_PAYMENT_FAILED = 'invoice.payment_failed',\n INVOICE_FINALIZED = 'invoice.finalized',\n\n // Checkout (→ one-off purchase completion for ONE_TIME, CREDIT_PACK, ITEM products)\n CHECKOUT_SESSION_COMPLETED = 'checkout.session.completed',\n\n // Customer (→ billing account sync)\n CUSTOMER_UPDATED = 'customer.updated',\n CUSTOMER_DELETED = 'customer.deleted',\n\n // Coupon (→ no local action; coupons are managed through Wildo's promotion system.\n // Included for logging/audit in case coupons are modified directly on the provider.)\n COUPON_CREATED = 'coupon.created',\n COUPON_UPDATED = 'coupon.updated',\n COUPON_DELETED = 'coupon.deleted',\n\n // Customer discount (→ subscription re-sync to pick up discount changes)\n CUSTOMER_DISCOUNT_CREATED = 'customer.discount.created',\n CUSTOMER_DISCOUNT_UPDATED = 'customer.discount.updated',\n CUSTOMER_DISCOUNT_DELETED = 'customer.discount.deleted',\n\n // Payment method (→ no local action needed; provider manages via Customer Portal.\n // Included for completeness: apps can optionally log these events for audit trails.)\n PAYMENT_METHOD_ATTACHED = 'payment_method.attached',\n PAYMENT_METHOD_DETACHED = 'payment_method.detached',\n}\n\n// ===============================================================\n// Standard Billing Webhook Event\n// ===============================================================\n\n/**\n * Canonical webhook event representation.\n * Provider transformers parse raw webhook payloads into this shape.\n */\nexport interface StandardBilling_WebhookEvent {\n /** Canonical event type */\n type: StandardBilling_EventType;\n /** Provider-assigned event ID (for idempotency) */\n providerEventId: string;\n /** Event payload — shape varies by event type */\n data: Record<string, unknown>;\n /** When the event occurred at the provider */\n createdAt: Date;\n}\n\n// ===============================================================\n// Request/Response Types\n// ===============================================================\n\n// ── Customer ────────────────────────────────────────────────────\n\nexport interface StandardBilling_CreateCustomerRequest {\n /**\n * Descriptive name — the organisation's name for an org-scoped account, the person's display name\n * for a user-scoped one.\n *\n * OPTIONAL, and that is the point (issue #486). It was required, and a caller that could not\n * resolve one therefore had to INVENT it: the engine sent the literal `'Unknown'` for every\n * customer it ever created. A contract that cannot express \"we do not know\" forces every caller to\n * lie, and a fabricated value is worse than an absent one — an operator reading the provider\n * dashboard cannot tell it from a real answer.\n */\n name?: string;\n /**\n * Contact email for invoices and receipts.\n *\n * OPTIONAL for the same reason as `name`, and additionally because **an organisation frequently has\n * no billing email at all**. Sending a natural person's address for an ORGANISATION's customer\n * record would put personal data on a record that is not about a person — the opposite of data\n * minimisation, which asks that personal data be \"adequate, relevant and limited to what is\n * necessary\".\n * spec-cite: GDPR Art. 5(1)(c) — https://gdpr-info.eu/art-5-gdpr/\n *\n * It also makes the later erasure story cheap: an organisation record carrying no individual's\n * identity never has to be visited when that individual exercises their right to erasure, so the\n * obligation to inform recipients of an erasure does not reach it.\n * spec-cite: GDPR Art. 17(2) — https://gdpr-info.eu/art-17-gdpr/\n *\n * Absent is a legitimate value at the provider: Stripe's own customer `email` is optional.\n * spec-cite: N/A — describes the Stripe Customer object's declared optionality in this\n * repository's own words (https://docs.stripe.com/api/customers/object).\n */\n email?: string;\n /** Arbitrary key-value metadata stored on the provider customer */\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateCustomerResponse {\n providerCustomerId: string;\n}\n\n/**\n * Postal address on a provider customer record.\n *\n * Every field is independently clearable (`null`) rather than merely omittable: `undefined` means\n * \"leave whatever the provider already has\", `null` means \"blank it\". Subject erasure needs the\n * second meaning — an address that is silently preserved because the request could only express\n * \"no change\" is personal data surviving an erasure.\n */\nexport interface StandardBilling_CustomerAddress {\n line1?: string | null;\n line2?: string | null;\n city?: string | null;\n state?: string | null;\n postalCode?: string | null;\n /** ISO 3166-1 alpha-2 country code. */\n country?: string | null;\n}\n\nexport interface StandardBilling_UpdateCustomerRequest {\n name?: string;\n email?: string;\n metadata?: Record<string, string>;\n /**\n * Contact phone. `null` clears it at the provider — see {@link StandardBilling_CustomerAddress}\n * for why clearability is expressed separately from omission.\n */\n phone?: string | null;\n /**\n * Billing address. `null` clears the whole address; a partial object clears only the fields it\n * sets to `null` and leaves the rest untouched.\n */\n address?: StandardBilling_CustomerAddress | null;\n}\n\n/**\n * A stored payment instrument attached to a provider customer.\n *\n * Deliberately thin: enough to identify an instrument for detachment and to render a\n * \"•••• 4242\"-style hint, and nothing more. Wildo never handles raw instrument data — that is the\n * whole point of routing users through the provider-hosted portal — so this carries no PAN, no\n * expiry, and no billing details.\n */\nexport interface StandardBilling_PaymentMethodSummary {\n providerPaymentMethodId: string;\n /**\n * Instrument kind as the provider names it (`'card'`, `'sepa_debit'`, `'us_bank_account'`, …).\n * Intentionally an OPEN provider identifier, not a closed Wildo vocabulary: the set differs per\n * provider and grows without our involvement, and nothing in the framework branches on it — it\n * is carried for display and diagnostics only.\n */\n type: string;\n /** Last four digits, when the instrument exposes them. */\n last4?: string;\n}\n\n// ── Product/Price Sync ──────────────────────────────────────────\n\nexport interface StandardBilling_SyncProductRequest {\n /** Internal Wildo product key (stored in metadata for reverse lookup) */\n productKey: string;\n name: string;\n description?: string;\n /** If set, updates existing provider product instead of creating new */\n providerProductId?: string;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_SyncProductResponse {\n providerProductId: string;\n}\n\nexport interface StandardBilling_SyncPriceRequest {\n providerProductId: string;\n model: PricingModel;\n /** Amount in smallest currency unit (cents) */\n amount: number;\n currency: string;\n interval?: BillingInterval;\n /** Multiplier of the recurring interval (3 months = quarterly). Omitted means 1; ignored for one-time prices. */\n intervalCount?: number;\n /** For TIERED/VOLUME pricing models */\n tiers?: Array<{\n upTo: number | null;\n unitAmount: number;\n flatAmount?: number;\n }>;\n /** For PACKAGE pricing */\n packageSize?: number;\n /** Tax behavior */\n taxBehavior?: TaxDisplayMode;\n /** If set, updates existing provider price instead of creating new */\n providerPriceId?: string;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_SyncPriceResponse {\n providerPriceId: string;\n}\n\n// ── Subscription Lifecycle ──────────────────────────────────────\n\nexport interface StandardBilling_CreateSubscriptionRequest {\n providerCustomerId: string;\n items: Array<{\n providerPriceId: string;\n quantity?: number;\n }>;\n trialPeriodDays?: number;\n /** Provider promotion code to apply */\n providerPromotionCodeId?: string;\n /**\n * Ask the provider to compute tax on this purchase (#408, 2026-09-08).\n *\n * Set from the application's `billing.tax.calculationMode`, which is PROVIDER_MANAGED or\n * DISABLED — Wildo never calculates tax locally, so the only question a provider is asked is\n * whether to calculate at all. A provider that cannot compute tax ignores this; one that can and\n * is not configured for the customer's jurisdiction will say so at the call, which is the right\n * place for that failure.\n *\n * Distinct from a price's `taxBehavior`, which says whether a displayed amount INCLUDES tax.\n * That one has always reached the provider; this one decides whether tax is computed.\n */\n automaticTax?: boolean;\n /**\n * Require a payment method up front for a trial (#408, 2026-09-08).\n *\n * Set from the product's `behaviorPolicy.trial.requirePaymentMethod`, which was declared,\n * labelled, rendered on billing screens and passed to no provider call — so a trial declared as\n * requiring a card behaved identically to one that did not. Wonder Todos' enterprise plan\n * (`true`) and professional plan (`false`) were indistinguishable at the provider.\n *\n * Two provider-side consequences follow and a connector should honour both: collect the payment\n * method during checkout, and decide what happens if the trial ends without one.\n */\n requirePaymentMethodForTrial?: boolean;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateSubscriptionResponse {\n providerSubscriptionId: string;\n status: string;\n}\n\n/** Provider-confirmed identities of correlated additions from the same update operation. */\nexport interface StandardBilling_UpdateSubscriptionResponse {\n createdItems: Array<{ clientItemKey: string; providerSubscriptionItemId: string }>;\n}\n\nexport interface StandardBilling_UpdateSubscriptionRequest {\n /**\n * Server-owned identity of one attempted change, reused with the SAME subscription and payload\n * when recovering a lost response. Never generate a new key for a retry. Provider retention is\n * bounded: this does not replace confirmation consumption, freshness checks or reconciliation.\n * This is request transport metadata, not subscription metadata or a browser authoring field.\n */\n idempotencyKey?: string;\n /** Item patches: omitted existing items are retained; an item without an ID is added. */\n items?: Array<{\n /** Provider-side subscription item ID to update. Omit only when adding a new item. */\n providerSubscriptionItemId?: string;\n /** Backend-generated correlation key for an intentional new item; echoed with its created provider ID. */\n clientItemKey?: string;\n providerPriceId: string;\n quantity?: number;\n }>;\n /** Explicit provider-side item IDs to remove. Omitting an item from `items` never removes it. */\n removedProviderSubscriptionItemIds?: string[];\n /** Provider promotion code to apply */\n providerPromotionCodeId?: string;\n /**\n * How the provider settles this mid-cycle change (#516).\n *\n * The engine resolves it from the target product's `upgrade`/`downgrade` behaviour policy and it\n * had nowhere to travel: it was put in `metadata`, a free-form bag the provider does not read, so a\n * product declaring `NONE` for a downgrade was still prorated by the provider's own default. Absent\n * means \"do not send one\" — the provider applies its account default, which is what every\n * subscription update did before this field existed.\n */\n prorationBehavior?: ProrationBehavior;\n /**\n * How the provider treats an unpaid resulting invoice (#535, D6). Absent sends none, so the provider's default\n * applies; the engine's own plan-change dispatch always declares it.\n */\n paymentBehavior?: StandardBilling_SubscriptionPaymentBehavior;\n /** Unix seconds used for proration. Reuse the preview instant when confirming the same change. */\n prorationDate?: number;\n metadata?: Record<string, string>;\n}\n\n/**\n * Hypothetical item patch for an upcoming invoice. Item identity, quantity and proration must match\n * the eventual update; selecting the first provider item can accidentally preview an addon change.\n * Omitted items remain on the subscription. This request never changes the subscription itself.\n */\nexport type StandardBilling_SubscriptionPreviewRequest = Pick<StandardBilling_UpdateSubscriptionRequest,\n 'items' | 'removedProviderSubscriptionItemIds' | 'prorationBehavior' | 'prorationDate'>;\n\n/**\n * Request transport options shared by the subscription mutations that carry no payload of their own.\n *\n * `idempotencyKey` has the same contract as on {@link StandardBilling_UpdateSubscriptionRequest}: a server-owned\n * identity of ONE attempted change, reused with the same subscription and options only to recover a lost response.\n */\nexport interface StandardBilling_SubscriptionMutationOptions {\n idempotencyKey?: string;\n}\n\n/**\n * A plan change deferred to the end of the subscription's current period (#1868).\n *\n * The provider keeps the subscription as it is until the period ends and then moves it onto `items`. Stripe does this with a\n * subscription schedule: one phase holding the current lines until `current_period_end`, a second holding `items`, released\n * afterwards so the subscription runs on without it. The adapter derives the current lines and the period end from the\n * subscription itself, so the change always lands at the renewal of the period it was confirmed in.\n */\nexport interface StandardBilling_SchedulePlanChangeRequest extends StandardBilling_SubscriptionMutationOptions {\n /** Every line the subscription carries from the next period: the new plan and the add-ons that carry over. */\n items: Array<{ providerPriceId: string; quantity: number }>;\n /** How the provider settles the move into the new lines at renewal. Absent sends none. */\n prorationBehavior?: ProrationBehavior;\n /** Written on the schedule, so a later read can name the change that created it (`wildo_mutation`). */\n metadata?: Record<string, string>;\n}\n\n/** The provider's handle on a deferred plan change: what `releaseSubscriptionSchedule` withdraws. */\nexport interface StandardBilling_SchedulePlanChangeResponse {\n providerScheduleId: string;\n}\n\n/** How a schedule is released (#1868). */\nexport interface StandardBilling_ReleaseScheduleOptions extends StandardBilling_SubscriptionMutationOptions {\n /**\n * Release only while the schedule still has a phase AHEAD of the current one — a WITHDRAWAL of a change that has not taken effect. A\n * schedule still managing the subscription with its next phase begun is refused conclusively, nothing sent: releasing it then would\n * keep the subscription on the lines the change moved it to, while the caller believed the change withdrawn. A schedule already\n * released, cancelled or completed succeeds only when the caller's key replays its own earlier release; otherwise it answers an\n * INDETERMINATE failure — it may be this caller's release, so only a read of what the provider bills can say whether the withdrawal\n * happened. Absent, a schedule is released whatever phase it is in, which is\n * how the engine lets go of a schedule whose change has already landed.\n */\n onlyBeforeNextPhase?: boolean;\n}\n\nexport interface StandardBilling_CancelSubscriptionOptions extends StandardBilling_SubscriptionMutationOptions {\n /** If true, subscription remains active until current period ends */\n atPeriodEnd?: boolean;\n}\n\n// ── Read/Sync (Reconciliation) ──────────────────────────────────\n\n/**\n * StandardBilling_SubscriptionData: canonical subscription representation\n * returned by the provider adapter's retrieveSubscription().\n * Used for reconciliation when webhooks may have been missed.\n */\nexport interface StandardBilling_SubscriptionData {\n providerSubscriptionId: string;\n status: SubscriptionStatus;\n currentPeriodStart: Date;\n currentPeriodEnd: Date;\n cancelAtPeriodEnd: boolean;\n /**\n * When the subscription's trial began and ends, if it had one. The provider keeps both after the trial\n * is over, so a subscription that trialed carries them for its whole life, and one that never did\n * carries neither.\n */\n trialStart?: Date;\n trialEnd?: Date;\n /**\n * The schedule the provider holds on this subscription, if any (#1868): how a deferred plan change is kept until renewal.\n * `upcomingPhase` is the phase after the current one — the lines the subscription moves to and when — and is absent once\n * the last phase is current, which for an engine-created schedule means its change has taken effect. `metadata` carries\n * the reference of the engine mutation that created the schedule (`wildo_mutation`), absent on one made elsewhere.\n */\n schedule?: {\n providerScheduleId: string;\n metadata: Record<string, string>;\n upcomingPhase?: { startsAt: Date; items: Array<{ providerPriceId: string; quantity: number }> };\n };\n items: Array<{\n providerSubscriptionItemId: string;\n providerProductId: string;\n providerPriceId: string;\n quantity: number;\n }>;\n /**\n * Every subscription-level discount the provider applies, from coupons and promotion codes, in the order the provider\n * applies them. Absent or empty when none applies, including after the last one has ended.\n *\n * ALL of them, because a subscription can hold several — a referral reward (`addSubscriptionDiscount`) is added BESIDE\n * a promotion the checkout applied — and each is charged (#1948). An adapter that reported only the first would leave\n * the application showing one discount while the customer is billed for two.\n * `duration` is a `PromotionDuration` value: `once`, `repeating` or `forever`.\n */\n discounts?: Array<{\n providerCouponId: string;\n percentOff?: number;\n amountOff?: number;\n currency?: string;\n duration: string;\n durationInMonths?: number;\n end?: Date;\n }>;\n}\n\n/**\n * StandardBilling_InvoicePreview: canonical upcoming invoice from provider.\n * Returned by retrieveUpcomingInvoice() for plan change previews.\n */\nexport interface StandardBilling_InvoicePreview {\n /** Upcoming invoice amount due, in currency minor units; not a promise of an immediate charge. */\n amount: number;\n currency: string;\n lineItems: Array<{\n description: string;\n amount: number;\n quantity: number;\n providerPriceId?: string;\n }>;\n periodStart: Date;\n periodEnd: Date;\n}\n\n/**\n * StandardBilling_InvoiceData: an invoice the provider ALREADY holds.\n *\n * Distinct from {@link StandardBilling_InvoicePreview}, and the distinction is the point: a preview\n * is a hypothetical the provider computes on request and never stores, while this is a record that\n * exists at the provider whether or not Wildo ever heard about it. The second is what a\n * reconciliation sweep needs — a webhook that was never delivered leaves an invoice that exists\n * there and nowhere here, and no amount of previewing finds it.\n *\n * Deliberately thin. It carries what `invoiceRefs` stores and nothing else: line items, tax\n * breakdowns and payment attempts live at the provider, and the customer reaches them through the\n * provider-hosted portal.\n */\nexport interface StandardBilling_InvoiceData {\n providerInvoiceId: string;\n /** The customer the invoice was billed to — the key that maps it back to a local billing account. */\n providerCustomerId: string;\n status: InvoiceStatus;\n /**\n * The invoice TOTAL, in the CURRENCY's smallest unit.\n *\n * The total, not the amount PAID: an invoice's value does not depend on whether it has been\n * settled, and an unpaid invoice recorded at zero is indistinguishable from a zero invoice.\n */\n total: number;\n currency: string;\n hostedInvoiceUrl?: string;\n invoicePdfUrl?: string;\n /** When the provider created the invoice — used to bound how far back a sweep looks. */\n createdAt: Date;\n}\n\n// ── Checkout / Portal (Provider-Hosted UI) ──────────────────────\n\nexport interface StandardBilling_CreateCheckoutSessionRequest {\n providerCustomerId: string;\n lineItems: Array<{\n providerPriceId: string;\n quantity?: number;\n }>;\n /** Checkout mode: 'subscription' for recurring, 'payment' for one-time */\n mode: 'subscription' | 'payment';\n successUrl: string;\n cancelUrl: string;\n /** Allow promotion codes in checkout */\n allowPromotionCodes?: boolean;\n /** Pre-fill promotion code */\n providerPromotionCodeId?: string;\n /** Trial period for subscriptions */\n trialPeriodDays?: number;\n /**\n * Ask the provider to compute tax on this purchase (#408, 2026-09-08).\n *\n * Set from the application's `billing.tax.calculationMode`, which is PROVIDER_MANAGED or\n * DISABLED — Wildo never calculates tax locally, so the only question a provider is asked is\n * whether to calculate at all. A provider that cannot compute tax ignores this; one that can and\n * is not configured for the customer's jurisdiction will say so at the call, which is the right\n * place for that failure.\n *\n * Distinct from a price's `taxBehavior`, which says whether a displayed amount INCLUDES tax.\n * That one has always reached the provider; this one decides whether tax is computed.\n */\n automaticTax?: boolean;\n /**\n * Require a payment method up front for a trial (#408, 2026-09-08).\n *\n * Set from the product's `behaviorPolicy.trial.requirePaymentMethod`, which was declared,\n * labelled, rendered on billing screens and passed to no provider call — so a trial declared as\n * requiring a card behaved identically to one that did not. Wonder Todos' enterprise plan\n * (`true`) and professional plan (`false`) were indistinguishable at the provider.\n *\n * Two provider-side consequences follow and a connector should honour both: collect the payment\n * method during checkout, and decide what happens if the trial ends without one.\n */\n requirePaymentMethodForTrial?: boolean;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateCheckoutSessionResponse {\n /** Redirect URL for the hosted checkout page */\n url: string;\n sessionId: string;\n}\n\nexport interface StandardBilling_CreateCustomerPortalSessionResponse {\n /** Redirect URL for the customer portal */\n url: string;\n}\n\n// ── Usage Reporting (METERED products via Billing Meter Events) ─\n\nexport interface StandardBilling_ReportUsageRequest {\n /** Meter event name (corresponds to the meter's event_name) */\n meterEventName: string;\n /** Provider customer ID (maps to payload.stripe_customer_id in Stripe) */\n providerCustomerId: string;\n /** Usage value to report */\n value: number;\n /** Optional event timestamp */\n timestamp?: Date;\n /** Optional unique event identifier (for idempotency) */\n identifier?: string;\n}\n\n// ── Promotions ──────────────────────────────────────────────────\n\nexport interface StandardBilling_CreateCouponRequest {\n /** Discount amount in smallest currency unit (for fixed discounts) */\n amountOff?: number;\n /** Discount percentage (for percentage discounts) */\n percentOff?: number;\n currency?: string;\n duration: 'once' | 'repeating' | 'forever';\n durationInMonths?: number;\n maxRedemptions?: number;\n metadata?: Record<string, string>;\n}\n\nexport interface StandardBilling_CreateCouponResponse {\n providerCouponId: string;\n}\n\nexport interface StandardBilling_CreatePromotionCodeResponse {\n providerPromotionId: string;\n}\n\n/**\n * A percentage discount GIVEN to one subscription — a referral reward (#1802) — rather than redeemed by the\n * customer from a code.\n */\nexport interface StandardBilling_AddSubscriptionDiscountRequest {\n /** Percentage taken off, 1–100. */\n percentOff: number;\n duration: 'once' | 'repeating' | 'forever';\n /** Months, for a `repeating` discount. */\n durationInMonths?: number;\n /**\n * Stable per grant. The adapter derives the provider coupon's identity and its idempotency keys from it, so\n * a repeated call with the same key adds the discount once.\n */\n grantKey: string;\n metadata?: Record<string, string>;\n}\n\n// ===============================================================\n// Standard Billing Interface\n// ===============================================================\n\n/**\n * Provider-agnostic billing interface.\n * Each billing provider (Stripe, Paddle, etc.) implements this interface\n * through a transformer that maps canonical operations to provider SDK calls.\n */\nexport interface StandardBilling_Interface {\n // ── Customer (maps to BillingAccount) ──\n createCustomer(request: StandardBilling_CreateCustomerRequest): Promise<StandardBilling_CreateCustomerResponse>;\n updateCustomer(providerCustomerId: string, request: StandardBilling_UpdateCustomerRequest): Promise<void>;\n /**\n * Hard-delete the provider customer.\n *\n * ⚠️ NOT the subject-erasure path. Erasing a subject ANONYMIZES this customer (blank the personal\n * fields, keep the record) because the financial history hanging off it — invoices, subscriptions,\n * usage — is retained under a legal obligation and must stay attributable to its provider record.\n * Deleting the customer would strand exactly the audit trail retention exists to preserve.\n * Reserve this for a genuine account teardown with no retained history.\n */\n deleteCustomer(providerCustomerId: string): Promise<void>;\n\n // ── Payment instruments ──\n /**\n * Stored payment instruments for a customer. Used by subject erasure to enumerate what must be\n * detached; day-to-day management belongs in the provider-hosted portal.\n */\n listPaymentMethods(providerCustomerId: string): Promise<StandardBilling_PaymentMethodSummary[]>;\n /**\n * Detach an instrument from its customer. Detaching does NOT delete the instrument's transaction\n * history at the provider — it stops future charges and unlinks it from the customer, which is\n * what erasure needs and what the retained invoice record requires.\n */\n detachPaymentMethod(providerPaymentMethodId: string): Promise<void>;\n /**\n * Blank the personal data an instrument carries about whoever paid with it — the cardholder's name,\n * email, phone and billing address — keeping the instrument itself (#869).\n *\n * Detaching does not do this: a detached instrument still exists at the provider with its billing\n * details intact, and on Stripe it can no longer be edited once detached (\"You must save this\n * PaymentMethod to a customer before you can update it\", measured 2026-09-25). So subject erasure\n * calls this BEFORE {@link detachPaymentMethod}. A provider field that cannot be unset stays: Stripe\n * refuses to clear `address.country`, which identifies nobody on its own.\n *\n * The card network data (brand, last four digits, expiry, fingerprint) is the instrument, not contact\n * data, and stays with the retained transaction record it belongs to.\n */\n redactPaymentMethodBillingDetails(providerPaymentMethodId: string): Promise<void>;\n\n // ── Product/Price sync (Wildo → Provider) ──\n syncProduct(request: StandardBilling_SyncProductRequest): Promise<StandardBilling_SyncProductResponse>;\n syncPrice(request: StandardBilling_SyncPriceRequest): Promise<StandardBilling_SyncPriceResponse>;\n /**\n * Whether the provider price a local price is LINKED to still carries the local terms (#1907): active, on the\n * requested product, and equal in amount, currency, cadence, tiers, packaging and tax behaviour.\n *\n * A provider price is immutable, so a link made under an earlier amount convention — or before a catalogue edit —\n * keeps charging the old amount unless something compares the two. The catalogue sync asks this of every linked\n * price and re-syncs one that answers `false`. Answer `false` when the price cannot be read: the caller then\n * creates a correct price rather than keeping a link nobody could check.\n */\n linkedPriceMatches(providerPriceId: string, request: StandardBilling_SyncPriceRequest): Promise<boolean>;\n\n // ── Subscription lifecycle ──\n // NOTE: User-initiated plan changes, cancellation, and payment method management\n // should use createCustomerPortalSession() instead of calling these directly.\n // These methods are for: initial checkout completion, backend-driven upgrades,\n // admin-triggered changes, and webhook-driven updates.\n createSubscription(request: StandardBilling_CreateSubscriptionRequest): Promise<StandardBilling_CreateSubscriptionResponse>;\n updateSubscription(providerSubscriptionId: string, request: StandardBilling_UpdateSubscriptionRequest): Promise<StandardBilling_UpdateSubscriptionResponse>;\n cancelSubscription(providerSubscriptionId: string, options?: StandardBilling_CancelSubscriptionOptions): Promise<void>;\n pauseSubscription(providerSubscriptionId: string): Promise<void>;\n /** Resume paused payment collection; does not undo a scheduled cancellation. */\n resumeSubscription(providerSubscriptionId: string): Promise<void>;\n /** Remove a pending period-end cancellation without changing collection or lifecycle status. */\n removeScheduledCancellation(providerSubscriptionId: string, options?: StandardBilling_SubscriptionMutationOptions): Promise<void>;\n /**\n * Defer a plan change to the end of the current period (#1868). One deferred change at a time: the engine refuses a second\n * while one is pending, and it is withdrawn (`releaseSubscriptionSchedule`) before another is made.\n */\n schedulePlanChange(providerSubscriptionId: string, request: StandardBilling_SchedulePlanChangeRequest): Promise<StandardBilling_SchedulePlanChangeResponse>;\n /**\n * Withdraw a schedule from its subscription, leaving the subscription running as it is now (#1868). Releasing a schedule that is\n * already released succeeds: the state asked for holds — except with `onlyBeforeNextPhase`, where it succeeds only as a replay of the\n * caller's own release and otherwise answers an INDETERMINATE failure, and the caller decides from what the provider bills.\n */\n releaseSubscriptionSchedule(providerScheduleId: string, options?: StandardBilling_ReleaseScheduleOptions): Promise<void>;\n /**\n * Classify an error thrown by `updateSubscription`, `cancelSubscription`, `removeScheduledCancellation`, `schedulePlanChange` or\n * `releaseSubscriptionSchedule` (#535, D3).\n *\n * Must answer {@link StandardBilling_MutationErrorClass.INDETERMINATE} for anything the adapter cannot positively place\n * — including an error the adapter itself threw AFTER the provider answered — because every other class licenses the\n * caller to record that the change did not happen.\n */\n classifyMutationError(error: unknown): StandardBilling_MutationErrorClass;\n\n // ── Read/sync (for reconciliation and upcoming cost preview) ──\n /** On-demand retrieval for reconciliation (if webhook missed) */\n retrieveSubscription(providerSubscriptionId: string): Promise<StandardBilling_SubscriptionData>;\n /** Preview the upcoming invoice for an optional item change; the amount is not necessarily charged immediately. */\n retrieveUpcomingInvoice(providerSubscriptionId: string, request?: StandardBilling_SubscriptionPreviewRequest): Promise<StandardBilling_InvoicePreview>;\n /**\n * Invoices the provider holds for one customer, newest first.\n *\n * The RECOVERY read for {@link StandardBilling_EventType.INVOICE_PAID} and its siblings. Wildo\n * never creates an invoice — every local `invoiceRefs` row exists because a webhook arrived — so a\n * delivery that is lost, or that arrives while the application is down and exhausts the provider's\n * retries, leaves an invoice with no local trace and nothing that could notice. This is the only\n * call that can find one.\n *\n * `limit` bounds one page and an adapter may cap it lower; the sweep asks for a recent window\n * rather than the whole history, because an invoice older than the window has either been\n * reconciled already or is a backlog no single tick should try to drain.\n */\n listInvoices(providerCustomerId: string, options?: { limit?: number }): Promise<StandardBilling_InvoiceData[]>;\n\n // ── Provider-hosted UI (primary user-facing interactions) ──\n /** Hosted checkout page — NO Stripe Elements needed, no PCI scope */\n createCheckoutSession(request: StandardBilling_CreateCheckoutSessionRequest): Promise<StandardBilling_CreateCheckoutSessionResponse>;\n /** Customer portal for: invoices, payment methods, billing address, cancel */\n createCustomerPortalSession(providerCustomerId: string, returnUrl: string): Promise<StandardBilling_CreateCustomerPortalSessionResponse>;\n\n // ── Usage reporting (for METERED products) ──\n reportUsage(request: StandardBilling_ReportUsageRequest): Promise<void>;\n\n // ── Webhooks ──\n /** HTTP header name that carries the webhook signature (e.g., 'stripe-signature') */\n readonly webhookSignatureHeaderName: string;\n verifyWebhookSignature(payload: string | Uint8Array, signature: string, secret: string): boolean;\n /** Parse a raw webhook payload into a canonical event. Returns null for unknown/unhandled event types. */\n parseWebhookEvent(payload: string | Uint8Array): StandardBilling_WebhookEvent | null;\n\n // ── Promotions (synced to provider) ──\n createCoupon(request: StandardBilling_CreateCouponRequest): Promise<StandardBilling_CreateCouponResponse>;\n createPromotionCode(providerCouponId: string, code: string): Promise<StandardBilling_CreatePromotionCodeResponse>;\n /**\n * Add a discount to a subscription, KEEPING any discount it already carries (#1802). Idempotent on\n * `request.grantKey`: a second call with the same key finds its discount already applied and adds nothing.\n */\n addSubscriptionDiscount(providerSubscriptionId: string, request: StandardBilling_AddSubscriptionDiscountRequest): Promise<void>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-extraction.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"document-extraction.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["../../../../src/protocols/document-extraction.external-connectors-models.schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-extraction.external-connectors-models.schemas.js","sourceRoot":"","sources":["../../../src/protocols/document-extraction.external-connectors-models.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\"\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n } from \"../core/commons.external-connectors-models.schemas\"\n\n//===============================================================\n// Document Extraction Provider\n// --------\n// Document bytes → text. Serves the file-side TEXT PROVIDER that\n// `FileTextExtractionBackendService` owns, whose largest consumer is the RAG\n// ingestion path (`.ragSource()` corpus building).\n//\n// ## Why this is a provider at all, and not just a better library\n//\n// The local `pdfjs-dist` path reads a PDF's TEXT LAYER. A scanned document — the\n// common case for uploaded contracts, invoices and forms — is an IMAGE of a page\n// and carries no text layer, so it extracts to the empty string, contributes no\n// chunks, and becomes silently unanswerable. That is not a defect in the local\n// library; it is its nature, and it is the entire reason a provider exists here.\n//\n// ## Deliberately a SEPARATE protocol kind from `LLM_PROVIDER`\n//\n// Same reasoning as `EMBEDDINGS_PROVIDER` (RAG plan DL2) and the `IMAGE_PROVIDER`\n// precedent before it: an unmapped LLM operation key fails SILENTLY across every\n// consumer surface (the registry's semantic-operation map filters it out, the\n// executor never dispatches it, the capability slot never fills), whereas a new\n// `runtimeContract.kind` fails COMPILATION at every switch over the union. That\n// compile-enforcement is the whole argument, and it is verified rather than\n// asserted — deleting an arm from `secretRefForRuntimeContract` reddens the\n// `never` check with the offending contract named in the diagnostic.\n//\n// It also fills its own `EngineCapability.AI_DOCUMENT_EXTRACTION` slot, so an\n// application selects its OCR provider INDEPENDENTLY of its chat and embeddings\n// providers. Those are three unrelated procurement decisions — a deployment may\n// well want Anthropic for chat, OpenAI for embeddings, and Mistral for OCR — and\n// fusing any two of them into one `selection` entry makes that unexpressible.\n//===============================================================\n\n/**\n * Concrete document-extraction model ids the framework knows.\n *\n * Import path: `@wildo-ai/external-connectors-models`.\n */\nexport enum DocumentExtractionProvider_Model {\n /**\n * Mistral's OCR model alias. An ALIAS deliberately, not a dated snapshot: unlike an embedding\n * model — where the concrete id is persisted as a stamp on every chunk and a silent change\n * would fracture the vector space — extraction output is consumed immediately and re-derived\n * on every ingestion pass, so tracking the vendor's current model is a benefit rather than a\n * hazard.\n */\n MISTRAL_OCR_LATEST = \"mistral-ocr-latest\",\n}\n\n/**\n * The document-extraction operation vocabulary — deliberately DISJOINT from\n * `LLMProvider_OperationKey`, `ImageProvider_OperationKey` and\n * `EmbeddingsProvider_OperationKey` (each protocol kind owns its own operation enum, so a key's\n * membership decides its protocol without inspection).\n *\n * Import path: `@wildo-ai/external-connectors-models`.\n */\nexport enum DocumentExtractionProvider_OperationKey {\n /** One document's bytes → its text, page by page. */\n EXTRACT_DOCUMENT_TEXT = \"documentExtraction.extractDocumentText\",\n}\n\n/**\n * @wildo_source:part:start saas.external-providers.document-extraction.applicability facet:kind:api facet:audience:app-developer\n *\n * WHAT a document is being extracted FOR — the durable axis of extraction-model selection\n * (model-selection-by-applicability rule: an author names a CLASS, never a concrete model id;\n * the framework resolves the id from the catalog + preference below).\n *\n * One class today, and that is a statement rather than a placeholder: every extraction in the\n * engine feeds `FileTextExtractionBackendService`, and a second class would only be earned by a\n * surface with genuinely different requirements (a layout-preserving export, say, or a\n * cheap-and-approximate preview tier).\n */\nexport enum DocumentExtraction_Applicability {\n /** The default document-text surface: file text extraction, and the RAG corpus built on it. */\n DOCUMENT_TEXT_DEFAULT = \"document-text-default\",\n}\n/** @wildo_source:part:end saas.external-providers.document-extraction.applicability */\n\n/**\n * One row per document-extraction model: everything the framework knows about a concrete id.\n * Mirrors `Embeddings_ModelCatalogEntry`'s shape at the size this axis needs today.\n */\nexport type DocumentExtraction_ModelCatalogEntry = {\n /** The `ref` of the provider module that serves this id. */\n providerRef: string;\n /**\n * MIME types this model can process, as declared by the provider's documentation.\n *\n * Consulted BEFORE bytes leave the deployment: sending a document the model cannot read wastes\n * an egress of application content, which the data-minimization posture on the execution seam\n * exists to avoid.\n */\n supportedMimeTypes: readonly string[];\n /** FRAMEWORK OPINION — which applicability classes this model may be resolved for. */\n applicabilities: readonly DocumentExtraction_Applicability[];\n};\n\n/**\n * THE document-extraction model catalog — the single per-model fact table (the\n * `EMBEDDINGS_MODEL_CATALOG` discipline: an EXHAUSTIVE `Record`, so a new\n * `DocumentExtractionProvider_Model` member without a row is a compile error).\n */\nexport const DOCUMENT_EXTRACTION_MODEL_CATALOG: Record<\n DocumentExtractionProvider_Model,\n DocumentExtraction_ModelCatalogEntry\n> = {\n [DocumentExtractionProvider_Model.MISTRAL_OCR_LATEST]: {\n providerRef: \"mistral\",\n /**\n * Mistral's published OCR format list (docs.mistral.ai \"Known limitations\": \"Supported\n * formats for OCR: PDF, PNG, JPG, JPEG, TIFF, BMP, GIF, WEBP\"), narrowed to the MIME types\n * the engine's own extraction gate admits today.\n *\n * `application/pdf` is the only entry that is currently REACHABLE: image MIME types are\n * refused by `FileTextExtractionBackendService.isExtractionSupported`, which is a separate,\n * deliberate decision (an uploaded photo is not a document). The image types are declared\n * here anyway because this row states what the MODEL can do, not what the engine currently\n * asks it to do — and admitting images to extraction later must be an engine decision, not\n * an accidental consequence of a catalog edit.\n */\n supportedMimeTypes: [\"application/pdf\", \"image/png\", \"image/jpeg\", \"image/tiff\", \"image/webp\"],\n applicabilities: [DocumentExtraction_Applicability.DOCUMENT_TEXT_DEFAULT],\n },\n};\n\n/**\n * The framework's DEFAULT answer to \"which extraction model serves this class\", ordered by\n * preference, highest first.\n *\n * Unlike the embeddings preference — which is a MIGRATION KEY, because editing it re-binds a\n * class and forces every stamped chunk to be re-embedded — this one carries no durable\n * consequence: extraction output is re-derived on the next ingestion pass and nothing persists\n * the model that produced it. Editing this list changes what the next extraction uses and\n * nothing else.\n */\nexport const DOCUMENT_EXTRACTION_MODEL_APPLICABILITY_PREFERENCE: Record<\n DocumentExtraction_Applicability,\n readonly DocumentExtractionProvider_Model[]\n> = {\n [DocumentExtraction_Applicability.DOCUMENT_TEXT_DEFAULT]: [\n DocumentExtractionProvider_Model.MISTRAL_OCR_LATEST,\n ],\n};\n\n/** Why {@link resolveDocumentExtractionModelForApplicability} could not answer — carried into a named CONFIGURATION error. */\nexport enum DocumentExtraction_ModelResolutionFailure {\n /** The applicability has no candidate at all for this provider. */\n NO_CANDIDATE_FOR_PROVIDER = \"no_candidate_for_provider\",\n}\n\nexport type DocumentExtraction_ModelResolution =\n | { resolved: true; model: DocumentExtractionProvider_Model; entry: DocumentExtraction_ModelCatalogEntry }\n | {\n resolved: false;\n failure: DocumentExtraction_ModelResolutionFailure;\n consideredModels: readonly DocumentExtractionProvider_Model[];\n };\n\n/**\n * Resolve an applicability class to ONE concrete extraction model for a given provider.\n *\n * Fails CLOSED and explains itself (the `resolveModelForApplicability` contract): a silent\n * fallback to some other model would send application documents to a model nobody chose.\n */\nexport const resolveDocumentExtractionModelForApplicability = (\n input: { applicability: DocumentExtraction_Applicability; providerRef: string },\n catalog: Record<DocumentExtractionProvider_Model, DocumentExtraction_ModelCatalogEntry> = DOCUMENT_EXTRACTION_MODEL_CATALOG,\n): DocumentExtraction_ModelResolution => {\n const candidates = DOCUMENT_EXTRACTION_MODEL_APPLICABILITY_PREFERENCE[input.applicability];\n const forProvider = candidates.filter((model) => {\n const entry = catalog[model];\n return entry.providerRef === input.providerRef && entry.applicabilities.includes(input.applicability);\n });\n if (forProvider.length === 0) {\n return {\n resolved: false,\n failure: DocumentExtraction_ModelResolutionFailure.NO_CANDIDATE_FOR_PROVIDER,\n consideredModels: candidates,\n };\n }\n const model = forProvider[0]!;\n return { resolved: true, model, entry: catalog[model] };\n};\n\n// ===============================================================\n// Document Extraction Operations Context\n// ===============================================================\n\n/**\n * Usage of one extraction call.\n *\n * There is NO token dimension, and its absence is structural rather than an omission: an OCR\n * call is billed and reported per PAGE, not per token. Any consumer judging usage completeness\n * for an extraction must do so on `pagesProcessed` alone — the operation-aware discipline the\n * embeddings arm records for its own missing completion-token dimension.\n */\nexport const DocumentExtractionProvider_UsageSchema = z.object({\n /**\n * Pages the provider reports having processed.\n *\n * The FRAMEWORK's name for the dimension. Which vendor field it is projected from is the\n * provider's `parseExtractResponse` to know — the wired one reads Mistral's\n * `usage_info.pages_processed`, and a second provider will read something else.\n */\n pagesProcessed: z.number().optional(),\n /** Document size the provider reports having received. Same ownership as `pagesProcessed`. */\n documentSizeBytes: z.number().optional(),\n});\nexport type DocumentExtractionProvider_Usage = z.infer<typeof DocumentExtractionProvider_UsageSchema>;\n\nexport const DocumentExtractionProvider_ExecutionTransportMetadataSchema = z.object({\n protocolKind: z.literal(ExternalProvider_ExchangeProtocol_Kind.DOCUMENT_EXTRACTION_PROVIDER),\n providerRef: z.string(),\n model: z.string().optional(),\n});\nexport type DocumentExtractionProvider_ExecutionTransportMetadata = z.infer<\n typeof DocumentExtractionProvider_ExecutionTransportMetadataSchema\n>;\n\n// ===============================================================\n// Document Extraction I/O Schemas\n// ===============================================================\n\n/**\n * Input DESCRIPTOR of the {@link DocumentExtractionProvider_OperationKey.EXTRACT_DOCUMENT_TEXT}\n * operation — the metadata about the document, deliberately NOT the document.\n *\n * ⚠️ THE BYTES ARE ABSENT ON PURPOSE, and this is the design decision most likely to be\n * \"corrected\" by a later reader. A `documentBase64: z.string()` field here would be structurally\n * correct and operationally dangerous: a Zod-shaped input object is the thing every diagnostic\n * path in this codebase reaches for when something goes wrong — error `context`, debug logs,\n * agent-call traces — and a multi-megabyte base64 blob of an application's private contract is\n * the single worst payload to make casually loggable. The embeddings arm reached the same\n * conclusion from the other direction (its header forbids raw texts and vectors from ever\n * entering a trace); here the prohibition is enforced by the SHAPE rather than by discipline.\n *\n * The bytes travel as a `Buffer` on the execution service's own request type, which no\n * serializer walks.\n */\nexport const DocumentExtractionProvider_ExtractDocumentTextInputSchema = z.object({\n /** The document's MIME type — checked against the model's catalog row before any egress. */\n mimeType: z.string(),\n /** Byte length of the document being sent. Diagnostic and ceiling-checking only. */\n documentByteLength: z.number().int().nonnegative(),\n});\nexport type DocumentExtractionProvider_ExtractDocumentTextInput = z.infer<\n typeof DocumentExtractionProvider_ExtractDocumentTextInputSchema\n>;\n\n/**\n * Output of {@link DocumentExtractionProvider_OperationKey.EXTRACT_DOCUMENT_TEXT}.\n *\n * `text` is the concatenation of the provider's per-page output in document order. Providers in\n * this family return MARKDOWN per page (Mistral's `pages[].markdown`), which is kept as-is:\n * headings and table structure are signal for a retrieval corpus, and stripping them to \"plain\"\n * text would discard information the provider was paid to recover.\n */\nexport const DocumentExtractionProvider_ExtractDocumentTextOutputSchema = z.object({\n text: z.string(),\n /** Pages the provider actually returned — the authoritative count, not the request's estimate. */\n pageCount: z.number().int().nonnegative(),\n /** The concrete model that produced the text. */\n model: z.string(),\n usage: DocumentExtractionProvider_UsageSchema,\n});\nexport type DocumentExtractionProvider_ExtractDocumentTextOutput = z.infer<\n typeof DocumentExtractionProvider_ExtractDocumentTextOutputSchema\n>;\n\n// ===============================================================\n// The PROVIDER-OWNED WIRE SEAM\n// --------\n// Until 2026-09-09 this arm declared `baseUrl`, `endpointPath`, `apiKey` and `models` — where the\n// call goes and how it authenticates — and NOTHING about the body or the response. So the engine's\n// execution seam composed Mistral's `/v1/ocr` request (`document: { type: 'document_url',\n// document_url }`, `include_image_base64`) and read Mistral's response (`pages[].markdown`,\n// `usage_info.pages_processed`) with the vendor named nowhere, and a second provider declaring\n// DOCUMENT_EXTRACTION_PROVIDER would have been sent through Mistral's API carrying its own key.\n//\n// The remedy is the one the EMAIL and SMS arms already converged on: the provider declares PURE\n// FUNCTIONS and the engine owns transport and credentials. The types those functions are written\n// against live HERE rather than beside the contract, because the failure vocabulary is read by\n// BOTH sides — the provider produces it, the engine's caller branches on it — and a vocabulary\n// with two homes is a vocabulary that drifts.\n// ===============================================================\n\n/**\n * WHY an extraction failed, in the only two senses a caller can act on differently.\n *\n * This is the arm's most load-bearing output after the text itself, and the consequence of\n * confusing the two is CORPUS DELETION rather than a misleading log line:\n * `RagIngestionBackendService` deletes a field's entire chunk set when an ingestion pass yields no\n * text, so reporting a provider OUTAGE as an unreadable document silently destroys a live,\n * already-embedded corpus and reports success.\n *\n * It lived in `saas-backend-lib`'s execution seam until 2026-09-09, which is exactly why the wire\n * shape lived there too: a vocabulary a provider cannot reach is one a provider cannot answer in,\n * so classification had to be done by whoever could. Moving it here is what makes\n * {@link DocumentExtraction_ProviderExtraction} expressible at all.\n */\nexport enum DocumentExtraction_FailureClass {\n /**\n * The provider read the request and judged the DOCUMENT unprocessable — corrupt bytes, an\n * unsupported format, a password-protected file. PERMANENT: re-sending the same bytes cannot\n * succeed, so a sweep may safely stop retrying and skip the document.\n */\n UNREADABLE_DOCUMENT = \"unreadable_document\",\n /**\n * The provider could not be reached, refused the credential, throttled, or failed internally —\n * a network error, a 401/403, a 429, any 5xx, or a timeout. TRANSIENT and, decisively, says\n * NOTHING about the document. A caller must not conclude anything about the bytes from this.\n */\n PROVIDER_UNAVAILABLE = \"provider_unavailable\",\n}\n\n/**\n * What a provider's `parseExtractResponse` returns, and what a COMPLETE poll carries (#2020): the extraction, or a\n * CLASSIFIED refusal.\n *\n * A discriminated union rather than \"return the output or throw\", for the reason the failure class\n * exists: a thrown `Error` carries no class, and the engine would have to guess one — which is the\n * guess that deletes a corpus. A provider that cannot classify a response must still say which of\n * the two it is, and the arm's JSDoc tells it to prefer `PROVIDER_UNAVAILABLE` when unsure,\n * because that is the answer with no destructive consequence.\n */\nexport type DocumentExtraction_ProviderExtraction =\n | {\n extracted: true;\n /** Per-page text joined in document order. Markdown is kept as-is; see the output schema. */\n text: string;\n /** Pages the provider actually returned — the authoritative count, not the request estimate. */\n pageCount: number;\n /** The model the provider says produced the text. Absent means \"the resolved model\". */\n model?: string;\n usage?: DocumentExtractionProvider_Usage;\n }\n | {\n extracted: false;\n failureClass: DocumentExtraction_FailureClass;\n /**\n * Operator-facing reason. MUST NOT contain the provider's response body or any part of the\n * document: this message reaches logs, and a provider error body can echo request content.\n */\n message: string;\n };\n\n/**\n * HOW a document-extraction provider exchanges with its vendor (#2020) — the discriminator of the runtime arm's\n * `exchange`.\n *\n * Two shapes exist in the field and they cannot be folded into one:\n * - SINGLE_REQUEST: one request carries the document and the answer carries the text (Mistral OCR).\n * - SUBMIT_AND_POLL: the vendor accepts the document, answers with a job, and the text is fetched later by polling\n * that job until it is done (Azure Document Intelligence's `Operation-Location`, VLM Run). Asynchronous Textract is\n * a job-based vendor this form does NOT serve (SigV4, S3 input, POST polls); see the private exchange type.\n * Folding this into one request is what #2001 showed failing: the first request answers a job id, not text.\n *\n * A closed vocabulary with one home, so the engine's switch over it is exhaustive: a new form, or a deleted one, is a\n * compile error at the one place that executes the exchange.\n */\nexport enum DocumentExtractionExchangeForm {\n SINGLE_REQUEST = \"single-request\",\n SUBMIT_AND_POLL = \"submit-and-poll\",\n}\n\n/**\n * What a SUBMIT_AND_POLL provider's `parseSubmitResponse` returns: the vendor's job id, or a CLASSIFIED refusal. The\n * refusal carries the same two classes as an extraction, for the same reason: a vendor refusing THIS document at\n * submission is permanent, an outage is not, and confusing them deletes a corpus.\n */\nexport type DocumentExtraction_JobSubmission =\n | {\n submitted: true;\n /** The vendor's identifier for the job. Opaque to the engine; handed back to `buildPollRequest`. */\n jobId: string;\n }\n | {\n submitted: false;\n failureClass: DocumentExtraction_FailureClass;\n /** Operator-facing; MUST NOT contain the response body or the document (see the extraction's `message`). */\n message: string;\n };\n\n/** Where a polled job stands. PENDING keeps the engine polling until the provider's deadline. */\nexport enum DocumentExtraction_JobState {\n PENDING = \"pending\",\n COMPLETE = \"complete\",\n}\n\n/**\n * What a SUBMIT_AND_POLL provider's `parsePollResponse` returns for one poll: still running, or done — with the\n * extraction or its classified refusal, exactly what a single-request parser returns.\n *\n * COMPLETE means the VENDOR says the job has ended. A job the vendor reports failed is COMPLETE with a refusal, and\n * only then may the engine submit the document again, because only then is nothing still running. A poll the vendor\n * answered with a transient error (a 5xx or 429 on the poll route) says nothing about the job, so it is PENDING: the\n * engine polls again until the deadline. Reading it as COMPLETE would stop the engine while the job may still run,\n * and a retry would then pay the vendor twice for one document.\n */\nexport type DocumentExtraction_JobPoll =\n | { state: DocumentExtraction_JobState.PENDING }\n | { state: DocumentExtraction_JobState.COMPLETE; extraction: DocumentExtraction_ProviderExtraction };\n\n/**\n * The framework's DEFAULT reading of an extraction response's HTTP status.\n *\n * Offered to every provider's `parseExtractResponse` rather than applied by the engine, because\n * only the provider knows whether its vendor also signals a per-document verdict inside a 2xx\n * body (Twilio does exactly that on the SMS arm). What it prevents is each provider re-deriving a\n * classification whose worst case is corpus deletion.\n *\n * Every boundary is deliberate:\n * - 4xx generally means the provider READ the request and refused THIS DOCUMENT → permanent.\n * - 401/403 is a CREDENTIAL fault, not a document fault. Classifying it as unreadable would make\n * a rotated key look like a corpus of corrupt files and delete chunk sets across every\n * document for as long as the key was wrong.\n * - 408/429 are explicitly retryable by their own definition.\n * - 5xx is the provider's fault, never the document's.\n */\nexport const classifyDocumentExtractionHttpStatus = (status: number): DocumentExtraction_FailureClass => {\n const isCredentialFault = status === 401 || status === 403;\n const isThrottleOrTimeout = status === 408 || status === 429;\n const isServerFault = status >= 500;\n return isCredentialFault || isThrottleOrTimeout || isServerFault\n ? DocumentExtraction_FailureClass.PROVIDER_UNAVAILABLE\n : DocumentExtraction_FailureClass.UNREADABLE_DOCUMENT;\n};\n\n"]}
|
|
1
|
+
{"version":3,"file":"document-extraction.external-connectors-models.schemas.js","sourceRoot":"","sources":["../../../../src/protocols/document-extraction.external-connectors-models.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\"\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n } from \"../core/commons.external-connectors-models.schemas\"\n\n//===============================================================\n// Document Extraction Provider\n// --------\n// Document bytes → text. Serves the file-side TEXT PROVIDER that\n// `FileTextExtractionBackendService` owns, whose largest consumer is the RAG\n// ingestion path (`.ragSource()` corpus building).\n//\n// ## Why this is a provider at all, and not just a better library\n//\n// The local `pdfjs-dist` path reads a PDF's TEXT LAYER. A scanned document — the\n// common case for uploaded contracts, invoices and forms — is an IMAGE of a page\n// and carries no text layer, so it extracts to the empty string, contributes no\n// chunks, and becomes silently unanswerable. That is not a defect in the local\n// library; it is its nature, and it is the entire reason a provider exists here.\n//\n// ## Deliberately a SEPARATE protocol kind from `LLM_PROVIDER`\n//\n// Same reasoning as `EMBEDDINGS_PROVIDER` (RAG plan DL2) and the `IMAGE_PROVIDER`\n// precedent before it: an unmapped LLM operation key fails SILENTLY across every\n// consumer surface (the registry's semantic-operation map filters it out, the\n// executor never dispatches it, the capability slot never fills), whereas a new\n// `runtimeContract.kind` fails COMPILATION at every switch over the union. That\n// compile-enforcement is the whole argument, and it is verified rather than\n// asserted — deleting an arm from `secretRefForRuntimeContract` reddens the\n// `never` check with the offending contract named in the diagnostic.\n//\n// It also fills its own `EngineCapability.AI_DOCUMENT_EXTRACTION` slot, so an\n// application selects its OCR provider INDEPENDENTLY of its chat and embeddings\n// providers. Those are three unrelated procurement decisions — a deployment may\n// well want Anthropic for chat, OpenAI for embeddings, and Mistral for OCR — and\n// fusing any two of them into one `selection` entry makes that unexpressible.\n//===============================================================\n\n/**\n * Concrete document-extraction model ids the framework knows.\n *\n * Import path: `@wildo-ai/external-connectors-models`.\n */\nexport enum DocumentExtractionProvider_Model {\n /**\n * Mistral's OCR model alias. An ALIAS deliberately, not a dated snapshot: unlike an embedding\n * model — where the concrete id is persisted as a stamp on every chunk and a silent change\n * would fracture the vector space — extraction output is consumed immediately and re-derived\n * on every ingestion pass, so tracking the vendor's current model is a benefit rather than a\n * hazard.\n */\n MISTRAL_OCR_LATEST = \"mistral-ocr-latest\",\n}\n\n/**\n * The document-extraction operation vocabulary — deliberately DISJOINT from\n * `LLMProvider_OperationKey`, `ImageProvider_OperationKey` and\n * `EmbeddingsProvider_OperationKey` (each protocol kind owns its own operation enum, so a key's\n * membership decides its protocol without inspection).\n *\n * Import path: `@wildo-ai/external-connectors-models`.\n */\nexport enum DocumentExtractionProvider_OperationKey {\n /** One document's bytes → its text, page by page. */\n EXTRACT_DOCUMENT_TEXT = \"documentExtraction.extractDocumentText\",\n}\n\n/**\n * @wildo_source:part:start saas.external-providers.document-extraction.applicability facet:kind:api facet:audience:app-developer\n *\n * WHAT a document is being extracted FOR — the durable axis of extraction-model selection\n * (model-selection-by-applicability rule: an author names a CLASS, never a concrete model id;\n * the framework resolves the id from the catalog + preference below).\n *\n * One class today, and that is a statement rather than a placeholder: every extraction in the\n * engine feeds `FileTextExtractionBackendService`, and a second class would only be earned by a\n * surface with genuinely different requirements (a layout-preserving export, say, or a\n * cheap-and-approximate preview tier).\n */\nexport enum DocumentExtraction_Applicability {\n /** The default document-text surface: file text extraction, and the RAG corpus built on it. */\n DOCUMENT_TEXT_DEFAULT = \"document-text-default\",\n}\n/** @wildo_source:part:end saas.external-providers.document-extraction.applicability */\n\n/**\n * One row per document-extraction model: everything the framework knows about a concrete id.\n * Mirrors `Embeddings_ModelCatalogEntry`'s shape at the size this axis needs today.\n */\nexport type DocumentExtraction_ModelCatalogEntry = {\n /** The `ref` of the provider module that serves this id. */\n providerRef: string;\n /**\n * MIME types this model can process, as declared by the provider's documentation.\n *\n * Consulted BEFORE bytes leave the deployment: sending a document the model cannot read wastes\n * an egress of application content, which the data-minimization posture on the execution seam\n * exists to avoid.\n */\n supportedMimeTypes: readonly string[];\n /** FRAMEWORK OPINION — which applicability classes this model may be resolved for. */\n applicabilities: readonly DocumentExtraction_Applicability[];\n};\n\n/**\n * THE document-extraction model catalog — the single per-model fact table (the\n * `EMBEDDINGS_MODEL_CATALOG` discipline: an EXHAUSTIVE `Record`, so a new\n * `DocumentExtractionProvider_Model` member without a row is a compile error).\n */\nexport const DOCUMENT_EXTRACTION_MODEL_CATALOG: Record<\n DocumentExtractionProvider_Model,\n DocumentExtraction_ModelCatalogEntry\n> = {\n [DocumentExtractionProvider_Model.MISTRAL_OCR_LATEST]: {\n providerRef: \"mistral\",\n /**\n * Mistral's published OCR format list (docs.mistral.ai \"Known limitations\": \"Supported\n * formats for OCR: PDF, PNG, JPG, JPEG, TIFF, BMP, GIF, WEBP\"), narrowed to the MIME types\n * the engine's own extraction gate admits today.\n *\n * `application/pdf` is the only entry that is currently REACHABLE: image MIME types are\n * refused by `FileTextExtractionBackendService.isExtractionSupported`, which is a separate,\n * deliberate decision (an uploaded photo is not a document). The image types are declared\n * here anyway because this row states what the MODEL can do, not what the engine currently\n * asks it to do — and admitting images to extraction later must be an engine decision, not\n * an accidental consequence of a catalog edit.\n */\n supportedMimeTypes: [\"application/pdf\", \"image/png\", \"image/jpeg\", \"image/tiff\", \"image/webp\"],\n applicabilities: [DocumentExtraction_Applicability.DOCUMENT_TEXT_DEFAULT],\n },\n};\n\n/**\n * The framework's DEFAULT answer to \"which extraction model serves this class\", ordered by\n * preference, highest first.\n *\n * Unlike the embeddings preference — which is a MIGRATION KEY, because editing it re-binds a\n * class and forces every stamped chunk to be re-embedded — this one carries no durable\n * consequence: extraction output is re-derived on the next ingestion pass and nothing persists\n * the model that produced it. Editing this list changes what the next extraction uses and\n * nothing else.\n */\nexport const DOCUMENT_EXTRACTION_MODEL_APPLICABILITY_PREFERENCE: Record<\n DocumentExtraction_Applicability,\n readonly DocumentExtractionProvider_Model[]\n> = {\n [DocumentExtraction_Applicability.DOCUMENT_TEXT_DEFAULT]: [\n DocumentExtractionProvider_Model.MISTRAL_OCR_LATEST,\n ],\n};\n\n/** Why {@link resolveDocumentExtractionModelForApplicability} could not answer — carried into a named CONFIGURATION error. */\nexport enum DocumentExtraction_ModelResolutionFailure {\n /** The applicability has no candidate at all for this provider. */\n NO_CANDIDATE_FOR_PROVIDER = \"no_candidate_for_provider\",\n}\n\nexport type DocumentExtraction_ModelResolution =\n | { resolved: true; model: DocumentExtractionProvider_Model; entry: DocumentExtraction_ModelCatalogEntry }\n | {\n resolved: false;\n failure: DocumentExtraction_ModelResolutionFailure;\n consideredModels: readonly DocumentExtractionProvider_Model[];\n };\n\n/**\n * Resolve an applicability class to ONE concrete extraction model for a given provider.\n *\n * Fails CLOSED and explains itself (the `resolveModelForApplicability` contract): a silent\n * fallback to some other model would send application documents to a model nobody chose.\n */\nexport const resolveDocumentExtractionModelForApplicability = (\n input: { applicability: DocumentExtraction_Applicability; providerRef: string },\n catalog: Record<DocumentExtractionProvider_Model, DocumentExtraction_ModelCatalogEntry> = DOCUMENT_EXTRACTION_MODEL_CATALOG,\n): DocumentExtraction_ModelResolution => {\n const candidates = DOCUMENT_EXTRACTION_MODEL_APPLICABILITY_PREFERENCE[input.applicability];\n const forProvider = candidates.filter((model) => {\n const entry = catalog[model];\n return entry.providerRef === input.providerRef && entry.applicabilities.includes(input.applicability);\n });\n if (forProvider.length === 0) {\n return {\n resolved: false,\n failure: DocumentExtraction_ModelResolutionFailure.NO_CANDIDATE_FOR_PROVIDER,\n consideredModels: candidates,\n };\n }\n const model = forProvider[0]!;\n return { resolved: true, model, entry: catalog[model] };\n};\n\n// ===============================================================\n// Document Extraction Operations Context\n// ===============================================================\n\n/**\n * Usage of one extraction call.\n *\n * There is NO token dimension, and its absence is structural rather than an omission: an OCR\n * call is billed and reported per PAGE, not per token. Any consumer judging usage completeness\n * for an extraction must do so on `pagesProcessed` alone — the operation-aware discipline the\n * embeddings arm records for its own missing completion-token dimension.\n */\nexport const DocumentExtractionProvider_UsageSchema = z.object({\n /**\n * Pages the provider reports having processed.\n *\n * The FRAMEWORK's name for the dimension. Which vendor field it is projected from is the\n * provider's `parseExtractResponse` to know — the wired one reads Mistral's\n * `usage_info.pages_processed`, and a second provider will read something else.\n */\n pagesProcessed: z.number().optional(),\n /** Document size the provider reports having received. Same ownership as `pagesProcessed`. */\n documentSizeBytes: z.number().optional(),\n});\nexport type DocumentExtractionProvider_Usage = z.infer<typeof DocumentExtractionProvider_UsageSchema>;\n\nexport const DocumentExtractionProvider_ExecutionTransportMetadataSchema = z.object({\n protocolKind: z.literal(ExternalProvider_ExchangeProtocol_Kind.DOCUMENT_EXTRACTION_PROVIDER),\n providerRef: z.string(),\n model: z.string().optional(),\n});\nexport type DocumentExtractionProvider_ExecutionTransportMetadata = z.infer<\n typeof DocumentExtractionProvider_ExecutionTransportMetadataSchema\n>;\n\n// ===============================================================\n// Document Extraction I/O Schemas\n// ===============================================================\n\n/**\n * Input DESCRIPTOR of the {@link DocumentExtractionProvider_OperationKey.EXTRACT_DOCUMENT_TEXT}\n * operation — the metadata about the document, deliberately NOT the document.\n *\n * ⚠️ THE BYTES ARE ABSENT ON PURPOSE, and this is the design decision most likely to be\n * \"corrected\" by a later reader. A `documentBase64: z.string()` field here would be structurally\n * correct and operationally dangerous: a Zod-shaped input object is the thing every diagnostic\n * path in this codebase reaches for when something goes wrong — error `context`, debug logs,\n * agent-call traces — and a multi-megabyte base64 blob of an application's private contract is\n * the single worst payload to make casually loggable. The embeddings arm reached the same\n * conclusion from the other direction (its header forbids raw texts and vectors from ever\n * entering a trace); here the prohibition is enforced by the SHAPE rather than by discipline.\n *\n * The bytes travel as a `Buffer` on the execution service's own request type, which no\n * serializer walks.\n */\nexport const DocumentExtractionProvider_ExtractDocumentTextInputSchema = z.object({\n /** The document's MIME type — checked against the model's catalog row before any egress. */\n mimeType: z.string(),\n /** Byte length of the document being sent. Diagnostic and ceiling-checking only. */\n documentByteLength: z.number().int().nonnegative(),\n});\nexport type DocumentExtractionProvider_ExtractDocumentTextInput = z.infer<\n typeof DocumentExtractionProvider_ExtractDocumentTextInputSchema\n>;\n\n/**\n * Output of {@link DocumentExtractionProvider_OperationKey.EXTRACT_DOCUMENT_TEXT}.\n *\n * `text` is the concatenation of the provider's per-page output in document order. Providers in\n * this family return MARKDOWN per page (Mistral's `pages[].markdown`), which is kept as-is:\n * headings and table structure are signal for a retrieval corpus, and stripping them to \"plain\"\n * text would discard information the provider was paid to recover.\n */\nexport const DocumentExtractionProvider_ExtractDocumentTextOutputSchema = z.object({\n text: z.string(),\n /** Pages the provider actually returned — the authoritative count, not the request's estimate. */\n pageCount: z.number().int().nonnegative(),\n /** The concrete model that produced the text. */\n model: z.string(),\n usage: DocumentExtractionProvider_UsageSchema,\n});\nexport type DocumentExtractionProvider_ExtractDocumentTextOutput = z.infer<\n typeof DocumentExtractionProvider_ExtractDocumentTextOutputSchema\n>;\n\n// ===============================================================\n// The PROVIDER-OWNED WIRE SEAM\n// --------\n// Until 2026-09-09 this arm declared `baseUrl`, `endpointPath`, `apiKey` and `models` — where the\n// call goes and how it authenticates — and NOTHING about the body or the response. So the engine's\n// execution seam composed Mistral's `/v1/ocr` request (`document: { type: 'document_url',\n// document_url }`, `include_image_base64`) and read Mistral's response (`pages[].markdown`,\n// `usage_info.pages_processed`) with the vendor named nowhere, and a second provider declaring\n// DOCUMENT_EXTRACTION_PROVIDER would have been sent through Mistral's API carrying its own key.\n//\n// The remedy is the one the EMAIL and SMS arms already converged on: the provider declares PURE\n// FUNCTIONS and the engine owns transport and credentials. The types those functions are written\n// against live HERE rather than beside the contract, because the failure vocabulary is read by\n// BOTH sides — the provider produces it, the engine's caller branches on it — and a vocabulary\n// with two homes is a vocabulary that drifts.\n// ===============================================================\n\n/**\n * WHY an extraction failed, in the only two senses a caller can act on differently.\n *\n * This is the arm's most load-bearing output after the text itself, and the consequence of\n * confusing the two is CORPUS DELETION rather than a misleading log line:\n * `RagIngestionBackendService` deletes a field's entire chunk set when an ingestion pass yields no\n * text, so reporting a provider OUTAGE as an unreadable document silently destroys a live,\n * already-embedded corpus and reports success.\n *\n * It lived in `saas-backend-lib`'s execution seam until 2026-09-09, which is exactly why the wire\n * shape lived there too: a vocabulary a provider cannot reach is one a provider cannot answer in,\n * so classification had to be done by whoever could. Moving it here is what makes\n * {@link DocumentExtraction_ProviderExtraction} expressible at all.\n */\nexport enum DocumentExtraction_FailureClass {\n /**\n * The provider read the request and judged the DOCUMENT unprocessable — corrupt bytes, an\n * unsupported format, a password-protected file. PERMANENT: re-sending the same bytes cannot\n * succeed, so a sweep may safely stop retrying and skip the document.\n */\n UNREADABLE_DOCUMENT = \"unreadable_document\",\n /**\n * The provider could not be reached, refused the credential, throttled, or failed internally —\n * a network error, a 401/403, a 429, any 5xx, or a timeout. TRANSIENT and, decisively, says\n * NOTHING about the document. A caller must not conclude anything about the bytes from this.\n */\n PROVIDER_UNAVAILABLE = \"provider_unavailable\",\n}\n\n/**\n * What a provider's `parseExtractResponse` returns, and what a COMPLETE poll carries (#2020): the extraction, or a\n * CLASSIFIED refusal.\n *\n * A discriminated union rather than \"return the output or throw\", for the reason the failure class\n * exists: a thrown `Error` carries no class, and the engine would have to guess one — which is the\n * guess that deletes a corpus. A provider that cannot classify a response must still say which of\n * the two it is, and the arm's JSDoc tells it to prefer `PROVIDER_UNAVAILABLE` when unsure,\n * because that is the answer with no destructive consequence.\n */\nexport type DocumentExtraction_ProviderExtraction =\n | {\n extracted: true;\n /** Per-page text joined in document order. Markdown is kept as-is; see the output schema. */\n text: string;\n /** Pages the provider actually returned — the authoritative count, not the request estimate. */\n pageCount: number;\n /** The model the provider says produced the text. Absent means \"the resolved model\". */\n model?: string;\n usage?: DocumentExtractionProvider_Usage;\n }\n | {\n extracted: false;\n failureClass: DocumentExtraction_FailureClass;\n /**\n * Operator-facing reason. MUST NOT contain the provider's response body or any part of the\n * document: this message reaches logs, and a provider error body can echo request content.\n */\n message: string;\n };\n\n/**\n * HOW a document-extraction provider exchanges with its vendor (#2020) — the discriminator of the runtime arm's\n * `exchange`.\n *\n * Two shapes exist in the field and they cannot be folded into one:\n * - SINGLE_REQUEST: one request carries the document and the answer carries the text (Mistral OCR).\n * - SUBMIT_AND_POLL: the vendor accepts the document, answers with a job, and the text is fetched later by polling\n * that job until it is done (Azure Document Intelligence's `Operation-Location`, VLM Run). Asynchronous Textract is\n * a job-based vendor this form does NOT serve (SigV4, S3 input, POST polls); see the private exchange type.\n * Folding this into one request is what #2001 showed failing: the first request answers a job id, not text.\n *\n * A closed vocabulary with one home, so the engine's switch over it is exhaustive: a new form, or a deleted one, is a\n * compile error at the one place that executes the exchange.\n */\nexport enum DocumentExtractionExchangeForm {\n SINGLE_REQUEST = \"single-request\",\n SUBMIT_AND_POLL = \"submit-and-poll\",\n}\n\n/**\n * What a SUBMIT_AND_POLL provider's `parseSubmitResponse` returns: the vendor's job id, or a CLASSIFIED refusal. The\n * refusal carries the same two classes as an extraction, for the same reason: a vendor refusing THIS document at\n * submission is permanent, an outage is not, and confusing them deletes a corpus.\n */\nexport type DocumentExtraction_JobSubmission =\n | {\n submitted: true;\n /** The vendor's identifier for the job. Opaque to the engine; handed back to `buildPollRequest`. */\n jobId: string;\n }\n | {\n submitted: false;\n failureClass: DocumentExtraction_FailureClass;\n /** Operator-facing; MUST NOT contain the response body or the document (see the extraction's `message`). */\n message: string;\n };\n\n/** Where a polled job stands. PENDING keeps the engine polling until the provider's deadline. */\nexport enum DocumentExtraction_JobState {\n PENDING = \"pending\",\n COMPLETE = \"complete\",\n}\n\n/**\n * What a SUBMIT_AND_POLL provider's `parsePollResponse` returns for one poll: still running, or done — with the\n * extraction or its classified refusal, exactly what a single-request parser returns.\n *\n * COMPLETE means the VENDOR says the job has ended. A job the vendor reports failed is COMPLETE with a refusal, and\n * only then may the engine submit the document again, because only then is nothing still running. A poll the vendor\n * answered with a transient error (a 5xx or 429 on the poll route) says nothing about the job, so it is PENDING: the\n * engine polls again until the deadline. Reading it as COMPLETE would stop the engine while the job may still run,\n * and a retry would then pay the vendor twice for one document.\n */\nexport type DocumentExtraction_JobPoll =\n | { state: DocumentExtraction_JobState.PENDING }\n | { state: DocumentExtraction_JobState.COMPLETE; extraction: DocumentExtraction_ProviderExtraction };\n\n/**\n * The framework's DEFAULT reading of an extraction response's HTTP status.\n *\n * Offered to every provider's `parseExtractResponse` rather than applied by the engine, because\n * only the provider knows whether its vendor also signals a per-document verdict inside a 2xx\n * body (Twilio does exactly that on the SMS arm). What it prevents is each provider re-deriving a\n * classification whose worst case is corpus deletion.\n *\n * Every boundary is deliberate:\n * - 4xx generally means the provider READ the request and refused THIS DOCUMENT → permanent.\n * - 401/403 is a CREDENTIAL fault, not a document fault. Classifying it as unreadable would make\n * a rotated key look like a corpus of corrupt files and delete chunk sets across every\n * document for as long as the key was wrong.\n * - 408/429 are explicitly retryable by their own definition.\n * - 5xx is the provider's fault, never the document's.\n */\nexport const classifyDocumentExtractionHttpStatus = (status: number): DocumentExtraction_FailureClass => {\n const isCredentialFault = status === 401 || status === 403;\n const isThrottleOrTimeout = status === 408 || status === 429;\n const isServerFault = status >= 500;\n return isCredentialFault || isThrottleOrTimeout || isServerFault\n ? DocumentExtraction_FailureClass.PROVIDER_UNAVAILABLE\n : DocumentExtraction_FailureClass.UNREADABLE_DOCUMENT;\n};\n\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-inbound.standard-interface.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"email-inbound.standard-interface.schemas.d.ts","sourceRoot":"","sources":["../../../../src/protocols/email-inbound.standard-interface.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB;;;;;;;;;;;GAWG;AACH,oBAAY,0BAA0B;IACpC,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,SAAS,cAAc;CACxB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,yCAAyC;;;;;iBAKpD,CAAC;AAEH,MAAM,MAAM,mCAAmC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yCAAyC,CAAC,CAAC;AAE5G,eAAO,MAAM,kCAAkC;;;iBAG7C,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F,iIAAiI;AACjI,oBAAY,0BAA0B;IACpC,UAAU,eAAe;IACzB,MAAM,WAAW;CAClB;AAED,kHAAkH;AAClH,eAAO,MAAM,qCAAqC;;;;;;;iBAShD,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AAEpG;;;GAGG;AACH,eAAO,MAAM,uCAAuC;;;;iBAMlD,CAAC;AAEH,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uCAAuC,CAAC,CAAC;AAExG;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwB7C,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F,mCAAmC;AACnC,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,4EAA4E;AAC5E,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAMD,+HAA+H;AAC/H,oBAAY,yBAAyB;IACnC,2HAA2H;IAC3H,OAAO,YAAY;IACnB,kDAAkD;IAClD,QAAQ,aAAa;IACrB,kDAAkD;IAClD,MAAM,WAAW;CAClB;AAED,wDAAwD;AACxD,eAAO,MAAM,mCAAmC;;;;;;;iBAQ9C,CAAC;AAEH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG,6CAA6C;AAC7C,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBAOpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,YAAY,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACrI,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACzE,wDAAwD;IACxD,YAAY,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,YAAY,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC7C,qHAAqH;IACrH,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,iCAAiC,CAAC;IACpE,0DAA0D;IAC1D,YAAY,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC/E,qEAAqE;IACrE,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qCAAqC,CAAC,CAAC;IAC5E,mEAAmE;IACnE,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;CAClE;AAMD;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,GACnC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,uBAAuB,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,GACtJ;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAElF;;;GAGG;AACH,oBAAY,uBAAuB;IACjC,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,KAAK,UAAU;IACf,MAAM,WAAW;CAClB;AAED,iFAAiF;AACjF,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-inbound.standard-interface.schemas.js","sourceRoot":"","sources":["../../../src/protocols/email-inbound.standard-interface.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\n// ===============================================================\n// Standard Inbound Email Interface (#1630)\n// --------\n// The canonical shape of a message an EMAIL_INBOUND provider RECEIVED for the application, and the\n// three calls the engine makes on the provider to get it. Provider-agnostic: a vendor's module maps\n// its own notification and message payloads onto these schemas, and nothing past that mapping ever\n// sees a vendor field.\n//\n// There is deliberately NO `verify` here. The notification reaches the application through the\n// provider's `WEBHOOK_ORIGINATOR` endpoint (the `inbound-email` key, capability `EMAIL_INBOUND`), and\n// that endpoint is verified by the ENGINE-owned scheme its `signatureConfig` names (#1596). A\n// provider that verified its own notifications would put the one fail-closed decision of the inbound\n// path in vendor code, where nothing checks it.\n// ===============================================================\n\n/**\n * One authentication method's result, as a receiving server records it in `Authentication-Results`.\n *\n * The union of the results the three methods define, so one vocabulary serves SPF, DKIM and DMARC.\n * Two members go beyond what a DMARC result can be — `SOFTFAIL` (SPF only) and `POLICY` (DKIM and\n * SPF) — and are here because mapping them onto a neighbour would record a result the receiver did\n * not report: a softfail is neither a fail nor neutral.\n *\n * spec-cite: RFC 8601 §2.7.1 (DKIM results: none, pass, fail, policy, neutral, temperror, permerror)\n * and §2.7.2 (SPF results: none, pass, fail, softfail, neutral, temperror, permerror, plus policy\n * from §2.4); DMARC results per RFC 7489 §11.2 (none, pass, fail, temperror, permerror). Fetched 2026-09-27.\n */\nexport enum EmailAuthenticationVerdict {\n PASS = \"pass\",\n FAIL = \"fail\",\n SOFTFAIL = \"softfail\",\n NEUTRAL = \"neutral\",\n NONE = \"none\",\n POLICY = \"policy\",\n TEMPERROR = \"temperror\",\n PERMERROR = \"permerror\",\n}\n\n/**\n * What the receiving provider concluded about a message's origin.\n *\n * `dmarcAligned` is kept beside the DMARC verdict rather than folded into it because it is the fact\n * sender assurance is built on: DMARC authenticates the `From` DOMAIN by requiring that it align with\n * an identifier SPF or DKIM authenticated. A provider that reports DMARC `pass` has already required\n * alignment, so for most vendors `dmarcAligned` equals `dmarc === PASS`; it is a separate field so a\n * vendor that reports the two independently is not forced to invent one from the other.\n */\nexport const StandardInboundEmail_AuthenticationSchema = z.object({\n spf: z.enum(EmailAuthenticationVerdict),\n dkim: z.enum(EmailAuthenticationVerdict),\n dmarc: z.enum(EmailAuthenticationVerdict),\n dmarcAligned: z.boolean(),\n});\n\nexport type StandardInboundEmail_Authentication = z.infer<typeof StandardInboundEmail_AuthenticationSchema>;\n\nexport const StandardInboundEmail_AddressSchema = z.object({\n address: z.string().min(1),\n name: z.string().optional(),\n});\n\nexport type StandardInboundEmail_Address = z.infer<typeof StandardInboundEmail_AddressSchema>;\n\n/** How a MIME part asks to be presented (`Content-Disposition`). spec-cite: RFC 2183 §2.1 (`inline`) and §2.2 (`attachment`). */\nexport enum EmailAttachmentDisposition {\n ATTACHMENT = \"attachment\",\n INLINE = \"inline\",\n}\n\n/** One attachment as the provider describes it. The bytes are fetched through `openAttachment`, never inlined. */\nexport const StandardInboundEmail_AttachmentSchema = z.object({\n /** Opaque to the engine; handed back to `openAttachment`. */\n ref: z.string().min(1),\n filename: z.string(),\n contentType: z.string(),\n sizeBytes: z.number().int().nonnegative(),\n /** The `Content-ID` of an inline part, without angle brackets. */\n contentId: z.string().optional(),\n disposition: z.enum(EmailAttachmentDisposition).optional(),\n});\n\nexport type StandardInboundEmail_Attachment = z.infer<typeof StandardInboundEmail_AttachmentSchema>;\n\n/**\n * What a provider's notification says, parsed. Small on purpose: a notification tells the engine\n * THAT a message arrived and where to fetch it, and nothing past this point trusts it for more.\n */\nexport const StandardInboundEmail_NotificationSchema = z.object({\n /** The provider's id for the message — what `fetchMessage` takes, and the dedup key of the channel delivery. */\n providerMessageId: z.string().min(1),\n /** The addresses the message was delivered FOR (the SMTP envelope recipients), which routing reads. */\n receivedFor: z.array(z.string().min(1)).min(1),\n receivedAt: z.coerce.date(),\n});\n\nexport type StandardInboundEmail_Notification = z.infer<typeof StandardInboundEmail_NotificationSchema>;\n\n/**\n * One received message, provider-neutral.\n *\n * The threading headers are separated out because the engine correlates threads from them;\n * `headers` carries the rest, for a channel record that chooses to keep an allow-listed subset.\n */\nexport const StandardInboundEmail_MessageSchema = z.object({\n providerMessageId: z.string().min(1),\n /** The RFC 5322 `Message-ID`, angle brackets included, or absent when the sender set none. */\n messageId: z.string().optional(),\n inReplyTo: z.string().optional(),\n references: z.array(z.string()).default([]),\n from: StandardInboundEmail_AddressSchema,\n to: z.array(StandardInboundEmail_AddressSchema).default([]),\n cc: z.array(StandardInboundEmail_AddressSchema).default([]),\n replyTo: StandardInboundEmail_AddressSchema.optional(),\n receivedFor: z.array(z.string().min(1)).min(1),\n subject: z.string().default(\"\"),\n textBody: z.string().optional(),\n htmlBody: z.string().optional(),\n headers: z.record(z.string(), z.string()).default({}),\n authentication: StandardInboundEmail_AuthenticationSchema,\n attachments: z.array(StandardInboundEmail_AttachmentSchema).default([]),\n sizeBytes: z.number().int().nonnegative().optional(),\n receivedAt: z.coerce.date(),\n /**\n * Where the ORIGINAL message bytes are, when the provider keeps them (#1600). Opaque to the engine; handed\n * to `openRaw`. Absent when the provider offers no raw copy — the engine then keeps no raw MIME.\n */\n rawRef: z.string().min(1).optional(),\n});\n\nexport type StandardInboundEmail_Message = z.infer<typeof StandardInboundEmail_MessageSchema>;\n\n/** The bytes of one attachment. */\nexport interface StandardInboundEmail_OpenedAttachment {\n readonly bytes: Uint8Array;\n readonly contentType: string;\n readonly filename: string;\n}\n\n/** The original bytes of a message, exactly as the provider serves them. */\nexport interface StandardInboundEmail_OpenedRaw {\n readonly bytes: Uint8Array;\n}\n\n// ===============================================================\n// Receiving domains (#1600)\n// ===============================================================\n\n/** Where a domain stands AT THE PROVIDER — distinct from the organization's own status, which also records ownership proof. */\nexport enum EmailProviderDomainStatus {\n /** The provider has not verified the domain's records yet (not started, pending, or a temporary failure it will retry). */\n PENDING = \"pending\",\n /** The provider verified the domain's records. */\n VERIFIED = \"verified\",\n /** The provider gave up verifying the records. */\n FAILED = \"failed\",\n}\n\n/** One DNS record the provider asks to be published. */\nexport const StandardEmailDomain_DnsRecordSchema = z.object({\n /** What it is for, as the provider names it (DKIM, SPF, MX, Receiving…). */\n purpose: z.string(),\n type: z.string(),\n name: z.string(),\n value: z.string(),\n priority: z.number().int().optional(),\n status: z.string().optional(),\n});\n\nexport type StandardEmailDomain_DnsRecord = z.infer<typeof StandardEmailDomain_DnsRecordSchema>;\n\n/** A domain as the provider describes it. */\nexport const StandardEmailDomainSchema = z.object({\n providerDomainId: z.string().min(1),\n name: z.string().min(1),\n status: z.enum(EmailProviderDomainStatus),\n sending: z.boolean(),\n receiving: z.boolean(),\n records: z.array(StandardEmailDomain_DnsRecordSchema).default([]),\n});\n\nexport type StandardEmailDomain = z.infer<typeof StandardEmailDomainSchema>;\n\n/**\n * What an EMAIL_INBOUND provider implements to host an organization's own domain. Every tenant shares one\n * provider account, so the ENGINE proves the organization owns the domain before it ever calls `createDomain`.\n */\nexport interface StandardEmailDomains_Interface {\n createDomain(input: { readonly name: string; readonly sending: boolean; readonly receiving: boolean }): Promise<StandardEmailDomain>;\n getDomain(providerDomainId: string): Promise<StandardEmailDomain | null>;\n /** Start the provider's (asynchronous) verification. */\n verifyDomain(providerDomainId: string): Promise<void>;\n deleteDomain(providerDomainId: string): Promise<void>;\n}\n\n/**\n * What an EMAIL_INBOUND provider implements. Built by the provider module's adapter factory with the\n * credential the engine resolved, exactly as a billing adapter is — the module never reads a secret\n * itself.\n */\nexport interface StandardInboundEmail_Interface {\n /** Map the verified notification body onto the standard notification. Pure; refuses an unknown shape by throwing. */\n parseNotification(body: unknown): StandardInboundEmail_Notification;\n /** Fetch the whole message the notification announced. */\n fetchMessage(providerMessageId: string): Promise<StandardInboundEmail_Message>;\n /** Fetch one attachment's bytes, by the `ref` the message listed. */\n openAttachment(ref: string): Promise<StandardInboundEmail_OpenedAttachment>;\n /** Fetch the original message bytes, by the message's `rawRef`. */\n openRaw(rawRef: string): Promise<StandardInboundEmail_OpenedRaw>;\n}\n\n// ===============================================================\n// What a provider module DECLARES (pure functions; the engine owns the transport)\n// ===============================================================\n\n/**\n * One request a provider module asks the engine to make on its behalf.\n *\n * `path` is appended to the contract's `baseUrl`. A provider that serves bytes from ANOTHER host (a\n * signed download URL) returns `url` instead, and the engine admits it only against the hosts the\n * contract declares — a provider-supplied URL is never fetched merely because a provider named it.\n */\nexport type InboundEmailProviderRequest =\n | { readonly path: string; readonly method?: EmailProviderHttpMethod; readonly jsonBody?: unknown; readonly headers?: Readonly<Record<string, string>> }\n | { readonly url: string; readonly headers?: Readonly<Record<string, string>> };\n\n/**\n * The methods a provider's `path` request may use. A `url` request (a signed download link) is always a GET.\n * Absent means GET.\n */\nexport enum EmailProviderHttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n}\n\n/** A provider's HTTP answer, as the engine hands it to the provider's parser. */\nexport interface InboundEmailProviderResponseInput {\n readonly status: number;\n /** The JSON body, or `undefined` when the answer was not JSON. */\n readonly body: unknown;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"email-inbound.standard-interface.schemas.js","sourceRoot":"","sources":["../../../../src/protocols/email-inbound.standard-interface.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\n// ===============================================================\n// Standard Inbound Email Interface (#1630)\n// --------\n// The canonical shape of a message an EMAIL_INBOUND provider RECEIVED for the application, and the\n// three calls the engine makes on the provider to get it. Provider-agnostic: a vendor's module maps\n// its own notification and message payloads onto these schemas, and nothing past that mapping ever\n// sees a vendor field.\n//\n// There is deliberately NO `verify` here. The notification reaches the application through the\n// provider's `WEBHOOK_ORIGINATOR` endpoint (the `inbound-email` key, capability `EMAIL_INBOUND`), and\n// that endpoint is verified by the ENGINE-owned scheme its `signatureConfig` names (#1596). A\n// provider that verified its own notifications would put the one fail-closed decision of the inbound\n// path in vendor code, where nothing checks it.\n// ===============================================================\n\n/**\n * One authentication method's result, as a receiving server records it in `Authentication-Results`.\n *\n * The union of the results the three methods define, so one vocabulary serves SPF, DKIM and DMARC.\n * Two members go beyond what a DMARC result can be — `SOFTFAIL` (SPF only) and `POLICY` (DKIM and\n * SPF) — and are here because mapping them onto a neighbour would record a result the receiver did\n * not report: a softfail is neither a fail nor neutral.\n *\n * spec-cite: RFC 8601 §2.7.1 (DKIM results: none, pass, fail, policy, neutral, temperror, permerror)\n * and §2.7.2 (SPF results: none, pass, fail, softfail, neutral, temperror, permerror, plus policy\n * from §2.4); DMARC results per RFC 7489 §11.2 (none, pass, fail, temperror, permerror). Fetched 2026-09-27.\n */\nexport enum EmailAuthenticationVerdict {\n PASS = \"pass\",\n FAIL = \"fail\",\n SOFTFAIL = \"softfail\",\n NEUTRAL = \"neutral\",\n NONE = \"none\",\n POLICY = \"policy\",\n TEMPERROR = \"temperror\",\n PERMERROR = \"permerror\",\n}\n\n/**\n * What the receiving provider concluded about a message's origin.\n *\n * `dmarcAligned` is kept beside the DMARC verdict rather than folded into it because it is the fact\n * sender assurance is built on: DMARC authenticates the `From` DOMAIN by requiring that it align with\n * an identifier SPF or DKIM authenticated. A provider that reports DMARC `pass` has already required\n * alignment, so for most vendors `dmarcAligned` equals `dmarc === PASS`; it is a separate field so a\n * vendor that reports the two independently is not forced to invent one from the other.\n */\nexport const StandardInboundEmail_AuthenticationSchema = z.object({\n spf: z.enum(EmailAuthenticationVerdict),\n dkim: z.enum(EmailAuthenticationVerdict),\n dmarc: z.enum(EmailAuthenticationVerdict),\n dmarcAligned: z.boolean(),\n});\n\nexport type StandardInboundEmail_Authentication = z.infer<typeof StandardInboundEmail_AuthenticationSchema>;\n\nexport const StandardInboundEmail_AddressSchema = z.object({\n address: z.string().min(1),\n name: z.string().optional(),\n});\n\nexport type StandardInboundEmail_Address = z.infer<typeof StandardInboundEmail_AddressSchema>;\n\n/** How a MIME part asks to be presented (`Content-Disposition`). spec-cite: RFC 2183 §2.1 (`inline`) and §2.2 (`attachment`). */\nexport enum EmailAttachmentDisposition {\n ATTACHMENT = \"attachment\",\n INLINE = \"inline\",\n}\n\n/** One attachment as the provider describes it. The bytes are fetched through `openAttachment`, never inlined. */\nexport const StandardInboundEmail_AttachmentSchema = z.object({\n /** Opaque to the engine; handed back to `openAttachment`. */\n ref: z.string().min(1),\n filename: z.string(),\n contentType: z.string(),\n sizeBytes: z.number().int().nonnegative(),\n /** The `Content-ID` of an inline part, without angle brackets. */\n contentId: z.string().optional(),\n disposition: z.enum(EmailAttachmentDisposition).optional(),\n});\n\nexport type StandardInboundEmail_Attachment = z.infer<typeof StandardInboundEmail_AttachmentSchema>;\n\n/**\n * What a provider's notification says, parsed. Small on purpose: a notification tells the engine\n * THAT a message arrived and where to fetch it, and nothing past this point trusts it for more.\n */\nexport const StandardInboundEmail_NotificationSchema = z.object({\n /** The provider's id for the message — what `fetchMessage` takes, and the dedup key of the channel delivery. */\n providerMessageId: z.string().min(1),\n /** The addresses the message was delivered FOR (the SMTP envelope recipients), which routing reads. */\n receivedFor: z.array(z.string().min(1)).min(1),\n receivedAt: z.coerce.date(),\n});\n\nexport type StandardInboundEmail_Notification = z.infer<typeof StandardInboundEmail_NotificationSchema>;\n\n/**\n * One received message, provider-neutral.\n *\n * The threading headers are separated out because the engine correlates threads from them;\n * `headers` carries the rest, for a channel record that chooses to keep an allow-listed subset.\n */\nexport const StandardInboundEmail_MessageSchema = z.object({\n providerMessageId: z.string().min(1),\n /** The RFC 5322 `Message-ID`, angle brackets included, or absent when the sender set none. */\n messageId: z.string().optional(),\n inReplyTo: z.string().optional(),\n references: z.array(z.string()).default([]),\n from: StandardInboundEmail_AddressSchema,\n to: z.array(StandardInboundEmail_AddressSchema).default([]),\n cc: z.array(StandardInboundEmail_AddressSchema).default([]),\n replyTo: StandardInboundEmail_AddressSchema.optional(),\n receivedFor: z.array(z.string().min(1)).min(1),\n subject: z.string().default(\"\"),\n textBody: z.string().optional(),\n htmlBody: z.string().optional(),\n headers: z.record(z.string(), z.string()).default({}),\n authentication: StandardInboundEmail_AuthenticationSchema,\n attachments: z.array(StandardInboundEmail_AttachmentSchema).default([]),\n sizeBytes: z.number().int().nonnegative().optional(),\n receivedAt: z.coerce.date(),\n /**\n * Where the ORIGINAL message bytes are, when the provider keeps them (#1600). Opaque to the engine; handed\n * to `openRaw`. Absent when the provider offers no raw copy — the engine then keeps no raw MIME.\n */\n rawRef: z.string().min(1).optional(),\n});\n\nexport type StandardInboundEmail_Message = z.infer<typeof StandardInboundEmail_MessageSchema>;\n\n/** The bytes of one attachment. */\nexport interface StandardInboundEmail_OpenedAttachment {\n readonly bytes: Uint8Array;\n readonly contentType: string;\n readonly filename: string;\n}\n\n/** The original bytes of a message, exactly as the provider serves them. */\nexport interface StandardInboundEmail_OpenedRaw {\n readonly bytes: Uint8Array;\n}\n\n// ===============================================================\n// Receiving domains (#1600)\n// ===============================================================\n\n/** Where a domain stands AT THE PROVIDER — distinct from the organization's own status, which also records ownership proof. */\nexport enum EmailProviderDomainStatus {\n /** The provider has not verified the domain's records yet (not started, pending, or a temporary failure it will retry). */\n PENDING = \"pending\",\n /** The provider verified the domain's records. */\n VERIFIED = \"verified\",\n /** The provider gave up verifying the records. */\n FAILED = \"failed\",\n}\n\n/** One DNS record the provider asks to be published. */\nexport const StandardEmailDomain_DnsRecordSchema = z.object({\n /** What it is for, as the provider names it (DKIM, SPF, MX, Receiving…). */\n purpose: z.string(),\n type: z.string(),\n name: z.string(),\n value: z.string(),\n priority: z.number().int().optional(),\n status: z.string().optional(),\n});\n\nexport type StandardEmailDomain_DnsRecord = z.infer<typeof StandardEmailDomain_DnsRecordSchema>;\n\n/** A domain as the provider describes it. */\nexport const StandardEmailDomainSchema = z.object({\n providerDomainId: z.string().min(1),\n name: z.string().min(1),\n status: z.enum(EmailProviderDomainStatus),\n sending: z.boolean(),\n receiving: z.boolean(),\n records: z.array(StandardEmailDomain_DnsRecordSchema).default([]),\n});\n\nexport type StandardEmailDomain = z.infer<typeof StandardEmailDomainSchema>;\n\n/**\n * What an EMAIL_INBOUND provider implements to host an organization's own domain. Every tenant shares one\n * provider account, so the ENGINE proves the organization owns the domain before it ever calls `createDomain`.\n */\nexport interface StandardEmailDomains_Interface {\n createDomain(input: { readonly name: string; readonly sending: boolean; readonly receiving: boolean }): Promise<StandardEmailDomain>;\n getDomain(providerDomainId: string): Promise<StandardEmailDomain | null>;\n /** Start the provider's (asynchronous) verification. */\n verifyDomain(providerDomainId: string): Promise<void>;\n deleteDomain(providerDomainId: string): Promise<void>;\n}\n\n/**\n * What an EMAIL_INBOUND provider implements. Built by the provider module's adapter factory with the\n * credential the engine resolved, exactly as a billing adapter is — the module never reads a secret\n * itself.\n */\nexport interface StandardInboundEmail_Interface {\n /** Map the verified notification body onto the standard notification. Pure; refuses an unknown shape by throwing. */\n parseNotification(body: unknown): StandardInboundEmail_Notification;\n /** Fetch the whole message the notification announced. */\n fetchMessage(providerMessageId: string): Promise<StandardInboundEmail_Message>;\n /** Fetch one attachment's bytes, by the `ref` the message listed. */\n openAttachment(ref: string): Promise<StandardInboundEmail_OpenedAttachment>;\n /** Fetch the original message bytes, by the message's `rawRef`. */\n openRaw(rawRef: string): Promise<StandardInboundEmail_OpenedRaw>;\n}\n\n// ===============================================================\n// What a provider module DECLARES (pure functions; the engine owns the transport)\n// ===============================================================\n\n/**\n * One request a provider module asks the engine to make on its behalf.\n *\n * `path` is appended to the contract's `baseUrl`. A provider that serves bytes from ANOTHER host (a\n * signed download URL) returns `url` instead, and the engine admits it only against the hosts the\n * contract declares — a provider-supplied URL is never fetched merely because a provider named it.\n */\nexport type InboundEmailProviderRequest =\n | { readonly path: string; readonly method?: EmailProviderHttpMethod; readonly jsonBody?: unknown; readonly headers?: Readonly<Record<string, string>> }\n | { readonly url: string; readonly headers?: Readonly<Record<string, string>> };\n\n/**\n * The methods a provider's `path` request may use. A `url` request (a signed download link) is always a GET.\n * Absent means GET.\n */\nexport enum EmailProviderHttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n}\n\n/** A provider's HTTP answer, as the engine hands it to the provider's parser. */\nexport interface InboundEmailProviderResponseInput {\n readonly status: number;\n /** The JSON body, or `undefined` when the answer was not JSON. */\n readonly body: unknown;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"email.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["../../../../src/protocols/email.external-connectors-models.schemas.ts"],"names":[],"mappings":"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"}
|