- ect library: create, verify, DAG validation, ledger interface - In-memory ledger and ECTStore for full ledger mode - Test vectors and unit tests; two-agent demo (cmd/demo) - README: document refimpl scope and usage Co-authored-by: Cursor <cursoragent@cursor.com>
98 lines
3.2 KiB
Markdown
98 lines
3.2 KiB
Markdown
# WIMSE Execution Context Tokens — Reference Implementation
|
|
|
|
This directory contains a **reference implementation** of [Execution Context Tokens (ECTs)](../draft-nennemann-wimse-execution-context-00.txt) for the WIMSE (Workload Identity in Multi System Environments) draft. It implements ECT creation, verification, DAG validation, and an in-memory audit ledger.
|
|
|
|
## Scope
|
|
|
|
- **ECT format**: JWT (JWS Compact Serialization) with required/optional claims per the spec (Section 4).
|
|
- **Creation**: Build and sign ECTs with ES256; `kid` and `typ: wimse-exec+jwt` in the JOSE header.
|
|
- **Verification**: Full Section 7 procedure (parse, typ/alg, key resolution, signature, claims, optional DAG).
|
|
- **DAG validation**: Section 6 (uniqueness, parent existence, temporal ordering, acyclicity, parent policy).
|
|
- **Ledger**: Interface plus in-memory append-only store (Section 9).
|
|
|
|
No WIT/WPT issuance or full WIMSE stack; the refimpl uses key resolution only. Suitable for conformance testing and as a template for production integrations.
|
|
|
|
## Layout
|
|
|
|
```
|
|
refimpl/
|
|
├── go.mod
|
|
├── README.md
|
|
├── ect/ # library
|
|
│ ├── types.go # Payload, Audience, constants
|
|
│ ├── audience.go # aud marshal/unmarshal
|
|
│ ├── create.go # Create(), GenerateKey()
|
|
│ ├── verify.go # Parse(), Verify(), VerifyOptions
|
|
│ ├── dag.go # ValidateDAG(), ECTStore
|
|
│ ├── ledger.go # Ledger, MemoryLedger
|
|
│ └── *_test.go
|
|
├── testdata/
|
|
│ └── valid_root_ect_payload.json
|
|
└── cmd/
|
|
└── demo/ # two-agent workflow demo
|
|
└── main.go
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Library
|
|
|
|
```go
|
|
import "github.com/nennemann/ect-refimpl/ect"
|
|
|
|
// Create
|
|
key, _ := ect.GenerateKey()
|
|
payload := &ect.Payload{
|
|
Iss: "spiffe://example.com/agent/a",
|
|
Aud: ect.Audience{"spiffe://example.com/agent/b"},
|
|
Iat: time.Now().Unix(),
|
|
Exp: time.Now().Add(10*time.Minute).Unix(),
|
|
Jti: "uuid-...",
|
|
Tid: "task-001",
|
|
ExecAct: "review_spec",
|
|
Par: []string{},
|
|
Pol: "policy_v1",
|
|
PolDecision: ect.PolDecisionApproved,
|
|
}
|
|
compact, err := ect.Create(payload, key, ect.CreateOptions{KeyID: "agent-a-key"})
|
|
|
|
// Verify (with DAG store)
|
|
store := ect.NewMemoryLedger()
|
|
resolver := func(kid string) (*ecdsa.PublicKey, error) { ... }
|
|
parsed, err := ect.Verify(compact, ect.VerifyOptions{
|
|
VerifierID: "spiffe://example.com/agent/b",
|
|
ResolveKey: resolver,
|
|
Store: store,
|
|
})
|
|
store.Append(compact, parsed.Payload)
|
|
```
|
|
|
|
### Demo
|
|
|
|
From the repo root (or `refimpl/`):
|
|
|
|
```bash
|
|
cd refimpl && go run ./cmd/demo
|
|
```
|
|
|
|
Runs a two-agent flow: Agent A issues a root ECT, Agent B verifies and appends it, then issues a child ECT; verification uses DAG validation against the ledger.
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
cd refimpl && go test ./...
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
- [go-jose/v4](https://github.com/go-jose/go-jose/v4) for JWS (ES256) and JWK handling. No custom crypto.
|
|
|
|
## Specification
|
|
|
|
- **Draft**: `draft-nennemann-wimse-execution-context-00`
|
|
- **Sections**: 4 (format), 5 (HTTP header), 6 (DAG), 7 (verification), 9 (ledger interface).
|
|
|
|
## License
|
|
|
|
Same as the Internet-Draft (IETF Trust). Code components under Revised BSD per BCP 78/79.
|