Controlled disclosure

Publication boundary

Local completion and public disclosure are two distinct events. The runtime completes a signing computation and holds the result under local control until a separate gate authorizes disclosure.

publication gateExecuted and Published are separate states
ExecutedSignature(local_private)ResultHandle
PublishGatepolicy / scope / receiptExecuted ≠ Published
PublishedSignature(public_all)PublicationReceipt
SubmittedToRailAcceptedByRailSettledReconciled
"scope""client | rail | evidence"
"result_ref""sigloc://..."
"publication_receipt""pubrec_..."
"prev_event_hash""evt_..."
"reason_code"null
N-01

What PublishGate protects

PublishGate checks whether a computed result can be disclosed for a given scope. It performs no computation — the result already exists. It decides whether that result can leave local control, and if so emits a PublicationReceipt binding scope, result reference, and continuation. Otherwise it records PUBLICATION_DENIED and the local result stays closed.

A result might go back to a client, be submitted to a settlement rail, published into an evidence package, or bound to an external directory. Each path has its own receipt and continuation state.

N-02

Operator-visible states

The lifecycle distinguishes a completed MPC computation from a public effect, and records which stage an operation reached: failed before execution, waiting for peers, locally complete, held at the publication gate, or accepted by an external rail. A wallet or custody UI shows a receipt for local completion and a separate receipt for publication.

N-03

External continuation

After publication, rail submission, settlement, reconciliation, directory updates, and customer evidence export continue independently and bind back to the publication receipt. The ExternalExportGate rejects unknown receipts, context mismatches, and state regression, holding the boundary with banking rails, blockchain submission, key transparency directories, and enterprise SIEM.

N-04

Disclosure scope and approval binding

PublishGate decides both whether to disclose and to which scope — client, settlement rail, evidence package, or external directory — and each scope carries its own receipt and continuation state. Controlled local disclosure stays separate from external submission, so a result can reach a client while its rail submission is still pending.

For value-moving operations the shown-and-approved view is cryptographically bound to the payload, message, and transcript hashes via display_hash, so what an approver saw is provably what was signed. A mismatch between the displayed intent and the request digest is rejected before any disclosure happens.

N-05

Hold, deny, and approve: the three gate outcomes

PublishGate has three paths. In the normal path the gate evaluates policy controls and emits a PublicationReceipt — the result moves from local_private to Published. In the deny path the gate records PUBLICATION_DENIED; the local result stays closed and the operation reaches a terminal state without disclosure. In the hold path (CUSTOMER_REVIEW_HOLD or an equivalent customer-defined code), the gate suspends — the computation is complete, the result exists locally, and the gate is waiting for a policy plane signal before deciding.

The hold path is the integration point for manual review workflows, compliance holds, and staged release controls. It can be exercised in DVM-SL via a hook (on call kind=publish-gate peer api => deny code "CUSTOMER_REVIEW_HOLD"). The result does not leave local control, the operation is not terminal, and the gate can be released through the policy plane without repeating the MPC computation.

N-06

What operators see at each outcome

After a PublicationReceipt: lifecycle.state == Published, publication.state == Published, and the artifact (SignaturePublic) is present. After PUBLICATION_DENIED: lifecycle.state == Aborted, publication.state == Denied, and a denial reason record appears in the evidence package. During a hold: the result is local_private, publication.state is not yet set, and no artifact has been released.

Customer-facing UIs and custody rails should map these three states explicitly: 'signed' only when the PublicationReceipt exists, 'held for review' when a hold is active, and 'declined' when PUBLICATION_DENIED is the terminal record. Each state maps to a distinct receipt and a distinct evidence record, separating a computation that failed from one that succeeded but was held.