Compare commits
6 Commits
16a1973d02
...
ba044f6626
| Author | SHA1 | Date | |
|---|---|---|---|
| ba044f6626 | |||
| 8cf0d8aade | |||
| bd2a5f819a | |||
| eb79c6998a | |||
| 139a4e85e2 | |||
| 2d3af57923 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1 +1,5 @@
|
|||||||
.refcache/
|
.refcache/
|
||||||
|
# Generated build outputs (XML, TXT, HTML)
|
||||||
|
draft-nennemann-wimse-ect-*.xml
|
||||||
|
draft-nennemann-wimse-ect-*.txt
|
||||||
|
draft-nennemann-wimse-ect-*.html
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ ECTs originated as an extension to the IETF WIMSE (Workload Identity in Multi-Sy
|
|||||||
The key properties:
|
The key properties:
|
||||||
|
|
||||||
- **Per-task granularity.** One ECT per task, not one per session or per request chain.
|
- **Per-task granularity.** One ECT per task, not one per session or per request chain.
|
||||||
- **DAG ordering.** Parent references (`par` claim) create a verifiable execution graph. Fan-out, fan-in, parallel branches — all representable.
|
- **DAG ordering.** Parent references (`pred` claim) create a verifiable execution graph. Fan-out, fan-in, parallel branches — all representable.
|
||||||
- **Data integrity without data exposure.** Input and output hashes (`inp_hash`, `out_hash`) prove what was processed without revealing the data itself.
|
- **Data integrity without data exposure.** Input and output hashes (`inp_hash`, `out_hash`) prove what was processed without revealing the data itself.
|
||||||
- **Identity-framework agnostic.** ECTs work with WIMSE WIT/WPT, X.509 certificates, OAuth credentials, or plain JWK sets. The spec defines abstract identity binding requirements and concrete profiles for each framework.
|
- **Identity-framework agnostic.** ECTs work with WIMSE WIT/WPT, X.509 certificates, OAuth credentials, or plain JWK sets. The spec defines abstract identity binding requirements and concrete profiles for each framework.
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ A single deployment can use different levels for different workflows. Your inter
|
|||||||
|
|
||||||
## The Upgrade Path
|
## The Upgrade Path
|
||||||
|
|
||||||
This is arguably the most important design property of the assurance levels: **the payload is the same at every level.** The same `jti`, `iss`, `aud`, `iat`, `exp`, `exec_act`, `par`, `inp_hash`, `out_hash`, and `ext` claims appear in every ECT, whether it's unsigned JSON or a ledger-committed JWS token.
|
This is arguably the most important design property of the assurance levels: **the payload is the same at every level.** The same `jti`, `iss`, `aud`, `iat`, `exp`, `exec_act`, `pred`, `inp_hash`, `out_hash`, and `ect_ext` claims appear in every ECT, whether it's unsigned JSON or a ledger-committed JWS token.
|
||||||
|
|
||||||
What changes is the envelope and the verification procedure. This means upgrading from L1 to L2 means adding a JWS wrapper around the same payload. Upgrading from L2 to L3 means deploying an audit ledger and adding the ledger recording step after JWS verification.
|
What changes is the envelope and the verification procedure. This means upgrading from L1 to L2 means adding a JWS wrapper around the same payload. Upgrading from L2 to L3 means deploying an audit ledger and adding the ledger recording step after JWS verification.
|
||||||
|
|
||||||
|
|||||||
25
build.sh
25
build.sh
@@ -1,22 +1,39 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
DRAFT="draft-nennemann-wimse-ect-01"
|
|
||||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
SRC="$DIR/draft-nennemann-wimse-ect.md"
|
||||||
|
|
||||||
|
# Extract docname from YAML front matter
|
||||||
|
DRAFT=$(grep '^docname:' "$SRC" | head -1 | awk '{print $2}')
|
||||||
|
if [ -z "$DRAFT" ]; then
|
||||||
|
echo "Error: could not extract docname from $SRC"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Tool paths
|
# Tool paths
|
||||||
KRAMDOWN="/usr/local/lib/ruby/gems/3.4.0/bin/kramdown-rfc2629"
|
KRAMDOWN="$(which kramdown-rfc2629 2>/dev/null)"
|
||||||
XML2RFC="/Users/christian/Library/Python/3.9/bin/xml2rfc"
|
XML2RFC="$(which xml2rfc 2>/dev/null)"
|
||||||
|
|
||||||
|
if [ -z "$KRAMDOWN" ]; then
|
||||||
|
echo "Error: kramdown-rfc2629 not found. Install with: gem install kramdown-rfc2629"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -z "$XML2RFC" ]; then
|
||||||
|
echo "Error: xml2rfc not found. Install with: pip install xml2rfc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
export PYTHONWARNINGS="ignore::UserWarning"
|
export PYTHONWARNINGS="ignore::UserWarning"
|
||||||
|
|
||||||
|
echo "Building: $DRAFT"
|
||||||
echo "Using kramdown-rfc2629: $KRAMDOWN"
|
echo "Using kramdown-rfc2629: $KRAMDOWN"
|
||||||
echo "Using xml2rfc: $XML2RFC"
|
echo "Using xml2rfc: $XML2RFC"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Step 1: Markdown -> XML
|
# Step 1: Markdown -> XML
|
||||||
echo "Converting markdown to XML..."
|
echo "Converting markdown to XML..."
|
||||||
"$KRAMDOWN" "$DIR/$DRAFT.md" > "$DIR/$DRAFT.xml"
|
"$KRAMDOWN" "$SRC" > "$DIR/$DRAFT.xml"
|
||||||
|
|
||||||
# Step 2: XML -> TXT
|
# Step 2: XML -> TXT
|
||||||
echo "Generating text output..."
|
echo "Generating text output..."
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,926 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Execution Context Tokens for Distributed Agentic Workflows"
|
|
||||||
abbrev: "WIMSE Execution Context"
|
|
||||||
category: std
|
|
||||||
docname: draft-nennemann-wimse-ect-00
|
|
||||||
submissiontype: IETF
|
|
||||||
number:
|
|
||||||
date:
|
|
||||||
v: 3
|
|
||||||
area: "ART"
|
|
||||||
workgroup: "WIMSE"
|
|
||||||
keyword:
|
|
||||||
- execution context
|
|
||||||
- workload identity
|
|
||||||
- agentic workflows
|
|
||||||
- audit trail
|
|
||||||
|
|
||||||
author:
|
|
||||||
-
|
|
||||||
fullname: Christian Nennemann
|
|
||||||
organization: Independent Researcher
|
|
||||||
email: ietf@nennemann.de
|
|
||||||
|
|
||||||
normative:
|
|
||||||
RFC7515:
|
|
||||||
RFC7517:
|
|
||||||
RFC7519:
|
|
||||||
RFC7518:
|
|
||||||
RFC9562:
|
|
||||||
RFC9110:
|
|
||||||
I-D.ietf-wimse-arch:
|
|
||||||
I-D.ietf-wimse-s2s-protocol:
|
|
||||||
|
|
||||||
informative:
|
|
||||||
RFC8693:
|
|
||||||
SPIFFE:
|
|
||||||
title: "Secure Production Identity Framework for Everyone (SPIFFE)"
|
|
||||||
target: https://spiffe.io/docs/latest/spiffe-about/overview/
|
|
||||||
date: false
|
|
||||||
OPENTELEMETRY:
|
|
||||||
title: "OpenTelemetry Specification"
|
|
||||||
target: https://opentelemetry.io/docs/specs/otel/
|
|
||||||
date: false
|
|
||||||
author:
|
|
||||||
- org: Cloud Native Computing Foundation
|
|
||||||
I-D.ietf-scitt-architecture:
|
|
||||||
RFC9449:
|
|
||||||
I-D.ietf-oauth-transaction-tokens:
|
|
||||||
I-D.oauth-transaction-tokens-for-agents:
|
|
||||||
|
|
||||||
--- abstract
|
|
||||||
|
|
||||||
This document defines Execution Context Tokens (ECTs), a JWT-based
|
|
||||||
extension to the WIMSE architecture that records task execution
|
|
||||||
across distributed agentic workflows. Each ECT is a signed record
|
|
||||||
of a single task, linked to predecessor tasks through a directed
|
|
||||||
acyclic graph (DAG). ECTs reuse the WIMSE signing model and are
|
|
||||||
transported in a new Execution-Context HTTP header field alongside
|
|
||||||
existing WIMSE identity headers.
|
|
||||||
|
|
||||||
--- middle
|
|
||||||
|
|
||||||
# Introduction
|
|
||||||
|
|
||||||
The WIMSE framework {{I-D.ietf-wimse-arch}} and its service-to-
|
|
||||||
service protocol {{I-D.ietf-wimse-s2s-protocol}} authenticate
|
|
||||||
workloads across call chains but do not record what those
|
|
||||||
workloads actually did. This document defines Execution Context
|
|
||||||
Tokens (ECTs), a JWT-based extension that fills the gap between
|
|
||||||
workload identity and execution accountability. Each ECT is a
|
|
||||||
signed record of a single task, linked to predecessor tasks
|
|
||||||
through a directed acyclic graph (DAG).
|
|
||||||
|
|
||||||
## Scope and Applicability
|
|
||||||
|
|
||||||
This document defines:
|
|
||||||
|
|
||||||
- The Execution Context Token (ECT) format ({{ect-format}})
|
|
||||||
- DAG structure for task dependency ordering ({{dag-validation}})
|
|
||||||
- An HTTP header for ECT transport ({{http-header}})
|
|
||||||
- Audit ledger interface requirements ({{ledger-interface}})
|
|
||||||
|
|
||||||
The following are out of scope and are handled by WIMSE:
|
|
||||||
|
|
||||||
- Workload authentication and identity provisioning
|
|
||||||
- Key distribution and management
|
|
||||||
- Trust domain establishment and management
|
|
||||||
- Credential lifecycle management
|
|
||||||
|
|
||||||
# Conventions and Definitions
|
|
||||||
|
|
||||||
{::boilerplate bcp14-tagged}
|
|
||||||
|
|
||||||
The following terms are used in this document:
|
|
||||||
|
|
||||||
Agent:
|
|
||||||
: An autonomous workload, as defined by WIMSE
|
|
||||||
{{I-D.ietf-wimse-arch}}, that executes tasks within a workflow.
|
|
||||||
|
|
||||||
Task:
|
|
||||||
: A discrete unit of agent work that consumes inputs and produces
|
|
||||||
outputs.
|
|
||||||
|
|
||||||
Directed Acyclic Graph (DAG):
|
|
||||||
: A graph structure representing task dependency ordering where
|
|
||||||
edges are directed and no cycles exist.
|
|
||||||
|
|
||||||
Execution Context Token (ECT):
|
|
||||||
: A JSON Web Token {{RFC7519}} defined by this specification that
|
|
||||||
records task execution details.
|
|
||||||
|
|
||||||
Audit Ledger:
|
|
||||||
: An append-only, immutable log of all ECTs within a workflow or
|
|
||||||
set of workflows, used for audit and verification.
|
|
||||||
|
|
||||||
Workload Identity Token (WIT):
|
|
||||||
: A WIMSE credential proving a workload's identity within a trust
|
|
||||||
domain.
|
|
||||||
|
|
||||||
Workload Proof Token (WPT):
|
|
||||||
: A WIMSE proof-of-possession token used for request-level
|
|
||||||
authentication.
|
|
||||||
|
|
||||||
Trust Domain:
|
|
||||||
: A WIMSE concept representing an organizational boundary with a
|
|
||||||
shared identity issuer, corresponding to a SPIFFE {{SPIFFE}}
|
|
||||||
trust domain.
|
|
||||||
|
|
||||||
# Execution Context Token Format {#ect-format}
|
|
||||||
|
|
||||||
An Execution Context Token is a JSON Web Token (JWT) {{RFC7519}}
|
|
||||||
signed as a JSON Web Signature (JWS) {{RFC7515}}. ECTs MUST use
|
|
||||||
JWS Compact Serialization (the base64url-encoded
|
|
||||||
`header.payload.signature` format) so that they can be carried in
|
|
||||||
a single HTTP header value.
|
|
||||||
|
|
||||||
ECTs reuse the WIMSE signing model. The ECT MUST be signed with
|
|
||||||
the same private key associated with the agent's WIT. The JOSE
|
|
||||||
header "kid" parameter MUST reference the public key identifier
|
|
||||||
from the agent's WIT, and the "alg" parameter MUST match the
|
|
||||||
algorithm used in the corresponding WIT. In WIMSE deployments,
|
|
||||||
the ECT "iss" claim SHOULD use the WIMSE workload identifier
|
|
||||||
format (a SPIFFE ID {{SPIFFE}}).
|
|
||||||
|
|
||||||
## JOSE Header {#jose-header}
|
|
||||||
|
|
||||||
The ECT JOSE header MUST contain the following parameters:
|
|
||||||
|
|
||||||
~~~json
|
|
||||||
{
|
|
||||||
"alg": "ES256",
|
|
||||||
"typ": "wimse-exec+jwt",
|
|
||||||
"kid": "agent-a-key-id-123"
|
|
||||||
}
|
|
||||||
~~~
|
|
||||||
{: #fig-header title="ECT JOSE Header Example"}
|
|
||||||
|
|
||||||
alg:
|
|
||||||
: REQUIRED. The digital signature algorithm used to sign the ECT.
|
|
||||||
MUST match the algorithm in the corresponding WIT.
|
|
||||||
Implementations MUST support ES256 {{RFC7518}}. The "alg"
|
|
||||||
value MUST NOT be "none". Symmetric algorithms (e.g., HS256,
|
|
||||||
HS384, HS512) MUST NOT be used, as ECTs require asymmetric
|
|
||||||
signatures for non-repudiation.
|
|
||||||
|
|
||||||
typ:
|
|
||||||
: REQUIRED. MUST be set to "wimse-exec+jwt" to distinguish ECTs
|
|
||||||
from other JWT types, consistent with the WIMSE convention for
|
|
||||||
type parameter values.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## JWT Claims {#jwt-claims}
|
|
||||||
|
|
||||||
### Standard JWT Claims
|
|
||||||
|
|
||||||
An ECT MUST contain the following standard JWT claims {{RFC7519}}:
|
|
||||||
|
|
||||||
iss:
|
|
||||||
: REQUIRED. StringOrURI. A URI identifying the issuer of the
|
|
||||||
ECT. In WIMSE deployments, this SHOULD be the workload's
|
|
||||||
SPIFFE ID in the format `spiffe://<trust-domain>/<path>`,
|
|
||||||
matching the "sub" claim of the agent's WIT. Non-WIMSE
|
|
||||||
deployments MAY use other URI schemes (e.g., HTTPS URLs or
|
|
||||||
URN:UUID identifiers).
|
|
||||||
|
|
||||||
aud:
|
|
||||||
: REQUIRED. StringOrURI or array of StringOrURI. The intended
|
|
||||||
recipient(s) of the ECT. The "aud" claim SHOULD contain the
|
|
||||||
identifiers of all entities that will verify the ECT. When
|
|
||||||
an ECT must be verified by both the next agent and the audit
|
|
||||||
ledger independently, "aud" MUST be an array containing both
|
|
||||||
identifiers. Each verifier checks that its own identity
|
|
||||||
appears in "aud".
|
|
||||||
|
|
||||||
iat:
|
|
||||||
: REQUIRED. NumericDate. The time at which the ECT was issued.
|
|
||||||
|
|
||||||
exp:
|
|
||||||
: REQUIRED. NumericDate. The expiration time of the ECT.
|
|
||||||
Implementations SHOULD set this to 5 to 15 minutes after "iat".
|
|
||||||
|
|
||||||
jti:
|
|
||||||
: REQUIRED. String. A unique identifier for both the ECT and
|
|
||||||
the task it records, in UUID format {{RFC9562}}. The "jti"
|
|
||||||
serves as both the token identifier (for replay detection) and
|
|
||||||
the task identifier (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}
|
|
||||||
|
|
||||||
The following claims are defined by this specification:
|
|
||||||
|
|
||||||
wid:
|
|
||||||
: OPTIONAL. String. A workflow identifier that groups related
|
|
||||||
ECTs into a single workflow. When present, MUST be a UUID
|
|
||||||
{{RFC9562}}.
|
|
||||||
|
|
||||||
exec_act:
|
|
||||||
: REQUIRED. String. The action or task type identifier describing
|
|
||||||
what the agent performed (e.g., "process_payment",
|
|
||||||
"validate_safety"). This claim name avoids collision with the
|
|
||||||
"act" (Actor) claim registered by {{RFC8693}}.
|
|
||||||
|
|
||||||
par:
|
|
||||||
: REQUIRED. Array of strings. Parent task identifiers
|
|
||||||
representing DAG dependencies. Each element MUST be the "jti"
|
|
||||||
value of a previously verified ECT. An empty array indicates
|
|
||||||
a root task with no dependencies. A workflow MAY contain
|
|
||||||
multiple root tasks.
|
|
||||||
|
|
||||||
### Data Integrity {#data-integrity-claims}
|
|
||||||
|
|
||||||
The following claims provide integrity verification for task
|
|
||||||
inputs and outputs without revealing the data itself:
|
|
||||||
|
|
||||||
inp_hash:
|
|
||||||
: OPTIONAL. String. The base64url encoding (without padding) of
|
|
||||||
the SHA-256 hash of the input data, computed over the raw octets
|
|
||||||
of the input. SHA-256 is the mandatory algorithm with no
|
|
||||||
algorithm prefix in the value, consistent with {{RFC9449}} and
|
|
||||||
{{I-D.ietf-wimse-s2s-protocol}}.
|
|
||||||
|
|
||||||
out_hash:
|
|
||||||
: OPTIONAL. String. The base64url encoding (without padding) of
|
|
||||||
the SHA-256 hash of the output data, using the same format as
|
|
||||||
"inp_hash".
|
|
||||||
|
|
||||||
### Extensions {#extension-claims}
|
|
||||||
|
|
||||||
ext:
|
|
||||||
: OPTIONAL. Object. A general-purpose extension object for
|
|
||||||
domain-specific claims not defined by this specification.
|
|
||||||
Implementations that do not understand extension claims MUST
|
|
||||||
ignore them. Extension key names SHOULD use reverse domain
|
|
||||||
notation (e.g., "com.example.custom_field") to avoid
|
|
||||||
collisions. The serialized "ext" object SHOULD NOT exceed
|
|
||||||
4096 bytes and SHOULD NOT exceed a nesting depth of 5 levels.
|
|
||||||
|
|
||||||
## Complete ECT Example
|
|
||||||
|
|
||||||
The following is a complete ECT payload example:
|
|
||||||
|
|
||||||
~~~json
|
|
||||||
{
|
|
||||||
"iss": "spiffe://example.com/agent/clinical",
|
|
||||||
"aud": "spiffe://example.com/agent/safety",
|
|
||||||
"iat": 1772064150,
|
|
||||||
"exp": 1772064750,
|
|
||||||
"jti": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
|
|
||||||
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
|
||||||
"exec_act": "recommend_treatment",
|
|
||||||
"par": [],
|
|
||||||
|
|
||||||
"inp_hash": "n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
|
|
||||||
"out_hash": "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
|
|
||||||
|
|
||||||
"ext": {
|
|
||||||
"com.example.trace_id": "abc123"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~~~
|
|
||||||
{: #fig-full-ect title="Complete ECT Payload Example"}
|
|
||||||
|
|
||||||
# HTTP Header Transport {#http-header}
|
|
||||||
|
|
||||||
## Execution-Context Header Field
|
|
||||||
|
|
||||||
This specification defines the Execution-Context HTTP header field
|
|
||||||
{{RFC9110}} for transporting ECTs between agents.
|
|
||||||
|
|
||||||
The header field value is the ECT in JWS Compact Serialization
|
|
||||||
format {{RFC7515}}. The value consists of three Base64url-encoded
|
|
||||||
parts separated by period (".") characters.
|
|
||||||
|
|
||||||
An agent sending a request to another agent includes the
|
|
||||||
Execution-Context header alongside the WIMSE Workload-Identity
|
|
||||||
header. When a Workload Proof Token (WPT) is available per
|
|
||||||
{{I-D.ietf-wimse-s2s-protocol}}, agents SHOULD include it
|
|
||||||
alongside the WIT and ECT.
|
|
||||||
|
|
||||||
~~~
|
|
||||||
GET /api/safety-check HTTP/1.1
|
|
||||||
Host: safety-agent.example.com
|
|
||||||
Workload-Identity: eyJhbGci...WIT...
|
|
||||||
Execution-Context: eyJhbGci...ECT...
|
|
||||||
~~~
|
|
||||||
{: #fig-http-example title="HTTP Request with ECT Header"}
|
|
||||||
|
|
||||||
When multiple parent tasks contribute context to a single request,
|
|
||||||
multiple Execution-Context header field lines MAY be included, each
|
|
||||||
carrying a separate ECT in JWS Compact Serialization format.
|
|
||||||
|
|
||||||
When a receiver processes multiple Execution-Context headers, it
|
|
||||||
MUST individually verify each ECT per the procedure in
|
|
||||||
{{verification}}. If any single ECT fails verification, the
|
|
||||||
receiver MUST reject the entire request. The set of verified
|
|
||||||
parent task IDs across all received ECTs represents the complete
|
|
||||||
set of parent dependencies available for the receiving agent's
|
|
||||||
subsequent ECT.
|
|
||||||
|
|
||||||
# DAG Validation {#dag-validation}
|
|
||||||
|
|
||||||
ECTs form a Directed Acyclic Graph (DAG) where each task
|
|
||||||
references its parent tasks via the "par" claim. DAG validation
|
|
||||||
is performed against the ECT store — either an audit ledger or
|
|
||||||
the set of parent ECTs received inline.
|
|
||||||
|
|
||||||
When receiving and verifying an ECT, implementations MUST perform
|
|
||||||
the following DAG validation steps:
|
|
||||||
|
|
||||||
1. Task ID Uniqueness: The "jti" claim MUST be unique within the
|
|
||||||
applicable scope (the workflow identified by "wid", or the
|
|
||||||
entire ECT store if "wid" is absent). If an ECT with the same
|
|
||||||
"jti" already exists, the ECT MUST be rejected.
|
|
||||||
|
|
||||||
2. Parent Existence: Every task identifier listed in the "par"
|
|
||||||
array MUST correspond to a task that is available in the ECT
|
|
||||||
store (either previously recorded in the ledger or received
|
|
||||||
inline as a verified parent ECT). If any parent task is not
|
|
||||||
found, the ECT MUST be rejected.
|
|
||||||
|
|
||||||
3. Temporal Ordering: The "iat" value of every parent task MUST
|
|
||||||
NOT be greater than the "iat" value of the current task plus a
|
|
||||||
configurable clock skew tolerance (RECOMMENDED: 30 seconds).
|
|
||||||
That is, for each parent: `parent.iat < child.iat +
|
|
||||||
clock_skew_tolerance`. The tolerance accounts for clock skew
|
|
||||||
between agents; it does not guarantee strict causal ordering
|
|
||||||
from timestamps alone. Causal ordering is primarily enforced
|
|
||||||
by the DAG structure (parent existence in the ECT store), not by
|
|
||||||
timestamps. If any parent task violates this constraint, the
|
|
||||||
ECT MUST be rejected.
|
|
||||||
|
|
||||||
4. Acyclicity: Following the chain of parent references MUST NOT
|
|
||||||
lead back to the current ECT's "jti". If a cycle is detected,
|
|
||||||
the ECT MUST be rejected.
|
|
||||||
|
|
||||||
5. Trust Domain Consistency: Parent tasks SHOULD belong to the
|
|
||||||
same trust domain or to a trust domain with which a federation
|
|
||||||
relationship has been established.
|
|
||||||
|
|
||||||
To prevent denial-of-service via extremely deep or wide DAGs,
|
|
||||||
implementations SHOULD enforce a maximum ancestor traversal limit
|
|
||||||
(RECOMMENDED: 10000 nodes). If the limit is reached before cycle
|
|
||||||
detection completes, the ECT SHOULD be rejected.
|
|
||||||
|
|
||||||
In distributed deployments, a parent ECT may not yet be available
|
|
||||||
locally due to replication lag. Implementations MAY defer
|
|
||||||
validation to allow parent ECTs to arrive, but MUST NOT treat
|
|
||||||
the ECT as verified until all parent references are resolved.
|
|
||||||
|
|
||||||
# Signature and Token Verification {#verification}
|
|
||||||
|
|
||||||
## Verification Procedure
|
|
||||||
|
|
||||||
When an agent receives an ECT, it MUST perform the following
|
|
||||||
verification steps in order:
|
|
||||||
|
|
||||||
1. Parse the JWS Compact Serialization to extract the JOSE header,
|
|
||||||
payload, and signature components per {{RFC7515}}.
|
|
||||||
|
|
||||||
2. Verify that the "typ" header parameter is "wimse-exec+jwt".
|
|
||||||
|
|
||||||
3. Verify that the "alg" header parameter appears in the
|
|
||||||
verifier's configured allowlist of accepted signing algorithms.
|
|
||||||
The allowlist MUST NOT include "none" or any symmetric
|
|
||||||
algorithm (e.g., HS256, HS384, HS512). Implementations MUST
|
|
||||||
include ES256 in the allowlist; additional asymmetric algorithms
|
|
||||||
MAY be included per deployment policy.
|
|
||||||
|
|
||||||
4. Verify the "kid" header parameter references a known, valid
|
|
||||||
public key from a WIT within the trust domain.
|
|
||||||
|
|
||||||
5. Retrieve the public key identified by "kid" and verify the JWS
|
|
||||||
signature per {{RFC7515}} Section 5.2.
|
|
||||||
|
|
||||||
6. Verify that the signing key identified by "kid" has not been
|
|
||||||
revoked within the trust domain. Implementations MUST check
|
|
||||||
the key's revocation status using the trust domain's key
|
|
||||||
lifecycle mechanism (e.g., certificate revocation list, OCSP,
|
|
||||||
or SPIFFE trust bundle updates).
|
|
||||||
|
|
||||||
7. Verify the "alg" header parameter matches the algorithm in the
|
|
||||||
corresponding WIT.
|
|
||||||
|
|
||||||
8. Verify the "iss" claim matches the "sub" claim of the WIT
|
|
||||||
associated with the "kid" public key.
|
|
||||||
|
|
||||||
9. Verify the "aud" claim contains the verifier's own workload
|
|
||||||
identity. When "aud" is an array, it is sufficient that the
|
|
||||||
verifier's identity appears as one element; the presence of
|
|
||||||
other audience values does not cause verification failure.
|
|
||||||
When the verifier is the audit ledger, the ledger's own
|
|
||||||
identity MUST appear in "aud".
|
|
||||||
|
|
||||||
10. Verify the "exp" claim indicates the ECT has not expired.
|
|
||||||
|
|
||||||
11. Verify the "iat" claim is not unreasonably far in the past
|
|
||||||
(implementation-specific threshold, RECOMMENDED maximum of
|
|
||||||
15 minutes) and is not unreasonably far in the future
|
|
||||||
(RECOMMENDED: no more than 30 seconds ahead of the
|
|
||||||
verifier's current time, to account for clock skew).
|
|
||||||
|
|
||||||
12. Verify all required claims ("jti", "exec_act", "par") are
|
|
||||||
present and well-formed.
|
|
||||||
|
|
||||||
13. Perform DAG validation per {{dag-validation}}.
|
|
||||||
|
|
||||||
14. If all checks pass and an audit ledger is deployed, the ECT
|
|
||||||
SHOULD be appended to the ledger.
|
|
||||||
|
|
||||||
If any verification step fails, the ECT MUST be rejected and the
|
|
||||||
failure MUST be logged for audit purposes. Error messages
|
|
||||||
SHOULD NOT reveal whether specific parent task IDs exist in the
|
|
||||||
ECT store, to prevent information disclosure.
|
|
||||||
|
|
||||||
When ECT verification fails during HTTP request processing, the
|
|
||||||
receiving agent SHOULD respond with HTTP 403 (Forbidden) if the
|
|
||||||
WIT is valid but the ECT is invalid, and HTTP 401
|
|
||||||
(Unauthorized) if the ECT signature verification fails. The
|
|
||||||
response body SHOULD include a generic error indicator without
|
|
||||||
revealing which specific verification step failed. The receiving
|
|
||||||
agent MUST NOT process the requested action when ECT verification
|
|
||||||
fails.
|
|
||||||
|
|
||||||
# Audit Ledger Interface {#ledger-interface}
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
2. Ordering: The ledger MUST maintain a total ordering of ECT
|
|
||||||
entries via a monotonically increasing sequence number.
|
|
||||||
|
|
||||||
3. Lookup by ECT ID: The ledger MUST support efficient retrieval
|
|
||||||
of ECT entries by "jti" value.
|
|
||||||
|
|
||||||
4. Integrity verification: The ledger SHOULD provide a mechanism
|
|
||||||
to verify that no entries have been tampered with (e.g.,
|
|
||||||
hash chains or Merkle trees).
|
|
||||||
|
|
||||||
The ledger SHOULD be maintained by an entity independent of the
|
|
||||||
workflow agents to reduce the risk of collusion.
|
|
||||||
|
|
||||||
# Security Considerations
|
|
||||||
|
|
||||||
## Threat Model
|
|
||||||
|
|
||||||
The threat model considers: (1) a malicious agent that creates
|
|
||||||
false ECT claims, (2) an agent whose private key has been
|
|
||||||
compromised, (3) a ledger tamperer attempting to modify recorded
|
|
||||||
entries, and (4) a time manipulator altering timestamps to affect
|
|
||||||
perceived ordering.
|
|
||||||
|
|
||||||
## Self-Assertion Limitation {#self-assertion-limitation}
|
|
||||||
|
|
||||||
ECTs are self-asserted by the executing agent. The agent claims
|
|
||||||
what it did, and this claim is signed with its private key. A
|
|
||||||
compromised or malicious agent could create ECTs with false claims
|
|
||||||
(e.g., claiming an action was performed when it was not).
|
|
||||||
|
|
||||||
ECTs do not independently verify that:
|
|
||||||
|
|
||||||
- The claimed execution actually occurred as described
|
|
||||||
- The input/output hashes correspond to the actual data processed
|
|
||||||
- The agent faithfully performed the stated action
|
|
||||||
|
|
||||||
The trustworthiness of ECT claims depends on the trustworthiness
|
|
||||||
of the signing agent and the integrity of the broader deployment
|
|
||||||
environment. ECTs provide a technical mechanism for execution
|
|
||||||
recording; they do not by themselves satisfy any specific
|
|
||||||
regulatory compliance requirement.
|
|
||||||
|
|
||||||
## Signature Verification
|
|
||||||
|
|
||||||
ECTs MUST be signed with the agent's private key using JWS
|
|
||||||
{{RFC7515}}. The signature algorithm MUST match the algorithm
|
|
||||||
specified in the agent's WIT. Receivers MUST verify the ECT
|
|
||||||
signature against the WIT public key before processing any
|
|
||||||
claims. Receivers MUST verify that the signing key has not been
|
|
||||||
revoked within the trust domain (see step 6 in
|
|
||||||
{{verification}}).
|
|
||||||
|
|
||||||
If signature verification fails or if the signing key has been
|
|
||||||
revoked, the ECT MUST be rejected entirely and the failure MUST
|
|
||||||
be logged.
|
|
||||||
|
|
||||||
Implementations MUST use established JWS libraries and MUST NOT
|
|
||||||
implement custom signature verification.
|
|
||||||
|
|
||||||
## Replay Attack Prevention
|
|
||||||
|
|
||||||
ECTs include short expiration times (RECOMMENDED: 5-15 minutes)
|
|
||||||
and audience restriction via "aud" to limit replay attacks.
|
|
||||||
Implementations MUST maintain a cache of recently-seen "jti"
|
|
||||||
values and MUST reject ECTs with duplicate "jti" values. Each
|
|
||||||
ECT is cryptographically bound to the issuing agent via "kid";
|
|
||||||
verifiers MUST confirm that "kid" resolves to the "iss" agent's
|
|
||||||
key (step 8 in {{verification}}).
|
|
||||||
|
|
||||||
## Man-in-the-Middle Protection
|
|
||||||
|
|
||||||
ECTs MUST be transmitted over TLS or mTLS connections. When used
|
|
||||||
with {{I-D.ietf-wimse-s2s-protocol}}, transport security is
|
|
||||||
already established.
|
|
||||||
|
|
||||||
## Key Compromise
|
|
||||||
|
|
||||||
If an agent's private key is compromised, an attacker can forge
|
|
||||||
ECTs that appear to originate from that agent. Mitigations:
|
|
||||||
|
|
||||||
- Implementations SHOULD use short-lived keys and rotate them
|
|
||||||
frequently.
|
|
||||||
- Private keys SHOULD be stored in hardware security modules or
|
|
||||||
equivalent secure key storage.
|
|
||||||
- Trust domains MUST support rapid key revocation.
|
|
||||||
|
|
||||||
ECTs recorded before key revocation remain valid historical
|
|
||||||
records but SHOULD be flagged for audit purposes. New ECTs
|
|
||||||
MUST NOT reference a parent ECT whose signing key is known to
|
|
||||||
be revoked at creation time.
|
|
||||||
|
|
||||||
## Collusion and DAG Integrity {#collusion-and-false-claims}
|
|
||||||
|
|
||||||
A single malicious agent cannot forge parent task references
|
|
||||||
because DAG validation requires parent tasks to exist in the ECT
|
|
||||||
store. However, multiple colluding agents could create a false
|
|
||||||
execution history. Additionally, a malicious agent may omit
|
|
||||||
actual parent dependencies from "par" to hide influences on its
|
|
||||||
output; because ECTs are self-asserted
|
|
||||||
({{self-assertion-limitation}}), no mechanism can force complete
|
|
||||||
dependency declaration.
|
|
||||||
|
|
||||||
Mitigations include:
|
|
||||||
|
|
||||||
- The ledger SHOULD be maintained by an entity independent of the
|
|
||||||
workflow agents.
|
|
||||||
- Multiple independent ledger replicas can be compared for
|
|
||||||
consistency.
|
|
||||||
- External auditors can compare the declared DAG against expected
|
|
||||||
workflow patterns.
|
|
||||||
|
|
||||||
Verifiers SHOULD validate that the declared "wid" of parent ECTs
|
|
||||||
matches the "wid" of the child ECT, rejecting cross-workflow
|
|
||||||
parent references unless explicitly permitted by deployment
|
|
||||||
policy.
|
|
||||||
|
|
||||||
## Privilege Escalation via ECTs
|
|
||||||
|
|
||||||
ECTs record execution history; they do not convey authorization.
|
|
||||||
Verifiers MUST NOT interpret the presence of an ECT, or a
|
|
||||||
particular set of parent references in "par", as an authorization
|
|
||||||
grant. Authorization decisions MUST remain with the identity and
|
|
||||||
authorization layer (WIT, WPT, and deployment policy).
|
|
||||||
|
|
||||||
## Denial of Service
|
|
||||||
|
|
||||||
Implementations SHOULD apply rate limiting to prevent excessive
|
|
||||||
ECT submissions. DAG validation SHOULD be performed after
|
|
||||||
signature verification to avoid wasting resources on unsigned
|
|
||||||
tokens.
|
|
||||||
|
|
||||||
## Timestamp Accuracy
|
|
||||||
|
|
||||||
Implementations SHOULD use synchronized time sources (e.g., NTP)
|
|
||||||
and SHOULD allow a configurable clock skew tolerance (RECOMMENDED:
|
|
||||||
30 seconds). Cross-organizational deployments MAY require a
|
|
||||||
higher tolerance and SHOULD document the configured value.
|
|
||||||
|
|
||||||
## ECT Size Constraints
|
|
||||||
|
|
||||||
Implementations SHOULD limit the "par" array to a maximum of
|
|
||||||
256 entries. See {{extension-claims}} for "ext" size limits.
|
|
||||||
|
|
||||||
# Privacy Considerations
|
|
||||||
|
|
||||||
## Data Exposure in ECTs
|
|
||||||
|
|
||||||
ECTs necessarily reveal:
|
|
||||||
|
|
||||||
- Agent identities ("iss", "aud") for accountability purposes
|
|
||||||
- Action descriptions ("exec_act") for audit trail completeness
|
|
||||||
- Timestamps ("iat", "exp") for temporal ordering
|
|
||||||
|
|
||||||
ECTs are designed to NOT reveal:
|
|
||||||
|
|
||||||
- Actual input or output data values (replaced with cryptographic
|
|
||||||
hashes via "inp_hash" and "out_hash")
|
|
||||||
- Internal computation details or intermediate steps
|
|
||||||
- Proprietary algorithms or intellectual property
|
|
||||||
- Personally identifiable information (PII)
|
|
||||||
|
|
||||||
## Data Minimization {#data-minimization}
|
|
||||||
|
|
||||||
Implementations SHOULD minimize the information included in ECTs.
|
|
||||||
The "exec_act" claim SHOULD use structured identifiers (e.g.,
|
|
||||||
"process_payment") rather than natural language descriptions.
|
|
||||||
Extension keys in "ext" ({{extension-claims}}) deserve particular
|
|
||||||
attention: human-readable values risk exposing sensitive operational
|
|
||||||
details. See {{extension-claims}} for guidance on using
|
|
||||||
structured identifiers.
|
|
||||||
|
|
||||||
## Storage and Access Control
|
|
||||||
|
|
||||||
ECTs stored in audit ledgers SHOULD be access-controlled so that
|
|
||||||
only authorized auditors can read them. Implementations SHOULD
|
|
||||||
consider encryption at rest for ledger storage. ECTs provide
|
|
||||||
structural records of execution ordering; they are not intended
|
|
||||||
for public disclosure.
|
|
||||||
|
|
||||||
Full input and output data (corresponding to the hashes in ECTs)
|
|
||||||
SHOULD be stored separately from the ledger with additional access
|
|
||||||
controls, since auditors may need to verify hash correctness but
|
|
||||||
general access to the data values is not needed.
|
|
||||||
|
|
||||||
# IANA Considerations
|
|
||||||
|
|
||||||
## Media Type Registration
|
|
||||||
|
|
||||||
This document requests registration of the following media type
|
|
||||||
in the "Media Types" registry maintained by IANA:
|
|
||||||
|
|
||||||
Type name:
|
|
||||||
: application
|
|
||||||
|
|
||||||
Subtype name:
|
|
||||||
: wimse-exec+jwt
|
|
||||||
|
|
||||||
Required parameters:
|
|
||||||
: none
|
|
||||||
|
|
||||||
Optional parameters:
|
|
||||||
: none
|
|
||||||
|
|
||||||
Encoding considerations:
|
|
||||||
: 8bit; an ECT is a JWT that is a JWS using the Compact
|
|
||||||
Serialization, which is a sequence of Base64url-encoded values
|
|
||||||
separated by period characters.
|
|
||||||
|
|
||||||
Security considerations:
|
|
||||||
: See the Security Considerations section of this document.
|
|
||||||
|
|
||||||
Interoperability considerations:
|
|
||||||
: none
|
|
||||||
|
|
||||||
Published specification:
|
|
||||||
: This document
|
|
||||||
|
|
||||||
Applications that use this media type:
|
|
||||||
: Applications that implement agentic workflows requiring execution
|
|
||||||
context tracing and audit trails.
|
|
||||||
|
|
||||||
Additional information:
|
|
||||||
: Magic number(s): none
|
|
||||||
File extension(s): none
|
|
||||||
Macintosh file type code(s): none
|
|
||||||
|
|
||||||
Person and email address to contact for further information:
|
|
||||||
: Christian Nennemann, ietf@nennemann.de
|
|
||||||
|
|
||||||
Intended usage:
|
|
||||||
: COMMON
|
|
||||||
|
|
||||||
Restrictions on usage:
|
|
||||||
: none
|
|
||||||
|
|
||||||
Author:
|
|
||||||
: Christian Nennemann
|
|
||||||
|
|
||||||
Change controller:
|
|
||||||
: IETF
|
|
||||||
|
|
||||||
## HTTP Header Field Registration {#header-registration}
|
|
||||||
|
|
||||||
This document requests registration of the following header field
|
|
||||||
in the "Hypertext Transfer Protocol (HTTP) Field Name Registry"
|
|
||||||
maintained by IANA:
|
|
||||||
|
|
||||||
Field name:
|
|
||||||
: Execution-Context
|
|
||||||
|
|
||||||
Status:
|
|
||||||
: permanent
|
|
||||||
|
|
||||||
Specification document:
|
|
||||||
: This document, {{http-header}}
|
|
||||||
|
|
||||||
## JWT Claims Registration {#claims-registration}
|
|
||||||
|
|
||||||
This document requests registration of the following claims in
|
|
||||||
the "JSON Web Token Claims" registry maintained by IANA:
|
|
||||||
|
|
||||||
| Claim Name | Claim Description | Change Controller | Reference |
|
|
||||||
|:---:|:---|:---:|:---:|
|
|
||||||
| wid | Workflow Identifier | IETF | {{exec-claims}} |
|
|
||||||
| exec_act | Action/Task Type | IETF | {{exec-claims}} |
|
|
||||||
| par | Parent Task Identifiers | IETF | {{exec-claims}} |
|
|
||||||
| inp_hash | Input Data Hash | IETF | {{data-integrity-claims}} |
|
|
||||||
| out_hash | Output Data Hash | IETF | {{data-integrity-claims}} |
|
|
||||||
| ext | Extension Object | IETF | {{extension-claims}} |
|
|
||||||
{: #table-claims title="JWT Claims Registrations"}
|
|
||||||
|
|
||||||
--- back
|
|
||||||
|
|
||||||
# Use Cases {#use-cases}
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
This section describes a representative use case demonstrating how
|
|
||||||
ECTs provide structured execution records.
|
|
||||||
|
|
||||||
Note: task identifiers in this section are abbreviated for
|
|
||||||
readability. In production, all "jti" values are required to be
|
|
||||||
UUIDs per {{exec-claims}}.
|
|
||||||
|
|
||||||
## Cross-Organization Financial Trading
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
In a cross-organization trading workflow, an investment bank's
|
|
||||||
agents coordinate with an external credit rating agency. The
|
|
||||||
agents operate in separate trust domains with a federation
|
|
||||||
relationship. The DAG records that independent assessments from
|
|
||||||
both organizations were completed before trade execution.
|
|
||||||
|
|
||||||
~~~
|
|
||||||
Trust Domain: bank.example
|
|
||||||
Agent A1 (Portfolio Risk):
|
|
||||||
jti: task-001 par: []
|
|
||||||
iss: spiffe://bank.example/agent/risk
|
|
||||||
exec_act: analyze_portfolio_risk
|
|
||||||
|
|
||||||
Trust Domain: ratings.example (external)
|
|
||||||
Agent B1 (Credit Rating):
|
|
||||||
jti: task-002 par: []
|
|
||||||
iss: spiffe://ratings.example/agent/credit
|
|
||||||
exec_act: assess_credit_rating
|
|
||||||
|
|
||||||
Trust Domain: bank.example
|
|
||||||
Agent A2 (Compliance):
|
|
||||||
jti: task-003 par: [task-001, task-002]
|
|
||||||
iss: spiffe://bank.example/agent/compliance
|
|
||||||
exec_act: verify_trade_compliance
|
|
||||||
|
|
||||||
Agent A3 (Execution):
|
|
||||||
jti: task-004 par: [task-003]
|
|
||||||
iss: spiffe://bank.example/agent/execution
|
|
||||||
exec_act: execute_trade
|
|
||||||
~~~
|
|
||||||
{: #fig-finance title="Cross-Organization Trading Workflow"}
|
|
||||||
|
|
||||||
The resulting DAG:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
task-001 (analyze_portfolio_risk) task-002 (assess_credit_rating)
|
|
||||||
[bank.example] [ratings.example]
|
|
||||||
\ /
|
|
||||||
v v
|
|
||||||
task-003 (verify_trade_compliance)
|
|
||||||
[bank.example]
|
|
||||||
|
|
|
||||||
v
|
|
||||||
task-004 (execute_trade)
|
|
||||||
[bank.example]
|
|
||||||
~~~
|
|
||||||
{: #fig-finance-dag title="Cross-Organization DAG"}
|
|
||||||
|
|
||||||
Task 003 has two parents from different trust domains,
|
|
||||||
demonstrating cross-organizational fan-in. The compliance agent
|
|
||||||
verifies both parent ECTs — one signed by a local key and one by
|
|
||||||
a federated key from the rating agency's trust domain.
|
|
||||||
|
|
||||||
# Related Work
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
## WIMSE Workload Identity
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
The WIMSE architecture {{I-D.ietf-wimse-arch}} and service-to-
|
|
||||||
service protocol {{I-D.ietf-wimse-s2s-protocol}} provide the
|
|
||||||
identity foundation upon which ECTs are built. WIT/WPT answer
|
|
||||||
"who is this agent?" and "does it control the claimed key?" while
|
|
||||||
ECTs record "what did this agent do?" Together they form an
|
|
||||||
identity-plus-accountability framework for regulated agentic
|
|
||||||
systems.
|
|
||||||
|
|
||||||
## OAuth 2.0 Token Exchange and the "act" Claim
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
{{RFC8693}} defines the OAuth 2.0 Token Exchange protocol and
|
|
||||||
registers the "act" (Actor) claim in the JWT Claims registry.
|
|
||||||
The "act" claim creates nested JSON objects representing a
|
|
||||||
delegation chain: "who is acting on behalf of whom." While
|
|
||||||
the nesting superficially resembles a chain, it is strictly
|
|
||||||
linear (each "act" object contains at most one nested "act"),
|
|
||||||
represents authorization delegation rather than task execution,
|
|
||||||
and carries no task identifiers or input/output integrity
|
|
||||||
data. The "act" chain cannot represent
|
|
||||||
branching (fan-out) or convergence (fan-in) and therefore
|
|
||||||
cannot form a DAG.
|
|
||||||
|
|
||||||
ECTs intentionally use the distinct claim name "exec_act" for the
|
|
||||||
action/task type to avoid collision with the "act" claim. The
|
|
||||||
two concepts are orthogonal: "act" records "who authorized whom,"
|
|
||||||
ECTs record "what was done, in what order."
|
|
||||||
|
|
||||||
## Transaction Tokens
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
OAuth Transaction Tokens {{I-D.ietf-oauth-transaction-tokens}}
|
|
||||||
propagate authorization context across workload call chains.
|
|
||||||
The Txn-Token "req_wl" claim accumulates a comma-separated list
|
|
||||||
of workloads that requested replacement tokens, which is the
|
|
||||||
closest existing mechanism to call-chain recording.
|
|
||||||
|
|
||||||
However, "req_wl" cannot form a DAG because:
|
|
||||||
|
|
||||||
- It is linear: a comma-separated string with no branching or
|
|
||||||
merging representation. When a workload fans out to multiple
|
|
||||||
downstream services, each receives the same "req_wl" value and
|
|
||||||
the branching is invisible.
|
|
||||||
- It is incomplete: only workloads that request a replacement
|
|
||||||
token from the Transaction Token Service appear in "req_wl";
|
|
||||||
workloads that forward the token unchanged are not recorded.
|
|
||||||
- It carries no task-level granularity, no parent references,
|
|
||||||
and no execution content.
|
|
||||||
- It cannot represent convergence (fan-in): when two independent
|
|
||||||
paths must both complete before a dependent task proceeds, a
|
|
||||||
linear "req_wl" string cannot express that relationship.
|
|
||||||
|
|
||||||
Extensions for agentic use cases
|
|
||||||
({{I-D.oauth-transaction-tokens-for-agents}}) add agent
|
|
||||||
identity and constraints ("agentic_ctx") but no execution
|
|
||||||
ordering or DAG structure.
|
|
||||||
|
|
||||||
ECTs and Transaction Tokens are complementary: a Txn-Token
|
|
||||||
propagates authorization context ("this request is authorized
|
|
||||||
for scope X on behalf of user Y"), while an ECT records
|
|
||||||
execution accountability ("task T was performed, depending on
|
|
||||||
tasks P1 and P2"). An
|
|
||||||
agent request could carry both a Txn-Token for authorization
|
|
||||||
and an ECT for execution recording. The WPT "tth" claim
|
|
||||||
defined in {{I-D.ietf-wimse-s2s-protocol}} can hash-bind a
|
|
||||||
WPT to a co-present Txn-Token; a similar binding mechanism
|
|
||||||
for ECTs is a potential future extension.
|
|
||||||
|
|
||||||
## Distributed Tracing (OpenTelemetry)
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
OpenTelemetry {{OPENTELEMETRY}} and similar distributed tracing
|
|
||||||
systems provide observability for debugging and monitoring. ECTs
|
|
||||||
differ in several important ways: ECTs are cryptographically
|
|
||||||
signed per-task with the agent's private key; ECTs are
|
|
||||||
tamper-evident through JWS signatures; ECTs enforce DAG validation
|
|
||||||
rules; and ECTs are designed for regulatory audit rather than
|
|
||||||
operational monitoring. OpenTelemetry data is typically controlled
|
|
||||||
by the platform operator and can be modified or deleted without
|
|
||||||
detection. ECTs and distributed traces are complementary: traces
|
|
||||||
provide observability while ECTs provide signed execution records.
|
|
||||||
ECTs may reference OpenTelemetry trace identifiers in the "ext"
|
|
||||||
claim for correlation.
|
|
||||||
|
|
||||||
## W3C Provenance Data Model (PROV)
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
The W3C PROV Data Model defines an Entity-Activity-Agent ontology
|
|
||||||
for representing provenance information. PROV's concepts map
|
|
||||||
closely to ECT structures: PROV Activities correspond to ECT
|
|
||||||
tasks, PROV Agents correspond to WIMSE workloads, and PROV's
|
|
||||||
"wasInformedBy" relation corresponds to ECT "par" references.
|
|
||||||
However, PROV uses RDF/OWL ontologies designed for post-hoc
|
|
||||||
documentation, while ECTs are runtime-embeddable JWT tokens with
|
|
||||||
cryptographic signatures. ECT audit data could be exported to
|
|
||||||
PROV format for interoperability with provenance-aware systems.
|
|
||||||
|
|
||||||
## SCITT (Supply Chain Integrity, Transparency, and Trust)
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
The SCITT architecture {{I-D.ietf-scitt-architecture}} defines a
|
|
||||||
framework for transparent and auditable supply chain records.
|
|
||||||
ECTs and SCITT are complementary: the ECT "wid" claim can serve
|
|
||||||
as a correlation identifier in SCITT Signed Statements, linking
|
|
||||||
an ECT audit trail to a supply chain transparency record.
|
|
||||||
|
|
||||||
# Acknowledgments
|
|
||||||
{:numbered="false"}
|
|
||||||
|
|
||||||
The author thanks the WIMSE working group for their foundational
|
|
||||||
work on workload identity in multi-system environments. The
|
|
||||||
concepts of Workload Identity Tokens and Workload Proof Tokens
|
|
||||||
provide the identity foundation upon which execution context
|
|
||||||
tracing is built.
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ submissiontype: IETF
|
|||||||
number:
|
number:
|
||||||
date:
|
date:
|
||||||
v: 3
|
v: 3
|
||||||
area: "ART"
|
area: "SEC"
|
||||||
workgroup: "WIMSE"
|
workgroup: "WIMSE"
|
||||||
keyword:
|
keyword:
|
||||||
- execution context
|
- execution context
|
||||||
@@ -25,18 +25,21 @@ author:
|
|||||||
normative:
|
normative:
|
||||||
RFC7515:
|
RFC7515:
|
||||||
RFC7517:
|
RFC7517:
|
||||||
RFC7519:
|
|
||||||
RFC7518:
|
RFC7518:
|
||||||
|
RFC7519:
|
||||||
|
RFC9449:
|
||||||
RFC9562:
|
RFC9562:
|
||||||
RFC9110:
|
RFC9110:
|
||||||
|
|
||||||
informative:
|
informative:
|
||||||
|
RFC6838:
|
||||||
RFC8693:
|
RFC8693:
|
||||||
|
RFC8725:
|
||||||
I-D.ietf-wimse-arch:
|
I-D.ietf-wimse-arch:
|
||||||
I-D.ietf-wimse-s2s-protocol:
|
I-D.ietf-wimse-s2s-protocol:
|
||||||
SPIFFE:
|
SPIFFE:
|
||||||
title: "Secure Production Identity Framework for Everyone (SPIFFE)"
|
title: "SPIFFE ID"
|
||||||
target: https://spiffe.io/docs/latest/spiffe-about/overview/
|
target: https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/
|
||||||
date: false
|
date: false
|
||||||
OPENTELEMETRY:
|
OPENTELEMETRY:
|
||||||
title: "OpenTelemetry Specification"
|
title: "OpenTelemetry Specification"
|
||||||
@@ -45,9 +48,16 @@ informative:
|
|||||||
author:
|
author:
|
||||||
- org: Cloud Native Computing Foundation
|
- org: Cloud Native Computing Foundation
|
||||||
I-D.ietf-scitt-architecture:
|
I-D.ietf-scitt-architecture:
|
||||||
RFC9449:
|
|
||||||
I-D.ietf-oauth-transaction-tokens:
|
I-D.ietf-oauth-transaction-tokens:
|
||||||
I-D.oauth-transaction-tokens-for-agents:
|
I-D.oauth-transaction-tokens-for-agents:
|
||||||
|
title: "Transaction Tokens for Agentic AI Systems"
|
||||||
|
target: https://datatracker.ietf.org/doc/draft-oauth-transaction-tokens-for-agents-00/
|
||||||
|
seriesinfo:
|
||||||
|
Internet-Draft: draft-oauth-transaction-tokens-for-agents-00
|
||||||
|
date: 2025
|
||||||
|
author:
|
||||||
|
- fullname: Vittorio Bertocci
|
||||||
|
RFC9334:
|
||||||
|
|
||||||
--- abstract
|
--- abstract
|
||||||
|
|
||||||
@@ -61,11 +71,10 @@ agnostic and can operate with any asymmetric key infrastructure
|
|||||||
including WIMSE WIT/WPT, X.509 certificates, OAuth-based
|
including WIMSE WIT/WPT, X.509 certificates, OAuth-based
|
||||||
credentials, or plain JWK sets.
|
credentials, or plain JWK sets.
|
||||||
|
|
||||||
This revision introduces three assurance levels — Level 1
|
ECTs support three assurance levels — Level 1 (unsigned JSON),
|
||||||
(unsigned JSON), Level 2 (JOSE asymmetric signing), and Level 3
|
Level 2 (JOSE asymmetric signing), and Level 3 (JOSE signing with
|
||||||
(JOSE signing with audit ledger) — allowing deployments to choose
|
audit ledger) — allowing deployments to choose the appropriate
|
||||||
the appropriate trade-off between simplicity and regulatory
|
trade-off between simplicity and regulatory compliance.
|
||||||
compliance.
|
|
||||||
|
|
||||||
--- middle
|
--- middle
|
||||||
|
|
||||||
@@ -119,7 +128,7 @@ Level 2 (L2) — JOSE Asymmetric Signing:
|
|||||||
L2 provides non-repudiation and tamper detection. This is
|
L2 provides non-repudiation and tamper detection. This is
|
||||||
the baseline assurance level for cross-organization and
|
the baseline assurance level for cross-organization and
|
||||||
peer-to-peer deployments. L2 corresponds to the behavior
|
peer-to-peer deployments. L2 corresponds to the behavior
|
||||||
defined in draft-nennemann-wimse-ect-00.
|
defined in Version -00 of this specification.
|
||||||
|
|
||||||
Level 3 (L3) — JOSE Signing with Audit Ledger:
|
Level 3 (L3) — JOSE Signing with Audit Ledger:
|
||||||
: L3 extends L2 by requiring that every ECT be recorded in an
|
: L3 extends L2 by requiring that every ECT be recorded in an
|
||||||
@@ -192,21 +201,23 @@ this section.
|
|||||||
The following standard JWT claims {{RFC7519}} are defined for ECTs:
|
The following standard JWT claims {{RFC7519}} are defined for ECTs:
|
||||||
|
|
||||||
iss:
|
iss:
|
||||||
: RECOMMENDED. StringOrURI. A URI identifying the issuer of the
|
: OPTIONAL at L1; REQUIRED at L2 and L3. StringOrURI. A URI
|
||||||
ECT. The value MUST correspond to the agent's identity as
|
identifying the issuer of the ECT. The value MUST correspond
|
||||||
asserted by its identity credential (see {{identity-binding}}).
|
to the agent's identity as asserted by its identity credential
|
||||||
In WIMSE deployments, this SHOULD be the workload's SPIFFE ID
|
(see {{identity-binding}}). In WIMSE deployments, this SHOULD
|
||||||
in the format `spiffe://<trust-domain>/<path>`. Other
|
be the workload's SPIFFE ID in the format
|
||||||
deployments MAY use HTTPS URLs, URN:UUID identifiers, or other
|
`spiffe://<trust-domain>/<path>`. Other deployments MAY use
|
||||||
URI schemes appropriate to the identity framework in use. The
|
HTTPS URLs, URN:UUID identifiers, or other URI schemes
|
||||||
"iss" claim is REQUIRED for L2 and L3 deployments (see
|
appropriate to the identity framework in use. L1 deployments
|
||||||
{{l2-verification}} and {{l3-verification}}).
|
are encouraged to include "iss" for consistency but it is not
|
||||||
|
required. See {{l2-verification}} and {{l3-verification}} for
|
||||||
|
the L2/L3 verification requirements.
|
||||||
|
|
||||||
aud:
|
aud:
|
||||||
: RECOMMENDED. StringOrURI or array of StringOrURI. The intended
|
: RECOMMENDED. StringOrURI or array of StringOrURI. The intended
|
||||||
recipient(s) of the ECT. The "aud" claim SHOULD contain the
|
recipient(s) of the ECT. The "aud" claim SHOULD contain the
|
||||||
identifiers of all entities that will verify the ECT. When
|
identifiers of all entities that will verify the ECT. When
|
||||||
an ECT must be verified by both the next agent and the audit
|
an ECT is to be verified by both the next agent and the audit
|
||||||
ledger independently, "aud" MUST be an array containing both
|
ledger independently, "aud" MUST be an array containing both
|
||||||
identifiers. Each verifier checks that its own identity
|
identifiers. Each verifier checks that its own identity
|
||||||
appears in "aud". The "aud" claim is REQUIRED for L2 and L3
|
appears in "aud". The "aud" claim is REQUIRED for L2 and L3
|
||||||
@@ -223,7 +234,7 @@ jti:
|
|||||||
: REQUIRED. String. A unique identifier for both the ECT and
|
: REQUIRED. String. A unique identifier for both the ECT and
|
||||||
the task it records, in UUID format {{RFC9562}}. The "jti"
|
the task it records, in UUID format {{RFC9562}}. The "jti"
|
||||||
serves as both the token identifier (for replay detection) and
|
serves as both the token identifier (for replay detection) and
|
||||||
the task identifier (for DAG parent references in "par").
|
the task identifier (for DAG parent references in "pred").
|
||||||
Receivers MUST reject ECTs whose "jti" has already been seen
|
Receivers MUST reject ECTs whose "jti" has already been seen
|
||||||
within the expiration window. When "wid" is present,
|
within the expiration window. When "wid" is present,
|
||||||
uniqueness is scoped to the workflow; when "wid" is absent,
|
uniqueness is scoped to the workflow; when "wid" is absent,
|
||||||
@@ -244,12 +255,15 @@ exec_act:
|
|||||||
"validate_safety"). This claim name avoids collision with the
|
"validate_safety"). This claim name avoids collision with the
|
||||||
"act" (Actor) claim registered by {{RFC8693}}.
|
"act" (Actor) claim registered by {{RFC8693}}.
|
||||||
|
|
||||||
par:
|
pred:
|
||||||
: REQUIRED. Array of strings. Parent task identifiers
|
: REQUIRED. Array of strings. Predecessor task identifiers
|
||||||
representing DAG dependencies. Each element MUST be the "jti"
|
representing DAG dependencies. Each element MUST be the "jti"
|
||||||
value of a previously verified ECT. 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. The "pred" claim is always required
|
||||||
|
(rather than optional with absence meaning "root task") to
|
||||||
|
simplify validation logic and eliminate ambiguity between a
|
||||||
|
root task and a claim accidentally omitted.
|
||||||
|
|
||||||
### Data Integrity Claims {#data-integrity-claims}
|
### Data Integrity Claims {#data-integrity-claims}
|
||||||
|
|
||||||
@@ -270,14 +284,16 @@ out_hash:
|
|||||||
|
|
||||||
### Extension Claims {#extension-claims}
|
### Extension Claims {#extension-claims}
|
||||||
|
|
||||||
ext:
|
ect_ext:
|
||||||
: OPTIONAL. Object. A general-purpose extension object for
|
: OPTIONAL. Object. A general-purpose extension object for
|
||||||
domain-specific claims not defined by this specification.
|
domain-specific claims not defined by this specification.
|
||||||
Implementations that do not understand extension claims MUST
|
Implementations that do not understand extension claims MUST
|
||||||
ignore them. Extension key names SHOULD use reverse domain
|
ignore them. Extension key names SHOULD use reverse domain
|
||||||
notation (e.g., "com.example.custom_field") to avoid
|
notation (e.g., "com.example.custom_field") to avoid
|
||||||
collisions. The serialized "ext" object SHOULD NOT exceed
|
collisions. The serialized "ect_ext" object MUST NOT exceed
|
||||||
4096 bytes and SHOULD NOT exceed a nesting depth of 5 levels.
|
4096 bytes and MUST NOT exceed a nesting depth of 5 levels.
|
||||||
|
Receivers MUST reject ECTs whose "ect_ext" object exceeds these
|
||||||
|
limits.
|
||||||
|
|
||||||
## Complete ECT Payload Example
|
## Complete ECT Payload Example
|
||||||
|
|
||||||
@@ -295,12 +311,12 @@ envelope differs.
|
|||||||
|
|
||||||
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
"wid": "a0b1c2d3-e4f5-6789-abcd-ef0123456789",
|
||||||
"exec_act": "recommend_treatment",
|
"exec_act": "recommend_treatment",
|
||||||
"par": [],
|
"pred": [],
|
||||||
|
|
||||||
"inp_hash": "n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
|
"inp_hash": "n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
|
||||||
"out_hash": "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
|
"out_hash": "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564",
|
||||||
|
|
||||||
"ext": {
|
"ect_ext": {
|
||||||
"com.example.trace_id": "abc123"
|
"com.example.trace_id": "abc123"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,12 +330,14 @@ defined in {{ect-payload}}. No cryptographic signature is applied.
|
|||||||
|
|
||||||
### L1 Transport {#l1-transport}
|
### L1 Transport {#l1-transport}
|
||||||
|
|
||||||
L1 ECTs are transported as serialized JSON. Two mechanisms are
|
L1 ECTs are transported as base64url-encoded JSON (without
|
||||||
defined:
|
padding). Two mechanisms are defined:
|
||||||
|
|
||||||
HTTP Header:
|
HTTP Header:
|
||||||
: The Execution-Context header field ({{http-header}}) carries
|
: The Execution-Context header field ({{http-header}}) carries
|
||||||
the base64url-encoded JSON payload (without padding).
|
the base64url-encoded JSON payload (without padding). The
|
||||||
|
header value is NOT raw JSON; the receiver MUST base64url-decode
|
||||||
|
the value before parsing.
|
||||||
|
|
||||||
HTTP Body:
|
HTTP Body:
|
||||||
: When the ECT is the primary request payload, the ECT MAY be
|
: When the ECT is the primary request payload, the ECT MAY be
|
||||||
@@ -337,16 +355,20 @@ verification steps:
|
|||||||
1. Parse the JSON object.
|
1. Parse the JSON object.
|
||||||
|
|
||||||
2. Verify that all required claims ("jti", "iat", "exp",
|
2. Verify that all required claims ("jti", "iat", "exp",
|
||||||
"exec_act", "par") are present and well-formed.
|
"exec_act", "pred") are present and well-formed.
|
||||||
|
|
||||||
3. Verify the "exp" claim indicates the ECT has not expired.
|
3. Verify that the "jti" has not been previously seen within the
|
||||||
|
expiration window, consistent with the replay detection
|
||||||
|
requirement in {{exec-claims}}.
|
||||||
|
|
||||||
4. Verify the "iat" claim is not unreasonably far in the past
|
4. Verify the "exp" claim indicates the ECT has not expired.
|
||||||
|
|
||||||
|
5. Verify the "iat" claim is not unreasonably far in the past
|
||||||
(RECOMMENDED maximum: 15 minutes) and is not unreasonably
|
(RECOMMENDED maximum: 15 minutes) and is not unreasonably
|
||||||
far in the future (RECOMMENDED: no more than 30 seconds
|
far in the future (RECOMMENDED: no more than 30 seconds
|
||||||
ahead of the verifier's current time).
|
ahead of the verifier's current time).
|
||||||
|
|
||||||
5. Perform DAG validation per {{dag-validation}}.
|
6. Perform DAG validation per {{dag-validation}}.
|
||||||
|
|
||||||
If any verification step fails, the ECT MUST be rejected and the
|
If any verification step fails, the ECT MUST be rejected and the
|
||||||
failure MUST be logged.
|
failure MUST be logged.
|
||||||
@@ -368,6 +390,12 @@ L1 does NOT provide:
|
|||||||
- Issuer authentication at the ECT layer (identity depends
|
- Issuer authentication at the ECT layer (identity depends
|
||||||
entirely on the transport layer)
|
entirely on the transport layer)
|
||||||
|
|
||||||
|
Note: At L1, without a deployed audit ledger, DAG parent
|
||||||
|
existence validation ({{dag-validation}} step 2) is limited to
|
||||||
|
parent ECTs received inline with the current request. Parents
|
||||||
|
from prior requests that were not forwarded inline cannot be
|
||||||
|
verified.
|
||||||
|
|
||||||
L1 MUST NOT be used across trust domain boundaries.
|
L1 MUST NOT be used across trust domain boundaries.
|
||||||
Deployments using L1 SHOULD restrict it to internal environments
|
Deployments using L1 SHOULD restrict it to internal environments
|
||||||
where all agents are operated by the same organization and
|
where all agents are operated by the same organization and
|
||||||
@@ -377,7 +405,7 @@ transport security is considered sufficient.
|
|||||||
|
|
||||||
At Level 2, an ECT is a JSON Web Token (JWT) {{RFC7519}} signed
|
At Level 2, an ECT is a JSON Web Token (JWT) {{RFC7519}} signed
|
||||||
as a JSON Web Signature (JWS) {{RFC7515}}. L2 corresponds to the
|
as a JSON Web Signature (JWS) {{RFC7515}}. L2 corresponds to the
|
||||||
signing behavior defined in draft-nennemann-wimse-ect-00.
|
signing behavior defined in Version -00 of this specification.
|
||||||
|
|
||||||
ECTs MUST use JWS Compact Serialization (the base64url-encoded
|
ECTs MUST use JWS Compact Serialization (the base64url-encoded
|
||||||
`header.payload.signature` format) so that they can be carried in
|
`header.payload.signature` format) so that they can be carried in
|
||||||
@@ -409,12 +437,20 @@ alg:
|
|||||||
credential. Implementations MUST support ES256 {{RFC7518}}.
|
credential. Implementations MUST support ES256 {{RFC7518}}.
|
||||||
The "alg" value MUST NOT be "none". Symmetric algorithms
|
The "alg" value MUST NOT be "none". Symmetric algorithms
|
||||||
(e.g., HS256, HS384, HS512) MUST NOT be used, as ECTs require
|
(e.g., HS256, HS384, HS512) MUST NOT be used, as ECTs require
|
||||||
asymmetric signatures for non-repudiation.
|
asymmetric signatures for non-repudiation. To support algorithm
|
||||||
|
agility, deployments SHOULD maintain an allowlist of accepted
|
||||||
|
signing algorithms and SHOULD plan for migration to stronger
|
||||||
|
algorithms as cryptographic requirements evolve. The algorithm
|
||||||
|
is signaled in-band via the "alg" header parameter, enabling
|
||||||
|
verifiers to support multiple algorithms during a transition
|
||||||
|
period. Deployments SHOULD document their algorithm migration
|
||||||
|
strategy and SHOULD NOT assume that ES256 will remain
|
||||||
|
sufficient indefinitely.
|
||||||
|
|
||||||
typ:
|
typ:
|
||||||
: REQUIRED. MUST be set to "exec+jwt" to distinguish ECTs from
|
: REQUIRED. MUST be set to "exec+jwt" to distinguish ECTs from
|
||||||
other JWT types. WIMSE deployments MAY use "wimse-exec+jwt"
|
other JWT types. WIMSE deployments MAY use "wimse-exec+jwt"
|
||||||
for backward compatibility with draft-nennemann-wimse-ect-00.
|
for backward compatibility with Version -00 of this specification.
|
||||||
Verifiers MUST accept both values.
|
Verifiers MUST accept both values.
|
||||||
|
|
||||||
kid:
|
kid:
|
||||||
@@ -487,7 +523,7 @@ 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", "exec_act", "par") are
|
12. Verify all required claims ("jti", "exec_act", "pred") are
|
||||||
present and well-formed.
|
present and well-formed.
|
||||||
|
|
||||||
13. Perform DAG validation per {{dag-validation}}.
|
13. Perform DAG validation per {{dag-validation}}.
|
||||||
@@ -575,7 +611,11 @@ Asynchronous Recording:
|
|||||||
MUST subsequently verify that the ledger accepted the ECT and
|
MUST subsequently verify that the ledger accepted the ECT and
|
||||||
MUST retain the receipt. If the ledger rejects the ECT, the
|
MUST retain the receipt. If the ledger rejects the ECT, the
|
||||||
agent MUST alert the workflow coordinator or log a critical
|
agent MUST alert the workflow coordinator or log a critical
|
||||||
error.
|
error. If asynchronous ledger recording fails, the producing
|
||||||
|
agent MUST notify downstream agents that the ECT's L3 status
|
||||||
|
is unconfirmed. Downstream agents SHOULD treat such an ECT as
|
||||||
|
L2-verified (not L3-verified) until ledger confirmation is
|
||||||
|
independently obtainable.
|
||||||
|
|
||||||
Deployments SHOULD use synchronous recording unless latency
|
Deployments SHOULD use synchronous recording unless latency
|
||||||
constraints make it impractical. The recording mode SHOULD be
|
constraints make it impractical. The recording mode SHOULD be
|
||||||
@@ -586,23 +626,32 @@ documented in the deployment's security policy.
|
|||||||
L3 verification consists of L2 verification ({{l2-verification}})
|
L3 verification consists of L2 verification ({{l2-verification}})
|
||||||
followed by ledger verification:
|
followed by ledger verification:
|
||||||
|
|
||||||
|
Note: The "iss" and "aud" claims, which are RECOMMENDED at L1
|
||||||
|
and verified at L2 (steps 8-9 of {{l2-verification}}), are
|
||||||
|
REQUIRED at L3.
|
||||||
|
|
||||||
1. Perform all L2 verification steps (steps 1 through 14 of
|
1. Perform all L2 verification steps (steps 1 through 14 of
|
||||||
{{l2-verification}}).
|
{{l2-verification}}).
|
||||||
|
|
||||||
2. Verify the "iss" claim is present (REQUIRED at L3).
|
2. Verify that the ECT has been recorded in the audit ledger by
|
||||||
|
querying the ledger for the ECT's "jti". If the ECT is
|
||||||
|
found, verify that the ledger entry's receipt contains a
|
||||||
|
valid sequence number, ECT hash, and cryptographic commitment
|
||||||
|
proof. Note: the producing agent is responsible for recording
|
||||||
|
the ECT per {{l3-recording}}; the verifier checks that
|
||||||
|
recording has occurred.
|
||||||
|
|
||||||
3. Verify the "aud" claim is present (REQUIRED at L3).
|
3. If the ECT is not yet present in the ledger (e.g., due to
|
||||||
|
asynchronous recording), the verifier MAY retry after a
|
||||||
|
short delay. If the ledger does not contain the ECT within
|
||||||
|
the configured timeout, the verifier MUST either reject the
|
||||||
|
ECT or downgrade to L2 verification per deployment policy.
|
||||||
|
|
||||||
4. Submit the ECT to the audit ledger for recording per
|
4. If the ledger is unavailable, the verifier SHOULD retry with
|
||||||
{{l3-recording}}.
|
exponential backoff. If the ledger remains unavailable after
|
||||||
|
a deployment-configured number of retries, the verifier MUST
|
||||||
5. Verify that the ledger returned a valid receipt containing
|
either reject the ECT or downgrade to L2 verification per
|
||||||
the sequence number, ECT hash, and cryptographic commitment
|
deployment policy.
|
||||||
proof.
|
|
||||||
|
|
||||||
6. If synchronous recording is required by deployment policy and
|
|
||||||
the ledger does not return a receipt within the configured
|
|
||||||
timeout, the ECT MUST be treated as unverified.
|
|
||||||
|
|
||||||
If any L3-specific verification step fails, the ECT MUST be
|
If any L3-specific verification step fails, the ECT MUST be
|
||||||
rejected even if L2 verification succeeded.
|
rejected even if L2 verification succeeded.
|
||||||
@@ -641,32 +690,51 @@ following criteria:
|
|||||||
|
|
||||||
- Use L3 when regulatory requirements mandate tamper-evident
|
- Use L3 when regulatory requirements mandate tamper-evident
|
||||||
audit trails with cryptographic commitment, or when the
|
audit trails with cryptographic commitment, or when the
|
||||||
deployment must demonstrate compliance with frameworks such as
|
deployment needs to demonstrate compliance with frameworks such as
|
||||||
FDA 21 CFR Part 11, MiFID II, or the EU AI Act.
|
FDA 21 CFR Part 11, MiFID II, or the EU AI Act.
|
||||||
|
|
||||||
A deployment MAY use different assurance levels for different
|
A deployment MAY use different assurance levels for different
|
||||||
workflows within the same infrastructure. When agents at
|
workflows within the same infrastructure. When agents at
|
||||||
different levels interact, the higher level's verification
|
different levels interact, the higher level's verification
|
||||||
requirements apply to the receiving agent.
|
requirements apply to the receiving agent. Specifically, an
|
||||||
|
ECT at a higher assurance level MAY reference parent ECTs at a
|
||||||
|
lower assurance level in its "pred" claim. In this case, the
|
||||||
|
receiving agent applies its own level's verification to the
|
||||||
|
current ECT and the parent's level verification to each parent
|
||||||
|
ECT. For example, an L2 agent receiving an L1 parent ECT
|
||||||
|
verifies the L1 parent per {{l1-verification}} and its own L2
|
||||||
|
ECT per {{l2-verification}}. Whether cross-level parent
|
||||||
|
references are permitted is a deployment policy decision;
|
||||||
|
deployments MAY reject ECTs whose parents are below a minimum
|
||||||
|
assurance level.
|
||||||
|
|
||||||
|
This specification does not define a level negotiation mechanism.
|
||||||
|
Deployments configure the required assurance level out of band.
|
||||||
|
A future extension MAY define in-band level signaling.
|
||||||
|
|
||||||
## Backward Compatibility and Level Detection {#level-detection}
|
## Backward Compatibility and Level Detection {#level-detection}
|
||||||
|
|
||||||
A verifier determines the assurance level of a received ECT as
|
A verifier determines the assurance level of a received ECT as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
1. If the Execution-Context header value or body content parses
|
1. If the raw Execution-Context header value (or body content)
|
||||||
as valid JSON (not JWS Compact Serialization), the ECT is L1.
|
contains exactly two period (".") characters separating three
|
||||||
|
non-empty segments, attempt to parse the value as JWS Compact
|
||||||
|
Serialization. If the first segment base64url-decodes to a
|
||||||
|
JSON object containing an "alg" field, the ECT is L2 or L3.
|
||||||
|
|
||||||
2. If the value parses as JWS Compact Serialization (three
|
2. Otherwise, base64url-decode the header value (without padding)
|
||||||
Base64url-encoded segments separated by periods), the ECT is
|
and attempt to parse the result as JSON. If successful, the
|
||||||
L2 or L3.
|
ECT is L1.
|
||||||
|
|
||||||
3. L2 and L3 use the same JWS format. Differentiation between
|
3. If neither parse succeeds, the ECT MUST be rejected.
|
||||||
L2 and L3 is a matter of deployment policy: L3 deployments
|
|
||||||
require ledger recording ({{l3-ledger}}), while L2
|
|
||||||
deployments treat ledger recording as optional.
|
|
||||||
|
|
||||||
Implementations compliant with draft-nennemann-wimse-ect-00 are
|
L2 and L3 use the same JWS format. Differentiation between
|
||||||
|
L2 and L3 is a matter of deployment policy: L3 deployments
|
||||||
|
require ledger recording ({{l3-ledger}}), while L2
|
||||||
|
deployments treat ledger recording as optional.
|
||||||
|
|
||||||
|
Implementations compliant with Version -00 of this specification are
|
||||||
L2-compatible. No changes to existing -00 implementations are
|
L2-compatible. No changes to existing -00 implementations are
|
||||||
required for L2 interoperability.
|
required for L2 interoperability.
|
||||||
|
|
||||||
@@ -778,10 +846,25 @@ parent task IDs across all received ECTs represents the complete
|
|||||||
set of parent dependencies available for the receiving agent's
|
set of parent dependencies available for the receiving agent's
|
||||||
subsequent ECT.
|
subsequent ECT.
|
||||||
|
|
||||||
|
## HTTP Error Handling
|
||||||
|
|
||||||
|
When ECT verification fails during HTTP request processing, the
|
||||||
|
receiving agent SHOULD respond with HTTP 403 (Forbidden). This
|
||||||
|
applies regardless of whether the failure is due to an invalid
|
||||||
|
ECT payload, a signature verification failure, or a missing ECT
|
||||||
|
when one is required by deployment policy. HTTP 401
|
||||||
|
(Unauthorized) SHOULD NOT be used for ECT failures, as 401
|
||||||
|
conventionally indicates that authentication credentials are
|
||||||
|
missing or invalid and requires a WWW-Authenticate header per
|
||||||
|
{{RFC9110}}. The response body SHOULD include a generic error
|
||||||
|
indicator without revealing which specific verification step
|
||||||
|
failed. The receiving agent MUST NOT process the requested
|
||||||
|
action when ECT verification fails.
|
||||||
|
|
||||||
# DAG Validation {#dag-validation}
|
# DAG Validation {#dag-validation}
|
||||||
|
|
||||||
ECTs form a Directed Acyclic Graph (DAG) where each task
|
ECTs form a Directed Acyclic Graph (DAG) where each task
|
||||||
references its parent tasks via the "par" claim. DAG validation
|
references its parent tasks via the "pred" claim. DAG validation
|
||||||
is performed against the ECT store — either an audit ledger or
|
is performed against the ECT store — either an audit ledger or
|
||||||
the set of parent ECTs received inline.
|
the set of parent ECTs received inline.
|
||||||
|
|
||||||
@@ -795,7 +878,7 @@ the following DAG validation steps:
|
|||||||
entire ECT store if "wid" is absent). If an ECT with the same
|
entire ECT store if "wid" is absent). If an ECT with the same
|
||||||
"jti" 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 "pred"
|
||||||
array MUST correspond to a task that is available in the ECT
|
array MUST correspond to a task that is available in the ECT
|
||||||
store (either previously recorded in the ledger or received
|
store (either previously recorded in the ledger or received
|
||||||
inline as a verified parent ECT). If any parent task is not
|
inline as a verified parent ECT). If any parent task is not
|
||||||
@@ -814,12 +897,25 @@ the following DAG validation steps:
|
|||||||
|
|
||||||
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 ECT's "jti". If a cycle is detected,
|
lead back to the current ECT's "jti". If a cycle is detected,
|
||||||
the ECT MUST be rejected.
|
the ECT MUST be rejected. Note: because the Parent Existence
|
||||||
|
check (step 2) requires that all parents already exist in the
|
||||||
|
ECT store, and an ECT cannot reference itself or a future ECT,
|
||||||
|
cycles are prevented by construction. This explicit check
|
||||||
|
serves as defense in depth against implementation errors or
|
||||||
|
store corruption.
|
||||||
|
|
||||||
5. Trust Domain Consistency: Parent tasks SHOULD belong to the
|
5. Trust Domain Consistency: Parent tasks SHOULD belong to the
|
||||||
same trust domain or to a trust domain with which a federation
|
same trust domain or to a trust domain with which a federation
|
||||||
relationship has been established.
|
relationship has been established.
|
||||||
|
|
||||||
|
6. Workflow Consistency: When "wid" is present, verifiers SHOULD
|
||||||
|
validate that the "wid" of each parent ECT matches the "wid"
|
||||||
|
of the current ECT. Cross-workflow parent references (where
|
||||||
|
a parent's "wid" differs from the child's "wid") MUST be
|
||||||
|
rejected unless explicitly permitted by deployment policy.
|
||||||
|
See also {{collusion-and-false-claims}} for the security
|
||||||
|
rationale.
|
||||||
|
|
||||||
To prevent denial-of-service via extremely deep or wide DAGs,
|
To prevent denial-of-service via extremely deep or wide DAGs,
|
||||||
implementations SHOULD enforce a maximum ancestor traversal limit
|
implementations SHOULD enforce a maximum ancestor traversal limit
|
||||||
(RECOMMENDED: 10000 nodes). If the limit is reached before cycle
|
(RECOMMENDED: 10000 nodes). If the limit is reached before cycle
|
||||||
@@ -830,36 +926,6 @@ locally due to replication lag. Implementations MAY defer
|
|||||||
validation to allow parent ECTs to arrive, but MUST NOT treat
|
validation to allow parent ECTs to arrive, but MUST NOT treat
|
||||||
the ECT as verified until all parent references are resolved.
|
the ECT as verified until all parent references are resolved.
|
||||||
|
|
||||||
# Signature and Token Verification {#verification}
|
|
||||||
|
|
||||||
## Level Detection
|
|
||||||
|
|
||||||
Before performing verification, the verifier MUST determine the
|
|
||||||
assurance level of the received ECT per {{level-detection}}. If
|
|
||||||
the ECT is L1 (unsigned JSON), the verifier follows the L1
|
|
||||||
verification procedure ({{l1-verification}}) and skips all
|
|
||||||
signature-related steps. If the ECT is L2 or L3 (JWS), the
|
|
||||||
verifier follows the L2 verification procedure
|
|
||||||
({{l2-verification}}) and, for L3 deployments, the additional
|
|
||||||
ledger verification steps ({{l3-verification}}).
|
|
||||||
|
|
||||||
## L2/L3 Verification Procedure
|
|
||||||
|
|
||||||
The L2 verification procedure is defined in {{l2-verification}}.
|
|
||||||
For L3 deployments, the additional steps in {{l3-verification}}
|
|
||||||
MUST also be performed.
|
|
||||||
|
|
||||||
## HTTP Error Handling
|
|
||||||
|
|
||||||
When ECT verification fails during HTTP request processing, the
|
|
||||||
receiving agent SHOULD respond with HTTP 403 (Forbidden) if the
|
|
||||||
agent's identity credential is valid but the ECT is invalid, and
|
|
||||||
HTTP 401 (Unauthorized) if the ECT signature verification fails.
|
|
||||||
The response body SHOULD include a generic error indicator without
|
|
||||||
revealing which specific verification step failed. The receiving
|
|
||||||
agent MUST NOT process the requested action when ECT verification
|
|
||||||
fails.
|
|
||||||
|
|
||||||
# Audit Ledger Interface {#ledger-interface}
|
# Audit Ledger Interface {#ledger-interface}
|
||||||
|
|
||||||
ECTs MAY be recorded in an immutable audit ledger for compliance
|
ECTs MAY be recorded in an immutable audit ledger for compliance
|
||||||
@@ -945,7 +1011,7 @@ perceived ordering.
|
|||||||
|
|
||||||
## Level-Specific Security Properties {#level-security}
|
## Level-Specific Security Properties {#level-security}
|
||||||
|
|
||||||
### Level 1
|
### Level 1 {#sec-level-1}
|
||||||
|
|
||||||
L1 provides no cryptographic binding between the ECT and its
|
L1 provides no cryptographic binding between the ECT and its
|
||||||
issuer. A compromised or malicious intermediary with access to
|
issuer. A compromised or malicious intermediary with access to
|
||||||
@@ -960,14 +1026,14 @@ organization, the transport channel is fully trusted (e.g.,
|
|||||||
service mesh with mTLS), and the deployment does not require
|
service mesh with mTLS), and the deployment does not require
|
||||||
non-repudiation or tamper evidence beyond transport security.
|
non-repudiation or tamper evidence beyond transport security.
|
||||||
|
|
||||||
### Level 2
|
### Level 2 {#sec-level-2}
|
||||||
|
|
||||||
L2 inherits all security properties of the JWS-based ECT
|
L2 inherits all security properties of the JWS-based ECT
|
||||||
mechanism defined in this document. The existing security
|
mechanism defined in this document. The existing security
|
||||||
analysis (signature verification, replay prevention, key
|
analysis (signature verification, replay prevention, key
|
||||||
compromise, collusion) applies directly to L2.
|
compromise, collusion) applies directly to L2.
|
||||||
|
|
||||||
### Level 3
|
### Level 3 {#sec-level-3}
|
||||||
|
|
||||||
L3 provides all L2 security properties plus tamper-evident
|
L3 provides all L2 security properties plus tamper-evident
|
||||||
history via the audit ledger's hash chain and cryptographic
|
history via the audit ledger's hash chain and cryptographic
|
||||||
@@ -981,6 +1047,24 @@ mechanism ({{l3-ledger}}) provides evidence of submission.
|
|||||||
Deployments concerned about ledger censorship SHOULD use multiple
|
Deployments concerned about ledger censorship SHOULD use multiple
|
||||||
independent ledger replicas.
|
independent ledger replicas.
|
||||||
|
|
||||||
|
## Assurance Level Downgrade Attacks
|
||||||
|
|
||||||
|
The assurance level of an ECT is determined by its format: unsigned
|
||||||
|
JSON indicates L1, while a JWS compact serialization indicates L2
|
||||||
|
or L3. This format-based detection determines what was sent, not
|
||||||
|
what was expected by the verifier.
|
||||||
|
|
||||||
|
A man-in-the-middle or compromised proxy could strip the JWS
|
||||||
|
signature from an L2 or L3 ECT and re-encode the payload as an
|
||||||
|
unsigned L1 JSON object. Because the resulting ECT is
|
||||||
|
syntactically valid at L1, a verifier that accepts any assurance
|
||||||
|
level would process it without detecting the downgrade.
|
||||||
|
|
||||||
|
Verifiers MUST be configured with a minimum acceptable assurance
|
||||||
|
level and MUST reject ECTs whose detected level falls below that
|
||||||
|
minimum. Format-based level detection alone is insufficient
|
||||||
|
without a policy-enforced minimum level requirement.
|
||||||
|
|
||||||
## Self-Assertion Limitation {#self-assertion-limitation}
|
## Self-Assertion Limitation {#self-assertion-limitation}
|
||||||
|
|
||||||
ECTs are self-asserted by the executing agent. The agent claims
|
ECTs are self-asserted by the executing agent. The agent claims
|
||||||
@@ -1001,6 +1085,11 @@ environment. ECTs provide a technical mechanism for execution
|
|||||||
recording; they do not by themselves satisfy any specific
|
recording; they do not by themselves satisfy any specific
|
||||||
regulatory compliance requirement.
|
regulatory compliance requirement.
|
||||||
|
|
||||||
|
At Level 1, the self-assertion limitation is compounded by the
|
||||||
|
absence of any cryptographic binding; any entity with access to
|
||||||
|
the transport channel can create ECTs claiming any identity and
|
||||||
|
any action.
|
||||||
|
|
||||||
## Signature Verification
|
## Signature Verification
|
||||||
|
|
||||||
For L2 and L3 deployments, ECTs MUST be signed with the agent's
|
For L2 and L3 deployments, ECTs MUST be signed with the agent's
|
||||||
@@ -1017,7 +1106,14 @@ revoked, the ECT MUST be rejected entirely and the failure MUST
|
|||||||
be logged.
|
be logged.
|
||||||
|
|
||||||
Implementations MUST use established JWS libraries and MUST NOT
|
Implementations MUST use established JWS libraries and MUST NOT
|
||||||
implement custom signature verification.
|
implement custom signature verification. Implementations SHOULD
|
||||||
|
follow the JWT security best practices defined in {{RFC8725}}.
|
||||||
|
|
||||||
|
The prohibition of "alg": "none" (see {{l2-verification}}) also
|
||||||
|
serves as defense against level-confusion attacks: an L1 payload
|
||||||
|
wrapped in a JWS with alg=none would be detected as L2 by format
|
||||||
|
and rejected at the algorithm allowlist check, preventing an
|
||||||
|
attacker from bypassing L2 security requirements.
|
||||||
|
|
||||||
## Replay Attack Prevention
|
## Replay Attack Prevention
|
||||||
|
|
||||||
@@ -1057,7 +1153,7 @@ A single malicious agent cannot forge parent task references
|
|||||||
because DAG validation requires parent tasks to exist in the ECT
|
because DAG validation requires parent tasks to exist in the ECT
|
||||||
store. However, multiple colluding agents could create a false
|
store. However, multiple colluding agents could create a false
|
||||||
execution history. Additionally, a malicious agent may omit
|
execution history. Additionally, a malicious agent may omit
|
||||||
actual parent dependencies from "par" to hide influences on its
|
actual parent dependencies from "pred" to hide influences on its
|
||||||
output; because ECTs are self-asserted
|
output; because ECTs are self-asserted
|
||||||
({{self-assertion-limitation}}), no mechanism can force complete
|
({{self-assertion-limitation}}), no mechanism can force complete
|
||||||
dependency declaration.
|
dependency declaration.
|
||||||
@@ -1080,7 +1176,7 @@ policy.
|
|||||||
|
|
||||||
ECTs record execution history; they do not convey authorization.
|
ECTs record execution history; they do not convey authorization.
|
||||||
Verifiers MUST NOT interpret the presence of an ECT, or a
|
Verifiers MUST NOT interpret the presence of an ECT, or a
|
||||||
particular set of parent references in "par", as an authorization
|
particular set of parent references in "pred", as an authorization
|
||||||
grant. Authorization decisions MUST remain with the deployment's
|
grant. Authorization decisions MUST remain with the deployment's
|
||||||
identity and authorization layer.
|
identity and authorization layer.
|
||||||
|
|
||||||
@@ -1103,8 +1199,85 @@ higher tolerance and SHOULD document the configured value.
|
|||||||
|
|
||||||
## ECT Size Constraints
|
## ECT Size Constraints
|
||||||
|
|
||||||
Implementations SHOULD limit the "par" array to a maximum of
|
Implementations SHOULD limit the "pred" array to a maximum of
|
||||||
256 entries. See {{extension-claims}} for "ext" size limits.
|
256 entries. See {{extension-claims}} for "ect_ext" size limits.
|
||||||
|
|
||||||
|
When ECTs are transported via HTTP headers, the total encoded
|
||||||
|
size of the Execution-Context header value is subject to
|
||||||
|
practical limits imposed by HTTP servers and intermediaries.
|
||||||
|
Many implementations enforce header size limits of 8 KB or 16 KB.
|
||||||
|
Implementations SHOULD ensure that the total size of an ECT
|
||||||
|
(including JWS overhead for L2/L3) does not exceed 8 KB when
|
||||||
|
transported via HTTP header. ECTs that exceed HTTP header size
|
||||||
|
limits SHOULD be transported in the HTTP request body instead
|
||||||
|
(see {{l1-transport}} and {{l2-transport}}). Deployments SHOULD
|
||||||
|
monitor ECT sizes and alert when ECTs approach transport limits.
|
||||||
|
|
||||||
|
## Identity Binding Security
|
||||||
|
|
||||||
|
### JWK Set Binding {#sec-jwk-binding}
|
||||||
|
|
||||||
|
When identity is bound via JWK Set URI (see {{identity-binding}}),
|
||||||
|
there is a time-of-check/time-of-use gap between JWK set
|
||||||
|
refreshes. A key that has been removed from the JWK set may still
|
||||||
|
be accepted by a verifier whose cached copy has not yet been
|
||||||
|
refreshed. Implementations SHOULD refresh JWK sets at
|
||||||
|
configurable intervals (RECOMMENDED: no longer than 5 minutes).
|
||||||
|
|
||||||
|
### X.509 Binding {#sec-x509-binding}
|
||||||
|
|
||||||
|
When identity is bound via X.509 certificates, revocation checking
|
||||||
|
depends on OCSP responder or CRL distribution point availability.
|
||||||
|
If the revocation source is unreachable, the verifier needs to decide
|
||||||
|
whether to accept or reject the ECT. Implementations SHOULD
|
||||||
|
hard-fail for L3 (reject the ECT if revocation status cannot be
|
||||||
|
determined), as L3 workflows require the strongest assurance.
|
||||||
|
Implementations MAY soft-fail for L2 with logging, accepting the
|
||||||
|
ECT but recording the revocation check failure for subsequent
|
||||||
|
audit review.
|
||||||
|
|
||||||
|
### WIMSE Binding {#sec-wimse-binding}
|
||||||
|
|
||||||
|
When identity is bound via WIMSE trust bundles, the same
|
||||||
|
time-of-check/time-of-use concern applies to trust bundle
|
||||||
|
refreshes. Implementations SHOULD refresh trust bundles
|
||||||
|
frequently to minimize the window during which a revoked or
|
||||||
|
rotated identity remains accepted.
|
||||||
|
|
||||||
|
## Audit Ledger Threats
|
||||||
|
|
||||||
|
### Availability
|
||||||
|
|
||||||
|
If the audit ledger is unavailable in synchronous recording mode
|
||||||
|
(see {{l3-ledger}}), all L3 workflows halt because agents cannot
|
||||||
|
obtain ledger receipts. Deployments SHOULD implement ledger
|
||||||
|
redundancy (e.g., multiple ledger replicas behind a load balancer)
|
||||||
|
to prevent the ledger from becoming a single point of failure.
|
||||||
|
|
||||||
|
### Split-View Attacks
|
||||||
|
|
||||||
|
A compromised ledger could present different views to different
|
||||||
|
verifiers (equivocation), causing inconsistent audit state across
|
||||||
|
the deployment. Deployments SHOULD use multiple independent
|
||||||
|
ledger replicas and SHOULD periodically compare their state to
|
||||||
|
detect divergence.
|
||||||
|
|
||||||
|
### Receipt Authenticity
|
||||||
|
|
||||||
|
If the ledger's signing key is compromised, an attacker can
|
||||||
|
generate fake receipts for entries that were never recorded.
|
||||||
|
Ledger signing keys SHOULD be stored in hardware security modules
|
||||||
|
(HSMs) and SHOULD be rotated regularly.
|
||||||
|
|
||||||
|
### Asynchronous Recording Gap
|
||||||
|
|
||||||
|
In asynchronous recording mode (see {{l3-ledger}}), downstream
|
||||||
|
agents act on ECTs before ledger confirmation is received.
|
||||||
|
During this gap, an ECT that will ultimately fail ledger recording
|
||||||
|
may already have influenced downstream workflow steps. Deployments
|
||||||
|
using asynchronous recording SHOULD implement reconciliation
|
||||||
|
procedures to detect and handle ECTs that fail ledger confirmation
|
||||||
|
after downstream processing has begun.
|
||||||
|
|
||||||
# Privacy Considerations
|
# Privacy Considerations
|
||||||
|
|
||||||
@@ -1135,7 +1308,7 @@ the privacy-relevant data but does not increase its scope.
|
|||||||
Implementations SHOULD minimize the information included in ECTs.
|
Implementations SHOULD minimize the information included in ECTs.
|
||||||
The "exec_act" claim SHOULD use structured identifiers (e.g.,
|
The "exec_act" claim SHOULD use structured identifiers (e.g.,
|
||||||
"process_payment") rather than natural language descriptions.
|
"process_payment") rather than natural language descriptions.
|
||||||
Extension keys in "ext" ({{extension-claims}}) deserve particular
|
Extension keys in "ect_ext" ({{extension-claims}}) deserve particular
|
||||||
attention: human-readable values risk exposing sensitive operational
|
attention: human-readable values risk exposing sensitive operational
|
||||||
details. See {{extension-claims}} for guidance on using
|
details. See {{extension-claims}} for guidance on using
|
||||||
structured identifiers.
|
structured identifiers.
|
||||||
@@ -1153,6 +1326,24 @@ SHOULD be stored separately from the ledger with additional access
|
|||||||
controls, since auditors may need to verify hash correctness but
|
controls, since auditors may need to verify hash correctness but
|
||||||
general access to the data values is not needed.
|
general access to the data values is not needed.
|
||||||
|
|
||||||
|
## Workflow Topology Leakage
|
||||||
|
|
||||||
|
The DAG structure of ECTs reveals workflow topology: which agents
|
||||||
|
interact, fan-out and fan-in patterns, sequential versus parallel
|
||||||
|
execution, and organizational structure. At L3, this topology is
|
||||||
|
permanently recorded in the audit ledger. Deployments SHOULD
|
||||||
|
consider whether workflow topology constitutes sensitive information
|
||||||
|
and apply appropriate access controls to ECT stores and ledgers.
|
||||||
|
|
||||||
|
## Cross-Workflow Correlation
|
||||||
|
|
||||||
|
Stable agent identifiers in the "iss" claim enable cross-workflow
|
||||||
|
activity correlation: an observer with access to ECTs from multiple
|
||||||
|
workflows can track which agents participate in which workflows and
|
||||||
|
how frequently. Deployments with privacy requirements MAY use
|
||||||
|
per-workflow or rotating agent identifiers where feasible to limit
|
||||||
|
cross-workflow correlation.
|
||||||
|
|
||||||
# IANA Considerations
|
# IANA Considerations
|
||||||
|
|
||||||
## Media Type Registrations
|
## Media Type Registrations
|
||||||
@@ -1160,6 +1351,12 @@ general access to the data values is not needed.
|
|||||||
This document requests registration of the following media types
|
This document requests registration of the following media types
|
||||||
in the "Media Types" registry maintained by IANA:
|
in the "Media Types" registry maintained by IANA:
|
||||||
|
|
||||||
|
Note: The media type "application/exec+jwt" uses the "+jwt"
|
||||||
|
structured syntax suffix. While "+jwt" is widely used in
|
||||||
|
practice, it is not yet a formally registered structured syntax
|
||||||
|
suffix per {{RFC6838}}. Registration of the "+jwt" suffix is
|
||||||
|
the subject of ongoing work in the IETF.
|
||||||
|
|
||||||
### application/exec+jwt
|
### application/exec+jwt
|
||||||
|
|
||||||
Type name:
|
Type name:
|
||||||
@@ -1217,11 +1414,61 @@ Change controller:
|
|||||||
### application/wimse-exec+jwt
|
### application/wimse-exec+jwt
|
||||||
|
|
||||||
This document also registers "application/wimse-exec+jwt" as an
|
This document also registers "application/wimse-exec+jwt" as an
|
||||||
alias for backward compatibility with draft-nennemann-wimse-ect-00.
|
alias for backward compatibility with Version -00 of this specification.
|
||||||
The registration details are identical to "application/exec+jwt"
|
WIMSE deployments MAY use either media type; new deployments
|
||||||
above except for the subtype name. WIMSE deployments MAY use
|
SHOULD prefer "application/exec+jwt".
|
||||||
either media type; new deployments SHOULD prefer
|
|
||||||
"application/exec+jwt".
|
Type name:
|
||||||
|
: application
|
||||||
|
|
||||||
|
Subtype name:
|
||||||
|
: wimse-exec+jwt
|
||||||
|
|
||||||
|
Required parameters:
|
||||||
|
: none
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
: none
|
||||||
|
|
||||||
|
Encoding considerations:
|
||||||
|
: 8bit; at Level 2 and Level 3, an ECT is a JWT that is a JWS
|
||||||
|
using the Compact Serialization, which is a sequence of
|
||||||
|
Base64url-encoded values separated by period characters. At
|
||||||
|
Level 1, this media type is not used; L1 ECTs use
|
||||||
|
application/json.
|
||||||
|
|
||||||
|
Security considerations:
|
||||||
|
: See the Security Considerations section of this document.
|
||||||
|
|
||||||
|
Interoperability considerations:
|
||||||
|
: none
|
||||||
|
|
||||||
|
Published specification:
|
||||||
|
: This document
|
||||||
|
|
||||||
|
Applications that use this media type:
|
||||||
|
: Applications that implement agentic workflows requiring execution
|
||||||
|
context tracing and audit trails.
|
||||||
|
|
||||||
|
Additional information:
|
||||||
|
: Magic number(s): none
|
||||||
|
File extension(s): none
|
||||||
|
Macintosh file type code(s): none
|
||||||
|
|
||||||
|
Person and email address to contact for further information:
|
||||||
|
: Christian Nennemann, ietf@nennemann.de
|
||||||
|
|
||||||
|
Intended usage:
|
||||||
|
: COMMON
|
||||||
|
|
||||||
|
Restrictions on usage:
|
||||||
|
: none
|
||||||
|
|
||||||
|
Author:
|
||||||
|
: Christian Nennemann
|
||||||
|
|
||||||
|
Change controller:
|
||||||
|
: IETF
|
||||||
|
|
||||||
## HTTP Header Field Registration {#header-registration}
|
## HTTP Header Field Registration {#header-registration}
|
||||||
|
|
||||||
@@ -1247,10 +1494,10 @@ the "JSON Web Token Claims" registry maintained by IANA:
|
|||||||
|:---:|:---|:---:|:---:|
|
|:---:|:---|:---:|:---:|
|
||||||
| wid | Workflow Identifier | IETF | {{exec-claims}} |
|
| wid | Workflow Identifier | IETF | {{exec-claims}} |
|
||||||
| exec_act | Action/Task Type | IETF | {{exec-claims}} |
|
| exec_act | Action/Task Type | IETF | {{exec-claims}} |
|
||||||
| par | Parent Task Identifiers | IETF | {{exec-claims}} |
|
| pred | Predecessor Task Identifiers | IETF | {{exec-claims}} |
|
||||||
| inp_hash | Input Data Hash | IETF | {{data-integrity-claims}} |
|
| inp_hash | Input Data Hash | IETF | {{data-integrity-claims}} |
|
||||||
| out_hash | Output Data Hash | IETF | {{data-integrity-claims}} |
|
| out_hash | Output Data Hash | IETF | {{data-integrity-claims}} |
|
||||||
| ext | Extension Object | IETF | {{extension-claims}} |
|
| ect_ext | Extension Object | IETF | {{extension-claims}} |
|
||||||
{: #table-claims title="JWT Claims Registrations"}
|
{: #table-claims title="JWT Claims Registrations"}
|
||||||
|
|
||||||
--- back
|
--- back
|
||||||
@@ -1282,24 +1529,24 @@ tamper-evident, auditable execution records.
|
|||||||
~~~
|
~~~
|
||||||
Trust Domain: bank.example
|
Trust Domain: bank.example
|
||||||
Agent A1 (Portfolio Risk):
|
Agent A1 (Portfolio Risk):
|
||||||
jti: task-001 par: []
|
jti: task-001 pred:[]
|
||||||
iss: spiffe://bank.example/agent/risk
|
iss: spiffe://bank.example/agent/risk
|
||||||
exec_act: analyze_portfolio_risk
|
exec_act: analyze_portfolio_risk
|
||||||
|
|
||||||
Trust Domain: ratings.example (external)
|
Trust Domain: ratings.example (external)
|
||||||
Agent B1 (Credit Rating):
|
Agent B1 (Credit Rating):
|
||||||
jti: task-002 par: []
|
jti: task-002 pred:[]
|
||||||
iss: spiffe://ratings.example/agent/credit
|
iss: spiffe://ratings.example/agent/credit
|
||||||
exec_act: assess_credit_rating
|
exec_act: assess_credit_rating
|
||||||
|
|
||||||
Trust Domain: bank.example
|
Trust Domain: bank.example
|
||||||
Agent A2 (Compliance):
|
Agent A2 (Compliance):
|
||||||
jti: task-003 par: [task-001, task-002]
|
jti: task-003 pred:[task-001, task-002]
|
||||||
iss: spiffe://bank.example/agent/compliance
|
iss: spiffe://bank.example/agent/compliance
|
||||||
exec_act: verify_trade_compliance
|
exec_act: verify_trade_compliance
|
||||||
|
|
||||||
Agent A3 (Execution):
|
Agent A3 (Execution):
|
||||||
jti: task-004 par: [task-003]
|
jti: task-004 pred:[task-003]
|
||||||
iss: spiffe://bank.example/agent/execution
|
iss: spiffe://bank.example/agent/execution
|
||||||
exec_act: execute_trade
|
exec_act: execute_trade
|
||||||
~~~
|
~~~
|
||||||
@@ -1326,6 +1573,82 @@ demonstrating cross-organizational fan-in. The compliance agent
|
|||||||
verifies both parent ECTs — one signed by a local key and one by
|
verifies both parent ECTs — one signed by a local key and one by
|
||||||
a federated key from the rating agency's trust domain.
|
a federated key from the rating agency's trust domain.
|
||||||
|
|
||||||
|
## Multi-Vendor SaaS Integration (L2)
|
||||||
|
{:numbered="false"}
|
||||||
|
|
||||||
|
In a document processing pipeline, a customer's orchestration
|
||||||
|
agent coordinates with third-party vendor agents across
|
||||||
|
organizational boundaries. The customer uploads documents that
|
||||||
|
pass through an OCR vendor for text extraction, then fan out to
|
||||||
|
a translation vendor for multi-language output, before results
|
||||||
|
converge back at the customer's storage agent.
|
||||||
|
|
||||||
|
This workflow uses Level 2 (JOSE signing without audit ledger)
|
||||||
|
because the cross-organization boundary requires non-repudiation
|
||||||
|
— each vendor must prove it performed its step — but no
|
||||||
|
regulatory audit ledger is mandated.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
Trust Domain: customer.example
|
||||||
|
Agent C1 (Orchestrator):
|
||||||
|
jti: task-201 pred:[]
|
||||||
|
iss: spiffe://customer.example/agent/orchestrator
|
||||||
|
exec_act: initiate_document_pipeline
|
||||||
|
|
||||||
|
Trust Domain: ocr-vendor.example (external)
|
||||||
|
Agent V1 (OCR Extractor):
|
||||||
|
jti: task-202 pred:[task-201]
|
||||||
|
iss: spiffe://ocr-vendor.example/agent/ocr
|
||||||
|
exec_act: extract_text
|
||||||
|
|
||||||
|
Trust Domain: translate-vendor.example (external)
|
||||||
|
Agent V2a (Translator EN→DE):
|
||||||
|
jti: task-203 pred:[task-202]
|
||||||
|
iss: spiffe://translate-vendor.example/agent/translate
|
||||||
|
exec_act: translate_de
|
||||||
|
|
||||||
|
Agent V2b (Translator EN→FR):
|
||||||
|
jti: task-204 pred:[task-202]
|
||||||
|
iss: spiffe://translate-vendor.example/agent/translate
|
||||||
|
exec_act: translate_fr
|
||||||
|
|
||||||
|
Trust Domain: customer.example
|
||||||
|
Agent C2 (Storage):
|
||||||
|
jti: task-205 pred:[task-203, task-204]
|
||||||
|
iss: spiffe://customer.example/agent/storage
|
||||||
|
exec_act: store_results
|
||||||
|
~~~
|
||||||
|
{: #fig-saas title="Multi-Vendor SaaS Document Pipeline (L2)"}
|
||||||
|
|
||||||
|
The resulting DAG:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
task-201 (initiate_document_pipeline)
|
||||||
|
[customer.example]
|
||||||
|
|
|
||||||
|
v
|
||||||
|
task-202 (extract_text)
|
||||||
|
[ocr-vendor.example]
|
||||||
|
/ \
|
||||||
|
v v
|
||||||
|
task-203 task-204
|
||||||
|
(translate_de) (translate_fr)
|
||||||
|
[translate-vendor] [translate-vendor]
|
||||||
|
\ /
|
||||||
|
v v
|
||||||
|
task-205 (store_results)
|
||||||
|
[customer.example]
|
||||||
|
~~~
|
||||||
|
{: #fig-saas-dag title="Multi-Vendor SaaS DAG"}
|
||||||
|
|
||||||
|
Task 202 fans out to two parallel translation tasks (203 and
|
||||||
|
204) at the translation vendor, demonstrating cross-vendor
|
||||||
|
fan-out. Task 205 performs fan-in, requiring both translations
|
||||||
|
to complete before storing the combined results. Each vendor's
|
||||||
|
ECT is signed with that vendor's private key, providing
|
||||||
|
cross-organizational non-repudiation without requiring an
|
||||||
|
external audit ledger.
|
||||||
|
|
||||||
## Internal Microservice Mesh (L1)
|
## Internal Microservice Mesh (L1)
|
||||||
{:numbered="false"}
|
{:numbered="false"}
|
||||||
|
|
||||||
@@ -1341,15 +1664,15 @@ cryptographic signing is not justified.
|
|||||||
~~~
|
~~~
|
||||||
Trust Domain: internal.example
|
Trust Domain: internal.example
|
||||||
Agent S1 (Preprocessor):
|
Agent S1 (Preprocessor):
|
||||||
jti: task-101 par: []
|
jti: task-101 pred:[]
|
||||||
exec_act: preprocess_input
|
exec_act: preprocess_input
|
||||||
|
|
||||||
Agent S2 (Model Inference):
|
Agent S2 (Model Inference):
|
||||||
jti: task-102 par: [task-101]
|
jti: task-102 pred:[task-101]
|
||||||
exec_act: run_inference
|
exec_act: run_inference
|
||||||
|
|
||||||
Agent S3 (Postprocessor):
|
Agent S3 (Postprocessor):
|
||||||
jti: task-103 par: [task-102]
|
jti: task-103 pred:[task-102]
|
||||||
exec_act: format_output
|
exec_act: format_output
|
||||||
~~~
|
~~~
|
||||||
{: #fig-internal title="Internal Microservice Workflow (L1)"}
|
{: #fig-internal title="Internal Microservice Workflow (L1)"}
|
||||||
@@ -1442,7 +1765,7 @@ than operational monitoring. OpenTelemetry data is typically
|
|||||||
controlled by the platform operator and can be modified or deleted
|
controlled by the platform operator and can be modified or deleted
|
||||||
without detection. ECTs and distributed traces are complementary:
|
without detection. ECTs and distributed traces are complementary:
|
||||||
traces provide observability while ECTs provide execution records.
|
traces provide observability while ECTs provide execution records.
|
||||||
ECTs may reference OpenTelemetry trace identifiers in the "ext"
|
ECTs may reference OpenTelemetry trace identifiers in the "ect_ext"
|
||||||
claim for correlation.
|
claim for correlation.
|
||||||
|
|
||||||
## W3C Provenance Data Model (PROV)
|
## W3C Provenance Data Model (PROV)
|
||||||
@@ -1452,7 +1775,7 @@ The W3C PROV Data Model defines an Entity-Activity-Agent ontology
|
|||||||
for representing provenance information. PROV's concepts map
|
for representing provenance information. PROV's concepts map
|
||||||
closely to ECT structures: PROV Activities correspond to ECT
|
closely to ECT structures: PROV Activities correspond to ECT
|
||||||
tasks, PROV Agents correspond to ECT-issuing agents, and PROV's
|
tasks, PROV Agents correspond to ECT-issuing agents, and PROV's
|
||||||
"wasInformedBy" relation corresponds to ECT "par" references.
|
"wasInformedBy" relation corresponds to ECT "pred" references.
|
||||||
However, PROV uses RDF/OWL ontologies designed for post-hoc
|
However, PROV uses RDF/OWL ontologies designed for post-hoc
|
||||||
documentation, while ECTs are runtime-embeddable JWT tokens with
|
documentation, while ECTs are runtime-embeddable JWT tokens with
|
||||||
cryptographic signatures. ECT audit data could be exported to
|
cryptographic signatures. ECT audit data could be exported to
|
||||||
@@ -1467,6 +1790,45 @@ ECTs and SCITT are complementary: the ECT "wid" claim can serve
|
|||||||
as a correlation identifier in SCITT Signed Statements, linking
|
as a correlation identifier in SCITT Signed Statements, linking
|
||||||
an ECT audit trail to a supply chain transparency record.
|
an ECT audit trail to a supply chain transparency record.
|
||||||
|
|
||||||
|
There is a notable parallel between SCITT's Transparency Service
|
||||||
|
and ECT's Level 3 audit ledger: both use append-only logs with
|
||||||
|
cryptographic commitment to provide tamper-evident recording.
|
||||||
|
SCITT Signed Statements use COSE for their envelope format while
|
||||||
|
ECTs use JOSE, but the architectural pattern — transparent,
|
||||||
|
verifiable recording of statements about artifacts or actions —
|
||||||
|
is shared. A deployment requiring L3 assurance could use a
|
||||||
|
SCITT Transparency Service as the audit ledger backend,
|
||||||
|
recording ECTs as supply chain statements about agent execution.
|
||||||
|
|
||||||
|
## RATS (Remote Attestation Procedures)
|
||||||
|
{:numbered="false"}
|
||||||
|
|
||||||
|
RATS {{RFC9334}} defines an architecture for conveying attestation
|
||||||
|
evidence about platform trustworthiness. RATS attests "is this
|
||||||
|
platform in a trustworthy state?" while ECTs record "what did
|
||||||
|
this agent do?" — both deal with claims about entities but at
|
||||||
|
different layers. RATS operates at the platform and firmware
|
||||||
|
layer, establishing that a workload's execution environment has
|
||||||
|
not been tampered with, whereas ECTs operate at the application
|
||||||
|
layer, recording the logical sequence of tasks performed by
|
||||||
|
agents. ECTs could complement RATS by recording execution
|
||||||
|
context on platforms whose trustworthiness has been established
|
||||||
|
through RATS attestation.
|
||||||
|
|
||||||
|
## Emerging Agent Protocol Frameworks
|
||||||
|
{:numbered="false"}
|
||||||
|
|
||||||
|
Several emerging frameworks address agent-to-agent communication,
|
||||||
|
including Google's Agent-to-Agent Protocol (A2A), Anthropic's
|
||||||
|
Model Context Protocol (MCP), and orchestration frameworks such
|
||||||
|
as LangChain and LangGraph. These frameworks primarily address
|
||||||
|
agent discovery, message routing, and tool invocation but do not
|
||||||
|
provide cryptographically verifiable execution records or DAG-based
|
||||||
|
audit trails. ECTs complement these frameworks by adding an
|
||||||
|
execution accountability layer: agents communicating via any of
|
||||||
|
these protocols can produce and verify ECTs to record what was
|
||||||
|
done, regardless of the communication mechanism used.
|
||||||
|
|
||||||
# Acknowledgments
|
# Acknowledgments
|
||||||
{:numbered="false"}
|
{:numbered="false"}
|
||||||
|
|
||||||
1186
master-prompt.md
1186
master-prompt.md
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ Suggestions that could make the implementations more robust, spec-strict, or pro
|
|||||||
## 1. **Spec alignment** ✅
|
## 1. **Spec alignment** ✅
|
||||||
|
|
||||||
- **ext size/depth (Section 4.2.7)**
|
- **ext size/depth (Section 4.2.7)**
|
||||||
**Done.** Both refimpls reject when serialized `ext` exceeds 4096 bytes or JSON depth exceeds 5 (`ValidateExt` / `validate_ext`). Used in create and verify.
|
**Done.** Both refimpls reject when serialized `ect_ext` exceeds 4096 bytes or JSON depth exceeds 5 (`ValidateExt` / `validate_ext`). Used in create and verify.
|
||||||
|
|
||||||
- **jti / wid format**
|
- **jti / wid format**
|
||||||
**Done.** Optional UUID (RFC 9562) validation: `CreateOptions.ValidateUUIDs` / `VerifyOptions.ValidateUUIDs` (Go), `validate_uuids` (Python). Helpers: `ValidUUID` / `valid_uuid`.
|
**Done.** Optional UUID (RFC 9562) validation: `CreateOptions.ValidateUUIDs` / `VerifyOptions.ValidateUUIDs` (Go), `validate_uuids` (Python). Helpers: `ValidUUID` / `valid_uuid`.
|
||||||
@@ -58,3 +58,18 @@ Suggestions that could make the implementations more robust, spec-strict, or pro
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Summary:** All listed improvements are implemented. For production, also consider: key rotation, WIT integration, and metrics around verify/create latency and error kinds.
|
**Summary:** All listed improvements are implemented. For production, also consider: key rotation, WIT integration, and metrics around verify/create latency and error kinds.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. **draft-01 migration** (NOT YET IMPLEMENTED)
|
||||||
|
|
||||||
|
The refimpl was built against draft-nennemann-wimse-ect-00. The -01 draft introduced breaking changes that need to be reflected:
|
||||||
|
|
||||||
|
- **Rename `par` to `pred`**: The predecessor claim was renamed. Update struct fields, JSON tags, serialization/deserialization, tests, and testdata.
|
||||||
|
- **Remove `pol` and `pol_decision`**: Policy claims were removed from the core spec. Deployments should use `ect_ext` for domain-specific claims like policy decisions.
|
||||||
|
- **Remove `sub`**: The `sub` claim is not part of the ECT specification. Remove from types and examples.
|
||||||
|
- **Update `typ` default**: Prefer `exec+jwt` over `wimse-exec+jwt`. Both must be accepted for backward compatibility.
|
||||||
|
- **Add L1 support**: The -01 draft introduces unsigned JSON ECTs (Level 1). The refimpl currently only supports L2 (signed JWS).
|
||||||
|
- **Add L3 support**: The -01 draft introduces audit ledger requirements for Level 3. The existing in-memory ledger needs hash chain and receipt support.
|
||||||
|
- **Update `MaxParLength` naming**: Rename to `MaxPredLength` to match the new claim name.
|
||||||
|
- **Update hash format**: The -01 draft specifies SHA-256 base64url without algorithm prefix (no `sha-256:` prefix), consistent with RFC 9449.
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
# WIMSE Execution Context Tokens — Reference Implementations
|
# WIMSE Execution Context Tokens — Reference Implementations
|
||||||
|
|
||||||
This directory contains **reference implementations** of [Execution Context Tokens (ECTs)](../draft-nennemann-wimse-execution-context-00.txt) for the WIMSE (Workload Identity in Multi System Environments) draft. Each refimpl provides ECT creation, verification, DAG validation, and an in-memory audit ledger.
|
> **Note**: These reference implementations were built against **draft-nennemann-wimse-ect-00**.
|
||||||
|
> The current draft (**-01**) introduced several claim name changes and structural updates:
|
||||||
|
>
|
||||||
|
> | -00 (refimpl) | -01 (current draft) | Notes |
|
||||||
|
> |---------------|---------------------|-------|
|
||||||
|
> | `par` | `pred` | Predecessor task IDs |
|
||||||
|
> | `pol`, `pol_decision` | removed (use `ect_ext`) | Policy claims moved to extension object |
|
||||||
|
> | `sub` | not defined | Standard JWT claim, not part of ECT spec |
|
||||||
|
> | `typ: wimse-exec+jwt` | `typ: exec+jwt` (preferred) | Both accepted for backward compat |
|
||||||
|
>
|
||||||
|
> The refimpl update to -01 is tracked in IMPROVEMENTS.md.
|
||||||
|
|
||||||
|
This directory contains **reference implementations** of Execution Context Tokens (ECTs) for the WIMSE (Workload Identity in Multi System Environments) draft. Each refimpl provides ECT creation, verification, DAG validation, and an in-memory audit ledger.
|
||||||
|
|
||||||
## Implementations
|
## Implementations
|
||||||
|
|
||||||
@@ -11,11 +23,11 @@ This directory contains **reference implementations** of [Execution Context Toke
|
|||||||
|
|
||||||
## Scope (all refimpls)
|
## Scope (all refimpls)
|
||||||
|
|
||||||
- **ECT format**: JWT (JWS Compact Serialization) with required/optional claims per the spec (Section 4).
|
- **ECT format**: JWT (JWS Compact Serialization) with required/optional claims per the spec.
|
||||||
- **Creation**: Build and sign ECTs with ES256; `kid` and `typ: wimse-exec+jwt` in the JOSE header.
|
- **Creation**: Build and sign ECTs with ES256; `kid` and `typ` in the JOSE header.
|
||||||
- **Verification**: Full Section 7 procedure (parse, typ/alg, key resolution, signature, claims, optional DAG).
|
- **Verification**: Full verification procedure (parse, typ/alg, key resolution, signature, claims, optional DAG).
|
||||||
- **DAG validation**: Section 6 (uniqueness, parent existence, temporal ordering, acyclicity, parent policy).
|
- **DAG validation**: Uniqueness, parent existence, temporal ordering, acyclicity, parent policy.
|
||||||
- **Ledger**: Interface plus in-memory append-only store (Section 9).
|
- **Ledger**: Interface plus in-memory append-only store.
|
||||||
|
|
||||||
No WIT/WPT issuance or full WIMSE stack; refimpls use key resolution only. Suitable for conformance testing and as a template for production integrations.
|
No WIT/WPT issuance or full WIMSE stack; refimpls use key resolution only. Suitable for conformance testing and as a template for production integrations.
|
||||||
|
|
||||||
@@ -41,8 +53,8 @@ python3 -m pytest tests/ -v
|
|||||||
|
|
||||||
## Specification
|
## Specification
|
||||||
|
|
||||||
- **Draft**: `draft-nennemann-wimse-execution-context-00`
|
- **Current draft**: `draft-nennemann-wimse-ect-01`
|
||||||
- **Sections**: 4 (format), 5 (HTTP header), 6 (DAG), 7 (verification), 9 (ledger interface).
|
- **Refimpl implements**: `-00` claim names (see migration note above)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user