Skip to main content

Partial Commit Is Not Finality: Composite Candidate Acts Across Multiple Finality Sinks
draft-das-composite-execution-finality-01

Document Type Active Internet-Draft (individual)
Author Sangam Das
Last updated 2026-09-18 (Latest revision 2026-09-16)
RFC stream (None)
Intended RFC status (None)
Formats
Additional resources GitHub - Composite Execution Finality — Runnable reference implementation
The Internet Solved Communication. It Never Solved Authority
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-das-composite-execution-finality-01
Individual Submission                                             S. Das
Internet-Draft                                               Independent
Intended status: Informational                         16 September 2026
Expires: 20 March 2027

Partial Commit Is Not Finality: Composite Candidate Acts Across Multiple
                             Finality Sinks
               draft-das-composite-execution-finality-01

Abstract

   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.  [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.

   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.

   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.

   The join is closed by a durable, linearizable Composite Decision Log
   holding one value per composite: empty, COMMIT, or ABORT, written
   only by compare-and-swap so that the first writer wins.  The
   coordinator MUST win the log before sending a decision to any child.
   A prepared child whose reservation timer expires MUST consult the
   log: it commits if COMMIT is recorded, releases if ABORT is recorded,
   attempts its own compare-and-swap of ABORT if the log is empty, and
   holds its reservation (HOLD) only if the log is unreachable.  No
   child acts on silence alone.

Das                       Expires 20 March 2027                 [Page 1]
Internet-Draft        Composite Execution Finality        September 2026

   This is not a new consensus protocol and not a claim that XA is
   obsolete.  Profiles that cannot obtain prepare-from-every-sink, or
   cannot reach a durable linearizable decision log, MUST NOT claim all-
   or-none prevention.

   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.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 20 March 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Das                       Expires 20 March 2027                 [Page 2]
Internet-Draft        Composite Execution Finality        September 2026

Table of Contents

   1.  What This Version (-01) Contains  . . . . . . . . . . . . . .   4
     1.1.  Contents of -01 . . . . . . . . . . . . . . . . . . . . .   4
     1.2.  Changes from -00  . . . . . . . . . . . . . . . . . . . .   5
   2.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   6
     2.1.  Vulnerability: One Intent, Split Reality  . . . . . . . .   6
     2.2.  Existing Mechanisms Already Coordinate Steps  . . . . . .   6
     2.3.  Residual Gap After a Single-Sink Handle . . . . . . . . .   7
     2.4.  What This Document Introduces . . . . . . . . . . . . . .   7
   3.  Conventions and Requirements Language . . . . . . . . . . . .   7
   4.  Direct Question . . . . . . . . . . . . . . . . . . . . . . .   7
   5.  Motivating Scenario: Pay, Book, Notify  . . . . . . . . . . .   8
   6.  Threat Model  . . . . . . . . . . . . . . . . . . . . . . . .   8
   7.  Goals and Non-Goals . . . . . . . . . . . . . . . . . . . . .   8
   8.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   9
   9.  Composite Objects . . . . . . . . . . . . . . . . . . . . . .   9
     9.1.  Composite CAD . . . . . . . . . . . . . . . . . . . . . .   9
     9.2.  Child Handles . . . . . . . . . . . . . . . . . . . . . .  10
     9.3.  Composite Handle  . . . . . . . . . . . . . . . . . . . .  11
   10. Composite State Machine . . . . . . . . . . . . . . . . . . .  11
   11. Prepare, Commit, Abort  . . . . . . . . . . . . . . . . . . .  12
     11.1.  Phase 0: Reconstruct Each Child  . . . . . . . . . . . .  13
     11.2.  Phase 1: Prepare . . . . . . . . . . . . . . . . . . . .  13
     11.3.  Phase 2: Commit or Abort . . . . . . . . . . . . . . . .  13
   12. Join Rules  . . . . . . . . . . . . . . . . . . . . . . . . .  14
   13. Compensation Is a New Act . . . . . . . . . . . . . . . . . .  15
   14. Coordinator Rules . . . . . . . . . . . . . . . . . . . . . .  15
   15. Timeouts, Crash, and Child CAS Abort  . . . . . . . . . . . .  16
   16. Formal Join . . . . . . . . . . . . . . . . . . . . . . . . .  18
   17. Safety, Closure, and Termination  . . . . . . . . . . . . . .  19
     17.1.  Decision-Log Axioms  . . . . . . . . . . . . . . . . . .  19
     17.2.  Child Action Invariants  . . . . . . . . . . . . . . . .  20
     17.3.  No-Split Theorem . . . . . . . . . . . . . . . . . . . .  20
     17.4.  Closure Theorem  . . . . . . . . . . . . . . . . . . . .  21
     17.5.  Termination Bounds . . . . . . . . . . . . . . . . . . .  21
     17.6.  Finality Point and Currentness . . . . . . . . . . . . .  22
     17.7.  Compensation Is Distinct from C  . . . . . . . . . . . .  22
   18. Illustrative Pseudocode . . . . . . . . . . . . . . . . . . .  22
   19. Composition with Existing Tools . . . . . . . . . . . . . . .  23
   20. Profiles  . . . . . . . . . . . . . . . . . . . . . . . . . .  24
   21. Anticipated Criticisms  . . . . . . . . . . . . . . . . . . .  24
     21.1.  Objection: Saga Plus Handle Is Enough  . . . . . . . . .  24
     21.2.  Objection: Prepare Across N Sinks Is a Latency Tax . . .  25
     21.3.  Objection: Each Child Cannot Reconstruct a Unified
            CAD  . . . . . . . . . . . . . . . . . . . . . . . . . .  25
     21.4.  What Would Settle the Argument . . . . . . . . . . . . .  26
   22. Industrial Relevance and Public-Roadmap Alignment . . . . . .  26

Das                       Expires 20 March 2027                 [Page 3]
Internet-Draft        Composite Execution Finality        September 2026

   23. Questions to the IETF Community . . . . . . . . . . . . . . .  26
   24. Potential IETF Discussion Venues  . . . . . . . . . . . . . .  27
     24.1.  DISPATCH . . . . . . . . . . . . . . . . . . . . . . . .  27
     24.2.  OAuth  . . . . . . . . . . . . . . . . . . . . . . . . .  27
     24.3.  WIMSE  . . . . . . . . . . . . . . . . . . . . . . . . .  28
     24.4.  RATS . . . . . . . . . . . . . . . . . . . . . . . . . .  28
     24.5.  HTTPAPI  . . . . . . . . . . . . . . . . . . . . . . . .  28
     24.6.  SCITT  . . . . . . . . . . . . . . . . . . . . . . . . .  28
     24.7.  SAAG . . . . . . . . . . . . . . . . . . . . . . . . . .  28
     24.8.  No Presumed Home . . . . . . . . . . . . . . . . . . . .  28
   25. Relationship to Other Execution-Finality Internet-Drafts  . .  28
   26. Security Considerations . . . . . . . . . . . . . . . . . . .  29
   27. Privacy Considerations  . . . . . . . . . . . . . . . . . . .  30
   28. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  30
   29. Criticism, Corrections, and Review Invited  . . . . . . . . .  30
   30. Conclusion  . . . . . . . . . . . . . . . . . . . . . . . . .  30
   31. Normative References  . . . . . . . . . . . . . . . . . . . .  30
   32. Informative References  . . . . . . . . . . . . . . . . . . .  31
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  32

1.  What This Version (-01) Contains

   This Internet-Draft is draft-das-composite-execution-finality-01.  It
   specifies how several handle-using sinks join as one Composite
   Candidate Act: child handles, prepare/commit/abort, ALL_REQUIRED
   prevention, and compensation as a new act.  Single-sink objects
   remain in [DAS-HANDLE]; code points remain in [DAS-REG].

1.1.  Contents of -01

   *  Problem of split reality (one child posts, another rejects) after
      a locally correct handle.

   *  Composite CAD, child handles bound to composite_id, coordinator
      rules.

   *  Prepare/commit/abort, join rules, and the mitigation profile for
      no_prepare sinks.

   *  2PC timeout incompatibility resolved by a compare-and-swap
      Composite Decision Log: child CAS ABORT on an empty log, HOLD only
      when the log is unreachable, EF-047 for a discovered split.

   *  Formal join identities and pointer to the handle-draft hash / TLA+
      embedding.

   *  Anticipated criticisms (saga plus handle, latency, reconstruction)
      and abstract hints.

Das                       Expires 20 March 2027                 [Page 4]
Internet-Draft        Composite Execution Finality        September 2026

   *  Industrial disclaimer, community questions, and IETF venue
      mapping.

1.2.  Changes from -00

   *  Document name and series info updated to -01.

   *  Abstract names saga, performance, and reconstruction objections,
      and states the decision-log rule.

   *  Added the Composite Decision Log: durable, linearizable, written
      only by compare-and-swap (first writer wins).  The coordinator
      wins the log before sending any decision.

   *  A prepared child whose reservation timer expires consults the log:
      COMMIT commits, ABORT releases, an empty log allows the child to
      CAS ABORT, and an unreachable log leads to HOLD (EF-048).  This
      removes the -00 partial-commit path and prevents indefinite
      blocking when the coordinator dies before deciding.

   *  Coordinator abort that loses the CAS to COMMIT re-drives commit
      instead of aborting.

   *  Coordinator re-checks EH_C currentness immediately before writing
      COMMIT.

   *  After COMMIT is recorded, child commits are retried to a terminal
      state; only a child that cannot post yields COMPENSATING with EF-
      047.

   *  The same rule is applied consistently in the state machine, Phase
      2, coordinator rules, timeouts, formal join, PreventionWellFormed,
      pseudocode, profiles, questions, venues, security, and IANA
      sections.

   *  ABORTED includes a deliberate coordinator abort, always via the
      log.

   *  Partial commit uses EF-047, not EF-044.

   *  Security Considerations adds decision-log integrity and
      availability as trusted computing base, and child-forced abort as
      a liveness (not safety) attack.

   *  Family references aligned to current titles, revisions, and
      Datatracker URLs; handle and registries cited as -01.

Das                       Expires 20 March 2027                 [Page 5]
Internet-Draft        Composite Execution Finality        September 2026

   *  Split(C,t) refined so that the normal in-progress window after
      COMMIT is Closing(C,t) and COMMIT_DECIDED, not COMPENSATING.

   *  Child handles bind composite_digest = d(C), a digest over the
      sorted child list, not only composite_id.

   *  Added Safety, Closure, and Termination: decision-log axioms, child
      action invariants, No-Split theorem with proof, Closure theorem
      with its separate assumptions, termination bounds, the finality
      point and currentness condition, and compensation identities.

2.  Introduction

2.1.  Vulnerability: One Intent, Split Reality

   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.

   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

        Figure 1: Child S1 commits; child S2 never becomes effective

2.2.  Existing Mechanisms Already Coordinate Steps

   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.

Das                       Expires 20 March 2027                 [Page 6]
Internet-Draft        Composite Execution Finality        September 2026

2.3.  Residual Gap After a Single-Sink Handle

   [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 COMPOSITE as a class and a sink type
   [DAS-REG].  They do not specify the protocol.

2.4.  What This Document Introduces

   *  Composite CAD with an ordered, explicit child list and a composite
      Act Digest.

   *  One child Execution Handle per required sink, all bound to the
      same composite id.

   *  Prepare / commit / abort on consume-state, with fail-closed
      defaults.

   *  A coordinator role that cannot substitute for child sinks.

   *  Compensation as a new Candidate Act, not a hidden reverse of the
      original handle.

3.  Conventions and Requirements Language

   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 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals.

4.  Direct Question

   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?

   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.

   That last sentence is the operational cost.  If a profile cannot
   prevent the child post, it must not advertise all-or-none prevention.

Das                       Expires 20 March 2027                 [Page 7]
Internet-Draft        Composite Execution Finality        September 2026

5.  Motivating Scenario: Pay, Book, Notify

   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.

   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

           Figure 2: Why retry-later is a different Candidate Act

6.  Threat Model

   The attacker need not forge handles.  Relevant failures:

   *  Child reordering so an optional notify is treated as required, or
      the reverse.

   *  Coordinator crash after S1 prepare and before S2 prepare.

   *  S2 commit of a mutated child CAD under the same composite id.

   *  Calling compensation on S1 without a new handle.

   *  Declaring success from the coordinator receipt while a required
      child is still PENDING.

   *  Using a saga log as proof that no child effect exists.

7.  Goals and Non-Goals

   Goal: define when a multi-sink Candidate Act may be called
   EFFECTUATED, PREPARED, ABORTED, or COMPENSATING, using the objects in
   [DAS-HANDLE].

   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.

Das                       Expires 20 March 2027                 [Page 8]
Internet-Draft        Composite Execution Finality        September 2026

8.  Terminology

   *Composite Candidate Act (C):* A Candidate Act whose intended
   consequence is the conjunction of two or more child consequences.

   *Child Act C_i:* The component that one sink would effectuate.

   *Required child:* A child that MUST reach EFFECTUATED for C to reach
   EFFECTUATED.

   *Optional child:* 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.

   *Coordinator:* The component that records composite state.  It is not
   a Finality Sink for a child effect unless it is also that child's
   sink.

   *Prepare:* Child sink has verified the live child act, reserved
   consume-state, and promises not to post until the Composite Decision
   Log records COMMIT, and not to release until it records ABORT.

   *Composite Decision Log (CDL):* A durable, linearizable register
   holding one value per composite identifier: empty, COMMIT, or ABORT.
   Its only write operation is CAS(C, empty -> v).  The first successful
   write is final; every later write fails and returns the recorded
   value.  The coordinator and every prepared required child can read it
   and attempt the write.  "Queryable" is not sufficient: an eventually
   consistent store cannot provide first-writer-wins.

   *HOLD:* The child-local state of a prepared child that cannot read or
   write the CDL.  A child in HOLD produces no external effect and keeps
   its reservation.

   *Compensation act:* A new Candidate Act that would reverse or contain
   a child effect that already escaped.  It uses a new handle.

9.  Composite Objects

9.1.  Composite CAD

   A composite CAD is a CAD whose consequence_class and coordinator
   sink_type are COMPOSITE [DAS-REG].  It MUST list children explicitly.

Das                       Expires 20 March 2027                 [Page 9]
Internet-Draft        Composite Execution Finality        September 2026

   composite_cad = {
     candidate_act_id,
     composite_act_digest,     // d(C), see below
     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.

   The composite Act Digest binds the whole child list, not only an
   identifier.  Children are sorted by child_id before canonicalization
   so that the digest does not depend on presentation order.

   d(C) = Hash( Canon( join_rule,
            sort_by_id[ (id_i, d(C_i), S_i, required_i) ]
            for all children i ) )

   Hash and Canon are those of [DAS-HANDLE].  Adding, removing,
   reordering-as-required, or substituting a child changes d(C).

9.2.  Child Handles

   Each required child has its own Execution Handle EH_i issued by the
   PED.  EH_i MUST bind:

   *  act_digest of child CAD_i

   *  sink_id of S_i

   *  composite_id = C.candidate_act_id

   *  composite_digest = d(C), the composite Act Digest

   *  reuse_policy compatible with the child class

Das                       Expires 20 March 2027                [Page 10]
Internet-Draft        Composite Execution Finality        September 2026

   A child handle MUST NOT be accepted at a sink whose consume would not
   serve that composite_id and composite_digest.  Binding only
   composite_id is insufficient: an attacker who can alter the child
   list while keeping the identifier would otherwise obtain child
   handles that still match.  Presenting EH_i for a standalone payment
   that is not C is EF-023 or EF-040 [DAS-REG].

9.3.  Composite Handle

   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.

10.  Composite State Machine

Das                       Expires 20 March 2027                [Page 11]
Internet-Draft        Composite Execution Finality        September 2026

                    issue
                      |
                      v
                 NON_EFFECTIVE
                      |
                 children verify
                      v
                   PREPARED --- CDL CAS ABORT wins ---> ABORTED
                      |       (coordinator or child)
                 CDL CAS COMMIT wins
                      v
                 COMMIT_DECIDED
                      |
                 every required child driven to commit
                      v
                 EFFECTUATED

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

   Prevention profile forbids entering COMPENSATING
   because a required child posted before join.

   Child-local, on reservation timer:
     CDL = COMMIT        --> commit        (EFFECTUATED)
     CDL = ABORT         --> release       (RELEASED)
     CDL = empty         --> CAS ABORT
                              won  --> release
                              lost --> commit (COMMIT won)
     CDL unreachable     --> HOLD, no post, EF-048
     HOLD, CDL readable  --> re-evaluate as above

           Figure 3: States of C, distinct from child sink states

   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.

11.  Prepare, Commit, Abort

Das                       Expires 20 March 2027                [Page 12]
Internet-Draft        Composite Execution Finality        September 2026

11.1.  Phase 0: Reconstruct Each Child

   Each S_i MUST reconstruct live child CAD_i from the pending local
   effect, not from a coordinator-supplied blob alone [DAS-HANDLE].
   Coordinator-supplied CAD_i is a hint.  Digest mismatch is EF-023.

11.2.  Phase 1: Prepare

   Prepare is consume-state reservation without external effect.

   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:
               Coordinator.abort(C)   // via the CDL

   A sink that cannot reserve without posting (typical third-party mail
   or card API) MUST be declared no_prepare=true.  A composite that
   includes a required no_prepare sink MUST NOT use the prevention
   profile.  It MAY use mitigation: post last, or accept COMPENSATING.

11.3.  Phase 2: Commit or Abort

Das                       Expires 20 March 2027                [Page 13]
Internet-Draft        Composite Execution Finality        September 2026

   Coordinator.commit(C):
       require all required children PREPARED
       require EH_C still current          // checked immediately
                                           // before the CAS
       v = CDL.CAS(C, empty -> COMMIT)
       if v == ABORT:                      // a child TTL or an
           release_all_prepared(C)         // earlier abort won
           C = ABORTED
           return
       C = COMMIT_DECIDED                  // point of no return
       for each required S_i:
           r = retry_until_terminal(S_i.commit, EH_i)
           // a PREPARED child promised to post; transient
           // failure is retried, never treated as abort
       if all required EFFECTUATED:
           C = EFFECTUATED
           emit composite receipt
       else:
           // reachable only if a prepared sink cannot post
           // (broken promise, sink destroyed, legal stop)
           C = COMPENSATING                // EF-047

   Coordinator.abort(C):
       v = CDL.CAS(C, empty -> ABORT)
       if v == COMMIT:                     // lost to an earlier
           Coordinator.commit_redrive(C)   // COMMIT: do not abort
           return
       for each PREPARED S_i:
           S_i.abort(EH_i)                 // RELEASED, no post
       C = ABORTED

   The composite finality point is the successful CAS of COMMIT, not the
   first child post.  Child currentness (generations, revocation) is
   evaluated inside each child's serialized prepare section
   [DAS-HANDLE], and EH_C currentness is re-checked immediately before
   the CAS.  A revocation that arrives after COMMIT is recorded applies
   to an act that is already final; it is handled by a new compensation
   act (Section 13), not by releasing a child that the log says must
   commit.

12.  Join Rules

    +===================+====================+========================+
    | Rule              | C EFFECTUATED when | Prevention claim       |
    +===================+====================+========================+
    | ALL_REQUIRED      | every required     | Yes, if every required |
    |                   | child EFFECTUATED  | sink supports prepare  |
    +-------------------+--------------------+------------------------+

Das                       Expires 20 March 2027                [Page 14]
Internet-Draft        Composite Execution Finality        September 2026

    | ALL_THEN_OPTIONAL | required set       | Only over the required |
    |                   | EFFECTUATED;       | set                    |
    |                   | optional attempted |                        |
    +-------------------+--------------------+------------------------+
    | QUORUM(k)         | any k children     | No for high-           |
    |                   |                    | consequence classes    |
    +-------------------+--------------------+------------------------+
    | BEST_EFFORT       | coordinator tried  | Never                  |
    +-------------------+--------------------+------------------------+

         Table 1: Join rules and whether prevention may be claimed

13.  Compensation Is a New Act

   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.

   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

      Figure 4: Compensation does not reuse the original child handle

   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.

14.  Coordinator Rules

   *  The coordinator MUST NOT post a child effect itself unless it is
      that child's sink.

   *  The coordinator MUST win CDL.CAS(C, empty -> COMMIT) or CDL.CAS(C,
      empty -> ABORT) before sending that decision to any child.
      Prepare messages are sent before any decision exists.

Das                       Expires 20 March 2027                [Page 15]
Internet-Draft        Composite Execution Finality        September 2026

   *  After crash, the coordinator MUST read the CDL first, then query
      child receipts; it MUST NOT assume commit or abort.  If the CDL
      records COMMIT, it MUST re-drive commit to every required child
      not yet EFFECTUATED.  If the CDL is empty, it MAY write ABORT.

   *  A coordinator whose abort CAS loses to COMMIT MUST re-drive commit
      and MUST NOT send abort.

   *  A coordinator receipt without child receipts is not evidence that
      C effectuated.

   *  The coordinator SHOULD be identifiable as sink type COMPOSITE in
      the registry sense only: it joins, it does not replace SETTLEMENT
      or ACTUATION.

15.  Timeouts, Crash, and Child CAS Abort

   Classic two-phase commit is blocking.  The following two rules cannot
   both hold in a prevention profile:

   1.  A PREPARED child whose reserve TTL expires aborts locally without
       asking anyone.

   2.  After the coordinator has decided COMMIT, no required child may
       abort.

   If the coordinator writes COMMIT, S1 posts, and then dies before S2
   hears COMMIT, S2's local TTL abort produces the partial commit this
   draft called unreachable.  That path is reachable unless children
   consult a durable decision before acting on a timer.

   A log that children can only query is not enough on its own.  If the
   coordinator dies before deciding, every child reads an empty log and
   cannot safely release, because the coordinator might still write
   COMMIT.  Every child would then block.  The CDL removes that case: a
   child may itself write ABORT into an empty log, and because the write
   is compare-and-swap, the coordinator can no longer write COMMIT
   afterwards.  HOLD is reserved for the case where the log itself is
   unreachable.

Das                       Expires 20 March 2027                [Page 16]
Internet-Draft        Composite Execution Finality        September 2026

   Forbidden pair (prevention profile):
       coordinator.decision == COMMIT
           AND
       some required child locally ABORTS on TTL

   Required instead:
       coordinator wins CDL.CAS before sending
           COMMIT or ABORT to any child
       child reservation timer fires
           -> read CDL[C]
           -> COMMIT:      commit locally
           -> ABORT:       release (RELEASED)
           -> empty:       CAS(C, empty -> ABORT)
                             won:  release
                             lost: commit
           -> unreachable: HOLD, no post, EF-048
                           retry the log; alert operator

   Dead coordinator, no decision:
       first child timer writes ABORT
       composite ABORTED, no child posts

   Dead coordinator, COMMIT recorded:
       every child timer reads COMMIT
       composite closes

   If the deployment cannot provide a durable,
   linearizable CDL:
       it MUST NOT claim PreventionWellFormed
       it MAY use hold-until-operator
       it MUST treat a discovered split as
           C = COMPENSATING, reason EF-047

   Automatic commit on coordinator silence remains forbidden.  Automatic
   release on a child timer is forbidden unless the child's own CAS of
   ABORT succeeds or the log already records ABORT.  Timers trigger a
   decision attempt; they never substitute for a decision.  An operator
   resolution procedure, if a profile defines one, MUST itself write
   through CDL.CAS so that a manual decision cannot contradict an
   automatic one.  A child in HOLD SHOULD raise an operator alert; for
   sinks where a long-held reservation is itself harmful (for example a
   held payment authorization), the profile SHOULD document the maximum
   acceptable HOLD duration and the escalation path.

Das                       Expires 20 March 2027                [Page 17]
Internet-Draft        Composite Execution Finality        September 2026

16.  Formal Join

   Let C have required index set R.  Child i has handle H_i, sink S_i,
   live act C_i(t), and local state q_i(t).  The identities below are
   the same join as the prepare/commit pseudocode.  Child digests use
   the hash function of [DAS-HANDLE].  A TLA+ model of this join is
   well-formed only if COMMIT followed by child TTL cannot reach Split
   under PreventionWellFormed.

   Posted(C,t)   = { i in R | q_i(t) = EFFECTUATED }

   Effect(C,t)   iff  Posted(C,t) = R
                 and  forall i in R. d(C_i(t)) = H_i.d
                 and  forall i in R. H_i.composite_id = C.id
                 and  forall i in R. H_i.composite_digest = d(C)

   Abort(C,t)    iff  Posted(C,t) = empty
                 and  CDL(C) = ABORT

   Split(C,t)    iff  Posted(C,t) nonempty and Posted(C,t) != R
                 and  ( CDL(C) != COMMIT
                        or exists i in R. CannotPost(i,t) )
   Split(C,t)    =>   COMPENSATING with EF-047

   Closing(C,t)  iff  CDL(C) = COMMIT
                 and  Posted(C,t) nonempty and Posted(C,t) != R
                 and  forall i in R. not CannotPost(i,t)
   Closing(C,t)  =>   COMMIT_DECIDED (transient, not a split)

   reject, deadline, operator abort, or child timer
       => attempt CDL.CAS(C, empty -> ABORT)
          (never a direct transition to Abort)

   CDL(C) = COMMIT => no PREPARED child is released
   Timer:  COMMIT -> commit
           ABORT  -> release
           empty  -> CAS ABORT (won: release; lost: commit)
           unreachable -> HOLD

Das                       Expires 20 March 2027                [Page 18]
Internet-Draft        Composite Execution Finality        September 2026

   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 CDL(C) == ABORT

   C.COMMIT_DECIDED iff CDL(C) == COMMIT
                    AND Posted(C) != Required(C)
                    // transient: every required child
                    // is being driven to EFFECTUATED

   C.COMPENSATING  iff Posted(C) nonempty
                    AND Posted(C) != Required(C)
                    AND some required child can no longer post

   PreventionWellFormed(C) iff
       join_rule == ALL_REQUIRED
   AND every required S_i supports prepare
   AND no required S_i has no_prepare
   AND a durable, linearizable CDL is reachable
       by the coordinator and every required child
   AND no child releases or posts on a timer
       except as the CDL dictates

   PreventionWellFormed(C) == false
       ==> MUST NOT claim all-or-none prevention

17.  Safety, Closure, and Termination

   This section states the properties the join claims and the
   assumptions each property needs.  Safety (no split) depends only on
   the Composite Decision Log and child behaviour.  Closure (the
   composite eventually ends) additionally depends on sinks keeping the
   promise made at prepare and on fair re-drive.  The two claims are
   kept separate so that a deployment can state which one it provides.

17.1.  Decision-Log Axioms

   Notation: bot is the empty value; CDL(C,t) is the value recorded for
   C at time t; Read_x(C,t) is a read by party x.

Das                       Expires 20 March 2027                [Page 19]
Internet-Draft        Composite Execution Finality        September 2026

   A1 Stability:
        CDL(C,t) != bot
          =>  forall t' >= t.  CDL(C,t') = CDL(C,t)

   A2 Single value (linearizability):
        Read_x(C,t) = v  and  Read_y(C,t') = v'
        and  v != bot  and  v' != bot
          =>  v = v'

   A3 First writer wins:
        CAS_x(C, bot -> v) succeeds at t
          =>  CDL(C,t) = v  and  every later CAS fails
              and returns v

17.2.  Child Action Invariants

   I1  Post_i(t)
         =>  exists t0 <= t.  Read_i(C,t0) = COMMIT

   I2  Release_i(t)
         =>  exists t0 <= t.  Read_i(C,t0) = ABORT
                           or WonCAS_i(C, ABORT, t0)

   I3  Post_i(t)
         =>  Prepared_i(t_p)  with  t_p < t_dec
       where t_dec is the time of the successful
       CAS(C, bot -> COMMIT)

   I4  Hold_i(t)
         =>  not Post_i(t)  and  not Release_i(t)

17.3.  No-Split Theorem

   Theorem 1 (Safety).  Under A1, A2, A3, I1, I2:

       not exists i, j in R.
           Posted_i  and  Released_j

   Proof.
       Posted_i    =>  some party read COMMIT      (I1)
       Released_j  =>  some party read ABORT
                       or won CAS ABORT            (I2, A3)
       A1 and A2 forbid the log holding both
       COMMIT and ABORT for C.
       Hence no execution has both.               QED

Das                       Expires 20 March 2027                [Page 20]
Internet-Draft        Composite Execution Finality        September 2026

   Theorem 1 does not require the coordinator to be correct, alive, or
   honest.  It requires only that the log satisfies A1 to A3 and that
   every required child obeys I1 and I2.

17.4.  Closure Theorem

   A4 Promise kept:
        CDL(C) = COMMIT  =>  forall i in R.  not CannotPost(i)

   A5 Weak fairness:
        a party that can re-drive commit, or retry a
        reachable log, eventually does so

   A6 Log eventually reachable:
        <>[] Reachable(CDL)

   Theorem 2 (Closure).  Under Theorem 1, A4, A5, A6:

       <>( Effect(C)  or  Abort(C) )

   Sketch.
       If CDL(C) stays bot, the first expiring child
       timer writes ABORT once the log is reachable
       (A5, A6), so Abort(C).
       If CDL(C) = COMMIT, every required child is
       driven to Post (A4, A5), so Effect(C).
       By A1 exactly one branch applies.           QED

   If A4 fails for some child (a prepared sink is destroyed, or a legal
   stop prevents posting), Theorem 1 still holds for all other children
   but the composite enters COMPENSATING with EF-047.  That case is a
   broken prepare promise, not a protocol split.

17.5.  Termination Bounds

   Coordinator dead before deciding, log reachable:
       T_abort  <=  min_i TTL_i  +  delta_cas

   HOLD duration for child i:
       T_hold(i)  <=  T_unreach(CDL)  +  TTL_i  +  delta_cas

   Commit completion after t_dec, with at most k
   retries per child and per-attempt time delta_post:
       T_close  <=  t_dec  +  |R| * k * delta_post
                (sequential; parallel re-drive gives
                 max_i instead of the sum)

Das                       Expires 20 March 2027                [Page 21]
Internet-Draft        Composite Execution Finality        September 2026

   T_unreach(CDL) is outside the protocol.  It is why log availability
   belongs to the trusted computing base and why a profile SHOULD state
   a maximum acceptable HOLD duration.

17.6.  Finality Point and Currentness

   t_prep_i  = time child i entered PREPARED
   t_dec     = time of successful CAS(C, bot -> COMMIT)

   Effect(C)
       =>  forall i in R.  Current(H_i.g, t_prep_i)
       and Current(EH_C.g, t_dec)
       and t_dec >= max_i t_prep_i

   Revoked(H_i, t)  with  t > t_dec
       =>  handled by a compensation act C'
           not by releasing child i

17.7.  Compensation Is Distinct from C

   Effect(C')  does not imply  Effect(C)

   Contained(C)  iff  Split(C)
                 and  Effect(C')
                 and  C'.parent = C.id
                 and  C'.handle != any H_i

   Failed containment:
       Split(C) and not Effect(C')  =>  UNKNOWN

18.  Illustrative Pseudocode

   function effectuate_composite(C, handles, cdl):
       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, C.id)
           if r.decision != "PREPARED":
               return abort_via_log(C, prepared, cdl, r.reason_code)
           prepared.append(child)

       if not ehc_current(C):                   # re-check before CAS
           return abort_via_log(C, prepared, cdl, "EF-041")

       if cdl.cas(C.id, EMPTY, COMMIT) == ABORT:

Das                       Expires 20 March 2027                [Page 22]
Internet-Draft        Composite Execution Finality        September 2026

           release_all(prepared)                # a child timer won
           return receipt(C, "ABORTED", "EF-048")

       for child in required(C):                # point of no return
           r = retry_until_terminal(child.sink.commit, handles[child])
           if r.decision != "EFFECTUATED":
               return receipt(C, "COMPENSATING", "EF-047")

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

   function abort_via_log(C, prepared, cdl, code):
       if cdl.cas(C.id, EMPTY, ABORT) == COMMIT:
           return redrive_commit(C)             # too late to abort
       release_all(prepared)
       return receipt(C, "ABORTED", code)

   function child_on_reservation_timer(child, C_id, cdl):
       try:
           v = cdl.read(C_id)
           if v == EMPTY:
               v = cdl.cas(C_id, EMPTY, ABORT)  # returns final value
       except Unreachable:
           child.state = HOLD                   # no post, keep reserve
           alert_operator(C_id)
           return report("EF-048")
       if v == ABORT:
           child.release()                      # RELEASED
       else:
           child.commit()                       # COMMIT is final

   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)

19.  Composition with Existing Tools

      +===============+==================+=========================+
      | Existing tool | Supplies         | Still required          |
      +===============+==================+=========================+
      | XA / 2PC      | Prepare/commit   | Child Act Digest +      |
      |               | wire to RMs      | handle bind             |
      +---------------+------------------+-------------------------+
      | Saga / TCC    | Forward +        | Compensation as new     |
      |               | compensate graph | handle; no silent undo  |

Das                       Expires 20 March 2027                [Page 23]
Internet-Draft        Composite Execution Finality        September 2026

      +---------------+------------------+-------------------------+
      | Outbox /      | Ordered jobs,    | Retries are new         |
      | workflow      | retries          | attempts, not C success |
      +---------------+------------------+-------------------------+
      | SCITT         | Logged composite | Log is not child commit |
      |               | receipt          |                         |
      +---------------+------------------+-------------------------+
      | Single-sink   | Local authority  | This join               |
      | handle        |                  |                         |
      +---------------+------------------+-------------------------+

        Table 2: What existing coordinators supply versus what is
                              still required

20.  Profiles

   ef-composite-strict: ALL_REQUIRED, every required sink supports
   prepare, a durable linearizable Composite Decision Log written only
   by compare-and-swap, child timers act only through that log (CAS
   ABORT if empty, HOLD if unreachable), compensation is a new act,
   coordinator receipt insufficient.

   ef-composite-mitigation: at least one required sink is no_prepare, or
   no durable linearizable decision log is available; document the
   escaped-effect window; MUST NOT claim prevention.

21.  Anticipated Criticisms

   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.

21.1.  Objection: Saga Plus Handle Is Enough

   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.

   The residual cases this draft still names:

   *  the saga logs SUCCESS after a required child posts and another
      required child rejects;

   *  compensation reuses the original child handle instead of a new
      reverse act;

Das                       Expires 20 March 2027                [Page 24]
Internet-Draft        Composite Execution Finality        September 2026

   *  a no_prepare child (mail, many MCP tools) is treated as if 2PC
      applied;

   *  the coordinator receipt is taken as proof that settlement
      occurred.

   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

   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.

21.2.  Objection: Prepare Across N Sinks Is a Latency Tax

   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.

   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.

21.3.  Objection: Each Child Cannot Reconstruct a Unified CAD

   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.

Das                       Expires 20 March 2027                [Page 25]
Internet-Draft        Composite Execution Finality        September 2026

   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.

21.4.  What Would Settle the Argument

   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.

22.  Industrial Relevance and Public-Roadmap Alignment

   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.

   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

   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.

   Named companies are not claimed as reviewers, implementers, or
   endorsers.  Corrections and requests to remove a framing are invited.
   Silence is not agreement.

23.  Questions to the IETF Community

   1.   Is composite finality a separate document, or a section of the
        handle draft?

   2.   Is ALL_REQUIRED the only join rule worth specifying?

   3.   Must every prevention-profile child support prepare, or is "post
        last no_prepare sink" an acceptable prevention trick?

Das                       Expires 20 March 2027                [Page 26]
Internet-Draft        Composite Execution Finality        September 2026

   4.   Is child compare-and-swap of ABORT into an empty decision log
        the right reservation-timer default, with HOLD only when the log
        is unreachable?

   5.   For sinks where a held reservation is itself harmful, should the
        profile define a maximum HOLD duration that ends in an operator
        decision written through the log?

   6.   Should the Composite Decision Log be a named wire object with a
        media type, or remain an abstract linearizable register?

   7.   Is compensation in scope here or a later draft?

   8.   How should composite receipts nest child receipts without
        becoming a new transparency protocol?

   9.   What prior art (XA, saga, TCC, TN, workflow) already closes this
        if child handles are added as resources?

   10.  Should optional children be forbidden in v1 so that notify-later
        is always a new act?

   11.  Which venue: DISPATCH, then none until handle lands?

   12.  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?

   13.  Is authorize/capture on existing rails accepted as prepare/
        commit, or must the wire names change?

24.  Potential IETF Discussion Venues

   This document does not claim that any named group should adopt the
   work.

24.1.  DISPATCH

   Natural first stop: the work spans payments, HTTP APIs, and agents.

24.2.  OAuth

   Relevant only if child handles are token profiles.  OAuth should not
   own actuation join.

Das                       Expires 20 March 2027                [Page 27]
Internet-Draft        Composite Execution Finality        September 2026

24.3.  WIMSE

   Relevant if child actors are workloads on different hops.  Workload
   identity is not composite join.

24.4.  RATS

   Relevant if a child CAD includes environment currentness.
   Attestation is not prepare.

24.5.  HTTPAPI

   Relevant to coordinator HTTP resources and problem+json mapping of
   EF-047 / COMPENSATING and EF-048 / HOLD.

24.6.  SCITT

   Relevant to logging composite receipts.  Not the commit protocol.

24.7.  SAAG

   Useful for whether all-or-none across administrative domains is in
   scope for the IETF at all.

24.8.  No Presumed Home

   Individual -00.  No IANA request in this revision beyond codes
   already reserved in [DAS-REG].

25.  Relationship to Other Execution-Finality Internet-Drafts

   This draft sits above the handle and the registries.  It does not
   replace predicate or domain drafts.

Das                       Expires 20 March 2027                [Page 28]
Internet-Draft        Composite Execution Finality        September 2026

   DAS-PROTOCOL      architecture
   DAS-HANDLE        authority at ONE sink
   DAS-REG           COMPOSITE class/type, EF-047
                     PARTIAL_COMMIT, EF-048
                     DECISION_LOG_UNREACHABLE
   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

   See [DAS-HANDLE], [DAS-REG], [DAS-PROTOCOL], [DAS-PATH], [DAS-STATE],
   [DAS-REVOCATION], [DAS-JURISDICTION], [DAS-PURPOSE], and
   [DAS-AGENTIC].

26.  Security Considerations

   Coordinator compromise is not child-sink compromise.  A malicious or
   failed coordinator can withhold a decision, but it cannot make a
   child post without a recorded COMMIT, and it cannot hold reservations
   indefinitely while the log is reachable, because any prepared child
   can write ABORT into an empty log.

   Child sinks MUST NOT release a PREPARED reservation on a timer when
   COMMIT may already be recorded.  They MUST consult the log: COMMIT
   commits, ABORT releases, an empty log allows a child CAS of ABORT,
   and an unreachable log leads to HOLD.

   The integrity and availability of the Composite Decision Log are part
   of the trusted computing base for the prevention claim.  An attacker
   who can rewrite a recorded value, or who can make two readers observe
   different values, can split the composite.  An attacker who can make
   the log unreachable can keep reservations in HOLD.  Profiles SHOULD
   replicate the log with a consensus protocol and SHOULD authenticate
   writers.

   Child CAS of ABORT means a compromised or misconfigured required
   child can force a composite to abort by writing ABORT early.  That is
   a liveness attack, not a safety break: no child posts, and no split
   occurs.  Profiles MAY restrict early child writes to children whose
   reservation timer has actually expired and SHOULD log the writer
   identity of every CAS.

Das                       Expires 20 March 2027                [Page 29]
Internet-Draft        Composite Execution Finality        September 2026

   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.

27.  Privacy Considerations

   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.

28.  IANA Considerations

   This version does not request IANA action.  It uses COMPOSITE, EF-047
   PARTIAL_COMMIT, and the composite states proposed in [DAS-REG].  It
   also uses EF-048 DECISION_LOG_UNREACHABLE, the COMMIT_DECIDED
   composite state, the HOLD child decision, and the ef-composite-strict
   and ef-composite-mitigation profile identifiers, which are expected
   to be added to [DAS-REG] in its next revision.

29.  Criticism, Corrections, and Review Invited

   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.

30.  Conclusion

   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.

   CHILD POST
         !=
   COMPOSITE FINALITY

   SAGA COMPENSATION
         !=
   THE ORIGINAL ACT SUCCEEDED

   PREPARE ALL REQUIRED
     or
   DO NOT CLAIM PREVENTION

31.  Normative References

Das                       Expires 20 March 2027                [Page 30]
Internet-Draft        Composite Execution Finality        September 2026

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, May 2017,
              <https://www.rfc-editor.org/rfc/rfc8174>.

32.  Informative References

   [DAS-AGENTIC]
              Das, S., "Tool Selection Is Not Execution: Finality for
              Agentic Tool Dispatch in High-Risk AI Systems", Work in
              Progress, Internet-Draft, draft-das-agentic-execution-
              finality-02, September 2026,
              <https://datatracker.ietf.org/doc/draft-das-agentic-
              execution-finality/>.

   [DAS-HANDLE]
              Das, S., "Possession Is Not Authority: Execution Handle,
              Sink Verification, Atomic Consumption, and Finality
              Receipt", Work in Progress, Internet-Draft, draft-das-
              execution-handle-01, September 2026,
              <https://datatracker.ietf.org/doc/draft-das-execution-
              handle/>.

   [DAS-JURISDICTION]
              Das, S., "Authorized Here, Not Authorized There:
              Jurisdiction-Bound Execution Finality for Cross-Border and
              Sovereign Systems", Work in Progress, Internet-Draft,
              draft-das-jurisdiction-bound-execution-finality-00,
              September 2026, <https://datatracker.ietf.org/doc/draft-
              das-jurisdiction-bound-execution-finality/>.

   [DAS-PATH] Das, S., "When the Gate Can Be Bypassed: Consequence-Path
              Completeness for Execution Finality", Work in Progress,
              Internet-Draft, draft-das-consequence-path-completeness-
              00, September 2026, <https://datatracker.ietf.org/doc/
              draft-das-consequence-path-completeness/>.

   [DAS-PROTOCOL]
              Das, S., "The Missing Protocol Layer for the Agentic
              Internet: Computation Is Not Authority", Work in Progress,
              Internet-Draft, draft-das-execution-finality-protocol-
              layer-01, September 2026,
              <https://datatracker.ietf.org/doc/draft-das-execution-
              finality-protocol-layer/>.

Das                       Expires 20 March 2027                [Page 31]
Internet-Draft        Composite Execution Finality        September 2026

   [DAS-PURPOSE]
              Das, S., "Data-Purpose Laundering Prevention: Execution-
              Finality for Preventing Cross-Domain Data Reuse", Work in
              Progress, Internet-Draft, draft-das-purpose-execution-
              finality-03, September 2026,
              <https://datatracker.ietf.org/doc/draft-das-purpose-
              execution-finality/>.

   [DAS-REG]  Das, S., "Illustrative Codes Are Not a Namespace:
              Registries for Execution-Finality Objects", Work in
              Progress, Internet-Draft, draft-das-ef-registries-01,
              September 2026, <https://datatracker.ietf.org/doc/draft-
              das-ef-registries/>.

   [DAS-REVOCATION]
              Das, S., "Revoked but Still Executable: Closing the
              Authorization-to-Effect Gap with Finality-Bound
              Revocation", Work in Progress, Internet-Draft, draft-das-
              finality-bound-revocation-00, September 2026,
              <https://datatracker.ietf.org/doc/draft-das-finality-
              bound-revocation/>.

   [DAS-STATE]
              Das, S., "When Valid Authorization Becomes Stale: State
              and Policy Continuity at the Execution-Finality Boundary",
              Work in Progress, Internet-Draft, draft-das-state-policy-
              continuity-finality-00, September 2026,
              <https://datatracker.ietf.org/doc/draft-das-state-policy-
              continuity-finality/>.

Author's Address

   Sangam Das
   Independent
   Balasore
   Odisha
   India
   Phone: +91-9861363532
   Email: info@sangamdas.com

Das                       Expires 20 March 2027                [Page 32]