Pre-launch. Not deployable to production. This page states what the tests prove and what is missing — nothing else.

From e-signature to exactly one immutable order

E-signature and signed orders

People ask this as: e-signature workflow with verified webhooks that creates an order

An approved quote version becomes one signature envelope — one, ever — whose provider events are cryptographically verified before any state changes, and whose completion produces one immutable Order in a single transaction. Every signature provider here is an offline fixture: no DocuSign, Adobe Sign or Dropbox Sign adapter exists, no credential ships, and no envelope has ever been sent to a real signer. The signed document is canonical JSON, not a PDF, and the artifact hash is provider-reported rather than independently recomputed.

Where this stops

Read this before the rest of the page. Every line below is a thing this does not do.

  • Every signature provider is an offline fixture. No DocuSign, Adobe Sign or Dropbox Sign adapter exists, no credential ships, and no envelope has ever been sent to a real signer.
  • The webhook verification key is test-only and lives in checked-in source. Rotation, per-tenant keys and a secret store are Production Spine work, so this is a verified webhook contract, not production webhook security.
  • The signed document is canonical JSON with the media type application/vnd.accordo.quote-package+json. It is not a PDF and is never called one.
  • The artifact hash is provider-reported. The framework never downloads the artifact bytes and verifies no signature cryptographically; what it does verify locally is that the stored canonical document re-hashes to the document hash at completion.
  • Signer identity assurance is not claimed. All signers are required, one to five of them, and the declared order is recorded and displayed but not sequentially gated — no reminders, no delegation, no conditional routing.
  • A failed envelope cannot be re-sent. There is no resend framework and no scheduler; reconciliation is an explicit call a human, a test or the starter makes.
  • An Order carries no fulfillment, billing, payment or invoice state, no ARR, MRR or TCV, and no amendment or cancellation path.

No authentication, tenancy or RBAC. The server is local-development-only. An actor header is an assertion, not an identity. Do not expose it to a network. Every claim and every limitation is on one page.

What it models

A human requests signature on an approved quote version. A deterministic canonical JSON document package is derived from the immutable snapshot rows — quote and version identity, parties, the offer and product-version snapshot, every component with its tier schedule and band breakdown, grouped totals, the discount-policy decision and the signer list — and SHA-256 is taken over exactly the bytes the provider receives. Object keys sort by code unit, array order is preserved, there is no whitespace and no locale-sensitive comparison anywhere. CRLF and LF, precomposed and decomposed Unicode, 1 and "1" are different documents; nothing is silently normalized.

The envelope moves over a published allowed-transition table, not a rank comparison, because completed, declined and voided are branching outcomes rather than points on a scale. Provider events land in an append-only inbox with a unique provider event id and a fingerprint of the verified bytes; each records whether its effect was applied, ignored or quarantined. A completion performs the envelope transition, the signer evidence, the signed artifact, the Order with its lines, components, tiers and grouped totals, the managed links and the audits in one transaction.

The Order copies everything from the Quote Version and re-reads nothing from the live catalog. A catalog tier and price change after signing leaves both the Quote Version and the Order byte-identical.

Two transactions that never pretend to be one

A local database and a remote provider cannot commit atomically. Rather than hide that, an action declares a bounded external-operation shape: intent inside transaction A, external outside every transaction with a bounded timeout, finalize inside transaction B, and compensate in its own transaction only when a later phase failed. The external context carries no database, no modules and no managed writes — it sees the frozen intent value, the validated input, the actor and the provider registry, and nothing else. Action code declares phases; it never gains transaction control.

One trace run records the intent, external, finalize and compensate spans separately, so local intent, the provider call and local finalization are always distinguishable when something goes wrong. A failed envelope keeps the failure phase and code, so a provider request that failed, a local finalization that failed after a possible provider success, a verification failure and an artifact failure stay four different facts.

The recovery policy is one sentence: never silently retry, always reconcile. Reconciliation queries the provider outside every transaction, by provider envelope id when known and otherwise by the deterministic idempotency key, applies the same monotonic transition and the same atomic completion, never duplicates an event, artifact or order, and says absent-at-provider when the provider holds nothing. No background scheduler runs it — it is always an explicit, audited call.

What the framework refuses

Only a user actor may request a signature; an agent is refused 403 HUMAN_APPROVAL_REQUIRED. An agent may prepare the quote, the version and the signer inputs — a human sends.

There is exactly one envelope per quote version, ever: the source key is database-unique and doubles as the provider idempotency key, so a repeat is 409 ENVELOPE_EXISTS and a second provider envelope is structurally impossible. An idempotency key is treated as a lookup rather than an identity — before a provider envelope is adopted, at creation and at reconciliation, it must agree with the local intent on the document hash and the signer set, and a disagreement is 409 PROVIDER_ENVELOPE_MISMATCH with nothing bound.

Webhook verification runs before any state mutation, over the raw bytes as they came off the socket, with constant-time HMAC-SHA256 and a replay window. A failure is a stable 401 that never echoes the payload, the signature or the key. The same event id with the same bytes is a duplicate; the same id with different bytes is 409 EVENT_ID_CONFLICT rather than an acknowledged replay. An event for an unknown envelope is quarantined as evidence — not discarded, not an error — and linked once the envelope learns its provider id, so an early completion is never lost.

A duplicate, late or contradictory event can never regress a completed envelope, and the document package is rebuilt and re-hashed before an Order is created: a snapshot that really moved is 409 DOCUMENT_HASH_MISMATCH rather than a mis-signed order.

What proves it

tests/signature-order-e2e.test.js walks the crash and recovery matrix — including a really killed child process and two application instances on one database — and asserts that in every row requesting again is refused, reconciliation is idempotent, and no second provider envelope can exist for one quote version. tests/signature-contract.test.js holds the transition table and the verification contract; tests/admin-signature.test.js covers the screens and the caveats they must print.

The order key is database-unique per quote version, so duplicate webhooks, concurrent webhooks and a webhook racing a reconcile can only ever produce one Order.

Where it stops

This produces a signed commitment and an immutable commercial snapshot. It does not produce fulfillment, billing, payment, invoicing, tax, revenue recognition, cancellation, amendment or renewal, and a quote version whose envelope failed cannot be sent again — reconciliation is the only recovery path, and the Admin says which of the three failure cases applies instead of implying the provider's state is known when it is not.

The evidence this page rests on

Claims and limitations are printed from site/claims.json word for word. Job statuses come from docs/benchmarks/jobs.json; a job with no page of its own is listed with its status rather than linked.

Claims

  • C-09 A signature envelope produces verified events and a hashed signed artifact, and exactly one immutable Order is built from the approved quote version.

    LimitA fixture signature provider with a test-only webhook key. No DocuSign, Adobe Sign or Dropbox Sign adapter exists, and the artifact hash is provider-reported rather than independently recomputed.

  • C-16 Every mutation goes through a module service or a named workflow, and leaves an audit event and a step-level trace behind it.

    LimitAudit records what the process did under an asserted actor. It is not a tamper-evident or externally attestable log, and it is not a compliance control.

Limitations

  • L-01 No authentication, tenancy or RBAC. The server is local-development-only. An actor header is an assertion, not an identity. Do not expose it to a network.
  • L-05 No email, calendar or marketing integrations. An in-memory notification provider contract exists. No adapter sends anything to anyone.

Jobs it covers

Documented in