HTTP B. Venkateswaran Internet-Draft A. Jamwal Intended status: Experimental Salesforce Expires: 20 December 2026 18 June 2026 2-Phase HTTP Protocol (2PHP) draft-venkateswaran-jamwal-twophp-00 Abstract This document specifies the 2-Phase HTTP Protocol (2PHP), a backward- compatible, opt-in extension to HTTP mutation semantics that introduces a two-phase handshake at service request boundaries. 2PHP ensures that a mutation request is durably registered on both the client and the server before any processing commences, addressing a structural gap in existing HTTP REST semantics where no standard mechanism exists to confirm bilateral intent registration prior to execution. 2PHP operates at the HTTP protocol layer, requires no new transport mechanisms, and is composable across independently operating service boundaries. This document further defines a standardized Intent Ledger model for durable, queryable, cross-service correlation of request intent, distinct from execution telemetry provided by distributed tracing systems. This document defines the protocol headers, phase state machine, idempotency and replay behavior, the three-tier Intent Ledger architecture, cross-service correlation model, and IANA registration of the associated HTTP header fields. 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 December 2026. Venkateswaran & Jamwal Expires 20 December 2026 [Page 1] Internet-Draft 2PHP June 2026 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. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4 3. Problem Statement . . . . . . . . . . . . . . . . . . . . . . 5 3.1. The Request Boundary Gap . . . . . . . . . . . . . . . . 5 3.2. Limitations of Existing Telemetry . . . . . . . . . . . . 6 3.3. Limitations of Existing Patterns . . . . . . . . . . . . 6 4. Protocol Overview . . . . . . . . . . . . . . . . . . . . . . 6 5. Protocol Specification . . . . . . . . . . . . . . . . . . . 7 5.1. Opt-In Header . . . . . . . . . . . . . . . . . . . . . . 7 5.2. Phase 1 — Intent Registration . . . . . . . . . . . . . . 7 5.2.1. Client Request . . . . . . . . . . . . . . . . . . . 7 5.2.2. Server Response . . . . . . . . . . . . . . . . . . . 8 5.2.3. Client Ledger Write . . . . . . . . . . . . . . . . . 9 5.3. Phase 2 — Client Confirmation . . . . . . . . . . . . . . 9 5.3.1. Client Request . . . . . . . . . . . . . . . . . . . 9 5.3.2. Server Response — Synchronous Mode . . . . . . . . . 9 5.3.3. Server Response — Asynchronous Mode . . . . . . . . . 9 5.4. TTL Expiry . . . . . . . . . . . . . . . . . . . . . . . 10 5.5. Auto-Confirm Mode . . . . . . . . . . . . . . . . . . . . 10 5.5.1. Overview . . . . . . . . . . . . . . . . . . . . . . 10 5.5.2. Activation Headers . . . . . . . . . . . . . . . . . 11 5.5.3. Protocol Flow . . . . . . . . . . . . . . . . . . . . 11 5.5.4. Callback Payload . . . . . . . . . . . . . . . . . . 12 5.5.5. Failure Detection via Callback Gap . . . . . . . . . 13 5.5.6. Transparent Mode (Auto-Confirm without Callback) . . 13 5.5.7. State Machine — Auto-Confirm Mode . . . . . . . . . . 13 5.5.8. Mode Comparison . . . . . . . . . . . . . . . . . . . 14 6. State Machine . . . . . . . . . . . . . . . . . . . . . . . . 14 7. Phase States . . . . . . . . . . . . . . . . . . . . . . . . 15 8. Idempotency and Replay Behavior . . . . . . . . . . . . . . . 16 8.1. Replay Before TTL . . . . . . . . . . . . . . . . . . . . 16 8.2. Replay After TTL . . . . . . . . . . . . . . . . . . . . 16 9. Intent Ledger . . . . . . . . . . . . . . . . . . . . . . . . 16 9.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . 16 Venkateswaran & Jamwal Expires 20 December 2026 [Page 2] Internet-Draft 2PHP June 2026 9.2. Architectural Contrast: Inline DTT vs. Passive Telemetry . . . . . . . . . . . . . . . . . . . . . . . . 16 9.3. Microservice Autonomy and Compensation Hooks . . . . . . 17 9.4. Architecture: 3-Tier Ledger Model . . . . . . . . . . . . 17 9.5. Write Flow . . . . . . . . . . . . . . . . . . . . . . . 17 9.6. On-Demand Pull . . . . . . . . . . . . . . . . . . . . . 18 9.7. Operational Modes . . . . . . . . . . . . . . . . . . . . 18 9.8. Ledger Schema . . . . . . . . . . . . . . . . . . . . . . 19 10. Cross-Service Correlation . . . . . . . . . . . . . . . . . . 20 10.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . 20 10.2. Propagation Rules . . . . . . . . . . . . . . . . . . . 20 10.3. Example Call Chain . . . . . . . . . . . . . . . . . . . 20 10.4. Tree Reconstruction Query Patterns . . . . . . . . . . . 21 11. Backward Compatibility . . . . . . . . . . . . . . . . . . . 21 12. Implementation Considerations . . . . . . . . . . . . . . . . 21 12.1. Reference Implementation Targets . . . . . . . . . . . . 21 12.2. Durable Storage for Phase 1 Persistence . . . . . . . . 22 12.3. TTL Defaults . . . . . . . . . . . . . . . . . . . . . . 22 12.4. Service Ledger Registration . . . . . . . . . . . . . . 22 13. Security Considerations . . . . . . . . . . . . . . . . . . . 22 13.1. Correlation ID Confidentiality . . . . . . . . . . . . . 23 13.2. Phase 2 Spoofing . . . . . . . . . . . . . . . . . . . . 23 13.3. Replay Attacks . . . . . . . . . . . . . . . . . . . . . 23 13.4. Intent Payload Confidentiality . . . . . . . . . . . . . 23 13.5. Ledger Access Control . . . . . . . . . . . . . . . . . 23 13.6. Transport Security . . . . . . . . . . . . . . . . . . . 23 14. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 24 14.1. HTTP Header Field Registrations . . . . . . . . . . . . 24 15. Requirements Language . . . . . . . . . . . . . . . . . . . . 26 16. Normative References . . . . . . . . . . . . . . . . . . . . 26 17. Informative References . . . . . . . . . . . . . . . . . . . 26 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 26 1. Introduction Microservices architectures built on HTTP REST APIs are widely deployed for distributed systems communication. Mutation requests—those using HTTP methods POST, PUT, PATCH, and DELETE—are treated as single atomic operations from the client’s perspective. In practice, however, no standard protocol mechanism exists to confirm that both the client and server have durably registered the intent of a request before processing begins. Venkateswaran & Jamwal Expires 20 December 2026 [Page 3] Internet-Draft 2PHP June 2026 Existing approaches—including the Saga pattern [SAGA], Transactional Outbox [OUTBOX], and application-layer idempotency keys—address failure recovery after the fact or are implemented ad hoc without a standard contract. Distributed tracing systems such as OpenTelemetry [OTEL] provide execution telemetry but cannot answer whether both parties registered intent before processing commenced. This document specifies the 2-Phase HTTP Protocol (2PHP), an opt-in, backward-compatible extension to HTTP that introduces a lightweight two-phase handshake at each service boundary. 2PHP ensures bilateral durable registration of request intent before any business logic is executed. It further defines a standardized Intent Ledger model that enables cross-service correlation of request intent across distributed call trees. 2PHP is designed to be: * *Backward compatible*—servers and clients that do not implement 2PHP are unaffected. * *Lightweight*—two HTTP round trips; no new transport layer. * *Composable*—each service boundary operates independently; no distributed coordination is required. * *Standardized*—a consistent header contract enabling uniform tooling, observability, and governance. 2. Conventions and Definitions 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, as shown here. 2PHP: The 2-Phase HTTP Protocol, as defined in this document. Phase 1: The Intent Registration phase, in which the client sends a mutation request and the server durably persists the request payload and an initial ledger record before responding. Phase 2: The Client Confirmation phase, in which the client confirms receipt of the Phase 1 acknowledgement, triggering server-side business logic execution. PONR (Point of No Return): The moment at which the server begins Venkateswaran & Jamwal Expires 20 December 2026 [Page 4] Internet-Draft 2PHP June 2026 executing business logic after receiving Phase 2 confirmation. Processing cannot be rolled back after this point. TTL (Time to Live): The server-defined duration, in milliseconds, within which the client MUST send Phase 2 confirmation. Delta (δ): A server-internal grace window applied after TTL expiry to handle race conditions at the PONR boundary. Not exposed to the client. Intent Ledger: A durable, queryable log of 2PHP transactions, distinct from execution telemetry. Local Ledger: A per-service, in-process ledger authoritative for that service’s phase states. Central Ledger: A read-optimized aggregate view of all local ledgers, populated via background batch sync. Client Correlation ID: A client-assigned identifier for a specific request, included in all protocol headers and ledger entries for that interaction. Server Correlation ID: A server-assigned identifier for a specific intent registration, returned in the Phase 1 response. Parent Reference ID: The correlation ID that the immediate upstream caller provided when initiating the call to a downstream service. Used to reconstruct distributed call trees. 3. Problem Statement 3.1. The Request Boundary Gap Current HTTP REST semantics treat a mutation request as a single atomic operation from the client’s perspective. In reality, a server may: * Receive and process the request without the client ever confirming receipt of the response. * Fail mid-processing with no durable record of the original intent. * Return a success response that is lost in transit. No standard HTTP mechanism exists to confirm that both the client and the server have registered the intent of a request before processing commences. Venkateswaran & Jamwal Expires 20 December 2026 [Page 5] Internet-Draft 2PHP June 2026 3.2. Limitations of Existing Telemetry Modern distributed tracing systems provide visibility into what executed across services, how long operations took, and where failures occurred. However, they cannot answer: * Did both client and server register the intent before processing? * Was a request abandoned or confirmed? * At what phase did a distributed transaction stall? 3.3. Limitations of Existing Patterns +===============+=============+===========+==========+=========+ | Pattern | Scope | Client | Protocol | Intent | | | | Involved? | Level? | Ledger? | +===============+=============+===========+==========+=========+ | Two-Phase | Database | No | No | No | | Commit (2PC) | | | | | +---------------+-------------+-----------+----------+---------+ | Saga Pattern | Application | No | No | No | +---------------+-------------+-----------+----------+---------+ | Transactional | Server-side | No | No | No | | Outbox | | | | | +---------------+-------------+-----------+----------+---------+ | Idempotency | Application | Partial | No | No | | Keys | | | | | +---------------+-------------+-----------+----------+---------+ | HTTP 100 | Protocol | Yes | Yes | No | | Continue | | | | | +---------------+-------------+-----------+----------+---------+ | 2PHP (this | Protocol | Yes | Yes | Yes | | document) | | | | | +---------------+-------------+-----------+----------+---------+ Table 1 4. Protocol Overview 2PHP extends HTTP mutation semantics with an opt-in two-phase handshake. Each service boundary owns its own independent handshake. Cross-service traceability is the responsibility of the centralized Intent Ledger, not the protocol itself. Venkateswaran & Jamwal Expires 20 December 2026 [Page 6] Internet-Draft 2PHP June 2026 Client Server | | |-- Phase 1: POST + payload --------> | | | Persist payload + | | ledger record atomically | <-- 200 OK + Server-Corr-ID ------- | | | | (Client writes local ledger entry) | | | |-- Phase 2: POST confirm ----------> | | | PONR crossed; | | business logic executes | <-- 200 OK + Resource-ID ---------- | | | Figure 1: 2PHP Protocol Flow (Synchronous Mode) The server MUST atomically persist the intent payload and the initial ledger record before returning the Phase 1 response. The resource is created only after Phase 2 confirmation is received and business logic has successfully executed. 5. Protocol Specification 5.1. Opt-In Header Clients signal 2PHP intent by including the following header on any mutation request: DTT-2PHP-Enabled: true Servers that do not recognize this header MUST ignore it and process the request normally, preserving backward compatibility. 5.2. Phase 1 — Intent Registration 5.2.1. Client Request POST /orders HTTP/1.1 DTT-2PHP-Enabled: true DTT-2PHP-Requested-TTL: DTT-2PHP-Client-Correlation-ID: Content-Type: application/json { ...payload... } Venkateswaran & Jamwal Expires 20 December 2026 [Page 7] Internet-Draft 2PHP June 2026 The client MUST include DTT-2PHP-Client-Correlation-ID with a unique identifier for this request. This identifier MUST be used in all subsequent protocol exchanges and ledger entries for this interaction. The client MAY include DTT-2PHP-Requested-TTL (in milliseconds) to request that the server override its default TTL setting. 5.2.2. Server Response The server MUST atomically persist the intent payload and an initial ledger record with phase state WAITING_CONFIRM before returning the response. HTTP/1.1 200 OK DTT-2PHP-Server-Correlation-ID: DTT-2PHP-Phase-State: WAITING_CONFIRM DTT-2PHP-TTL: DTT-2PHP-PONR-Deadline: Response header semantics: DTT-2PHP-Server-Correlation-ID: Server-assigned identifier for this intent registration. The client MUST echo this value in the Phase 2 confirmation. DTT-2PHP-TTL: Milliseconds the server will wait for Phase 2 confirmation. Server-defined. The client MUST send Phase 2 before this duration elapses. If the client includes DTT-2PHP- Requested-TTL, the server MAY accommodate by increasing the TTL. DTT-2PHP-PONR-Deadline: Server-computed absolute deadline in ISO 8601 format. The client MUST send Phase 2 before this timestamp. DTT-2PHP-Phase-State: Current phase state. Value is WAITING_CONFIRM on Phase 1 response. No DTT-2PHP-Resource-ID is returned in Phase 1. The resource does not yet exist; it is created only after Phase 2 confirmation is received and business logic has successfully executed. Venkateswaran & Jamwal Expires 20 December 2026 [Page 8] Internet-Draft 2PHP June 2026 5.2.3. Client Ledger Write After receiving the Phase 1 response, the client MUST write a ledger entry to its local ledger. The client writes after the Phase 1 response so that both client_correlation_id and server_correlation_id are available at write time. The client’s parent_reference_id MUST be set to its own client_correlation_id as the root anchor. 5.3. Phase 2 — Client Confirmation 5.3.1. Client Request The client confirms receipt of the Phase 1 acknowledgement: POST /orders/confirm HTTP/1.1 DTT-2PHP-Enabled: true DTT-2PHP-Client-Correlation-ID: DTT-2PHP-Server-Correlation-ID: The client MUST send Phase 2 before the DTT-2PHP-PONR-Deadline timestamp received in the Phase 1 response. 5.3.2. Server Response — Synchronous Mode The server crosses the PONR, executes business logic inline, and responds once processing is complete: HTTP/1.1 200 OK DTT-2PHP-Phase-State: COMMITTED DTT-2PHP-Resource-ID: The server MUST return 200 OK only after business logic has completed and the resource is fully created. The DTT-2PHP-Resource-ID is authoritative—the resource exists at the point this response is returned. If business logic fails after PONR is crossed, the server MUST return 500 Internal Server Error. If the request is invalid, the server MUST return the appropriate 4xx response. In both cases the client receives a definitive outcome in the Phase 2 response—no polling is required. 5.3.3. Server Response — Asynchronous Mode In asynchronous mode, the server crosses the PONR and returns 202 Accepted immediately upon receiving Phase 2 confirmation. Business logic executes out-of-band on the original request channel. Venkateswaran & Jamwal Expires 20 December 2026 [Page 9] Internet-Draft 2PHP June 2026 HTTP/1.1 202 Accepted DTT-2PHP-Phase-State: PROCESSING DTT-2PHP-Resource-ID: The DTT-2PHP-Resource-ID returned in a 202 Accepted response is provisional—the resource is not yet fully created at the point this response is returned. The client MUST poll the resource endpoint until DTT-2PHP-Phase-State transitions to COMMITTED or FAILED. The phase state machine is identical to synchronous mode. Only the timing of the COMMITTED transition differs—in asynchronous mode it occurs out-of-band rather than inline on the Phase 2 response channel. 202 Accepted semantics are as defined in [RFC9110]. 5.4. TTL Expiry Any Phase 2 confirmation received after TTL expiry MUST be rejected with: HTTP/1.1 408 Request Timeout DTT-2PHP-Phase-State: TTL_EXPIRED DTT-2PHP-Message: Request TTL exceeded. Re-submit as new request. The server MAY apply an internal grace window (δ) after TTL expiry to handle race conditions at the PONR boundary. This grace window is server-internal and MUST NOT be exposed in protocol headers or communicated to the client. 5.5. Auto-Confirm Mode 5.5.1. Overview Auto-Confirm mode is an opt-in extension to 2PHP that eliminates the explicit Phase 2 client confirmation round trip. When Auto-Confirm is enabled, the server writes the ledger record and crosses the PONR immediately after Phase 1, then executes business logic inline on the original request channel. The final result (200 OK + Resource-ID) is returned synchronously on that same channel—behaviorally identical to a standard HTTP request from the client’s perspective. Concurrently, immediately after the ledger write and before processing begins, the server dispatches an asynchronous callback to a client-provided endpoint carrying the server_correlation_id and ledger state. This out-of-band delivery gives the client a durable record of the registered intent independent of the original response channel. Auto-Confirm mode is valuable for: Venkateswaran & Jamwal Expires 20 December 2026 [Page 10] Internet-Draft 2PHP June 2026 * *Brownfield adoption*—clients with no 2PHP implementation receive full ledger observability with zero behavior change. * *Low-latency critical paths*—the Phase 2 round trip cost is eliminated. * *Server-side opt-in*—platform teams can enable ledger tracking without requiring client participation. 5.5.2. Activation Headers DTT-2PHP-Auto-Confirm: true DTT-2PHP-Callback: DTT-2PHP-Auto-Confirm: When true, the server does not wait for a Phase 2 confirmation before crossing the PONR and executing business logic. DTT-2PHP-Callback: A client-provided HTTPS endpoint to receive the asynchronous intent acknowledgment payload. This header is OPTIONAL when DTT-2PHP-Auto-Confirm: true is set. If omitted, the server proceeds in Transparent Mode with no client-side ledger participation. 5.5.3. Protocol Flow Venkateswaran & Jamwal Expires 20 December 2026 [Page 11] Internet-Draft 2PHP June 2026 Client Server Client Callback | | | |-- POST /orders -------------> | | | DTT-2PHP-Enabled: true | | | DTT-2PHP-Auto-Confirm: true | | | DTT-2PHP-Callback: | | | DTT-2PHP-Client-Corr-ID: C1 | | | | | | Ledger write (WAITING_CONFIRM | | -> PROCESSING, atomic) | | | | | |-- POST callback --> | | | (immediately, | | | off-thread, | | | BEFORE processing)| | | | | Server processes inline... | | | | | <-- 200 OK + Resource-ID ---- | | | DTT-2PHP-Phase-State: | | | COMMITTED | | | DTT-2PHP-Server-Corr-ID: S1 | | | | | Figure 2: Auto-Confirm Mode with Callback The key invariant: the callback MUST be dispatched immediately after the ledger write and MUST fire before processing begins. This maximizes the client detection window. If the original response is never received but the callback was, the client knows the PONR was crossed and MAY query the ledger by server_correlation_id for final state. 5.5.4. Callback Payload +=======================+==========================================+ | Field | Description | +=======================+==========================================+ | server_correlation_id | Server-assigned intent identifier. | +-----------------------+------------------------------------------+ | client_correlation_id | Echo of the client-provided identifier. | +-----------------------+------------------------------------------+ | phase_state | PROCESSING at time of callback dispatch. | +-----------------------+------------------------------------------+ | ponr_crossed | Always true in Auto-Confirm mode. | +-----------------------+------------------------------------------+ | callback_timestamp | ISO 8601 timestamp of callback dispatch. | | | Fired before processing begins. | Venkateswaran & Jamwal Expires 20 December 2026 [Page 12] Internet-Draft 2PHP June 2026 +-----------------------+------------------------------------------+ Table 2 5.5.5. Failure Detection via Callback Gap The callback creates a first-class detectable failure taxonomy: +==========+==========+========================================+ | Callback | Original | Interpretation | | Received | Response | | | | Received | | +==========+==========+========================================+ | Yes | Yes | Normal success. Reconcile by | | | | correlation IDs. | +----------+----------+----------------------------------------+ | Yes | No | PONR crossed; response lost in | | | | transit. Query ledger by | | | | server_correlation_id for final state. | +----------+----------+----------------------------------------+ | No | Yes | Callback delivery failed. Ledger | | | | entry exists server-side; client has | | | | no local record. | +----------+----------+----------------------------------------+ | No | No | Network failure before PONR. Safe to | | | | retry as a new Phase 1 request. | +----------+----------+----------------------------------------+ Table 3 5.5.6. Transparent Mode (Auto-Confirm without Callback) When DTT-2PHP-Auto-Confirm: true is set without DTT-2PHP-Callback, the server operates in Transparent Mode. The server records a ledger entry using a server-generated UUID as the client_correlation_id proxy. The client receives a standard synchronous response with no 2PHP headers required. The server MAY return DTT-2PHP-Server- Correlation-ID in the response for optional client-side ledger lookup. Transparent Mode provides full server-side ledger observability with zero client behavior change. It is the recommended adoption path for brownfield services. 5.5.7. State Machine — Auto-Confirm Mode Venkateswaran & Jamwal Expires 20 December 2026 [Page 13] Internet-Draft 2PHP June 2026 Client POST (Phase 1, DTT-2PHP-Auto-Confirm: true) | v [WAITING_CONFIRM] <-- ledger write (transient, atomic) | v (immediate -- PONR crossed, no client confirmation) [PROCESSING] --> (off-thread) Callback dispatched to client | BEFORE processing begins | +-- Success --> [COMMITTED] <-- 200 OK + Resource-ID | on original channel | +-- Failure --> [FAILED] <-- 500 / 4xx on original channel Figure 3: Auto-Confirm Phase State Machine In Auto-Confirm mode, WAITING_CONFIRM is a transient internal state written and immediately superseded by PROCESSING within the same atomic ledger operation. It is never visible to the client on the original channel. 5.5.8. Mode Comparison +==============+========+========+=======+========+===============+ | Mode |Phase 2 |Callback|Latency|Client | Ledger | | |Required| | |2PHP | Participation | | | | | |Support | | +==============+========+========+=======+========+===============+ | Standard |Yes |No |2 round|Yes | Both sides | | 2PHP | | |trips | | | +--------------+--------+--------+-------+--------+---------------+ | Auto-Confirm |No |Yes |1 round|Callback| Both sides | | (with | |(async) |trip |endpoint| | | callback) | | | |only | | +--------------+--------+--------+-------+--------+---------------+ | Transparent |No |No |1 round|None | Server-side | | Mode (no | | |trip | | only | | callback) | | | | | | +--------------+--------+--------+-------+--------+---------------+ Table 4 6. State Machine Venkateswaran & Jamwal Expires 20 December 2026 [Page 14] Internet-Draft 2PHP June 2026 Client POST (Phase 1) | v [WAITING_CONFIRM] <-- persisted in durable storage | +-- Client confirms within TTL | | | v | [PROCESSING] <-- PONR crossed; business logic executing | | | +-- Success --> [COMMITTED] <-- 200 OK + Resource-ID | | | +-- Failure --> [FAILED] <-- 500 / 4xx | +-- TTL expires without confirmation | v [TTL_EXPIRED] -- [ PONR, PONR+delta-x ) --> [ABANDONED] Figure 4: 2PHP Phase State Machine 7. Phase States +=================+===============================================+ | State | Description | +=================+===============================================+ | WAITING_CONFIRM | Phase 1 received and persisted. Awaiting | | | client Phase 2 confirmation. | +-----------------+-----------------------------------------------+ | PROCESSING | Phase 2 confirmed. PONR crossed. Business | | | logic executing (synchronous mode). | +-----------------+-----------------------------------------------+ | COMMITTED | Processing complete. Resource created. | | | Terminal success state. | +-----------------+-----------------------------------------------+ | FAILED | Processing failed after PONR. Server | | | returned 500 or 4xx. Terminal failure state. | +-----------------+-----------------------------------------------+ | TTL_EXPIRED | Client did not confirm within TTL. Pending | | | cleanup. | +-----------------+-----------------------------------------------+ | ABANDONED | Cleaned up after TTL + δ grace window. | | | Terminal state. | +-----------------+-----------------------------------------------+ Table 5 Venkateswaran & Jamwal Expires 20 December 2026 [Page 15] Internet-Draft 2PHP June 2026 8. Idempotency and Replay Behavior 8.1. Replay Before TTL If a client replays Phase 2 before TTL expiry, the server MUST return the same response associated with the original DTT-2PHP-Server- Correlation-ID. No duplicate processing occurs. 8.2. Replay After TTL Two configurable server behaviors are defined, applicable per endpoint or globally: REJECT (default): Return 408 TTL_EXPIRED. The client MUST re-submit Phase 1 as a new request with a new DTT-2PHP-Client-Correlation- ID. REUSE: The server accepts the late Phase 2 confirmation and uses the persisted intent, provided cleanup has not yet occurred within the δ grace window. Servers MAY expose the replay policy via the following header: DTT-2PHP-Replay-Policy: REJECT | REUSE 9. Intent Ledger 9.1. Overview The Intent Ledger is a durable, queryable log of all 2PHP transactions. It is distinct from execution telemetry—it is an intent registry, not a trace of execution. Its purpose is to provide provable bilateral registration of every mutation intent across all participating services. 9.2. Architectural Contrast: Inline DTT vs. Passive Telemetry Existing distributed tracing frameworks, such as OpenTelemetry [OTEL], pass trace contexts out-of-band to log execution data after it happens. This post-mortem model suffers from ingestion lag and cannot stop data mismatches when a network drops right at a service boundary. In contrast, the 2PHP Distributed Transaction Tracker (DTT) Ledger operates inline as an active safety gate. It forces both the client and server to write an atomic record of intent BEFORE data processing starts. This turns passive logging into real-time failure prevention. Venkateswaran & Jamwal Expires 20 December 2026 [Page 16] Internet-Draft 2PHP June 2026 9.3. Microservice Autonomy and Compensation Hooks 2PHP is NOT a Distributed Transaction Coordinator (DTC). It requires zero cross-service thread blocking or lock coordination. Each service boundary handles its handshake independently. The 3-Tier Ledger architecture uses a local-first design where writes are synchronous but local, completely removing network hops from the runtime path. By standardizing states like WAITING_CONFIRM and TTL_EXPIRED across all systems, the platform provides a uniform data layer. Infrastructure tools can read these state transitions to automatically trigger custom application-layer compensation scripts or data-cleanup workflows without human intervention. 9.4. Architecture: 3-Tier Ledger Model The Intent Ledger uses a local-first, batch-sync architecture to ensure it is never on the critical path of service processing. Tier 1 — Local Ledger: Per-service, in-process write. Synchronous but local—no network hop. Authoritative source of truth for that service’s phase states. Tier 2 — Batch Sync: Scheduled background job syncing local ledger entries to the Central Ledger. Frequency configurable per service. Not on the critical path. Tier 3 — Central Ledger: Read-optimized aggregate view across all services. Used for audit, incident investigation, and SLA reporting. Does not require high availability or low latency guarantees. 9.5. Write Flow The intent payload and ledger record MUST both be persisted as a single unit of work before 200 OK is returned. Venkateswaran & Jamwal Expires 20 December 2026 [Page 17] Internet-Draft 2PHP June 2026 Phase 1 received | v Persist as single unit of work: - Intent payload (durable store) - Ledger record (Local Ledger, phase: WAITING_CONFIRM) `|` `v` 200 OK returned to client | v (async background batch job) Local Ledger --> Central Ledger (eventually consistent) Figure 5: Ledger Write Flow For highly critical services, the payload and ledger SHOULD be co- located in the same store to eliminate the need for distributed transaction coordination. For less critical services, a temporary copy of the payload and ledger entry is sufficient for Phase 1 and Phase 2 lifecycle management, with the ledger entry synced to the Central Ledger via event publish, not on the critical path. 9.6. On-Demand Pull The Central Ledger Management Application MAY trigger an on-demand pull from any service’s local ledger. This mechanism is used during incident investigation when the latest data is needed immediately, without waiting for the next scheduled batch sync. 9.7. Operational Modes +==================+===================+========================+ | Scenario | Ledger Used | Trigger | +==================+===================+========================+ | Normal operation | Local Ledger only | Per phase transition | +------------------+-------------------+------------------------+ | Routine audit | Central Ledger | Batch sync (scheduled) | +------------------+-------------------+------------------------+ | Incident | Central Ledger | On-demand pull from | | investigation | | Management App | +------------------+-------------------+------------------------+ | Compliance | Central Ledger | Batch sync (scheduled) | | reporting | | | +------------------+-------------------+------------------------+ Table 6 Venkateswaran & Jamwal Expires 20 December 2026 [Page 18] Internet-Draft 2PHP June 2026 9.8. Ledger Schema Each ledger entry MUST include the following fields: +=======================+==========================================+ | Field | Description | +=======================+==========================================+ | client_correlation_id | Client-assigned request identifier. | +-----------------------+------------------------------------------+ | server_correlation_id | Server-assigned intent identifier. | +-----------------------+------------------------------------------+ | service_ledger_id | GUID issued to the service at ledger | | | registration. | +-----------------------+------------------------------------------+ | service_endpoint | Target service and resource path. | +-----------------------+------------------------------------------+ | actor | Role of the entry writer: client or | | | server. | +-----------------------+------------------------------------------+ | source | Identity of the participant writing this | | | entry (e.g., client, serviceA, | | | serviceB1). | +-----------------------+------------------------------------------+ | target | The downstream service being called. | | | Populated only when actor = client. | | | MUST be null for actor = server entries. | +-----------------------+------------------------------------------+ | parent_reference_id | The correlation ID that the immediate | | | upstream caller provided when calling | | | this service. Used to reconstruct the | | | full distributed call tree. | +-----------------------+------------------------------------------+ | phase | Current or terminal phase state. | +-----------------------+------------------------------------------+ | phase_1_timestamp | When Phase 1 was received (ISO 8601). | +-----------------------+------------------------------------------+ | phase_2_timestamp | When Phase 2 confirmation was received, | | | if applicable (ISO 8601). | +-----------------------+------------------------------------------+ | ttl_ms | Configured TTL for this request, in | | | milliseconds. | +-----------------------+------------------------------------------+ | outcome | Terminal outcome: COMMITTED, ABANDONED, | | | or TTL_EXPIRED. | +-----------------------+------------------------------------------+ | payload_ref | Reference to the persisted payload. Not | | | the payload itself. | +-----------------------+------------------------------------------+ Venkateswaran & Jamwal Expires 20 December 2026 [Page 19] Internet-Draft 2PHP June 2026 | sync_timestamp | When this entry was synced to the | | | Central Ledger (ISO 8601). | +-----------------------+------------------------------------------+ | transaction_reference | Reference to transaction ID (optional). | +-----------------------+------------------------------------------+ Table 7 10. Cross-Service Correlation 10.1. Overview When a service fans out to multiple downstream services, the Intent Ledger captures every participant’s view of every call—both the caller (actor = client) and the callee (actor = server). This produces a unified, traversable ledger that can reconstruct the full distributed call tree without any distributed coordination at the protocol level. 10.2. Propagation Rules * Every service MUST write its own ledger entry after each phase transition. * The client MUST write its ledger entry after receiving the Phase 1 response, so that both client_correlation_id and server_correlation_id are available at write time. * parent_reference_id MUST always record what the immediate upstream caller provided as its correlation ID when calling this service— enabling upward tree traversal. * Each call MUST produce exactly two matching ledger rows: one actor = client and one actor = server, linked by the same client_correlation_id + server_correlation_id pair. This confirms dual-side registration—the core guarantee of 2PHP. * target MUST be populated only on actor = client rows. It MUST be null on actor = server rows. 10.3. Example Call Chain Client --> Service A --> Service B1 --> Service C1 --> Service B2 --> Service D1 --> Service B3 --> Service E1 Figure 6: Fan-Out Call Chain Venkateswaran & Jamwal Expires 20 December 2026 [Page 20] Internet-Draft 2PHP June 2026 The complete ledger for this call chain contains 14 entries—two rows (one actor = client, one actor = server) for each of the seven service-boundary interactions. The root client entry uses client- corr-id1 as both its client_correlation_id and its parent_reference_id, establishing the tree anchor. Each subsequent tier sets parent_reference_id to the correlation ID received from its immediate upstream caller. 10.4. Tree Reconstruction Query Patterns * *Full tree from root:* Query parent_reference_id = client-corr-id1 recursively—walks the entire fan-out tree. * *Everything a service initiated:* Query source = serviceA AND actor = client. * *Confirm dual registration:* Match rows by client_correlation_id + server_correlation_id—one actor = client, one actor = server. * *Find stalled transactions:* Query phase = WAITING_CONFIRM or phase = TTL_EXPIRED across any source. 11. Backward Compatibility 2PHP is designed to be fully backward compatible: * Clients that do not include DTT-2PHP-Enabled: true MUST experience no change in behavior. * Servers that do not implement 2PHP MUST ignore the header and process normally. * 2PHP MAY be adopted incrementally—per endpoint, per service, or organization-wide. * 2PHP makes no changes to existing HTTP methods (POST, PUT, PATCH, DELETE). It is purely additive. * No new transport layer or connection upgrade is required. 12. Implementation Considerations 12.1. Reference Implementation Targets * **Spring Boot** — OncePerRequestFilter interceptor * **Express.js** — middleware Venkateswaran & Jamwal Expires 20 December 2026 [Page 21] Internet-Draft 2PHP June 2026 * **Azure API Management** — inbound policy * **MuleSoft** — HTTP request/response interceptor policy 12.2. Durable Storage for Phase 1 Persistence Implementations SHOULD use one of the following for durable storage of intent payload and ledger records: * Relational database with TTL-aware cleanup job. * Redis with TTL-based key expiry (plus δ buffer). * Distributed queue (e.g., Azure Service Bus, AWS SQS) with visibility timeout. 12.3. TTL Defaults The following are recommended starting values. Implementations MAY adjust these per endpoint. +=========================+============+=====================+ | Scenario | TTL | δ (server-internal) | +=========================+============+=====================+ | Low-latency APIs | 5,000 ms | 1,000 ms | +-------------------------+------------+---------------------+ | Standard APIs | 30,000 ms | 5,000 ms | +-------------------------+------------+---------------------+ | Long-running operations | 120,000 ms | 10,000 ms | +-------------------------+------------+---------------------+ Table 8 δ values are server implementation defaults and MUST NOT be exposed in protocol headers. 12.4. Service Ledger Registration Each service SHOULD register with the Intent Ledger at onboarding and be issued a GUID (service_ledger_id) that is included in all ledger entries for that service. This enables cross-service querying while maintaining service-level isolation. 13. Security Considerations Venkateswaran & Jamwal Expires 20 December 2026 [Page 22] Internet-Draft 2PHP June 2026 13.1. Correlation ID Confidentiality DTT-2PHP-Client-Correlation-ID and DTT-2PHP-Server-Correlation-ID values MUST be treated as opaque identifiers. Implementations SHOULD use UUID v4 or equivalent cryptographically random values to prevent enumeration or prediction of correlation IDs by unauthorized parties. 13.2. Phase 2 Spoofing A malicious actor in possession of both DTT-2PHP-Client-Correlation- ID and DTT-2PHP-Server-Correlation-ID could attempt to submit a spoofed Phase 2 confirmation. Implementations MUST authenticate Phase 2 confirmation requests using the same authentication mechanism applied to Phase 1 requests. The server MUST verify that the authenticated identity of the Phase 2 requester matches that of the Phase 1 requester. 13.3. Replay Attacks The REUSE replay policy (Section 8.2) introduces a window during which a replayed Phase 2 confirmation may be accepted. Implementations using REUSE SHOULD apply additional controls, such as request signing or short-lived tokens, to mitigate replay risk within the δ grace window. 13.4. Intent Payload Confidentiality The intent payload persisted during Phase 1 may contain sensitive data. Implementations MUST ensure that persisted payloads are protected at rest using appropriate encryption mechanisms consistent with the sensitivity of the data. 13.5. Ledger Access Control The Central Ledger aggregates intent records across all services. Access to the Central Ledger MUST be restricted to authorized audit, operations, and compliance consumers. The on-demand pull mechanism (Section 9.6) MUST be protected by appropriate authentication and authorization controls. 13.6. Transport Security All 2PHP exchanges MUST be conducted over TLS (HTTPS). Use of 2PHP over unencrypted HTTP is NOT RECOMMENDED. Venkateswaran & Jamwal Expires 20 December 2026 [Page 23] Internet-Draft 2PHP June 2026 14. IANA Considerations 14.1. HTTP Header Field Registrations This document requests registration of the following HTTP header fields in the "Permanent Message Header Field Names" registry defined in [RFC3864] and updated by [RFC9110]: Venkateswaran & Jamwal Expires 20 December 2026 [Page 24] Internet-Draft 2PHP June 2026 +================================+==========+============+=========+ | Header Field Name |Applicable|Status |Reference| | |Protocol | | | +================================+==========+============+=========+ | DTT-2PHP-Enabled |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Client-Correlation-ID |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Auto-Confirm |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Callback |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Requested-TTL |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Server-Correlation-ID |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Phase-State |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-TTL |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-PONR-Deadline |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Resource-ID |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Replay-Policy |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ | DTT-2PHP-Message |HTTP |Experimental|This | | | | |document | +--------------------------------+----------+------------+---------+ Table 9 Venkateswaran & Jamwal Expires 20 December 2026 [Page 25] Internet-Draft 2PHP June 2026 15. 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, as shown here. 16. Normative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, May 2017, . [RFC9110] Fielding, R., Nottingham, M., and J. Reschke, "HTTP Semantics", RFC 9110, June 2022, . [RFC9112] Fielding, R. and J. Reschke, "HTTP/1.1", RFC 9112, June 2022, . [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004, . 17. Informative References [OTEL] OpenTelemetry Authors, "OpenTelemetry Specification", https://opentelemetry.io/docs/specs/otel/, 2024. [SAGA] Garcia-Molina, H. and K. Salem, "Sagas", ACM SIGMOD Record, Vol. 16, Issue 3, 1987. [OUTBOX] Richardson, C., "Pattern: Transactional outbox", 2018. Authors' Addresses Barathan Venkateswaran Salesforce Email: bvenkateswaran@salesforce.com Aditya Jamwal Salesforce Venkateswaran & Jamwal Expires 20 December 2026 [Page 26] Internet-Draft 2PHP June 2026 Email: ajamwal@salesforce.com Venkateswaran & Jamwal Expires 20 December 2026 [Page 27]