{"id":46662389,"url":"https://github.com/invariant-systems-ai/aiir","last_synced_at":"2026-04-17T04:01:07.672Z","repository":{"id":343000423,"uuid":"1174843852","full_name":"invariant-systems-ai/aiir","owner":"invariant-systems-ai","description":"AI Integrity Receipts — generate, verify, and attest cryptographic receipts for commits with declared AI involvement. Release verification with SLSA-compatible VSA. Zero dependencies. Apache 2.0.","archived":false,"fork":false,"pushed_at":"2026-04-11T12:17:03.000Z","size":2708,"stargazers_count":4,"open_issues_count":7,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-11T20:21:26.180Z","etag":null,"topics":["ai","attestation","audit","compliance","copilot","cryptography","eu-ai-act","git","github-actions","in-toto","mcp","receipts","security","slsa","supply-chain-security","verification"],"latest_commit_sha":null,"homepage":"https://invariantsystems.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/invariant-systems-ai.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":"THREAT_MODEL.md","audit":null,"citation":"CITATION.cff","codeowners":".github/CODEOWNERS","security":".github/SECURITY.md","support":null,"governance":"docs/governance-adoption-plan.md","roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-06T22:47:42.000Z","updated_at":"2026-04-11T12:16:46.000Z","dependencies_parsed_at":"2026-03-09T03:14:59.012Z","dependency_job_id":null,"html_url":"https://github.com/invariant-systems-ai/aiir","commit_stats":null,"previous_names":["invariant-systems-ai/aiir","invariant-systems-ai/receipt-action"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/invariant-systems-ai/aiir","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invariant-systems-ai%2Faiir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invariant-systems-ai%2Faiir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invariant-systems-ai%2Faiir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invariant-systems-ai%2Faiir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/invariant-systems-ai","download_url":"https://codeload.github.com/invariant-systems-ai/aiir/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invariant-systems-ai%2Faiir/sbom","scorecard":{"id":1244574,"data":{"date":"2026-03-09T01:32:11Z","repo":{"name":"github.com/invariant-systems-ai/aiir","commit":"5ea7c85b7bd7c46574548ddcdee168e0a61a3104"},"scorecard":{"version":"v5.3.0","commit":"c22063e786c11f9dd714d777a687ff7c4599b600"},"score":5.4,"checks":[{"name":"Maintained","score":0,"reason":"project was created within the last 90 days. Please review its contents carefully","details":["Warn: Repository was created within the last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/25 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#code-review"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#security-policy"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dependency-update-tool"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/publish.yml:168","Info: jobLevel 'contents' permission set to 'read': .github/workflows/scorecard.yml:28","Info: jobLevel 'actions' permission set to 'read': .github/workflows/scorecard.yml:29","Info: topLevel 'contents' permission set to 'read': .github/workflows/action-health.yml:39","Info: topLevel 'contents' permission set to 'read': .github/workflows/ci.yml:17","Warn: topLevel 'contents' permission set to 'write': .github/workflows/dependabot-auto-merge.yml:31","Warn: topLevel 'contents' permission set to 'write': .github/workflows/dogfood.yml:19","Warn: topLevel 'contents' permission set to 'write': .github/workflows/publish.yml:26","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:19","Info: topLevel 'contents' permission set to 'read': .github/workflows/sync.yml:28","Warn: topLevel 'contents' permission set to 'write': .github/workflows/update-major-tag.yml:32","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#token-permissions"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#vulnerabilities"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: containerImage not pinned by hash: Dockerfile:17: pin your Docker image by updating python:3.11-slim to python:3.11-slim@sha256:d6e4d224f70f9e0172a06a3a2eba2f768eb146811a349278b38fff3a36463b47","Warn: pipCommand not pinned by hash: Dockerfile:31-37","Warn: pipCommand not pinned by hash: Dockerfile:31-37","Warn: pipCommand not pinned by hash: .github/workflows/action-health.yml:163","Warn: pipCommand not pinned by hash: .github/workflows/action-health.yml:190","Warn: downloadThenRun not pinned by hash: .github/workflows/action-health.yml:192","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:46","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:67","Warn: downloadThenRun not pinned by hash: .github/workflows/ci.yml:84","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:109","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:132","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:156","Warn: downloadThenRun not pinned by hash: .github/workflows/publish.yml:195","Warn: downloadThenRun not pinned by hash: .github/workflows/sync.yml:85","Warn: downloadThenRun not pinned by hash: .github/workflows/sync.yml:90","Info:  25 out of  25 GitHub-owned GitHubAction dependencies pinned","Info:   3 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   9 pipCommand dependencies pinned","Info:   0 out of   5 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:162"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#packaging"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#sast"}},{"name":"CI-Tests","score":10,"reason":"5 out of 5 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#ci-tests"}},{"name":"Contributors","score":0,"reason":"project has 0 contributing companies or organizations -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#contributors"}}]},"last_synced_at":"2026-03-09T06:36:43.896Z","repository_id":343000423,"created_at":"2026-03-09T06:36:43.897Z","updated_at":"2026-03-09T06:36:43.897Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31700889,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T21:17:31.016Z","status":"ssl_error","status_checked_at":"2026-04-11T21:17:24.556Z","response_time":54,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","attestation","audit","compliance","copilot","cryptography","eu-ai-act","git","github-actions","in-toto","mcp","receipts","security","slsa","supply-chain-security","verification"],"created_at":"2026-03-08T13:02:41.490Z","updated_at":"2026-04-17T04:01:07.652Z","avatar_url":"https://github.com/invariant-systems-ai.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD041 --\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://invariantsystems.io\"\u003e\n    \u003cimg src=\"docs/logo.svg\" alt=\"Invariant Systems\" width=\"120\" height=\"120\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# AIIR — AI Integrity Receipts\n\n**The missing provenance layer for AI-assisted code.**\n\nYour team uses AI to write code. In six months, someone — an auditor, a security review, a regulator, a customer — will ask: *which parts of this codebase were AI-generated, and can you prove it?*\n\nGit history can't answer that. `Co-authored-by` trailers are inconsistent and easy to strip. Policy documents aren't machine-verifiable. Today, most AI involvement in code leaves no durable, tamper-evident trace.\n\nAIIR closes that gap. It generates deterministic, content-addressed receipts for commits with declared AI involvement, and verifies them anywhere — locally, in CI, or offline — without trusting a central service. Zero dependencies. Apache 2.0.\n\n[![PyPI](https://img.shields.io/pypi/v/aiir?color=blue)](https://pypi.org/project/aiir/)\n[![CI](https://github.com/invariant-systems-ai/aiir/actions/workflows/ci.yml/badge.svg)](https://github.com/invariant-systems-ai/aiir/actions/workflows/ci.yml)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)](https://github.com/invariant-systems-ai/aiir)\n[![Website](https://img.shields.io/badge/Website-invariantsystems.io-blue)](https://invariantsystems.io)\n[![GitHub Marketplace](https://img.shields.io/badge/Marketplace-AIIR-blue?logo=github)](https://github.com/marketplace/actions/aiir-ai-integrity-receipts)\n[![GitLab CI/CD Catalog](https://img.shields.io/badge/GitLab-CI%2FCD%20Catalog-orange?logo=gitlab)](https://gitlab.com/explore/catalog/invariant-systems/aiir)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/invariant-systems-ai/aiir/badge)](https://scorecard.dev/viewer/?uri=github.com/invariant-systems-ai/aiir)\n[![GitHub stars](https://img.shields.io/github/stars/invariant-systems-ai/aiir?style=social)](https://github.com/invariant-systems-ai/aiir/stargazers)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/demo.svg\" alt=\"AIIR terminal demo — pip install aiir \u0026\u0026 aiir --pretty\" width=\"720\"\u003e\n\u003c/p\u003e\n\n---\n\n## Install → Generate → Verify\n\n```bash\npip install aiir              # Python 3.9+, zero dependencies\ncd your-repo\naiir --pretty                 # receipt your last commit\naiir --verify .aiir/receipts.jsonl   # verify nothing was tampered with\n```\n\nThat's it. Your last commit now has a content-addressed receipt in `.aiir/receipts.jsonl`. Run it again on the same commit: same receipt, zero duplicates. Add CI and signing later only if you need stronger release evidence.\n\n### What just happened?\n\n```text\n┌─ Receipt: g1-a3f8b2c1d4e5f6a7...\n│  Commit:  c4dec85630\n│  Author:  Jane Dev \u003cjane@example.com\u003e\n│  Files:   4 changed\n│  AI:      YES (copilot)\n│  Hash:    sha256:7f3a8b...\n└──────────────────────────────────────\n```\n\nAIIR read your commit metadata, canonicalized the declared AI context, and produced a **content-addressed receipt**. Change one byte in the receipt core and verification fails — that's the tamper-evidence.\n\nWithout signing, a receipt proves **integrity** (nothing was altered). Add [Sigstore signing](#sigstore-signing) in CI for **authenticity** (proving *who* generated it).\n\nVerification does not require trusting AIIR or a hosted service. Receipts are plain JSON and can be checked anywhere a verifier runs.\n\n---\n\n## What AIIR does — and does not do\n\nAIIR does three things at its core:\n\n- Records **declared** AI involvement in commit metadata\n- Generates deterministic, tamper-evident receipts for those commits\n- Verifies those receipts independently across local, CI, and offline workflows\n\nAIIR does **not** attempt to prove hidden AI usage.\n\nIt does not claim to detect every undeclared use of Copilot, ChatGPT, Claude, Cursor, or any other tool. Its job is narrower and stronger: make declared AI involvement verifiable and tamper-evident.\n\n---\n\n## Why not just trailers or git notes?\n\nYou could track AI involvement with `Co-authored-by` trailers or ADRs — and AIIR is compatible with that. The difference:\n\n- **Machine-verifiable** — receipts have a deterministic hash. Change one byte and verification fails.\n- **Consistent** — same format across CLI, editor, CI, and AI assistants instead of ad-hoc free text.\n- **Optional signing** — add Sigstore in CI when you need cryptographic non-repudiation.\n\nTrailers are the baseline. AIIR makes that baseline verifiable.\n\n---\n\n## Declared Provenance and Optional Signal Enrichment\n\nAIIR records what is **declared** in commit metadata, not what is hidden.\n\nDetection signals are optional enrichment. They help normalize and classify declared context, but they are not authoritative proof of hidden AI usage.\n\n**Catches:** `Co-authored-by: Copilot` trailers, bot authors (Dependabot, Renovate), `Generated-by:` trailers, 48 known AI-tool signals, and Unicode evasion attempts (TR39 confusable resolution, NFKC normalization).\n\n**Does not catch:** Copilot inline completions (no trailer), copy-paste from ChatGPT, agent-mode sessions (Copilot Chat, Claude Code, Cursor Agent), squash merges that strip trailers, or amended commits.\n\nWe built this repo mostly with Copilot Chat. Of 252 dogfood receipts, 199 are classified `human` because Copilot Chat doesn't add trailers. Those false negatives aren't a bug — they're the gap AIIR exists to close by encouraging the ecosystem to declare.\n\nSee [THREAT_MODEL.md](THREAT_MODEL.md) for the full STRIDE/DREAD analysis, and the [detection table](#detection-details) below for every signal.\n\n---\n\n## System Layers\n\nAIIR is one kernel with trust layers around it, not a bundle of separate products.\n\n- **Kernel** — deterministic receipts + independent verification\n- **Assurance** — signing, policy enforcement, release evidence\n- **Adapters** — CLI, GitHub Action, GitLab CI, VS Code, MCP, browser verification\n- **Enrichment** — AI signal detection, heuristics, metadata extraction\n\nEverything above emits or verifies the same receipt format.\n\n---\n\n## Where AIIR fits in the supply chain\n\nAIIR is not a replacement for SLSA, in-toto, or SCITT. It fills a specific gap: **authorship-level provenance** — recording *who or what* produced a code change, before it enters the build pipeline.\n\n| System | Layer | What it proves | Where AIIR fits |\n|--------|-------|---------------|-----------------|\n| [SLSA](https://slsa.dev) | Build provenance | *How* an artifact was built, from which source | AIIR receipts feed SLSA as source-level attestations |\n| [in-toto](https://in-toto.io) | Supply chain attestation | That each step in a layout was performed correctly | AIIR wraps receipts as in-toto Statements (`--in-toto`) |\n| [SCITT](https://scitt.io) | Transparency ledger | That a claim was registered in a tamper-evident log | AIIR receipts are valid SCITT claims (content-addressed, signable) |\n| [Sigstore](https://sigstore.dev) | Signing infrastructure | *Who* signed an artifact (identity binding) | AIIR uses Sigstore for receipt signing (`--sign`) |\n| [OpenSSF Scorecard](https://scorecard.dev) | Project health | Security posture of an OSS project | Orthogonal — AIIR tracks per-commit AI provenance, not project posture |\n| Git trailers | Commit metadata | Free-text annotation | AIIR makes trailers machine-verifiable and tamper-evident |\n\n**Think of it this way:** Git records *that* a change happened. SLSA records *how* the artifact was built. AIIR records *what* produced the change — human, AI-assisted, or bot — with a verifiable receipt.\n\nFor narrow public adapter notes that fit AIIR into existing attestation, graph, and\npolicy ecosystems without overclaiming standards status, see [docs/ecosystem.md](docs/ecosystem.md)\nand the public hub at \u003chttps://invariantsystems.io/ecosystem/\u003e.\n\n---\n\n## Next steps: pick your path\n\nOnce the CLI works for you, add whichever surface fits your workflow:\n\n### VS Code\n\nInstall the [AIIR extension](https://marketplace.visualstudio.com/items?itemName=invariant-systems.aiir) if you want editor-side inspection and local receipt workflows in VS Code. The CLI and CI/CD integrations are the primary release surfaces today; the extension is an optional convenience layer.\n\n### CI/CD\n\n```yaml\n# GitHub Actions — one line (signing on by default)\n- uses: invariant-systems-ai/aiir@v1\n  with:\n    output-dir: .receipts/\n```\n\n```yaml\n# GitLab CI/CD Catalog — one line\ninclude:\n  - component: gitlab.com/invariant-systems/aiir/receipt@1\n```\n\nSee [GitHub Action details](#github-action-details), [GitLab CI details](#gitlab-ci-details), or [other CI platforms](#more-cicd-platforms) (Azure, CircleCI, Bitbucket, Jenkins, Docker).\n\n### AI assistants via MCP\n\n```json\n{\n  \"mcpServers\": {\n    \"aiir\": { \"command\": \"aiir-mcp-server\", \"args\": [\"--stdio\"] }\n  }\n}\n```\n\nWorks with Claude, Copilot, Cursor, Continue, Cline, and Windsurf. Your assistant generates receipts automatically after writing code.\n\n### Adoption guides\n\n| Guide | For |\n|-------|-----|\n| [Solo developer](docs/guide-solo-developer.md) | Local receipting, pre-commit hook, no CI needed |\n| [OSS maintainer](docs/guide-oss-maintainer.md) | Signed CI receipts, policy gates, contributor guidelines |\n| [Security team](docs/guide-security-team.md) | Independent verification, trust tiers, compliance integration |\n\nSee also: [Verify AIIR independently](docs/verify-independently.md) — verify receipts without trusting AIIR, using only standard tools.\n\n---\n\n## Proof points\n\nEverything below is verifiable. No testimonials-behind-a-login — just public artifacts you can audit yourself.\n\nThese proof surfaces support the kernel. They do not replace it.\n\n| Proof | What it proves | Verify it |\n|-------|---------------|-----------|\n| **This repo receipts itself** | Dogfood — AIIR generates its own receipts on every push to `main` | `for f in .receipts/*.json; do aiir --verify \"$f\"; done` |\n| **2,214 collected tests, 100% coverage** | Every release passes Python 3.9–3.13 × Ubuntu/macOS/Windows | [CI runs](https://github.com/invariant-systems-ai/aiir/actions/workflows/ci.yml) |\n| **97 conformance test vectors** | Third-party implementors can verify hashing, adversarial handling, Unicode evasion, and canonicalization | [schemas/test_vectors.json](schemas/test_vectors.json), [conformance-manifest.json](schemas/conformance-manifest.json) |\n| **153 security controls** | Full STRIDE/DREAD analysis — we show attackers what we defend against | [THREAT_MODEL.md](THREAT_MODEL.md) |\n| **Release evidence on every release** | PyPI artifacts, GitHub provenance bundles, the release SBOM, and a Rekor-backed release manifest are bound into a public verification surface | `python scripts/verify-release-evidence.py 1.3.0` |\n| **OpenSSF Scorecard** | Automated security health assessment | [Scorecard](https://scorecard.dev/viewer/?uri=github.com/invariant-systems-ai/aiir) |\n| **CycloneDX SBOM** | Machine-readable bill of materials on every GitHub Release | [Latest release](https://github.com/invariant-systems-ai/aiir/releases/latest) → `aiir-sbom.cdx.json` |\n| **Zero runtime dependencies** | Nothing to compromise | `pip install aiir \u0026\u0026 pip show aiir` |\n| **Browser verifier** | Client-side receipt verification — no upload, no account | [invariantsystems.io/verify](https://invariantsystems.io/verify) |\n\n---\n\n## Trust tiers\n\n| Tier | What you get | Use when |\n|------|-------------|----------|\n| **Unsigned** (`sign: false`) | Tamper-evident — hash integrity detects modification | Local dev, internal audit trails |\n| **Inference-Bound** | Model output cryptographically committed via hash chain | Verifying AI inference provenance |\n| **Signed** (`sign: true`, default in CI) | Authenticity — Sigstore binds the receipt to an OIDC identity | CI/CD compliance, SOC 2 evidence |\n| **Enveloped** (`--in-toto --sign`) | Signed + in-toto Statement v1 envelope | SLSA provenance, EU AI Act evidence |\n\n---\n\n## Verification pipeline\n\n```text\ngit commit → AIIR receipt → Sigstore signing → Policy evaluation → VSA → CI gate\n```\n\nFor developers: add `aiir` to CI and get a pass/fail check.\nFor security teams: get policy-evaluated results as signed attestations.\nFor auditors: query the JSONL ledger — every claim is cryptographically verifiable.\n\n```bash\n# Verify a receipt with explanation\naiir --verify receipt.json --explain\n\n# Verify an inference receipt (auto-detected by field signature)\naiir --verify inference_receipt.json\n\n# Evaluate all receipts against policy, emit a Verification Summary Attestation\naiir --verify-release --policy strict --emit-vsa\n```\n\n---\n\n## CLI reference\n\n```bash\n# Receipt the last commit (auto-saves to .aiir/receipts.jsonl)\naiir --pretty\n\n# Receipt a whole PR branch\naiir --range origin/main..HEAD --pretty\n\n# Only AI-authored commits (CI mode)\naiir --ai-only --output .receipts/\n\n# Verify with explanation\naiir --verify receipt.json --explain\n\n# Sign + in-toto envelope (full supply-chain attestation)\naiir --sign --in-toto --output .receipts/\n\n# Policy gate in CI\naiir --check --policy strict\n\n# Release verification → VSA\naiir --verify-release --receipts .aiir/receipts.jsonl --emit-vsa --policy strict\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eFull CLI reference\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\n# Print JSON to stdout for piping (bypasses ledger)\naiir --json | jq .receipt_id\n\n# JSON Lines output for streaming\naiir --range HEAD~5..HEAD --jsonl | jq .receipt_id\n\n# Custom ledger location\naiir --ledger .audit/\n\n# Wrap receipts in an in-toto Statement v1 envelope\naiir --range HEAD~3..HEAD --in-toto --output .receipts/\n\n# Attach agent attestation metadata\naiir --agent-tool copilot --agent-model gpt-4o --agent-context ide\n\n# Initialize .aiir/ directory\naiir --init                        # scaffolds receipts.jsonl, index, config, .gitignore\naiir --init --policy strict        # also creates policy.json\n\n# Review receipts — human attestation\naiir --review HEAD\naiir --review abc123 --review-outcome rejected --review-comment \"needs refactor\"\n\n# Commit trailers\naiir --trailer                     # prints AIIR-Receipt, AIIR-Type, AIIR-AI, AIIR-Verified\n\n# Policy engine\naiir --policy-init strict          # creates .aiir/policy.json\naiir --check --policy strict       # CI gate: fail if policy violated\naiir --check --max-ai-percent 50   # fail if \u003e50% commits are AI-authored\n\n# Ledger utilities\naiir --stats                       # dashboard of ledger statistics\naiir --badge                       # shields.io badge Markdown\naiir --export backup.json          # portable JSON bundle\n\n# Privacy — omit file paths from receipts\naiir --redact-files --namespace acme-corp\n\n# Native GitLab CI mode\naiir --gitlab-ci --output .receipts/\naiir --gitlab-ci --gl-sast-report\n```\n\n\u003c/details\u003e\n\n---\n\n## Reference\n\n\u003cdetails id=\"detection-details\"\u003e\n\u003csummary\u003e\u003cstrong\u003eDetection details\u003c/strong\u003e\u003c/summary\u003e\n\n### Declared AI assistance\n\n| Signal | Examples |\n|--------|----------|\n| **Copilot** | `Co-authored-by: Copilot`, `Co-authored-by: GitHub Copilot` |\n| **ChatGPT** | `Generated by ChatGPT`, `Co-authored-by: ChatGPT` |\n| **Claude** | `Generated by Claude`, `Co-authored-by: Claude` |\n| **Cursor** | `Generated by Cursor`, `Co-authored-by: Cursor` |\n| **Amazon Q / CodeWhisperer** | `amazon q`, `codewhisperer`, `Co-authored-by: Amazon Q` |\n| **Devin** | `Co-authored-by: Devin`, `devin[bot]` |\n| **Gemini** | `gemini code assist`, `google gemini`, `gemini[bot]` |\n| **GitLab Duo** | `gitlab duo`, `duo code suggestions`, `duo chat`, `duo enterprise` |\n| **Tabnine** | `tabnine` in commit metadata |\n| **Aider** | `aider:` prefix in commit messages |\n| **Generic markers** | `AI-generated`, `LLM-generated`, `machine-generated` |\n| **Git trailers** | `Generated-by:`, `AI-assisted:`, `Tool:` |\n\n### Automation / bot activity\n\n| Signal | Examples |\n|--------|----------|\n| **Dependabot** | `dependabot[bot]` as author |\n| **Renovate** | `renovate[bot]` as author |\n| **Snyk** | `snyk-bot` as author |\n| **CodeRabbit** | `coderabbit[bot]` as author |\n| **GitHub Actions** | `github-actions[bot]` as author |\n| **GitLab Bot** | `gitlab-bot` as author |\n| **DeepSource** | `deepsource[bot]` as author |\n\nSince v1.0.4, bot and AI signals are fully separated. A Dependabot commit gets `is_bot_authored: true` and `authorship_class: \"bot\"`, **not** `is_ai_authored: true`.\n\n### Detection internals\n\nHomoglyph detection uses the full [Unicode TR39 confusable map](https://www.unicode.org/reports/tr39/) — 669 single-codepoint → ASCII mappings across 69 scripts. Combined with NFKC normalization, this covers all single-character homoglyphs documented by the Unicode Consortium. Multi-character confusable sequences are not covered — see S-02 in the threat model.\n\n\u003c/details\u003e\n\n\u003cdetails id=\"github-action-details\"\u003e\n\u003csummary\u003e\u003cstrong\u003eGitHub Action details\u003c/strong\u003e\u003c/summary\u003e\n\n### Full workflow (signed, with PR integration)\n\n```yaml\nname: AIIR\non:\n  push:\n    tags-ignore: ['**']\n  pull_request:\n\npermissions:\n  id-token: write\n  contents: read\n  checks: write\n  pull-requests: write\n\njobs:\n  receipt:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: invariant-systems-ai/aiir@v1\n        with:\n          output-dir: .receipts/\n```\n\nSigning is **on by default**. Artifacts uploaded automatically when `output-dir` is set.\n\n**Hardened (pin to full SHA):**\n\n```yaml\n      - uses: invariant-systems-ai/aiir@a54fe440a2be18fe51ad30149f1bbab944d578e5  # v1\n```\n\n**Unsigned (no permissions needed):**\n\n```yaml\n      - uses: invariant-systems-ai/aiir@v1\n        with:\n          sign: false\n```\n\n**Automatic PR integration** (when `GITHUB_TOKEN` is available):\n\n- Creates an `aiir/verify` Check Run (pass/fail status on every PR)\n- Posts a receipt summary comment (idempotent, no spam)\n\n### Inputs\n\n| Input | Description | Default |\n|-------|-------------|---------|\n| `ai-only` | Only receipt AI-authored commits | `false` |\n| `commit-range` | Specific commit range (e.g., `main..HEAD`) | Auto-detected |\n| `output-dir` | Directory to write receipt JSON files | *(log only)* |\n| `sign` | Sign receipts with Sigstore | `true` |\n\n### Outputs\n\n| Output | Description |\n|--------|-------------|\n| `receipt_count` | Number of receipts generated |\n| `ai_commit_count` | Number of AI-authored commits detected |\n| `signed_receipt_count` | Number of signed receipts generated |\n| `unsigned_receipt_count` | Number of unsigned receipts generated |\n| `receipts_json` | Full JSON array (set to `\"OVERFLOW\"` if \u003e1 MB) |\n| `receipts_overflow` | `\"true\"` when truncated |\n\n\u003e ⚠️ **Security note on `receipts_json`**: Contains commit metadata which may include shell metacharacters. **Never** interpolate directly into `run:` steps via `${{ }}`. Write to a file instead.\n\n### Example: PR Comment with AI Summary\n\n```yaml\n      - uses: invariant-systems-ai/aiir@v1\n        id: receipt\n        with:\n          output-dir: .receipts/\n\n      - name: Comment on PR\n        if: steps.receipt.outputs.ai_commit_count \u003e 0\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const count = '${{ steps.receipt.outputs.ai_commit_count }}';\n            const total = '${{ steps.receipt.outputs.receipt_count }}';\n            const signed = '${{ steps.receipt.outputs.signed_receipt_count }}';\n            const unsigned = '${{ steps.receipt.outputs.unsigned_receipt_count }}';\n            github.rest.issues.createComment({\n              issue_number: context.issue.number,\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              body: `🔐 **AIIR**: ${total} commits receipted, ${count} AI-authored, ${signed} signed, ${unsigned} unsigned.\\n\\nReceipts uploaded as build artifacts.`\n            });\n```\n\n\u003c/details\u003e\n\n\u003cdetails id=\"gitlab-ci-details\"\u003e\n\u003csummary\u003e\u003cstrong\u003eGitLab CI details\u003c/strong\u003e\u003c/summary\u003e\n\n**CI/CD Catalog component** (recommended — [browse in Catalog](https://gitlab.com/explore/catalog/invariant-systems/aiir)):\n\n```yaml\ninclude:\n  - component: gitlab.com/invariant-systems/aiir/receipt@1\n    inputs:\n      stage: test\n```\n\n| Input | Type | Default | Description |\n|-------|------|---------|-------------|\n| `stage` | string | `test` | Pipeline stage |\n| `version` | string | `1.3.0` | AIIR version from PyPI |\n| `ai-only` | boolean | `false` | Only receipt AI-authored commits |\n| `output-dir` | string | `.aiir-receipts` | Artifact output directory |\n| `artifact-expiry` | string | `90 days` | Artifact retention |\n| `sign` | boolean | `true` | Sigstore keyless signing (GitLab OIDC) |\n| `gl-sast-report` | boolean | `false` | Generate SAST report for Security Dashboard |\n| `approval-threshold` | number | `0` | AI% threshold for extra MR approvals (0 = off) |\n| `extra-args` | string | `\"\"` | Additional CLI flags |\n\n**Legacy include** (no Catalog required):\n\n```yaml\ninclude:\n  - remote: 'https://raw.githubusercontent.com/invariant-systems-ai/aiir/v1.3.0/templates/gitlab-ci.yml'\n```\n\n**Self-hosted GitLab?** Mirror the repo and use `project:` instead:\n\n```yaml\ninclude:\n  - project: 'your-group/aiir'\n    ref: 'v1.3.0'\n    file: '/templates/gitlab-ci.yml'\n```\n\nCustomise via pipeline variables: `AIIR_VERSION`, `AIIR_AI_ONLY`, `AIIR_EXTRA_ARGS`, `AIIR_ARTIFACT_EXPIRY`. See [templates/gitlab-ci.yml](templates/gitlab-ci.yml).\n\n\u003c/details\u003e\n\n\u003cdetails id=\"more-cicd-platforms\"\u003e\n\u003csummary\u003e\u003cstrong\u003eMore CI/CD platforms (Docker, Bitbucket, Azure, CircleCI, Jenkins)\u003c/strong\u003e\u003c/summary\u003e\n\n### Docker\n\n```bash\ndocker run --rm -v \"$(pwd):/repo\" -w /repo invariantsystems/aiir --pretty\ndocker run --rm -v \"$(pwd):/repo\" -w /repo invariantsystems/aiir --ai-only --output .receipts/\n```\n\nWorks in any CI system that supports container steps — Tekton, Buildkite, Drone, Woodpecker, etc.\n\n### pre-commit Hook\n\n```yaml\n# .pre-commit-config.yaml\nrepos:\n  - repo: https://github.com/invariant-systems-ai/aiir\n    rev: v1.3.0\n    hooks:\n      - id: aiir\n```\n\nRuns **post-commit**. Customise with args: `[\"--ai-only\", \"--output\", \".receipts\"]`\n\n### Bitbucket Pipelines\n\n```yaml\npipelines:\n  default:\n    - step:\n        name: AIIR Receipt\n        image: python:3.11\n        script:\n          - pip install aiir\n          - aiir --pretty --output .receipts/\n        artifacts:\n          - .receipts/**\n```\n\nFull template: [templates/bitbucket-pipelines.yml](templates/bitbucket-pipelines.yml)\n\n### Azure DevOps\n\n```yaml\nsteps:\n  - task: UsePythonVersion@0\n    inputs: { versionSpec: '3.11' }\n  - script: pip install aiir \u0026\u0026 aiir --pretty --output .receipts/\n    displayName: 'Generate AIIR receipt'\n  - publish: .receipts/\n    artifact: aiir-receipts\n```\n\nFull template: [templates/azure-pipelines.yml](templates/azure-pipelines.yml)\n\n### CircleCI\n\n```yaml\njobs:\n  receipt:\n    docker:\n      - image: cimg/python:3.11\n    steps:\n      - checkout\n      - run: pip install aiir \u0026\u0026 aiir --pretty --output .receipts/\n      - store_artifacts:\n          path: .receipts\n```\n\nFull template: [templates/circleci/config.yml](templates/circleci/config.yml)\n\n### Jenkins\n\n```groovy\npipeline {\n    agent { docker { image 'python:3.11' } }\n    stages {\n        stage('AIIR Receipt') {\n            steps {\n                sh 'pip install aiir \u0026\u0026 aiir --pretty --output .receipts/'\n                archiveArtifacts artifacts: '.receipts/**'\n            }\n        }\n    }\n}\n```\n\nFull template: [templates/jenkins/Jenkinsfile](templates/jenkins/Jenkinsfile)\n\n\u003c/details\u003e\n\n\u003cdetails id=\"sigstore-signing\"\u003e\n\u003csummary\u003e\u003cstrong\u003eSigstore signing\u003c/strong\u003e\u003c/summary\u003e\n\nSign receipts with [Sigstore](https://sigstore.dev) keyless signing for cryptographic non-repudiation:\n\n```yaml\npermissions:\n  id-token: write\n  contents: read\n\nsteps:\n  - uses: invariant-systems-ai/aiir@v1\n    with:\n      output-dir: .receipts/\n      sign: true\n```\n\n\u003e **Fork PRs**: GitHub does not grant OIDC tokens to fork pull requests. AIIR will detect the missing credential and fail with a clear error rather than hanging.\n\nEach receipt gets an accompanying `.sigstore` bundle (Fulcio certificate + Rekor transparency log entry + signature).\n\n```bash\n# Basic: checks signature is valid (any signer)\naiir --verify receipt.json --verify-signature\n\n# Recommended: pin to a specific CI identity\naiir --verify receipt.json --verify-signature \\\n  --signer-identity \"https://github.com/myorg/myrepo/.github/workflows/aiir.yml@refs/heads/main\" \\\n  --signer-issuer \"https://token.actions.githubusercontent.com\"\n```\n\n\u003e ⚠️ **Always use `--signer-identity` and `--signer-issuer` in production.**\n\u003e Without identity pinning, verification accepts any valid Sigstore signature.\n\nInstall signing support: `pip install aiir[sign]`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eLedger — .aiir/ directory\u003c/strong\u003e\u003c/summary\u003e\n\nBy default, `aiir` appends receipts to a local JSONL ledger:\n\n```text\n.aiir/\n├── receipts.jsonl   # One receipt per line (append-only)\n└── index.json       # Auto-maintained lookup index\n```\n\n- **One file to commit** — `git add .aiir/` is your entire audit trail\n- **Auto-deduplicates** — re-running `aiir` on the same commit is a no-op\n- **Git-friendly** — append-only JSONL means clean diffs and easy `git blame`\n- **Queryable** — `jq`, `grep`, and `wc -l` all work naturally\n\n| Flag | Behaviour |\n|------|-----------|\n| *(none)* | Append to `.aiir/receipts.jsonl` (default) |\n| `--ledger .audit/` | Append to custom ledger directory |\n| `--json` | Print JSON to stdout — no ledger write |\n| `--jsonl` | Print JSON Lines to stdout — no ledger write |\n| `--output dir/` | Write individual files to `dir/` — no ledger write |\n| `--pretty` | Human-readable summary to stderr (combines with any mode) |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eReceipt format\u003c/strong\u003e\u003c/summary\u003e\n\n```json\n{\n  \"type\": \"aiir.commit_receipt\",\n  \"schema\": \"aiir/commit_receipt.v2\",\n  \"receipt_id\": \"g1-a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4\",\n  \"content_hash\": \"sha256:7f3a...\",\n  \"timestamp\": \"2026-03-06T09:48:59Z\",\n  \"commit\": {\n    \"sha\": \"c4dec85630232666aba81b6588894a11d07e5d18\",\n    \"author\": { \"name\": \"Jane Dev\", \"email\": \"jane@example.com\" },\n    \"subject\": \"feat: add receipt generation to CI\",\n    \"files_changed\": 4\n  },\n  \"ai_attestation\": {\n    \"is_ai_authored\": true,\n    \"signals_detected\": [\"message_match:co-authored-by: copilot\"],\n    \"authorship_class\": \"ai_assisted\",\n    \"detection_method\": \"heuristic_v2\"\n  }\n}\n```\n\n**Content-addressed**: `receipt_id` is derived from SHA-256 of the canonical JSON. Change any field → hash changes → receipt invalid.\n\n\u003e **Receipt identity depends on repository provenance.**\n\u003e The `provenance.repository` field is part of the content hash. The same commit\n\u003e produces a different `receipt_id` if the remote URL changes (fork, rename, etc.).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eRelease verification \u0026 VSA\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\naiir --verify-release --receipts .aiir/receipts.jsonl --policy strict --emit-vsa\n```\n\nProduces an [in-toto Statement v1](https://in-toto.io/Statement/v1) with a [Verification Summary Attestation](https://slsa.dev/verification_summary) predicate recording: verifier identity, policy digest, coverage metrics, and pass/fail result.\n\nPolicy presets: `strict` (hard-fail, signing required, zero unsigned receipts, max 50% AI), `balanced` (soft-fail, signing recommended), `permissive` (warn-only). Customise via `.aiir/policy.json`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003ePolicy engine\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\naiir --policy-init strict   # creates .aiir/policy.json\naiir --check --policy strict\naiir --check --max-ai-percent 50\n```\n\n| Preset | Enforcement | Signing | Max AI % | Use case |\n|--------|-------------|---------|----------|----------|\n| `strict` | Hard-fail | Required | 50% | Regulated industries, SOC 2, EU AI Act |\n| `balanced` | Soft-fail | Recommended | 80% | Most teams |\n| `permissive` | Warn-only | Optional | 100% | Early adoption |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eAgent attestation\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\naiir --agent-tool copilot --agent-model gpt-4o --agent-context ide\n```\n\nStored in `extensions.agent_attestation` (not part of the content hash). Six allowlisted keys: `tool_id`, `model_class`, `session_id`, `run_context`, `tool_version`, `confidence`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eMCP server details\u003c/strong\u003e\u003c/summary\u003e\n\nSeven tools: `aiir_receipt`, `aiir_verify`, `aiir_stats`, `aiir_explain`, `aiir_policy_check`, `aiir_verify_release`, `aiir_gitlab_summary`.\n\n**Claude Desktop** (`claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"aiir\": { \"command\": \"aiir-mcp-server\", \"args\": [\"--stdio\"] }\n  }\n}\n```\n\n**VS Code / Copilot** (`.vscode/mcp.json`):\n\n```json\n{\n  \"servers\": {\n    \"aiir\": { \"command\": \"aiir-mcp-server\", \"args\": [\"--stdio\"] }\n  }\n}\n```\n\nAlso works with Cursor (`.cursor/mcp.json`), Continue (`.continue/mcpServers/`), Cline (`cline_mcp_settings.json`), and Windsurf (`~/.codeium/windsurf/mcp_config.json`).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003ein-toto Statement wrapping\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\naiir --in-toto --output .receipts/\naiir --sign --in-toto --output .receipts/\n```\n\nCurrent predicate type: `https://invariantsystems.io/predicates/aiir/commit_receipt/v2`. Compatible with SLSA verifiers, Sigstore policy-controller, Kyverno/OPA, and Tekton Chains. Legacy `aiir/commit_receipt.v1` receipts use the matching `/v1` predicate URI.\n\n\u003c/details\u003e\n\n---\n\n## Show AIIR in your README\n\nAdd a transparency badge so reviewers and auditors know your project receipts AI involvement:\n\n```bash\naiir --badge        # auto-generates Markdown with your repo's AI %\n```\n\nOr copy a static badge:\n\n```markdown\n[![AIIR Receipts](https://img.shields.io/badge/AIIR-Receipted-blue)](https://github.com/invariant-systems-ai/aiir)\n```\n\nPreview: [![AIIR Receipts](https://img.shields.io/badge/AIIR-Receipted-blue)](https://github.com/invariant-systems-ai/aiir)\n\nThe `--badge` variant reads your ledger and shows the actual AI-assisted percentage. The static badge signals adoption without revealing stats.\n\n---\n\n## Specification \u0026 schemas\n\n| Document | Purpose |\n|----------|---------|\n| [SPEC.md](SPEC.md) | Normative specification — canonical JSON, content addressing, verification |\n| [SPEC_GOVERNANCE.md](SPEC_GOVERNANCE.md) | Change control, compatibility policy, extension registry |\n| [docs/ecosystem.md](docs/ecosystem.md) | Where AIIR fits — comparison with SLSA, in-toto, SCITT, Sigstore |\n| [schemas/commit_receipt.v2.schema.json](schemas/commit_receipt.v2.schema.json) | JSON Schema (draft 2020-12) for current receipt format |\n| [schemas/test_vectors.json](schemas/test_vectors.json) | 25 core vectors in this file; 97 total across all published vector files and formats |\n| [schemas/verification_summary.v1.schema.json](schemas/verification_summary.v1.schema.json) | JSON Schema for VSA predicate |\n| [THREAT_MODEL.md](THREAT_MODEL.md) | STRIDE/DREAD threat model |\n| [docs/tamper-detection.md](docs/tamper-detection.md) | Walkthrough — what happens when a receipt is modified |\n| [docs/stability-contract.md](docs/stability-contract.md) | 1.0 stability contract — what freezes, what doesn't |\n| [docs/verify-independently.md](docs/verify-independently.md) | Verify receipts without trusting AIIR |\n\n---\n\n## About\n\nBuilt by [Invariant Systems, Inc.](https://invariantsystems.io) — Apache-2.0.\n\n**Citing**: Use the **Cite this repository** button on GitHub or see [CITATION.cff](CITATION.cff).\n\n**Trademarks**: \"AIIR\", \"AI Integrity Receipts\", and \"Invariant Systems\" are trademarks of Invariant Systems, Inc. See [TRADEMARK.md](TRADEMARK.md).\n\n**Signed releases**: Every PyPI release uses [Trusted Publishers](https://docs.pypi.org/trusted-publishers/) (OIDC) — no static API tokens. Each release is tied to a specific GitHub Actions run, commit SHA, and workflow file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finvariant-systems-ai%2Faiir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finvariant-systems-ai%2Faiir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finvariant-systems-ai%2Faiir/lists"}