Simplify spec: remove sub, move compensation and policy to ext

- Remove sub claim (always equals iss, added no information)
- Move compensation_required and compensation_reason to ext keys
- Move pol, pol_decision, pol_enforcer to ext keys
- IANA JWT Claims table reduced from 11 to 6 registered claims
- Trim witness attestation section to concise guidance
- Fix remaining ledger-mandatory language in verification
  step 15 and minimal implementation guidance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 12:38:14 +01:00
parent 898b0f8747
commit bf0f94ab30
4 changed files with 1679 additions and 1773 deletions

View File

@@ -1242,7 +1242,7 @@ li > p:last-of-type:only-child {
</tr></thead> </tr></thead>
<tfoot><tr> <tfoot><tr>
<td class="left">Nennemann</td> <td class="left">Nennemann</td>
<td class="center">Expires 28 August 2026</td> <td class="center">Expires 29 August 2026</td>
<td class="right">[Page]</td> <td class="right">[Page]</td>
</tr></tfoot> </tr></tfoot>
</table> </table>
@@ -1255,12 +1255,12 @@ li > p:last-of-type:only-child {
<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>
<dd class="published"> <dd class="published">
<time datetime="2026-02-24" class="published">24 February 2026</time> <time datetime="2026-02-25" class="published">25 February 2026</time>
</dd> </dd>
<dt class="label-intended-status">Intended Status:</dt> <dt class="label-intended-status">Intended Status:</dt>
<dd class="intended-status">Standards Track</dd> <dd class="intended-status">Standards Track</dd>
<dt class="label-expires">Expires:</dt> <dt class="label-expires">Expires:</dt>
<dd class="expires"><time datetime="2026-08-28">28 August 2026</time></dd> <dd class="expires"><time datetime="2026-08-29">29 August 2026</time></dd>
<dt class="label-authors">Author:</dt> <dt class="label-authors">Author:</dt>
<dd class="authors"> <dd class="authors">
<div class="author"> <div class="author">
@@ -1312,7 +1312,7 @@ regulatory frameworks.<a href="#section-abstract-1" class="pilcrow">¶</a></p>
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."<a href="#section-boilerplate.1-3" class="pilcrow"></a></p> material or to cite them other than as "work in progress."<a href="#section-boilerplate.1-3" class="pilcrow"></a></p>
<p id="section-boilerplate.1-4"> <p id="section-boilerplate.1-4">
This Internet-Draft will expire on 28 August 2026.<a href="#section-boilerplate.1-4" class="pilcrow"></a></p> This Internet-Draft will expire on 29 August 2026.<a href="#section-boilerplate.1-4" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="copyright"> <div id="copyright">
@@ -1391,7 +1391,7 @@ regulatory frameworks.<a href="#section-abstract-1" class="pilcrow">¶</a></p>
<p id="section-toc.1-1.4.2.2.2.2.1"><a href="#section-4.2.2" class="auto internal xref">4.2.2</a>.  <a href="#name-execution-context" class="internal xref">Execution Context</a></p> <p id="section-toc.1-1.4.2.2.2.2.1"><a href="#section-4.2.2" class="auto internal xref">4.2.2</a>.  <a href="#name-execution-context" class="internal xref">Execution Context</a></p>
</li> </li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.2.2.3"> <li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.2.2.3">
<p id="section-toc.1-1.4.2.2.2.3.1"><a href="#section-4.2.3" class="auto internal xref">4.2.3</a>.  <a href="#name-policy-evaluation" class="internal xref">Policy Evaluation</a></p> <p id="section-toc.1-1.4.2.2.2.3.1"><a href="#section-4.2.3" class="auto internal xref">4.2.3</a>.  <a href="#name-policy-evaluation-extension" class="internal xref">Policy Evaluation Extension Keys</a></p>
</li> </li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.2.2.4"> <li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.2.2.4">
<p id="section-toc.1-1.4.2.2.2.4.1"><a href="#section-4.2.4" class="auto internal xref">4.2.4</a>.  <a href="#name-data-integrity" class="internal xref">Data Integrity</a></p> <p id="section-toc.1-1.4.2.2.2.4.1"><a href="#section-4.2.4" class="auto internal xref">4.2.4</a>.  <a href="#name-data-integrity" class="internal xref">Data Integrity</a></p>
@@ -1475,11 +1475,6 @@ regulatory frameworks.<a href="#section-abstract-1" class="pilcrow">¶</a></p>
</li> </li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.2"> <li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.2">
<p id="section-toc.1-1.10.2.2.1"><a href="#section-10.2" class="auto internal xref">10.2</a>.  <a href="#name-self-assertion-limitation" class="internal xref">Self-Assertion Limitation</a></p> <p id="section-toc.1-1.10.2.2.1"><a href="#section-10.2" class="auto internal xref">10.2</a>.  <a href="#name-self-assertion-limitation" class="internal xref">Self-Assertion Limitation</a></p>
<ul class="compact toc ulBare ulEmpty">
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.2.2.1">
<p id="section-toc.1-1.10.2.2.2.1.1"><a href="#section-10.2.1" class="auto internal xref">10.2.1</a>.  <a href="#name-witness-attestation-model" class="internal xref">Witness Attestation Model</a></p>
</li>
</ul>
</li> </li>
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.3"> <li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.3">
<p id="section-toc.1-1.10.2.3.1"><a href="#section-10.3" class="auto internal xref">10.3</a>.  <a href="#name-organizational-prerequisite" class="internal xref">Organizational Prerequisites</a></p> <p id="section-toc.1-1.10.2.3.1"><a href="#section-10.3" class="auto internal xref">10.3</a>.  <a href="#name-organizational-prerequisite" class="internal xref">Organizational Prerequisites</a></p>
@@ -1705,7 +1700,7 @@ regulatory audit scenarios.<a href="#section-1.2-3" class="pilcrow">¶</a></p>
<p id="section-1.3-2.2.1">DAG structure for task dependency ordering (<a href="#dag-validation" class="auto internal xref">Section 6</a>)<a href="#section-1.3-2.2.1" class="pilcrow"></a></p> <p id="section-1.3-2.2.1">DAG structure for task dependency ordering (<a href="#dag-validation" class="auto internal xref">Section 6</a>)<a href="#section-1.3-2.2.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-1.3-2.3"> <li class="normal" id="section-1.3-2.3">
<p id="section-1.3-2.3.1">Policy checkpoint recording (<a href="#policy-claims" class="auto internal xref">Section 4.2.3</a>)<a href="#section-1.3-2.3.1" class="pilcrow"></a></p> <p id="section-1.3-2.3.1">Policy checkpoint recording via extension keys (<a href="#policy-claims" class="auto internal xref">Section 4.2.3</a>)<a href="#section-1.3-2.3.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-1.3-2.4"> <li class="normal" id="section-1.3-2.4">
<p id="section-1.3-2.4.1">Integration with the WIMSE identity framework <p id="section-1.3-2.4.1">Integration with the WIMSE identity framework
@@ -2068,63 +2063,55 @@ deployments <span class="bcp14">MAY</span> use other URI schemes (e.g., HTTPS UR
URN:UUID identifiers).<a href="#section-4.2.1-2.2.1" class="pilcrow"></a></p> URN:UUID identifiers).<a href="#section-4.2.1-2.2.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.1-2.3">sub:</dt> <dt id="section-4.2.1-2.3">aud:</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">REQUIRED</span>. StringOrURI or array of StringOrURI. The intended
<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 class="break"></dd>
<dt id="section-4.2.1-2.5">aud:</dt>
<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
recipient(s) of the ECT. Because ECTs serve as both inter-agent recipient(s) of the ECT. Because ECTs serve as both inter-agent
messages and audit records, the "aud" claim <span class="bcp14">SHOULD</span> contain the messages and audit records, the "aud" claim <span class="bcp14">SHOULD</span> contain the
identifiers of all entities that will verify the ECT. In 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> practice this means:<a href="#section-4.2.1-2.4.1" class="pilcrow"></a></p>
<ul class="normal"> <ul class="normal">
<li class="normal" id="section-4.2.1-2.6.2.1"> <li class="normal" id="section-4.2.1-2.4.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 <p id="section-4.2.1-2.4.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 agent to a single next agent, "aud" contains that agent's
workload identity. The receiving agent verifies the ECT and 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> forwards it to the ledger on behalf of the issuer.<a href="#section-4.2.1-2.4.2.1.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.1-2.6.2.2"> <li class="normal" id="section-4.2.1-2.4.2.2">
<p id="section-4.2.1-2.6.2.2.1"><strong>Direct-to-ledger submission</strong>: when an ECT is submitted <p id="section-4.2.1-2.4.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 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> workflow completion), "aud" contains the ledger's identity.<a href="#section-4.2.1-2.4.2.2.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.1-2.6.2.3"> <li class="normal" id="section-4.2.1-2.4.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 <p id="section-4.2.1-2.4.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 next agent and the ledger independently, "aud" <span class="bcp14">MUST</span> be an
array containing both identifiers (e.g., array containing both identifiers (e.g.,
["spiffe://example.com/agent/next", ["spiffe://example.com/agent/next",
"spiffe://example.com/system/ledger"]). Each verifier checks "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> that its own identity appears in the array.<a href="#section-4.2.1-2.4.2.3.1" class="pilcrow"></a></p>
</li> </li>
</ul> </ul>
<p id="section-4.2.1-2.6.3">In multi-parent (join) scenarios where a task depends on ECTs <p id="section-4.2.1-2.4.3">In multi-parent (join) scenarios where a task depends on ECTs
from multiple parent agents, the joining agent creates a new ECT from multiple parent agents, the joining agent creates a new ECT
with the parent task IDs in "par". The "aud" of this 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 is set according to the rules above based on where the ECT will
be delivered — it is independent of the "aud" values in the 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> parent ECTs.<a href="#section-4.2.1-2.4.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.5">iat:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.1-2.8"> <dd style="margin-left: 1.5em" id="section-4.2.1-2.6">
<p id="section-4.2.1-2.8.1"><span class="bcp14">REQUIRED</span>. NumericDate. The time at which the ECT was issued. <p id="section-4.2.1-2.6.1"><span class="bcp14">REQUIRED</span>. NumericDate. The time at which the ECT was issued.
The ECT records a completed action, so the "iat" value reflects The ECT records a completed action, so the "iat" value reflects
when the record was created, not when task execution began.<a href="#section-4.2.1-2.8.1" class="pilcrow"></a></p> when the record was created, not when task execution began.<a href="#section-4.2.1-2.6.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.1-2.9">exp:</dt> <dt id="section-4.2.1-2.7">exp:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.1-2.10"> <dd style="margin-left: 1.5em" id="section-4.2.1-2.8">
<p id="section-4.2.1-2.10.1"><span class="bcp14">REQUIRED</span>. NumericDate. The expiration time of the ECT. <p id="section-4.2.1-2.8.1"><span class="bcp14">REQUIRED</span>. NumericDate. The expiration time of the ECT.
Implementations <span class="bcp14">SHOULD</span> set this to 5 to 15 minutes after "iat" Implementations <span class="bcp14">SHOULD</span> set this to 5 to 15 minutes after "iat"
to limit the replay window while allowing for reasonable clock 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.8.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
</dl> </dl>
@@ -2186,70 +2173,73 @@ multiple root tasks.<a href="#section-4.2.2-2.6.1" class="pilcrow">¶</a></p>
</div> </div>
<div id="policy-claims"> <div id="policy-claims">
<section id="section-4.2.3"> <section id="section-4.2.3">
<h4 id="name-policy-evaluation"> <h4 id="name-policy-evaluation-extension">
<a href="#section-4.2.3" class="section-number selfRef">4.2.3. </a><a href="#name-policy-evaluation" class="section-name selfRef">Policy Evaluation</a> <a href="#section-4.2.3" class="section-number selfRef">4.2.3. </a><a href="#name-policy-evaluation-extension" class="section-name selfRef">Policy Evaluation Extension Keys</a>
</h4> </h4>
<p id="section-4.2.3-1">The following claims record policy evaluation outcomes:<a href="#section-4.2.3-1" class="pilcrow"></a></p> <p id="section-4.2.3-1">Policy evaluation outcomes are recorded as extension keys within
<span class="break"></span><dl class="dlParallel" id="section-4.2.3-2"> the "ext" object (<a href="#extension-claims" class="auto internal xref">Section 4.2.6</a>). This keeps the core
<dt id="section-4.2.3-2.1">pol:</dt> registered claims focused on DAG structure and execution context,
<dd style="margin-left: 1.5em" id="section-4.2.3-2.2"> while allowing deployments to add policy recording as needed.<a href="#section-4.2.3-1" class="pilcrow"></a></p>
<p id="section-4.2.3-2.2.1"><span class="bcp14">OPTIONAL</span>. String. The identifier of the policy rule that was <p id="section-4.2.3-2">The following extension keys are defined for policy evaluation:<a href="#section-4.2.3-2" class="pilcrow"></a></p>
evaluated for this task (e.g., <span class="break"></span><dl class="dlParallel" id="section-4.2.3-3">
"clinical_data_access_policy_v1"). <span class="bcp14">MUST</span> be present when <dt id="section-4.2.3-3.1">"pol":</dt>
"pol_decision" is present.<a href="#section-4.2.3-2.2.1" class="pilcrow"></a></p> <dd style="margin-left: 1.5em" id="section-4.2.3-3.2">
<p id="section-4.2.3-3.2.1">String. The identifier of the policy rule that was evaluated
for this task (e.g., "clinical_data_access_policy_v1"). <span class="bcp14">MUST</span>
be present when "pol_decision" is present.<a href="#section-4.2.3-3.2.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
<dt id="section-4.2.3-2.3">pol_decision:</dt> <dt id="section-4.2.3-3.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-3.4">
<p id="section-4.2.3-2.4.1"><span class="bcp14">OPTIONAL</span>. String. The result of the policy evaluation. When <p id="section-4.2.3-3.4.1">String. The result of the policy evaluation. When present,
present, <span class="bcp14">MUST</span> be one of the values registered in the ECT Policy <span class="bcp14">MUST</span> be one of the values registered in the ECT Policy Decision
Decision Values registry (<a href="#pol-decision-registry" class="auto internal xref">Section 12.4</a>). <span class="bcp14">MUST</span> be Values registry (<a href="#pol-decision-registry" class="auto internal xref">Section 12.4</a>). <span class="bcp14">MUST</span> be present
present when "pol" is present. Initial values are:<a href="#section-4.2.3-2.4.1" class="pilcrow"></a></p> when "pol" is present. Initial values are:<a href="#section-4.2.3-3.4.1" class="pilcrow"></a></p>
<ul class="normal"> <ul class="normal">
<li class="normal" id="section-4.2.3-2.4.2.1"> <li class="normal" id="section-4.2.3-3.4.2.1">
<p id="section-4.2.3-2.4.2.1.1">"approved": The policy evaluation succeeded and the task <p id="section-4.2.3-3.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> was authorized to proceed.<a href="#section-4.2.3-3.4.2.1.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.3-2.4.2.2"> <li class="normal" id="section-4.2.3-3.4.2.2">
<p id="section-4.2.3-2.4.2.2.1">"rejected": The policy evaluation failed. A "rejected" ECT <p id="section-4.2.3-3.4.2.2.1">"rejected": The policy evaluation failed. A "rejected" ECT
<span class="bcp14">MUST</span> still be recorded for accountability. An ECT with <span class="bcp14">MUST</span> still be recorded for accountability. An ECT with
"pol_decision" of "rejected" <span class="bcp14">MAY</span> appear as a parent in the "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, "par" array of a subsequent ECT, but only for compensation,
rollback, or remediation tasks. Agents <span class="bcp14">MUST NOT</span> proceed rollback, or remediation tasks. Agents <span class="bcp14">MUST NOT</span> proceed
with normal workflow execution based on a parent ECT whose 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> "pol_decision" is "rejected".<a href="#section-4.2.3-3.4.2.2.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.3-2.4.2.3"> <li class="normal" id="section-4.2.3-3.4.2.3">
<p id="section-4.2.3-2.4.2.3.1">"pending_human_review": The policy evaluation requires human <p id="section-4.2.3-3.4.2.3.1">"pending_human_review": The policy evaluation requires human
judgment before proceeding. Agents <span class="bcp14">MUST NOT</span> proceed with judgment before proceeding. Agents <span class="bcp14">MUST NOT</span> proceed with
dependent tasks until a subsequent ECT from a human reviewer dependent tasks until a subsequent ECT from a human reviewer
records an "approved" decision referencing this task as a 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> parent.<a href="#section-4.2.3-3.4.2.3.1" class="pilcrow"></a></p>
</li> </li>
</ul> </ul>
<p id="section-4.2.3-2.4.3">When "pol" and "pol_decision" are absent, the ECT records task <p id="section-4.2.3-3.4.3">When "pol" and "pol_decision" are absent from "ext", the ECT
execution without a policy checkpoint. Regulated deployments records task execution without a policy checkpoint. Regulated
<span class="bcp14">SHOULD</span> include policy claims on all ECTs to maintain complete deployments <span class="bcp14">SHOULD</span> include policy keys on all ECTs to maintain
audit trails.<a href="#section-4.2.3-2.4.3" class="pilcrow"></a></p> complete audit trails.<a href="#section-4.2.3-3.4.3" class="pilcrow"></a></p>
</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-3.5">"pol_enforcer":</dt>
<dd style="margin-left: 1.5em" id="section-4.2.3-2.6"> <dd style="margin-left: 1.5em" id="section-4.2.3-3.6">
<p id="section-4.2.3-2.6.1"><span class="bcp14">OPTIONAL</span>. StringOrURI. The identity of the entity (system or <p id="section-4.2.3-3.6.1">StringOrURI. The identity of the entity (system or person)
person) that evaluated the policy decision. When present, that evaluated the policy decision. When present, <span class="bcp14">SHOULD</span> use
<span class="bcp14">SHOULD</span> use SPIFFE ID format.<a href="#section-4.2.3-2.6.1" class="pilcrow"></a></p> SPIFFE ID format.<a href="#section-4.2.3-3.6.1" class="pilcrow"></a></p>
</dd> </dd>
<dd class="break"></dd> <dd class="break"></dd>
</dl> </dl>
<p id="section-4.2.3-3">This specification intentionally defines only the recording of <p id="section-4.2.3-4">This specification intentionally defines only the recording of
policy evaluation outcomes. The mechanisms by which policies are policy evaluation outcomes. The mechanisms by which policies are
defined, distributed to agents, and evaluated are out of scope. defined, distributed to agents, and evaluated are out of scope.
The "pol" claim is an opaque identifier referencing an external The "pol" key is an opaque identifier referencing an external
policy; the semantics and enforcement of that policy are policy; the semantics and enforcement of that policy are
determined by the deployment environment. Implementations may determined by the deployment environment. Implementations may
use any policy engine or framework (e.g., OPA/Rego, Cedar, XACML, use any policy engine or framework (e.g., OPA/Rego, Cedar, XACML,
or custom solutions) provided that the evaluation outcome is or custom solutions) provided that the evaluation outcome is
faithfully recorded in the ECT claims defined above.<a href="#section-4.2.3-3" class="pilcrow"></a></p> faithfully recorded in the "ext" keys defined above.<a href="#section-4.2.3-4" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="data-integrity-claims"> <div id="data-integrity-claims">
@@ -2288,31 +2278,12 @@ using the same format and algorithm requirements as "inp_hash".<a href="#section
<h4 id="name-compensation-and-rollback"> <h4 id="name-compensation-and-rollback">
<a href="#section-4.2.5" class="section-number selfRef">4.2.5. </a><a href="#name-compensation-and-rollback" class="section-name selfRef">Compensation and Rollback</a> <a href="#section-4.2.5" class="section-number selfRef">4.2.5. </a><a href="#name-compensation-and-rollback" class="section-name selfRef">Compensation and Rollback</a>
</h4> </h4>
<span class="break"></span><dl class="dlParallel" id="section-4.2.5-1"> <p id="section-4.2.5-1">Compensation and rollback actions are recorded using the "par"
<dt id="section-4.2.5-1.1">compensation_required:</dt> claim to reference the original task and the "exec_act" claim to
<dd style="margin-left: 1.5em" id="section-4.2.5-1.2"> describe the remediation action. The referenced parent ECTs may
<p id="section-4.2.5-1.2.1"><span class="bcp14">OPTIONAL</span>. Boolean. Indicates whether this task is a have passed their own "exp" time; ECT expiration applies to the
compensation or rollback action for a previous task.<a href="#section-4.2.5-1.2.1" class="pilcrow"></a></p> verification window of the ECT itself, not to its validity as a
</dd> parent reference in the ECT store.<a href="#section-4.2.5-1" class="pilcrow"></a></p>
<dd class="break"></dd>
<dt id="section-4.2.5-1.3">compensation_reason:</dt>
<dd style="margin-left: 1.5em" id="section-4.2.5-1.4">
<p id="section-4.2.5-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.
Values <span class="bcp14">SHOULD</span> use structured identifiers (e.g.,
"policy_violation_in_parent_trade") rather than free-form text
to minimize the risk of embedding sensitive information. See
<a href="#data-minimization" class="auto internal xref">Section 11.2</a> for privacy guidance.
If "compensation_reason" is present, "compensation_required"
<span class="bcp14">MUST</span> be true.<a href="#section-4.2.5-1.4.1" class="pilcrow"></a></p>
</dd>
<dd class="break"></dd>
</dl>
<p id="section-4.2.5-2">Note: compensation ECTs reference historical parent tasks via the
"par" claim. The referenced parent ECTs may have passed their own
"exp" time; ECT expiration applies to the verification window of
the ECT itself, not to its validity as a parent reference in the
ledger.<a href="#section-4.2.5-2" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="extension-claims"> <div id="extension-claims">
@@ -2340,31 +2311,57 @@ levels. Implementations <span class="bcp14">SHOULD</span> reject ECTs whose "ex
exceeds these limits.<a href="#section-4.2.6-2" class="pilcrow"></a></p> exceeds these limits.<a href="#section-4.2.6-2" class="pilcrow"></a></p>
<p id="section-4.2.6-3">The following extension keys are defined by this specification <p id="section-4.2.6-3">The following extension keys are defined by this specification
for common use cases. Because these keys are documented here, for common use cases. Because these keys are documented here,
they use short names without reverse domain prefixes:<a href="#section-4.2.6-3" class="pilcrow"></a></p> they use short names without reverse domain prefixes.<a href="#section-4.2.6-3" class="pilcrow"></a></p>
<p id="section-4.2.6-4">Policy evaluation keys (see <a href="#policy-claims" class="auto internal xref">Section 4.2.3</a> for full
definitions and decision value semantics):<a href="#section-4.2.6-4" class="pilcrow"></a></p>
<ul class="normal"> <ul class="normal">
<li class="normal" id="section-4.2.6-4.1"> <li class="normal" id="section-4.2.6-5.1">
<p id="section-4.2.6-4.1.1">"exec_time_ms": Integer. Execution duration in milliseconds.<a href="#section-4.2.6-4.1.1" class="pilcrow"></a></p> <p id="section-4.2.6-5.1.1">"pol": String. Policy rule identifier.<a href="#section-4.2.6-5.1.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.6-4.2"> <li class="normal" id="section-4.2.6-5.2">
<p id="section-4.2.6-4.2.1">"regulated_domain": String. Regulatory domain (e.g., <p id="section-4.2.6-5.2.1">"pol_decision": String. Policy evaluation outcome
"medtech", "finance", "military").<a href="#section-4.2.6-4.2.1" class="pilcrow"></a></p> ("approved", "rejected", or "pending_human_review").<a href="#section-4.2.6-5.2.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.6-4.3"> <li class="normal" id="section-4.2.6-5.3">
<p id="section-4.2.6-4.3.1">"model_version": String. AI/ML model version.<a href="#section-4.2.6-4.3.1" class="pilcrow"></a></p> <p id="section-4.2.6-5.3.1">"pol_enforcer": StringOrURI. Identity of the policy
evaluator.<a href="#section-4.2.6-5.3.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.6-4.4"> <li class="normal" id="section-4.2.6-5.4">
<p id="section-4.2.6-4.4.1">"witnessed_by": Array of StringOrURI. Identifiers of <p id="section-4.2.6-5.4.1">"pol_timestamp": NumericDate. Time at which the policy
decision was made, if distinct from "iat".<a href="#section-4.2.6-5.4.1" class="pilcrow"></a></p>
</li>
</ul>
<p id="section-4.2.6-6">Operational metadata keys:<a href="#section-4.2.6-6" class="pilcrow"></a></p>
<ul class="normal">
<li class="normal" id="section-4.2.6-7.1">
<p id="section-4.2.6-7.1.1">"exec_time_ms": Integer. Execution duration in milliseconds.<a href="#section-4.2.6-7.1.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.6-7.2">
<p id="section-4.2.6-7.2.1">"regulated_domain": String. Regulatory domain (e.g.,
"medtech", "finance", "military").<a href="#section-4.2.6-7.2.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.6-7.3">
<p id="section-4.2.6-7.3.1">"model_version": String. AI/ML model version.<a href="#section-4.2.6-7.3.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.6-7.4">
<p id="section-4.2.6-7.4.1">"witnessed_by": Array of StringOrURI. Identifiers of
third-party entities that the issuer claims observed the third-party entities that the issuer claims observed the
task. Note: this is self-asserted; for verifiable witness task. Note: this is self-asserted; for verifiable witness
attestation, witnesses should submit independent signed ECTs.<a href="#section-4.2.6-4.4.1" class="pilcrow"></a></p> attestation, witnesses should submit independent signed ECTs.<a href="#section-4.2.6-7.4.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.6-4.5"> <li class="normal" id="section-4.2.6-7.5">
<p id="section-4.2.6-4.5.1">"inp_classification": String. Data sensitivity classification <p id="section-4.2.6-7.5.1">"inp_classification": String. Data sensitivity classification
(e.g., "public", "confidential", "restricted").<a href="#section-4.2.6-4.5.1" class="pilcrow"></a></p> (e.g., "public", "confidential", "restricted").<a href="#section-4.2.6-7.5.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-4.2.6-4.6"> <li class="normal" id="section-4.2.6-7.6">
<p id="section-4.2.6-4.6.1">"pol_timestamp": NumericDate. Time at which the policy <p id="section-4.2.6-7.6.1">"compensation_required": Boolean. Indicates whether this task
decision was made, if distinct from "iat".<a href="#section-4.2.6-4.6.1" class="pilcrow"></a></p> is a compensation or rollback action.<a href="#section-4.2.6-7.6.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-4.2.6-7.7">
<p id="section-4.2.6-7.7.1">"compensation_reason": String. Structured reason code for the
compensation action (e.g., "policy_violation_in_parent_trade").
<span class="bcp14">SHOULD</span> use structured identifiers rather than free-form text
to minimize information leakage (see <a href="#data-minimization" class="auto internal xref">Section 11.2</a>).<a href="#section-4.2.6-7.7.1" class="pilcrow"></a></p>
</li> </li>
</ul> </ul>
</section> </section>
@@ -2383,7 +2380,6 @@ decision was made, if distinct from "iat".<a href="#section-4.2.6-4.6.1" class="
<pre> <pre>
{ {
"iss": "spiffe://example.com/agent/clinical", "iss": "spiffe://example.com/agent/clinical",
"sub": "spiffe://example.com/agent/clinical",
"aud": "spiffe://example.com/agent/safety", "aud": "spiffe://example.com/agent/safety",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
@@ -2393,14 +2389,13 @@ decision was made, if distinct from "iat".<a href="#section-4.2.6-4.6.1" class="
"exec_act": "recommend_treatment", "exec_act": "recommend_treatment",
"par": [], "par": [],
"pol": "clinical_reasoning_policy_v2",
"pol_decision": "approved",
"pol_enforcer": "spiffe://example.com/policy/clinical-engine",
"inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg", "inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564", "out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
"ext": { "ext": {
"pol": "clinical_reasoning_policy_v2",
"pol_decision": "approved",
"pol_enforcer": "spiffe://example.com/policy/clinical-engine",
"pol_timestamp": 1772064145, "pol_timestamp": 1772064145,
"exec_time_ms": 245, "exec_time_ms": 245,
"regulated_domain": "medtech", "regulated_domain": "medtech",
@@ -2521,15 +2516,14 @@ lead back to the current ECT's "jti". 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">Parent Policy Decision: If any parent ECT contains a <p id="section-6.2-2.5.1">Parent Policy Decision: If any parent ECT's "ext" object
"pol_decision" of "rejected" or "pending_human_review", the contains a "pol_decision" of "rejected" or
current ECT's "exec_act" <span class="bcp14">MUST</span> indicate a compensation, "pending_human_review", the current ECT's "exec_act" <span class="bcp14">MUST</span>
rollback, remediation, or human review action. indicate a compensation, rollback, remediation, or human
Implementations <span class="bcp14">MUST NOT</span> accept an ECT representing normal review action. Implementations <span class="bcp14">MUST NOT</span> accept an ECT
workflow continuation when a parent's "pol_decision" is not representing normal workflow continuation when a parent's
"approved", unless the current ECT has "compensation_required" "pol_decision" is not "approved". This rule only applies
set to true. This rule only applies when the parent ECT when the parent ECT's "ext" contains policy keys.<a href="#section-6.2-2.5.1" class="pilcrow"></a></p>
contains policy claims.<a href="#section-6.2-2.5.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-6.2-2.6"> <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 <p id="section-6.2-2.6.1">Trust Domain Consistency: Parent tasks <span class="bcp14">SHOULD</span> belong to the
@@ -2678,22 +2672,22 @@ verifier's current time, to account for clock skew).<a href="#section-7.1-2.11.1
present and well-formed.<a href="#section-7.1-2.12.1" class="pilcrow"></a></p> present and well-formed.<a href="#section-7.1-2.12.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-7.1-2.13"> <li id="section-7.1-2.13">
<p id="section-7.1-2.13.1">If "pol" or "pol_decision" is present, verify that both are <p id="section-7.1-2.13.1">If "ext" is present and contains "pol" or "pol_decision",
present and that "pol_decision" is one of "approved", verify that both are present and that "pol_decision" is one
"rejected", or "pending_human_review".<a href="#section-7.1-2.13.1" class="pilcrow"></a></p> of "approved", "rejected", or "pending_human_review".<a href="#section-7.1-2.13.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-7.1-2.14"> <li id="section-7.1-2.14">
<p id="section-7.1-2.14.1">Perform DAG validation per <a href="#dag-validation" class="auto internal xref">Section 6</a>.<a href="#section-7.1-2.14.1" class="pilcrow"></a></p> <p id="section-7.1-2.14.1">Perform DAG validation per <a href="#dag-validation" class="auto internal xref">Section 6</a>.<a href="#section-7.1-2.14.1" class="pilcrow"></a></p>
</li> </li>
<li id="section-7.1-2.15"> <li id="section-7.1-2.15">
<p id="section-7.1-2.15.1">If all checks pass, the ECT <span class="bcp14">MUST</span> be appended to the audit <p id="section-7.1-2.15.1">If all checks pass and an audit ledger is deployed, the ECT
ledger.<a href="#section-7.1-2.15.1" class="pilcrow"></a></p> <span class="bcp14">SHOULD</span> be appended to the ledger.<a href="#section-7.1-2.15.1" class="pilcrow"></a></p>
</li> </li>
</ol> </ol>
<p id="section-7.1-3">If any verification step fails, the ECT <span class="bcp14">MUST</span> be rejected and the <p id="section-7.1-3">If any verification step fails, the ECT <span class="bcp14">MUST</span> be rejected and the
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> ECT store, 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 <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 receiving agent <span class="bcp14">SHOULD</span> respond with HTTP 403 (Forbidden) if the
WIT is valid but the ECT is invalid, and HTTP 401 WIT is valid but the ECT is invalid, and HTTP 401
@@ -2767,11 +2761,12 @@ function verify_ect(ect_jws, verifier_id,
if claim not in payload: if claim not in payload:
return reject("Missing required claim: " + claim) return reject("Missing required claim: " + claim)
// Validate policy claims (optional, but must be paired) // Validate policy extension keys (optional, but must be paired)
if "pol" in payload or "pol_decision" in payload: ext = payload.ext or {}
if "pol" not in payload or "pol_decision" not in payload: if "pol" in ext or "pol_decision" in ext:
if "pol" not in ext or "pol_decision" not in ext:
return reject("pol and pol_decision must both be present") return reject("pol and pol_decision must both be present")
if payload.pol_decision not in if ext.pol_decision not in
["approved", "rejected", "pending_human_review"]: ["approved", "rejected", "pending_human_review"]:
return reject("Invalid pol_decision value") return reject("Invalid pol_decision value")
@@ -2862,29 +2857,34 @@ software used in medical devices.<a href="#section-9.1-1" class="pilcrow">¶</a>
Agent A (Spec Reviewer): Agent A (Spec Reviewer):
jti: task-001 par: [] jti: task-001 par: []
exec_act: review_requirements_spec exec_act: review_requirements_spec
pol: spec_review_policy_v2 pol_decision: approved ext.pol: spec_review_policy_v2
ext.pol_decision: approved
Agent B (Code Generator): Agent B (Code Generator):
jti: task-002 par: [task-001] jti: task-002 par: [task-001]
exec_act: implement_module exec_act: implement_module
pol: coding_standards_v3 pol_decision: approved ext.pol: coding_standards_v3
ext.pol_decision: approved
Agent C (Test Agent): Agent C (Test Agent):
jti: task-003 par: [task-002] jti: task-003 par: [task-002]
exec_act: execute_test_suite exec_act: execute_test_suite
pol: test_coverage_policy_v1 pol_decision: approved ext.pol: test_coverage_policy_v1
ext.pol_decision: approved
Agent D (Build Agent): Agent D (Build Agent):
jti: task-004 par: [task-003] jti: task-004 par: [task-003]
exec_act: build_release_artifact exec_act: build_release_artifact
pol: build_validation_v2 pol_decision: approved ext.pol: build_validation_v2
ext.pol_decision: approved
Human Release Manager: Human Release Manager:
jti: task-005 par: [task-004] jti: task-005 par: [task-004]
exec_act: approve_release exec_act: approve_release
pol: release_approval_policy pol_decision: approved ext.pol: release_approval_policy
pol_enforcer: spiffe://meddev.example/human/release-mgr-42 ext.pol_decision: approved
ext: {witnessed_by: [...]} (extension metadata) ext.pol_enforcer: spiffe://meddev.example/human/release-mgr-42
ext.witnessed_by: [...]
</pre> </pre>
</div> </div>
<figcaption><a href="#figure-8" class="selfRef">Figure 8</a>: <figcaption><a href="#figure-8" class="selfRef">Figure 8</a>:
@@ -2987,17 +2987,20 @@ execution.<a href="#section-9.2-1" class="pilcrow">¶</a></p>
Agent A (Risk Assessment): Agent A (Risk Assessment):
jti: task-001 par: [] jti: task-001 par: []
exec_act: calculate_risk_exposure exec_act: calculate_risk_exposure
pol: risk_limits_policy_v2 pol_decision: approved ext.pol: risk_limits_policy_v2
ext.pol_decision: approved
Agent B (Compliance): Agent B (Compliance):
jti: task-002 par: [task-001] jti: task-002 par: [task-001]
exec_act: verify_compliance exec_act: verify_compliance
pol: compliance_check_v1 pol_decision: approved ext.pol: compliance_check_v1
ext.pol_decision: approved
Agent C (Execution): Agent C (Execution):
jti: task-003 par: [task-002] jti: task-003 par: [task-002]
exec_act: execute_trade exec_act: execute_trade
pol: execution_policy_v3 pol_decision: approved ext.pol: execution_policy_v3
ext.pol_decision: approved
</pre> </pre>
</div> </div>
<figcaption><a href="#figure-10" class="selfRef">Figure 10</a>: <figcaption><a href="#figure-10" class="selfRef">Figure 10</a>:
@@ -3034,7 +3037,6 @@ a cryptographic link to the original task:<a href="#section-9.3-1" class="pilcro
<pre> <pre>
{ {
"iss": "spiffe://bank.example/agent/operations", "iss": "spiffe://bank.example/agent/operations",
"sub": "spiffe://bank.example/agent/operations",
"aud": "spiffe://bank.example/system/ledger", "aud": "spiffe://bank.example/system/ledger",
"iat": 1772150550, "iat": 1772150550,
"exp": 1772151150, "exp": 1772151150,
@@ -3042,12 +3044,14 @@ a cryptographic link to the original task:<a href="#section-9.3-1" class="pilcro
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012", "wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
"exec_act": "initiate_trade_rollback", "exec_act": "initiate_trade_rollback",
"par": ["550e8400-e29b-41d4-a716-446655440003"], "par": ["550e8400-e29b-41d4-a716-446655440003"],
"ext": {
"pol": "compensation_policy_v1", "pol": "compensation_policy_v1",
"pol_decision": "approved", "pol_decision": "approved",
"pol_enforcer": "spiffe://bank.example/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"
} }
}
</pre> </pre>
</div> </div>
<figcaption><a href="#figure-11" class="selfRef">Figure 11</a>: <figcaption><a href="#figure-11" class="selfRef">Figure 11</a>:
@@ -3074,27 +3078,32 @@ required checks were completed:<a href="#section-9.4-1" class="pilcrow">¶</a></
Agent A (Route Planning): Agent A (Route Planning):
jti: task-001 par: [] jti: task-001 par: []
exec_act: plan_route exec_act: plan_route
pol: route_policy_v1 pol_decision: approved ext.pol: route_policy_v1
ext.pol_decision: approved
Agent B (Customs): Agent B (Customs):
jti: task-002 par: [task-001] jti: task-002 par: [task-001]
exec_act: validate_customs exec_act: validate_customs
pol: customs_policy_v2 pol_decision: approved ext.pol: customs_policy_v2
ext.pol_decision: approved
Agent C (Safety): Agent C (Safety):
jti: task-003 par: [task-001] jti: task-003 par: [task-001]
exec_act: verify_cargo_safety exec_act: verify_cargo_safety
pol: safety_policy_v1 pol_decision: approved ext.pol: safety_policy_v1
ext.pol_decision: approved
Agent D (Payment): Agent D (Payment):
jti: task-004 par: [task-002, task-003] jti: task-004 par: [task-002, task-003]
exec_act: authorize_payment exec_act: authorize_payment
pol: payment_policy_v3 pol_decision: approved ext.pol: payment_policy_v3
ext.pol_decision: approved
System (Commitment): System (Commitment):
jti: task-005 par: [task-004] jti: task-005 par: [task-004]
exec_act: commit_shipment exec_act: commit_shipment
pol: commitment_policy_v1 pol_decision: approved ext.pol: commitment_policy_v1
ext.pol_decision: approved
</pre> </pre>
</div> </div>
<figcaption><a href="#figure-12" class="selfRef">Figure 12</a>: <figcaption><a href="#figure-12" class="selfRef">Figure 12</a>:
@@ -3149,8 +3158,8 @@ to alter perceived execution ordering.<a href="#section-10.1-2.4.1" class="pilcr
<p id="section-10.2-1">ECTs are self-asserted by the executing agent. The agent claims <p id="section-10.2-1">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
compromised or malicious agent could create ECTs with false claims compromised or malicious agent could create ECTs with false claims
(e.g., setting "pol_decision" to "approved" without actually (e.g., setting "pol_decision" in "ext" to "approved" without
evaluating the policy).<a href="#section-10.2-1" class="pilcrow"></a></p> actually evaluating the policy).<a href="#section-10.2-1" class="pilcrow"></a></p>
<p id="section-10.2-2">ECTs do not independently verify that:<a href="#section-10.2-2" class="pilcrow"></a></p> <p id="section-10.2-2">ECTs do not independently verify that:<a href="#section-10.2-2" class="pilcrow"></a></p>
<ul class="normal"> <ul class="normal">
<li class="normal" id="section-10.2-3.1"> <li class="normal" id="section-10.2-3.1">
@@ -3176,44 +3185,11 @@ witnesses do not co-sign the ECT and there is no cryptographic
evidence within a single ECT that the witnesses actually evidence within a single ECT that the witnesses actually
observed the task. An issuing agent could list witnesses that observed the task. An issuing agent could list witnesses that
did not participate.<a href="#section-10.2-4" class="pilcrow"></a></p> did not participate.<a href="#section-10.2-4" class="pilcrow"></a></p>
<div id="witness-attestation-model"> <p id="section-10.2-5">To strengthen witness attestation beyond self-assertion, witnesses
<section id="section-10.2.1"> <span class="bcp14">SHOULD</span> submit their own independent signed ECTs referencing the
<h4 id="name-witness-attestation-model"> observed task's "jti" in the "par" array. Auditors can then
<a href="#section-10.2.1" class="section-number selfRef">10.2.1. </a><a href="#name-witness-attestation-model" class="section-name selfRef">Witness Attestation Model</a> cross-check the "witnessed_by" extension against independent
</h4> witness ECTs in the ECT store.<a href="#section-10.2-5" class="pilcrow"></a></p>
<p id="section-10.2.1-1">To address the self-assertion limitation of the
"witnessed_by" extension, witnesses <span class="bcp14">SHOULD</span> submit their
own independent signed ECTs to the audit ledger attesting to the
observed task. A witness attestation ECT:<a href="#section-10.2.1-1" class="pilcrow"></a></p>
<ul class="normal">
<li class="normal" id="section-10.2.1-2.1">
<p id="section-10.2.1-2.1.1"><span class="bcp14">MUST</span> set "iss" to the witness's own workload identity.<a href="#section-10.2.1-2.1.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-10.2.1-2.2">
<p id="section-10.2.1-2.2.1"><span class="bcp14">MUST</span> set "exec_act" to "witness_attestation" (or a domain-
specific equivalent).<a href="#section-10.2.1-2.2.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-10.2.1-2.3">
<p id="section-10.2.1-2.3.1"><span class="bcp14">MUST</span> include the observed task's "jti" in the "par" array,
linking the attestation to the original task.<a href="#section-10.2.1-2.3.1" class="pilcrow"></a></p>
</li>
<li class="normal" id="section-10.2.1-2.4">
<p id="section-10.2.1-2.4.1"><span class="bcp14">MUST</span> set "pol_decision" to "approved" to indicate the witness
confirms the observation.<a href="#section-10.2.1-2.4.1" class="pilcrow"></a></p>
</li>
</ul>
<p id="section-10.2.1-3">When a task's "witnessed_by" extension lists one or more
witnesses, auditors <span class="bcp14">SHOULD</span> verify that corresponding witness
attestation ECTs exist in the ledger for each listed witness. A
mismatch between the extension value and the set of independent
witness ECTs in the ledger <span class="bcp14">SHOULD</span> be flagged during audit review.<a href="#section-10.2.1-3" class="pilcrow"></a></p>
<p id="section-10.2.1-4">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.<a href="#section-10.2.1-4" class="pilcrow"></a></p>
</section>
</div>
</section> </section>
</div> </div>
<div id="organizational-prerequisites"> <div id="organizational-prerequisites">
@@ -3439,8 +3415,8 @@ serialized as JSON and <span class="bcp14">SHOULD NOT</span> exceed a nesting de
<p id="section-11.1-2.2.1">Action descriptions ("exec_act") for audit trail completeness<a href="#section-11.1-2.2.1" class="pilcrow"></a></p> <p id="section-11.1-2.2.1">Action descriptions ("exec_act") for audit trail completeness<a href="#section-11.1-2.2.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-11.1-2.3"> <li class="normal" id="section-11.1-2.3">
<p id="section-11.1-2.3.1">Policy evaluation outcomes ("pol", "pol_decision") for <p id="section-11.1-2.3.1">Policy evaluation outcomes (via "ext" keys "pol",
compliance verification<a href="#section-11.1-2.3.1" class="pilcrow"></a></p> "pol_decision") when present, for compliance verification<a href="#section-11.1-2.3.1" class="pilcrow"></a></p>
</li> </li>
<li class="normal" id="section-11.1-2.4"> <li class="normal" id="section-11.1-2.4">
<p id="section-11.1-2.4.1">Timestamps ("iat", "exp") for temporal ordering<a href="#section-11.1-2.4.1" class="pilcrow"></a></p> <p id="section-11.1-2.4.1">Timestamps ("iat", "exp") for temporal ordering<a href="#section-11.1-2.4.1" class="pilcrow"></a></p>
@@ -3472,17 +3448,13 @@ hashes via "inp_hash" and "out_hash")<a href="#section-11.1-4.1.1" class="pilcro
<p id="section-11.2-1">Implementations <span class="bcp14">SHOULD</span> minimize the information included in ECTs. <p id="section-11.2-1">Implementations <span class="bcp14">SHOULD</span> minimize the information included in ECTs.
The "exec_act" claim <span class="bcp14">SHOULD</span> use structured identifiers (e.g., The "exec_act" claim <span class="bcp14">SHOULD</span> use structured identifiers (e.g.,
"process_payment") rather than natural language descriptions. "process_payment") rather than natural language descriptions.
The "pol" claim <span class="bcp14">SHOULD</span> reference policy identifiers rather than The "pol" extension key <span class="bcp14">SHOULD</span> reference policy identifiers
embedding policy content.<a href="#section-11.2-1" class="pilcrow"></a></p> rather than embedding policy content.<a href="#section-11.2-1" class="pilcrow"></a></p>
<p id="section-11.2-2">The "compensation_reason" claim (<a href="#compensation-claims" class="auto internal xref">Section 4.2.5</a>) <p id="section-11.2-2">The "compensation_reason" extension key in "ext"
deserves particular attention: because it is human-readable and (<a href="#compensation-claims" class="auto internal xref">Section 4.2.5</a>) deserves particular attention: because
may describe the circumstances of a failure or policy violation, it is human-readable, it risks exposing sensitive operational
it risks exposing sensitive operational details. Implementations details. See <a href="#extension-claims" class="auto internal xref">Section 4.2.6</a> for guidance on using
<span class="bcp14">SHOULD</span> use short, structured reason codes (e.g., structured identifiers.<a href="#section-11.2-2" class="pilcrow"></a></p>
"policy_violation_in_parent_trade") rather than free-form
natural language explanations. Implementers <span class="bcp14">SHOULD</span> review
"compensation_reason" values for potential information leakage
before deploying to production.<a href="#section-11.2-2" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="storage-and-access-control"> <div id="storage-and-access-control">
@@ -3680,30 +3652,6 @@ 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="#exec-claims" class="auto internal xref">Section 4.2.2</a> <a href="#exec-claims" class="auto internal xref">Section 4.2.2</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">pol</td>
<td class="text-left" rowspan="1" colspan="1">Policy Rule Identifier</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">pol_decision</td>
<td class="text-left" rowspan="1" colspan="1">Policy Decision Result</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">pol_enforcer</td>
<td class="text-left" rowspan="1" colspan="1">Policy Enforcer Identity</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> </td>
</tr> </tr>
<tr> <tr>
@@ -3720,22 +3668,6 @@ 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="#data-integrity-claims" class="auto internal xref">Section 4.2.4</a> <a href="#data-integrity-claims" class="auto internal xref">Section 4.2.4</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">compensation_required</td>
<td class="text-left" rowspan="1" colspan="1">Compensation Flag</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#compensation-claims" class="auto internal xref">Section 4.2.5</a>
</td>
</tr>
<tr>
<td class="text-center" rowspan="1" colspan="1">compensation_reason</td>
<td class="text-left" rowspan="1" colspan="1">Compensation Reason</td>
<td class="text-center" rowspan="1" colspan="1">IETF</td>
<td class="text-center" rowspan="1" colspan="1">
<a href="#compensation-claims" class="auto internal xref">Section 4.2.5</a>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -3749,6 +3681,10 @@ the "JSON Web Token Claims" registry maintained by IANA:<a href="#section-12.3-1
</tbody> </tbody>
</table> </table>
</div> </div>
<p id="section-12.3-3">Note: Policy evaluation keys ("pol", "pol_decision",
"pol_enforcer") are carried within the "ext" object as
spec-defined extension keys (<a href="#policy-claims" class="auto internal xref">Section 4.2.3</a>) and do not
require separate JWT Claims registration.<a href="#section-12.3-3" class="pilcrow"></a></p>
</section> </section>
</div> </div>
<div id="pol-decision-registry"> <div id="pol-decision-registry">
@@ -4101,8 +4037,9 @@ use cases are distinct.<a href="#appendix-A.7-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", "jti", "exec_act", "par") and policy claims ("pol", "exp", "jti", "exec_act", "par") and policy extension keys
"pol_decision") when policy evaluation was performed.<a href="#appendix-B.1-2.1.1" class="pilcrow"></a></p> ("ext.pol", "ext.pol_decision") when policy evaluation was
performed.<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
@@ -4116,7 +4053,7 @@ matching the WIT (ES256 recommended).<a href="#appendix-B.1-2.2.1" class="pilcro
cycle detection).<a href="#appendix-B.1-2.4.1" class="pilcrow"></a></p> cycle detection).<a href="#appendix-B.1-2.4.1" class="pilcrow"></a></p>
</li> </li>
<li id="appendix-B.1-2.5"> <li id="appendix-B.1-2.5">
<p id="appendix-B.1-2.5.1">Append verified ECTs to the audit ledger.<a href="#appendix-B.1-2.5.1" class="pilcrow"></a></p> <p id="appendix-B.1-2.5.1">If an audit ledger is deployed, append verified ECTs to it.<a href="#appendix-B.1-2.5.1" class="pilcrow"></a></p>
</li> </li>
</ol> </ol>
</section> </section>
@@ -4269,7 +4206,6 @@ Agent B:<a href="#appendix-D.1-1" class="pilcrow">¶</a></p>
<pre> <pre>
{ {
"iss": "spiffe://example.com/agent/data-retrieval", "iss": "spiffe://example.com/agent/data-retrieval",
"sub": "spiffe://example.com/agent/data-retrieval",
"aud": "spiffe://example.com/agent/validator", "aud": "spiffe://example.com/agent/validator",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
@@ -4277,10 +4213,12 @@ Agent B:<a href="#appendix-D.1-1" class="pilcrow">¶</a></p>
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890", "wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
"exec_act": "fetch_patient_data", "exec_act": "fetch_patient_data",
"par": [], "par": [],
"pol": "clinical_data_access_policy_v1",
"pol_decision": "approved",
"inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg", "inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564" "out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
"ext": {
"pol": "clinical_data_access_policy_v1",
"pol_decision": "approved"
}
} }
</pre><a href="#appendix-D.1-5" class="pilcrow"></a> </pre><a href="#appendix-D.1-5" class="pilcrow"></a>
</div> </div>
@@ -4290,7 +4228,6 @@ task, and creates its own ECT:<a href="#appendix-D.1-6" class="pilcrow">¶</a></
<pre> <pre>
{ {
"iss": "spiffe://example.com/agent/validator", "iss": "spiffe://example.com/agent/validator",
"sub": "spiffe://example.com/agent/validator",
"aud": "spiffe://example.com/system/ledger", "aud": "spiffe://example.com/system/ledger",
"iat": 1772064160, "iat": 1772064160,
"exp": 1772064760, "exp": 1772064760,
@@ -4298,9 +4235,11 @@ task, and creates its own ECT:<a href="#appendix-D.1-6" class="pilcrow">¶</a></
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890", "wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
"exec_act": "validate_safety", "exec_act": "validate_safety",
"par": ["550e8400-e29b-41d4-a716-446655440001"], "par": ["550e8400-e29b-41d4-a716-446655440001"],
"ext": {
"pol": "safety_validation_policy_v2", "pol": "safety_validation_policy_v2",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
</pre><a href="#appendix-D.1-7" class="pilcrow"></a> </pre><a href="#appendix-D.1-7" class="pilcrow"></a>
</div> </div>
<p id="appendix-D.1-8">The resulting DAG:<a href="#appendix-D.1-8" class="pilcrow"></a></p> <p id="appendix-D.1-8">The resulting DAG:<a href="#appendix-D.1-8" class="pilcrow"></a></p>
@@ -4326,7 +4265,6 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
<pre> <pre>
{ {
"iss": "spiffe://meddev.example/agent/spec-reviewer", "iss": "spiffe://meddev.example/agent/spec-reviewer",
"sub": "spiffe://meddev.example/agent/spec-reviewer",
"aud": "spiffe://meddev.example/agent/code-gen", "aud": "spiffe://meddev.example/agent/code-gen",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
@@ -4334,10 +4272,12 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "review_requirements_spec", "exec_act": "review_requirements_spec",
"par": [], "par": [],
"pol": "spec_review_policy_v2",
"pol_decision": "approved",
"inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg", "inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564" "out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
"ext": {
"pol": "spec_review_policy_v2",
"pol_decision": "approved"
}
} }
</pre><a href="#appendix-D.2-3" class="pilcrow"></a> </pre><a href="#appendix-D.2-3" class="pilcrow"></a>
</div> </div>
@@ -4346,7 +4286,6 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
<pre> <pre>
{ {
"iss": "spiffe://meddev.example/agent/code-gen", "iss": "spiffe://meddev.example/agent/code-gen",
"sub": "spiffe://meddev.example/agent/code-gen",
"aud": "spiffe://meddev.example/agent/test-runner", "aud": "spiffe://meddev.example/agent/test-runner",
"iat": 1772064200, "iat": 1772064200,
"exp": 1772064800, "exp": 1772064800,
@@ -4354,9 +4293,11 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "implement_module", "exec_act": "implement_module",
"par": ["a1b2c3d4-0001-0000-0000-000000000001"], "par": ["a1b2c3d4-0001-0000-0000-000000000001"],
"ext": {
"pol": "coding_standards_v3", "pol": "coding_standards_v3",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
</pre><a href="#appendix-D.2-5" class="pilcrow"></a> </pre><a href="#appendix-D.2-5" class="pilcrow"></a>
</div> </div>
<p id="appendix-D.2-6">Task 3 (Autonomous Test Agent):<a href="#appendix-D.2-6" class="pilcrow"></a></p> <p id="appendix-D.2-6">Task 3 (Autonomous Test Agent):<a href="#appendix-D.2-6" class="pilcrow"></a></p>
@@ -4364,7 +4305,6 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
<pre> <pre>
{ {
"iss": "spiffe://meddev.example/agent/test-runner", "iss": "spiffe://meddev.example/agent/test-runner",
"sub": "spiffe://meddev.example/agent/test-runner",
"aud": "spiffe://meddev.example/agent/build", "aud": "spiffe://meddev.example/agent/build",
"iat": 1772064260, "iat": 1772064260,
"exp": 1772064860, "exp": 1772064860,
@@ -4372,9 +4312,11 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "execute_test_suite", "exec_act": "execute_test_suite",
"par": ["a1b2c3d4-0001-0000-0000-000000000002"], "par": ["a1b2c3d4-0001-0000-0000-000000000002"],
"ext": {
"pol": "test_coverage_policy_v1", "pol": "test_coverage_policy_v1",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
</pre><a href="#appendix-D.2-7" class="pilcrow"></a> </pre><a href="#appendix-D.2-7" class="pilcrow"></a>
</div> </div>
<p id="appendix-D.2-8">Task 4 (Build Agent):<a href="#appendix-D.2-8" class="pilcrow"></a></p> <p id="appendix-D.2-8">Task 4 (Build Agent):<a href="#appendix-D.2-8" class="pilcrow"></a></p>
@@ -4382,7 +4324,6 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
<pre> <pre>
{ {
"iss": "spiffe://meddev.example/agent/build", "iss": "spiffe://meddev.example/agent/build",
"sub": "spiffe://meddev.example/agent/build",
"aud": "spiffe://meddev.example/human/release-mgr-42", "aud": "spiffe://meddev.example/human/release-mgr-42",
"iat": 1772064310, "iat": 1772064310,
"exp": 1772064910, "exp": 1772064910,
@@ -4390,9 +4331,11 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "build_release_artifact", "exec_act": "build_release_artifact",
"par": ["a1b2c3d4-0001-0000-0000-000000000003"], "par": ["a1b2c3d4-0001-0000-0000-000000000003"],
"out_hash": "sha-256:Ry1YfOoW2XpC5Mq8HkGzNx3dL9vBa4sUjE7iKt0wPZc",
"ext": {
"pol": "build_validation_v2", "pol": "build_validation_v2",
"pol_decision": "approved", "pol_decision": "approved"
"out_hash": "sha-256:Ry1YfOoW2XpC5Mq8HkGzNx3dL9vBa4sUjE7iKt0wPZc" }
} }
</pre><a href="#appendix-D.2-9" class="pilcrow"></a> </pre><a href="#appendix-D.2-9" class="pilcrow"></a>
</div> </div>
@@ -4401,7 +4344,6 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
<pre> <pre>
{ {
"iss": "spiffe://meddev.example/human/release-mgr-42", "iss": "spiffe://meddev.example/human/release-mgr-42",
"sub": "spiffe://meddev.example/human/release-mgr-42",
"aud": "spiffe://meddev.example/system/ledger", "aud": "spiffe://meddev.example/system/ledger",
"iat": 1772064510, "iat": 1772064510,
"exp": 1772065110, "exp": 1772065110,
@@ -4409,10 +4351,10 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "approve_release", "exec_act": "approve_release",
"par": ["a1b2c3d4-0001-0000-0000-000000000004"], "par": ["a1b2c3d4-0001-0000-0000-000000000004"],
"ext": {
"pol": "release_approval_policy", "pol": "release_approval_policy",
"pol_decision": "approved", "pol_decision": "approved",
"pol_enforcer": "spiffe://meddev.example/human/release-mgr-42", "pol_enforcer": "spiffe://meddev.example/human/release-mgr-42",
"ext": {
"witnessed_by": [ "witnessed_by": [
"spiffe://meddev.example/audit/qa-observer-1" "spiffe://meddev.example/audit/qa-observer-1"
] ]
@@ -4474,7 +4416,6 @@ task-...-0004 (execute_trade)
<pre> <pre>
{ {
"iss": "spiffe://bank.example/agent/execution", "iss": "spiffe://bank.example/agent/execution",
"sub": "spiffe://bank.example/agent/execution",
"aud": "spiffe://bank.example/system/ledger", "aud": "spiffe://bank.example/system/ledger",
"iat": 1772064250, "iat": 1772064250,
"exp": 1772064850, "exp": 1772064850,
@@ -4485,9 +4426,11 @@ task-...-0004 (execute_trade)
"f1e2d3c4-0002-0000-0000-000000000002", "f1e2d3c4-0002-0000-0000-000000000002",
"f1e2d3c4-0003-0000-0000-000000000003" "f1e2d3c4-0003-0000-0000-000000000003"
], ],
"ext": {
"pol": "trade_execution_policy_v3", "pol": "trade_execution_policy_v3",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
</pre><a href="#appendix-D.3-4" class="pilcrow"></a> </pre><a href="#appendix-D.3-4" class="pilcrow"></a>
</div> </div>
<p id="appendix-D.3-5">The "par" array with two entries records that both compliance <p id="appendix-D.3-5">The "par" array with two entries records that both compliance

View File

@@ -167,7 +167,7 @@ This document defines:
- The Execution Context Token (ECT) format ({{ect-format}}) - The Execution Context Token (ECT) format ({{ect-format}})
- DAG structure for task dependency ordering ({{dag-validation}}) - DAG structure for task dependency ordering ({{dag-validation}})
- Policy checkpoint recording ({{policy-claims}}) - Policy checkpoint recording via extension keys ({{policy-claims}})
- Integration with the WIMSE identity framework - Integration with the WIMSE identity framework
({{wimse-integration}}) ({{wimse-integration}})
- An HTTP header for ECT transport ({{http-header}}) - An HTTP header for ECT transport ({{http-header}})
@@ -403,12 +403,6 @@ iss:
deployments MAY use other URI schemes (e.g., HTTPS URLs or deployments MAY use other URI schemes (e.g., HTTPS URLs or
URN:UUID identifiers). URN:UUID identifiers).
sub:
: OPTIONAL. StringOrURI. The subject of the ECT. When present,
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. Because ECTs serve as both inter-agent recipient(s) of the ECT. Because ECTs serve as both inter-agent
@@ -489,21 +483,25 @@ par:
a root task with no dependencies. A workflow MAY contain a root task with no dependencies. A workflow MAY contain
multiple root tasks. multiple root tasks.
### Policy Evaluation {#policy-claims} ### Policy Evaluation Extension Keys {#policy-claims}
The following claims record policy evaluation outcomes: Policy evaluation outcomes are recorded as extension keys within
the "ext" object ({{extension-claims}}). This keeps the core
registered claims focused on DAG structure and execution context,
while allowing deployments to add policy recording as needed.
pol: The following extension keys are defined for policy evaluation:
: OPTIONAL. String. The identifier of the policy rule that was
evaluated for this task (e.g.,
"clinical_data_access_policy_v1"). MUST be present when
"pol_decision" is present.
pol_decision: "pol":
: OPTIONAL. String. The result of the policy evaluation. When : String. The identifier of the policy rule that was evaluated
present, MUST be one of the values registered in the ECT Policy for this task (e.g., "clinical_data_access_policy_v1"). MUST
Decision Values registry ({{pol-decision-registry}}). MUST be be present when "pol_decision" is present.
present when "pol" is present. Initial values are:
"pol_decision":
: String. The result of the policy evaluation. When present,
MUST be one of the values registered in the ECT Policy Decision
Values registry ({{pol-decision-registry}}). MUST be present
when "pol" is present. Initial values are:
* "approved": The policy evaluation succeeded and the task * "approved": The policy evaluation succeeded and the task
was authorized to proceed. was authorized to proceed.
@@ -522,25 +520,25 @@ pol_decision:
records an "approved" decision referencing this task as a records an "approved" decision referencing this task as a
parent. parent.
When "pol" and "pol_decision" are absent, the ECT records task When "pol" and "pol_decision" are absent from "ext", the ECT
execution without a policy checkpoint. Regulated deployments records task execution without a policy checkpoint. Regulated
SHOULD include policy claims on all ECTs to maintain complete deployments SHOULD include policy keys on all ECTs to maintain
audit trails. complete audit trails.
pol_enforcer: "pol_enforcer":
: OPTIONAL. StringOrURI. The identity of the entity (system or : StringOrURI. The identity of the entity (system or person)
person) that evaluated the policy decision. When present, that evaluated the policy decision. When present, SHOULD use
SHOULD use SPIFFE ID format. SPIFFE ID format.
This specification intentionally defines only the recording of This specification intentionally defines only the recording of
policy evaluation outcomes. The mechanisms by which policies are policy evaluation outcomes. The mechanisms by which policies are
defined, distributed to agents, and evaluated are out of scope. defined, distributed to agents, and evaluated are out of scope.
The "pol" claim is an opaque identifier referencing an external The "pol" key is an opaque identifier referencing an external
policy; the semantics and enforcement of that policy are policy; the semantics and enforcement of that policy are
determined by the deployment environment. Implementations may determined by the deployment environment. Implementations may
use any policy engine or framework (e.g., OPA/Rego, Cedar, XACML, use any policy engine or framework (e.g., OPA/Rego, Cedar, XACML,
or custom solutions) provided that the evaluation outcome is or custom solutions) provided that the evaluation outcome is
faithfully recorded in the ECT claims defined above. faithfully recorded in the "ext" keys defined above.
### Data Integrity {#data-integrity-claims} ### Data Integrity {#data-integrity-claims}
@@ -565,25 +563,12 @@ out_hash:
### Compensation and Rollback {#compensation-claims} ### Compensation and Rollback {#compensation-claims}
compensation_required: Compensation and rollback actions are recorded using the "par"
: OPTIONAL. Boolean. Indicates whether this task is a claim to reference the original task and the "exec_act" claim to
compensation or rollback action for a previous task. describe the remediation action. The referenced parent ECTs may
have passed their own "exp" time; ECT expiration applies to the
compensation_reason: verification window of the ECT itself, not to its validity as a
: OPTIONAL. String. A human-readable reason for the compensation parent reference in the ECT store.
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
"par" claim. The referenced parent ECTs may have passed their own
"exp" time; ECT expiration applies to the verification window of
the ECT itself, not to its validity as a parent reference in the
ledger.
### Extensions {#extension-claims} ### Extensions {#extension-claims}
@@ -604,7 +589,20 @@ exceeds these limits.
The following extension keys are defined by this specification The following extension keys are defined by this specification
for common use cases. Because these keys are documented here, for common use cases. Because these keys are documented here,
they use short names without reverse domain prefixes: they use short names without reverse domain prefixes.
Policy evaluation keys (see {{policy-claims}} for full
definitions and decision value semantics):
- "pol": String. Policy rule identifier.
- "pol\_decision": String. Policy evaluation outcome
("approved", "rejected", or "pending\_human\_review").
- "pol\_enforcer": StringOrURI. Identity of the policy
evaluator.
- "pol\_timestamp": NumericDate. Time at which the policy
decision was made, if distinct from "iat".
Operational metadata keys:
- "exec\_time\_ms": Integer. Execution duration in milliseconds. - "exec\_time\_ms": Integer. Execution duration in milliseconds.
- "regulated\_domain": String. Regulatory domain (e.g., - "regulated\_domain": String. Regulatory domain (e.g.,
@@ -616,8 +614,12 @@ they use short names without reverse domain prefixes:
attestation, witnesses should submit independent signed ECTs. attestation, witnesses should submit independent signed ECTs.
- "inp\_classification": String. Data sensitivity classification - "inp\_classification": String. Data sensitivity classification
(e.g., "public", "confidential", "restricted"). (e.g., "public", "confidential", "restricted").
- "pol\_timestamp": NumericDate. Time at which the policy - "compensation\_required": Boolean. Indicates whether this task
decision was made, if distinct from "iat". is a compensation or rollback action.
- "compensation\_reason": String. Structured reason code for the
compensation action (e.g., "policy\_violation\_in\_parent\_trade").
SHOULD use structured identifiers rather than free-form text
to minimize information leakage (see {{data-minimization}}).
## Complete ECT Example ## Complete ECT Example
@@ -626,7 +628,6 @@ The following is a complete ECT payload example:
~~~json ~~~json
{ {
"iss": "spiffe://example.com/agent/clinical", "iss": "spiffe://example.com/agent/clinical",
"sub": "spiffe://example.com/agent/clinical",
"aud": "spiffe://example.com/agent/safety", "aud": "spiffe://example.com/agent/safety",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
@@ -636,14 +637,13 @@ The following is a complete ECT payload example:
"exec_act": "recommend_treatment", "exec_act": "recommend_treatment",
"par": [], "par": [],
"pol": "clinical_reasoning_policy_v2",
"pol_decision": "approved",
"pol_enforcer": "spiffe://example.com/policy/clinical-engine",
"inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg", "inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564", "out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
"ext": { "ext": {
"pol": "clinical_reasoning_policy_v2",
"pol_decision": "approved",
"pol_enforcer": "spiffe://example.com/policy/clinical-engine",
"pol_timestamp": 1772064145, "pol_timestamp": 1772064145,
"exec_time_ms": 245, "exec_time_ms": 245,
"regulated_domain": "medtech", "regulated_domain": "medtech",
@@ -733,15 +733,14 @@ the following DAG validation steps:
lead back to the current ECT's "jti". If a cycle is detected, lead back to the current ECT's "jti". If a cycle is detected,
the ECT MUST be rejected. the ECT MUST be rejected.
5. Parent Policy Decision: If any parent ECT contains a 5. Parent Policy Decision: If any parent ECT's "ext" object
"pol_decision" of "rejected" or "pending_human_review", the contains a "pol_decision" of "rejected" or
current ECT's "exec_act" MUST indicate a compensation, "pending_human_review", the current ECT's "exec_act" MUST
rollback, remediation, or human review action. indicate a compensation, rollback, remediation, or human
Implementations MUST NOT accept an ECT representing normal review action. Implementations MUST NOT accept an ECT
workflow continuation when a parent's "pol_decision" is not representing normal workflow continuation when a parent's
"approved", unless the current ECT has "compensation_required" "pol_decision" is not "approved". This rule only applies
set to true. This rule only applies when the parent ECT when the parent ECT's "ext" contains policy keys.
contains policy claims.
6. Trust Domain Consistency: Parent tasks SHOULD belong to the 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
@@ -856,19 +855,19 @@ verification steps in order:
12. Verify all required claims ("jti", "exec_act", "par") are 12. Verify all required claims ("jti", "exec_act", "par") are
present and well-formed. present and well-formed.
13. If "pol" or "pol_decision" is present, verify that both are 13. If "ext" is present and contains "pol" or "pol_decision",
present and that "pol_decision" is one of "approved", verify that both are present and that "pol_decision" is one
"rejected", or "pending_human_review". of "approved", "rejected", or "pending_human_review".
14. Perform DAG validation per {{dag-validation}}. 14. Perform DAG validation per {{dag-validation}}.
15. If all checks pass, the ECT MUST be appended to the audit 15. If all checks pass and an audit ledger is deployed, the ECT
ledger. SHOULD be appended to the 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
failure MUST be logged for audit purposes. Error messages 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. ECT store, to prevent information disclosure.
When ECT verification fails during HTTP request processing, the When ECT verification fails during HTTP request processing, the
receiving agent SHOULD respond with HTTP 403 (Forbidden) if the receiving agent SHOULD respond with HTTP 403 (Forbidden) if the
@@ -936,11 +935,12 @@ function verify_ect(ect_jws, verifier_id,
if claim not in payload: if claim not in payload:
return reject("Missing required claim: " + claim) return reject("Missing required claim: " + claim)
// Validate policy claims (optional, but must be paired) // Validate policy extension keys (optional, but must be paired)
if "pol" in payload or "pol_decision" in payload: ext = payload.ext or {}
if "pol" not in payload or "pol_decision" not in payload: if "pol" in ext or "pol_decision" in ext:
if "pol" not in ext or "pol_decision" not in ext:
return reject("pol and pol_decision must both be present") return reject("pol and pol_decision must both be present")
if payload.pol_decision not in if ext.pol_decision not in
["approved", "rejected", "pending_human_review"]: ["approved", "rejected", "pending_human_review"]:
return reject("Invalid pol_decision value") return reject("Invalid pol_decision value")
@@ -1010,29 +1010,34 @@ software used in medical devices.
Agent A (Spec Reviewer): Agent A (Spec Reviewer):
jti: task-001 par: [] jti: task-001 par: []
exec_act: review_requirements_spec exec_act: review_requirements_spec
pol: spec_review_policy_v2 pol_decision: approved ext.pol: spec_review_policy_v2
ext.pol_decision: approved
Agent B (Code Generator): Agent B (Code Generator):
jti: task-002 par: [task-001] jti: task-002 par: [task-001]
exec_act: implement_module exec_act: implement_module
pol: coding_standards_v3 pol_decision: approved ext.pol: coding_standards_v3
ext.pol_decision: approved
Agent C (Test Agent): Agent C (Test Agent):
jti: task-003 par: [task-002] jti: task-003 par: [task-002]
exec_act: execute_test_suite exec_act: execute_test_suite
pol: test_coverage_policy_v1 pol_decision: approved ext.pol: test_coverage_policy_v1
ext.pol_decision: approved
Agent D (Build Agent): Agent D (Build Agent):
jti: task-004 par: [task-003] jti: task-004 par: [task-003]
exec_act: build_release_artifact exec_act: build_release_artifact
pol: build_validation_v2 pol_decision: approved ext.pol: build_validation_v2
ext.pol_decision: approved
Human Release Manager: Human Release Manager:
jti: task-005 par: [task-004] jti: task-005 par: [task-004]
exec_act: approve_release exec_act: approve_release
pol: release_approval_policy pol_decision: approved ext.pol: release_approval_policy
pol_enforcer: spiffe://meddev.example/human/release-mgr-42 ext.pol_decision: approved
ext: {witnessed_by: [...]} (extension metadata) ext.pol_enforcer: spiffe://meddev.example/human/release-mgr-42
ext.witnessed_by: [...]
~~~ ~~~
{: #fig-medtech-sdlc title="Medical Device SDLC Workflow"} {: #fig-medtech-sdlc title="Medical Device SDLC Workflow"}
@@ -1098,17 +1103,20 @@ execution.
Agent A (Risk Assessment): Agent A (Risk Assessment):
jti: task-001 par: [] jti: task-001 par: []
exec_act: calculate_risk_exposure exec_act: calculate_risk_exposure
pol: risk_limits_policy_v2 pol_decision: approved ext.pol: risk_limits_policy_v2
ext.pol_decision: approved
Agent B (Compliance): Agent B (Compliance):
jti: task-002 par: [task-001] jti: task-002 par: [task-001]
exec_act: verify_compliance exec_act: verify_compliance
pol: compliance_check_v1 pol_decision: approved ext.pol: compliance_check_v1
ext.pol_decision: approved
Agent C (Execution): Agent C (Execution):
jti: task-003 par: [task-002] jti: task-003 par: [task-002]
exec_act: execute_trade exec_act: execute_trade
pol: execution_policy_v3 pol_decision: approved ext.pol: execution_policy_v3
ext.pol_decision: approved
~~~ ~~~
{: #fig-finance title="Financial Trading Workflow"} {: #fig-finance title="Financial Trading Workflow"}
@@ -1129,7 +1137,6 @@ a cryptographic link to the original task:
~~~json ~~~json
{ {
"iss": "spiffe://bank.example/agent/operations", "iss": "spiffe://bank.example/agent/operations",
"sub": "spiffe://bank.example/agent/operations",
"aud": "spiffe://bank.example/system/ledger", "aud": "spiffe://bank.example/system/ledger",
"iat": 1772150550, "iat": 1772150550,
"exp": 1772151150, "exp": 1772151150,
@@ -1137,12 +1144,14 @@ a cryptographic link to the original task:
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012", "wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
"exec_act": "initiate_trade_rollback", "exec_act": "initiate_trade_rollback",
"par": ["550e8400-e29b-41d4-a716-446655440003"], "par": ["550e8400-e29b-41d4-a716-446655440003"],
"ext": {
"pol": "compensation_policy_v1", "pol": "compensation_policy_v1",
"pol_decision": "approved", "pol_decision": "approved",
"pol_enforcer": "spiffe://bank.example/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"
} }
}
~~~ ~~~
{: #fig-compensation title="Compensation ECT Example"} {: #fig-compensation title="Compensation ECT Example"}
@@ -1160,27 +1169,32 @@ required checks were completed:
Agent A (Route Planning): Agent A (Route Planning):
jti: task-001 par: [] jti: task-001 par: []
exec_act: plan_route exec_act: plan_route
pol: route_policy_v1 pol_decision: approved ext.pol: route_policy_v1
ext.pol_decision: approved
Agent B (Customs): Agent B (Customs):
jti: task-002 par: [task-001] jti: task-002 par: [task-001]
exec_act: validate_customs exec_act: validate_customs
pol: customs_policy_v2 pol_decision: approved ext.pol: customs_policy_v2
ext.pol_decision: approved
Agent C (Safety): Agent C (Safety):
jti: task-003 par: [task-001] jti: task-003 par: [task-001]
exec_act: verify_cargo_safety exec_act: verify_cargo_safety
pol: safety_policy_v1 pol_decision: approved ext.pol: safety_policy_v1
ext.pol_decision: approved
Agent D (Payment): Agent D (Payment):
jti: task-004 par: [task-002, task-003] jti: task-004 par: [task-002, task-003]
exec_act: authorize_payment exec_act: authorize_payment
pol: payment_policy_v3 pol_decision: approved ext.pol: payment_policy_v3
ext.pol_decision: approved
System (Commitment): System (Commitment):
jti: task-005 par: [task-004] jti: task-005 par: [task-004]
exec_act: commit_shipment exec_act: commit_shipment
pol: commitment_policy_v1 pol_decision: approved ext.pol: commitment_policy_v1
ext.pol_decision: approved
~~~ ~~~
{: #fig-logistics title="Logistics Workflow with Parallel Tasks"} {: #fig-logistics title="Logistics Workflow with Parallel Tasks"}
@@ -1211,8 +1225,8 @@ The following threat actors are considered:
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
compromised or malicious agent could create ECTs with false claims compromised or malicious agent could create ECTs with false claims
(e.g., setting "pol_decision" to "approved" without actually (e.g., setting "pol_decision" in "ext" to "approved" without
evaluating the policy). actually evaluating the policy).
ECTs do not independently verify that: ECTs do not independently verify that:
@@ -1232,32 +1246,11 @@ evidence within a single ECT that the witnesses actually
observed the task. An issuing agent could list witnesses that observed the task. An issuing agent could list witnesses that
did not participate. did not participate.
### Witness Attestation Model {#witness-attestation-model} To strengthen witness attestation beyond self-assertion, witnesses
SHOULD submit their own independent signed ECTs referencing the
To address the self-assertion limitation of the observed task's "jti" in the "par" array. Auditors can then
"witnessed_by" extension, witnesses SHOULD submit their cross-check the "witnessed_by" extension against independent
own independent signed ECTs to the audit ledger attesting to the witness ECTs in the ECT store.
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 "jti" 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" extension 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 extension value 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
@@ -1409,8 +1402,8 @@ ECTs necessarily reveal:
- Agent identities ("iss", "aud") for accountability purposes - Agent identities ("iss", "aud") for accountability purposes
- Action descriptions ("exec_act") for audit trail completeness - Action descriptions ("exec_act") for audit trail completeness
- Policy evaluation outcomes ("pol", "pol_decision") for - Policy evaluation outcomes (via "ext" keys "pol",
compliance verification "pol_decision") when present, for compliance verification
- Timestamps ("iat", "exp") for temporal ordering - Timestamps ("iat", "exp") for temporal ordering
ECTs are designed to NOT reveal: ECTs are designed to NOT reveal:
@@ -1426,18 +1419,14 @@ ECTs are designed to NOT reveal:
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.,
"process_payment") rather than natural language descriptions. "process_payment") rather than natural language descriptions.
The "pol" claim SHOULD reference policy identifiers rather than The "pol" extension key SHOULD reference policy identifiers
embedding policy content. rather than embedding policy content.
The "compensation_reason" claim ({{compensation-claims}}) The "compensation_reason" extension key in "ext"
deserves particular attention: because it is human-readable and ({{compensation-claims}}) deserves particular attention: because
may describe the circumstances of a failure or policy violation, it is human-readable, it risks exposing sensitive operational
it risks exposing sensitive operational details. Implementations details. See {{extension-claims}} for guidance on using
SHOULD use short, structured reason codes (e.g., structured identifiers.
"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
@@ -1540,16 +1529,16 @@ the "JSON Web Token Claims" registry maintained by IANA:
| wid | Workflow Identifier | IETF | {{exec-claims}} | | wid | Workflow Identifier | IETF | {{exec-claims}} |
| exec_act | Action/Task Type | IETF | {{exec-claims}} | | exec_act | Action/Task Type | IETF | {{exec-claims}} |
| par | Parent Task Identifiers | IETF | {{exec-claims}} | | par | Parent Task Identifiers | IETF | {{exec-claims}} |
| pol | Policy Rule Identifier | IETF | {{policy-claims}} |
| pol_decision | Policy Decision Result | IETF | {{policy-claims}} |
| pol_enforcer | Policy Enforcer Identity | IETF | {{policy-claims}} |
| inp_hash | Input Data Hash | IETF | {{data-integrity-claims}} | | inp_hash | Input Data Hash | IETF | {{data-integrity-claims}} |
| out_hash | Output Data Hash | IETF | {{data-integrity-claims}} | | out_hash | Output Data Hash | IETF | {{data-integrity-claims}} |
| compensation_required | Compensation Flag | IETF | {{compensation-claims}} |
| compensation_reason | Compensation Reason | IETF | {{compensation-claims}} |
| ext | Extension Object | IETF | {{extension-claims}} | | ext | Extension Object | IETF | {{extension-claims}} |
{: #table-claims title="JWT Claims Registrations"} {: #table-claims title="JWT Claims Registrations"}
Note: Policy evaluation keys ("pol", "pol_decision",
"pol_enforcer") are carried within the "ext" object as
spec-defined extension keys ({{policy-claims}}) and do not
require separate JWT Claims registration.
## ECT Policy Decision Values Registry {#pol-decision-registry} ## ECT Policy Decision Values Registry {#pol-decision-registry}
This document establishes the "ECT Policy Decision Values" This document establishes the "ECT Policy Decision Values"
@@ -1704,14 +1693,15 @@ use cases are distinct.
A minimal conforming implementation needs to: 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", "jti", "exec_act", "par") and policy claims ("pol", "exp", "jti", "exec_act", "par") and policy extension keys
"pol_decision") when policy evaluation was performed. ("ext.pol", "ext.pol_decision") when policy evaluation was
performed.
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.
4. Perform DAG validation (parent existence, temporal ordering, 4. Perform DAG validation (parent existence, temporal ordering,
cycle detection). cycle detection).
5. Append verified ECTs to the audit ledger. 5. If an audit ledger is deployed, append verified ECTs to it.
## Storage Recommendations ## Storage Recommendations
{:numbered="false"} {:numbered="false"}
@@ -1787,7 +1777,6 @@ ECT Payload:
~~~json ~~~json
{ {
"iss": "spiffe://example.com/agent/data-retrieval", "iss": "spiffe://example.com/agent/data-retrieval",
"sub": "spiffe://example.com/agent/data-retrieval",
"aud": "spiffe://example.com/agent/validator", "aud": "spiffe://example.com/agent/validator",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
@@ -1795,10 +1784,12 @@ ECT Payload:
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890", "wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
"exec_act": "fetch_patient_data", "exec_act": "fetch_patient_data",
"par": [], "par": [],
"pol": "clinical_data_access_policy_v1",
"pol_decision": "approved",
"inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg", "inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564" "out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
"ext": {
"pol": "clinical_data_access_policy_v1",
"pol_decision": "approved"
}
} }
~~~ ~~~
@@ -1808,7 +1799,6 @@ task, and creates its own ECT:
~~~json ~~~json
{ {
"iss": "spiffe://example.com/agent/validator", "iss": "spiffe://example.com/agent/validator",
"sub": "spiffe://example.com/agent/validator",
"aud": "spiffe://example.com/system/ledger", "aud": "spiffe://example.com/system/ledger",
"iat": 1772064160, "iat": 1772064160,
"exp": 1772064760, "exp": 1772064760,
@@ -1816,9 +1806,11 @@ task, and creates its own ECT:
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890", "wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
"exec_act": "validate_safety", "exec_act": "validate_safety",
"par": ["550e8400-e29b-41d4-a716-446655440001"], "par": ["550e8400-e29b-41d4-a716-446655440001"],
"ext": {
"pol": "safety_validation_policy_v2", "pol": "safety_validation_policy_v2",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
~~~ ~~~
The resulting DAG: The resulting DAG:
@@ -1841,7 +1833,6 @@ Task 1 (Spec Review Agent):
~~~json ~~~json
{ {
"iss": "spiffe://meddev.example/agent/spec-reviewer", "iss": "spiffe://meddev.example/agent/spec-reviewer",
"sub": "spiffe://meddev.example/agent/spec-reviewer",
"aud": "spiffe://meddev.example/agent/code-gen", "aud": "spiffe://meddev.example/agent/code-gen",
"iat": 1772064150, "iat": 1772064150,
"exp": 1772064750, "exp": 1772064750,
@@ -1849,10 +1840,12 @@ Task 1 (Spec Review Agent):
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "review_requirements_spec", "exec_act": "review_requirements_spec",
"par": [], "par": [],
"pol": "spec_review_policy_v2",
"pol_decision": "approved",
"inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg", "inp_hash": "sha-256:n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564" "out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
"ext": {
"pol": "spec_review_policy_v2",
"pol_decision": "approved"
}
} }
~~~ ~~~
@@ -1861,7 +1854,6 @@ Task 2 (Code Generation Agent):
~~~json ~~~json
{ {
"iss": "spiffe://meddev.example/agent/code-gen", "iss": "spiffe://meddev.example/agent/code-gen",
"sub": "spiffe://meddev.example/agent/code-gen",
"aud": "spiffe://meddev.example/agent/test-runner", "aud": "spiffe://meddev.example/agent/test-runner",
"iat": 1772064200, "iat": 1772064200,
"exp": 1772064800, "exp": 1772064800,
@@ -1869,9 +1861,11 @@ Task 2 (Code Generation Agent):
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "implement_module", "exec_act": "implement_module",
"par": ["a1b2c3d4-0001-0000-0000-000000000001"], "par": ["a1b2c3d4-0001-0000-0000-000000000001"],
"ext": {
"pol": "coding_standards_v3", "pol": "coding_standards_v3",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
~~~ ~~~
Task 3 (Autonomous Test Agent): Task 3 (Autonomous Test Agent):
@@ -1879,7 +1873,6 @@ Task 3 (Autonomous Test Agent):
~~~json ~~~json
{ {
"iss": "spiffe://meddev.example/agent/test-runner", "iss": "spiffe://meddev.example/agent/test-runner",
"sub": "spiffe://meddev.example/agent/test-runner",
"aud": "spiffe://meddev.example/agent/build", "aud": "spiffe://meddev.example/agent/build",
"iat": 1772064260, "iat": 1772064260,
"exp": 1772064860, "exp": 1772064860,
@@ -1887,9 +1880,11 @@ Task 3 (Autonomous Test Agent):
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "execute_test_suite", "exec_act": "execute_test_suite",
"par": ["a1b2c3d4-0001-0000-0000-000000000002"], "par": ["a1b2c3d4-0001-0000-0000-000000000002"],
"ext": {
"pol": "test_coverage_policy_v1", "pol": "test_coverage_policy_v1",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
~~~ ~~~
Task 4 (Build Agent): Task 4 (Build Agent):
@@ -1897,7 +1892,6 @@ Task 4 (Build Agent):
~~~json ~~~json
{ {
"iss": "spiffe://meddev.example/agent/build", "iss": "spiffe://meddev.example/agent/build",
"sub": "spiffe://meddev.example/agent/build",
"aud": "spiffe://meddev.example/human/release-mgr-42", "aud": "spiffe://meddev.example/human/release-mgr-42",
"iat": 1772064310, "iat": 1772064310,
"exp": 1772064910, "exp": 1772064910,
@@ -1905,9 +1899,11 @@ Task 4 (Build Agent):
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "build_release_artifact", "exec_act": "build_release_artifact",
"par": ["a1b2c3d4-0001-0000-0000-000000000003"], "par": ["a1b2c3d4-0001-0000-0000-000000000003"],
"out_hash": "sha-256:Ry1YfOoW2XpC5Mq8HkGzNx3dL9vBa4sUjE7iKt0wPZc",
"ext": {
"pol": "build_validation_v2", "pol": "build_validation_v2",
"pol_decision": "approved", "pol_decision": "approved"
"out_hash": "sha-256:Ry1YfOoW2XpC5Mq8HkGzNx3dL9vBa4sUjE7iKt0wPZc" }
} }
~~~ ~~~
@@ -1916,7 +1912,6 @@ Task 5 (Human Release Manager Approval):
~~~json ~~~json
{ {
"iss": "spiffe://meddev.example/human/release-mgr-42", "iss": "spiffe://meddev.example/human/release-mgr-42",
"sub": "spiffe://meddev.example/human/release-mgr-42",
"aud": "spiffe://meddev.example/system/ledger", "aud": "spiffe://meddev.example/system/ledger",
"iat": 1772064510, "iat": 1772064510,
"exp": 1772065110, "exp": 1772065110,
@@ -1924,10 +1919,10 @@ Task 5 (Human Release Manager Approval):
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901", "wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
"exec_act": "approve_release", "exec_act": "approve_release",
"par": ["a1b2c3d4-0001-0000-0000-000000000004"], "par": ["a1b2c3d4-0001-0000-0000-000000000004"],
"ext": {
"pol": "release_approval_policy", "pol": "release_approval_policy",
"pol_decision": "approved", "pol_decision": "approved",
"pol_enforcer": "spiffe://meddev.example/human/release-mgr-42", "pol_enforcer": "spiffe://meddev.example/human/release-mgr-42",
"ext": {
"witnessed_by": [ "witnessed_by": [
"spiffe://meddev.example/audit/qa-observer-1" "spiffe://meddev.example/audit/qa-observer-1"
] ]
@@ -1986,7 +1981,6 @@ Task 004 ECT payload:
~~~json ~~~json
{ {
"iss": "spiffe://bank.example/agent/execution", "iss": "spiffe://bank.example/agent/execution",
"sub": "spiffe://bank.example/agent/execution",
"aud": "spiffe://bank.example/system/ledger", "aud": "spiffe://bank.example/system/ledger",
"iat": 1772064250, "iat": 1772064250,
"exp": 1772064850, "exp": 1772064850,
@@ -1997,9 +1991,11 @@ Task 004 ECT payload:
"f1e2d3c4-0002-0000-0000-000000000002", "f1e2d3c4-0002-0000-0000-000000000002",
"f1e2d3c4-0003-0000-0000-000000000003" "f1e2d3c4-0003-0000-0000-000000000003"
], ],
"ext": {
"pol": "trade_execution_policy_v3", "pol": "trade_execution_policy_v3",
"pol_decision": "approved" "pol_decision": "approved"
} }
}
~~~ ~~~
The "par" array with two entries records that both compliance The "par" array with two entries records that both compliance

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff