Remove non-protocol claims and make ledger optional
Move 6 metadata claims (pol_timestamp, inp_classification, exec_time_ms, regulated_domain, model_version, witnessed_by) from registered JWT claims to recommended ext extension keys. Use short key names for spec-defined extensions. Make audit ledger explicitly optional: rename pseudocode parameter from ledger to ect_store, mark architecture diagram ledger layer as optional, add conditional append logic, and soften Audit Ledger Interface language. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1906,8 +1906,8 @@ between the identity layer and the application layer:<a href="#section-3.2-1" cl
|
||||
|
|
||||
v
|
||||
+--------------------------------------------------+
|
||||
| Ledger Layer (Immutable Record) |
|
||||
| "All ECTs appended to audit ledger" |
|
||||
| Optional: Audit Ledger (Immutable Record) |
|
||||
| "ECTs MAY be appended to an audit ledger" |
|
||||
+--------------------------------------------------+
|
||||
</pre>
|
||||
</div>
|
||||
@@ -1978,7 +1978,8 @@ trust domain. WPT verification, if present, per
|
||||
evaluated, and what precedent tasks exist.<a href="#section-3.3-7.2.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
<li id="section-3.3-7.3">
|
||||
<p id="section-3.3-7.3.1">Ledger: Appends the verified ECT to the audit ledger.<a href="#section-3.3-7.3.1" class="pilcrow">¶</a></p>
|
||||
<p id="section-3.3-7.3.1">Ledger (if deployed): Appends the verified ECT to the audit
|
||||
ledger.<a href="#section-3.3-7.3.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
@@ -2329,42 +2330,41 @@ that do not understand extension claims <span class="bcp14">MUST</span> ignore t
|
||||
<dd class="break"></dd>
|
||||
</dl>
|
||||
<p id="section-4.2.6-2">To avoid key collisions between different domains, extension
|
||||
key names <span class="bcp14">MUST</span> use reverse domain notation (e.g.,
|
||||
"com.example.custom_field"). Implementations <span class="bcp14">MUST NOT</span> use
|
||||
unqualified key names within the "ext" object. To prevent
|
||||
abuse and excessive token size, the serialized JSON
|
||||
representation of the "ext" object <span class="bcp14">SHOULD NOT</span> exceed 4096
|
||||
bytes, and the JSON nesting depth within the "ext" object
|
||||
<span class="bcp14">SHOULD NOT</span> exceed 5 levels. Implementations <span class="bcp14">SHOULD</span> reject
|
||||
ECTs whose "ext" claim 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 <span class="bcp14">RECOMMENDED</span> for common use
|
||||
cases. These are not registered claims; they are carried
|
||||
within the "ext" object:<a href="#section-4.2.6-3" class="pilcrow">¶</a></p>
|
||||
key names <span class="bcp14">SHOULD</span> use reverse domain notation (e.g.,
|
||||
"com.example.custom_field") to avoid collisions between
|
||||
independently developed extensions. To prevent abuse and
|
||||
excessive token size, the serialized JSON representation of
|
||||
the "ext" object <span class="bcp14">SHOULD NOT</span> exceed 4096 bytes, and the JSON
|
||||
nesting depth within the "ext" object <span class="bcp14">SHOULD NOT</span> exceed 5
|
||||
levels. Implementations <span class="bcp14">SHOULD</span> reject ECTs whose "ext" claim
|
||||
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
|
||||
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>
|
||||
<ul class="normal">
|
||||
<li class="normal" id="section-4.2.6-4.1">
|
||||
<p id="section-4.2.6-4.1.1">"org.ietf.wimse.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-4.1.1">"exec_time_ms": Integer. Execution duration in milliseconds.<a href="#section-4.2.6-4.1.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
<li class="normal" id="section-4.2.6-4.2">
|
||||
<p id="section-4.2.6-4.2.1">"org.ietf.wimse.regulated_domain": String. Regulatory domain
|
||||
(e.g., "medtech", "finance", "military").<a href="#section-4.2.6-4.2.1" class="pilcrow">¶</a></p>
|
||||
<p id="section-4.2.6-4.2.1">"regulated_domain": String. Regulatory domain (e.g.,
|
||||
"medtech", "finance", "military").<a href="#section-4.2.6-4.2.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
<li class="normal" id="section-4.2.6-4.3">
|
||||
<p id="section-4.2.6-4.3.1">"org.ietf.wimse.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-4.3.1">"model_version": String. AI/ML model version.<a href="#section-4.2.6-4.3.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
<li class="normal" id="section-4.2.6-4.4">
|
||||
<p id="section-4.2.6-4.4.1">"org.ietf.wimse.witnessed_by": Array of StringOrURI. Identifiers
|
||||
of third-party entities that the issuer claims observed the
|
||||
<p id="section-4.2.6-4.4.1">"witnessed_by": Array of StringOrURI. Identifiers of
|
||||
third-party entities that the issuer claims observed the
|
||||
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>
|
||||
</li>
|
||||
<li class="normal" id="section-4.2.6-4.5">
|
||||
<p id="section-4.2.6-4.5.1">"org.ietf.wimse.inp_classification": String. Data sensitivity
|
||||
classification (e.g., "public", "confidential", "restricted").<a href="#section-4.2.6-4.5.1" class="pilcrow">¶</a></p>
|
||||
<p id="section-4.2.6-4.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>
|
||||
</li>
|
||||
<li class="normal" id="section-4.2.6-4.6">
|
||||
<p id="section-4.2.6-4.6.1">"org.ietf.wimse.pol_timestamp": NumericDate. Time at which the
|
||||
policy decision was made, if distinct from "iat".<a href="#section-4.2.6-4.6.1" class="pilcrow">¶</a></p>
|
||||
<p id="section-4.2.6-4.6.1">"pol_timestamp": NumericDate. Time at which the policy
|
||||
decision was made, if distinct from "iat".<a href="#section-4.2.6-4.6.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -2401,10 +2401,10 @@ policy decision was made, if distinct from "iat".<a href="#section-4.2.6-4.6.1"
|
||||
"out_hash": "sha-256:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
|
||||
|
||||
"ext": {
|
||||
"org.ietf.wimse.pol_timestamp": 1772064145,
|
||||
"org.ietf.wimse.exec_time_ms": 245,
|
||||
"org.ietf.wimse.regulated_domain": "medtech",
|
||||
"org.ietf.wimse.model_version": "clinical-reasoning-v4.2"
|
||||
"pol_timestamp": 1772064145,
|
||||
"exec_time_ms": 245,
|
||||
"regulated_domain": "medtech",
|
||||
"model_version": "clinical-reasoning-v4.2"
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
@@ -2479,8 +2479,8 @@ provides a cryptographically signed record of execution ordering,
|
||||
enabling auditors to reconstruct the complete workflow and verify
|
||||
that required predecessor tasks were recorded before dependent
|
||||
tasks.<a href="#section-6.1-1" class="pilcrow">¶</a></p>
|
||||
<p id="section-6.1-2">DAG validation is performed against the audit ledger, which
|
||||
serves as the authoritative store of previously verified ECTs.<a href="#section-6.1-2" class="pilcrow">¶</a></p>
|
||||
<p id="section-6.1-2">DAG validation is performed against the ECT store — either an
|
||||
audit ledger or the set of parent ECTs received inline.<a href="#section-6.1-2" class="pilcrow">¶</a></p>
|
||||
</section>
|
||||
</div>
|
||||
<div id="validation-rules">
|
||||
@@ -2549,14 +2549,14 @@ relationship has been established.<a href="#section-6.2-2.6.1" class="pilcrow">
|
||||
<figure id="figure-6">
|
||||
<div class="lang-pseudocode sourcecode" id="section-6.3-2.1">
|
||||
<pre>
|
||||
function validate_dag(ect, ledger, clock_skew_tolerance):
|
||||
function validate_dag(ect, ect_store, clock_skew_tolerance):
|
||||
// Step 1: Uniqueness check
|
||||
if ledger.contains(ect.jti, ect.wid):
|
||||
if ect_store.contains(ect.jti, ect.wid):
|
||||
return error("ECT ID already exists")
|
||||
|
||||
// Step 2: Parent existence and temporal ordering
|
||||
for parent_id in ect.par:
|
||||
parent = ledger.get(parent_id)
|
||||
parent = ect_store.get(parent_id)
|
||||
if parent is null:
|
||||
return error("Parent task not found: " + parent_id)
|
||||
if parent.iat >= ect.iat + clock_skew_tolerance:
|
||||
@@ -2564,14 +2564,14 @@ function validate_dag(ect, ledger, clock_skew_tolerance):
|
||||
|
||||
// Step 3: Cycle detection (with traversal limit)
|
||||
visited = set()
|
||||
result = has_cycle(ect.jti, ect.par, ledger, visited,
|
||||
result = has_cycle(ect.jti, ect.par, ect_store, visited,
|
||||
max_ancestor_limit)
|
||||
if result is error or result is true:
|
||||
return error("Circular dependency or depth limit exceeded")
|
||||
|
||||
return success
|
||||
|
||||
function has_cycle(target_jti, parent_ids, ledger,
|
||||
function has_cycle(target_jti, parent_ids, ect_store,
|
||||
visited, max_depth):
|
||||
if visited.size() >= max_depth:
|
||||
return error("Maximum ancestor traversal limit exceeded")
|
||||
@@ -2581,9 +2581,9 @@ function has_cycle(target_jti, parent_ids, ledger,
|
||||
if parent_id in visited:
|
||||
continue
|
||||
visited.add(parent_id)
|
||||
parent = ledger.get(parent_id)
|
||||
parent = ect_store.get(parent_id)
|
||||
if parent is not null:
|
||||
result = has_cycle(target_jti, parent.par, ledger,
|
||||
result = has_cycle(target_jti, parent.par, ect_store,
|
||||
visited, max_depth)
|
||||
if result is error or result is true:
|
||||
return result
|
||||
@@ -2714,7 +2714,7 @@ fails.<a href="#section-7.1-4" class="pilcrow">¶</a></p>
|
||||
<div class="breakable lang-pseudocode sourcecode" id="section-7.2-1.1">
|
||||
<pre>
|
||||
function verify_ect(ect_jws, verifier_id,
|
||||
trust_domain_keys, ledger):
|
||||
trust_domain_keys, ect_store):
|
||||
// Parse JWS
|
||||
(header, payload, signature) = parse_jws(ect_jws)
|
||||
|
||||
@@ -2775,14 +2775,15 @@ function verify_ect(ect_jws, verifier_id,
|
||||
["approved", "rejected", "pending_human_review"]:
|
||||
return reject("Invalid pol_decision value")
|
||||
|
||||
// Validate DAG (against ledger or inline parent ECTs)
|
||||
result = validate_dag(payload, ledger,
|
||||
// Validate DAG (against ECT store or inline parent ECTs)
|
||||
result = validate_dag(payload, ect_store,
|
||||
clock_skew_tolerance)
|
||||
if result is error:
|
||||
return reject("DAG validation failed")
|
||||
|
||||
// All checks passed; append to ledger
|
||||
ledger.append(payload)
|
||||
// All checks passed; record if store is available
|
||||
if ect_store is not null:
|
||||
ect_store.append(payload)
|
||||
return accept
|
||||
</pre>
|
||||
</div>
|
||||
@@ -2799,14 +2800,14 @@ function verify_ect(ect_jws, verifier_id,
|
||||
<h2 id="name-audit-ledger-interface">
|
||||
<a href="#section-8" class="section-number selfRef">8. </a><a href="#name-audit-ledger-interface" class="section-name selfRef">Audit Ledger Interface</a>
|
||||
</h2>
|
||||
<p id="section-8-1">ECTs are designed to be recorded in an immutable audit ledger for
|
||||
compliance verification and post-hoc analysis. This specification
|
||||
defines required properties for the ledger but does not mandate
|
||||
a specific storage technology. Implementations <span class="bcp14">MAY</span> use
|
||||
append-only logs, databases with cryptographic commitment schemes,
|
||||
distributed ledgers, or any storage mechanism that provides the
|
||||
required properties.<a href="#section-8-1" class="pilcrow">¶</a></p>
|
||||
<p id="section-8-2">An audit ledger implementation <span class="bcp14">MUST</span> provide:<a href="#section-8-2" class="pilcrow">¶</a></p>
|
||||
<p id="section-8-1">ECTs <span class="bcp14">MAY</span> be recorded in an immutable audit ledger for compliance
|
||||
verification and post-hoc analysis. A ledger is <span class="bcp14">RECOMMENDED</span> for
|
||||
regulated environments but is not required for point-to-point
|
||||
operation. This specification does not mandate a specific storage
|
||||
technology. Implementations <span class="bcp14">MAY</span> use append-only logs, databases
|
||||
with cryptographic commitment schemes, distributed ledgers, or
|
||||
any storage mechanism that provides the required properties.<a href="#section-8-1" class="pilcrow">¶</a></p>
|
||||
<p id="section-8-2">When an audit ledger is deployed, the implementation <span class="bcp14">MUST</span> provide:<a href="#section-8-2" class="pilcrow">¶</a></p>
|
||||
<ol start="1" type="1" class="normal type-1" id="section-8-3">
|
||||
<li id="section-8-3.1">
|
||||
<p id="section-8-3.1.1">Append-only semantics: Once an ECT is recorded, it <span class="bcp14">MUST NOT</span> be
|
||||
@@ -2883,7 +2884,7 @@ Human Release Manager:
|
||||
exec_act: approve_release
|
||||
pol: release_approval_policy pol_decision: approved
|
||||
pol_enforcer: spiffe://meddev.example/human/release-mgr-42
|
||||
ext: {org.ietf.wimse.witnessed_by: [...]} (extension metadata)
|
||||
ext: {witnessed_by: [...]} (extension metadata)
|
||||
</pre>
|
||||
</div>
|
||||
<figcaption><a href="#figure-8" class="selfRef">Figure 8</a>:
|
||||
@@ -3167,7 +3168,7 @@ evaluating the policy).<a href="#section-10.2-1" class="pilcrow">¶</a></p>
|
||||
</ul>
|
||||
<p id="section-10.2-4">The trustworthiness of ECT claims depends on the trustworthiness
|
||||
of the signing agent. To mitigate single-agent false claims,
|
||||
regulated environments <span class="bcp14">SHOULD</span> use the "org.ietf.wimse.witnessed_by"
|
||||
regulated environments <span class="bcp14">SHOULD</span> use the "witnessed_by"
|
||||
extension key (carried in "ext") to include independent
|
||||
third-party observers at critical decision points. However,
|
||||
this value is self-asserted by the ECT issuer: the listed
|
||||
@@ -3181,7 +3182,7 @@ did not participate.<a href="#section-10.2-4" class="pilcrow">¶</a></p>
|
||||
<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>
|
||||
</h4>
|
||||
<p id="section-10.2.1-1">To address the self-assertion limitation of the
|
||||
"org.ietf.wimse.witnessed_by" extension, witnesses <span class="bcp14">SHOULD</span> submit their
|
||||
"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">
|
||||
@@ -3201,7 +3202,7 @@ linking the attestation to the original task.<a href="#section-10.2.1-2.3.1" cla
|
||||
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 "org.ietf.wimse.witnessed_by" extension lists one or more
|
||||
<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
|
||||
@@ -3353,7 +3354,7 @@ create a false execution history if they control the ledger.<a href="#section-10
|
||||
by an entity independent of the workflow agents.<a href="#section-10.8-3.1.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
<li class="normal" id="section-10.8-3.2">
|
||||
<p id="section-10.8-3.2.1">Witness attestation: Using the "org.ietf.wimse.witnessed_by" extension
|
||||
<p id="section-10.8-3.2.1">Witness attestation: Using the "witnessed_by" extension
|
||||
key in "ext" to include independent third-party observers.<a href="#section-10.8-3.2.1" class="pilcrow">¶</a></p>
|
||||
</li>
|
||||
<li class="normal" id="section-10.8-3.3">
|
||||
@@ -4412,7 +4413,7 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
||||
"pol_decision": "approved",
|
||||
"pol_enforcer": "spiffe://meddev.example/human/release-mgr-42",
|
||||
"ext": {
|
||||
"org.ietf.wimse.witnessed_by": [
|
||||
"witnessed_by": [
|
||||
"spiffe://meddev.example/audit/qa-observer-1"
|
||||
]
|
||||
}
|
||||
@@ -4423,7 +4424,7 @@ autonomous agents and human release approval:<a href="#appendix-D.2-1" class="pi
|
||||
implementation, implementation preceded testing, testing preceded
|
||||
build, and a human release manager approved the final release.
|
||||
The "ext" object in task 5 carries witness metadata via
|
||||
the "org.ietf.wimse.witnessed_by" extension key.<a href="#appendix-D.2-12" class="pilcrow">¶</a></p>
|
||||
the "witnessed_by" extension key.<a href="#appendix-D.2-12" class="pilcrow">¶</a></p>
|
||||
<div class="alignLeft art-text artwork" id="appendix-D.2-13">
|
||||
<pre>
|
||||
task-...-0001 (review_requirements_spec)
|
||||
|
||||
Reference in New Issue
Block a user