Skip to content
Closed
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
23 changes: 7 additions & 16 deletions schemas/aep/evidence-envelope.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wasmagent.dev/schemas/aep/evidence-envelope.schema.json",
"title": "EvidenceEnvelope",
"description": "Shared base fields for all AEP evidence records \u2014 schema_version, trace_id, created_at_ms, and optional signature. Every evidence type $refs this schema for its envelope fields.",
"description": "Shared base fields for all AEP evidence records schema_version, trace_id, created_at_ms, and optional signature. Every evidence type $refs this schema for its envelope fields.",
"type": "object",
"required": [
"schema_version",
Expand All @@ -23,27 +23,18 @@
},
"signature": {
"type": "object",
"description": "Optional tamper-evident signature over the record content",
"required": [
"alg",
"key_id",
"sig"
],
"properties": {
"alg": {
"type": "string",
"description": "Signature algorithm, e.g. ed25519"
},
"key_id": {
"type": "string",
"description": "Identifier of the signing key"
},
"sig": {
"type": "string",
"description": "Base64-encoded signature bytes"
}
},
"additionalProperties": false
"alg": { "type": "string" },
"key_id": { "type": "string" },
"sig": { "type": "string" },
"bundle": { "type": "object" },
"transparency_log_ref": { "type": "string" }
}
}
}
}
32 changes: 23 additions & 9 deletions src/wasmagent_protocol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@

def _read(rel_path: str) -> str:
# rel_path is e.g. "index.json" or "aep/aep-record.schema.json"
resource = resources.files(_SCHEMAS_PKG)
for part in rel_path.split("/"):
resource = resource / part
return resource.read_text(encoding="utf-8")
try:
resource = resources.files(_SCHEMAS_PKG)
for part in rel_path.split("/"):
resource = resource / part
return resource.read_text(encoding="utf-8")
except (ModuleNotFoundError, TypeError, FileNotFoundError):
schemas_dir = Path(__file__).resolve().parent.parent.parent / "schemas"
p = schemas_dir
for part in rel_path.split("/"):
p = p / part
return p.read_text(encoding="utf-8")


INDEX: dict[str, Any] = json.loads(_read("index.json"))
Expand Down Expand Up @@ -69,8 +76,15 @@ def schema_path(schema_id: str) -> Path:
raise KeyError(
f"unknown schema id {schema_id!r}; known: {', '.join(_PATHS)}"
) from None
resource = resources.files(_SCHEMAS_PKG)
for part in rel.split("/"):
resource = resource / part
with resources.as_file(resource) as p:
return Path(p)
try:
resource = resources.files(_SCHEMAS_PKG)
for part in rel.split("/"):
resource = resource / part
with resources.as_file(resource) as p:
return Path(p)
except (ModuleNotFoundError, TypeError, FileNotFoundError):
schemas_dir = Path(__file__).resolve().parent.parent.parent / "schemas"
p = schemas_dir
for part in rel.split("/"):
p = p / part
return p
53 changes: 53 additions & 0 deletions tests/test_conformance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Pytest entry for the conformance harness.

`tests/conformance.py` is a runnable script (`python3 tests/conformance.py`)
with a ``main()`` but no ``test_*`` functions, so ``pytest tests/`` collects
nothing from it directly. This module surfaces that harness as a single pytest
test so the bot/CI pytest gate actually exercises the schema + fixture
invariants — the same checks documented in CLAUDE.md.
"""
from __future__ import annotations

import sys
from pathlib import Path

# tests/ is not a package; make conformance.py importable whether pytest runs
# from the repo root or collects this file directly.
_HERE = Path(__file__).resolve().parent
if str(_HERE) not in sys.path:
sys.path.insert(0, str(_HERE))

import conformance # noqa: E402


def test_conformance_harness() -> None:
"""Every registered schema is well-formed, $refs resolve, and fixtures
pass/fail as expected. Mirrors ``python3 tests/conformance.py``'s exit code.
"""
conformance.errors.clear()
rc = conformance.main()
assert rc == 0, (
"conformance harness reported failures:\n"
+ "\n".join(f" - {e}" for e in conformance.errors)
)


def test_evidence_envelope_schema() -> None:
"""Verify evidence-envelope schema registration, canonical $id, and signature shape."""
import wasmagent_protocol

assert "evidence-envelope" in wasmagent_protocol.schema_ids()
envelope = wasmagent_protocol.get_schema("evidence-envelope")
assert envelope["$id"] == "https://wasmagent.dev/schemas/aep/evidence-envelope.schema.json"
assert envelope["title"] == "EvidenceEnvelope"
assert set(envelope["required"]) == {"schema_version", "created_at_ms"}

# Signature field properties must match aep-record signature fields
aep_record = wasmagent_protocol.get_schema("aep-record")
env_sig = envelope["properties"]["signature"]
aep_sig = aep_record["properties"]["signature"]

assert set(env_sig["required"]) == set(aep_sig["required"])
assert set(env_sig["properties"].keys()) == set(aep_sig["properties"].keys())
assert env_sig["properties"]["bundle"] == aep_sig["properties"]["bundle"]

Loading