Implement a shipping adapter
Implement shipping operations in a local module or external route app.
Use features/keystone/utils/shippingProviderAdapter.ts as the dispatch contract. The built-in manual.ts, shippo.ts, and shipengine.ts files are local examples; an independently deployed app can implement the same operations through URLs stored on the ShippingProvider record.
Operations
getRatesFunction({ provider, order, dimensions })
validateAddressFunction({ provider, address })
createLabelFunction({ provider, order, rateId, dimensions, lineItems })
trackShipmentFunction({ provider, trackingNumber })
cancelLabelFunction({ provider, labelId })For an HTTP adapter, Openfront sends POST JSON containing provider plus the operation arguments. The route app translates that payload to its carrier, aggregator, warehouse, local courier, or custom fulfillment API and returns the provider-neutral result expected by Openfront.
Provider-neutral results
Return only the data needed by the domain caller:
- rates: stable rate ID, service, carrier, price, currency, and delivery estimate;
- validation: validity, normalized/suggested address, and safe errors;
- labels: status, label/tracking identifiers and URLs, carrier, service, rate, and bounded metadata;
- tracking: status, estimate, tracking URL, and normalized events;
- cancellation: provider result and final cancellation state.
Validate these runtime responses before creating or updating fulfillment records.
Rules
- check operator authority, order ownership/scope, unfulfilled quantities, address, parcel, and rate eligibility before calling the adapter;
- authenticate calls from Openfront to an external route app;
- forward only the provider and customer/order fields required by that operation;
- treat label purchase and cancellation as idempotent intents;
- use timeouts and reconcile an uncertain label purchase before retrying;
- redact access tokens, addresses, labels, and provider payloads from logs and browser errors;
- deduplicate tracking callbacks or polling observations;
- keep fulfillment lifecycle and audit evidence in Openfront rather than the adapter app.
Current configuration gap
The backend supports HTTP operation fields, but the current custom-provider forms do not wire them correctly: one stores metadata.apiUrl, and another selects a nonexistent local custom module. Configure the operation URLs through a trusted administrative path until those forms are repaired and covered by an end-to-end test.
Verification
- unit-test request/response translation;
- contract-test malformed, delayed, unauthorized, and replayed route calls;
- run sandbox rates, validation, label, tracking, and cancellation;
- retry one label intent and assert one purchase;
- reject rate/address/order/line mismatches;
- verify endpoint and credential edits require privileged operator authority;
- reconcile label cost, state, tracking, and cancellation with the fulfillment record.
See Add a shipping adapter for configuration details.