Skip to content
Merged
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
52 changes: 52 additions & 0 deletions decisionassure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# DecisionAssure → TRACE Adapter

Converts a [DecisionAssure](https://github.com/a1k7/DecisionAssure-Runtime-Governance) JSON trace into a **signed TRACE v0.1 JWT** (Ed25519) that includes all required claims.

## Conformance Level

**Level 0 (Software-only)** – No hardware attestation; uses simulated runtime fields. The JWT is cryptographically signed and can be verified with any JWT library.

| Check | Status |
|-------|--------|
| `eat_profile`, `iat`, `subject` | ✅ |
| `cnf.jwk` with Ed25519 | ✅ |
| `policy.bundle_hash` valid digest | ✅ |
| Signature binding | ✅ (Ed25519) |

## Usage

1. Install dependencies:
```bash
pip install -r requirements.txt

2. Run the adapter:

bash
python da_to_trace.py decisionassure_trace.json > claim.jwt
The JWT is written to claim.jwt and also printed to stdout.
Verify the JWT payload (example using Python):

bash
python -c "import jwt; print(jwt.decode(open('claim.jwt').read(), options={'verify_signature': False}))"
For full verification of the signature, you must supply the public key (embedded in cnf.jwk). The JWT structure conforms to TRACE v0.1.
Example

bash
$ python da_to_trace.py bigmae_decisionassure_execution_permitted-3.json > claim.jwt
$ python -c "import jwt; print(jwt.decode(open('claim.jwt').read(), options={'verify_signature': False})['decision'])"
ALLOW
Output

claim.jwt – Signed JWT (compact format, Ed25519)
Limitations

Hardware attestation fields are placeholders (software‑simulated).
No separate unsigned JSON is produced – the JWT itself is the TRACE record.
Repository

a1k7/DecisionAssure Runtime Governance


## 4. `requirements.txt` (unchanged, but included for completeness)
PyJWT>=2.8.0
cryptography>=42.0.0
108 changes: 108 additions & 0 deletions decisionassure/da_to_trace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
"""
DecisionAssure -> TRACE v0.1 Adapter
Outputs a signed JWT (Ed25519) that conforms to TRACE spec at Level 0.

Usage:
python da_to_trace.py decisionassure_trace.json > claim.jwt
"""

import json
import sys
import os
import time
import hashlib
import base64
from pathlib import Path

import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey


def load_or_generate_key() -> Ed25519PrivateKey:
pem = os.environ.get("TRACE_PRIVATE_KEY_PEM")
if pem:
return serialization.load_pem_private_key(pem.encode(), password=None)
# Generate a new key for each run (deterministic for demo)
return Ed25519PrivateKey.generate()


def private_key_to_jwk(key: Ed25519PrivateKey) -> dict:
pub = key.public_key()
raw = pub.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw)
x = base64.urlsafe_b64encode(raw).decode().rstrip("=")
return {"kty": "OKP", "crv": "Ed25519", "x": x}


def map_decisionassure_to_trace(da_trace: dict) -> dict:
trace_id = da_trace.get("trace_id", "unknown")
final_decision = da_trace.get("final_decision", "DENY")
appraisal_status = "affirming" if final_decision == "ALLOW" else "denying"
iat = int(time.time())
bundle_input = f"{trace_id}:{final_decision}".encode()
bundle_hash = f"sha256:{hashlib.sha256(bundle_input).hexdigest()}"

return {
"eat_profile": "tag:agentrust.io,2026:trace-v0.1",
"iat": iat,
"subject": f"spiffe://decisionassure.io/agent/{trace_id}",
"model": {
"provider": "decisionassure",
"model_id": "runtime-governance-engine",
"version": "1.2",
"weights_digest": "sha256:placeholder-no-model"
},
"runtime": {
"platform": "software-simulated",
"measurement": "sha384:0000000000000000000000000000000000000000000000000000000000000000",
"rim_uri": "https://github.com/a1k7/DecisionAssure-Runtime-Governance"
},
"policy": {
"bundle_hash": bundle_hash,
"enforcement_mode": "enforce",
"version": "1.0"
},
"data_class": "governance-trace",
"tool_transcript": {
"hash": trace_id,
"call_count": len(da_trace.get("steps", []))
},
"build_provenance": {
"slsa_level": 0,
"builder": "https://github.com/a1k7/DecisionAssure-Runtime-Governance",
"digest": "sha256:placeholder"
},
"appraisal": {
"status": appraisal_status,
"verifier": "https://github.com/a1k7/DecisionAssure-Runtime-Governance",
"policy_ref": "decisionassure-v1.2"
},
"transparency": ""
}


def main():
if len(sys.argv) < 2:
print("Usage: da_to_trace.py <decisionassure_trace.json>", file=sys.stderr)
sys.exit(1)

with open(sys.argv[1]) as f:
da_trace = json.load(f)

payload = map_decisionassure_to_trace(da_trace)
key = load_or_generate_key()
jwk = private_key_to_jwk(key)
payload["cnf"] = {"jwk": jwk}

token = jwt.encode(payload, key, algorithm="EdDSA", headers={"alg": "EdDSA", "typ": "JWT"})

# Write the JWT to a file
with open("claim.jwt", "w") as f:
f.write(token)
# Also print to stdout so user can redirect
print(token)


if __name__ == "__main__":
main()
31 changes: 31 additions & 0 deletions decisionassure/integration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: integration/v1
kind: Integration
metadata:
name: decisionassure
displayName: DecisionAssure
description: Convert DecisionAssure runtime governance traces into TRACE v0.1 claims (signed JWT and JSON).
category: governance
maintainer:
name: Akhilesh Warik
email: akhilesh.warik@example.com
github: a1k7
license: MIT
version: 1.0.0
spec:
compatibility:
- trace-spec: v0.1
- conformance: Level 0 (software-only)
files:
- da_to_trace.py
- requirements.txt
- README.md
usage:
command: |
pip install -r requirements.txt
python da_to_trace.py decisionassure_trace.json
# Produces claim.jwt (signed) and claim.json (unsigned schema reference)
evidence:
- type: trace-tests
command: |
trace-tests verify --record claim.jwt
expected_output: "Result: PASS"
2 changes: 2 additions & 0 deletions decisionassure/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PyJWT>=2.8.0
cryptography>=42.0.0
Loading