<?xml version='1.0' encoding='UTF-8'?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" category="info" docName="draft-das-composite-execution-finality-00" ipr="trust200902" submissionType="IETF" consensus="false" xml:lang="en" tocInclude="true" tocDepth="3" symRefs="true" sortRefs="true" version="3">
  <front>
    <title abbrev="Composite Execution Finality">Partial Commit Is Not Finality: Composite Candidate Acts Across Multiple Finality Sinks</title>
    <seriesInfo name="Internet-Draft" value="draft-das-composite-execution-finality-00"/>
    <author fullname="Sangam Das" initials="S." surname="Das">
      <organization>Independent</organization>
      <address>
        <postal>
          <city>Balasore</city>
          <region>Odisha</region>
          <country>IN</country>
        </postal>
        <phone>+91-9861363532</phone>
        <email>info@sangamdas.com</email>
      </address>
    </author>
    <date year="2026" month="September" day="16"/>
    <area>Security</area>
    <workgroup>Individual Submission</workgroup>
    <keyword>execution finality</keyword>
    <keyword>composite act</keyword>
    <keyword>multi-sink</keyword>
    <keyword>atomic consume</keyword>
    <keyword>all-or-none</keyword>
    <keyword>execution handle</keyword>
    <keyword>finality receipt</keyword>

    <abstract>
      <t>
        An agent, a payment orchestrator, or a control-plane applicator often intends
        one Candidate Act that would become real only as several consequences: a
        settlement post, a ledger write, a tool invoke, a notification, a radio
        enable.  <xref target="DAS-HANDLE"/> specifies verify, consume, and receipt
        at one Finality Sink.  It does not say what "the act was permitted" means
        when sink S1 has consumed and posted and sink S2 has rejected, timed out,
        or committed a different digest.
      </t>
      <t>
        Existing distributed-transaction tools already address adjacent problems.
        Two-phase commit, XA, sagas, TCC, transactional outbox, and workflow
        engines coordinate steps.  OAuth, WIMSE, RATS, and SCITT still name
        identity, environment, and signed statements.  None of them, by themselves,
        bind N sink-local Execution Handles to one composite Act Digest and require
        that no child consequence become externally effective unless every required
        child reaches a defined terminal state.
      </t>
      <t>
        This document specifies Composite Candidate Acts, child handles, a
        coordinator that may only prepare, a two-phase consume rule, and the
        distinction between prevention (no child commits unless the composite
        closes) and mitigation (compensate after a partial post).  Compensation
        is itself a Candidate Act.  It is not a silent undo and not a license to
        skip verify on the original child.
      </t>
      <t>
        This is not a new consensus protocol and not a claim that XA is obsolete.
        Profiles that cannot obtain prepare-from-every-sink MUST NOT claim
        all-or-none prevention.
      </t>
      <t>
        Three rejections are expected and are treated as design constraints.
        "Saga plus handle is enough" is accepted when each saga step already
        reconstructs the live child, consumes a child handle, and cannot log
        SUCCESS after a required child rejects; this draft then shrinks to
        join fields.  Prepare across N sinks is a latency tax only if
        consume-state is global; it is per child handle, and a no_prepare
        mail or MCP child must use the mitigation profile rather than pretend
        2PC.  Child sinks reconstruct only their own pending effect, not a
        mesh-wide CAD.  Reviewers who would reject on saga, performance, or
        reconstruction grounds are asked to read those sections before
        discarding the document.  Criticism, including "this should stay a
        note in the handle draft," remains invited.
      </t>
    </abstract>
  </front>

  <middle>
    <section anchor="intro">
      <name>Introduction</name>

      <section anchor="intro-vulnerability">
        <name>Vulnerability: One Intent, Split Reality</name>
        <t>
          A composite intent C is authorized as a unit: pay vendor X AND write
          the invoice AND notify finance.  If the settlement sink consumes its
          handle and posts, and the notification sink times out, operators
          still say "the agent paid."  The Candidate Act that was reviewed was
          not the world that occurred.  No child token was forged.  The failure
          is split effectuation of one intended act.
        </t>
        <figure anchor="fig-split">
          <name>Child S1 commits; child S2 never becomes effective</name>
          <artwork type="ascii-art">
Intended C = { pay X, book invoice, notify finance }

        +-- S1 SETTLEMENT   consume + post     EFFECTUATED
   C ---+-- S2 CONTROL      timeout            NON_EFFECTIVE
        +-- S3 TOOL         never invoked      NON_EFFECTIVE

Reviewed act:   C
Occurred world: pay X only

Partial commit
      !=
composite finality
          </artwork>
        </figure>
      </section>

      <section anchor="intro-existing">
        <name>Existing Mechanisms Already Coordinate Steps</name>
        <t>
          Two-phase commit and XA serialize prepare/commit across resource
          managers.  Sagas and TCC specify forward actions plus compensations.
          Outbox and workflow engines order side effects.  Those tools should
          be used.  They do not define an Execution Handle per child sink, do
          not reconstruct each live child act, and do not make "compensation"
          a second handled Candidate Act.
        </t>
      </section>

      <section anchor="intro-gap">
        <name>Residual Gap After a Single-Sink Handle</name>
        <t>
          <xref target="DAS-HANDLE"/> closes possession-versus-authority at one
          boundary.  After that draft, each child can be locally correct and
          the composite still wrong.  Registries reserve <tt>COMPOSITE</tt>
          as a class and a sink type <xref target="DAS-REG"/>.  They do not
          specify the protocol.
        </t>
      </section>

      <section anchor="intro-delta">
        <name>What This Document Introduces</name>
        <ul spacing="normal">
          <li>Composite CAD with an ordered, explicit child list and a composite Act Digest.</li>
          <li>One child Execution Handle per required sink, all bound to the same composite id.</li>
          <li>Prepare / commit / abort on consume-state, with fail-closed defaults.</li>
          <li>A coordinator role that cannot substitute for child sinks.</li>
          <li>Compensation as a new Candidate Act, not a hidden reverse of the original handle.</li>
        </ul>
      </section>
    </section>

    <section anchor="conventions">
      <name>Conventions and Requirements Language</name>
      <t>
        The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
        "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
        "OPTIONAL" in this document are to be interpreted as described in
        BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and
        only when, they appear in all capitals.
      </t>
    </section>

    <section anchor="direct-question">
      <name>Direct Question</name>
      <t>
        If C is the act that was authorized, and only a proper subset of C's
        required children have become externally effective, was C effectuated?
      </t>
      <artwork type="ascii-art">
Prevention profile:
    C is EFFECTUATED
        iff every required child is EFFECTUATED
        under handles bound to C
        and no extra child effect is attributed to C.

Otherwise C remains NON_EFFECTIVE
    even if some child already moved money or iron.
      </artwork>
      <t>
        That last sentence is the operational cost.  If a profile cannot
        prevent the child post, it must not advertise all-or-none prevention.
      </t>
    </section>

    <section anchor="motivating-scenario">
      <name>Motivating Scenario: Pay, Book, Notify</name>
      <t>
        An enterprise agent is allowed to settle a vendor invoice only as a
        unit with the ERP booking and an audit mail.  Settlement posts in
        80 ms.  ERP is in a change window.  Mail is a third-party API with
        no prepare.  A coordinator that "retries notify later" has not
        effectuated C.  It has effectuated a different act: pay-without-book.
      </t>
      <figure anchor="fig-pay-book">
        <name>Why retry-later is a different Candidate Act</name>
        <artwork type="ascii-art">
Authorized C17 = pay + book + notify   [all required]

After S1 post, S2 reject:
    world = paid, not booked
    C17   = still NON_EFFECTIVE

C18 = "notify later about a payment already posted"
    is a new CAD
    and needs its own handle
        </artwork>
      </figure>
    </section>

    <section anchor="threat-model">
      <name>Threat Model</name>
      <t>The attacker need not forge handles.  Relevant failures:</t>
      <ul spacing="normal">
        <li>Child reordering so an optional notify is treated as required, or the reverse.</li>
        <li>Coordinator crash after S1 prepare and before S2 prepare.</li>
        <li>S2 commit of a mutated child CAD under the same composite id.</li>
        <li>Calling compensation on S1 without a new handle.</li>
        <li>Declaring success from the coordinator receipt while a required child is still PENDING.</li>
        <li>Using a saga log as proof that no child effect exists.</li>
      </ul>
    </section>

    <section anchor="goals">
      <name>Goals and Non-Goals</name>
      <t>
        Goal: define when a multi-sink Candidate Act may be called EFFECTUATED,
        PREPARED, ABORTED, or COMPENSATING, using the objects in
        <xref target="DAS-HANDLE"/>.
      </t>
      <t>
        Non-goals: a new Paxos/Raft; replacing XA or workflow engines; requiring
        every SaaS to implement prepare; claiming exactly-once delivery across
        the open Internet; automatic legal netting of a posted payment.
      </t>
    </section>

    <section anchor="terminology">
      <name>Terminology</name>
      <t><strong>Composite Candidate Act (C):</strong> A Candidate Act whose intended consequence is the conjunction of two or more child consequences.</t>
      <t><strong>Child Act C_i:</strong> The component that one sink would effectuate.</t>
      <t><strong>Required child:</strong> A child that MUST reach EFFECTUATED for C to reach EFFECTUATED.</t>
      <t><strong>Optional child:</strong> A child that MUST NOT block C if it fails, and MUST NOT be advertised as part of C's authorized unit if it is skipped.  Optional children SHOULD be separate acts.</t>
      <t><strong>Coordinator:</strong> The component that records composite state.  It is not a Finality Sink for a child effect unless it is also that child's sink.</t>
      <t><strong>Prepare:</strong> Child sink has verified the live child act, reserved consume-state, and promises not to post until commit or abort.</t>
      <t><strong>Compensation act:</strong> A new Candidate Act that would reverse or contain a child effect that already escaped.  It uses a new handle.</t>
    </section>

    <section anchor="objects">
      <name>Composite Objects</name>

      <section anchor="ccad">
        <name>Composite CAD</name>
        <t>
          A composite CAD is a CAD whose <tt>consequence_class</tt> and
          coordinator <tt>sink_type</tt> are <tt>COMPOSITE</tt>
          <xref target="DAS-REG"/>.  It MUST list children explicitly.
        </t>
        <artwork type="ascii-art">
composite_cad = {
  candidate_act_id,
  composite_act_digest,     // over canonical child list
  consequence_class: "COMPOSITE",
  children: [
    { child_id, cad_i, sink_i, required: true|false },
    ...
  ],
  join_rule: "ALL_REQUIRED",
  expires_at,
  generations
}

ALL_REQUIRED:
    every child with required=true must EFFECTUATE
    for C to EFFECTUATE.

QUORUM / BEST_EFFORT:
    MUST NOT be used in a prevention profile
    for FINANCIAL, PHYSICAL, RF, CLINICAL, MODEL_RELEASE.
        </artwork>
      </section>

      <section anchor="child-handle">
        <name>Child Handles</name>
        <t>
          Each required child has its own Execution Handle EH_i issued by the
          PED.  EH_i MUST bind:
        </t>
        <ul spacing="normal">
          <li><tt>act_digest</tt> of child CAD_i</li>
          <li><tt>sink_id</tt> of S_i</li>
          <li><tt>composite_id</tt> = C.candidate_act_id</li>
          <li><tt>reuse_policy</tt> compatible with the child class</li>
        </ul>
        <t>
          A child handle MUST NOT be accepted at a sink whose consume would
          not serve that composite_id.  Presenting EH_i for a standalone
          payment that is not C is EF-023 or EF-040
          <xref target="DAS-REG"/>.
        </t>
      </section>

      <section anchor="composite-handle">
        <name>Composite Handle</name>
        <t>
          The coordinator MAY hold a composite handle EH_C whose digest is
          the composite Act Digest.  EH_C authorizes the coordinator to
          drive prepare/commit/abort.  It does not authorize S_i to post.
        </t>
      </section>
    </section>

    <section anchor="state-machine">
      <name>Composite State Machine</name>
      <figure anchor="fig-states">
        <name>States of C, distinct from child sink states</name>
        <artwork type="ascii-art">
                 issue
                   |
                   v
              NON_EFFECTIVE
                   |
              children verify
                   v
                PREPARED -------- abort / timeout ------&gt; ABORTED
                   |
              all required commit
                   v
              EFFECTUATED

If any required child already posted
and others cannot:
              EFFECTUATED is forbidden
                   |
                   v
              COMPENSATING -- compensation C' --&gt; CONTAINED
                   |
                   +--&gt; UNKNOWN (compensation also split)

Prevention profile forbids entering COMPENSATING
because a required child posted before join.
        </artwork>
      </figure>
      <t>
        Child sinks use the handle draft states locally: verify, consume
        (here: reserve / commit / abort), receipt.  C's state is a join of
        those receipts, not a vote by the model that proposed C.
      </t>
    </section>

    <section anchor="protocol">
      <name>Prepare, Commit, Abort</name>

      <section anchor="phase-verify">
        <name>Phase 0: Reconstruct Each Child</name>
        <t>
          Each S_i MUST reconstruct live child CAD_i from the pending local
          effect, not from a coordinator-supplied blob alone
          <xref target="DAS-HANDLE"/>.  Coordinator-supplied CAD_i is a
          hint.  Digest mismatch is EF-023.
        </t>
      </section>

      <section anchor="phase-prepare">
        <name>Phase 1: Prepare</name>
        <t>
          Prepare is consume-state reservation without external effect.
        </t>
        <artwork type="ascii-art">
S_i.prepare(EH_i, live_cad_i):
    verify handle and reconstruct digest
    if fail: receipt REJECTED, do not reserve
    if consume-store down: EF-081, fail closed
    reserve EH_i  (not yet posted)
    return PREPARED

Coordinator:
    if any required child not PREPARED
        before deadline:
            abort all prepared children
            C = ABORTED
        </artwork>
        <t>
          A sink that cannot reserve without posting (typical third-party
          mail or card API) MUST be declared <tt>no_prepare=true</tt>.  A
          composite that includes a required no_prepare sink MUST NOT use
          the prevention profile.  It MAY use mitigation: post last, or
          accept COMPENSATING.
        </t>
      </section>

      <section anchor="phase-commit">
        <name>Phase 2: Commit or Abort</name>
        <artwork type="ascii-art">
Coordinator.commit(C):
    require all required children PREPARED
    require EH_C still current
    for each S_i:
        S_i.commit(EH_i)   // post + CONSUMED
    if all required EFFECTUATED:
        C = EFFECTUATED
        emit composite receipt
    else:
        // prevention profile: this branch
        // should be unreachable if prepare held
        C = COMPENSATING

Coordinator.abort(C):
    for each PREPARED S_i:
        S_i.abort(EH_i)    // release reserve, no post
    C = ABORTED
        </artwork>
      </section>
    </section>

    <section anchor="join-rules">
      <name>Join Rules</name>
      <table>
        <name>Join rules and whether prevention may be claimed</name>
        <thead>
          <tr>
            <th>Rule</th>
            <th>C EFFECTUATED when</th>
            <th>Prevention claim</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>ALL_REQUIRED</td>
            <td>every required child EFFECTUATED</td>
            <td>Yes, if every required sink supports prepare</td>
          </tr>
          <tr>
            <td>ALL_THEN_OPTIONAL</td>
            <td>required set EFFECTUATED; optional attempted</td>
            <td>Only over the required set</td>
          </tr>
          <tr>
            <td>QUORUM(k)</td>
            <td>any k children</td>
            <td>No for high-consequence classes</td>
          </tr>
          <tr>
            <td>BEST_EFFORT</td>
            <td>coordinator tried</td>
            <td>Never</td>
          </tr>
        </tbody>
      </table>
    </section>

    <section anchor="compensation">
      <name>Compensation Is a New Act</name>
      <t>
        If a required child has already posted, C cannot become EFFECTUATED
        and cannot become cleanly ABORTED.  A compensation Candidate Act C'
        MAY be issued: reverse the post, hold the funds, disable the radio,
        retract the tool side effect.
      </t>
      <figure anchor="fig-comp">
        <name>Compensation does not reuse the original child handle</name>
        <artwork type="ascii-art">
EH_pay  CONSUMED + posted
EH_book REJECTED

Forbidden:
    S_pay.undo(EH_pay)     // handle already consumed

Required:
    C' = "return funds for composite C17"
    new CAD', new EH'
    S_pay.verify/consume(EH')
    C  = COMPENSATING then CONTAINED
         only if C' EFFECTUATED
        </artwork>
      </figure>
      <t>
        Success of C' is not success of C.  Receipts MUST keep the two
        identifiers distinct.  Failure of C' leaves C in UNKNOWN containment
        and MUST be visible.
      </t>
    </section>

    <section anchor="coordinator">
      <name>Coordinator Rules</name>
      <ul spacing="normal">
        <li>The coordinator MUST NOT post a child effect itself unless it is that child's sink.</li>
        <li>The coordinator MUST persist composite state before sending commit.</li>
        <li>After crash, the coordinator MUST query child receipts; it MUST NOT assume commit or abort.</li>
        <li>A coordinator receipt without child receipts is not evidence that C effectuated.</li>
        <li>The coordinator SHOULD be identifiable as sink type COMPOSITE in the registry sense only: it joins, it does not replace SETTLEMENT or ACTUATION.</li>
      </ul>
    </section>

    <section anchor="timeouts">
      <name>Timeouts and Crash</name>
      <artwork type="ascii-art">
prepare_deadline exceeded
    -&gt; abort all PREPARED children
    -&gt; C = ABORTED

commit sent, coordinator dies
    -&gt; children stay PREPARED until
       commit, abort, or child-local reserve TTL
    -&gt; reserve TTL MUST fail closed
       (no automatic post)

child PREPARED, never hears commit/abort
    -&gt; on TTL: abort locally
    -&gt; report EF-080 / EF-081 if store cannot decide
      </artwork>
      <t>
        Automatic commit on coordinator silence is forbidden in the
        prevention profile.  That pattern is how partial posts happen.
      </t>
    </section>

    <section anchor="formal">
      <name>Formal Join</name>
      <artwork type="ascii-art">
Required(C)     = { i | child_i.required }
Prepared(C)     = { i in Required(C) | S_i.state == PREPARED }
Posted(C)       = { i in Required(C) | S_i.state == EFFECTUATED }
Rejected(C)     = { i in Required(C) | S_i.state == REJECTED }

C.EFFECTUATED   iff Posted(C) == Required(C)
                 AND no child digest diverged
                 AND join_rule == ALL_REQUIRED
                     or ALL_THEN_OPTIONAL

C.ABORTED       iff Posted(C) empty
                 AND (Rejected(C) nonempty
                      OR prepare_deadline missed)

C.COMPENSATING  iff Posted(C) nonempty
                 AND Posted(C) != Required(C)

PreventionWellFormed(C) iff
    join_rule == ALL_REQUIRED
AND every required S_i supports prepare
AND no required S_i has no_prepare
AND reserve TTL fail-closed

PreventionWellFormed(C) == false
    ==&gt; MUST NOT claim all-or-none prevention
      </artwork>
    </section>

    <section anchor="pseudocode">
      <name>Illustrative Pseudocode</name>
      <artwork type="ascii-art">
function effectuate_composite(C, handles):
    if not PreventionWellFormed(C):
        return mitigation_mode(C, handles)   # different claim

    prepared = []
    for child in required(C):
        live = child.sink.reconstruct()
        r = child.sink.prepare(handles[child], live)
        if r.decision != "PREPARED":
            abort_all(prepared)
            return receipt(C, "ABORTED", r.reason_code)
        prepared.append(child)

    for child in prepared:
        r = child.sink.commit(handles[child])
        if r.decision != "EFFECTUATED":
            return receipt(C, "COMPENSATING", "EF-044")

    return receipt(C, "EFFECTUATED", consume_outcome="CONSUMED")


function compensate(C, child_posted):
    C2 = new_cad(reverse_of(child_posted), parent=C.id)
    eh2 = PED.issue(C2)
    return child_posted.sink.verify_consume(eh2)
      </artwork>
    </section>

    <section anchor="composition">
      <name>Composition with Existing Tools</name>
      <table>
        <name>What existing coordinators supply versus what is still required</name>
        <thead>
          <tr>
            <th>Existing tool</th>
            <th>Supplies</th>
            <th>Still required</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>XA / 2PC</td>
            <td>Prepare/commit wire to RMs</td>
            <td>Child Act Digest + handle bind</td>
          </tr>
          <tr>
            <td>Saga / TCC</td>
            <td>Forward + compensate graph</td>
            <td>Compensation as new handle; no silent undo</td>
          </tr>
          <tr>
            <td>Outbox / workflow</td>
            <td>Ordered jobs, retries</td>
            <td>Retries are new attempts, not C success</td>
          </tr>
          <tr>
            <td>SCITT</td>
            <td>Logged composite receipt</td>
            <td>Log is not child commit</td>
          </tr>
          <tr>
            <td>Single-sink handle</td>
            <td>Local authority</td>
            <td>This join</td>
          </tr>
        </tbody>
      </table>
    </section>

    <section anchor="profiles">
      <name>Profiles</name>
      <t><tt>ef-composite-strict</tt>: ALL_REQUIRED, every required sink supports prepare, reserve TTL fail-closed, compensation is a new act, coordinator receipt insufficient.</t>
      <t><tt>ef-composite-mitigation</tt>: at least one required sink is no_prepare; document the escaped-effect window; MUST NOT claim prevention.</t>
    </section>

    <section anchor="anticipated-criticisms">
      <name>Anticipated Criticisms</name>
      <t>
        The invitation in the abstract to treat "saga plus handle is
        enough" as a successful review outcome is deliberate.  The same
        is true of the performance and reconstruction objections.  This
        section states where those objections are accepted.
      </t>

      <section anchor="crit-saga-enough">
        <name>Objection: Saga Plus Handle Is Enough</name>
        <t>
          If each saga step is already a handle-using sink — reconstruct
          live child, prepare or consume, fail closed — then this draft
          is a join profile on top of that saga, not a replacement for
          it.  XA resource managers that expose prepare, and PSP
          authorize/capture pairs, are the same pattern under other
          names.
        </t>
        <t>
          The residual cases this draft still names:
        </t>
        <ul spacing="normal">
          <li>the saga logs SUCCESS after a required child posts and another required child rejects;</li>
          <li>compensation reuses the original child handle instead of a new reverse act;</li>
          <li>a no_prepare child (mail, many MCP tools) is treated as if 2PC applied;</li>
          <li>the coordinator receipt is taken as proof that settlement occurred.</li>
        </ul>
        <artwork type="ascii-art">
Accepted:
    saga / XA / workflow
        AS coordinator
    child Execution Handle
        AS per-sink authority

Not accepted as prevention:
    saga success
        without child PREPARED/EFFECTUATED receipts
    compensate(original_token)
        after the original handle is CONSUMED
    BEST_EFFORT notify
        advertised as C EFFECTUATED
        </artwork>
        <t>
          If reviewers produce a saga profile that already forbids those
          four cases, this document should shrink to that profile plus
          the composite CAD fields.  That outcome is welcome.
        </t>
      </section>

      <section anchor="crit-perf-join">
        <name>Objection: Prepare Across N Sinks Is a Latency Tax</name>
        <t>
          ALL_REQUIRED prepare adds one reservation round to every
          required child before any child posts.  On a payment rail
          that is already authorize-then-capture, that round already
          exists.  On a three-sink agent path where mail cannot
          prepare, the honest profile is mitigation: do not claim
          all-or-none, or split notify into a later act.
        </t>
        <t>
          Consume-state remains per child handle, not one lock for the
          whole composite.  The coordinator persists join state; it
          does not serialize unrelated composites.  Automatic commit
          on coordinator silence is still forbidden in the strict
          profile, because that is how partial posts happen.
        </t>
      </section>

      <section anchor="crit-reconstruct-child">
        <name>Objection: Each Child Cannot Reconstruct a Unified CAD</name>
        <t>
          Children do not reconstruct the composite CAD.  Each sink
          reconstructs only its child: the payment it would post, the
          tool it would invoke, the row it would write.  The
          coordinator compares child receipts and the composite digest
          over the declared child list.  A mesh hop that is not a
          child sink does not reconstruct anything.
        </t>
        <t>
          If a child sink cannot observe the fields that change its
          own effect, that child cannot be in a prevention-profile
          composite.  It can be an optional later act.  Hiding that
          limitation inside a caller-supplied composite blob is how
          split reality occurs.
        </t>
      </section>

      <section anchor="crit-sdk-composite">
        <name>What Would Settle the Argument</name>
        <t>
          A minimal demonstration is more useful than another join
          diagram: one MCP (or payment) middleware that consumes a
          child handle, one second sink that can prepare, and a
          coordinator that aborts when the second child rejects —
          including the case where a prompt-injected destination
          changes only one child's digest.  This document does not
          ship that code.  An implementation that does is invited.
        </t>
      </section>
    </section>

    <section anchor="industry-relevance">
      <name>Industrial Relevance and Public-Roadmap Alignment</name>
      <t>
        Agent products already chain tools: pay, ticket, mail, CRM write.
        Cloud workflow services already run sagas.  PSPs already split
        authorize and capture.  Those roadmaps are complementary.  This
        document does not assert that any named orchestrator is unsafe,
        incomplete, or required to implement prepare.
      </t>
      <artwork type="ascii-art">
PSP authorize/capture   ~  prepare/commit at SETTLEMENT
Cloud workflow / saga   ~  coordinator + compensation graph
MCP tool chain          ~  children; often no_prepare
Agent runtime           ~  proposer of C, not the join
      </artwork>
      <t>
        A PSP capture API that already holds an authorization and voids it
        on timeout is already a prepare-capable SETTLEMENT sink under
        another name.  An MCP server that cannot reserve a Gmail send is a
        no_prepare TOOL_DISPATCH sink.  Putting both in one "strict"
        composite would be a mis-profile, not a vendor defect.
      </t>
      <t>
        Named companies are not claimed as reviewers, implementers, or
        endorsers.  Corrections and requests to remove a framing are
        invited.  Silence is not agreement.
      </t>
    </section>

    <section anchor="questions-community">
      <name>Questions to the IETF Community</name>
      <ol spacing="normal">
        <li>Is composite finality a separate document, or a section of the handle draft?</li>
        <li>Is ALL_REQUIRED the only join rule worth specifying?</li>
        <li>Must every prevention-profile child support prepare, or is "post last no_prepare sink" an acceptable prevention trick?</li>
        <li>Should reserve TTL default to abort or to hold-until-operator?</li>
        <li>Is compensation in scope here or a later draft?</li>
        <li>How should composite receipts nest child receipts without becoming a new transparency protocol?</li>
        <li>What prior art (XA, saga, TCC, TN, workflow) already closes this if child handles are added as resources?</li>
        <li>Should optional children be forbidden in v1 so that notify-later is always a new act?</li>
        <li>Which venue: DISPATCH, then none until handle lands?</li>
        <li>If a saga profile already forbids success-without-child-receipts and silent reuse of a consumed handle, should this draft shrink to CAD fields only?</li>
        <li>Is authorize/capture on existing rails accepted as prepare/commit, or must the wire names change?</li>
      </ol>
    </section>

    <section anchor="ietf-venues">
      <name>Potential IETF Discussion Venues</name>
      <t>This document does not claim that any named group should adopt the work.</t>
      <section anchor="venue-dispatch">
        <name>DISPATCH</name>
        <t>Natural first stop: the work spans payments, HTTP APIs, and agents.</t>
      </section>
      <section anchor="venue-oauth">
        <name>OAuth</name>
        <t>Relevant only if child handles are token profiles.  OAuth should not own actuation join.</t>
      </section>
      <section anchor="venue-wimse">
        <name>WIMSE</name>
        <t>Relevant if child actors are workloads on different hops.  Workload identity is not composite join.</t>
      </section>
      <section anchor="venue-rats">
        <name>RATS</name>
        <t>Relevant if a child CAD includes environment currentness.  Attestation is not prepare.</t>
      </section>
      <section anchor="venue-httpapi">
        <name>HTTPAPI</name>
        <t>Relevant to coordinator HTTP resources and problem+json mapping of EF-044 / COMPENSATING.</t>
      </section>
      <section anchor="venue-scitt">
        <name>SCITT</name>
        <t>Relevant to logging composite receipts.  Not the commit protocol.</t>
      </section>
      <section anchor="venue-saag">
        <name>SAAG</name>
        <t>Useful for whether all-or-none across administrative domains is in scope for the IETF at all.</t>
      </section>
      <section anchor="venue-no-home">
        <name>No Presumed Home</name>
        <t>Individual -00.  No IANA request in this revision beyond codes already reserved in <xref target="DAS-REG"/>.</t>
      </section>
    </section>

    <section anchor="related-drafts">
      <name>Relationship to Other Execution-Finality Internet-Drafts</name>
      <t>
        This draft sits above the handle and the registries.  It does not
        replace predicate or domain drafts.
      </t>
      <artwork type="ascii-art">
DAS-PROTOCOL      architecture
DAS-HANDLE        authority at ONE sink
DAS-REG           COMPOSITE class/type, EF-044
this document     join of N handle-using sinks
DAS-PATH          every child path must still be covered
DAS-STATE         generations still current at commit
DAS-REVOCATION    a child handle can be withdrawn before commit
DAS-JURISDICTION  each child JEC may differ; join must see that
DAS-PURPOSE       live purpose of C and of each child
DAS-AGENTIC       tool chain is often the composite proposer

Still not this draft:
    delegation warrant
    break-glass override
      </artwork>
      <t>
        See <xref target="DAS-HANDLE"/>, <xref target="DAS-REG"/>,
        <xref target="DAS-PROTOCOL"/>, <xref target="DAS-PATH"/>,
        <xref target="DAS-STATE"/>, <xref target="DAS-REVOCATION"/>,
        <xref target="DAS-JURISDICTION"/>, <xref target="DAS-PURPOSE"/>,
        and <xref target="DAS-AGENTIC"/>.
      </t>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      <t>
        Coordinator compromise is not child-sink compromise, but a malicious
        coordinator can withhold abort and leave reserves hanging.  Child
        sinks MUST expire reserves fail-closed.  Treating a coordinator
        signature as a settlement receipt recreates bearer authority at the
        wrong layer.  Quorum join on financial or physical children is a
        safety bug, not an availability feature.
      </t>
    </section>

    <section anchor="privacy">
      <name>Privacy Considerations</name>
      <t>
        A composite CAD lists every child destination.  That list can reveal
        a payment, a patient-adjacent system, and a mail target together.
        Coordinators SHOULD store child digests and sink ids, and SHOULD
        omit raw arguments from composite receipts sent off-path.
      </t>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>
        This version does not request IANA action.  It uses
        <tt>COMPOSITE</tt>, <tt>EF-044</tt>, and profile names already
        proposed in <xref target="DAS-REG"/>.  A later revision MAY add
        <tt>ef-composite-strict</tt> and <tt>ef-composite-mitigation</tt>
        to the profile registry.
      </t>
    </section>

    <section anchor="review-request">
      <name>Criticism, Corrections, and Review Invited</name>
      <t>
        The most useful criticism is that XA plus per-resource handles
        already yields this join, or that mitigation sagas are the only
        honest Internet profile.  Either result should shrink the draft.
        Named-product corrections are welcome.  Silence is not endorsement.
      </t>
    </section>

    <section anchor="conclusion">
      <name>Conclusion</name>
      <t>
        Local handle correctness at each sink does not make a multi-sink
        intent final.  C is effectuated only when every required child is
        effectuated under handles bound to C.  If a required child cannot
        prepare, the honest claim is mitigation plus a later compensation
        act — not all-or-none prevention.
      </t>
      <artwork type="ascii-art">
CHILD POST
      !=
COMPOSITE FINALITY

SAGA COMPENSATION
      !=
THE ORIGINAL ACT SUCCEEDED

PREPARE ALL REQUIRED
  or
DO NOT CLAIM PREVENTION
      </artwork>
    </section>
  </middle>

  <back>
    <references>
      <name>Normative References</name>
      <reference anchor="RFC2119" target="https://www.rfc-editor.org/rfc/rfc2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="Scott Bradner" initials="S." surname="Bradner"/>
          <date year="1997" month="March"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
      </reference>
      <reference anchor="RFC8174" target="https://www.rfc-editor.org/rfc/rfc8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="Barry Leiba" initials="B." surname="Leiba"/>
          <date year="2017" month="May"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
      </reference>
    </references>
    <references>
      <name>Informative References</name>
      <reference anchor="DAS-HANDLE">
        <front>
          <title>Possession Is Not Authority: Execution Handle, Sink Verification, Atomic Consumption, and Finality Receipt</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-execution-handle-00"/>
      </reference>
      <reference anchor="DAS-REG">
        <front>
          <title>Illustrative Codes Are Not a Namespace: Registries for Execution-Finality Objects</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-ef-registries-00"/>
      </reference>

      <reference anchor="DAS-PROTOCOL" target="https://datatracker.ietf.org/doc/draft-das-execution-finality-protocol-layer/">
        <front>
          <title>The Missing Protocol Layer for the Agentic Internet: Computation Is Not Authority</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-execution-finality-protocol-layer-01"/>
      </reference>

      <reference anchor="DAS-PATH">
        <front>
          <title>Consequence-Path Completeness for Execution Finality</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-consequence-path-completeness-00"/>
      </reference>

      <reference anchor="DAS-STATE">
        <front>
          <title>When Valid Authorization Becomes Stale: State and Policy Continuity at the Execution-Finality Boundary</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-state-policy-continuity-finality-00"/>
      </reference>

      <reference anchor="DAS-REVOCATION">
        <front>
          <title>Revoked but Still Executable: Closing the Authorization-to-Effect Gap with Finality-Bound Revocation</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-finality-bound-revocation-00"/>
      </reference>

      <reference anchor="DAS-JURISDICTION">
        <front>
          <title>Authorized Here, Not Authorized There: Jurisdiction-Bound Execution Finality for Cross-Border and Sovereign Systems</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-jurisdiction-bound-execution-finality-00"/>
      </reference>

      <reference anchor="DAS-PURPOSE">
        <front>
          <title>Purpose-Bound Execution Finality</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-purpose-execution-finality-00"/>
      </reference>

      <reference anchor="DAS-AGENTIC">
        <front>
          <title>Agentic Execution Finality</title>
          <author fullname="Sangam Das" initials="S." surname="Das"/>
          <date year="2026" month="September"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-das-agentic-execution-finality-00"/>
      </reference>
    </references>
  </back>
</rfc>
