Remove duplicate RFC 2119/8174 refs and add compiled output

Remove RFC 2119 and RFC 8174 from normative YAML block since the
BCP 14 boilerplate directive adds them automatically, causing
duplicate reference warnings. Rebuild draft with zero warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 18:51:45 +01:00
parent 397419d711
commit 8615105ce0
4 changed files with 2137 additions and 1078 deletions

View File

@@ -1249,7 +1249,7 @@ li > p:last-of-type:only-child {
<div id="internal-metadata" class="document-information"> <div id="internal-metadata" class="document-information">
<dl id="identifiers"> <dl id="identifiers">
<dt class="label-workgroup">Workgroup:</dt> <dt class="label-workgroup">Workgroup:</dt>
<dd class="workgroup">Network Working Group</dd> <dd class="workgroup">WIMSE</dd>
<dt class="label-internet-draft">Internet-Draft:</dt> <dt class="label-internet-draft">Internet-Draft:</dt>
<dd class="internet-draft">draft-nennemann-wimse-execution-context-00</dd> <dd class="internet-draft">draft-nennemann-wimse-execution-context-00</dd>
<dt class="label-published">Published:</dt> <dt class="label-published">Published:</dt>
@@ -1548,6 +1548,12 @@ regulatory frameworks.<a href="#section-abstract-1" class="pilcrow">¶</a></p>
</li> </li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12.2.3"> <li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12.2.3">
<p id="section-toc.1-1.12.2.3.1"><a href="#section-12.3" class="auto internal xref">12.3</a>.  <a href="#name-jwt-claims-registration" class="internal xref">JWT Claims Registration</a></p> <p id="section-toc.1-1.12.2.3.1"><a href="#section-12.3" class="auto internal xref">12.3</a>.  <a href="#name-jwt-claims-registration" class="internal xref">JWT Claims Registration</a></p>
</li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12.2.4">
<p id="section-toc.1-1.12.2.4.1"><a href="#section-12.4" class="auto internal xref">12.4</a>.  <a href="#name-ect-policy-decision-values-" class="internal xref">ECT Policy Decision Values Registry</a></p>
</li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12.2.5">
<p id="section-toc.1-1.12.2.5.1"><a href="#section-12.5" class="auto internal xref">12.5</a>.  <a href="#name-ect-regulated-domain-values" class="internal xref">ECT Regulated Domain Values Registry</a></p>
</li> </li>
</ul> </ul>
</li> </li>
@@ -1683,7 +1689,7 @@ addresses the gap between workload identity and execution
accountability. WIMSE authenticates agents; this extension records accountability. WIMSE authenticates agents; this extension records
what they did, in what order, and what policy was evaluated.<a href="#section-1.1-5" class="pilcrow"></a></p> what they did, in what order, and what policy was evaluated.<a href="#section-1.1-5" class="pilcrow"></a></p>
<p id="section-1.1-6">As identified in <span>[<a href="#I-D.ni-wimse-ai-agent-identity" class="cite xref">I-D.ni-wimse-ai-agent-identity</a>]</span>, call context <p id="section-1.1-6">As identified in <span>[<a href="#I-D.ni-wimse-ai-agent-identity" class="cite xref">I-D.ni-wimse-ai-agent-identity</a>]</span>, call context
in agentic workflows must always be visible and preserved. ECTs in agentic workflows needs to be visible and preserved. ECTs
provide a mechanism to address this requirement with cryptographic provide a mechanism to address this requirement with cryptographic
assurances.<a href="#section-1.1-6" class="pilcrow"></a></p> assurances.<a href="#section-1.1-6" class="pilcrow"></a></p>
</section> </section>
@@ -2088,14 +2094,45 @@ claim of the agent's WIT.<a href="#section-4.2.1-2.2.1" class="pilcrow">¶</a></
<dt id="section-4.2.1-2.3">sub:</dt> <dt id="section-4.2.1-2.3">sub:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.1-2.4"> <dd style="margin-left: 1.5em" id="section-4.2.1-2.4">
<p id="section-4.2.1-2.4.1"><span class="bcp14">OPTIONAL</span>. StringOrURI. The subject of the ECT. When present, <p id="section-4.2.1-2.4.1"><span class="bcp14">OPTIONAL</span>. StringOrURI. The subject of the ECT. When present,
<span class="bcp14">MUST</span> equal the "iss" claim.<a href="#section-4.2.1-2.4.1" class="pilcrow"></a></p> <span class="bcp14">MUST</span> equal the "iss" claim. This claim is included for
compatibility with JWT libraries and frameworks that expect a
"sub" claim to be present.<a href="#section-4.2.1-2.4.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.1-2.5">aud:</dt> <dt id="section-4.2.1-2.5">aud:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.1-2.6"> <dd style="margin-left: 1.5em" id="section-4.2.1-2.6">
<p id="section-4.2.1-2.6.1"><span class="bcp14">REQUIRED</span>. StringOrURI or array of StringOrURI. The intended <p id="section-4.2.1-2.6.1"><span class="bcp14">REQUIRED</span>. StringOrURI or array of StringOrURI. The intended
recipient(s) of the ECT. Typically the next agent in the recipient(s) of the ECT. Because ECTs serve as both inter-agent
workflow or the ledger endpoint.<a href="#section-4.2.1-2.6.1" class="pilcrow"></a></p> messages and audit records, the "aud" claim <span class="bcp14">SHOULD</span> contain the
identifiers of all entities that will verify the ECT. In
practice this means:<a href="#section-4.2.1-2.6.1" class="pilcrow"></a></p>
<ul class="normal">
<li class="normal" id="section-4.2.1-2.6.2.1">
<p id="section-4.2.1-2.6.2.1.1"><strong>Point-to-point delivery</strong>: when an ECT is sent from one
agent to a single next agent, "aud" contains that agent's
workload identity. The receiving agent verifies the ECT and
forwards it to the ledger on behalf of the issuer.<a href="#section-4.2.1-2.6.2.1.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.1-2.6.2.2">
<p id="section-4.2.1-2.6.2.2.1"><strong>Direct-to-ledger submission</strong>: when an ECT is submitted
directly to the audit ledger (e.g., after a join or at
workflow completion), "aud" contains the ledger's identity.<a href="#section-4.2.1-2.6.2.2.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.1-2.6.2.3">
<p id="section-4.2.1-2.6.2.3.1"><strong>Multi-audience</strong>: when an ECT must be verified by both the
next agent and the ledger independently, "aud" <span class="bcp14">MUST</span> be an
array containing both identifiers (e.g.,
["spiffe://example.com/agent/next",
"spiffe://example.com/system/ledger"]). Each verifier checks
that its own identity appears in the array.<a href="#section-4.2.1-2.6.2.3.1" class="pilcrow"></a></p>
</li>
</ul>
<p id="section-4.2.1-2.6.3">In multi-parent (join) scenarios where a task depends on ECTs
from multiple parent agents, the joining agent creates a new ECT
with the parent task IDs in "par". The "aud" of this new ECT
is set according to the rules above based on where the ECT will
be delivered — it is independent of the "aud" values in the
parent ECTs.<a href="#section-4.2.1-2.6.3" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.1-2.7">iat:</dt> <dt id="section-4.2.1-2.7">iat:</dt>
@@ -2113,10 +2150,18 @@ to limit the replay window while allowing for reasonable clock
skew and processing time.<a href="#section-4.2.1-2.10.1" class="pilcrow"></a></p> skew and processing time.<a href="#section-4.2.1-2.10.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.1-2.11">jti:</dt> </dl>
<dd style="margin-left: 1.5em" id="section-4.2.1-2.12"> <p id="section-4.2.1-3">The standard JWT "nbf" (Not Before) claim is not used in ECTs
<p id="section-4.2.1-2.12.1"><span class="bcp14">OPTIONAL</span>. String. A unique identifier for the ECT, useful for because ECTs record completed actions and are valid immediately
additional replay detection.<a href="#section-4.2.1-2.12.1" class="pilcrow"></a></p> upon issuance.<a href="#section-4.2.1-3" class="pilcrow"></a></p>
<span class="break"></span><dl class="dlParallel" id="section-4.2.1-4">
<dt id="section-4.2.1-4.1">jti:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.1-4.2">
<p id="section-4.2.1-4.2.1"><span class="bcp14">REQUIRED</span>. String. A unique identifier for the ECT in UUID
format <span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>. Used for replay detection: receivers <span class="bcp14">MUST</span>
reject ECTs whose "jti" has already been seen within the
expiration window. The "jti" value <span class="bcp14">MUST</span> be unique across all
ECTs issued by the same agent.<a href="#section-4.2.1-4.2.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
</dl> </dl>
@@ -2185,7 +2230,30 @@ evaluated for this task (e.g.,
<dt id="section-4.2.3-2.3">pol_decision:</dt> <dt id="section-4.2.3-2.3">pol_decision:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.3-2.4"> <dd style="margin-left: 1.5em" id="section-4.2.3-2.4">
<p id="section-4.2.3-2.4.1"><span class="bcp14">REQUIRED</span>. String. The result of the policy evaluation. <span class="bcp14">MUST</span> <p id="section-4.2.3-2.4.1"><span class="bcp14">REQUIRED</span>. String. The result of the policy evaluation. <span class="bcp14">MUST</span>
be one of: "approved", "rejected", or "pending_human_review".<a href="#section-4.2.3-2.4.1" class="pilcrow"></a></p> be one of the values registered in the ECT Policy Decision
Values registry (<a href="#pol-decision-registry" class="auto internal xref">Section 12.4</a>). Initial values
are:<a href="#section-4.2.3-2.4.1" class="pilcrow"></a></p>
<ul class="normal">
<li class="normal" id="section-4.2.3-2.4.2.1">
<p id="section-4.2.3-2.4.2.1.1">"approved": The policy evaluation succeeded and the task
was authorized to proceed.<a href="#section-4.2.3-2.4.2.1.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.3-2.4.2.2">
<p id="section-4.2.3-2.4.2.2.1">"rejected": The policy evaluation failed. A "rejected" ECT
<span class="bcp14">MUST</span> still be appended to the audit ledger for accountability.
An ECT with "pol_decision" of "rejected" <span class="bcp14">MAY</span> appear as a
parent in the "par" array of a subsequent ECT, but only for
compensation, rollback, or remediation tasks. Agents <span class="bcp14">MUST NOT</span> proceed with normal workflow execution based on a parent
ECT whose "pol_decision" is "rejected".<a href="#section-4.2.3-2.4.2.2.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.3-2.4.2.3">
<p id="section-4.2.3-2.4.2.3.1">"pending_human_review": The policy evaluation requires human
judgment before proceeding. Agents <span class="bcp14">MUST NOT</span> proceed with
dependent tasks until a subsequent ECT from a human reviewer
records an "approved" decision referencing this task as a
parent.<a href="#section-4.2.3-2.4.2.3.1" class="pilcrow"></a></p>
</li>
</ul>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.3-2.5">pol_enforcer:</dt> <dt id="section-4.2.3-2.5">pol_enforcer:</dt>
@@ -2218,8 +2286,12 @@ inputs and outputs without revealing the data itself:<a href="#section-4.2.4-1"
<p id="section-4.2.4-2.2.1"><span class="bcp14">OPTIONAL</span>. String. A cryptographic hash of the input data, <p id="section-4.2.4-2.2.1"><span class="bcp14">OPTIONAL</span>. String. A cryptographic hash of the input data,
formatted as "hash-algorithm:base64url-encoded-hash" (e.g., formatted as "hash-algorithm:base64url-encoded-hash" (e.g.,
"sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg"). The "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg"). The
hash algorithm identifier <span class="bcp14">SHOULD</span> be "sha-256". The hash <span class="bcp14">MUST</span> be hash algorithm identifier <span class="bcp14">MUST</span> be a lowercase value from the
computed over the raw octets of the input data.<a href="#section-4.2.4-2.2.1" class="pilcrow"></a></p> IANA Named Information Hash Algorithm Registry (e.g., "sha-256",
"sha-384", "sha-512"). Implementations <span class="bcp14">MUST</span> support "sha-256"
and <span class="bcp14">SHOULD</span> use "sha-256" unless a stronger algorithm is
required. The hash <span class="bcp14">MUST</span> be computed over the raw octets of the
input data.<a href="#section-4.2.4-2.2.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.4-2.3">out_hash:</dt> <dt id="section-4.2.4-2.3">out_hash:</dt>
@@ -2253,8 +2325,8 @@ milliseconds. <span class="bcp14">MUST</span> be a non-negative integer.<a href
<dt id="section-4.2.5-2.3">regulated_domain:</dt> <dt id="section-4.2.5-2.3">regulated_domain:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.5-2.4"> <dd style="margin-left: 1.5em" id="section-4.2.5-2.4">
<p id="section-4.2.5-2.4.1"><span class="bcp14">OPTIONAL</span>. String. The regulatory domain applicable to this <p id="section-4.2.5-2.4.1"><span class="bcp14">OPTIONAL</span>. String. The regulatory domain applicable to this
task. Values are drawn from an extensible set; initial values task. Values <span class="bcp14">MUST</span> be registered in the ECT Regulated Domain
include "medtech", "finance", and "military".<a href="#section-4.2.5-2.4.1" class="pilcrow"></a></p> Values registry (<a href="#regulated-domain-registry" class="auto internal xref">Section 12.5</a>).<a href="#section-4.2.5-2.4.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.5-2.5">model_version:</dt> <dt id="section-4.2.5-2.5">model_version:</dt>
@@ -2300,7 +2372,9 @@ compensation or rollback action for a previous task.<a href="#section-4.2.7-1.2.
<dt id="section-4.2.7-1.3">compensation_reason:</dt> <dt id="section-4.2.7-1.3">compensation_reason:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.7-1.4"> <dd style="margin-left: 1.5em" id="section-4.2.7-1.4">
<p id="section-4.2.7-1.4.1"><span class="bcp14">OPTIONAL</span>. String. A human-readable reason for the compensation <p id="section-4.2.7-1.4.1"><span class="bcp14">OPTIONAL</span>. String. A human-readable reason for the compensation
action. <span class="bcp14">MUST</span> be present if "compensation_required" is true.<a href="#section-4.2.7-1.4.1" class="pilcrow"></a></p> action. <span class="bcp14">MUST</span> be present if "compensation_required" is true.
If "compensation_reason" is present, "compensation_required"
<span class="bcp14">MUST</span> be true.<a href="#section-4.2.7-1.4.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
</dl> </dl>
@@ -2321,16 +2395,14 @@ ledger.<a href="#section-4.2.7-2" class="pilcrow">¶</a></p>
<dd style="margin-left: 1.5em" id="section-4.2.8-1.2"> <dd style="margin-left: 1.5em" id="section-4.2.8-1.2">
<p id="section-4.2.8-1.2.1"><span class="bcp14">OPTIONAL</span>. Object. An extension object for domain-specific <p id="section-4.2.8-1.2.1"><span class="bcp14">OPTIONAL</span>. Object. An extension object for domain-specific
claims not defined by this specification. Implementations claims not defined by this specification. Implementations
that do not understand extension claims <span class="bcp14">SHOULD</span> ignore them. that do not understand extension claims <span class="bcp14">MUST</span> ignore them.<a href="#section-4.2.8-1.2.1" class="pilcrow"></a></p>
To avoid key collisions between different domains, extension
key names <span class="bcp14">SHOULD</span> use reverse domain notation (e.g.,
"com.example.custom_field").<a href="#section-4.2.8-1.2.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
</dl> </dl>
<p id="section-4.2.8-2">The "ext" claim is a generic extension mechanism; it is not <p id="section-4.2.8-2">To avoid key collisions between different domains, extension
registered in the IANA JWT Claims registry because its semantics key names <span class="bcp14">MUST</span> use reverse domain notation (e.g.,
depend on the domain-specific claims within it.<a href="#section-4.2.8-2" class="pilcrow"></a></p> "com.example.custom_field"). Implementations <span class="bcp14">MUST NOT</span> use
unqualified key names within the "ext" object.<a href="#section-4.2.8-2" class="pilcrow"></a></p>
</section> </section>
</div> </div>
</section> </section>
@@ -2351,6 +2423,7 @@ depend on the domain-specific claims within it.<a href="#section-4.2.8-2" class=
"aud": "spiffe://example.com/agent/safety", "aud": "spiffe://example.com/agent/safety",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
"jti": "7f3a8b2c-d1e4-4f56-9a0b-c3d4e5f6a7b8",
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789", "wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
"tid": "550e8400-e29b-41d4-a716-446655440001", "tid": "550e8400-e29b-41d4-a716-446655440001",
@@ -2419,6 +2492,13 @@ Execution-Context: eyJhbGci...ECT...
<p id="section-5.1-5">When multiple parent tasks contribute context to a single request, <p id="section-5.1-5">When multiple parent tasks contribute context to a single request,
multiple Execution-Context header field lines <span class="bcp14">MAY</span> be included, each multiple Execution-Context header field lines <span class="bcp14">MAY</span> be included, each
carrying a separate ECT in JWS Compact Serialization format.<a href="#section-5.1-5" class="pilcrow"></a></p> carrying a separate ECT in JWS Compact Serialization format.<a href="#section-5.1-5" class="pilcrow"></a></p>
<p id="section-5.1-6">When a receiver processes multiple Execution-Context headers, it
<span class="bcp14">MUST</span> individually verify each ECT per the procedure in
<a href="#verification" class="auto internal xref">Section 7</a>. If any single ECT fails verification, the
receiver <span class="bcp14">MUST</span> reject the entire request. The set of verified
parent task IDs across all received ECTs represents the complete
set of parent dependencies available for the receiving agent's
subsequent ECT.<a href="#section-5.1-6" class="pilcrow"></a></p>
</section> </section>
</div> </div>
</section> </section>
@@ -2462,11 +2542,15 @@ recorded in the ledger. If any parent task is not found, the
ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.2.1" class="pilcrow"></a></p> ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.2.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-6.2-2.3"> <li id="section-6.2-2.3">
<p id="section-6.2-2.3.1">Temporal Ordering: The "iat" value of every parent task <span class="bcp14">MUST</span> be <p id="section-6.2-2.3.1">Temporal Ordering: The "iat" value of every parent task <span class="bcp14">MUST NOT</span> be greater than the "iat" value of the current task plus a
less than the "iat" value of the current task plus a
configurable clock skew tolerance (<span class="bcp14">RECOMMENDED</span>: 30 seconds). configurable clock skew tolerance (<span class="bcp14">RECOMMENDED</span>: 30 seconds).
If any parent task has an "iat" that violates this constraint, That is, for each parent: <code>parent.iat &lt; child.iat +
the ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.3.1" class="pilcrow"></a></p> clock_skew_tolerance</code>. The tolerance accounts for clock skew
between agents; it does not guarantee strict causal ordering
from timestamps alone. Causal ordering is primarily enforced
by the DAG structure (parent existence in the ledger), not by
timestamps. If any parent task violates this constraint, the
ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.3.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-6.2-2.4"> <li id="section-6.2-2.4">
<p id="section-6.2-2.4.1">Acyclicity: Following the chain of parent references <span class="bcp14">MUST NOT</span> <p id="section-6.2-2.4.1">Acyclicity: Following the chain of parent references <span class="bcp14">MUST NOT</span>
@@ -2474,9 +2558,18 @@ lead back to the current task's "tid". If a cycle is detected,
the ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.4.1" class="pilcrow"></a></p> the ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.4.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-6.2-2.5"> <li id="section-6.2-2.5">
<p id="section-6.2-2.5.1">Trust Domain Consistency: Parent tasks <span class="bcp14">SHOULD</span> belong to the <p id="section-6.2-2.5.1">Parent Policy Decision: If any parent task has a "pol_decision"
of "rejected" or "pending_human_review", the current task's
"exec_act" <span class="bcp14">MUST</span> indicate a compensation, rollback, remediation,
or human review action. Implementations <span class="bcp14">MUST NOT</span> accept an ECT
representing normal workflow continuation when a parent's
"pol_decision" is not "approved", unless the current ECT has
"compensation_required" set to true.<a href="#section-6.2-2.5.1" class="pilcrow"></a></p>
</li>
<li id="section-6.2-2.6">
<p id="section-6.2-2.6.1">Trust Domain Consistency: Parent tasks <span class="bcp14">SHOULD</span> belong to the
same trust domain or to a trust domain with which a federation same trust domain or to a trust domain with which a federation
relationship has been established.<a href="#section-6.2-2.5.1" class="pilcrow"></a></p> relationship has been established.<a href="#section-6.2-2.6.1" class="pilcrow"></a></p>
</li> </li>
</ol> </ol>
</section> </section>
@@ -2581,7 +2674,11 @@ associated with the "kid" public key.<a href="#section-7.1-2.7.1" class="pilcrow
</li> </li>
<li id="section-7.1-2.8"> <li id="section-7.1-2.8">
<p id="section-7.1-2.8.1">Verify the "aud" claim contains the verifier's own workload <p id="section-7.1-2.8.1">Verify the "aud" claim contains the verifier's own workload
identity or an expected recipient identifier.<a href="#section-7.1-2.8.1" class="pilcrow"></a></p> identity. When "aud" is an array, it is sufficient that the
verifier's identity appears as one element; the presence of
other audience values does not cause verification failure.
When the verifier is the audit ledger, the ledger's own
identity <span class="bcp14">MUST</span> appear in "aud".<a href="#section-7.1-2.8.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-7.1-2.9"> <li id="section-7.1-2.9">
<p id="section-7.1-2.9.1">Verify the "exp" claim indicates the ECT has not expired.<a href="#section-7.1-2.9.1" class="pilcrow"></a></p> <p id="section-7.1-2.9.1">Verify the "exp" claim indicates the ECT has not expired.<a href="#section-7.1-2.9.1" class="pilcrow"></a></p>
@@ -2592,8 +2689,8 @@ identity or an expected recipient identifier.<a href="#section-7.1-2.8.1" class=
15 minutes).<a href="#section-7.1-2.10.1" class="pilcrow"></a></p> 15 minutes).<a href="#section-7.1-2.10.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-7.1-2.11"> <li id="section-7.1-2.11">
<p id="section-7.1-2.11.1">Verify all required claims ("tid", "exec_act", "par", "pol", <p id="section-7.1-2.11.1">Verify all required claims ("jti", "tid", "exec_act", "par",
"pol_decision") are present and well-formed.<a href="#section-7.1-2.11.1" class="pilcrow"></a></p> "pol", "pol_decision") are present and well-formed.<a href="#section-7.1-2.11.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-7.1-2.12"> <li id="section-7.1-2.12">
<p id="section-7.1-2.12.1">Verify "pol_decision" is one of "approved", "rejected", or <p id="section-7.1-2.12.1">Verify "pol_decision" is one of "approved", "rejected", or
@@ -2611,6 +2708,14 @@ ledger.<a href="#section-7.1-2.14.1" class="pilcrow">¶</a></p>
failure <span class="bcp14">MUST</span> be logged for audit purposes. Error messages failure <span class="bcp14">MUST</span> be logged for audit purposes. Error messages
<span class="bcp14">SHOULD NOT</span> reveal whether specific parent task IDs exist in the <span class="bcp14">SHOULD NOT</span> reveal whether specific parent task IDs exist in the
ledger, to prevent information disclosure.<a href="#section-7.1-3" class="pilcrow"></a></p> ledger, to prevent information disclosure.<a href="#section-7.1-3" class="pilcrow"></a></p>
<p id="section-7.1-4">When ECT verification fails during HTTP request processing, the
receiving agent <span class="bcp14">SHOULD</span> respond with HTTP 403 (Forbidden) if the
WIT and WPT are valid but the ECT is invalid, and HTTP 401
(Unauthorized) if the ECT signature verification fails. The
response body <span class="bcp14">SHOULD</span> include a generic error indicator without
revealing which specific verification step failed. The receiving
agent <span class="bcp14">MUST NOT</span> process the requested action when ECT verification
fails.<a href="#section-7.1-4" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="verification-pseudocode"> <div id="verification-pseudocode">
@@ -2666,7 +2771,7 @@ function verify_ect(ect_jws, verifier_id,
return reject("ECT issued too long ago") return reject("ECT issued too long ago")
// Verify required claims // Verify required claims
for claim in ["tid", "exec_act", "par", for claim in ["jti", "tid", "exec_act", "par",
"pol", "pol_decision"]: "pol", "pol_decision"]:
if claim not in payload: if claim not in payload:
return reject("Missing required claim: " + claim) return reject("Missing required claim: " + claim)
@@ -2790,8 +2895,8 @@ examples demonstrate ECT mechanics; production deployments would
include additional domain-specific requirements beyond the scope include additional domain-specific requirements beyond the scope
of this specification.<a href="#section-9-1" class="pilcrow"></a></p> of this specification.<a href="#section-9-1" class="pilcrow"></a></p>
<p id="section-9-2">Note: task identifiers in this section are abbreviated for <p id="section-9-2">Note: task identifiers in this section are abbreviated for
readability. In production, all "tid" values <span class="bcp14">MUST</span> be UUIDs per readability. In production, all "tid" values are required to be
<span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>.<a href="#section-9-2" class="pilcrow"></a></p> UUIDs per <a href="#exec-claims" class="auto internal xref">Section 4.2.2</a>.<a href="#section-9-2" class="pilcrow"></a></p>
<div id="medical-device-sdlc-workflow"> <div id="medical-device-sdlc-workflow">
<section id="section-9.1"> <section id="section-9.1">
<h3 id="name-medical-device-sdlc-workflo"> <h3 id="name-medical-device-sdlc-workflo">
@@ -2981,9 +3086,9 @@ a cryptographic link to the original task:<a href="#section-9.3-1" class="pilcro
<div class="lang-json sourcecode" id="section-9.3-2.1"> <div class="lang-json sourcecode" id="section-9.3-2.1">
<pre> <pre>
{ {
"iss": "spiffe://bank.com/agent/operations", "iss": "spiffe://bank.example/agent/operations",
"sub": "spiffe://bank.com/agent/operations", "sub": "spiffe://bank.example/agent/operations",
"aud": "spiffe://bank.com/system/ledger", "aud": "spiffe://bank.example/system/ledger",
"iat": 1772150550, "iat": 1772150550,
"exp": 1772151150, "exp": 1772151150,
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012", "wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
@@ -2992,7 +3097,7 @@ a cryptographic link to the original task:<a href="#section-9.3-1" class="pilcro
"par": ["550e8400-e29b-41d4-a716-446655440003"], "par": ["550e8400-e29b-41d4-a716-446655440003"],
"pol": "compensation_policy_v1", "pol": "compensation_policy_v1",
"pol_decision": "approved", "pol_decision": "approved",
"pol_enforcer": "spiffe://bank.com/human/compliance-officer", "pol_enforcer": "spiffe://bank.example/human/compliance-officer",
"compensation_required": true, "compensation_required": true,
"compensation_reason": "policy_violation_in_parent_trade" "compensation_reason": "policy_violation_in_parent_trade"
} }
@@ -3012,7 +3117,7 @@ violation discovery to remediation.<a href="#section-9.3-3" class="pilcrow">¶</
<h3 id="name-autonomous-logistics-coordi"> <h3 id="name-autonomous-logistics-coordi">
<a href="#section-9.4" class="section-number selfRef">9.4. </a><a href="#name-autonomous-logistics-coordi" class="section-name selfRef">Autonomous Logistics Coordination</a> <a href="#section-9.4" class="section-number selfRef">9.4. </a><a href="#name-autonomous-logistics-coordi" class="section-name selfRef">Autonomous Logistics Coordination</a>
</h3> </h3>
<p id="section-9.4-1">In a logistics workflow, multiple compliance checks must complete <p id="section-9.4-1">In a logistics workflow, multiple compliance checks complete
before shipment commitment. The DAG structure records that all before shipment commitment. The DAG structure records that all
required checks were completed:<a href="#section-9.4-1" class="pilcrow"></a></p> required checks were completed:<a href="#section-9.4-1" class="pilcrow"></a></p>
<span id="name-logistics-workflow-with-par"></span><div id="fig-logistics"> <span id="name-logistics-workflow-with-par"></span><div id="fig-logistics">
@@ -3179,9 +3284,9 @@ reject ECTs that are too old, even if not yet expired.<a href="#section-10.5-1"
<p id="section-10.5-2">The DAG structure provides additional replay protection: an ECT <p id="section-10.5-2">The DAG structure provides additional replay protection: an ECT
referencing parent tasks that already have a recorded child task referencing parent tasks that already have a recorded child task
with the same action can be flagged as a potential replay.<a href="#section-10.5-2" class="pilcrow"></a></p> with the same action can be flagged as a potential replay.<a href="#section-10.5-2" class="pilcrow"></a></p>
<p id="section-10.5-3">Implementations <span class="bcp14">SHOULD</span> maintain a cache of recently-seen "jti" <p id="section-10.5-3">Implementations <span class="bcp14">MUST</span> maintain a cache of recently-seen "jti"
values (when present) to detect replayed ECTs within the values to detect replayed ECTs within the expiration window.
expiration window.<a href="#section-10.5-3" class="pilcrow"></a></p> An ECT with a duplicate "jti" value <span class="bcp14">MUST</span> be rejected.<a href="#section-10.5-3" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="man-in-the-middle-protection"> <div id="man-in-the-middle-protection">
@@ -3678,6 +3783,120 @@ the "JSON Web Token Claims" registry maintained by IANA:<a href="#section-12.3-1
<td class="text-center" rowspan="1" colspan="1">IETF</td> <td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1"> <td class="text-center" rowspan="1" colspan="1">
<a href="#compensation-claims" class="auto internal xref">Section 4.2.7</a> <a href="#compensation-claims" class="auto internal xref">Section 4.2.7</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">ext</td>
<td class="text-left" rowspan="1" colspan="1">Extension Object</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#extension-claims" class="auto internal xref">Section 4.2.8</a>
</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
<div id="pol-decision-registry">
<section id="section-12.4">
<h3 id="name-ect-policy-decision-values-">
<a href="#section-12.4" class="section-number selfRef">12.4. </a><a href="#name-ect-policy-decision-values-" class="section-name selfRef">ECT Policy Decision Values Registry</a>
</h3>
<p id="section-12.4-1">This document establishes the "ECT Policy Decision Values"
registry under the "JSON Web Token (JWT)" group. Registration
policy is Specification Required per <span>[<a href="#RFC8126" class="cite xref">RFC8126</a>]</span>.<a href="#section-12.4-1" class="pilcrow"></a></p>
<p id="section-12.4-2">The initial contents of the registry are:<a href="#section-12.4-2" class="pilcrow"></a></p>
<span id="name-ect-policy-decision-values"></span><div id="_table-pol-decision">
<table class="center" id="table-2">
<caption>
<a href="#table-2" class="selfRef">Table 2</a>:
<a href="#name-ect-policy-decision-values" class="selfRef">ECT Policy Decision Values</a>
</caption>
<thead>
<tr>
<th class="text-center" rowspan="1" colspan="1">Value</th>
<th class="text-left" rowspan="1" colspan="1">Description</th>
<th class="text-center" rowspan="1" colspan="1">Change Controller</th>
<th class="text-center" rowspan="1" colspan="1">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center" rowspan="1" colspan="1">approved</td>
<td class="text-left" rowspan="1" colspan="1">Policy evaluation succeeded</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#policy-claims" class="auto internal xref">Section 4.2.3</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">rejected</td>
<td class="text-left" rowspan="1" colspan="1">Policy evaluation failed</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#policy-claims" class="auto internal xref">Section 4.2.3</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">pending_human_review</td>
<td class="text-left" rowspan="1" colspan="1">Awaiting human judgment</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#policy-claims" class="auto internal xref">Section 4.2.3</a>
</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
<div id="regulated-domain-registry">
<section id="section-12.5">
<h3 id="name-ect-regulated-domain-values">
<a href="#section-12.5" class="section-number selfRef">12.5. </a><a href="#name-ect-regulated-domain-values" class="section-name selfRef">ECT Regulated Domain Values Registry</a>
</h3>
<p id="section-12.5-1">This document establishes the "ECT Regulated Domain Values"
registry under the "JSON Web Token (JWT)" group. Registration
policy is Specification Required per <span>[<a href="#RFC8126" class="cite xref">RFC8126</a>]</span>.<a href="#section-12.5-1" class="pilcrow"></a></p>
<p id="section-12.5-2">The initial contents of the registry are:<a href="#section-12.5-2" class="pilcrow"></a></p>
<span id="name-ect-regulated-domain-values-2"></span><div id="_table-regulated-domain">
<table class="center" id="table-3">
<caption>
<a href="#table-3" class="selfRef">Table 3</a>:
<a href="#name-ect-regulated-domain-values-2" class="selfRef">ECT Regulated Domain Values</a>
</caption>
<thead>
<tr>
<th class="text-center" rowspan="1" colspan="1">Value</th>
<th class="text-left" rowspan="1" colspan="1">Description</th>
<th class="text-center" rowspan="1" colspan="1">Change Controller</th>
<th class="text-center" rowspan="1" colspan="1">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center" rowspan="1" colspan="1">medtech</td>
<td class="text-left" rowspan="1" colspan="1">Medical technology and devices</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#operational-claims" class="auto internal xref">Section 4.2.5</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">finance</td>
<td class="text-left" rowspan="1" colspan="1">Financial services and trading</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#operational-claims" class="auto internal xref">Section 4.2.5</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">military</td>
<td class="text-left" rowspan="1" colspan="1">Military and defense</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#operational-claims" class="auto internal xref">Section 4.2.5</a>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -3710,14 +3929,14 @@ the "JSON Web Token Claims" registry maintained by IANA:<a href="#section-12.3-1
<dd> <dd>
<span class="refAuthor">Bradner, S.</span>, <span class="refTitle">"Key words for use in RFCs to Indicate Requirement Levels"</span>, <span class="seriesInfo">BCP 14</span>, <span class="seriesInfo">RFC 2119</span>, <span class="seriesInfo">DOI 10.17487/RFC2119</span>, <time datetime="1997-03" class="refDate">March 1997</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc2119">https://www.rfc-editor.org/rfc/rfc2119</a>&gt;</span>. </dd> <span class="refAuthor">Bradner, S.</span>, <span class="refTitle">"Key words for use in RFCs to Indicate Requirement Levels"</span>, <span class="seriesInfo">BCP 14</span>, <span class="seriesInfo">RFC 2119</span>, <span class="seriesInfo">DOI 10.17487/RFC2119</span>, <time datetime="1997-03" class="refDate">March 1997</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc2119">https://www.rfc-editor.org/rfc/rfc2119</a>&gt;</span>. </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="RFC3339">[RFC3339]</dt>
<dd>
<span class="refAuthor">Klyne, G.</span> and <span class="refAuthor">C. Newman</span>, <span class="refTitle">"Date and Time on the Internet: Timestamps"</span>, <span class="seriesInfo">RFC 3339</span>, <span class="seriesInfo">DOI 10.17487/RFC3339</span>, <time datetime="2002-07" class="refDate">July 2002</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc3339">https://www.rfc-editor.org/rfc/rfc3339</a>&gt;</span>. </dd>
<dd class="break"></dd>
<dt id="RFC7515">[RFC7515]</dt> <dt id="RFC7515">[RFC7515]</dt>
<dd> <dd>
<span class="refAuthor">Jones, M.</span>, <span class="refAuthor">Bradley, J.</span>, and <span class="refAuthor">N. Sakimura</span>, <span class="refTitle">"JSON Web Signature (JWS)"</span>, <span class="seriesInfo">RFC 7515</span>, <span class="seriesInfo">DOI 10.17487/RFC7515</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7515">https://www.rfc-editor.org/rfc/rfc7515</a>&gt;</span>. </dd> <span class="refAuthor">Jones, M.</span>, <span class="refAuthor">Bradley, J.</span>, and <span class="refAuthor">N. Sakimura</span>, <span class="refTitle">"JSON Web Signature (JWS)"</span>, <span class="seriesInfo">RFC 7515</span>, <span class="seriesInfo">DOI 10.17487/RFC7515</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7515">https://www.rfc-editor.org/rfc/rfc7515</a>&gt;</span>. </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="RFC7517">[RFC7517]</dt>
<dd>
<span class="refAuthor">Jones, M.</span>, <span class="refTitle">"JSON Web Key (JWK)"</span>, <span class="seriesInfo">RFC 7517</span>, <span class="seriesInfo">DOI 10.17487/RFC7517</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7517">https://www.rfc-editor.org/rfc/rfc7517</a>&gt;</span>. </dd>
<dd class="break"></dd>
<dt id="RFC7518">[RFC7518]</dt> <dt id="RFC7518">[RFC7518]</dt>
<dd> <dd>
<span class="refAuthor">Jones, M.</span>, <span class="refTitle">"JSON Web Algorithms (JWA)"</span>, <span class="seriesInfo">RFC 7518</span>, <span class="seriesInfo">DOI 10.17487/RFC7518</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7518">https://www.rfc-editor.org/rfc/rfc7518</a>&gt;</span>. </dd> <span class="refAuthor">Jones, M.</span>, <span class="refTitle">"JSON Web Algorithms (JWA)"</span>, <span class="seriesInfo">RFC 7518</span>, <span class="seriesInfo">DOI 10.17487/RFC7518</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7518">https://www.rfc-editor.org/rfc/rfc7518</a>&gt;</span>. </dd>
@@ -3726,6 +3945,10 @@ the "JSON Web Token Claims" registry maintained by IANA:<a href="#section-12.3-1
<dd> <dd>
<span class="refAuthor">Jones, M.</span>, <span class="refAuthor">Bradley, J.</span>, and <span class="refAuthor">N. Sakimura</span>, <span class="refTitle">"JSON Web Token (JWT)"</span>, <span class="seriesInfo">RFC 7519</span>, <span class="seriesInfo">DOI 10.17487/RFC7519</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7519">https://www.rfc-editor.org/rfc/rfc7519</a>&gt;</span>. </dd> <span class="refAuthor">Jones, M.</span>, <span class="refAuthor">Bradley, J.</span>, and <span class="refAuthor">N. Sakimura</span>, <span class="refTitle">"JSON Web Token (JWT)"</span>, <span class="seriesInfo">RFC 7519</span>, <span class="seriesInfo">DOI 10.17487/RFC7519</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7519">https://www.rfc-editor.org/rfc/rfc7519</a>&gt;</span>. </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="RFC8126">[RFC8126]</dt>
<dd>
<span class="refAuthor">Cotton, M.</span>, <span class="refAuthor">Leiba, B.</span>, and <span class="refAuthor">T. Narten</span>, <span class="refTitle">"Guidelines for Writing an IANA Considerations Section in RFCs"</span>, <span class="seriesInfo">BCP 26</span>, <span class="seriesInfo">RFC 8126</span>, <span class="seriesInfo">DOI 10.17487/RFC8126</span>, <time datetime="2017-06" class="refDate">June 2017</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc8126">https://www.rfc-editor.org/rfc/rfc8126</a>&gt;</span>. </dd>
<dd class="break"></dd>
<dt id="RFC8174">[RFC8174]</dt> <dt id="RFC8174">[RFC8174]</dt>
<dd> <dd>
<span class="refAuthor">Leiba, B.</span>, <span class="refTitle">"Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words"</span>, <span class="seriesInfo">BCP 14</span>, <span class="seriesInfo">RFC 8174</span>, <span class="seriesInfo">DOI 10.17487/RFC8174</span>, <time datetime="2017-05" class="refDate">May 2017</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc8174">https://www.rfc-editor.org/rfc/rfc8174</a>&gt;</span>. </dd> <span class="refAuthor">Leiba, B.</span>, <span class="refTitle">"Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words"</span>, <span class="seriesInfo">BCP 14</span>, <span class="seriesInfo">RFC 8174</span>, <span class="seriesInfo">DOI 10.17487/RFC8174</span>, <time datetime="2017-05" class="refDate">May 2017</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc8174">https://www.rfc-editor.org/rfc/rfc8174</a>&gt;</span>. </dd>
@@ -3783,10 +4006,6 @@ the "JSON Web Token Claims" registry maintained by IANA:<a href="#section-12.3-1
<dd> <dd>
<span class="refAuthor">Rescorla, E.</span> and <span class="refAuthor">B. Korver</span>, <span class="refTitle">"Guidelines for Writing RFC Text on Security Considerations"</span>, <span class="seriesInfo">BCP 72</span>, <span class="seriesInfo">RFC 3552</span>, <span class="seriesInfo">DOI 10.17487/RFC3552</span>, <time datetime="2003-07" class="refDate">July 2003</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc3552">https://www.rfc-editor.org/rfc/rfc3552</a>&gt;</span>. </dd> <span class="refAuthor">Rescorla, E.</span> and <span class="refAuthor">B. Korver</span>, <span class="refTitle">"Guidelines for Writing RFC Text on Security Considerations"</span>, <span class="seriesInfo">BCP 72</span>, <span class="seriesInfo">RFC 3552</span>, <span class="seriesInfo">DOI 10.17487/RFC3552</span>, <time datetime="2003-07" class="refDate">July 2003</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc3552">https://www.rfc-editor.org/rfc/rfc3552</a>&gt;</span>. </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="RFC7517">[RFC7517]</dt>
<dd>
<span class="refAuthor">Jones, M.</span>, <span class="refTitle">"JSON Web Key (JWK)"</span>, <span class="seriesInfo">RFC 7517</span>, <span class="seriesInfo">DOI 10.17487/RFC7517</span>, <time datetime="2015-05" class="refDate">May 2015</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc7517">https://www.rfc-editor.org/rfc/rfc7517</a>&gt;</span>. </dd>
<dd class="break"></dd>
<dt id="RFC8693">[RFC8693]</dt> <dt id="RFC8693">[RFC8693]</dt>
<dd> <dd>
<span class="refAuthor">Jones, M.</span>, <span class="refAuthor">Nadalin, A.</span>, <span class="refAuthor">Campbell, B., Ed.</span>, <span class="refAuthor">Bradley, J.</span>, and <span class="refAuthor">C. Mortimore</span>, <span class="refTitle">"OAuth 2.0 Token Exchange"</span>, <span class="seriesInfo">RFC 8693</span>, <span class="seriesInfo">DOI 10.17487/RFC8693</span>, <time datetime="2020-01" class="refDate">January 2020</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc8693">https://www.rfc-editor.org/rfc/rfc8693</a>&gt;</span>. </dd> <span class="refAuthor">Jones, M.</span>, <span class="refAuthor">Nadalin, A.</span>, <span class="refAuthor">Campbell, B., Ed.</span>, <span class="refAuthor">Bradley, J.</span>, and <span class="refAuthor">C. Mortimore</span>, <span class="refTitle">"OAuth 2.0 Token Exchange"</span>, <span class="seriesInfo">RFC 8693</span>, <span class="seriesInfo">DOI 10.17487/RFC8693</span>, <time datetime="2020-01" class="refDate">January 2020</time>, <span>&lt;<a href="https://www.rfc-editor.org/rfc/rfc8693">https://www.rfc-editor.org/rfc/rfc8693</a>&gt;</span>. </dd>
@@ -3917,11 +4136,12 @@ use cases are distinct.<a href="#appendix-A.6-1" class="pilcrow">¶</a></p>
<h3 id="name-minimal-implementation"> <h3 id="name-minimal-implementation">
<a href="#name-minimal-implementation" class="section-name selfRef">Minimal Implementation</a> <a href="#name-minimal-implementation" class="section-name selfRef">Minimal Implementation</a>
</h3> </h3>
<p id="appendix-B.1-1">A minimal conforming implementation should:<a href="#appendix-B.1-1" class="pilcrow"></a></p> <p id="appendix-B.1-1">A minimal conforming implementation needs to:<a href="#appendix-B.1-1" class="pilcrow"></a></p>
<ol start="1" type="1" class="normal type-1" id="appendix-B.1-2"> <ol start="1" type="1" class="normal type-1" id="appendix-B.1-2">
<li id="appendix-B.1-2.1"> <li id="appendix-B.1-2.1">
<p id="appendix-B.1-2.1.1">Create JWTs with all required claims ("iss", "aud", "iat", <p id="appendix-B.1-2.1.1">Create JWTs with all required claims ("iss", "aud", "iat",
"exp", "tid", "exec_act", "par", "pol", "pol_decision").<a href="#appendix-B.1-2.1.1" class="pilcrow"></a></p> "exp", "jti", "tid", "exec_act", "par", "pol",
"pol_decision").<a href="#appendix-B.1-2.1.1" class="pilcrow"></a></p>
</li> </li>
<li id="appendix-B.1-2.2"> <li id="appendix-B.1-2.2">
<p id="appendix-B.1-2.2.1">Sign ECTs with the agent's private key using an algorithm <p id="appendix-B.1-2.2.1">Sign ECTs with the agent's private key using an algorithm
@@ -3994,10 +4214,11 @@ latency.<a href="#appendix-B.3-1.4.1" class="pilcrow">¶</a></p>
<h3 id="name-interoperability"> <h3 id="name-interoperability">
<a href="#name-interoperability" class="section-name selfRef">Interoperability</a> <a href="#name-interoperability" class="section-name selfRef">Interoperability</a>
</h3> </h3>
<p id="appendix-B.4-1">Implementations should use established JWT/JWS libraries (JOSE) <p id="appendix-B.4-1">Implementations are expected to use established JWT/JWS libraries
for token creation and verification. Custom cryptographic (JOSE) for token creation and verification. Custom cryptographic
implementations should not be used. Implementations should be implementations are strongly discouraged. Implementations are
tested against multiple JWT libraries to ensure interoperability.<a href="#appendix-B.4-1" class="pilcrow"></a></p> expected to be tested against multiple JWT libraries to ensure
interoperability.<a href="#appendix-B.4-1" class="pilcrow"></a></p>
</section> </section>
</div> </div>
</section> </section>
@@ -4012,9 +4233,9 @@ compliance with various regulatory frameworks. ECTs are a
technical building block; achieving compliance requires technical building block; achieving compliance requires
additional organizational measures beyond this specification.<a href="#appendix-C-1" class="pilcrow"></a></p> additional organizational measures beyond this specification.<a href="#appendix-C-1" class="pilcrow"></a></p>
<span id="name-regulatory-compliance-mappin"></span><div id="_table-regulatory"> <span id="name-regulatory-compliance-mappin"></span><div id="_table-regulatory">
<table class="center" id="table-2"> <table class="center" id="table-4">
<caption> <caption>
<a href="#table-2" class="selfRef">Table 2</a>: <a href="#table-4" class="selfRef">Table 4</a>:
<a href="#name-regulatory-compliance-mappin" class="selfRef">Regulatory Compliance Mapping</a> <a href="#name-regulatory-compliance-mappin" class="selfRef">Regulatory Compliance Mapping</a>
</caption> </caption>
<thead> <thead>

View File

@@ -8,6 +8,7 @@ number:
date: date:
v: 3 v: 3
area: "Security" area: "Security"
workgroup: "WIMSE"
keyword: keyword:
- execution context - execution context
- workload identity - workload identity
@@ -23,9 +24,8 @@ author:
email: ietf@nennemann.de email: ietf@nennemann.de
normative: normative:
RFC2119:
RFC8174:
RFC7515: RFC7515:
RFC7517:
RFC7519: RFC7519:
RFC7518: RFC7518:
RFC9562: RFC9562:
@@ -35,7 +35,6 @@ normative:
informative: informative:
RFC3552: RFC3552:
RFC7517:
RFC8693: RFC8693:
RFC9421: RFC9421:
I-D.ni-wimse-ai-agent-identity: I-D.ni-wimse-ai-agent-identity:
@@ -150,7 +149,7 @@ accountability. WIMSE authenticates agents; this extension records
what they did, in what order, and what policy was evaluated. what they did, in what order, and what policy was evaluated.
As identified in {{I-D.ni-wimse-ai-agent-identity}}, call context As identified in {{I-D.ni-wimse-ai-agent-identity}}, call context
in agentic workflows must always be visible and preserved. ECTs in agentic workflows needs to be visible and preserved. ECTs
provide a mechanism to address this requirement with cryptographic provide a mechanism to address this requirement with cryptographic
assurances. assurances.
@@ -409,12 +408,39 @@ iss:
sub: sub:
: OPTIONAL. StringOrURI. The subject of the ECT. When present, : OPTIONAL. StringOrURI. The subject of the ECT. When present,
MUST equal the "iss" claim. MUST equal the "iss" claim. This claim is included for
compatibility with JWT libraries and frameworks that expect a
"sub" claim to be present.
aud: aud:
: REQUIRED. StringOrURI or array of StringOrURI. The intended : REQUIRED. StringOrURI or array of StringOrURI. The intended
recipient(s) of the ECT. Typically the next agent in the recipient(s) of the ECT. Because ECTs serve as both inter-agent
workflow or the ledger endpoint. messages and audit records, the "aud" claim SHOULD contain the
identifiers of all entities that will verify the ECT. In
practice this means:
* **Point-to-point delivery**: when an ECT is sent from one
agent to a single next agent, "aud" contains that agent's
workload identity. The receiving agent verifies the ECT and
forwards it to the ledger on behalf of the issuer.
* **Direct-to-ledger submission**: when an ECT is submitted
directly to the audit ledger (e.g., after a join or at
workflow completion), "aud" contains the ledger's identity.
* **Multi-audience**: when an ECT must be verified by both the
next agent and the ledger independently, "aud" MUST be an
array containing both identifiers (e.g.,
\["spiffe://example.com/agent/next",
"spiffe://example.com/system/ledger"\]). Each verifier checks
that its own identity appears in the array.
In multi-parent (join) scenarios where a task depends on ECTs
from multiple parent agents, the joining agent creates a new ECT
with the parent task IDs in "par". The "aud" of this new ECT
is set according to the rules above based on where the ECT will
be delivered — it is independent of the "aud" values in the
parent ECTs.
iat: iat:
: REQUIRED. NumericDate. The time at which the ECT was issued. : REQUIRED. NumericDate. The time at which the ECT was issued.
@@ -427,9 +453,16 @@ exp:
to limit the replay window while allowing for reasonable clock to limit the replay window while allowing for reasonable clock
skew and processing time. skew and processing time.
The standard JWT "nbf" (Not Before) claim is not used in ECTs
because ECTs record completed actions and are valid immediately
upon issuance.
jti: jti:
: OPTIONAL. String. A unique identifier for the ECT, useful for : REQUIRED. String. A unique identifier for the ECT in UUID
additional replay detection. format {{RFC9562}}. Used for replay detection: receivers MUST
reject ECTs whose "jti" has already been seen within the
expiration window. The "jti" value MUST be unique across all
ECTs issued by the same agent.
### Execution Context Claims {#exec-claims} ### Execution Context Claims {#exec-claims}
@@ -474,7 +507,26 @@ pol:
pol_decision: pol_decision:
: REQUIRED. String. The result of the policy evaluation. MUST : REQUIRED. String. The result of the policy evaluation. MUST
be one of: "approved", "rejected", or "pending_human_review". be one of the values registered in the ECT Policy Decision
Values registry ({{pol-decision-registry}}). Initial values
are:
* "approved": The policy evaluation succeeded and the task
was authorized to proceed.
* "rejected": The policy evaluation failed. A "rejected" ECT
MUST still be appended to the audit ledger for accountability.
An ECT with "pol_decision" of "rejected" MAY appear as a
parent in the "par" array of a subsequent ECT, but only for
compensation, rollback, or remediation tasks. Agents MUST
NOT proceed with normal workflow execution based on a parent
ECT whose "pol_decision" is "rejected".
* "pending_human_review": The policy evaluation requires human
judgment before proceeding. Agents MUST NOT proceed with
dependent tasks until a subsequent ECT from a human reviewer
records an "approved" decision referencing this task as a
parent.
pol_enforcer: pol_enforcer:
: OPTIONAL. StringOrURI. The identity of the entity (system or : OPTIONAL. StringOrURI. The identity of the entity (system or
@@ -495,12 +547,17 @@ inp_hash:
: OPTIONAL. String. A cryptographic hash of the input data, : OPTIONAL. String. A cryptographic hash of the input data,
formatted as "hash-algorithm:base64url-encoded-hash" (e.g., formatted as "hash-algorithm:base64url-encoded-hash" (e.g.,
"sha-256:n4bQgYhMfWWaL-qgxVrQFaO\_TxsrC4Is0V1sFbDwCgg"). The "sha-256:n4bQgYhMfWWaL-qgxVrQFaO\_TxsrC4Is0V1sFbDwCgg"). The
hash algorithm identifier SHOULD be "sha-256". The hash MUST be hash algorithm identifier MUST be a lowercase value from the
IANA Named Information Hash Algorithm Registry (e.g., "sha-256",
"sha-384", "sha-512"). Implementations MUST support "sha-256"
and SHOULD use "sha-256" unless a stronger algorithm is
required. Implementations MUST NOT accept hash algorithms
weaker than SHA-256 (e.g., MD5, SHA-1). The hash MUST be
computed over the raw octets of the input data. computed over the raw octets of the input data.
out_hash: out_hash:
: OPTIONAL. String. A cryptographic hash of the output data, : OPTIONAL. String. A cryptographic hash of the output data,
using the same format as "inp_hash". using the same format and algorithm requirements as "inp_hash".
inp_classification: inp_classification:
: OPTIONAL. String. The data sensitivity classification of the : OPTIONAL. String. The data sensitivity classification of the
@@ -516,8 +573,8 @@ exec_time_ms:
regulated_domain: regulated_domain:
: OPTIONAL. String. The regulatory domain applicable to this : OPTIONAL. String. The regulatory domain applicable to this
task. Values are drawn from an extensible set; initial values task. Values MUST be registered in the ECT Regulated Domain
include "medtech", "finance", and "military". Values registry ({{regulated-domain-registry}}).
model_version: model_version:
: OPTIONAL. String. The version identifier of the AI or ML model : OPTIONAL. String. The version identifier of the AI or ML model
@@ -527,11 +584,17 @@ model_version:
witnessed_by: witnessed_by:
: OPTIONAL. Array of StringOrURI. Identifiers of third-party : OPTIONAL. Array of StringOrURI. Identifiers of third-party
entities that observed or attested to the execution of this entities that the issuing agent claims observed or attested to
task. When present, each element SHOULD use SPIFFE ID format. the execution of this task. When present, each element SHOULD
In regulated environments, implementations SHOULD use witness use SPIFFE ID format. Note that this claim is self-asserted by
attestation for critical decision points to mitigate the risk the ECT issuer; witnesses listed here do not co-sign this ECT.
of single-agent false claims. For stronger assurance, witnesses SHOULD submit independent
signed ECTs to the ledger attesting to their observation (see
{{witness-attestation-model}}). In regulated environments,
implementations SHOULD use witness attestation for critical
decision points to mitigate the risk of single-agent false
claims. See also {{self-assertion-limitation}} for the security
implications of self-asserted witness claims.
### Compensation Claims {#compensation-claims} ### Compensation Claims {#compensation-claims}
@@ -542,6 +605,12 @@ compensation_required:
compensation_reason: compensation_reason:
: OPTIONAL. String. A human-readable reason for the compensation : OPTIONAL. String. A human-readable reason for the compensation
action. MUST be present if "compensation_required" is true. action. MUST be present if "compensation_required" is true.
Values SHOULD use structured identifiers (e.g.,
"policy_violation_in_parent_trade") rather than free-form text
to minimize the risk of embedding sensitive information. See
{{data-minimization}} for privacy guidance.
If "compensation_reason" is present, "compensation_required"
MUST be true.
Note: compensation ECTs reference historical parent tasks via the Note: compensation ECTs reference historical parent tasks via the
"par" claim. The referenced parent ECTs may have passed their own "par" claim. The referenced parent ECTs may have passed their own
@@ -554,14 +623,17 @@ ledger.
ext: ext:
: OPTIONAL. Object. An extension object for domain-specific : OPTIONAL. Object. An extension object for domain-specific
claims not defined by this specification. Implementations claims not defined by this specification. Implementations
that do not understand extension claims SHOULD ignore them. that do not understand extension claims MUST ignore them.
To avoid key collisions between different domains, extension
key names SHOULD use reverse domain notation (e.g.,
"com.example.custom_field").
The "ext" claim is a generic extension mechanism; it is not To avoid key collisions between different domains, extension
registered in the IANA JWT Claims registry because its semantics key names MUST use reverse domain notation (e.g.,
depend on the domain-specific claims within it. "com.example.custom_field"). Implementations MUST NOT use
unqualified key names within the "ext" object. To prevent
abuse and excessive token size, the serialized JSON
representation of the "ext" object SHOULD NOT exceed 4096
bytes, and the JSON nesting depth within the "ext" object
SHOULD NOT exceed 5 levels. Implementations SHOULD reject
ECTs whose "ext" claim exceeds these limits.
## Complete ECT Example ## Complete ECT Example
@@ -574,6 +646,7 @@ The following is a complete ECT payload example:
"aud": "spiffe://example.com/agent/safety", "aud": "spiffe://example.com/agent/safety",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
"jti": "7f3a8b2c-d1e4-4f56-9a0b-c3d4e5f6a7b8",
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789", "wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
"tid": "550e8400-e29b-41d4-a716-446655440001", "tid": "550e8400-e29b-41d4-a716-446655440001",
@@ -627,6 +700,14 @@ When multiple parent tasks contribute context to a single request,
multiple Execution-Context header field lines MAY be included, each multiple Execution-Context header field lines MAY be included, each
carrying a separate ECT in JWS Compact Serialization format. carrying a separate ECT in JWS Compact Serialization format.
When a receiver processes multiple Execution-Context headers, it
MUST individually verify each ECT per the procedure in
{{verification}}. If any single ECT fails verification, the
receiver MUST reject the entire request. The set of verified
parent task IDs across all received ECTs represents the complete
set of parent dependencies available for the receiving agent's
subsequent ECT.
# DAG Validation {#dag-validation} # DAG Validation {#dag-validation}
## Overview ## Overview
@@ -653,17 +734,30 @@ the following DAG validation steps:
recorded in the ledger. If any parent task is not found, the recorded in the ledger. If any parent task is not found, the
ECT MUST be rejected. ECT MUST be rejected.
3. Temporal Ordering: The "iat" value of every parent task MUST be 3. Temporal Ordering: The "iat" value of every parent task MUST
less than the "iat" value of the current task plus a NOT be greater than the "iat" value of the current task plus a
configurable clock skew tolerance (RECOMMENDED: 30 seconds). configurable clock skew tolerance (RECOMMENDED: 30 seconds).
If any parent task has an "iat" that violates this constraint, That is, for each parent: `parent.iat < child.iat +
the ECT MUST be rejected. clock_skew_tolerance`. The tolerance accounts for clock skew
between agents; it does not guarantee strict causal ordering
from timestamps alone. Causal ordering is primarily enforced
by the DAG structure (parent existence in the ledger), not by
timestamps. If any parent task violates this constraint, the
ECT MUST be rejected.
4. Acyclicity: Following the chain of parent references MUST NOT 4. Acyclicity: Following the chain of parent references MUST NOT
lead back to the current task's "tid". If a cycle is detected, lead back to the current task's "tid". If a cycle is detected,
the ECT MUST be rejected. the ECT MUST be rejected.
5. Trust Domain Consistency: Parent tasks SHOULD belong to the 5. Parent Policy Decision: If any parent task has a "pol_decision"
of "rejected" or "pending_human_review", the current task's
"exec_act" MUST indicate a compensation, rollback, remediation,
or human review action. Implementations MUST NOT accept an ECT
representing normal workflow continuation when a parent's
"pol_decision" is not "approved", unless the current ECT has
"compensation_required" set to true.
6. Trust Domain Consistency: Parent tasks SHOULD belong to the
same trust domain or to a trust domain with which a federation same trust domain or to a trust domain with which a federation
relationship has been established. relationship has been established.
@@ -685,14 +779,19 @@ function validate_dag(ect, ledger, clock_skew_tolerance):
if parent.iat >= ect.iat + clock_skew_tolerance: if parent.iat >= ect.iat + clock_skew_tolerance:
return error("Parent task not earlier than current") return error("Parent task not earlier than current")
// Step 3: Cycle detection // Step 3: Cycle detection (with traversal limit)
visited = set() visited = set()
if has_cycle(ect.tid, ect.par, ledger, visited): result = has_cycle(ect.tid, ect.par, ledger, visited,
return error("Circular dependency detected") max_ancestor_limit)
if result is error or result is true:
return error("Circular dependency or depth limit exceeded")
return success return success
function has_cycle(target_tid, parent_ids, ledger, visited): function has_cycle(target_tid, parent_ids, ledger, visited,
max_depth):
if visited.size() >= max_depth:
return error("Maximum ancestor traversal limit exceeded")
for parent_id in parent_ids: for parent_id in parent_ids:
if parent_id == target_tid: if parent_id == target_tid:
return true return true
@@ -701,8 +800,10 @@ function has_cycle(target_tid, parent_ids, ledger, visited):
visited.add(parent_id) visited.add(parent_id)
parent = ledger.get(parent_id) parent = ledger.get(parent_id)
if parent is not null: if parent is not null:
if has_cycle(target_tid, parent.par, ledger, visited): result = has_cycle(target_tid, parent.par, ledger,
return true visited, max_depth)
if result is error or result is true:
return result
return false return false
~~~ ~~~
{: #fig-dag-validation title="DAG Validation Pseudocode"} {: #fig-dag-validation title="DAG Validation Pseudocode"}
@@ -711,7 +812,11 @@ The cycle detection traverses the ancestor graph rooted at the
current task's parents. The complexity is O(V) where V is the current task's parents. The complexity is O(V) where V is the
number of ancestor nodes reachable from the current task's parent number of ancestor nodes reachable from the current task's parent
references. For typical workflows with shallow DAGs, this is references. For typical workflows with shallow DAGs, this is
efficient. Implementations SHOULD cache cycle detection results efficient. To prevent denial-of-service via extremely deep or
wide DAGs, implementations SHOULD enforce a maximum ancestor
traversal limit (RECOMMENDED: 10000 nodes). If the limit is
reached before cycle detection completes, the ECT SHOULD be
rejected. Implementations SHOULD cache cycle detection results
for previously verified tasks to avoid redundant traversals. for previously verified tasks to avoid redundant traversals.
# Signature and Token Verification {#verification} # Signature and Token Verification {#verification}
@@ -735,30 +840,42 @@ verification steps in order:
5. Retrieve the public key identified by "kid" and verify the JWS 5. Retrieve the public key identified by "kid" and verify the JWS
signature per {{RFC7515}} Section 5.2. signature per {{RFC7515}} Section 5.2.
6. Verify the "alg" header parameter matches the algorithm in the 6. Verify that the signing key identified by "kid" has not been
revoked within the trust domain. Implementations MUST check
the key's revocation status using the trust domain's key
lifecycle mechanism (e.g., certificate revocation list, OCSP,
or SPIFFE trust bundle updates).
7. Verify the "alg" header parameter matches the algorithm in the
corresponding WIT. corresponding WIT.
7. Verify the "iss" claim matches the "sub" claim of the WIT 8. Verify the "iss" claim matches the "sub" claim of the WIT
associated with the "kid" public key. associated with the "kid" public key.
8. Verify the "aud" claim contains the verifier's own workload 9. Verify the "aud" claim contains the verifier's own workload
identity or an expected recipient identifier. identity. When "aud" is an array, it is sufficient that the
verifier's identity appears as one element; the presence of
other audience values does not cause verification failure.
When the verifier is the audit ledger, the ledger's own
identity MUST appear in "aud".
9. Verify the "exp" claim indicates the ECT has not expired. 10. Verify the "exp" claim indicates the ECT has not expired.
10. Verify the "iat" claim is not unreasonably far in the past 11. Verify the "iat" claim is not unreasonably far in the past
(implementation-specific threshold, RECOMMENDED maximum of (implementation-specific threshold, RECOMMENDED maximum of
15 minutes). 15 minutes) and is not unreasonably far in the future
(RECOMMENDED: no more than 30 seconds ahead of the
verifier's current time, to account for clock skew).
11. Verify all required claims ("tid", "exec_act", "par", "pol", 12. Verify all required claims ("jti", "tid", "exec_act", "par",
"pol_decision") are present and well-formed. "pol", "pol_decision") are present and well-formed.
12. Verify "pol_decision" is one of "approved", "rejected", or 13. Verify "pol_decision" is one of "approved", "rejected", or
"pending_human_review". "pending_human_review".
13. Perform DAG validation per {{dag-validation}}. 14. Perform DAG validation per {{dag-validation}}.
14. If all checks pass, the ECT MUST be appended to the audit 15. If all checks pass, the ECT MUST be appended to the audit
ledger. ledger.
If any verification step fails, the ECT MUST be rejected and the If any verification step fails, the ECT MUST be rejected and the
@@ -766,6 +883,15 @@ failure MUST be logged for audit purposes. Error messages
SHOULD NOT reveal whether specific parent task IDs exist in the SHOULD NOT reveal whether specific parent task IDs exist in the
ledger, to prevent information disclosure. ledger, to prevent information disclosure.
When ECT verification fails during HTTP request processing, the
receiving agent SHOULD respond with HTTP 403 (Forbidden) if the
WIT and WPT are valid but the ECT is invalid, and HTTP 401
(Unauthorized) if the ECT signature verification fails. The
response body SHOULD include a generic error indicator without
revealing which specific verification step failed. The receiving
agent MUST NOT process the requested action when ECT verification
fails.
## Verification Pseudocode ## Verification Pseudocode
~~~ pseudocode ~~~ pseudocode
@@ -791,6 +917,10 @@ function verify_ect(ect_jws, verifier_id,
signature, public_key): signature, public_key):
return reject("Invalid signature") return reject("Invalid signature")
// Verify key not revoked
if is_key_revoked(header.kid, trust_domain_keys):
return reject("Signing key has been revoked")
// Verify algorithm alignment // Verify algorithm alignment
wit = get_wit_for_key(header.kid) wit = get_wit_for_key(header.kid)
if header.alg != wit.alg: if header.alg != wit.alg:
@@ -808,12 +938,14 @@ function verify_ect(ect_jws, verifier_id,
if payload.exp < current_time(): if payload.exp < current_time():
return reject("ECT has expired") return reject("ECT has expired")
// Verify iat freshness // Verify iat freshness (not too old, not in the future)
if payload.iat < current_time() - max_age_threshold: if payload.iat < current_time() - max_age_threshold:
return reject("ECT issued too long ago") return reject("ECT issued too long ago")
if payload.iat > current_time() + clock_skew_tolerance:
return reject("ECT issued in the future")
// Verify required claims // Verify required claims
for claim in ["tid", "exec_act", "par", for claim in ["jti", "tid", "exec_act", "par",
"pol", "pol_decision"]: "pol", "pol_decision"]:
if claim not in payload: if claim not in payload:
return reject("Missing required claim: " + claim) return reject("Missing required claim: " + claim)
@@ -890,7 +1022,10 @@ The "ect_jws" field contains the full JWS Compact Serialization
and is the authoritative record. The other fields ("agent_id", and is the authoritative record. The other fields ("agent_id",
"action", "parents") are convenience indexes derived from the "action", "parents") are convenience indexes derived from the
ECT payload; if they disagree with the JWS payload, the JWS ECT payload; if they disagree with the JWS payload, the JWS
payload takes precedence. payload takes precedence. Implementations SHOULD validate that
convenience index fields match the corresponding values in the
JWS payload at write time to prevent desynchronization between
the authoritative JWS and the indexed fields.
# Use Cases {#use-cases} # Use Cases {#use-cases}
@@ -901,8 +1036,8 @@ include additional domain-specific requirements beyond the scope
of this specification. of this specification.
Note: task identifiers in this section are abbreviated for Note: task identifiers in this section are abbreviated for
readability. In production, all "tid" values MUST be UUIDs per readability. In production, all "tid" values are required to be
{{RFC9562}}. UUIDs per {{exec-claims}}.
## Medical Device SDLC Workflow ## Medical Device SDLC Workflow
@@ -1059,7 +1194,7 @@ violation discovery to remediation.
## Autonomous Logistics Coordination ## Autonomous Logistics Coordination
In a logistics workflow, multiple compliance checks must complete In a logistics workflow, multiple compliance checks complete
before shipment commitment. The DAG structure records that all before shipment commitment. The DAG structure records that all
required checks were completed: required checks were completed:
@@ -1113,7 +1248,7 @@ The following threat actors are considered:
- Time manipulator: An entity attempting to manipulate timestamps - Time manipulator: An entity attempting to manipulate timestamps
to alter perceived execution ordering. to alter perceived execution ordering.
## Self-Assertion Limitation ## Self-Assertion Limitation {#self-assertion-limitation}
ECTs are self-asserted by the executing agent. The agent claims ECTs are self-asserted by the executing agent. The agent claims
what it did, and this claim is signed with its private key. A what it did, and this claim is signed with its private key. A
@@ -1132,7 +1267,38 @@ The trustworthiness of ECT claims depends on the trustworthiness
of the signing agent. To mitigate single-agent false claims, of the signing agent. To mitigate single-agent false claims,
regulated environments SHOULD use the "witnessed_by" mechanism regulated environments SHOULD use the "witnessed_by" mechanism
to include independent third-party observers at critical decision to include independent third-party observers at critical decision
points. points. However, the "witnessed_by" claim is self-asserted by
the ECT issuer: the listed witnesses do not co-sign the ECT and
there is no cryptographic proof within a single ECT that the
witnesses actually observed the task. An issuing agent could
list witnesses that did not participate.
### Witness Attestation Model {#witness-attestation-model}
To address the self-assertion limitation of the "witnessed_by"
claim, witnesses SHOULD submit their own independent signed ECTs
to the audit ledger attesting to the observed task. A witness
attestation ECT:
- MUST set "iss" to the witness's own workload identity.
- MUST set "exec_act" to "witness_attestation" (or a domain-
specific equivalent).
- MUST include the observed task's "tid" in the "par" array,
linking the attestation to the original task.
- MUST set "pol_decision" to "approved" to indicate the witness
confirms the observation.
When a task's "witnessed_by" claim lists one or more witnesses,
auditors SHOULD verify that corresponding witness attestation
ECTs exist in the ledger for each listed witness. A mismatch
between the "witnessed_by" list and the set of independent witness
ECTs in the ledger SHOULD be flagged during audit review.
This model converts witness attestation from a self-asserted claim
to a cryptographically verifiable property of the ledger: the
witness independently signs their own ECT using their own key,
and the ledger records both the original task ECT and the witness
attestation ECTs.
## Organizational Prerequisites ## Organizational Prerequisites
@@ -1156,10 +1322,12 @@ ECTs MUST be signed with the agent's private key using JWS
specified in the agent's WIT. Receivers MUST verify the ECT specified in the agent's WIT. Receivers MUST verify the ECT
signature against the WIT public key before processing any signature against the WIT public key before processing any
claims. Receivers MUST verify that the signing key has not been claims. Receivers MUST verify that the signing key has not been
revoked within the trust domain. revoked within the trust domain (see step 6 in
{{verification}}).
If signature verification fails, the ECT MUST be rejected entirely If signature verification fails or if the signing key has been
and the failure MUST be logged. revoked, the ECT MUST be rejected entirely and the failure MUST
be logged.
Implementations MUST use established JWS libraries and MUST NOT Implementations MUST use established JWS libraries and MUST NOT
implement custom signature verification. implement custom signature verification.
@@ -1176,9 +1344,9 @@ The DAG structure provides additional replay protection: an ECT
referencing parent tasks that already have a recorded child task referencing parent tasks that already have a recorded child task
with the same action can be flagged as a potential replay. with the same action can be flagged as a potential replay.
Implementations SHOULD maintain a cache of recently-seen "jti" Implementations MUST maintain a cache of recently-seen "jti"
values (when present) to detect replayed ECTs within the values to detect replayed ECTs within the expiration window.
expiration window. An ECT with a duplicate "jti" value MUST be rejected.
## Man-in-the-Middle Protection ## Man-in-the-Middle Protection
@@ -1254,6 +1422,12 @@ judgments. Implementations SHOULD use synchronized time sources
(e.g., NTP) and SHOULD allow a configurable clock skew tolerance (e.g., NTP) and SHOULD allow a configurable clock skew tolerance
(RECOMMENDED: 30 seconds). (RECOMMENDED: 30 seconds).
Cross-organizational deployments where agents span multiple trust
domains with independent time sources MAY require a higher clock
skew tolerance. Deployments using trust domain federation SHOULD
document their configured clock skew tolerance value and SHOULD
ensure all participating trust domains agree on a common tolerance.
The temporal ordering check in DAG validation incorporates the The temporal ordering check in DAG validation incorporates the
clock skew tolerance to account for minor clock differences clock skew tolerance to account for minor clock differences
between agents. between agents.
@@ -1262,8 +1436,11 @@ between agents.
ECTs with many parent tasks or large extension objects can ECTs with many parent tasks or large extension objects can
increase HTTP header size. Implementations SHOULD limit the "par" increase HTTP header size. Implementations SHOULD limit the "par"
array to a reasonable size and SHOULD set maximum size limits for array to a maximum of 256 entries. Workflows requiring more
the "ext" object to prevent abuse. parent references SHOULD introduce intermediate aggregation
tasks. The "ext" object SHOULD NOT exceed 4096 bytes when
serialized as JSON and SHOULD NOT exceed a nesting depth of
5 levels (see also {{extension-claims}}).
# Privacy Considerations # Privacy Considerations
@@ -1285,7 +1462,7 @@ ECTs are designed to NOT reveal:
- Proprietary algorithms or intellectual property - Proprietary algorithms or intellectual property
- Personally identifiable information (PII) - Personally identifiable information (PII)
## Data Minimization ## Data Minimization {#data-minimization}
Implementations SHOULD minimize the information included in ECTs. Implementations SHOULD minimize the information included in ECTs.
The "exec_act" claim SHOULD use structured identifiers (e.g., The "exec_act" claim SHOULD use structured identifiers (e.g.,
@@ -1293,6 +1470,16 @@ The "exec_act" claim SHOULD use structured identifiers (e.g.,
The "pol" claim SHOULD reference policy identifiers rather than The "pol" claim SHOULD reference policy identifiers rather than
embedding policy content. embedding policy content.
The "compensation_reason" claim ({{compensation-claims}})
deserves particular attention: because it is human-readable and
may describe the circumstances of a failure or policy violation,
it risks exposing sensitive operational details. Implementations
SHOULD use short, structured reason codes (e.g.,
"policy_violation_in_parent_trade") rather than free-form
natural language explanations. Implementers SHOULD review
"compensation_reason" values for potential information leakage
before deploying to production.
## Storage and Access Control ## Storage and Access Control
ECTs stored in audit ledgers SHOULD be access-controlled so that ECTs stored in audit ledgers SHOULD be access-controlled so that
@@ -1408,8 +1595,39 @@ the "JSON Web Token Claims" registry maintained by IANA:
| model_version | AI/ML Model Version | IETF | {{operational-claims}} | | model_version | AI/ML Model Version | IETF | {{operational-claims}} |
| compensation_required | Compensation Flag | IETF | {{compensation-claims}} | | compensation_required | Compensation Flag | IETF | {{compensation-claims}} |
| compensation_reason | Compensation Reason | IETF | {{compensation-claims}} | | compensation_reason | Compensation Reason | IETF | {{compensation-claims}} |
| ext | Extension Object | IETF | {{extension-claims}} |
{: #table-claims title="JWT Claims Registrations"} {: #table-claims title="JWT Claims Registrations"}
## ECT Policy Decision Values Registry {#pol-decision-registry}
This document establishes the "ECT Policy Decision Values"
registry under the "JSON Web Token (JWT)" group. Registration
policy is Specification Required per {{!RFC8126}}.
The initial contents of the registry are:
| Value | Description | Change Controller | Reference |
|:---:|:---|:---:|:---:|
| approved | Policy evaluation succeeded | IETF | {{policy-claims}} |
| rejected | Policy evaluation failed | IETF | {{policy-claims}} |
| pending_human_review | Awaiting human judgment | IETF | {{policy-claims}} |
{: #table-pol-decision title="ECT Policy Decision Values"}
## ECT Regulated Domain Values Registry {#regulated-domain-registry}
This document establishes the "ECT Regulated Domain Values"
registry under the "JSON Web Token (JWT)" group. Registration
policy is Specification Required per {{!RFC8126}}.
The initial contents of the registry are:
| Value | Description | Change Controller | Reference |
|:---:|:---|:---:|:---:|
| medtech | Medical technology and devices | IETF | {{operational-claims}} |
| finance | Financial services and trading | IETF | {{operational-claims}} |
| military | Military and defense | IETF | {{operational-claims}} |
{: #table-regulated-domain title="ECT Regulated Domain Values"}
--- back --- back
# Related Work # Related Work
@@ -1499,10 +1717,11 @@ use cases are distinct.
## Minimal Implementation ## Minimal Implementation
{:numbered="false"} {:numbered="false"}
A minimal conforming implementation should: A minimal conforming implementation needs to:
1. Create JWTs with all required claims ("iss", "aud", "iat", 1. Create JWTs with all required claims ("iss", "aud", "iat",
"exp", "tid", "exec_act", "par", "pol", "pol_decision"). "exp", "jti", "tid", "exec_act", "par", "pol",
"pol_decision").
2. Sign ECTs with the agent's private key using an algorithm 2. Sign ECTs with the agent's private key using an algorithm
matching the WIT (ES256 recommended). matching the WIT (ES256 recommended).
3. Verify ECT signatures against WIT public keys. 3. Verify ECT signatures against WIT public keys.
@@ -1536,10 +1755,11 @@ A minimal conforming implementation should:
## Interoperability ## Interoperability
{:numbered="false"} {:numbered="false"}
Implementations should use established JWT/JWS libraries (JOSE) Implementations are expected to use established JWT/JWS libraries
for token creation and verification. Custom cryptographic (JOSE) for token creation and verification. Custom cryptographic
implementations should not be used. Implementations should be implementations are strongly discouraged. Implementations are
tested against multiple JWT libraries to ensure interoperability. expected to be tested against multiple JWT libraries to ensure
interoperability.
# Regulatory Compliance Mapping # Regulatory Compliance Mapping
{:numbered="false"} {:numbered="false"}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff