# Outbound resource lifecycle receipts

Runtime owns immutable outbound intents, admission, and exact terminal
receipts. Integration owns provider execution, retries, leases, uncertainty,
and remote identities. Runtime must not inspect Integration command tables to
decide whether a local record can be deleted or its identity transferred.

Runtime coordinates intent admission, result commit, delete, and identity
transfer with the same local owner fence. Result commit retains its intent
transaction lock. A pending or accepted intent blocks
destructive changes even before a remote link exists. A terminal Runtime
receipt releases that outstanding-intent guard. Only a matching successful
resource receipt can prove remote ownership for an identity transfer; a
no-effect receipt never establishes an identity.

## Accepted commands that produce no effect

`AdmissionRejected` describes rejection before durable Integration acceptance.
It cannot settle an already accepted command. Such a resource command can use
the existing `CommitResultRequest` with these fields:

| Field | Value |
|---|---|
| `ResultFormatVersion` | `ResourceNoEffectResultFormatV1` (`2`) |
| `RemoteID` | empty |
| `CanonicalResult` | Canonical `ResourceNoEffectResultV1` JSON |
| `ResultDigest` | `sha256:` followed by lowercase SHA-256 of those bytes |

The resource result payload has `version: 1`, `outcome: "NO_EFFECT"`, and one
closed reason:

- `REJECTED_BEFORE_DISPATCH`: no attempt reached provider I/O.
- `DEFINITIVE_NO_EFFECT`: affirmative evidence proves that every dispatched
  attempt produced no external effect.

Only `UPSERT` and `DELETE` intents admit this variant. Integration must persist
the result and prohibit any further dispatch before sending it. It retains and
retries the exact receipt request until Runtime confirms it. Runtime validates
the complete trusted scope, immutable intent ID/payload digest/Catalog revision,
and previously accepted Integration command ID under its transaction lock.
Duplicate commits require the same immutable result; conflicting results fail
closed. The Runtime transaction records the terminal result without applying a
metadata projection.

A timeout, expired lease, retry exhaustion, ambiguous attempt, or successful
partial provider mutation cannot be converted to `NO_EFFECT`. A definitive
failure of the latest attempt is insufficient when an earlier attempt remains
unresolved. Those commands keep blocking owner changes until Integration
reconciles their effects. The Catalog-retirement `CommitNoEffectRequest`
retains its separate, existing requirement for strictly newer trusted serving
authority; this resource variant does not relax that check or authorize replay
through a new Catalog revision.

## Completion and identity transfer

A successful Runtime result receipt may commit before Integration finishes
local bookkeeping. If Runtime transfers the identity during that window,
Integration may finish the original command using the exact successful receipt
and persisted result, without republishing the retired source identity. The
receipt is bound to the original intent and accepted command; an unrelated
completion, a no-effect result, or a matching digest by itself is insufficient.

`IntegrationScopeDigest`, `IntegrationLinkKeyV2`, and
`IntegrationRemoteLocatorHash` publish the existing V2 identity bytes in one
shared contract implementation. They are pure codecs over already authorized,
validated coordinates, not a registry, selector, ownership proof, or permission
check. Runtime and Integration still compare complete identities and owned
receipts. The separator bytes, link prefix, historical `PushToConnector`
discriminator, and remote-ID whitespace normalization remain unchanged. The
scope intentionally excludes Catalog revision so upgrades cannot move remote
identity. Golden vectors fix these compatibility semantics.

## Deployment and recovery

The new result uses existing wire fields and RPCs. Existing valid mail results
(envelope format `1`) and successful resource projections (`RemoteID`, no typed
result) remain unchanged. Runtime and Integration must both consume the
contract release containing this result and implement its durable lifecycle
before the fix is considered active. Updating only the contract pin is
insufficient. Deploy supporting Runtime before enabling the Integration sender;
complete the Integration upgrade before relying on the new owner protection
for old accepted work. A pre-upgrade failure may require explicit no-effect
reconciliation if the old worker never persisted a terminal result.

An old Runtime rejects result format `2`; Integration must retain the durable
result and retry after the Runtime upgrade. It must not fall back to a success
RemoteID, admission rejection, Catalog-retirement receipt, or unguarded deletion
to bypass that rejection. No extra capability or RPC is introduced: the
implementation release tuple is the deployment gate, while rejection is the
fail-closed compatibility behavior. Older Integration workers that do not emit
terminal receipts can leave accepted intents blocking; do not infer settlement
from their private status, age, or absence after retention cleanup.
