Draft improvements: - Rename ext -> ect_ext, clarify iss/aud requirements per level - Add algorithm agility guidance and RFC 8725 reference - Add HTTP header size constraints and body transport fallback - Add cross-level parent reference semantics - Add emerging agent protocols (A2A, MCP) to Related Work - Fix HTTP error handling (403 not 401), IANA +jwt suffix note - Add workflow consistency check to DAG validation - Add defense-in-depth note for acyclicity check Supporting files: - Fix blog post outdated claim names (par -> pred, ext -> ect_ext) - Update refimpl README with -00 vs -01 migration mapping - Add refimpl IMPROVEMENTS.md section 6 with -01 migration tasks
3.9 KiB
Possible Improvements (Go & Python Refimpls)
Suggestions that could make the implementations more robust, spec-strict, or production-friendly. All items below have been implemented in both refimpls unless noted.
1. Spec alignment ✅
-
ext size/depth (Section 4.2.7)
Done. Both refimpls reject when serializedect_extexceeds 4096 bytes or JSON depth exceeds 5 (ValidateExt/validate_ext). Used in create and verify. -
jti / wid format
Done. Optional UUID (RFC 9562) validation:CreateOptions.ValidateUUIDs/VerifyOptions.ValidateUUIDs(Go),validate_uuids(Python). Helpers:ValidUUID/valid_uuid.
2. API and safety ✅
-
Payload mutation in Create
Done. Documented in both: Create may set Iat, Exp, Sub, Par when zero/nil. Go: comment onCreate(); Python: create works on a deep copy so the caller’s payload is not modified. -
Structured errors (Go)
Done. Sentinel errors inect/errors.go:ErrExpired,ErrReplay,ErrInvalidSignature(wrapped),ErrInvalidTyp,ErrPolPolDecisionPair, etc. Verify and create return these where applicable.
3. Production / operations ✅
-
Replay cache
Done. Documented: JTICache is in-memory; for multi-instance deployments a shared store (Redis, DB) is required. See refimpl README and go-lang/README “Replay cache (multi-instance)”. -
Observability
Done. Go:VerifyOptions.LogVerify func(jti string, err error)called after each verify. Python:VerifyOptions.on_verify_attempt(jti, err)callback.
4. Small cleanups ✅
-
Python Ledger docstring
Done. “Lookup by task id (jti)”. -
Python
verify
Done. Documented thatparmay be set to[]when missing;from_claimsalready supplies[], so mutation is defensive only. -
par length
Done. Go:CreateOptions.MaxParLength,VerifyOptions.MaxParLength,DAGConfig.MaxParLength(0 = no limit; default 100 in DAG). Python:CreateOptions.max_par_length,VerifyOptions.max_par_length,DAGConfig.max_par_length.
5. Nice-to-have ✅
-
inp_hash / out_hash format
Done. Optional check in create and verify:algorithm:base64urlwith algorithm in allowlist (sha-256, sha-384, sha-512). Helpers:ValidateHashFormat/validate_hash_format. -
Constant-time comparison
Done. Go:crypto/subtle.ConstantTimeComparefortypin verify. Python:hmac.compare_digestfortyp.
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
partopred: The predecessor claim was renamed. Update struct fields, JSON tags, serialization/deserialization, tests, and testdata. - Remove
polandpol_decision: Policy claims were removed from the core spec. Deployments should useect_extfor domain-specific claims like policy decisions. - Remove
sub: Thesubclaim is not part of the ECT specification. Remove from types and examples. - Update
typdefault: Preferexec+jwtoverwimse-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
MaxParLengthnaming: Rename toMaxPredLengthto 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.