Merge tid into jti and make policy claims optional
- Eliminate the "tid" claim; "jti" now serves as both token ID (for replay detection) and task ID (for DAG parent references in "par") - Make "pol" and "pol_decision" OPTIONAL (must be paired when present) - Regulated deployments SHOULD still include policy claims - Reduces required ECT-specific claims to just "exec_act" and "par" - Remove "tid" from IANA JWT Claims registration - Update all examples, pseudocode, and DAG validation rules Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2180,11 +2180,15 @@ upon issuance.<a href="#section-4.2.1-3" class="pilcrow">¶</a></p>
|
|||||||
<span class="break"></span><dl class="dlParallel" id="section-4.2.1-4">
|
<span class="break"></span><dl class="dlParallel" id="section-4.2.1-4">
|
||||||
<dt id="section-4.2.1-4.1">jti:</dt>
|
<dt id="section-4.2.1-4.1">jti:</dt>
|
||||||
<dd style="margin-left: 1.5em" id="section-4.2.1-4.2">
|
<dd style="margin-left: 1.5em" id="section-4.2.1-4.2">
|
||||||
<p id="section-4.2.1-4.2.1"><span class="bcp14">REQUIRED</span>. String. A unique identifier for the ECT in UUID
|
<p id="section-4.2.1-4.2.1"><span class="bcp14">REQUIRED</span>. String. A globally unique identifier for both the
|
||||||
format <span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>. Used for replay detection: receivers <span class="bcp14">MUST</span>
|
ECT and the task it records, in UUID format <span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>. Since
|
||||||
reject ECTs whose "jti" has already been seen within the
|
each ECT represents exactly one task, "jti" serves as both the
|
||||||
expiration window. The "jti" value <span class="bcp14">MUST</span> be unique across all
|
token identifier (for replay detection) and the task identifier
|
||||||
ECTs issued by the same agent.<a href="#section-4.2.1-4.2.1" class="pilcrow">¶</a></p>
|
(for DAG parent references in "par"). Receivers <span class="bcp14">MUST</span> reject
|
||||||
|
ECTs whose "jti" has already been seen within the expiration
|
||||||
|
window. When "wid" is present, uniqueness is scoped to the
|
||||||
|
workflow; when "wid" is absent, uniqueness <span class="bcp14">MUST</span> be enforced
|
||||||
|
globally across the ECT store.<a href="#section-4.2.1-4.2.1" class="pilcrow">¶</a></p>
|
||||||
</dd>
|
</dd>
|
||||||
<dd class="break"></dd>
|
<dd class="break"></dd>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -2201,36 +2205,26 @@ ECTs issued by the same agent.<a href="#section-4.2.1-4.2.1" class="pilcrow">¶<
|
|||||||
<dd style="margin-left: 1.5em" id="section-4.2.2-2.2">
|
<dd style="margin-left: 1.5em" id="section-4.2.2-2.2">
|
||||||
<p id="section-4.2.2-2.2.1"><span class="bcp14">OPTIONAL</span>. String. A workflow identifier that groups related
|
<p id="section-4.2.2-2.2.1"><span class="bcp14">OPTIONAL</span>. String. A workflow identifier that groups related
|
||||||
ECTs into a single workflow. When present, <span class="bcp14">MUST</span> be a UUID
|
ECTs into a single workflow. When present, <span class="bcp14">MUST</span> be a UUID
|
||||||
<span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>. When absent, the "tid" uniqueness requirement
|
<span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>.<a href="#section-4.2.2-2.2.1" class="pilcrow">¶</a></p>
|
||||||
applies globally across the entire ledger.<a href="#section-4.2.2-2.2.1" class="pilcrow">¶</a></p>
|
|
||||||
</dd>
|
</dd>
|
||||||
<dd class="break"></dd>
|
<dd class="break"></dd>
|
||||||
<dt id="section-4.2.2-2.3">tid:</dt>
|
<dt id="section-4.2.2-2.3">exec_act:</dt>
|
||||||
<dd style="margin-left: 1.5em" id="section-4.2.2-2.4">
|
<dd style="margin-left: 1.5em" id="section-4.2.2-2.4">
|
||||||
<p id="section-4.2.2-2.4.1"><span class="bcp14">REQUIRED</span>. String. A globally unique task identifier in UUID
|
<p id="section-4.2.2-2.4.1"><span class="bcp14">REQUIRED</span>. String. The action or task type identifier describing
|
||||||
format <span>[<a href="#RFC9562" class="cite xref">RFC9562</a>]</span>. Each task <span class="bcp14">MUST</span> have a unique "tid" value.
|
|
||||||
When "wid" is present, uniqueness is scoped to the workflow;
|
|
||||||
when "wid" is absent, uniqueness <span class="bcp14">MUST</span> be enforced globally
|
|
||||||
across the ledger.<a href="#section-4.2.2-2.4.1" class="pilcrow">¶</a></p>
|
|
||||||
</dd>
|
|
||||||
<dd class="break"></dd>
|
|
||||||
<dt id="section-4.2.2-2.5">exec_act:</dt>
|
|
||||||
<dd style="margin-left: 1.5em" id="section-4.2.2-2.6">
|
|
||||||
<p id="section-4.2.2-2.6.1"><span class="bcp14">REQUIRED</span>. String. The action or task type identifier describing
|
|
||||||
what the agent performed (e.g., "process_payment",
|
what the agent performed (e.g., "process_payment",
|
||||||
"validate_safety", "calculate_dosage"). Note: this claim is
|
"validate_safety", "calculate_dosage"). Note: this claim is
|
||||||
intentionally named "exec_act" rather than "act" to avoid
|
intentionally named "exec_act" rather than "act" to avoid
|
||||||
collision with the "act" (Actor) claim registered by
|
collision with the "act" (Actor) claim registered by
|
||||||
<span>[<a href="#RFC8693" class="cite xref">RFC8693</a>]</span>.<a href="#section-4.2.2-2.6.1" class="pilcrow">¶</a></p>
|
<span>[<a href="#RFC8693" class="cite xref">RFC8693</a>]</span>.<a href="#section-4.2.2-2.4.1" class="pilcrow">¶</a></p>
|
||||||
</dd>
|
</dd>
|
||||||
<dd class="break"></dd>
|
<dd class="break"></dd>
|
||||||
<dt id="section-4.2.2-2.7">par:</dt>
|
<dt id="section-4.2.2-2.5">par:</dt>
|
||||||
<dd style="margin-left: 1.5em" id="section-4.2.2-2.8">
|
<dd style="margin-left: 1.5em" id="section-4.2.2-2.6">
|
||||||
<p id="section-4.2.2-2.8.1"><span class="bcp14">REQUIRED</span>. Array of strings. Parent task identifiers
|
<p id="section-4.2.2-2.6.1"><span class="bcp14">REQUIRED</span>. Array of strings. Parent task identifiers
|
||||||
representing DAG dependencies. Each element <span class="bcp14">MUST</span> be a valid
|
representing DAG dependencies. Each element <span class="bcp14">MUST</span> be the "jti"
|
||||||
"tid" from a previously executed task. An empty array indicates
|
value of a previously verified ECT. An empty array indicates
|
||||||
a root task with no dependencies. A workflow <span class="bcp14">MAY</span> contain
|
a root task with no dependencies. A workflow <span class="bcp14">MAY</span> contain
|
||||||
multiple root tasks.<a href="#section-4.2.2-2.8.1" class="pilcrow">¶</a></p>
|
multiple root tasks.<a href="#section-4.2.2-2.6.1" class="pilcrow">¶</a></p>
|
||||||
</dd>
|
</dd>
|
||||||
<dd class="break"></dd>
|
<dd class="break"></dd>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -2245,17 +2239,18 @@ multiple root tasks.<a href="#section-4.2.2-2.8.1" class="pilcrow">¶</a></p>
|
|||||||
<span class="break"></span><dl class="dlParallel" id="section-4.2.3-2">
|
<span class="break"></span><dl class="dlParallel" id="section-4.2.3-2">
|
||||||
<dt id="section-4.2.3-2.1">pol:</dt>
|
<dt id="section-4.2.3-2.1">pol:</dt>
|
||||||
<dd style="margin-left: 1.5em" id="section-4.2.3-2.2">
|
<dd style="margin-left: 1.5em" id="section-4.2.3-2.2">
|
||||||
<p id="section-4.2.3-2.2.1"><span class="bcp14">REQUIRED</span>. String. The identifier of the policy rule that was
|
<p id="section-4.2.3-2.2.1"><span class="bcp14">OPTIONAL</span>. String. The identifier of the policy rule that was
|
||||||
evaluated for this task (e.g.,
|
evaluated for this task (e.g.,
|
||||||
"clinical_data_access_policy_v1").<a href="#section-4.2.3-2.2.1" class="pilcrow">¶</a></p>
|
"clinical_data_access_policy_v1"). <span class="bcp14">MUST</span> be present when
|
||||||
|
"pol_decision" is present.<a href="#section-4.2.3-2.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-2.3">pol_decision:</dt>
|
||||||
<dd style="margin-left: 1.5em" id="section-4.2.3-2.4">
|
<dd style="margin-left: 1.5em" id="section-4.2.3-2.4">
|
||||||
<p id="section-4.2.3-2.4.1"><span class="bcp14">REQUIRED</span>. String. The result of the policy evaluation. <span class="bcp14">MUST</span>
|
<p id="section-4.2.3-2.4.1"><span class="bcp14">OPTIONAL</span>. String. The result of the policy evaluation. When
|
||||||
be one of the values registered in the ECT Policy Decision
|
present, <span class="bcp14">MUST</span> be one of the values registered in the ECT Policy
|
||||||
Values registry (<a href="#pol-decision-registry" class="auto internal xref">Section 13.4</a>). Initial values
|
Decision Values registry (<a href="#pol-decision-registry" class="auto internal xref">Section 13.4</a>). <span class="bcp14">MUST</span> be
|
||||||
are:<a href="#section-4.2.3-2.4.1" class="pilcrow">¶</a></p>
|
present when "pol" is present. Initial values are:<a href="#section-4.2.3-2.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-2.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-2.4.2.1.1">"approved": The policy evaluation succeeded and the task
|
||||||
@@ -2263,11 +2258,12 @@ was authorized to proceed.<a href="#section-4.2.3-2.4.2.1.1" class="pilcrow">¶<
|
|||||||
</li>
|
</li>
|
||||||
<li class="normal" id="section-4.2.3-2.4.2.2">
|
<li class="normal" id="section-4.2.3-2.4.2.2">
|
||||||
<p id="section-4.2.3-2.4.2.2.1">"rejected": The policy evaluation failed. A "rejected" ECT
|
<p id="section-4.2.3-2.4.2.2.1">"rejected": The policy evaluation failed. A "rejected" ECT
|
||||||
<span class="bcp14">MUST</span> still be appended to the audit ledger for accountability.
|
<span class="bcp14">MUST</span> still be recorded for accountability. An ECT with
|
||||||
An ECT with "pol_decision" of "rejected" <span class="bcp14">MAY</span> appear as a
|
"pol_decision" of "rejected" <span class="bcp14">MAY</span> appear as a parent in the
|
||||||
parent in the "par" array of a subsequent ECT, but only for
|
"par" array of a subsequent ECT, but only for compensation,
|
||||||
compensation, rollback, or remediation tasks. Agents <span class="bcp14">MUST NOT</span> proceed with normal workflow execution based on a parent
|
rollback, or remediation tasks. Agents <span class="bcp14">MUST NOT</span> proceed
|
||||||
ECT whose "pol_decision" is "rejected".<a href="#section-4.2.3-2.4.2.2.1" class="pilcrow">¶</a></p>
|
with normal workflow execution based on a parent ECT whose
|
||||||
|
"pol_decision" is "rejected".<a href="#section-4.2.3-2.4.2.2.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li class="normal" id="section-4.2.3-2.4.2.3">
|
<li class="normal" id="section-4.2.3-2.4.2.3">
|
||||||
<p id="section-4.2.3-2.4.2.3.1">"pending_human_review": The policy evaluation requires human
|
<p id="section-4.2.3-2.4.2.3.1">"pending_human_review": The policy evaluation requires human
|
||||||
@@ -2277,6 +2273,10 @@ 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-2.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
|
||||||
|
execution without a policy checkpoint. Regulated deployments
|
||||||
|
<span class="bcp14">SHOULD</span> include policy claims on all ECTs to maintain complete
|
||||||
|
audit trails.<a href="#section-4.2.3-2.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-2.5">pol_enforcer:</dt>
|
||||||
@@ -2463,10 +2463,9 @@ ECTs whose "ext" claim exceeds these limits.<a href="#section-4.2.7-2" class="pi
|
|||||||
"aud": "spiffe://example.com/agent/safety",
|
"aud": "spiffe://example.com/agent/safety",
|
||||||
"iat": 1772064150,
|
"iat": 1772064150,
|
||||||
"exp": 1772064750,
|
"exp": 1772064750,
|
||||||
"jti": "7f3a8b2c-d1e4-4f56-9a0b-c3d4e5f6a7b8",
|
"jti": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
|
||||||
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"exec_act": "recommend_treatment",
|
"exec_act": "recommend_treatment",
|
||||||
"par": [],
|
"par": [],
|
||||||
|
|
||||||
@@ -2576,10 +2575,10 @@ parent ECTs available to the verifier.<a href="#section-6.1-2" class="pilcrow">
|
|||||||
the following DAG validation steps:<a href="#section-6.2-1" class="pilcrow">¶</a></p>
|
the following DAG validation steps:<a href="#section-6.2-1" class="pilcrow">¶</a></p>
|
||||||
<ol start="1" type="1" class="normal type-1" id="section-6.2-2">
|
<ol start="1" type="1" class="normal type-1" id="section-6.2-2">
|
||||||
<li id="section-6.2-2.1">
|
<li id="section-6.2-2.1">
|
||||||
<p id="section-6.2-2.1.1">Task ID Uniqueness: The "tid" claim <span class="bcp14">MUST</span> be unique within the
|
<p id="section-6.2-2.1.1">Task ID Uniqueness: The "jti" claim <span class="bcp14">MUST</span> be unique within the
|
||||||
applicable scope (the workflow identified by "wid", or the
|
applicable scope (the workflow identified by "wid", or the
|
||||||
entire ECT store if "wid" is absent). If a task with the same
|
entire ECT store if "wid" is absent). If an ECT with the same
|
||||||
"tid" already exists, the ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.1.1" class="pilcrow">¶</a></p>
|
"jti" already exists, the ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.1.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li id="section-6.2-2.2">
|
<li id="section-6.2-2.2">
|
||||||
<p id="section-6.2-2.2.1">Parent Existence: Every task identifier listed in the "par"
|
<p id="section-6.2-2.2.1">Parent Existence: Every task identifier listed in the "par"
|
||||||
@@ -2601,17 +2600,19 @@ ECT <span class="bcp14">MUST</span> be rejected.<a href="#section-6.2-2.3.1" cla
|
|||||||
</li>
|
</li>
|
||||||
<li id="section-6.2-2.4">
|
<li id="section-6.2-2.4">
|
||||||
<p id="section-6.2-2.4.1">Acyclicity: Following the chain of parent references <span class="bcp14">MUST NOT</span>
|
<p id="section-6.2-2.4.1">Acyclicity: Following the chain of parent references <span class="bcp14">MUST NOT</span>
|
||||||
lead back to the current task's "tid". If a cycle is detected,
|
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 task has a "pol_decision"
|
<p id="section-6.2-2.5.1">Parent Policy Decision: If any parent ECT contains a
|
||||||
of "rejected" or "pending_human_review", the current task's
|
"pol_decision" of "rejected" or "pending_human_review", the
|
||||||
"exec_act" <span class="bcp14">MUST</span> indicate a compensation, rollback, remediation,
|
current ECT's "exec_act" <span class="bcp14">MUST</span> indicate a compensation,
|
||||||
or human review action. Implementations <span class="bcp14">MUST NOT</span> accept an ECT
|
rollback, remediation, or human review action.
|
||||||
representing normal workflow continuation when a parent's
|
Implementations <span class="bcp14">MUST NOT</span> accept an ECT representing normal
|
||||||
"pol_decision" is not "approved", unless the current ECT has
|
workflow continuation when a parent's "pol_decision" is not
|
||||||
"compensation_required" set to true.<a href="#section-6.2-2.5.1" class="pilcrow">¶</a></p>
|
"approved", unless the current ECT has "compensation_required"
|
||||||
|
set to true. This rule only applies when the parent ECT
|
||||||
|
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
|
||||||
@@ -2634,8 +2635,8 @@ relationship has been established.<a href="#section-6.2-2.6.1" class="pilcrow">
|
|||||||
function validate_dag(ect, ect_store, clock_skew_tolerance):
|
function validate_dag(ect, ect_store, clock_skew_tolerance):
|
||||||
// ect_store: ledger or local cache of verified ECTs
|
// ect_store: ledger or local cache of verified ECTs
|
||||||
// Step 1: Uniqueness check
|
// Step 1: Uniqueness check
|
||||||
if ect_store.contains(ect.tid, ect.wid):
|
if ect_store.contains(ect.jti, ect.wid):
|
||||||
return error("Task ID already exists")
|
return error("ECT ID already exists")
|
||||||
|
|
||||||
// Step 2: Parent existence and temporal ordering
|
// Step 2: Parent existence and temporal ordering
|
||||||
for parent_id in ect.par:
|
for parent_id in ect.par:
|
||||||
@@ -2647,26 +2648,26 @@ function validate_dag(ect, ect_store, clock_skew_tolerance):
|
|||||||
|
|
||||||
// Step 3: Cycle detection (with traversal limit)
|
// Step 3: Cycle detection (with traversal limit)
|
||||||
visited = set()
|
visited = set()
|
||||||
result = has_cycle(ect.tid, ect.par, ect_store, visited,
|
result = has_cycle(ect.jti, ect.par, ect_store, visited,
|
||||||
max_ancestor_limit)
|
max_ancestor_limit)
|
||||||
if result is error or result is true:
|
if result is error or result is true:
|
||||||
return error("Circular dependency or depth limit exceeded")
|
return error("Circular dependency or depth limit exceeded")
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
function has_cycle(target_tid, parent_ids, ect_store,
|
function has_cycle(target_jti, parent_ids, ect_store,
|
||||||
visited, max_depth):
|
visited, max_depth):
|
||||||
if visited.size() >= max_depth:
|
if visited.size() >= max_depth:
|
||||||
return error("Maximum ancestor traversal limit exceeded")
|
return error("Maximum ancestor traversal limit exceeded")
|
||||||
for parent_id in parent_ids:
|
for parent_id in parent_ids:
|
||||||
if parent_id == target_tid:
|
if parent_id == target_jti:
|
||||||
return true
|
return true
|
||||||
if parent_id in visited:
|
if parent_id in visited:
|
||||||
continue
|
continue
|
||||||
visited.add(parent_id)
|
visited.add(parent_id)
|
||||||
parent = ect_store.get(parent_id)
|
parent = ect_store.get(parent_id)
|
||||||
if parent is not null:
|
if parent is not null:
|
||||||
result = has_cycle(target_tid, parent.par, ect_store,
|
result = has_cycle(target_jti, parent.par, ect_store,
|
||||||
visited, max_depth)
|
visited, max_depth)
|
||||||
if result is error or result is true:
|
if result is error or result is true:
|
||||||
return result
|
return result
|
||||||
@@ -2757,12 +2758,13 @@ identity <span class="bcp14">MUST</span> appear in "aud".<a href="#section-7.1-2
|
|||||||
verifier's current time, to account for clock skew).<a href="#section-7.1-2.11.1" class="pilcrow">¶</a></p>
|
verifier's current time, to account for clock skew).<a href="#section-7.1-2.11.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li id="section-7.1-2.12">
|
<li id="section-7.1-2.12">
|
||||||
<p id="section-7.1-2.12.1">Verify all required claims ("jti", "tid", "exec_act", "par",
|
<p id="section-7.1-2.12.1">Verify all required claims ("jti", "exec_act", "par") are
|
||||||
"pol", "pol_decision") are 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">Verify "pol_decision" is one of "approved", "rejected", or
|
<p id="section-7.1-2.13.1">If "pol" or "pol_decision" is present, verify that both are
|
||||||
"pending_human_review".<a href="#section-7.1-2.13.1" class="pilcrow">¶</a></p>
|
present and that "pol_decision" is one 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>
|
||||||
@@ -2847,15 +2849,17 @@ function verify_ect(ect_jws, verifier_id,
|
|||||||
return reject("ECT issued in the future")
|
return reject("ECT issued in the future")
|
||||||
|
|
||||||
// Verify required claims
|
// Verify required claims
|
||||||
for claim in ["jti", "tid", "exec_act", "par",
|
for claim in ["jti", "exec_act", "par"]:
|
||||||
"pol", "pol_decision"]:
|
|
||||||
if claim not in payload:
|
if claim not in payload:
|
||||||
return reject("Missing required claim: " + claim)
|
return reject("Missing required claim: " + claim)
|
||||||
|
|
||||||
// Validate pol_decision value
|
// Validate policy claims (optional, but must be paired)
|
||||||
if payload.pol_decision not in
|
if "pol" in payload or "pol_decision" in payload:
|
||||||
["approved", "rejected", "pending_human_review"]:
|
if "pol" not in payload or "pol_decision" not in payload:
|
||||||
return reject("Invalid pol_decision value")
|
return reject("pol and pol_decision must both be present")
|
||||||
|
if payload.pol_decision not in
|
||||||
|
["approved", "rejected", "pending_human_review"]:
|
||||||
|
return reject("Invalid pol_decision value")
|
||||||
|
|
||||||
// Validate DAG (against ledger or inline parent ECTs)
|
// Validate DAG (against ledger or inline parent ECTs)
|
||||||
result = validate_dag(payload, ect_store,
|
result = validate_dag(payload, ect_store,
|
||||||
@@ -2921,7 +2925,7 @@ ECTs<a href="#section-8.1-5.1.1" class="pilcrow">¶</a></p>
|
|||||||
</li>
|
</li>
|
||||||
<li class="normal" id="section-8.1-5.2">
|
<li class="normal" id="section-8.1-5.2">
|
||||||
<p id="section-8.1-5.2.1">Global replay detection relies solely on "jti" caches at each
|
<p id="section-8.1-5.2.1">Global replay detection relies solely on "jti" caches at each
|
||||||
agent; there is no centralized "tid" uniqueness check<a href="#section-8.1-5.2.1" class="pilcrow">¶</a></p>
|
agent; there is no centralized "jti" uniqueness check<a href="#section-8.1-5.2.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li class="normal" id="section-8.1-5.3">
|
<li class="normal" id="section-8.1-5.3">
|
||||||
<p id="section-8.1-5.3.1">The parent ECT chain grows with each hop, increasing HTTP
|
<p id="section-8.1-5.3.1">The parent ECT chain grows with each hop, increasing HTTP
|
||||||
@@ -3008,7 +3012,7 @@ entries via a monotonically increasing sequence number.<a href="#section-9.2-2.2
|
|||||||
</li>
|
</li>
|
||||||
<li id="section-9.2-2.3">
|
<li id="section-9.2-2.3">
|
||||||
<p id="section-9.2-2.3.1">Lookup by task ID: The ledger <span class="bcp14">MUST</span> support efficient retrieval
|
<p id="section-9.2-2.3.1">Lookup by task ID: The ledger <span class="bcp14">MUST</span> support efficient retrieval
|
||||||
of ECT entries by "tid" value.<a href="#section-9.2-2.3.1" class="pilcrow">¶</a></p>
|
of ECT entries by "jti" value.<a href="#section-9.2-2.3.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li id="section-9.2-2.4">
|
<li id="section-9.2-2.4">
|
||||||
<p id="section-9.2-2.4.1">Integrity verification: The ledger <span class="bcp14">SHOULD</span> provide a mechanism
|
<p id="section-9.2-2.4.1">Integrity verification: The ledger <span class="bcp14">SHOULD</span> provide a mechanism
|
||||||
@@ -3032,7 +3036,7 @@ workflow agents to reduce the risk of collusion.<a href="#section-9.2-3" class="
|
|||||||
<pre>
|
<pre>
|
||||||
{
|
{
|
||||||
"ledger_sequence": 42,
|
"ledger_sequence": 42,
|
||||||
"task_id": "550e8400-e29b-41d4-a716-446655440001",
|
"ect_jti": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
"agent_id": "spiffe://example.com/agent/clinical",
|
"agent_id": "spiffe://example.com/agent/clinical",
|
||||||
"action": "recommend_treatment",
|
"action": "recommend_treatment",
|
||||||
"parents": [],
|
"parents": [],
|
||||||
@@ -3070,7 +3074,7 @@ examples demonstrate ECT mechanics; production deployments would
|
|||||||
include additional domain-specific requirements beyond the scope
|
include additional domain-specific requirements beyond the scope
|
||||||
of this specification.<a href="#section-10-1" class="pilcrow">¶</a></p>
|
of this specification.<a href="#section-10-1" class="pilcrow">¶</a></p>
|
||||||
<p id="section-10-2">Note: task identifiers in this section are abbreviated for
|
<p id="section-10-2">Note: task identifiers in this section are abbreviated for
|
||||||
readability. In production, all "tid" values are required to be
|
readability. In production, all "jti" values are required to be
|
||||||
UUIDs per <a href="#exec-claims" class="auto internal xref">Section 4.2.2</a>.<a href="#section-10-2" class="pilcrow">¶</a></p>
|
UUIDs per <a href="#exec-claims" class="auto internal xref">Section 4.2.2</a>.<a href="#section-10-2" class="pilcrow">¶</a></p>
|
||||||
<div id="medical-device-sdlc-workflow">
|
<div id="medical-device-sdlc-workflow">
|
||||||
<section id="section-10.1">
|
<section id="section-10.1">
|
||||||
@@ -3088,27 +3092,27 @@ software used in medical devices.<a href="#section-10.1-1" class="pilcrow">¶</a
|
|||||||
<div class="alignLeft art-text artwork" id="section-10.1-2.1">
|
<div class="alignLeft art-text artwork" id="section-10.1-2.1">
|
||||||
<pre>
|
<pre>
|
||||||
Agent A (Spec Reviewer):
|
Agent A (Spec Reviewer):
|
||||||
tid: 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
|
pol: spec_review_policy_v2 pol_decision: approved
|
||||||
|
|
||||||
Agent B (Code Generator):
|
Agent B (Code Generator):
|
||||||
tid: 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
|
pol: coding_standards_v3 pol_decision: approved
|
||||||
|
|
||||||
Agent C (Test Agent):
|
Agent C (Test Agent):
|
||||||
tid: 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
|
pol: test_coverage_policy_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent D (Build Agent):
|
Agent D (Build Agent):
|
||||||
tid: 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
|
pol: build_validation_v2 pol_decision: approved
|
||||||
|
|
||||||
Human Release Manager:
|
Human Release Manager:
|
||||||
tid: 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
|
pol: release_approval_policy pol_decision: approved
|
||||||
pol_enforcer: spiffe://meddev.example/human/release-mgr-42
|
pol_enforcer: spiffe://meddev.example/human/release-mgr-42
|
||||||
@@ -3213,17 +3217,17 @@ execution.<a href="#section-10.2-1" class="pilcrow">¶</a></p>
|
|||||||
<div class="alignLeft art-text artwork" id="section-10.2-2.1">
|
<div class="alignLeft art-text artwork" id="section-10.2-2.1">
|
||||||
<pre>
|
<pre>
|
||||||
Agent A (Risk Assessment):
|
Agent A (Risk Assessment):
|
||||||
tid: 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
|
pol: risk_limits_policy_v2 pol_decision: approved
|
||||||
|
|
||||||
Agent B (Compliance):
|
Agent B (Compliance):
|
||||||
tid: 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
|
pol: compliance_check_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent C (Execution):
|
Agent C (Execution):
|
||||||
tid: 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
|
pol: execution_policy_v3 pol_decision: approved
|
||||||
</pre>
|
</pre>
|
||||||
@@ -3266,9 +3270,8 @@ a cryptographic link to the original task:<a href="#section-10.3-1" class="pilcr
|
|||||||
"aud": "spiffe://bank.example/system/ledger",
|
"aud": "spiffe://bank.example/system/ledger",
|
||||||
"iat": 1772150550,
|
"iat": 1772150550,
|
||||||
"exp": 1772151150,
|
"exp": 1772151150,
|
||||||
"jti": "e4f5a6b7-c8d9-0123-ef01-234567890abc",
|
"jti": "550e8400-e29b-41d4-a716-446655440099",
|
||||||
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440099",
|
|
||||||
"exec_act": "initiate_trade_rollback",
|
"exec_act": "initiate_trade_rollback",
|
||||||
"par": ["550e8400-e29b-41d4-a716-446655440003"],
|
"par": ["550e8400-e29b-41d4-a716-446655440003"],
|
||||||
"pol": "compensation_policy_v1",
|
"pol": "compensation_policy_v1",
|
||||||
@@ -3301,27 +3304,27 @@ required checks were completed:<a href="#section-10.4-1" class="pilcrow">¶</a><
|
|||||||
<div class="alignLeft art-text artwork" id="section-10.4-2.1">
|
<div class="alignLeft art-text artwork" id="section-10.4-2.1">
|
||||||
<pre>
|
<pre>
|
||||||
Agent A (Route Planning):
|
Agent A (Route Planning):
|
||||||
tid: task-001 par: []
|
jti: task-001 par: []
|
||||||
exec_act: plan_route
|
exec_act: plan_route
|
||||||
pol: route_policy_v1 pol_decision: approved
|
pol: route_policy_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent B (Customs):
|
Agent B (Customs):
|
||||||
tid: 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
|
pol: customs_policy_v2 pol_decision: approved
|
||||||
|
|
||||||
Agent C (Safety):
|
Agent C (Safety):
|
||||||
tid: 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
|
pol: safety_policy_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent D (Payment):
|
Agent D (Payment):
|
||||||
tid: 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
|
pol: payment_policy_v3 pol_decision: approved
|
||||||
|
|
||||||
System (Commitment):
|
System (Commitment):
|
||||||
tid: 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
|
pol: commitment_policy_v1 pol_decision: approved
|
||||||
</pre>
|
</pre>
|
||||||
@@ -3422,7 +3425,7 @@ attestation ECT:<a href="#section-11.2.1-1" class="pilcrow">¶</a></p>
|
|||||||
specific equivalent).<a href="#section-11.2.1-2.2.1" class="pilcrow">¶</a></p>
|
specific equivalent).<a href="#section-11.2.1-2.2.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li class="normal" id="section-11.2.1-2.3">
|
<li class="normal" id="section-11.2.1-2.3">
|
||||||
<p id="section-11.2.1-2.3.1"><span class="bcp14">MUST</span> include the observed task's "tid" in the "par" array,
|
<p id="section-11.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-11.2.1-2.3.1" class="pilcrow">¶</a></p>
|
linking the attestation to the original task.<a href="#section-11.2.1-2.3.1" class="pilcrow">¶</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li class="normal" id="section-11.2.1-2.4">
|
<li class="normal" id="section-11.2.1-2.4">
|
||||||
@@ -3892,14 +3895,6 @@ the "JSON Web Token Claims" registry maintained by IANA:<a href="#section-13.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">tid</td>
|
|
||||||
<td class="text-left" rowspan="1" colspan="1">Task Identifier</td>
|
|
||||||
<td class="text-center" rowspan="1" colspan="1">IETF</td>
|
|
||||||
<td class="text-center" rowspan="1" colspan="1">
|
|
||||||
<a href="#exec-claims" class="auto internal xref">Section 4.2.2</a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -4438,8 +4433,8 @@ 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", "tid", "exec_act", "par", "pol",
|
"exp", "jti", "exec_act", "par") and policy claims ("pol",
|
||||||
"pol_decision").<a href="#appendix-B.1-2.1.1" class="pilcrow">¶</a></p>
|
"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
|
||||||
@@ -4612,9 +4607,8 @@ Agent B:<a href="#appendix-D.1-1" class="pilcrow">¶</a></p>
|
|||||||
"aud": "spiffe://example.com/agent/validator",
|
"aud": "spiffe://example.com/agent/validator",
|
||||||
"iat": 1772064150,
|
"iat": 1772064150,
|
||||||
"exp": 1772064750,
|
"exp": 1772064750,
|
||||||
"jti": "1a2b3c4d-e5f6-7890-abcd-ef0123456701",
|
"jti": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"exec_act": "fetch_patient_data",
|
"exec_act": "fetch_patient_data",
|
||||||
"par": [],
|
"par": [],
|
||||||
"pol": "clinical_data_access_policy_v1",
|
"pol": "clinical_data_access_policy_v1",
|
||||||
@@ -4636,9 +4630,8 @@ task, and creates its own ECT:<a href="#appendix-D.1-6" class="pilcrow">¶</a></
|
|||||||
"aud": "spiffe://example.com/system/ledger",
|
"aud": "spiffe://example.com/system/ledger",
|
||||||
"iat": 1772064160,
|
"iat": 1772064160,
|
||||||
"exp": 1772064760,
|
"exp": 1772064760,
|
||||||
"jti": "2b3c4d5e-f6a7-8901-bcde-f01234567802",
|
"jti": "550e8400-e29b-41d4-a716-446655440002",
|
||||||
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440002",
|
|
||||||
"exec_act": "validate_safety",
|
"exec_act": "validate_safety",
|
||||||
"par": ["550e8400-e29b-41d4-a716-446655440001"],
|
"par": ["550e8400-e29b-41d4-a716-446655440001"],
|
||||||
"pol": "safety_validation_policy_v2",
|
"pol": "safety_validation_policy_v2",
|
||||||
@@ -4675,9 +4668,8 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
|||||||
"aud": "spiffe://meddev.example/agent/code-gen",
|
"aud": "spiffe://meddev.example/agent/code-gen",
|
||||||
"iat": 1772064150,
|
"iat": 1772064150,
|
||||||
"exp": 1772064750,
|
"exp": 1772064750,
|
||||||
"jti": "3c4d5e6f-a7b8-9012-cdef-012345678903",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000001",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000001",
|
|
||||||
"exec_act": "review_requirements_spec",
|
"exec_act": "review_requirements_spec",
|
||||||
"par": [],
|
"par": [],
|
||||||
"pol": "spec_review_policy_v2",
|
"pol": "spec_review_policy_v2",
|
||||||
@@ -4698,9 +4690,8 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
|||||||
"aud": "spiffe://meddev.example/agent/test-runner",
|
"aud": "spiffe://meddev.example/agent/test-runner",
|
||||||
"iat": 1772064200,
|
"iat": 1772064200,
|
||||||
"exp": 1772064800,
|
"exp": 1772064800,
|
||||||
"jti": "4d5e6f7a-b8c9-0123-def0-123456789004",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000002",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000002",
|
|
||||||
"exec_act": "implement_module",
|
"exec_act": "implement_module",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000001"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000001"],
|
||||||
"pol": "coding_standards_v3",
|
"pol": "coding_standards_v3",
|
||||||
@@ -4719,9 +4710,8 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
|||||||
"aud": "spiffe://meddev.example/agent/build",
|
"aud": "spiffe://meddev.example/agent/build",
|
||||||
"iat": 1772064260,
|
"iat": 1772064260,
|
||||||
"exp": 1772064860,
|
"exp": 1772064860,
|
||||||
"jti": "5e6f7a8b-c9d0-1234-ef01-234567890005",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000003",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000003",
|
|
||||||
"exec_act": "execute_test_suite",
|
"exec_act": "execute_test_suite",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000002"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000002"],
|
||||||
"pol": "test_coverage_policy_v1",
|
"pol": "test_coverage_policy_v1",
|
||||||
@@ -4740,9 +4730,8 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
|||||||
"aud": "spiffe://meddev.example/human/release-mgr-42",
|
"aud": "spiffe://meddev.example/human/release-mgr-42",
|
||||||
"iat": 1772064310,
|
"iat": 1772064310,
|
||||||
"exp": 1772064910,
|
"exp": 1772064910,
|
||||||
"jti": "6f7a8b9c-d0e1-2345-f012-345678900006",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000004",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000004",
|
|
||||||
"exec_act": "build_release_artifact",
|
"exec_act": "build_release_artifact",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000003"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000003"],
|
||||||
"pol": "build_validation_v2",
|
"pol": "build_validation_v2",
|
||||||
@@ -4761,9 +4750,8 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
|||||||
"aud": "spiffe://meddev.example/system/ledger",
|
"aud": "spiffe://meddev.example/system/ledger",
|
||||||
"iat": 1772064510,
|
"iat": 1772064510,
|
||||||
"exp": 1772065110,
|
"exp": 1772065110,
|
||||||
"jti": "7a8b9c0d-e1f2-3456-0123-456789000007",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000005",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000005",
|
|
||||||
"exec_act": "approve_release",
|
"exec_act": "approve_release",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000004"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000004"],
|
||||||
"pol": "release_approval_policy",
|
"pol": "release_approval_policy",
|
||||||
@@ -4833,9 +4821,8 @@ task-...-0004 (execute_trade)
|
|||||||
"aud": "spiffe://bank.example/system/ledger",
|
"aud": "spiffe://bank.example/system/ledger",
|
||||||
"iat": 1772064250,
|
"iat": 1772064250,
|
||||||
"exp": 1772064850,
|
"exp": 1772064850,
|
||||||
"jti": "8b9c0d1e-f2a3-4567-1234-567890000008",
|
"jti": "f1e2d3c4-0004-0000-0000-000000000004",
|
||||||
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
||||||
"tid": "f1e2d3c4-0004-0000-0000-000000000004",
|
|
||||||
"exec_act": "execute_trade",
|
"exec_act": "execute_trade",
|
||||||
"par": [
|
"par": [
|
||||||
"f1e2d3c4-0002-0000-0000-000000000002",
|
"f1e2d3c4-0002-0000-0000-000000000002",
|
||||||
|
|||||||
@@ -462,11 +462,15 @@ because ECTs record completed actions and are valid immediately
|
|||||||
upon issuance.
|
upon issuance.
|
||||||
|
|
||||||
jti:
|
jti:
|
||||||
: REQUIRED. String. A unique identifier for the ECT in UUID
|
: REQUIRED. String. A globally unique identifier for both the
|
||||||
format {{RFC9562}}. Used for replay detection: receivers MUST
|
ECT and the task it records, in UUID format {{RFC9562}}. Since
|
||||||
reject ECTs whose "jti" has already been seen within the
|
each ECT represents exactly one task, "jti" serves as both the
|
||||||
expiration window. The "jti" value MUST be unique across all
|
token identifier (for replay detection) and the task identifier
|
||||||
ECTs issued by the same agent.
|
(for DAG parent references in "par"). Receivers MUST reject
|
||||||
|
ECTs whose "jti" has already been seen within the expiration
|
||||||
|
window. When "wid" is present, uniqueness is scoped to the
|
||||||
|
workflow; when "wid" is absent, uniqueness MUST be enforced
|
||||||
|
globally across the ECT store.
|
||||||
|
|
||||||
### Execution Context {#exec-claims}
|
### Execution Context {#exec-claims}
|
||||||
|
|
||||||
@@ -475,15 +479,7 @@ The following claims are defined by this specification:
|
|||||||
wid:
|
wid:
|
||||||
: OPTIONAL. String. A workflow identifier that groups related
|
: OPTIONAL. String. A workflow identifier that groups related
|
||||||
ECTs into a single workflow. When present, MUST be a UUID
|
ECTs into a single workflow. When present, MUST be a UUID
|
||||||
{{RFC9562}}. When absent, the "tid" uniqueness requirement
|
{{RFC9562}}.
|
||||||
applies globally across the entire ledger.
|
|
||||||
|
|
||||||
tid:
|
|
||||||
: REQUIRED. String. A globally unique task identifier in UUID
|
|
||||||
format {{RFC9562}}. Each task MUST have a unique "tid" value.
|
|
||||||
When "wid" is present, uniqueness is scoped to the workflow;
|
|
||||||
when "wid" is absent, uniqueness MUST be enforced globally
|
|
||||||
across the ledger.
|
|
||||||
|
|
||||||
exec_act:
|
exec_act:
|
||||||
: REQUIRED. String. The action or task type identifier describing
|
: REQUIRED. String. The action or task type identifier describing
|
||||||
@@ -495,8 +491,8 @@ exec_act:
|
|||||||
|
|
||||||
par:
|
par:
|
||||||
: REQUIRED. Array of strings. Parent task identifiers
|
: REQUIRED. Array of strings. Parent task identifiers
|
||||||
representing DAG dependencies. Each element MUST be a valid
|
representing DAG dependencies. Each element MUST be the "jti"
|
||||||
"tid" from a previously executed task. An empty array indicates
|
value of a previously verified ECT. An empty array indicates
|
||||||
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.
|
||||||
|
|
||||||
@@ -505,26 +501,27 @@ par:
|
|||||||
The following claims record policy evaluation outcomes:
|
The following claims record policy evaluation outcomes:
|
||||||
|
|
||||||
pol:
|
pol:
|
||||||
: REQUIRED. String. The identifier of the policy rule that was
|
: OPTIONAL. String. The identifier of the policy rule that was
|
||||||
evaluated for this task (e.g.,
|
evaluated for this task (e.g.,
|
||||||
"clinical_data_access_policy_v1").
|
"clinical_data_access_policy_v1"). MUST be present when
|
||||||
|
"pol_decision" is present.
|
||||||
|
|
||||||
pol_decision:
|
pol_decision:
|
||||||
: REQUIRED. String. The result of the policy evaluation. MUST
|
: OPTIONAL. String. The result of the policy evaluation. When
|
||||||
be one of the values registered in the ECT Policy Decision
|
present, MUST be one of the values registered in the ECT Policy
|
||||||
Values registry ({{pol-decision-registry}}). Initial values
|
Decision Values registry ({{pol-decision-registry}}). MUST be
|
||||||
are:
|
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.
|
||||||
|
|
||||||
* "rejected": The policy evaluation failed. A "rejected" ECT
|
* "rejected": The policy evaluation failed. A "rejected" ECT
|
||||||
MUST still be appended to the audit ledger for accountability.
|
MUST still be recorded for accountability. An ECT with
|
||||||
An ECT with "pol_decision" of "rejected" MAY appear as a
|
"pol_decision" of "rejected" MAY appear as a parent in the
|
||||||
parent in the "par" array of a subsequent ECT, but only for
|
"par" array of a subsequent ECT, but only for compensation,
|
||||||
compensation, rollback, or remediation tasks. Agents MUST
|
rollback, or remediation tasks. Agents MUST NOT proceed
|
||||||
NOT proceed with normal workflow execution based on a parent
|
with normal workflow execution based on a parent ECT whose
|
||||||
ECT whose "pol_decision" is "rejected".
|
"pol_decision" is "rejected".
|
||||||
|
|
||||||
* "pending_human_review": The policy evaluation requires human
|
* "pending_human_review": The policy evaluation requires human
|
||||||
judgment before proceeding. Agents MUST NOT proceed with
|
judgment before proceeding. Agents MUST NOT proceed with
|
||||||
@@ -532,6 +529,11 @@ 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
|
||||||
|
execution without a policy checkpoint. Regulated deployments
|
||||||
|
SHOULD include policy claims on all ECTs to maintain complete
|
||||||
|
audit trails.
|
||||||
|
|
||||||
pol_enforcer:
|
pol_enforcer:
|
||||||
: OPTIONAL. StringOrURI. The identity of the entity (system or
|
: OPTIONAL. StringOrURI. The identity of the entity (system or
|
||||||
person) that evaluated the policy decision. When present,
|
person) that evaluated the policy decision. When present,
|
||||||
@@ -659,10 +661,9 @@ The following is a complete ECT payload example:
|
|||||||
"aud": "spiffe://example.com/agent/safety",
|
"aud": "spiffe://example.com/agent/safety",
|
||||||
"iat": 1772064150,
|
"iat": 1772064150,
|
||||||
"exp": 1772064750,
|
"exp": 1772064750,
|
||||||
"jti": "7f3a8b2c-d1e4-4f56-9a0b-c3d4e5f6a7b8",
|
"jti": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
|
||||||
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"exec_act": "recommend_treatment",
|
"exec_act": "recommend_treatment",
|
||||||
"par": [],
|
"par": [],
|
||||||
|
|
||||||
@@ -744,10 +745,10 @@ parent ECTs available to the verifier.
|
|||||||
When receiving and verifying an ECT, implementations MUST perform
|
When receiving and verifying an ECT, implementations MUST perform
|
||||||
the following DAG validation steps:
|
the following DAG validation steps:
|
||||||
|
|
||||||
1. Task ID Uniqueness: The "tid" claim MUST be unique within the
|
1. Task ID Uniqueness: The "jti" claim MUST be unique within the
|
||||||
applicable scope (the workflow identified by "wid", or the
|
applicable scope (the workflow identified by "wid", or the
|
||||||
entire ECT store if "wid" is absent). If a task with the same
|
entire ECT store if "wid" is absent). If an ECT with the same
|
||||||
"tid" already exists, the ECT MUST be rejected.
|
"jti" already exists, the ECT MUST be rejected.
|
||||||
|
|
||||||
2. Parent Existence: Every task identifier listed in the "par"
|
2. Parent Existence: Every task identifier listed in the "par"
|
||||||
array MUST correspond to a task that is available in the ECT
|
array MUST correspond to a task that is available in the ECT
|
||||||
@@ -767,16 +768,18 @@ the following DAG validation steps:
|
|||||||
ECT MUST be rejected.
|
ECT MUST be rejected.
|
||||||
|
|
||||||
4. Acyclicity: Following the chain of parent references MUST NOT
|
4. Acyclicity: Following the chain of parent references MUST NOT
|
||||||
lead back to the current task's "tid". If a cycle is detected,
|
lead back to the current 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 task has a "pol_decision"
|
5. Parent Policy Decision: If any parent ECT contains a
|
||||||
of "rejected" or "pending_human_review", the current task's
|
"pol_decision" of "rejected" or "pending_human_review", the
|
||||||
"exec_act" MUST indicate a compensation, rollback, remediation,
|
current ECT's "exec_act" MUST indicate a compensation,
|
||||||
or human review action. Implementations MUST NOT accept an ECT
|
rollback, remediation, or human review action.
|
||||||
representing normal workflow continuation when a parent's
|
Implementations MUST NOT accept an ECT representing normal
|
||||||
"pol_decision" is not "approved", unless the current ECT has
|
workflow continuation when a parent's "pol_decision" is not
|
||||||
"compensation_required" set to true.
|
"approved", unless the current ECT has "compensation_required"
|
||||||
|
set to true. This rule only applies when the parent ECT
|
||||||
|
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
|
||||||
@@ -790,8 +793,8 @@ The following pseudocode describes the DAG validation procedure:
|
|||||||
function validate_dag(ect, ect_store, clock_skew_tolerance):
|
function validate_dag(ect, ect_store, clock_skew_tolerance):
|
||||||
// ect_store: ledger or local cache of verified ECTs
|
// ect_store: ledger or local cache of verified ECTs
|
||||||
// Step 1: Uniqueness check
|
// Step 1: Uniqueness check
|
||||||
if ect_store.contains(ect.tid, ect.wid):
|
if ect_store.contains(ect.jti, ect.wid):
|
||||||
return error("Task ID already exists")
|
return error("ECT ID already exists")
|
||||||
|
|
||||||
// Step 2: Parent existence and temporal ordering
|
// Step 2: Parent existence and temporal ordering
|
||||||
for parent_id in ect.par:
|
for parent_id in ect.par:
|
||||||
@@ -803,26 +806,26 @@ function validate_dag(ect, ect_store, clock_skew_tolerance):
|
|||||||
|
|
||||||
// Step 3: Cycle detection (with traversal limit)
|
// Step 3: Cycle detection (with traversal limit)
|
||||||
visited = set()
|
visited = set()
|
||||||
result = has_cycle(ect.tid, ect.par, ect_store, visited,
|
result = has_cycle(ect.jti, ect.par, ect_store, visited,
|
||||||
max_ancestor_limit)
|
max_ancestor_limit)
|
||||||
if result is error or result is true:
|
if result is error or result is true:
|
||||||
return error("Circular dependency or depth limit exceeded")
|
return error("Circular dependency or depth limit exceeded")
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
function has_cycle(target_tid, parent_ids, ect_store,
|
function has_cycle(target_jti, parent_ids, ect_store,
|
||||||
visited, max_depth):
|
visited, max_depth):
|
||||||
if visited.size() >= max_depth:
|
if visited.size() >= max_depth:
|
||||||
return error("Maximum ancestor traversal limit exceeded")
|
return error("Maximum ancestor traversal limit exceeded")
|
||||||
for parent_id in parent_ids:
|
for parent_id in parent_ids:
|
||||||
if parent_id == target_tid:
|
if parent_id == target_jti:
|
||||||
return true
|
return true
|
||||||
if parent_id in visited:
|
if parent_id in visited:
|
||||||
continue
|
continue
|
||||||
visited.add(parent_id)
|
visited.add(parent_id)
|
||||||
parent = ect_store.get(parent_id)
|
parent = ect_store.get(parent_id)
|
||||||
if parent is not null:
|
if parent is not null:
|
||||||
result = has_cycle(target_tid, parent.par, ect_store,
|
result = has_cycle(target_jti, parent.par, ect_store,
|
||||||
visited, max_depth)
|
visited, max_depth)
|
||||||
if result is error or result is true:
|
if result is error or result is true:
|
||||||
return result
|
return result
|
||||||
@@ -889,11 +892,12 @@ verification steps in order:
|
|||||||
(RECOMMENDED: no more than 30 seconds ahead of the
|
(RECOMMENDED: no more than 30 seconds ahead of the
|
||||||
verifier's current time, to account for clock skew).
|
verifier's current time, to account for clock skew).
|
||||||
|
|
||||||
12. Verify all required claims ("jti", "tid", "exec_act", "par",
|
12. Verify all required claims ("jti", "exec_act", "par") are
|
||||||
"pol", "pol_decision") are present and well-formed.
|
present and well-formed.
|
||||||
|
|
||||||
13. Verify "pol_decision" is one of "approved", "rejected", or
|
13. If "pol" or "pol_decision" is present, verify that both are
|
||||||
"pending_human_review".
|
present and that "pol_decision" is one of "approved",
|
||||||
|
"rejected", or "pending_human_review".
|
||||||
|
|
||||||
14. Perform DAG validation per {{dag-validation}}.
|
14. Perform DAG validation per {{dag-validation}}.
|
||||||
|
|
||||||
@@ -969,15 +973,17 @@ function verify_ect(ect_jws, verifier_id,
|
|||||||
return reject("ECT issued in the future")
|
return reject("ECT issued in the future")
|
||||||
|
|
||||||
// Verify required claims
|
// Verify required claims
|
||||||
for claim in ["jti", "tid", "exec_act", "par",
|
for claim in ["jti", "exec_act", "par"]:
|
||||||
"pol", "pol_decision"]:
|
|
||||||
if claim not in payload:
|
if claim not in payload:
|
||||||
return reject("Missing required claim: " + claim)
|
return reject("Missing required claim: " + claim)
|
||||||
|
|
||||||
// Validate pol_decision value
|
// Validate policy claims (optional, but must be paired)
|
||||||
if payload.pol_decision not in
|
if "pol" in payload or "pol_decision" in payload:
|
||||||
["approved", "rejected", "pending_human_review"]:
|
if "pol" not in payload or "pol_decision" not in payload:
|
||||||
return reject("Invalid pol_decision value")
|
return reject("pol and pol_decision must both be present")
|
||||||
|
if payload.pol_decision not in
|
||||||
|
["approved", "rejected", "pending_human_review"]:
|
||||||
|
return reject("Invalid pol_decision value")
|
||||||
|
|
||||||
// Validate DAG (against ledger or inline parent ECTs)
|
// Validate DAG (against ledger or inline parent ECTs)
|
||||||
result = validate_dag(payload, ect_store,
|
result = validate_dag(payload, ect_store,
|
||||||
@@ -1023,7 +1029,7 @@ Limitations of point-to-point mode:
|
|||||||
- No persistent audit trail unless agents independently retain
|
- No persistent audit trail unless agents independently retain
|
||||||
ECTs
|
ECTs
|
||||||
- Global replay detection relies solely on "jti" caches at each
|
- Global replay detection relies solely on "jti" caches at each
|
||||||
agent; there is no centralized "tid" uniqueness check
|
agent; there is no centralized "jti" uniqueness check
|
||||||
- The parent ECT chain grows with each hop, increasing HTTP
|
- The parent ECT chain grows with each hop, increasing HTTP
|
||||||
header size
|
header size
|
||||||
- Post-hoc audit reconstruction requires collecting ECTs from
|
- Post-hoc audit reconstruction requires collecting ECTs from
|
||||||
@@ -1083,7 +1089,7 @@ An audit ledger implementation MUST provide:
|
|||||||
entries via a monotonically increasing sequence number.
|
entries via a monotonically increasing sequence number.
|
||||||
|
|
||||||
3. Lookup by task ID: The ledger MUST support efficient retrieval
|
3. Lookup by task ID: The ledger MUST support efficient retrieval
|
||||||
of ECT entries by "tid" value.
|
of ECT entries by "jti" value.
|
||||||
|
|
||||||
4. Integrity verification: The ledger SHOULD provide a mechanism
|
4. Integrity verification: The ledger SHOULD provide a mechanism
|
||||||
to verify that no entries have been tampered with (e.g.,
|
to verify that no entries have been tampered with (e.g.,
|
||||||
@@ -1099,7 +1105,7 @@ Each ledger entry is a logical record containing:
|
|||||||
~~~json
|
~~~json
|
||||||
{
|
{
|
||||||
"ledger_sequence": 42,
|
"ledger_sequence": 42,
|
||||||
"task_id": "550e8400-e29b-41d4-a716-446655440001",
|
"ect_jti": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
"agent_id": "spiffe://example.com/agent/clinical",
|
"agent_id": "spiffe://example.com/agent/clinical",
|
||||||
"action": "recommend_treatment",
|
"action": "recommend_treatment",
|
||||||
"parents": [],
|
"parents": [],
|
||||||
@@ -1129,7 +1135,7 @@ include additional domain-specific requirements beyond the scope
|
|||||||
of this specification.
|
of this specification.
|
||||||
|
|
||||||
Note: task identifiers in this section are abbreviated for
|
Note: task identifiers in this section are abbreviated for
|
||||||
readability. In production, all "tid" values are required to be
|
readability. In production, all "jti" values are required to be
|
||||||
UUIDs per {{exec-claims}}.
|
UUIDs per {{exec-claims}}.
|
||||||
|
|
||||||
## Medical Device SDLC Workflow
|
## Medical Device SDLC Workflow
|
||||||
@@ -1143,27 +1149,27 @@ software used in medical devices.
|
|||||||
|
|
||||||
~~~
|
~~~
|
||||||
Agent A (Spec Reviewer):
|
Agent A (Spec Reviewer):
|
||||||
tid: 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
|
pol: spec_review_policy_v2 pol_decision: approved
|
||||||
|
|
||||||
Agent B (Code Generator):
|
Agent B (Code Generator):
|
||||||
tid: 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
|
pol: coding_standards_v3 pol_decision: approved
|
||||||
|
|
||||||
Agent C (Test Agent):
|
Agent C (Test Agent):
|
||||||
tid: 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
|
pol: test_coverage_policy_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent D (Build Agent):
|
Agent D (Build Agent):
|
||||||
tid: 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
|
pol: build_validation_v2 pol_decision: approved
|
||||||
|
|
||||||
Human Release Manager:
|
Human Release Manager:
|
||||||
tid: 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
|
pol: release_approval_policy pol_decision: approved
|
||||||
pol_enforcer: spiffe://meddev.example/human/release-mgr-42
|
pol_enforcer: spiffe://meddev.example/human/release-mgr-42
|
||||||
@@ -1231,17 +1237,17 @@ execution.
|
|||||||
|
|
||||||
~~~
|
~~~
|
||||||
Agent A (Risk Assessment):
|
Agent A (Risk Assessment):
|
||||||
tid: 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
|
pol: risk_limits_policy_v2 pol_decision: approved
|
||||||
|
|
||||||
Agent B (Compliance):
|
Agent B (Compliance):
|
||||||
tid: 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
|
pol: compliance_check_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent C (Execution):
|
Agent C (Execution):
|
||||||
tid: 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
|
pol: execution_policy_v3 pol_decision: approved
|
||||||
~~~
|
~~~
|
||||||
@@ -1268,9 +1274,8 @@ a cryptographic link to the original task:
|
|||||||
"aud": "spiffe://bank.example/system/ledger",
|
"aud": "spiffe://bank.example/system/ledger",
|
||||||
"iat": 1772150550,
|
"iat": 1772150550,
|
||||||
"exp": 1772151150,
|
"exp": 1772151150,
|
||||||
"jti": "e4f5a6b7-c8d9-0123-ef01-234567890abc",
|
"jti": "550e8400-e29b-41d4-a716-446655440099",
|
||||||
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440099",
|
|
||||||
"exec_act": "initiate_trade_rollback",
|
"exec_act": "initiate_trade_rollback",
|
||||||
"par": ["550e8400-e29b-41d4-a716-446655440003"],
|
"par": ["550e8400-e29b-41d4-a716-446655440003"],
|
||||||
"pol": "compensation_policy_v1",
|
"pol": "compensation_policy_v1",
|
||||||
@@ -1294,27 +1299,27 @@ required checks were completed:
|
|||||||
|
|
||||||
~~~
|
~~~
|
||||||
Agent A (Route Planning):
|
Agent A (Route Planning):
|
||||||
tid: task-001 par: []
|
jti: task-001 par: []
|
||||||
exec_act: plan_route
|
exec_act: plan_route
|
||||||
pol: route_policy_v1 pol_decision: approved
|
pol: route_policy_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent B (Customs):
|
Agent B (Customs):
|
||||||
tid: 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
|
pol: customs_policy_v2 pol_decision: approved
|
||||||
|
|
||||||
Agent C (Safety):
|
Agent C (Safety):
|
||||||
tid: 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
|
pol: safety_policy_v1 pol_decision: approved
|
||||||
|
|
||||||
Agent D (Payment):
|
Agent D (Payment):
|
||||||
tid: 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
|
pol: payment_policy_v3 pol_decision: approved
|
||||||
|
|
||||||
System (Commitment):
|
System (Commitment):
|
||||||
tid: 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
|
pol: commitment_policy_v1 pol_decision: approved
|
||||||
~~~
|
~~~
|
||||||
@@ -1377,7 +1382,7 @@ attestation ECT:
|
|||||||
- MUST set "iss" to the witness's own workload identity.
|
- MUST set "iss" to the witness's own workload identity.
|
||||||
- MUST set "exec_act" to "witness_attestation" (or a domain-
|
- MUST set "exec_act" to "witness_attestation" (or a domain-
|
||||||
specific equivalent).
|
specific equivalent).
|
||||||
- MUST include the observed task's "tid" in the "par" array,
|
- MUST include the observed task's "jti" in the "par" array,
|
||||||
linking the attestation to the original task.
|
linking the attestation to the original task.
|
||||||
- MUST set "pol_decision" to "approved" to indicate the witness
|
- MUST set "pol_decision" to "approved" to indicate the witness
|
||||||
confirms the observation.
|
confirms the observation.
|
||||||
@@ -1673,7 +1678,6 @@ the "JSON Web Token Claims" registry maintained by IANA:
|
|||||||
| Claim Name | Claim Description | Change Controller | Reference |
|
| Claim Name | Claim Description | Change Controller | Reference |
|
||||||
|:---:|:---|:---:|:---:|
|
|:---:|:---|:---:|:---:|
|
||||||
| wid | Workflow Identifier | IETF | {{exec-claims}} |
|
| wid | Workflow Identifier | IETF | {{exec-claims}} |
|
||||||
| tid | Task 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 | Policy Rule Identifier | IETF | {{policy-claims}} |
|
||||||
@@ -1861,8 +1865,8 @@ 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", "tid", "exec_act", "par", "pol",
|
"exp", "jti", "exec_act", "par") and policy claims ("pol",
|
||||||
"pol_decision").
|
"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.
|
||||||
@@ -1950,9 +1954,8 @@ ECT Payload:
|
|||||||
"aud": "spiffe://example.com/agent/validator",
|
"aud": "spiffe://example.com/agent/validator",
|
||||||
"iat": 1772064150,
|
"iat": 1772064150,
|
||||||
"exp": 1772064750,
|
"exp": 1772064750,
|
||||||
"jti": "1a2b3c4d-e5f6-7890-abcd-ef0123456701",
|
"jti": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"exec_act": "fetch_patient_data",
|
"exec_act": "fetch_patient_data",
|
||||||
"par": [],
|
"par": [],
|
||||||
"pol": "clinical_data_access_policy_v1",
|
"pol": "clinical_data_access_policy_v1",
|
||||||
@@ -1974,9 +1977,8 @@ task, and creates its own ECT:
|
|||||||
"aud": "spiffe://example.com/system/ledger",
|
"aud": "spiffe://example.com/system/ledger",
|
||||||
"iat": 1772064160,
|
"iat": 1772064160,
|
||||||
"exp": 1772064760,
|
"exp": 1772064760,
|
||||||
"jti": "2b3c4d5e-f6a7-8901-bcde-f01234567802",
|
"jti": "550e8400-e29b-41d4-a716-446655440002",
|
||||||
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
"wid": "b1c2d3e4-f5a6-7890-bcde-f01234567890",
|
||||||
"tid": "550e8400-e29b-41d4-a716-446655440002",
|
|
||||||
"exec_act": "validate_safety",
|
"exec_act": "validate_safety",
|
||||||
"par": ["550e8400-e29b-41d4-a716-446655440001"],
|
"par": ["550e8400-e29b-41d4-a716-446655440001"],
|
||||||
"pol": "safety_validation_policy_v2",
|
"pol": "safety_validation_policy_v2",
|
||||||
@@ -2010,9 +2012,8 @@ Task 1 (Spec Review Agent):
|
|||||||
"aud": "spiffe://meddev.example/agent/code-gen",
|
"aud": "spiffe://meddev.example/agent/code-gen",
|
||||||
"iat": 1772064150,
|
"iat": 1772064150,
|
||||||
"exp": 1772064750,
|
"exp": 1772064750,
|
||||||
"jti": "3c4d5e6f-a7b8-9012-cdef-012345678903",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000001",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000001",
|
|
||||||
"exec_act": "review_requirements_spec",
|
"exec_act": "review_requirements_spec",
|
||||||
"par": [],
|
"par": [],
|
||||||
"pol": "spec_review_policy_v2",
|
"pol": "spec_review_policy_v2",
|
||||||
@@ -2033,9 +2034,8 @@ Task 2 (Code Generation Agent):
|
|||||||
"aud": "spiffe://meddev.example/agent/test-runner",
|
"aud": "spiffe://meddev.example/agent/test-runner",
|
||||||
"iat": 1772064200,
|
"iat": 1772064200,
|
||||||
"exp": 1772064800,
|
"exp": 1772064800,
|
||||||
"jti": "4d5e6f7a-b8c9-0123-def0-123456789004",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000002",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000002",
|
|
||||||
"exec_act": "implement_module",
|
"exec_act": "implement_module",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000001"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000001"],
|
||||||
"pol": "coding_standards_v3",
|
"pol": "coding_standards_v3",
|
||||||
@@ -2054,9 +2054,8 @@ Task 3 (Autonomous Test Agent):
|
|||||||
"aud": "spiffe://meddev.example/agent/build",
|
"aud": "spiffe://meddev.example/agent/build",
|
||||||
"iat": 1772064260,
|
"iat": 1772064260,
|
||||||
"exp": 1772064860,
|
"exp": 1772064860,
|
||||||
"jti": "5e6f7a8b-c9d0-1234-ef01-234567890005",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000003",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000003",
|
|
||||||
"exec_act": "execute_test_suite",
|
"exec_act": "execute_test_suite",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000002"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000002"],
|
||||||
"pol": "test_coverage_policy_v1",
|
"pol": "test_coverage_policy_v1",
|
||||||
@@ -2075,9 +2074,8 @@ Task 4 (Build Agent):
|
|||||||
"aud": "spiffe://meddev.example/human/release-mgr-42",
|
"aud": "spiffe://meddev.example/human/release-mgr-42",
|
||||||
"iat": 1772064310,
|
"iat": 1772064310,
|
||||||
"exp": 1772064910,
|
"exp": 1772064910,
|
||||||
"jti": "6f7a8b9c-d0e1-2345-f012-345678900006",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000004",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000004",
|
|
||||||
"exec_act": "build_release_artifact",
|
"exec_act": "build_release_artifact",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000003"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000003"],
|
||||||
"pol": "build_validation_v2",
|
"pol": "build_validation_v2",
|
||||||
@@ -2096,9 +2094,8 @@ Task 5 (Human Release Manager Approval):
|
|||||||
"aud": "spiffe://meddev.example/system/ledger",
|
"aud": "spiffe://meddev.example/system/ledger",
|
||||||
"iat": 1772064510,
|
"iat": 1772064510,
|
||||||
"exp": 1772065110,
|
"exp": 1772065110,
|
||||||
"jti": "7a8b9c0d-e1f2-3456-0123-456789000007",
|
"jti": "a1b2c3d4-0001-0000-0000-000000000005",
|
||||||
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
"wid": "c2d3e4f5-a6b7-8901-cdef-012345678901",
|
||||||
"tid": "a1b2c3d4-0001-0000-0000-000000000005",
|
|
||||||
"exec_act": "approve_release",
|
"exec_act": "approve_release",
|
||||||
"par": ["a1b2c3d4-0001-0000-0000-000000000004"],
|
"par": ["a1b2c3d4-0001-0000-0000-000000000004"],
|
||||||
"pol": "release_approval_policy",
|
"pol": "release_approval_policy",
|
||||||
@@ -2165,9 +2162,8 @@ Task 004 ECT payload:
|
|||||||
"aud": "spiffe://bank.example/system/ledger",
|
"aud": "spiffe://bank.example/system/ledger",
|
||||||
"iat": 1772064250,
|
"iat": 1772064250,
|
||||||
"exp": 1772064850,
|
"exp": 1772064850,
|
||||||
"jti": "8b9c0d1e-f2a3-4567-1234-567890000008",
|
"jti": "f1e2d3c4-0004-0000-0000-000000000004",
|
||||||
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
"wid": "d3e4f5a6-b7c8-9012-def0-123456789012",
|
||||||
"tid": "f1e2d3c4-0004-0000-0000-000000000004",
|
|
||||||
"exec_act": "execute_trade",
|
"exec_act": "execute_trade",
|
||||||
"par": [
|
"par": [
|
||||||
"f1e2d3c4-0002-0000-0000-000000000002",
|
"f1e2d3c4-0002-0000-0000-000000000002",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user