Skip to main content

procurement-decision-api

CI License: MIT Python Framework: FastAPI

The machine that produces buyer-side AI procurement decisions, schema-conformant and ready to publish.

A FastAPI service that ingests a buyer's evaluation rubric plus a set of vendor Kinetic Gain Protocol Suite declarations and returns a draft AI Procurement Decision Card (spec #11 of the Suite). The Decision Card is the canonical machine-readable carrier for NIST AI RMF-aligned procurement outcomes under OMB M-24-10 — see the crosswalk doc.

The cross-ecosystem bridge

This is the first repo that composes the Kinetic Gain Protocol Suite with the Decision Intelligence Engines portfolio:

Vendor publishes:                Buyer publishes (this service produces):
─────────────────────────        ────────────────────────────────────────
AEO Protocol Card           ┐
Tool Disclosure             │
Clinical AI Card            ├──> AI Procurement Decision Card
Student AI Disclosure       │       (status / rubric / conditions /
Agent Card                  │        documents reviewed / rationale)
…the other six specs…       ┘

Quick start

pip install procurement-decision-api
procurement-decision-api  # listens on http://0.0.0.0:8088

Or via Docker:

docker run -p 8088:8088 ghcr.io/mizcausevic-dev/procurement-decision-api:latest

Then draft a decision:

curl -s http://localhost:8088/decisions/draft \
  -H 'content-type: application/json' \
  -d '{
    "decision_id": "SPRINGFIELD-DEC-2026-001",
    "buyer": {
      "name": "Springfield Unified School District",
      "type": "school-district",
      "jurisdiction": "US-CA"
    },
    "decision_maker": {
      "role": "Director of Educational Technology",
      "name": "Dr. Jane Doe",
      "authority": "Board Resolution 2026-04"
    },
    "vendor_name": "AcmeTutor Inc.",
    "product_name": "AcmeTutor 3.0",
    "vendor_id": "https://acmetutor.example/.well-known/aeo.json",
    "fetch_targets": [
      { "type": "aeo",                    "url": "https://acmetutor.example/.well-known/aeo.json" },
      { "type": "tutor-card",             "url": "https://acmetutor.example/.well-known/tutor-card.json" },
      { "type": "student-ai-disclosure",  "url": "https://acmetutor.example/.well-known/student-ai-disclosure.json" }
    ],
    "policy_uris": [
      "https://springfield.edu/.well-known/aup.json"
    ],
    "rubric": [
      { "id": "ferpa-compliance",         "result": "pass", "weight": 1.0 },
      { "id": "coppa-compliance",         "result": "pass", "weight": 1.0 },
      { "id": "no-training-on-student-data", "result": "pass-with-condition", "weight": 1.0,
        "notes": "Disclosure asserts no-training; require contractual confirmation." },
      { "id": "bias-audit-completed",     "result": "partial", "weight": 0.8,
        "notes": "Audit current but due for refresh by 2026-09." }
    ],
    "conditions": [
      { "id": "no-training-restriction",
        "description": "Vendor SHALL NOT use Springfield USD student-provided content for model training.",
        "enforcement": "contractual" },
      { "id": "bias-audit-refresh",
        "description": "Vendor SHALL deliver a refreshed third-party bias audit by 2026-12-01.",
        "enforcement": "audit" }
    ]
  }' | jq

The response includes:

  • draft — the full, schema-conformant Decision Card (ready to sign + publish at /.well-known/decisions/<id>.json)
  • documents_fetched[] — each vendor URL with its retrieval timestamp + sha256 content hash
  • fetch_errors[] — per-target retrieval errors (the draft doesn't fail wholesale on one missing URL)
  • inferred_status — true if the service inferred the decision status from the rubric

What the service does

  1. Fetches every URL in fetch_targets concurrently with httpx, capped at 2 MB / 10 s per document, and computes a canonical sha256 hash over each (sorted keys, no whitespace).
  2. Infers decision.status from the rubric if you didn't supply proposed_status. The inference rules:
    • Any fail → rejected-with-remediation
    • Any partial or pass-with-condition → approved-with-conditions
    • All pass → approved
    • Empty / all n/a → pending
  3. Composes a default rationale from the rubric results if you didn't supply rationale_template.
  4. Validates the Decision Card against the same conditional rules the upstream zod schema enforces:
    • status ∈ {approved-with-conditions, rejected-with-remediation} → conditions must be non-empty
    • status = withdrawn → withdrawal block required
    • publication.is_public = true → publication_uri required
  5. Returns the Draft Decision Card. Review, edit, sign, publish.

Endpoints

Method Path Purpose
GET / Service info + relevant links
GET /healthz Liveness probe (always 200 if the process is running)
POST /decisions/draft Produce a Draft Decision Card
POST /decisions/validate Validate an existing Decision Card against the v0.1 schema
GET /docs Interactive OpenAPI documentation (Swagger UI)
GET /openapi.json Machine-readable API schema

Why this matters

AI procurement under OMB M-24-10 and NIST AI RMF requires agencies to publish reviewable decisions about vendor AI systems. Today, those decisions sit in PDFs and procurement databases — invisible to vendors trying to win future RFPs and invisible to citizens whose data is being processed.

The AI Procurement Decision Card spec defines a machine-readable carrier for those decisions. This service is the tool that produces them at scale: a reviewer fills in the rubric, points at the vendor's published declarations, and gets back a schema-valid card ready to publish at /.well-known/decisions/<decision_id>.json.

For procurement teams, this means a decision becomes a queryable, searchable, audit-friendly artifact — and the vendor's published declarations are cited by URL and content hash, so any drift after the decision is detectable.

Architecture

┌────────────────────────────────────────────────────────────┐
│                  FastAPI app (lifespan-managed)            │
│                                                            │
│   POST /decisions/draft                                    │
│       │                                                    │
│       ▼                                                    │
│   ┌────────────────────────────────────────────────┐       │
│   │ fetcher.fetch_documents (async, httpx)         │       │
│   │   - timeout 10s per doc                        │       │
│   │   - 2 MB size cap                              │       │
│   │   - canonical sha256 hash                      │       │
│   │   - per-target error collection                │       │
│   └────────────────────────────────────────────────┘       │
│       │                                                    │
│       ▼                                                    │
│   ┌────────────────────────────────────────────────┐       │
│   │ rubric.infer_status                            │       │
│   │ rubric.compose_rationale                       │       │
│   │ rubric.weighted_score                          │       │
│   └────────────────────────────────────────────────┘       │
│       │                                                    │
│       ▼                                                    │
│   ┌────────────────────────────────────────────────┐       │
│   │ drafter.draft_decision_card                    │       │
│   │   - validates conditional rules                │       │
│   │   - assembles history events                   │       │
│   └────────────────────────────────────────────────┘       │
│       │                                                    │
│       ▼                                                    │
│   DraftResponse                                            │
└────────────────────────────────────────────────────────────┘

Pydantic v2 models mirror the JSON Schema 2020-12 spec exactly, including the conditional rules (which run as @model_validator(mode="after") hooks).

Development

git clone https://github.com/mizcausevic-dev/procurement-decision-api
cd procurement-decision-api
pip install -e ".[dev]"

# Run the test suite (mocks the vendor HTTP layer; no internet required)
pytest -q

# Lint, format, typecheck
ruff check src tests
ruff format src tests
mypy src

# Run the service
python -m procurement_decision_api
# or
uvicorn procurement_decision_api.app:app --reload --port 8088

Composability

This service composes naturally with the rest of the Kinetic Gain ecosystem:

  • Input documents can be fetched directly from any vendor's /.well-known/ paths, or validated first via kg-validate-action in your CI.
  • Output Decision Cards can be inspected by mcp-kinetic-gain (tools: decision_card_inspect, decision_card_validate).
  • Inline validation in the browser is available at validator.kineticgain.com — paste the produced draft, get inline error markers.

License

MIT. The Kinetic Gain Protocol Suite specifications this service produces are also MIT; reference implementations like mcp-kinetic-gain are AGPL-3.0.

Related

Metadata

Release files for procurement-decision-api 0.1.1

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

Source distribution (sdist)

Source distribution for procurement-decision-api 0.1.1
File Size Uploaded
procurement_decision_api-0.1.1.tar.gz 20.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for procurement-decision-api 0.1.1
File Interpreter ABI Platform
procurement_decision_api-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 39.7 kB

Release files / procurement_decision_api-0.1.1.tar.gz

Download URL procurement_decision_api-0.1.1.tar.gz
Size 20.8 kB
Tags Source
SHA-256 checksum
How to use checksums
23ba3e358a31b2a4c045f16e5076597a9bd028f0b44c85247b645688b99dcf75
BLAKE2b-256 checksum
How to use checksums
b06f0af95cc6d69d891024206a5950c8fb46ebdee8d44ecc813a9b60beea4a2b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 15, 2026.

Transparency log

Release files / procurement_decision_api-0.1.1-py3-none-any.whl

Download URL procurement_decision_api-0.1.1-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c66d3106c9ae64f1e2ed6d1bb4ad91334dd67dea7e0060e4478440a49196510
BLAKE2b-256 checksum
How to use checksums
002dc9d74a6f3924a3174612ec224bbfac796f62fdaa3be3d174eb81e5f928b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

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