Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,24 @@ jobs:
- name: Verify committed evidence artifacts
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
run: python validate_artifacts.py

embodied-action-receipts:
runs-on: ubuntu-latest
defaults:
run:
working-directory: embodied-action-receipts
steps:
- uses: actions/checkout@v4

- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: embodied-action-receipts/requirements.txt

- name: Install dependencies
run: python -m pip install -r requirements.txt

- name: Verify embodied-action receipt fixtures
run: python -m unittest discover -s tests -v
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ End-to-end integration examples showing cMCP, Agent Manifest, and TRACE working

| Example | What it shows | Platform | Compliance |
|---|---|---|---|
| `embodied-action-receipts/` | Fixture-style offline verification for embodied action receipts: accepted chain, missing receipt, signature mismatch and valid controller rejection | Software-only fixtures | TRACE action-receipt evidence boundary |
| `financial-services/` | Credit risk agent: MiFID II escalation deny above EUR 500k with structured policy advice | SEV-SNP / TDX | EU AI Act Art. 9/12, MiFID II Art. 25, DORA Art. 9 |
| `healthcare/` | Clinical decision agent: EU AI Act Art. 14 HITL deny on high-risk treatment plans | SEV-SNP / TDX | EU AI Act Art. 14, HIPAA |
| `industrial-embodied-ai/` | Material-movement agent with cMCP authorization, an independent safety-controller boundary and offline-verifiable closed-session evidence | TEE / software-only development mode | OT security and industrial robot safety references |
Expand Down
62 changes: 62 additions & 0 deletions embodied-action-receipts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Embodied Action Receipt Fixtures

Fixture-style example for offline verification of embodied-action receipts.

This example complements the cMCP Embodied Action Evidence Profile and the TRACE
`verification.action_receipts` axis. It demonstrates action-level evidence below
a session-level TRACE claim without claiming physical completion, controller
safety, or functional-safety certification.

Related design threads:

- cMCP Embodied Action Evidence Profile: agentrust-io/cmcp#339
- TRACE action-receipt verification axis: agentrust-io/trace-spec#66

## What It Shows

The fixtures cover four verifier outcomes:

| Fixture | Expected result | What it demonstrates |
|---|---|---|
| `valid-chain.json` | `accepted` | A signed, hash-chained controller receipt sequence binds to the TRACE session, cMCP call id, and action reference. |
| `missing-receipt.json` | `missing` | `verification.action_receipts: required` fails when no action receipt is attached. |
| `signature-mismatch.json` | `invalid` | A receipt with a bad Ed25519 signature is rejected. |
| `controller-rejected.json` | `rejected` | A valid signed receipt can prove controller rejection; rejection is evidence, not a verifier failure. |

## Boundary

For embodied AI, `verification.action_receipts: required` means every externally
consequential action has offline-verifiable receipt evidence bound to the
session or cMCP audit `call_id`.

It does not mean TRACE proves:

- physical completion;
- controller safety;
- functional-safety certification;
- that the real world changed as intended.

## Run

```bash
cd embodied-action-receipts
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python -m unittest discover -s tests -v
```

Verify one fixture manually:

```bash
python verify_receipts.py fixtures/valid-chain.json
```

Regenerate fixtures from the deterministic test key:

```bash
python generate_fixtures.py
```

The deterministic signing seed is public test material. It is only used to make
the committed fixtures reproducible and must never be used in production.
41 changes: 41 additions & 0 deletions embodied-action-receipts/fixtures/controller-rejected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"action": {
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"action_scope": "robot-cell-7/material-bin-a",
"action_timestamp": "2026-06-25T16:30:00Z",
"action_type": "move_material",
"agent_id": "spiffe://factory.example/agent/material-movement/dev"
},
"case": "controller-rejected",
"expected": {
"receipt_state": "rejected",
"result": "valid"
},
"note": "A valid rejected receipt is evidence of controller rejection, not physical completion.",
"receipts": [
{
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"call_id": "call-material-move-001",
"issuer": "spiffe://factory.example/controller/robot-cell-7",
"issuer_key_id": "robot-cell-7-controller",
"observed_at": "2026-06-25T16:30:02Z",
"prev_receipt_hash": null,
"reason": "human_detected_in_safeguarded_area",
"receipt_id": "receipt-001",
"sequence": 1,
"signature": "ed25519:FvPr51RvrY9iSnUPGlTw_4dRRK8b5c7X8shDFzcaZ6hmiVoFu3m0fsWEjuSsTXi2DNbQ5NutMFZ6z8JHHSbjBQ",
"terminal_state": "controller_rejected",
"trace_id": "trace-session-embodied-001",
"type": "embodied.action_receipt.v0",
"verdict": "rejected"
}
],
"trace": {
"cmcp_call_id": "call-material-move-001",
"policy_decision": "allow",
"trace_id": "trace-session-embodied-001",
"verification": {
"action_receipts": "required"
}
}
}
23 changes: 23 additions & 0 deletions embodied-action-receipts/fixtures/missing-receipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"action": {
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"action_scope": "robot-cell-7/material-bin-a",
"action_timestamp": "2026-06-25T16:30:00Z",
"action_type": "move_material",
"agent_id": "spiffe://factory.example/agent/material-movement/dev"
},
"case": "missing-receipt",
"expected": {
"receipt_state": "missing",
"result": "invalid"
},
"receipts": [],
"trace": {
"cmcp_call_id": "call-material-move-001",
"policy_decision": "allow",
"trace_id": "trace-session-embodied-001",
"verification": {
"action_receipts": "required"
}
}
}
54 changes: 54 additions & 0 deletions embodied-action-receipts/fixtures/signature-mismatch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"action": {
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"action_scope": "robot-cell-7/material-bin-a",
"action_timestamp": "2026-06-25T16:30:00Z",
"action_type": "move_material",
"agent_id": "spiffe://factory.example/agent/material-movement/dev"
},
"case": "signature-mismatch",
"expected": {
"receipt_state": "invalid_signature",
"result": "invalid"
},
"receipts": [
{
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"call_id": "call-material-move-001",
"issuer": "spiffe://factory.example/controller/robot-cell-7",
"issuer_key_id": "robot-cell-7-controller",
"observed_at": "2026-06-25T16:30:01Z",
"prev_receipt_hash": null,
"receipt_id": "receipt-001",
"sequence": 1,
"signature": "ed25519:GqkLo5j8ZJzjOGwyv8hzS8vdgaYr_1VAZtdgoNTyjMU0NDuCAXK0oDiC2TTz2raMdXy7KiOoWlr4LgBDzWlGDA",
"terminal_state": "handoff_accepted",
"trace_id": "trace-session-embodied-001",
"type": "embodied.action_receipt.v0",
"verdict": "accepted"
},
{
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"call_id": "call-material-move-001",
"issuer": "spiffe://factory.example/controller/robot-cell-7",
"issuer_key_id": "robot-cell-7-controller",
"observed_at": "2026-06-25T16:30:05Z",
"prev_receipt_hash": "sha256:997a9dd7abb8e6a32bab079da314b62bf867605428f7920e91f2a806db1cd338",
"receipt_id": "receipt-002",
"sequence": 2,
"signature": "ed25519:RdJXHXzttRHLqKm6ockpPAU5-Odc3mZuEwzw4wNZRlm-QNPiQTvp2_LJ33TWqquhebJ9PFaq0SS4UEBW3G7bAQ",
"terminal_state": "controller_completed",
"trace_id": "trace-session-embodied-001",
"type": "embodied.action_receipt.v0",
"verdict": "accepted"
}
],
"trace": {
"cmcp_call_id": "call-material-move-001",
"policy_decision": "allow",
"trace_id": "trace-session-embodied-001",
"verification": {
"action_receipts": "required"
}
}
}
54 changes: 54 additions & 0 deletions embodied-action-receipts/fixtures/valid-chain.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"action": {
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"action_scope": "robot-cell-7/material-bin-a",
"action_timestamp": "2026-06-25T16:30:00Z",
"action_type": "move_material",
"agent_id": "spiffe://factory.example/agent/material-movement/dev"
},
"case": "valid-chain",
"expected": {
"receipt_state": "accepted",
"result": "valid"
},
"receipts": [
{
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"call_id": "call-material-move-001",
"issuer": "spiffe://factory.example/controller/robot-cell-7",
"issuer_key_id": "robot-cell-7-controller",
"observed_at": "2026-06-25T16:30:01Z",
"prev_receipt_hash": null,
"receipt_id": "receipt-001",
"sequence": 1,
"signature": "ed25519:GqkLo5j8ZJzjOGwyv8hzS8vdgaYr_1VAZtdgoNTyjMU0NDuCAXK0oDiC2TTz2raMdXy7KiOoWlr4LgBDzWlGDw",
"terminal_state": "handoff_accepted",
"trace_id": "trace-session-embodied-001",
"type": "embodied.action_receipt.v0",
"verdict": "accepted"
},
{
"action_ref": "sha256:6572d6707269d815b6f59aadeca709e29a5a7d73330265f2b5feb92d0290b21f",
"call_id": "call-material-move-001",
"issuer": "spiffe://factory.example/controller/robot-cell-7",
"issuer_key_id": "robot-cell-7-controller",
"observed_at": "2026-06-25T16:30:05Z",
"prev_receipt_hash": "sha256:997a9dd7abb8e6a32bab079da314b62bf867605428f7920e91f2a806db1cd338",
"receipt_id": "receipt-002",
"sequence": 2,
"signature": "ed25519:RdJXHXzttRHLqKm6ockpPAU5-Odc3mZuEwzw4wNZRlm-QNPiQTvp2_LJ33TWqquhebJ9PFaq0SS4UEBW3G7bAQ",
"terminal_state": "controller_completed",
"trace_id": "trace-session-embodied-001",
"type": "embodied.action_receipt.v0",
"verdict": "accepted"
}
],
"trace": {
"cmcp_call_id": "call-material-move-001",
"policy_decision": "allow",
"trace_id": "trace-session-embodied-001",
"verification": {
"action_receipts": "required"
}
}
}
Loading
Loading