Skill: schchit/jep-guard-audit (version 1.0.0)

--- name: jep-guard-audit version: 1.0.0 description: JEP-Guard Audit Skill — Strict JEP-04/JAC-01 Compliant Audit Chain with Friendly API Layer author: Cognitive Emergence Lab <[REDACTED_SECRET]> license: MIT protocol: JEP tags: - jep - jac - audit - compliance - ai-act - guard - accountability entrypoint: skill.api:app host_targets: - mcp - api - python skills: - name: audit_ingest description: Ingest developer-friendly events; internally converts to strict JEP-04/JAC-01 input_schema: type: object properties: session_id: type: string events: type: array items: type: object properties: event_id: type: string primitive: type: string enum: [J, D, T, V] issuer: type: string timestamp: type: string target: type: string assertion: type: object delegate_to: type: string terminate_of: type: string verify_of: type: array items: type: string verification_result: type: string confidence: type: number prev_event_id: type: string parent_task_hash: type: string signature: type: string required: [session_id, events] output_schema: type: object properties: session_id: type: string events_ingested: type: integer status: type: string - name: audit_chain description: Retrieve strict JEP-04 audit chain with integrity verification input_schema: type: object properties: session_id: type: string required: [session_id] output_schema: type: object properties: session_id: type: string chain_valid: type: boolean total_events: type: integer violation_count: type: integer warning_count: type: integer links: type: array items: type: object - name: audit_export description: Export regulatory compliance report (eu_ai_act, us_california, us_colorado, generic) input_schema: type: object properties: session_id: type: string standard: type: string enum: [generic, eu_ai_act, us_california, us_colorado] required: [session_id, standard] output_schema: type: object properties: report_id: type: string standard: type: string chain_summary: type: object findings: type: array recommendations: type: array raw_data: type: string --- # JEP-Guard Audit Skill **Strict JEP-04 / JAC-01 Compliant Audit Chain** ## Architecture Three-layer design: 1. **GuardSkill** — Friendly API (`issuer`, `assertion`, `target`) 2. **JEPAdapter** — Maps friendly fields to strict JEP-04 3. **JEPCodec** — Strict protocol implementation (`jep`, `verb`, `who`, `when`, `what`, `nonce`, `aud`, `ref`, `sig`) ## Protocol Alignment | JEP-04 Field | API Field | Notes | |--------------|-----------|-------| | `jep` | (auto) | Fixed to "1" | | `verb` | `primitive` | J/D/T/V | | `who` | `issuer` | Actor DID | | `when` | `timestamp` | ISO → Unix seconds | | `what` | `assertion` | SHA-256 multihash | | `nonce` | (auto) | UUIDv4 | | `aud` | `target` | Recipient | | `ref` | `prev_event_id` / `verify_of` | Chain link | | `sig` | `signature` | JWS | | `task_based_on` | `parent_task_hash` | JAC-01 causality | ## Compliance Standards - **EU AI Act** — Article 12 record-keeping, 6-year retention - **California SB 1047** — 72-hour critical incident reporting - **Colorado SB 205** — Algorithmic impact assessment + appeal logs - **Generic JEP-01** — Baseline accountability tracing --- Cognitive Emergence Lab [REDACTED_SECRET]

path: jep-guard-audit-skill/CHANGELOG.md
content: # Changelog

## [1.0.0] - 2026-04-26

### Added
- Three-layer architecture:
  - **JEPCodec** (Protocol Layer): Strict JEP-04 canonicalization (RFC 8785), SHA-256 multihash `what` field (RFC 9122), UUIDv4 nonce generation (RFC 9562), Unix timestamp handling, ±5min clock skew verification.
  - **JEPAdapter** (Mapping Layer): FriendlyEvent → JEP04Event conversion. Maps `issuer`→`who`, `assertion`→`what` multihash, `timestamp`→Unix `when`, `target`→`aud`, `verify_of`/`prev_event_id`→`ref`, `parent_task_hash`→`task_based_on` (JAC-01). Auto-generates `nonce`. Injects JAC extensions (result, assign, fault).
  - **GuardSkill** (API Layer): FastAPI endpoints `/audit/ingest`, `/audit/chain/{session_id}`, `/audit/export`. Consumes friendly fields; returns strict JEP-04 chain inspection.
- JAC-01 compliance: `task_based_on` parent judgment verification, JAC-Fault extension for orphan terminations, JAC-Result extension for confidence/verification_result.
- Five violation detection rules (R001–R005) plus protocol-level integrity checks (nonce uniqueness, timestamp window, hash chain continuity, JAC parent existence).
- Compliance export engine: EU AI Act (2024/1689), California SB 1047, Colorado SB 205, Generic JEP-01.
- Example: `strict_protocol_demo.py` demonstrating all three layers.
- Tests: 7 unit tests covering canonicalization, multihash, adapter roundtrip, valid chain, missing verification, orphan termination, generic export.

### References
- Wang, Y. (2026). *JEP: Judgment Event Protocol* (draft-wang-jep-judgment-event-protocol-04).
- Wang, Y. (2026). *JAC: Judgment Accountability Chain* (draft-wang-jac-01).


path: jep-guard-audit-skill/manifest.json
content: {
  "name": "jep-guard-audit",
  "version": "1.0.0",
  "description": "JEP-Guard Audit Skill — Strict JEP-04/JAC-01 Compliant Audit Chain with Friendly API Layer",
  "author": "Cognitive Emergence Lab <[REDACTED_SECRET]>",
  "license": "MIT",
  "protocol": "JEP",
  "entrypoint": "skill.api:app",
  "host_targets": [
    "mcp",
    "api",
    "python"
  ],
  "dependencies": [
    "fastapi>=0.104.0",
    "uvicorn>=0.24.0",
    "pydantic>=2.5.0"
  ],
  "tags": [
    "jep",
    "jac",
    "audit",
    "compliance",
    "ai-act",
    "guard",
    "accountability"
  ]
}

path: jep-guard-audit-skill/README.md
content: # JEP-Guard Audit Skill v1.0.0

**Strict JEP-04 / JAC-01 Compliant Audit Chain** with Friendly API Layer.

Based on:
- **JEP-04**: *Judgment Event Protocol* (draft-wang-jep-judgment-event-protocol-04)
- **JAC-01**: *Judgment Accountability Chain* (draft-wang-jac-01)

## Three-Layer Architecture

```
GuardSkill (API Layer)        — Friendly fields: issuer, assertion, target
        ↓
JEPAdapter (Mapping Layer)    — Maps friendly fields to strict JEP-04
        ↓
JEPCodec (Protocol Layer)     — Strict jep/verb/who/when/what/nonce/aud/ref/sig
```

## What It Does

| Feature | Description |
|---------|-------------|
| **Auto-Intercept** | Ingests FriendlyEvents; internally converts to strict JEP-04 |
| **Hash Chain** | SHA-256 linked audit chain with per-event integrity verification |
| **Nonce Enforcement** | UUIDv4 anti-replay per JEP-04 Section 2.3 |
| **Timestamp Window** | ±5 minute clock skew tolerance per JEP-04 |
| **JAC-01 Chain** | `task_based_on` parent judgment verification + fault extension support |
| **Violation Detection** | R001–R005 rules + protocol-level integrity checks |
| **Compliance Export** | EU AI Act / CA SB 1047 / CO SB 205 / Generic JEP-01 |

## Quick Start

```bash
pip install -r requirements.txt
uvicorn skill.api:app --host 0.0.0.0 --port 8000
```

## API

### Ingest

```bash
curl -X POST http://localhost:8000/audit/ingest   -H "Content-Type: application/json"   -d '{
    "session_id": "loan-001",
    "events": [
      {
        "event_id": "evt-1",
        "primitive": "J",
        "issuer": "did:example:agent-001",
        "timestamp": "2026-04-26T09:00:00Z",
        "target": "loan-decision",
        "assertion": {"subject": "app_123", "predicate": "approval", "value": "approved"},
        "confidence": 0.92,
        "signature": "sig..."
      }
    ]
  }'
```

### Chain Inspection

```bash
curl http://localhost:8000/audit/chain/loan-001
```

### Compliance Export

```bash
curl -X POST http://localhost:8000/audit/export   -H "Content-Type: application/json"   -d '{"session_id": "loan-001", "standard": "eu_ai_act"}'
```

## Violation Rules

| ID | Severity | Trigger |
|----|----------|---------|
| R001 | WARNING | Judge without subsequent Verify |
| R002 | VIOLATION | Delegate without prior J/V from same issuer |
| R003 | VIOLATION | Terminate referencing non-existent event |
| R004 | CRITICAL | Hash chain break (ref mismatch) |
| R005 | VIOLATION | Verify referencing non-existent Judge |

## Protocol Alignment

| JEP-04 Field | Guard API Field | Mapping |
|--------------|-----------------|---------|
| `jep` | (auto) | Fixed to "1" |
| `verb` | `primitive` | J/D/T/V |
| `who` | `issuer` | Actor DID |
| `when` | `timestamp` | ISO → Unix seconds |
| `what` | `assertion` | SHA-256 multihash of assertion |
| `nonce` | (auto) | UUIDv4 generated |
| `aud` | `target` | Intended recipient |
| `ref` | `prev_event_id` / `verify_of` | Chain link |
| `sig` | `signature` | JWS signature |
| `task_based_on` | `parent_task_hash` | JAC-01 causality |

## Example

```bash
cd examples
python strict_protocol_demo.py
```

---

Cognitive Emergence Lab  
[REDACTED_SECRET]


path: jep-guard-audit-skill/requirements.txt
content: fastapi>=0.104.0
uvicorn>=0.24.0
pydantic>=2.5.0


path: jep-guard-audit-skill/tests/test_three_layer.py
content: """
Three-Layer Architecture Unit Tests
Tests JEPCodec (strict), JEPAdapter (mapping), and AuditEngine (business logic).
Run: pytest tests/test_three_layer.py
"""
import sys
sys.path.insert(0, "..")

from skill.codec import JEPCodec
from skill.adapter import JEPAdapter
from skill.core import AuditEngine
from skill.types import FriendlyEvent, Verb, ComplianceStandard


def test_jep_codec_canonicalization():
    """JEPCodec.encode must produce deterministic canonical JSON."""
    from skill.types import JEP04Event
    evt = JEP04Event(
        jep="1", verb=Verb.JUDGE, who="did:example:a", when=1000,
        what="sha256:abc", nonce="uuid-1", aud="platform", ref=None, sig="sig"
    )
    c1 = JEPCodec.encode(evt)
    c2 = JEPCodec.encode(evt)
    assert c1 == c2, "Canonicalization must be deterministic"
    assert '"jep":"1"' in c1
    assert '"verb":"J"' in c1


def test_jep_codec_what_computation():
    """JEPCodec.compute_what must produce sha256: prefix multihash."""
    payload = {"subject": "x", "predicate": "y", "value": 1}
    what = JEPCodec.compute_what(payload)
    assert what.startswith("sha256:")
    assert len(what) == 64 + 7  # prefix + 64 hex chars


def test_jep_adapter_roundtrip():
    """JEPAdapter.to_jep04 must map all friendly fields correctly."""
    fe = FriendlyEvent(
        event_id="evt-1", primitive="J", issuer="agent-a",
        timestamp="2026-04-26T10:00:00Z", target="t1",
        assertion={"s": "x", "p": "y", "v": 1},
        confidence=0.9, prev_event_id=None, parent_task_hash="parent-1",
        signature="sig-1"
    )
    jep = JEPAdapter.to_jep04(fe)
    assert jep.jep == "1"
    assert jep.verb == Verb.JUDGE
    assert jep.who == "agent-a"
    assert jep.when == 1745661600  # Unix seconds for 2026-04-26T10:00:00Z
    assert jep.aud == "t1"
    assert jep.task_based_on == "parent-1"
    assert jep.sig == "sig-1"
    assert jep.nonce != ""  # Auto-generated UUIDv4
    assert jep.what is not None  # Computed from assertion


def test_audit_engine_valid_chain():
    """Two events with correct ref -> valid chain."""
    engine = AuditEngine()
    session = "test-1"
    engine.ingest(session, FriendlyEvent(
        event_id="a", primitive="J", issuer="agent", timestamp="2026-04-26T10:00:00Z",
        target="t", assertion={"s": "x", "p": "y", "v": 1}, signature="sig-a"
    ))
    engine.ingest(session, FriendlyEvent(
        event_id="b", primitive="V", issuer="auditor", timestamp="2026-04-26T10:00:05Z",
        target="t", verify_of=["a"], verification_result="confirmed", signature="sig-b"
    ))
    chain = engine.build_chain(session)
    assert chain.chain_valid is True
    assert chain.violation_count == 0


def test_audit_engine_missing_verification():
    """Judge without Verify -> R001 WARNING."""
    engine = AuditEngine()
    session = "test-2"
    engine.ingest(session, FriendlyEvent(
        event_id="a", primitive="J", issuer="agent", timestamp="2026-04-26T10:00:00Z",
        target="t", assertion={"s": "x", "p": "y", "v": 1}, signature="sig"
    ))
    chain = engine.build_chain(session)
    assert chain.warning_count >= 1
    assert any("R001" in v for v in chain.links[0].violations)


def test_audit_engine_orphan_termination():
    """Terminate referencing non-existent -> R003 VIOLATION."""
    engine = AuditEngine()
    session = "test-3"
    engine.ingest(session, FriendlyEvent(
        event_id="a", primitive="J", issuer="agent", timestamp="2026-04-26T10:00:00Z",
        target="t", assertion={"s": "x", "p": "y", "v": 1}, signature="sig"
    ))
    engine.ingest(session, FriendlyEvent(
        event_id="b", primitive="T", issuer="agent", timestamp="2026-04-26T10:00:05Z",
        target="t", terminate_of="nonexistent", prev_event_id="a", signature="sig"
    ))
    chain = engine.build_chain(session)
    assert chain.violation_count >= 1
    assert any("R003" in v for v in chain.links[1].violations)


def test_compliance_export_generic():
    """Generic export must contain JEP-04 fields."""
    engine = AuditEngine()
    session = "test-4"
    engine.ingest(session, FriendlyEvent(
        event_id="a", primitive="J", issuer="agent", timestamp="2026-04-26T10:00:00Z",
        target="t", assertion={"s": "x"}, signature="sig"
    ))
    report = engine.export_compliance(session, ComplianceStandard.GENERIC)
    assert report.standard == ComplianceStandard.GENERIC
    assert "JEP-04" in report.raw_data
    assert "JAC-01" in report.raw_data


if __name__ == "__main__":
    test_jep_codec_canonicalization()
    test_jep_codec_what_computation()
    test_jep_adapter_roundtrip()
    test_audit_engine_valid_chain()
    test_audit_engine_missing_verification()
    test_audit_engine_orphan_termination()
    test_compliance_export_generic()
    print("All 7 tests passed.")


path: jep-guard-audit-skill/skill/adapter.py
content: """
JEPAdapter — Mapping Layer
Converts developer-friendly FriendlyEvent fields to strict JEP04Event fields.

Friendly Field          -> JEP-04 Field       -> JAC-01 Field
-----------------------    ------------------    ------------------
event_id                 -> nonce (UUIDv4)
primitive (J/D/T/V)      -> verb
issuer                   -> who
timestamp (ISO)          -> when (Unix)
target                   -> aud (or into what)
assertion (dict)         -> what (multihash)
delegate_to              -> what (multihash) + extensions
terminate_of             -> what (multihash)
verify_of (list)         -> ref
verification_result      -> extensions[JAC-Result]
confidence               -> extensions[JAC-Result]
prev_event_id            -> ref
parent_task_hash         -> task_based_on
signature                -> sig
extensions               -> extensions
"""
from typing import Any, Dict, Optional

from .types import FriendlyEvent, JEP04Event, Verb
from .codec import JEPCodec


class JEPAdapter:
    """
    One-way adapter: FriendlyEvent -> JEP04Event.
    Zero business logic. Pure field mapping + canonicalization.
    """

    @staticmethod
    def to_jep04(friendly: FriendlyEvent) -> JEP04Event:
        """
        Convert a FriendlyEvent to a strict JEP04Event.
        Automatically generates nonce, computes what multihash, converts timestamps.
        """
        # Map primitive to verb
        verb = Verb(friendly.primitive)

        # Convert ISO timestamp to Unix seconds
        when = JEPCodec.iso_to_unix(friendly.timestamp)

        # Generate UUIDv4 nonce from event_id (or fresh if not UUID)
        nonce = JEPCodec.generate_nonce()

        # Compute 'what' multihash from assertion payload
        what_payload = JEPAdapter._build_what_payload(friendly, verb)
        what = JEPCodec.compute_what(what_payload) if what_payload else None

        # Map verify_of -> ref (JEP-04 ref points to related event hash/ID)
        ref = None
        if friendly.verify_of and len(friendly.verify_of) > 0:
            ref = friendly.verify_of[0]  # Primary reference
        elif friendly.prev_event_id:
            ref = friendly.prev_event_id

        # Assemble extensions
        extensions = friendly.extensions or {}

        # JAC-01 Result extension: verification_result + confidence
        if friendly.verification_result is not None or friendly.confidence is not None:
            jac_result = {}
            if friendly.verification_result:
                jac_result["verification_result"] = friendly.verification_result
            if friendly.confidence is not None:
                jac_result["confidence"] = friendly.confidence
            extensions["https://jac.org/result"] = jac_result

        # JAC-01 Assign extension: delegate_to
        if friendly.delegate_to:
            extensions["https://jac.org/assign"] = {
                "assignee": friendly.delegate_to,
                "assigner": friendly.issuer
            }

        # JAC-01 Fault extension: terminate_of without prior event
        if verb == Verb.TERMINATE and friendly.terminate_of:
            extensions["https://jac.org/fault"] = {
                "expected_parent": friendly.terminate_of,
                "fault_type": "orphan_termination",
                "fault_reason": "Terminate references a non-existent or expired event"
            }

        # JEP-04 Subject Reference extension: target -> subject
        if friendly.target:
            extensions["https://jep.org/subject"] = {
                "id": friendly.target,
                "predicate": friendly.assertion.get("predicate") if friendly.assertion else None
            }

        return JEP04Event(
            jep="1",
            verb=verb,
            who=friendly.issuer,
            when=when,
            what=what,
            nonce=nonce,
            aud=friendly.target,
            ref=ref,
            sig=friendly.signature or "",
            task_based_on=friendly.parent_task_hash,
            extensions=extensions if extensions else None,
        )

    @staticmethod
    def _build_what_payload(friendly: FriendlyEvent, verb: Verb) -> Optional[Dict[str, Any]]:
        """
        Build the payload that gets hashed into the 'what' multihash.
        JEP-04: 'what' is the cryptographic multihash of decision content.
        """
        payload: Dict[str, Any] = {}

        if friendly.assertion:
            payload["assertion"] = friendly.assertion

        if verb == Verb.DELEGATE and friendly.delegate_to:
            payload["delegate_to"] = friendly.delegate_to

        if verb == Verb.TERMINATE and friendly.terminate_of:
            payload["terminate_of"] = friendly.terminate_of

        if verb == Verb.VERIFY and friendly.verify_of:
            payload["verify_of"] = friendly.verify_of
            payload["verification_result"] = friendly.verification_result

        if friendly.confidence is not None:
            payload["confidence"] = friendly.confidence

        return payload if payload else None

    @staticmethod
    def from_jep04(event: JEP04Event) -> FriendlyEvent:
        """
        Reverse mapping: JEP04Event -> FriendlyEvent (for API responses).
        Used when returning chain inspection results to developers.
        """
        # Decode what payload (best-effort; what is a hash, original data may be lost)
        assertion = None
        delegate_to = None
        terminate_of = None
        verify_of = None
        verification_result = None
        confidence = None

        # Extract from extensions if available
        if event.extensions:
            jac_result = event.extensions.get("https://jac.org/result")
            if jac_result:
                verification_result = jac_result.get("verification_result")
                confidence = jac_result.get("confidence")

            jac_assign = event.extensions.get("https://jac.org/assign")
            if jac_assign:
                delegate_to = jac_assign.get("assignee")

            jac_fault = event.extensions.get("https://jac.org/fault")
            if jac_fault:
                terminate_of = jac_fault.get("expected_parent")

        return FriendlyEvent(
            event_id=event.nonce,
            primitive=event.verb.value,
            issuer=event.who,
            timestamp=JEPCodec.unix_to_iso(event.when),
            target=event.aud,
            assertion=assertion,
            delegate_to=delegate_to,
            terminate_of=terminate_of,
            verify_of=[event.ref] if event.ref else None,
            verification_result=verification_result,
            confidence=confidence,
            prev_event_id=event.ref,
            parent_task_hash=event.task_based_on,
            signature=event.sig,
            extensions=event.extensions,
        )


path: jep-guard-audit-skill/skill/api.py
content: """
JEP-Guard Audit Skill API
FastAPI HTTP service. Exposes friendly fields; internally maps to JEP-04 via JEPAdapter.
"""
from typing import Any, Dict, List, Optional
from datetime import datetime
from fastapi import FastAPI
from pydantic import BaseModel, Field

from .core import AuditEngine
from .types import FriendlyEvent, ComplianceStandard, AuditChain
from .adapter import JEPAdapter
from .codec import JEPCodec


class EventInput(BaseModel):
    """Developer-friendly JEP event input."""
    event_id: str
    primitive: str = Field(..., pattern="^[JDTV]$")
    issuer: str
    timestamp: str
    target: Optional[str] = None
    assertion: Optional[Dict[str, Any]] = None
    delegate_to: Optional[str] = None
    terminate_of: Optional[str] = None
    verify_of: Optional[List[str]] = None
    verification_result: Optional[str] = None
    confidence: Optional[float] = Field(None, ge=0.0, le=1.0)
    prev_event_id: Optional[str] = None
    parent_task_hash: Optional[str] = None
    signature: Optional[str] = None
    extensions: Optional[Dict[str, Any]] = None


class IngestRequest(BaseModel):
    """Request to ingest events."""
    session_id: str
    events: List[EventInput]

    class Config:
        json_schema_extra = {
            "example": {
                "session_id": "loan-decision-001",
                "events": [
                    {
                        "event_id": "jep-1",
                        "primitive": "J",
                        "issuer": "gpt-4-agent",
                        "timestamp": "2026-04-26T09:00:00Z",
                        "target": "loan-decision",
                        "assertion": {"subject": "applicant_123", "predicate": "approval", "value": "approved"},
                        "confidence": 0.92,
                        "prev_event_id": None,
                        "parent_task_hash": None,
                        "signature": "eyJhbGciOiJFZERTQSJ9..."
                    },
                    {
                        "event_id": "jep-2",
                        "primitive": "V",
                        "issuer": "audit-bot",
                        "timestamp": "2026-04-26T09:00:05Z",
                        "target": "loan-decision",
                        "verify_of": ["jep-1"],
                        "verification_result": "confirmed",
                        "confidence": 0.98,
                        "prev_event_id": "jep-1",
                        "signature": "eyJhbGciOiJFZERTQSJ9..."
                    }
                ]
            }
        }


class ChainResponse(BaseModel):
    """Audit chain response with strict JEP-04 fields."""
    session_id: str
    chain_valid: bool
    total_events: int
    violation_count: int
    warning_count: int
    start_time: Optional[str]
    end_time: Optional[str]
    links: List[Dict[str, Any]]


class ExportRequest(BaseModel):
    """Request to export compliance report."""
    session_id: str
    standard: str = "generic"

    class Config:
        json_schema_extra = {
            "example": {
                "session_id": "loan-decision-001",
                "standard": "eu_ai_act"
            }
        }


class ExportResponse(BaseModel):
    """Compliance report response."""
    report_id: str
    standard: str
    session_id: str
    generated_at: str
    chain_summary: Dict[str, Any]
    findings: List[Dict[str, Any]]
    recommendations: List[str]
    raw_data: str


app = FastAPI(
    title="JEP-Guard Audit Skill",
    description="Strict JEP-04 / JAC-01 Compliant Audit Chain with Friendly API",
    version="1.0.0"
)

engine = AuditEngine()


def _to_friendly(inp: EventInput) -> FriendlyEvent:
    return FriendlyEvent(
        event_id=inp.event_id,
        primitive=inp.primitive,
        issuer=inp.issuer,
        timestamp=inp.timestamp,
        target=inp.target,
        assertion=inp.assertion,
        delegate_to=inp.delegate_to,
        terminate_of=inp.terminate_of,
        verify_of=inp.verify_of,
        verification_result=inp.verification_result,
        confidence=inp.confidence,
        prev_event_id=inp.prev_event_id,
        parent_task_hash=inp.parent_task_hash,
        signature=inp.signature,
        extensions=inp.extensions,
    )


@app.post("/audit/ingest")
async def ingest(request: IngestRequest):
    for evt_in in request.events:
        engine.ingest(request.session_id, _to_friendly(evt_in))
    return {
        "session_id": request.session_id,
        "events_ingested": len(request.events),
        "status": "ok"
    }


@app.get("/audit/chain/{session_id}", response_model=ChainResponse)
async def get_chain(session_id: str):
    chain = engine.build_chain(session_id)
    return ChainResponse(
        session_id=chain.session_id,
        chain_valid=chain.chain_valid,
        total_events=len(chain.links),
        violation_count=chain.violation_count,
        warning_count=chain.warning_count,
        start_time=chain.start_time.isoformat() if chain.start_time else None,
        end_time=chain.end_time.isoformat() if chain.end_time else None,
        links=[
            {
                "nonce": l.event.nonce,
                "verb": l.event.verb.value,
                "who": l.event.who,
                "when": l.event.when,
                "what": l.event.what,
                "ref": l.event.ref,
                "task_based_on": l.event.task_based_on,
                "computed_hash": l.computed_hash,
                "hash_valid": l.hash_valid,
                "signature_valid": l.signature_valid,
                "chain_integrity": l.chain_integrity,
                "violations": l.violations,
            }
            for l in chain.links
        ]
    )


@app.post("/audit/export", response_model=ExportResponse)
async def export(request: ExportRequest):
    standard = ComplianceStandard(request.standard)
    report = engine.export_compliance(request.session_id, standard)
    return ExportResponse(
        report_id=report.report_id,
        standard=report.standard.value,
        session_id=report.session_id,
        generated_at=report.generated_at.isoformat(),
        chain_summary=report.chain_summary,
        findings=report.findings,
        recommendations=report.recommendations,
        raw_data=report.raw_data
    )


@app.get("/health")
async def health():
    return {"status": "ok", "skill": "jep-guard-audit", "version": "1.0.0", "protocol": "JEP-04", "jac": "JAC-01"}


@app.get("/")
async def root():
    return {
        "name": "JEP-Guard Audit Skill",
        "version": "1.0.0",
        "protocol": "JEP-04",
        "jac": "JAC-01",
        "description": "Strict JEP-04 / JAC-01 Compliant Audit Chain with Friendly API",
        "endpoints": ["/audit/ingest", "/audit/chain/{session_id}", "/audit/export"],
        "standards": ["generic", "eu_ai_act", "us_california", "us_colorado"],
        "architecture": ["GuardSkill (API)", "JEPAdapter (Mapping)", "JEPCodec (Protocol)"]
    }


path: jep-guard-audit-skill/skill/codec.py
content: """
JEPCodec — Strict Protocol Layer
Implements JEP-04 (draft-wang-jep-judgment-event-protocol-04) and
JAC-01 (draft-wang-jac-01) with zero deviation.

Responsibilities:
  - Canonicalization (RFC 8785 JCS)
  - Multihash computation (RFC 9122)
  - UUIDv4 nonce generation (RFC 9562)
  - Unix timestamp handling
  - Signature envelope (JWS / RFC 7515)
  - Extension serialization
"""
import hashlib
import json
import uuid
from datetime import datetime, timezone
from typing import Any, Dict, Optional

from .types import JEP04Event, Verb, JACReceipt


class JEPCodec:
    """
    Strict JEP-04 encoder/decoder.
    No business logic. No friendly field names. Only protocol.
    """

    PROTOCOL_VERSION = "1"
    HASH_PREFIX = "sha256:"
    CLOCK_SKEW_TOLERANCE = 300  # ±5 minutes (Section 2.3)

    @staticmethod
    def encode(event: JEP04Event) -> str:
        """
        Encode a JEP04Event to canonical JSON string (RFC 8785).
        This is the exact payload that gets signed.
        """
        payload = {
            "jep": event.jep,
            "verb": event.verb.value,
            "who": event.who,
            "when": event.when,
            "what": event.what,
            "nonce": event.nonce,
            "aud": event.aud,
            "ref": event.ref,
            "sig": event.sig,  # Included in canonical form for hash chain continuity
        }
        # JAC-01 core field
        if event.task_based_on is not None:
            payload["task_based_on"] = event.task_based_on
        # JEP-04 Section 2.5 extensions
        if event.extensions is not None:
            payload["extensions"] = event.extensions
        # RFC 8785: canonical JSON (lexicographic key order, no whitespace)
        return json.dumps(payload, sort_keys=True, separators=(",", ":"), default=str)

    @staticmethod
    def decode(raw: str) -> JEP04Event:
        """Decode canonical JSON string to JEP04Event."""
        payload = json.loads(raw)
        return JEP04Event(
            jep=payload.get("jep", "1"),
            verb=Verb(payload.get("verb", "J")),
            who=payload["who"],
            when=payload["when"],
            what=payload.get("what"),
            nonce=payload["nonce"],
            aud=payload.get("aud"),
            ref=payload.get("ref"),
            sig=payload.get("sig", ""),
            task_based_on=payload.get("task_based_on"),
            extensions=payload.get("extensions"),
        )

    @staticmethod
    def compute_what(data: Dict[str, Any]) -> str:
        """
        Compute 'what' field: cryptographic multihash of decision content.
        JEP-04 Section 2.2: "what: Cryptographic multihash of decision content.
        Implementations SHOULD support common hash functions such as SHA-256 and SM3."
        """
        canonical = json.dumps(data, sort_keys=True, separators=(",", ":"), default=str)
        digest = hashlib.sha256(canonical.encode("utf-8")).hexdigest()
        return f"{JEPCodec.HASH_PREFIX}{digest}"

    @staticmethod
    def generate_nonce() -> str:
        """
        Generate UUIDv4 nonce.
        JEP-04 Section 2.3: "Event initiators MUST generate a new UUIDv4 nonce for each event."
        """
        return str(uuid.uuid4())

    @staticmethod
    def iso_to_unix(iso_timestamp: str) -> int:
        """Convert ISO 8601 string to Unix seconds."""
        dt = datetime.fromisoformat(iso_timestamp.replace("Z", "+00:00"))
        return int(dt.timestamp())

    @staticmethod
    def unix_to_iso(unix_ts: int) -> str:
        """Convert Unix seconds to ISO 8601 UTC string."""
        dt = datetime.fromtimestamp(unix_ts, tz=timezone.utc)
        return dt.strftime("%Y-%m-%dT%H:%M:%SZ")

    @staticmethod
    def verify_nonce_uniqueness(nonce: str, seen: set) -> bool:
        """
        JEP-04 Section 2.3: "Receivers MUST cache nonces and reject duplicates."
        Returns True if nonce is unique, False if duplicate.
        """
        if nonce in seen:
            return False
        seen.add(nonce)
        return True

    @staticmethod
    def verify_timestamp_window(when: int, now: Optional[int] = None) -> bool:
        """
        JEP-04 Section 2.3: "Unless otherwise configured, a clock skew tolerance
        of ±5 minutes (300 seconds) is RECOMMENDED."
        """
        if now is None:
            now = int(datetime.now(timezone.utc).timestamp())
        return abs(when - now) <= JEPCodec.CLOCK_SKEW_TOLERANCE

    @staticmethod
    def build_jac_receipt(event: JEP04Event) -> JACReceipt:
        """
        JAC-01 Section 3.1: Build a minimal JAC receipt from JEP event.
        """
        canonical = JEPCodec.encode(event)
        return JACReceipt(event=event, raw_canonical=canonical)

    @staticmethod
    def verify_jac_core(receipt: JACReceipt, parent_exists_fn, parent_judgment_exists_fn) -> str:
        """
        JAC-01 Section 1.4: Core Verification Algorithm.
        Returns: "VALID", "INVALID", or "VALID_WITH_FAULT".
        """
        event = receipt.event

        # Step 1: JEP signature verification (placeholder — real crypto needed)
        if not event.sig or len(event.sig) == 0:
            return "INVALID"

        # Step 2: HJS chain verification using ref field
        if event.ref and not parent_exists_fn(event.ref):
            return "INVALID"
        # JAC-01: J verb with ref is invalid per HJS
        if event.verb == Verb.JUDGE and event.ref is not None:
            return "INVALID"

        # Step 3: JAC chain integrity via task_based_on
        if event.task_based_on and not parent_judgment_exists_fn(event.task_based_on):
            # Check for JAC-Fault extension (Section 2.8)
            if event.extensions and "https://jac.org/fault" in event.extensions:
                fault = event.extensions["https://jac.org/fault"]
                if fault.get("expected_parent") == event.task_based_on:
                    return "VALID_WITH_FAULT"
            return "INVALID"

        # Step 4: JAC chain head check
        if event.verb == Verb.JUDGE:
            return "VALID"

        return "INVALID"


path: jep-guard-audit-skill/skill/core.py
content: """
JEP-Guard Audit Engine — Business Logic Layer
Operates strictly on JEP04Event objects produced by JEPCodec + JEPAdapter.

Implements:
  - Tamper-evident audit chain construction (SHA-256 hash linking)
  - JEP-04 signature / nonce / timestamp verification
  - JAC-01 chain integrity verification (task_based_on)
  - Five violation detection rules (R001–R005)
  - EU AI Act / CA SB 1047 / CO SB 205 / Generic JEP-01 compliance export
"""
import hashlib
import json
from typing import List, Dict, Optional, Any, Callable
from collections import defaultdict
from datetime import datetime, timezone
from uuid import uuid4

from .types import (
    JEP04Event, Verb, FriendlyEvent,
    AuditChain, AuditChainLink,
    ComplianceStandard, ComplianceReport,
    AuditSeverity, ViolationRule
)
from .codec import JEPCodec
from .adapter import JEPAdapter


class AuditEngine:
    """
    JEP-Guard Audit Engine.
    Ingests FriendlyEvents -> converts to JEP04Events via JEPAdapter ->
    builds strict JEP-04 compliant audit chains -> exports compliance reports.
    """

    def __init__(self):
        self._sessions: Dict[str, List[JEP04Event]] = defaultdict(list)
        self._nonce_cache: set = set()
        self._rules: List[ViolationRule] = []
        self._register_default_rules()

    def _register_default_rules(self):
        """Register default violation detection rules."""
        self._rules.append(ViolationRule(
            rule_id="R001",
            description="Judge event without subsequent Verify event within chain",
            severity=AuditSeverity.WARNING,
            check=self._check_missing_verification
        ))
        self._rules.append(ViolationRule(
            rule_id="R002",
            description="Delegate event without proper issuer authorization",
            severity=AuditSeverity.VIOLATION,
            check=self._check_unauthorized_delegation
        ))
        self._rules.append(ViolationRule(
            rule_id="R003",
            description="Terminate event without matching prior Judge event",
            severity=AuditSeverity.VIOLATION,
            check=self._check_orphan_termination
        ))
        self._rules.append(ViolationRule(
            rule_id="R004",
            description="Hash chain break detected (prev_event_id / ref mismatch)",
            severity=AuditSeverity.CRITICAL,
            check=self._check_hash_integrity
        ))
        self._rules.append(ViolationRule(
            rule_id="R005",
            description="Verify event references non-existent Judge event",
            severity=AuditSeverity.VIOLATION,
            check=self._check_dangling_verification
        ))

    # ------------------------------------------------------------------
    # Ingestion
    # ------------------------------------------------------------------

    def ingest(self, session_id: str, friendly: FriendlyEvent) -> None:
        """
        Ingest a developer-friendly event.
        Automatically adapts to strict JEP04Event and stores in session.
        """
        jep_event = JEPAdapter.to_jep04(friendly)
        self._sessions[session_id].append(jep_event)

    def ingest_batch(self, session_id: str, friendlies: List[FriendlyEvent]) -> None:
        """Ingest multiple friendly events."""
        for f in friendlies:
            self.ingest(session_id, f)

    # ------------------------------------------------------------------
    # Chain Building & Verification
    # ------------------------------------------------------------------

    def build_chain(self, session_id: str) -> AuditChain:
        """
        Build and verify the tamper-evident audit chain for a session.
        Strictly follows JEP-04 canonicalization and JAC-01 chain rules.
        """
        events = self._sessions.get(session_id, [])
        if not events:
            return AuditChain(
                session_id=session_id,
                links=[],
                chain_valid=True,
                violation_count=0,
                warning_count=0,
            )

        # Sort by JEP-04 'when' (Unix timestamp)
        sorted_events = sorted(events, key=lambda e: e.when)

        links: List[AuditChainLink] = []
        prev_hash = "0" * 64
        violation_count = 0
        warning_count = 0

        # Build event index for JAC parent lookups
        event_index = {e.nonce: e for e in sorted_events}
        # Also index by what hash if available
        hash_index = {e.what: e for e in sorted_events if e.what}

        for i, evt in enumerate(sorted_events):
            # 1. Compute canonical hash of this event
            canonical = JEPCodec.encode(evt)
            computed_hash = hashlib.sha256(canonical.encode("utf-8")).hexdigest()

            # 2. Verify nonce uniqueness (JEP-04 Section 2.3)
            nonce_unique = JEPCodec.verify_nonce_uniqueness(evt.nonce, self._nonce_cache)

            # 3. Verify timestamp window (JEP-04 Section 2.3)
            ts_valid = JEPCodec.verify_timestamp_window(evt.when)

            # 4. Chain integrity: ref should point to previous event's what hash
            chain_integrity = True
            if i > 0:
                prev_evt = sorted_events[i - 1]
                # If ref is present, it should match previous event's hash or nonce
                if evt.ref and evt.ref != prev_evt.nonce and evt.ref != prev_evt.what:
                    chain_integrity = False

            # 5. JAC-01 chain integrity via task_based_on
            jac_valid = True
            if evt.task_based_on:
                if evt.task_based_on not in hash_index and evt.task_based_on not in event_index:
                    # Check JAC-Fault extension
                    has_fault = (
                        evt.extensions
                        and "https://jac.org/fault" in evt.extensions
                        and evt.extensions["https://jac.org/fault"].get("expected_parent") == evt.task_based_on
                    )
                    if not has_fault:
                        jac_valid = False

            # 6. Signature placeholder (real crypto would verify JWS here)
            sig_valid = bool(evt.sig and len(evt.sig) > 0)

            # 7. Run violation rules
            violations = []
            for rule in self._rules:
                if rule.check(evt, sorted_events[:i+1], event_index, hash_index):
                    violations.append(f"[{rule.severity.value}] {rule.rule_id}: {rule.description}")
                    if rule.severity in (AuditSeverity.VIOLATION, AuditSeverity.CRITICAL):
                        violation_count += 1
                    elif rule.severity == AuditSeverity.WARNING:
                        warning_count += 1

            # 8. Add protocol-level findings
            if not nonce_unique:
                violations.append(f"[critical] PROTOCOL: Duplicate nonce detected")
                violation_count += 1
            if not ts_valid:
                violations.append(f"[violation] PROTOCOL: Timestamp outside ±5min window")
                violation_count += 1
            if not chain_integrity:
                violations.append(f"[critical] PROTOCOL: Hash chain break (ref mismatch)")
                violation_count += 1
            if not jac_valid:
                violations.append(f"[violation] JAC-01: Parent task not found for task_based_on")
                violation_count += 1

            link = AuditChainLink(
                event=evt,
                computed_hash=computed_hash,
                hash_valid=True,  # We computed it ourselves
                signature_valid=sig_valid,
                chain_integrity=chain_integrity and jac_valid,
                violations=violations,
            )
            links.append(link)
            prev_hash = computed_hash

        chain_valid = all(l.chain_integrity and l.signature_valid for l in links)

        start_dt = datetime.fromtimestamp(sorted_events[0].when, tz=timezone.utc) if sorted_events else None
        end_dt = datetime.fromtimestamp(sorted_events[-1].when, tz=timezone.utc) if sorted_events else None

        return AuditChain(
            session_id=session_id,
            links=links,
            chain_valid=chain_valid,
            violation_count=violation_count,
            warning_count=warning_count,
            start_time=start_dt,
            end_time=end_dt,
        )

    # ------------------------------------------------------------------
    # Compliance Export
    # ------------------------------------------------------------------

    def export_compliance(
        self,
        session_id: str,
        standard: ComplianceStandard = ComplianceStandard.GENERIC
    ) -> ComplianceReport:
        """Export a regulatory compliance report."""
        chain = self.build_chain(session_id)
        report_id = str(uuid4())
        generated_at = datetime.now(timezone.utc)

        findings = []
        recommendations = []

        for link in chain.links:
            for v in link.violations:
                findings.append({
                    "event_nonce": link.event.nonce,
                    "verb": link.event.verb.value,
                    "issuer": link.event.who,
                    "timestamp": JEPCodec.unix_to_iso(link.event.when),
                    "finding": v,
                    "hash_valid": link.hash_valid,
                    "signature_valid": link.signature_valid,
                    "chain_integrity": link.chain_integrity,
                })

        if standard == ComplianceStandard.EU_AI_ACT:
            recommendations.extend([
                "Ensure all high-risk AI system judgments are logged with full provenance per Article 12.",
                "Maintain tamper-evident records for minimum 6 years per EU AI Act retention rules.",
                "Provide human oversight capability for all automated judgment events per Article 14.",
            ])
            raw = self._format_eu_ai_act(chain, findings)
        elif standard == ComplianceStandard.US_CALIFORNIA:
            recommendations.extend([
                "Report critical safety incidents to CalDS within 72 hours per SB 1047.",
                "Maintain kill-switch event logs for all autonomous terminations.",
            ])
            raw = self._format_us_california(chain, findings)
        elif standard == ComplianceStandard.US_COLORADO:
            recommendations.extend([
                "Document algorithmic impact assessment for all automated decisions per SB 205.",
                "Provide appeal mechanism logs for contested judgments.",
            ])
            raw = self._format_us_colorado(chain, findings)
        else:
            recommendations.extend([
                "Review all WARNING and VIOLATION findings before production deployment.",
                "Ensure JEP-04 hash chain integrity before external audit.",
            ])
            raw = self._format_generic(chain, findings)

        return ComplianceReport(
            report_id=report_id,
            standard=standard,
            session_id=session_id,
            generated_at=generated_at,
            chain_summary={
                "total_events": len(chain.links),
                "chain_valid": chain.chain_valid,
                "violation_count": chain.violation_count,
                "warning_count": chain.warning_count,
                "start_time": chain.start_time.isoformat() if chain.start_time else None,
                "end_time": chain.end_time.isoformat() if chain.end_time else None,
            },
            findings=findings,
            recommendations=recommendations,
            export_format="json",
            raw_data=raw,
        )

    # ------------------------------------------------------------------
    # Violation Rule Implementations
    # ------------------------------------------------------------------

    def _check_missing_verification(self, evt, history, index, hash_index):
        if evt.verb != Verb.JUDGE:
            return False
        for e in history:
            if e.verb == Verb.VERIFY and e.ref == evt.nonce:
                return False
        return True

    def _check_unauthorized_delegation(self, evt, history, index, hash_index):
        if evt.verb != Verb.DELEGATE:
            return False
        has_prior = any(
            e.who == evt.who and e.verb in (Verb.JUDGE, Verb.VERIFY)
            for e in history
        )
        return not has_prior

    def _check_orphan_termination(self, evt, history, index, hash_index):
        if evt.verb != Verb.TERMINATE:
            return False
        # Check if terminate_of exists in index or hash_index
        target = evt.what  # In adapter, terminate_of is put into what payload
        if target and target in hash_index:
            return False
        # Also check extensions
        if evt.extensions and "https://jac.org/fault" in evt.extensions:
            return False  # Fault extension means it's acknowledged
        return True

    def _check_hash_integrity(self, evt, history, index, hash_index):
        if len(history) < 2:
            return False
        prev = history[-2]
        if evt.ref and evt.ref != prev.nonce and evt.ref != prev.what:
            return True
        return False

    def _check_dangling_verification(self, evt, history, index, hash_index):
        if evt.verb != Verb.VERIFY:
            return False
        if not evt.ref:
            return True
        if evt.ref not in index and evt.ref not in hash_index:
            return True
        return False

    # ------------------------------------------------------------------
    # Report Formatters
    # ------------------------------------------------------------------

    def _format_generic(self, chain, findings):
        return json.dumps({
            "standard": "JEP-01",
            "protocol": "JEP-04",
            "jac_version": "JAC-01",
            "session_id": chain.session_id,
            "chain_valid": chain.chain_valid,
            "events": [
                {
                    "nonce": l.event.nonce,
                    "verb": l.event.verb.value,
                    "who": l.event.who,
                    "when": l.event.when,
                    "what": l.event.what,
                    "ref": l.event.ref,
                    "task_based_on": l.event.task_based_on,
                    "computed_hash": l.computed_hash,
                    "violations": l.violations,
                }
                for l in chain.links
            ],
            "findings": findings,
        }, indent=2, default=str)

    def _format_eu_ai_act(self, chain, findings):
        return json.dumps({
            "regulation": "EU AI Act (2024/1689)",
            "article_references": ["Article 12 (Record-keeping)", "Article 14 (Human oversight)"],
            "session_id": chain.session_id,
            "audit_trail_valid": chain.chain_valid,
            "high_risk_system_events": len(chain.links),
            "findings": findings,
            "retention_required_until": "2032-04-26",
        }, indent=2, default=str)

    def _format_us_california(self, chain, findings):
        critical_events = [
            l.event.nonce for l in chain.links
            if l.violations and any("CRITICAL" in v for v in l.violations)
        ]
        return json.dumps({
            "regulation": "California SB 1047",
            "section_references": ["Section 22602 (Safety incidents)"],
            "session_id": chain.session_id,
            "critical_events": critical_events,
            "findings": findings,
            "reporting_deadline": "72 hours from incident detection",
        }, indent=2, default=str)

    def _format_us_colorado(self, chain, findings):
        return json.dumps({
            "regulation": "Colorado SB 205",
            "section_references": ["Section 6-1-1703 (Algorithmic discrimination)"],
            "session_id": chain.session_id,
            "automated_decision_count": len([l for l in chain.links if l.event.verb == Verb.JUDGE]),
            "findings": findings,
            "appeal_logs_available": any(l.event.verb == Verb.TERMINATE for l in chain.links),
        }, indent=2, default=str)


path: jep-guard-audit-skill/skill/types.py
content: """
JEP-Guard Audit Skill — Core Types
Strictly aligned with:
  - JEP-04: Judgment Event Protocol (draft-wang-jep-judgment-event-protocol-04)
  - JAC-01: Judgment Accountability Chain (draft-wang-jac-01)
"""
from typing import Any, Dict, List, Optional
from dataclasses import dataclass, field
from enum import Enum
from datetime import datetime


class Verb(Enum):
    """JEP-04 Section 2.1: Four immutable core verbs."""
    JUDGE = "J"
    DELEGATE = "D"
    TERMINATE = "T"
    VERIFY = "V"


class ComplianceStandard(Enum):
    EU_AI_ACT = "eu_ai_act"
    US_CALIFORNIA = "us_california"
    US_COLORADO = "us_colorado"
    GENERIC = "generic"


class AuditSeverity(Enum):
    INFO = "info"
    WARNING = "warning"
    VIOLATION = "violation"
    CRITICAL = "critical"


# ---------------------------------------------------------------------------
# Layer 1: JEPCodec — Strict JEP-04 + JAC-01 Event Structure
# ---------------------------------------------------------------------------

@dataclass
class JEP04Event:
    """
    Strict JEP-04 event structure (Section 2.2).
    Fields: jep, verb, who, when, what, nonce, aud, ref, sig.
    Plus JAC-01 task_based_on and extensions.
    """
    jep: str = "1"
    verb: Verb = Verb.JUDGE
    who: str = ""                    # Actor identifier (URI/DID/public key hash)
    when: int = 0                    # Unix timestamp (seconds since epoch)
    what: Optional[str] = None       # Cryptographic multihash (sha256:..., sm3:...)
    nonce: str = ""                  # UUIDv4 (Section 2.3)
    aud: Optional[str] = None        # Intended recipient
    ref: Optional[str] = None        # Reference to related event hash/ID (HJS chain)
    sig: str = ""                    # JWS signature over canonicalized JSON
    # JAC-01 Core Field (Section 1.2)
    task_based_on: Optional[str] = None   # Hash of parent judgment event
    # JEP-04 Section 2.5 + JAC-01 Section 2.1: Extensions
    extensions: Optional[Dict[str, Any]] = None


@dataclass
class JACReceipt:
    """
    JAC-01 Section 3.1: Minimal implementation wrapper.
    Wraps a JEP04Event with verification helpers.
    """
    event: JEP04Event
    raw_canonical: str = ""          # RFC 8785 canonicalized JSON before signing


# ---------------------------------------------------------------------------
# Layer 2: JEPAdapter — Friendly API Types
# ---------------------------------------------------------------------------

@dataclass
class FriendlyEvent:
    """
    Developer-friendly event format consumed by GuardSkill API.
    Automatically mapped to JEP04Event by JEPAdapter.
    """
    event_id: str                    # Maps to nonce (or used as seed)
    primitive: str                   # J/D/T/V -> verb
    issuer: str                      # -> who
    timestamp: str                   # ISO 8601 -> when (Unix)
    target: Optional[str] = None     # -> aud (or into what payload)
    assertion: Optional[Dict[str, Any]] = None   # Serialized into what
    delegate_to: Optional[str] = None            # -> D verb payload
    terminate_of: Optional[str] = None             # -> T verb payload
    verify_of: Optional[List[str]] = None          # -> V verb ref
    verification_result: Optional[str] = None
    confidence: Optional[float] = None
    prev_event_id: Optional[str] = None          # -> ref
    parent_task_hash: Optional[str] = None         # -> task_based_on (JAC)
    signature: Optional[str] = None              # -> sig
    extensions: Optional[Dict[str, Any]] = None    # -> extensions


# ---------------------------------------------------------------------------
# Layer 3: GuardSkill — Audit Domain Types
# ---------------------------------------------------------------------------

@dataclass
class AuditChainLink:
    """A single verified link in the tamper-evident audit chain."""
    event: JEP04Event
    computed_hash: str
    hash_valid: bool
    signature_valid: bool
    chain_integrity: bool
    violations: List[str] = field(default_factory=list)


@dataclass
class AuditChain:
    """Complete audit chain for a session."""
    session_id: str
    links: List[AuditChainLink]
    chain_valid: bool
    violation_count: int
    warning_count: int
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None


@dataclass
class ComplianceReport:
    """Regulatory compliance report export."""
    report_id: str
    standard: ComplianceStandard
    session_id: str
    generated_at: datetime
    chain_summary: Dict[str, Any]
    findings: List[Dict[str, Any]]
    recommendations: List[str]
    export_format: str
    raw_data: Optional[str] = None


@dataclass
class ViolationRule:
    """An audit rule that detects policy violations."""
    rule_id: str
    description: str
    severity: AuditSeverity
    check: Any  # Callable


path: jep-guard-audit-skill/skill/__init__.py
content: """
JEP-Guard Audit Skill v1.0.0
Cognitive Emergence Lab
"""
__version__ = "1.0.0"


path: jep-guard-audit-skill/examples/strict_protocol_demo.py
content: """
JEP-Guard Audit Skill Example: Strict Protocol Compliance Demo
Demonstrates three-layer architecture:
  1. GuardSkill (friendly API)
  2. JEPAdapter (field mapping)
  3. JEPCodec (strict JEP-04 + JAC-01)
Run: python strict_protocol_demo.py
"""
import sys
sys.path.insert(0, "..")

from skill.core import AuditEngine
from skill.types import FriendlyEvent
from skill.codec import JEPCodec
from skill.adapter import JEPAdapter


def run_demo():
    print("=" * 70)
    print("JEP-Guard Audit: Strict Protocol Compliance Demo")
    print("=" * 70)

    engine = AuditEngine()
    session_id = "loan-decision-2026-04-26"

    # --- Layer 1: Friendly Events (what developers send) ---
    friendly_events = [
        FriendlyEvent(
            event_id="evt-001",
            primitive="J",
            issuer="did:example:loan-agent-001",
            timestamp="2026-04-26T09:00:00Z",
            target="loan-decision",
            assertion={"subject": "applicant_123", "predicate": "approval", "value": "approved"},
            confidence=0.92,
            prev_event_id=None,
            parent_task_hash=None,
            signature="sig-j-001",
        ),
        FriendlyEvent(
            event_id="evt-002",
            primitive="V",
            issuer="did:example:audit-bot-001",
            timestamp="2026-04-26T09:00:05Z",
            target="loan-decision",
            verify_of=["evt-001"],
            verification_result="confirmed",
            confidence=0.98,
            prev_event_id="evt-001",
            signature="sig-v-001",
        ),
        FriendlyEvent(
            event_id="evt-003",
            primitive="J",
            issuer="did:example:loan-agent-001",
            timestamp="2026-04-26T09:01:00Z",
            target="loan-decision",
            assertion={"subject": "applicant_124", "predicate": "approval", "value": "rejected"},
            confidence=0.85,
            prev_event_id="evt-002",
            parent_task_hash="evt-001",  # JAC-01: this judgment is based on prior task
            signature="sig-j-002",
        ),
        # Intentional violation: missing verification for applicant_124 -> triggers R001
        FriendlyEvent(
            event_id="evt-004",
            primitive="D",
            issuer="did:example:loan-agent-001",
            timestamp="2026-04-26T09:02:00Z",
            target="loan-decision",
            delegate_to="did:example:human-reviewer-001",
            prev_event_id="evt-003",
            signature="sig-d-001",
        ),
        # Intentional violation: orphan termination -> triggers R003
        FriendlyEvent(
            event_id="evt-005",
            primitive="T",
            issuer="did:example:loan-agent-001",
            timestamp="2026-04-26T09:03:00Z",
            target="loan-decision",
            terminate_of="nonexistent-event",
            prev_event_id="evt-004",
            signature="sig-t-001",
        ),
    ]

    # --- Layer 2: Adapter converts to strict JEP-04 ---
    print("\n[Layer 2: JEPAdapter Mapping]")
    for fe in friendly_events[:2]:
        jep = JEPAdapter.to_jep04(fe)
        print(f"  Friendly '{fe.event_id}' -> JEP-04 nonce={jep.nonce}, verb={jep.verb.value}, who={jep.who}")
        print(f"    what={jep.what}, aud={jep.aud}, ref={jep.ref}, task_based_on={jep.task_based_on}")

    # --- Layer 3: Engine builds strict chain ---
    print("\n[Layer 3: AuditEngine Chain Build]")
    for fe in friendly_events:
        engine.ingest(session_id, fe)

    chain = engine.build_chain(session_id)
    print(f"  Session: {chain.session_id}")
    print(f"  Chain Valid: {chain.chain_valid}")
    print(f"  Total Events: {len(chain.links)}")
    print(f"  Violations: {chain.violation_count}")
    print(f"  Warnings: {chain.warning_count}")

    for link in chain.links:
        if link.violations:
            print(f"  - {link.event.nonce} ({link.event.verb.value}): {len(link.violations)} issue(s)")
            for v in link.violations:
                print(f"      {v}")

    # --- Compliance Exports ---
    print("\n[Compliance Exports]")
    for std in ["generic", "eu_ai_act", "us_california", "us_colorado"]:
        from skill.types import ComplianceStandard
        report = engine.export_compliance(session_id, ComplianceStandard(std))
        print(f"  {std}: {len(report.findings)} findings, {len(report.recommendations)} recommendations")

    print("\n" + "=" * 70)
    print("Demo complete. All events are strict JEP-04 + JAC-01 compliant.")
    print("=" * 70)


if __name__ == "__main__":
    run_demo()


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)