Skip to main content

Operations

Moving documents is the easy half. This page covers the operational surface an EDI program actually runs on.

Reconciliation

Two levels: An outbound document with no 997 after EDI_ACK_SLA_HOURS (default 24) is overdue. The monitor fires an alert when the overdue set grows. Trace a single reference end to end with GET /v1/lifecycle/{reference}.

Evidence bundles

Compliance evidence, exportable for audit:
  • GET /v1/documents/{id}/evidence β€” one document and its related order chain.
  • GET /v1/evidence/{reference} β€” the bundle for a PO, shipment, or invoice reference.
  • GET /v1/artifacts/conformance β€” WS-1 acceptance evidence: for each packaged retail connector, instantiate and exercise it.

Deductions

Chargeback and deduction recovery, sourced from inbound 812s or keyed by an operator.

Monitoring and alerting

GET /v1/monitoring returns a real-time snapshot: per-partner acknowledgment SLA status and more. POST /v1/monitoring/evaluate evaluates monitoring and fires every critical alert through the configured channels. Alerts fan out to every configured channel independently β€” a Slack-compatible webhook (EDI_ALERT_WEBHOOK_URL) and/or email via the stateset-mail connector (EDI_MAIL_* plus EDI_ALERT_EMAIL_TO). The reconciliation monitor and delivery worker fire on:
  • The overdue-997 set growing β€” a partner failing to acknowledge.
  • The AS2 certificate nearing expiry (EDI_CERT_EXPIRY_WARN_DAYS, default 21 days).
  • AS2 deliveries failing after retries.
Alerts fire on change, not every cycle, so they don’t flood the channel. Repeats of the same alert kind and partner within EDI_ALERT_THROTTLE_SECONDS (default 300) are counted rather than re-sent; the next delivery carries the count. Set EDI_ALERT_WEBHOOK_SECRET and each alert POST carries an X-StateSet-Signature: sha256=<hex> HMAC of the body. Webhook URLs are validated at startup β€” a private or loopback URL fails fast unless EDI_ALERT_WEBHOOK_ALLOW_PRIVATE=true.

Analytics

  • GET /v1/analytics β€” volume, error rate, throughput trend.
  • GET /v1/analytics/export β€” per-partner analytics as a CSV download.
  • GET /v1/fulfillment β€” 3PL scorecard: fill rate, perfect-order rate, at-risk shipments.
  • GET /v1/network/readiness β€” trading-network readiness across the tenant’s partners.

Documents and replay

The document ledger is durable and paged. In HA deployments it is shared Postgres; a JSONL fallback covers single-node development. Events the sequencer permanently rejected land in the dead-letter store: inspect with GET /v1/deadletter, and push them all back into the active outbox with POST /v1/deadletter/replay.

Multi-tenancy

Every trading partner belongs to a tenant, and partner data is isolated per tenant. The credential carries the tenant: a partner API key implies its tenant, while the admin token selects one with an x-tenant-id header (default default). Reads and writes are scoped so one tenant never sees another’s partners. Provision tenants via GET/POST /v1/tenants. Cross-instance isolation requires Postgres; without DATABASE_URL the deployment is effectively single-tenant.

Operator dashboard

A Vite + React console behind a WorkOS AuthKit gateway: OAuth at the edge, a sealed session cookie, and a tenant-pinning proxy to the API. The browser never holds a backend credential, and each signed-in organization maps to a tenant. It surfaces document throughput, live alerts, 997 reconciliation, tracked AS2 deliveries, partners, and connectors, with trend sparklines. Operators can:
  • Create and edit partner identities and transports.
  • Page through the durable document ledger.
  • Reprocess inbound documents behind a confirmation.
  • Inspect immutable, actor-attributed audit events (GET /v1/audit).
  • Use an EDI agent whose mutations require signed, single-use confirmation tokens.
The dashboard is tested in CI (lint, vitest, build) and fails closed in production builds.

Health and metrics

Data retention

All *_RETENTION_DAYS sweeps run hourly on the cluster monitor leader. 0 (the default) keeps rows forever.
Pruning dedup entries re-opens the replay window past the cutoff, which lets legitimately wrapped control numbers through β€” but also lets a genuine replay through. Set EDI_SEEN_RETENTION_DAYS deliberately.