Skip to main content

aeo-validator-service

CI Python License: MIT

Local HTTP smoke validator for AEO and ten other recognised Kinetic Gain Suite document kinds. It sniffs a *_version field, runs limited structural checks, computes a legacy JSON hash, and compares caller-triggered re-checks. The fourth layer of the AEO Reference Stack is a reference component, not a hosted trust decision service.

1. SDKs       aeo-sdk-python / -typescript / -rust / -go / -swift
2. CLI        aeo-cli
3. Crawler    aeo-crawler
4. Validator service   <- this repo

Why an HTTP service instead of just the CLI

The CLI answers "does this document pass its checks right now?" This local HTTP reference adds three things for experimentation:

  1. HTTP for non-Python services. The CLI is Python-only. The service is a curl away.
  2. Drift across manual checks. Hash a vendor's AEO document, re-check it later, and identify changed top-level fields.
  3. Process-local watches. A watch holds a bounded history for comparison while this process runs. There is no scheduler, durable store, or alert delivery.

Install

pip install aeo-validator-service
aeo-validator-service          # binds 127.0.0.1:8091

Python 3.11+. Runtime deps: fastapi, httpx, pydantic, uvicorn. Remote fetching is disabled until AEO_FETCH_ALLOWED_HOSTS names exact vendor hostnames. For example, set AEO_FETCH_ALLOWED_HOSTS=acme.example before starting the service. URLs must use HTTPS on port 443, cannot redirect, and cannot carry credentials or query parameters. DNS is checked for non-public addresses before each fetch; a network egress policy is still needed to close DNS rebinding at the actual connection.

All endpoints are unauthenticated. Keep the process on loopback for local development. Do not expose it on a public network or use it for buyer authorization. A hosted service also needs authenticated callers, tenant isolation, network egress enforcement, rate limits, durable watch and audit state, and an operator runbook.


Endpoints

Method Path What it does
GET / Service info + supported spec list.
GET /healthz Liveness probe.
POST /validate/by-url Fetch + validate by URL. One-shot, no watch.
POST /validate/inline Validate an already-fetched document — no network.
POST /watches Create a process-local watch for a URL; the initial fetch + validation runs synchronously.
GET /watches List watch IDs.
GET /watches/{id} Watch metadata + last result.
GET /watches/{id}/history Up to 20 recent results (oldest → newest), without fetched bodies.
POST /watches/{id}/recheck Caller-triggered re-fetch + validate. Returns a structured DriftReport vs. the previous result.
DELETE /watches/{id} Delete the watch.

Supported specs

The validator sniffs the spec kind from the top-level *_version field — the same trick the unified visualizer uses. Eleven specs auto-detected:

Spec Detected via
AEO Protocol aeo_version
Prompt Provenance provenance_version
Agent Cards agent_card_version
AI Evidence Format evidence_version
MCP Tool Cards tool_card_version
AI Tutor Cards tutor_card_version
Student AI Disclosure disclosure_version
Classroom AI AUP aup_version
Clinical AI Disclosure clinical_ai_card_version
AI Incident Card incident_card_version
AI Procurement Decision Card decision_card_version

For all eleven it checks for a nonblank version field. Additional structural smoke checks currently cover AEO, agent cards, tool cards, incident cards, and decision cards. The other six kinds receive the version check only. The service also rejects unknown or ambiguous kinds. A watch's optional spec_hint must match the detected kind.

These are examples of the limited checks:

  • Universal checks — version field present, non-blank
  • Spec-specific smoke checks — AEO entity has id + type + name; agent-card has agent_id + capabilities; decision-card with approved-with-conditions requires non-empty conditions[]; etc.

valid: true means only these smoke checks passed. It does not prove schema conformance, source identity, vendor claims, signature validity, buyer approval, or permission to act. Use the corresponding specification and a trusted signature/authority workflow when those assurances matter.


Drift report

{
  "url": "https://acme.example/.well-known/aeo.json",
  "drifted": true,
  "spec_changed": false,
  "became_invalid": false,
  "became_valid": false,
  "content_hash_before": "sha256:9a3f...",
  "content_hash_after":  "sha256:b7d1...",
  "added_fields":   ["claims"],
  "removed_fields": [],
  "changed_fields": ["entity"],
  "before_issues":  0,
  "after_issues":   0
}

A drift is any of: hash changed, spec kind changed, validity flipped, or top-level field set changed. Webhooks-on-drift are an obvious follow-up (PR welcome).


Quick start

# One-shot validation:
# Start the service with AEO_FETCH_ALLOWED_HOSTS=acme.example first.
curl -X POST http://localhost:8091/validate/by-url \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://acme.example/.well-known/aeo.json", "include_body": true}'

# Process-local watch:
curl -X POST http://localhost:8091/watches \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://acme.example/.well-known/aeo.json"}'
# -> {"watch_id": "a1b2c3", ...}

# Trigger a re-check while the same process is still running:
curl -X POST http://localhost:8091/watches/a1b2c3/recheck

Hashing convention

content_hash is sha256:<hex> over Python sorted-key, compact JSON, with default ASCII escaping. It matches the legacy hash in procurement-decision-api for the same parsed JSON values. It is not the versioned RFC 8785 JCS hash used by hash-attestation-rs v0.2 or procurement's document_hashes[]. Do not compare these hash profiles or treat a hash as publisher authentication.

Fetched JSON rejects duplicate object keys and non-finite numbers. A fetch is capped at 2 MiB while streaming. The 16-watch limit and 20-result history bound limit local memory use; all watch data is lost on restart. Watch API responses omit document bodies. The optional audit-stream event contains the URL and document hash, and its delivery is best effort.


Tests

pip install -e ".[dev]"
ruff check src tests && ruff format --check src tests
mypy src
pytest -v

Test fixtures use httpx.MockTransport so no vendor URL is fetched. CI matrix Python 3.11 / 3.12 / 3.13. Local tests do not prove hosted egress, authentication, persistence, or an operator rollback.



License

MIT. See LICENSE.

Metadata

Release files for aeo-validator-service 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aeo-validator-service 0.2.0
File Size Uploaded
aeo_validator_service-0.2.0.tar.gz 21.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aeo-validator-service 0.2.0
File Interpreter ABI Platform
aeo_validator_service-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 41.4 kB

Release files / aeo_validator_service-0.2.0.tar.gz

Download URL aeo_validator_service-0.2.0.tar.gz
Size 21.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c4a5bd10851dd1a029bd714aecb09d10e8d1c94fba28c1f3128f2b669d987a55
BLAKE2b-256 checksum
How to use checksums
ecb7074db66c815b4fad438f2cd15ffe9ff6c360972ae049a76e15f908128f09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / aeo_validator_service-0.2.0-py3-none-any.whl

Download URL aeo_validator_service-0.2.0-py3-none-any.whl
Size 20.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9c224897a77c6d5abf439217e276b2924f396effa1feeedb1dd45b3fd75fe578
BLAKE2b-256 checksum
How to use checksums
482122b1dd0959dcbf43f1d04eaed68a7fb4e5b03b3347ed7d847348ee2d6310
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page