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:
@@ -409,8 +409,8 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
|
||||
v
|
||||
+--------------------------------------------------+
|
||||
| Ledger Layer (Immutable Record) |
|
||||
| "All ECTs appended to audit ledger" |
|
||||
| Optional: Audit Ledger (Immutable Record) |
|
||||
| "ECTs MAY be appended to an audit ledger" |
|
||||
+--------------------------------------------------+
|
||||
|
||||
Figure 1: WIMSE Extension Architecture Layers
|
||||
@@ -466,7 +466,8 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
2. ECT (this extension): Records what Agent A did, what policy was
|
||||
evaluated, and what precedent tasks exist.
|
||||
|
||||
3. Ledger: Appends the verified ECT to the audit ledger.
|
||||
3. Ledger (if deployed): Appends the verified ECT to the audit
|
||||
ledger.
|
||||
|
||||
4. Execution Context Token Format
|
||||
|
||||
@@ -497,7 +498,6 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
from other JWT types, consistent with the WIMSE convention for
|
||||
type parameter values.
|
||||
|
||||
kid: REQUIRED. The key identifier referencing the public key from
|
||||
|
||||
|
||||
|
||||
@@ -506,6 +506,7 @@ Nennemann Expires 28 August 2026 [Page 9]
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
kid: REQUIRED. The key identifier referencing the public key from
|
||||
the agent's WIT [RFC7517]. Used by verifiers to look up the
|
||||
correct public key for signature verification.
|
||||
|
||||
@@ -556,7 +557,6 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
|
||||
|
||||
Nennemann Expires 28 August 2026 [Page 10]
|
||||
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
@@ -734,36 +734,35 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
not understand extension claims MUST ignore them.
|
||||
|
||||
To avoid key collisions between different domains, extension key
|
||||
names MUST use reverse domain notation (e.g.,
|
||||
"com.example.custom_field"). Implementations MUST NOT use
|
||||
unqualified key names within the "ext" object. To prevent abuse and
|
||||
excessive token size, the serialized JSON representation of the "ext"
|
||||
object SHOULD NOT exceed 4096 bytes, and the JSON nesting depth
|
||||
within the "ext" object SHOULD NOT exceed 5 levels. Implementations
|
||||
SHOULD reject ECTs whose "ext" claim exceeds these limits.
|
||||
names SHOULD 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 SHOULD NOT exceed
|
||||
4096 bytes, and the JSON nesting depth within the "ext" object SHOULD
|
||||
NOT exceed 5 levels. Implementations SHOULD reject ECTs whose "ext"
|
||||
claim exceeds these limits.
|
||||
|
||||
The following extension keys are RECOMMENDED for common use cases.
|
||||
These are not registered claims; they are carried within the "ext"
|
||||
object:
|
||||
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:
|
||||
|
||||
* "org.ietf.wimse.exec_time_ms": Integer. Execution duration in
|
||||
milliseconds.
|
||||
* "exec_time_ms": Integer. Execution duration in milliseconds.
|
||||
|
||||
* "org.ietf.wimse.regulated_domain": String. Regulatory domain
|
||||
(e.g., "medtech", "finance", "military").
|
||||
* "regulated_domain": String. Regulatory domain (e.g., "medtech",
|
||||
"finance", "military").
|
||||
|
||||
* "org.ietf.wimse.model_version": String. AI/ML model version.
|
||||
* "model_version": String. AI/ML model version.
|
||||
|
||||
* "org.ietf.wimse.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.
|
||||
* "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.
|
||||
|
||||
* "org.ietf.wimse.inp_classification": String. Data sensitivity
|
||||
classification (e.g., "public", "confidential", "restricted").
|
||||
* "inp_classification": String. Data sensitivity classification
|
||||
(e.g., "public", "confidential", "restricted").
|
||||
|
||||
* "org.ietf.wimse.pol_timestamp": NumericDate. Time at which the
|
||||
policy decision was made, if distinct from "iat".
|
||||
* "pol_timestamp": NumericDate. Time at which the policy decision
|
||||
was made, if distinct from "iat".
|
||||
|
||||
4.3. Complete ECT Example
|
||||
|
||||
@@ -781,6 +780,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
|
||||
|
||||
Nennemann Expires 28 August 2026 [Page 14]
|
||||
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
@@ -806,10 +806,10 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,8 +865,8 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
auditors to reconstruct the complete workflow and verify that
|
||||
required predecessor tasks were recorded before dependent tasks.
|
||||
|
||||
DAG validation is performed against the audit ledger, which serves as
|
||||
the authoritative store of previously verified ECTs.
|
||||
DAG validation is performed against the ECT store — either an audit
|
||||
ledger or the set of parent ECTs received inline.
|
||||
|
||||
6.2. Validation Rules
|
||||
|
||||
@@ -954,14 +954,14 @@ Nennemann Expires 28 August 2026 [Page 17]
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
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:
|
||||
@@ -969,14 +969,14 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
// 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")
|
||||
@@ -986,9 +986,9 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
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
|
||||
@@ -1100,7 +1100,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
7.2. Verification Pseudocode
|
||||
|
||||
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)
|
||||
|
||||
@@ -1169,7 +1169,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
["approved", "rejected", "pending_human_review"]:
|
||||
return reject("Invalid pol_decision value")
|
||||
|
||||
// Validate DAG (against ledger or inline parent ECTs)
|
||||
// Validate DAG (against ECT store or inline parent ECTs)
|
||||
|
||||
|
||||
|
||||
@@ -1178,28 +1178,29 @@ Nennemann Expires 28 August 2026 [Page 21]
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
result = validate_dag(payload, ledger,
|
||||
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
|
||||
|
||||
Figure 7: ECT Verification Pseudocode
|
||||
|
||||
8. Audit Ledger Interface
|
||||
|
||||
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 MAY use append-only
|
||||
logs, databases with cryptographic commitment schemes, distributed
|
||||
ledgers, or any storage mechanism that provides the required
|
||||
properties.
|
||||
ECTs MAY be recorded in an immutable audit ledger for compliance
|
||||
verification and post-hoc analysis. A ledger is RECOMMENDED for
|
||||
regulated environments but is not required for point-to-point
|
||||
operation. This specification does not mandate a specific storage
|
||||
technology. Implementations MAY use append-only logs, databases with
|
||||
cryptographic commitment schemes, distributed ledgers, or any storage
|
||||
mechanism that provides the required properties.
|
||||
|
||||
An audit ledger implementation MUST provide:
|
||||
When an audit ledger is deployed, the implementation MUST provide:
|
||||
|
||||
1. Append-only semantics: Once an ECT is recorded, it MUST NOT be
|
||||
modified or deleted.
|
||||
@@ -1228,7 +1229,6 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
|
||||
|
||||
Nennemann Expires 28 August 2026 [Page 22]
|
||||
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
@@ -1271,7 +1271,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
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)
|
||||
|
||||
Figure 8: Medical Device SDLC Workflow
|
||||
|
||||
@@ -1536,20 +1536,20 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
The trustworthiness of ECT claims depends on the trustworthiness of
|
||||
the signing agent. To mitigate single-agent false claims, regulated
|
||||
environments SHOULD use the "org.ietf.wimse.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 witnesses do not co-sign the ECT and there
|
||||
is no cryptographic evidence within a single ECT that the witnesses
|
||||
environments SHOULD 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 witnesses do not co-sign the ECT and there is no
|
||||
cryptographic evidence within a single ECT that the witnesses
|
||||
actually observed the task. An issuing agent could list witnesses
|
||||
that did not participate.
|
||||
|
||||
10.2.1. Witness Attestation Model
|
||||
|
||||
To address the self-assertion limitation of the
|
||||
"org.ietf.wimse.witnessed_by" extension, witnesses SHOULD submit
|
||||
their own independent signed ECTs to the audit ledger attesting to
|
||||
the observed task. A witness attestation ECT:
|
||||
To address the self-assertion limitation of the "witnessed_by"
|
||||
extension, witnesses SHOULD submit their own independent signed ECTs
|
||||
to the audit ledger attesting to the observed task. A witness
|
||||
attestation ECT:
|
||||
|
||||
* MUST set "iss" to the witness's own workload identity.
|
||||
|
||||
@@ -1570,11 +1570,11 @@ Nennemann Expires 28 August 2026 [Page 28]
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
When a task's "org.ietf.wimse.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.
|
||||
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
|
||||
@@ -1702,9 +1702,8 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
* Independent ledger maintenance: The ledger SHOULD be maintained by
|
||||
an entity independent of the workflow agents.
|
||||
|
||||
* Witness attestation: Using the "org.ietf.wimse.witnessed_by"
|
||||
extension key in "ext" to include independent third-party
|
||||
observers.
|
||||
* Witness attestation: Using the "witnessed_by" extension key in
|
||||
"ext" to include independent third-party observers.
|
||||
|
||||
* Cross-verification: Multiple independent ledger replicas can be
|
||||
compared for consistency.
|
||||
@@ -1733,6 +1732,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
|
||||
|
||||
|
||||
|
||||
Nennemann Expires 28 August 2026 [Page 31]
|
||||
|
||||
Internet-Draft WIMSE Execution Context February 2026
|
||||
@@ -2611,7 +2611,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
"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"
|
||||
]
|
||||
}
|
||||
@@ -2621,7 +2621,7 @@ Internet-Draft WIMSE Execution Context February 2026
|
||||
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.
|
||||
"witnessed_by" extension key.
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user