IntentProof is auditable execution records for actions that must be defensible—intent tied to what actually ran.
This service ingests ExecutionEvent payloads over HTTPS, keeps them in an append-only store, and serves tenant-scoped correlation queries—so proof can be reconciled with reality downstream, not only observed.
Observability captures what happened. IntentProof tells you whether it matched what was meant to happen.
Every ExecutionEvent contains:
intent: what this invocation was meant to proveaction: the stable operation id for this stepstatus: success or errorinputsandoutput: what the runtime saw going in and coming out
Modern systems—especially AI agents—do not only compute; they act: issuing refunds, sending emails, updating databases.
When something goes wrong, logs tell you what ran. They don't tell you:
- what was supposed to happen
- whether all steps completed
- whether systems ended up in a consistent state
IntentProof exists to bridge that gap.
It records intent alongside execution so systems can be verified, not just observed.
It's 4:47 on a Friday. A customer insists the critical action never happened. Support sees scattered traces; engineering sees green checks; finance asks for one clean chain: what was supposed to occur, what did occur, and whether the outcome is complete.
Ordinary telemetry shows that something ran. It rarely ships an auditable story you can hand to someone who doesn't read your codebase. IntentProof exists for when the question stops being "what was logged?" and starts being "prove it."
Repository: IntentProof/intentproof-api.
intentproof-api is the hosted ingestion plane for ExecutionEvent evidence: strict tenant boundaries, deterministic behavior, and quality gates you can trust in CI. It is built with Python, FastAPI, Pydantic, SQLAlchemy, and Postgres.
Implemented now:
POST /v1/eventsingestion endpoint- API key authentication with server-side tenant derivation
- append-only persistence model with idempotent duplicate handling (hash-based)
- tenant-scoped correlation query:
GET /v1/events/by-correlation/{correlation_id} - deterministic JSON error envelope
- quality gates:
tox,ruff, pre-commit, and 100% test coverage enforcement
Planned next:
- production auth mode (JWT or equivalent)
- cursor-based pagination for correlation queries
- OpenAPI hardening and endpoint versioning policy
- optional deploy-pipeline check that pinned
intentproof-specrevision matches conformance artifacts (when CI/CD exists) - expanded integration suite against long-lived Postgres
Shipped toward ops: Alembic migrations (Postgres), Docker image + docker-compose.yml, post-deploy scripts/smoke.sh, optional SQS transactional outbox (app/verification_queue.py) when INTENTPROOF_SQS_QUEUE_URL is set.
To keep this README unambiguous:
- Implemented now: present in the current codebase and tests.
- Planned: intended direction, not fully implemented yet.
Quick status map:
| Area | Status | Notes |
|---|---|---|
POST /v1/events ingest |
Implemented now | Auth, validation, idempotent hash check, append-only write, 202 |
GET /v1/events/by-correlation/{correlation_id} |
Implemented now | Tenant-scoped reads, ordered results, limit parameter |
| Canonical error envelope | Implemented now | unauthenticated, unauthorized_tenant, http_error |
| API key -> tenant mapping | Implemented now | Derived server-side via X-API-Key |
| Spec-generated request model | Implemented now | ExecutionEvent request model generated from intentproof-spec |
| JWT/production auth mode | Planned | API keys are MVP-only |
| Cursor pagination | Planned | Current query uses limit, no cursor token yet |
| Alembic migrations | Implemented now | Initial revision under alembic/versions/; run alembic upgrade head or use the Docker entrypoint |
| Docker / Compose | Implemented now | Dockerfile, docker-compose.yml (API + Postgres) |
| Post-append SQS (optional) | Implemented now | INTENTPROOF_SQS_QUEUE_URL → transactional proof_ingest_outbox + intentproof.proof.ingested envelope (schema_version / message_id); scripts/publish_outbox.py retries unpublished rows |
| Expanded API reference docs | Planned | Swagger/OpenAPI endpoints available, long-form reference pending |
- Python 3.12 or newer
- Postgres 15+ (recommended for local and production parity)
- Install Docker.
- Run:
docker compose up --build
- Call the API with header
X-API-Key: compose-local-key(seedocker-compose.yml). - Open docs:
http://127.0.0.1:8000/docs
Migrations run automatically via the container entrypoint (alembic upgrade head).
- Create and activate a virtual environment.
- Install dependencies:
pip install -e ".[dev]"
- Copy environment file:
cp .env.example .env
- Postgres: apply schema before first request:
alembic upgrade head
- Start the API:
uvicorn app.main:app --reload
- Open docs:
- Swagger UI:
http://127.0.0.1:8000/docs - OpenAPI JSON:
http://127.0.0.1:8000/openapi.json
- Swagger UI:
With BASE_URL and an API key:
export BASE_URL="http://127.0.0.1:8000"
export API_KEY="your-key"
bash scripts/smoke.shRequires curl and jq.
INTENTPROOF_DATABASE_URL: SQLAlchemy URL (defaults to local Postgres)INTENTPROOF_API_KEYS: JSON object mapping API key to tenant id (production deployments should use hashed keys stored in Postgres, not environment JSON)INTENTPROOF_ENV: environment name (dev,staging,prod, etc.)INTENTPROOF_SQS_QUEUE_URL(optional): Amazon SQS queue URL — after a successful append (non-duplicate), enqueueintentproof.proof.ingestedfor verification workersINTENTPROOF_AWS_REGION(optional): AWS region for the SQS client when it cannot be inferred from the environment
Example API key map:
{"dev-local-key":"tenant-dev","ops-local-key":"tenant-ops"}Status: Implemented now
GET /health- Purpose: liveness probe for local/dev orchestration
POST /v1/events- Auth:
X-API-Keyheader - Behavior:
- derives
tenant_idfrom API key map (never trusted from request body) - validates request shape with Pydantic
- computes deterministic event hash for idempotent retries
- writes append-only event record
- optionally notifies Amazon SQS for downstream verification (when
INTENTPROOF_SQS_QUEUE_URLis set; failures are logged and do not fail the request) - returns
202 Accepted
- derives
GET /v1/events/by-correlation/{correlation_id}- Auth:
X-API-Keyheader - Behavior:
- tenant-scoped reads only
- stable ascending order by insertion id
- bounded result size via
limitquery param
Status: Implemented now
All failures return a canonical envelope:
{
"code": "unauthenticated",
"message": "Missing API key.",
"details": {},
"correlation_id": null
}Current codes include:
unauthenticatedfor missing API keyunauthorized_tenantfor invalid API key / tenant accesshttp_errorfallback for framework-level HTTP exceptions
Runnable curl and Python scripts live under examples/ (see examples/README.md). Set INTENTPROOF_API_BASE and INTENTPROOF_API_KEY to match your deployment. The SDK example uses the real intentproof package — pip install -e ../intentproof-sdk-python when that repo sits next to intentproof-api (typical ~/src layout), or install intentproof-sdk from PyPI.
python3 -m tox -qstatic: Ruff formatting/lint checks- validates generated models are in sync with
intentproof-spec
- validates generated models are in sync with
cov: pytest with 100% coverage gate
Status: Implemented now
- Request model for
POST /v1/eventsis generated fromintentproof-specschema:app/generated/execution_event.py
- Generate/update models:
python3 scripts/generate_spec_models.py
- Verify drift against spec (also run by
tox -e static):bash scripts/verify-generated-models.sh
- Install once:
python3 -m pre_commit install
- Run manually:
python3 -m pre_commit run --all-files
- Hooks configured:
ruff-check --fixruff-format
app/main.py: FastAPI app, routes, exception handlingapp/auth.py: API key -> tenant mapping dependencyapp/models.py: SQLAlchemy persistence modelsapp/schemas.py: request/response and envelope schemasapp/db.py: engine/session lifecycleexamples/: samplecurland Python callers (seeexamples/README.md); sharedhttp_utils.pyfor URL validation in Python scriptstests/test_api.py: API behavior and coverage gatestox.ini: quality/test orchestration
- API keys are an MVP mechanism; move to stronger auth before production.
- Tenant identity is derived from trusted auth context, not client payload.
- Event storage is append-only in application paths.
- Keep DB credentials and keys out of logs and source control.
- Run this service behind TLS and hardened ingress in non-local environments.
These sections are intentionally reserved for upcoming docs:
- API Reference (expanded endpoint contracts)
- Auth and tenancy model (production mode)
- Data model and migrations
- Deployment guide
- SLOs, observability, and runbooks
- Verification and reconciliation integration
intentproof-spec(schemas, conformance, normative semantics)intentproof-sdk-nodeintentproof-sdk-pythonintentproof-sdk-java
- Contribution guide:
CONTRIBUTING.md - Security policy:
SECURITY.md - Change history:
CHANGELOG.md
Apache-2.0 (see LICENSE).