Skip to content
Get started

Spec: Portable Import Contract v1

A Portable Import Contract is a signed, data-free bundle describing what a receiving tenant accepts: the pinned target catalog, the required columns, policy limits, and — when the receiver has import history for this file shape — a declarative profile (header row, mapping, transform recipe). A counterparty, human or agent, checks a file against it before sending anything. The check runs entirely on the sender’s side: zero egress.

What the contract is for, in product terms, is covered by Import contracts. This page is the normative format.

Schema: import-contract.v1.schema.json · current version: contractVersion: 1

Same discipline as receipts:

{
"contract": { "contractVersion": 1, "...": "the plain contract document" },
"signature": { "protected": "<b64url header>", "signature": "<b64url signature>" },
"keyId": "<key id>"
}

The canonical JSON rules and the detached-JWS scheme (RFC 7515 flattened + RFC 7797 unencoded payload, ES256) are identical to the receipt’s — one canonicalizer, one signature scheme, deliberately. They are specified once, on the receipt page.

Field Semantics
contractVersion Always 1 for this revision.
id Content address: sha256:<hex> — see below.
issuer The tenant that exported the contract, and the signing key id.
title Human-readable name (“Contacts import — Q3 supplier onboarding”).
profile The declarative import profile: optional file-shape fingerprint, headerRow, mapping (source header → target column key), and an optional recipe. Decisions, never data — no cell values appear anywhere.
catalog The target catalog as a pinned snapshot — the fields, types, validations, and options the receiver accepts. Never a live reference.
keySeparator Composite-key separator the receiving flow uses (optional).
engine Parity pins: the matcher and transform engine versions the profile was minted under.
policy requiredColumns (target keys that must be mapped), optional maxRows, optional accepted encodings.
createdAt / expiresAt Issue time; optional expiry.

The recipe member is opaque at the contract boundary: its interpretation belongs to the transform engine that minted it. A third-party runner treats it as an opaque value and can still enforce everything else on this page.

id is the contract’s content address, computed as:

  1. Take the contract document with id excluded (a document cannot contain its own hash).
  2. Compute its canonical JSON (receipt-page rules).
  3. SHA-256 the canonical string; render as lowercase hex; prefix sha256:.

Verifiers recompute this and reject on mismatch — before even checking the signature. Two contracts with the same id are the same contract.

Conformance: what a pre-flight runner must do

Section titled “Conformance: what a pre-flight runner must do”

A runner claiming to check a file against a contract:

  1. Verify first. Recompute the content address; verify the detached JWS; reject if expiresAt has passed. A runner must not report pre-flight results for a contract it could not verify.
  2. Refuse on engine mismatch. If the runner executes the recipe or replays the mapping, it must compare its engine versions against the engine pins and refuse rather than guess on incompatibility. (A runner that only checks policy and the catalog needs no engine parity.)
  3. Enforce policy. Fail the pre-flight when a requiredColumns entry ends up unmapped, when the file exceeds maxRows, or when its encoding is outside encodings (when declared).
  4. Validate against the snapshot. Field-level checks use the pinned catalog in the contract — not any live source. Contracts are not updated in place; a receiver whose requirements changed reissues, and the stale contract simply stops verifying against expectations (or expires).
  5. Send nothing. The pre-flight is defined as a local computation. A conforming runner performs it without transmitting file contents anywhere — verification never phones home, on either side of the exchange.

Minting is a shipped, documented API route (see the OpenAPI document). A packaged, standalone pre-flight checker is not shipped today: the checking half currently exists as reference code inside Mildport’s own applications. The format above plus the published schema is sufficient to build one — which is exactly what the implementations page invites.


This specification page and the linked schema are licensed CC BY 4.0 — see the spec overview for scope.