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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Only contracts that genuinely cross a repository boundary:
| Schema | Version | Consumers |
| --- | --- | --- |
| `aep-record` | `aep/v0.3` | wasmagent-js, wasmagent-proxy, trace-pipeline, wasmagent-train-replay, open-agent-audit |
| `canonical-event` | `canonical-event/v0.1` | open-agent-audit, wasmagent-js |
| `constraint-ir` | `compliance/v1` | wasmagent-js, trace-pipeline |
| `constraint-violation` | `compliance/v1` | wasmagent-js, trace-pipeline |
| `repair-trace` | `compliance/v1` | wasmagent-js, trace-pipeline |
Expand Down
43 changes: 43 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,49 @@ export const schemas: Record<string, unknown>;
*/
export function getSchema(id: string): unknown;

// ---------------------------------------------------------------------------
// Schema instance types (convenience views).
//
// The authoritative contract for every record shape is its JSON Schema
// (see schemas/index.json). Load and validate against it at runtime via
// getSchema(<id>). The interfaces below capture only the required top-level
// fields so consumers can type their payloads ergonomically; the index
// signature passes through every optional schema property unchanged.
// ---------------------------------------------------------------------------

/**
* Convenience structural view of an Agent Evidence Protocol (AEP) record —
* runtime action evidence and run provenance. Authoritative shape:
* getSchema('aep-record') → schemas/aep/aep-record.schema.json.
*/
export interface AEPRecord {
/** Schema version, one of `aep/v0.1` | `aep/v0.2` | `aep/v0.3`. */
schema_version: string;
/** Identifier of the run this record captures. */
run_id: string;
/** UTC epoch milliseconds when the record was created. */
created_at_ms: number;
[key: string]: unknown;
}

/**
* Convenience structural view of a normalized event — the foundational record
* heterogeneous agent evidence is normalized into before being mapped onto an
* AEPRecord. Authoritative shape:
* getSchema('canonical-event') → schemas/aep/canonical-event.schema.json.
*/
export interface CanonicalEvent {
/** Canonical-event schema version, currently `canonical-event/v0.1`. */
schema_version: string;
/** Globally-unique identifier for this event within its trace. */
event_id: string;
/** Kind of event: action | decision | observation | error | lifecycle. */
event_type: string;
/** UTC epoch milliseconds when the event occurred. */
timestamp_ms: number;
[key: string]: unknown;
}

// ---------------------------------------------------------------------------
// Cross-repo schema drift detection.
// ---------------------------------------------------------------------------
Expand Down
112 changes: 112 additions & 0 deletions schemas/aep/canonical-event.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wasmagent.dev/schemas/aep/canonical-event.schema.json",
"title": "CanonicalEvent",
"description": "Foundational, normalized event record for the WasmAgent evidence stream. Heterogeneous agent evidence (e.g. an open-agent-audit run) is normalized into one or more CanonicalEvents, which an adapter then maps onto an aep-record. Field names deliberately mirror aep-record (trace_id, run_id, tool_name, state_changing, refs, signature) so the mapping is mechanical rather than lossy.",
"type": "object",
"required": ["schema_version", "event_id", "event_type", "timestamp_ms"],
"properties": {
"schema_version": {
"type": "string",
"enum": ["canonical-event/v0.1"],
"description": "Version of the canonical-event schema this record conforms to."
},
"event_id": {
"type": "string",
"description": "Globally-unique identifier for this event within its trace."
},
"event_type": {
"type": "string",
"enum": ["action", "decision", "observation", "error", "lifecycle"],
"description": "Kind of event. 'action' maps to an aep-record action; 'decision' to a capability_decision; 'observation'/'error'/'lifecycle' to verifier_results or provenance."
},
"timestamp_ms": {
"type": "number",
"description": "UTC epoch milliseconds when the event occurred."
},
"trace_id": {
"type": "string",
"description": "Correlation id linking related events; maps to aep-record.trace_id."
},
"run_id": {
"type": "string",
"description": "Identifier of the run this event belongs to; maps to aep-record.run_id."
},
"parent_event_id": {
"type": ["string", "null"],
"description": "Event id of the causally-preceding event, enabling causal-chain reconstruction; maps to aep-record.actions[].parent_action_id."
},
"actor": {
"type": "object",
"description": "The agent/tool/human/system that produced the event.",
"required": ["actor_id"],
"properties": {
"actor_id": { "type": "string", "description": "Stable identifier for the actor." },
"actor_type": {
"type": "string",
"enum": ["agent", "tool", "human", "system"],
"description": "Category of actor."
},
"agent_version": { "type": "string", "description": "Agent/runtime version, e.g. wasmagent-js@1.20.0; maps to aep-record.runtime_version / run_context.agent_version." }
},
"additionalProperties": true
},
"subject_id": {
"type": "string",
"description": "Optional principal the event was performed on behalf of; maps to aep-record.subject_id / user_id."
},
"tool_name": {
"type": "string",
"description": "For action events, the tool invoked; maps to aep-record.actions[].tool_name."
},
"state_changing": {
"type": "boolean",
"description": "Whether the event mutates external state; maps to aep-record.actions[].state_changing and side_effect_class."
},
"data": {
"type": "object",
"description": "Type-specific payload for the event. Free-form; consumers narrow it by event_type. May carry tool arguments/results, decision rationale, verifier scores, etc.",
"additionalProperties": true
},
"refs": {
"type": "array",
"description": "Input/output/evidence artifacts referenced by the event; maps to aep-record.input_refs / output_refs / evidence_refs.",
"items": {
"type": "object",
"required": ["uri"],
"properties": {
"uri": { "type": "string", "description": "Location of the referenced artifact." },
"digest": { "type": "string", "description": "Content digest of the referenced artifact." },
"relation": {
"type": "string",
"enum": ["input", "output", "evidence", "memory"],
"description": "How the artifact relates to the event."
}
},
"additionalProperties": true
}
},
"source": {
"type": "object",
"description": "Provenance of the event for adapter traceability.",
"properties": {
"system": { "type": "string", "description": "Originating system, e.g. open-agent-audit, wasmagent-js." },
"adapter": { "type": "string", "description": "Name/version of the adapter that produced this canonical event." },
"source_event_type": { "type": "string", "description": "The native event type this was normalized from." }
},
"additionalProperties": true
},
"signature": {
"type": "object",
"description": "Optional tamper-evident signature over the event content; maps to aep-record.signature.",
"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": true
}
},
"additionalProperties": true
}
16 changes: 16 additions & 0 deletions schemas/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@
],
"summary": "Shared envelope base for all AEP evidence records \u2014 schema_version, trace_id, created_at_ms, and optional signature."
},
{
"id": "canonical-event",
"title": "CanonicalEvent",
"path": "schemas/aep/canonical-event.schema.json",
"canonical_id": "https://wasmagent.dev/schemas/aep/canonical-event.schema.json",
"version": "canonical-event/v0.1",
"stability": "evolving",
"owners": [
"wasmagent-protocol"
],
"consumers": [
"open-agent-audit",
"wasmagent-js"
],
"summary": "Foundational normalized event record. Heterogeneous agent evidence is normalized into CanonicalEvents that an adapter maps onto an aep-record."
},
{
"id": "constraint-ir",
"title": "ConstraintIR",
Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/invalid/canonical-event/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"schema_version": "canonical-event/v9.9",
"event_type": "not-a-real-event-type",
"timestamp_ms": 1737600000000
}
38 changes: 38 additions & 0 deletions tests/fixtures/valid/canonical-event/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"schema_version": "canonical-event/v0.1",
"event_id": "evt-0001",
"event_type": "action",
"timestamp_ms": 1737600000100,
"trace_id": "trace-001",
"run_id": "run-abc123",
"parent_event_id": "evt-0000",
"actor": {
"actor_id": "agent-1",
"actor_type": "agent",
"agent_version": "wasmagent-js@1.20.0"
},
"subject_id": "user-42",
"tool_name": "write_file",
"state_changing": true,
"data": {
"path": "/tmp/out.txt",
"bytes_written": 128
},
"refs": [
{
"uri": "file:///tmp/out.txt",
"digest": "sha256:deadbeef",
"relation": "output"
}
],
"source": {
"system": "open-agent-audit",
"adapter": "oaa-aep-adapter@0.1",
"source_event_type": "tool_call"
},
"signature": {
"alg": "ed25519",
"key_id": "k1",
"sig": "base64sig=="
}
}
6 changes: 6 additions & 0 deletions tests/fixtures/valid/canonical-event/minimal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"schema_version": "canonical-event/v0.1",
"event_id": "evt-minimal",
"event_type": "observation",
"timestamp_ms": 1737600000000
}
Loading