From 7e7f28d6d8ba8d94cd42d8f3ff4989bf637068d6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:41:36 +0000 Subject: [PATCH 1/3] AC-037: add AGENTS.md machine-facing operating instructions No agent instruction surface existed (no AGENTS.md, CONTRIBUTING.md, skills, or machine-readable usage guidance), so this is additive rather than duplicative. Documents only verified behavior: the six real CLI commands, the three valid --execution-result values, the canonical success and both canonical refusal paths, receipt verification including the wrapper-vs-receipt extraction step that returns VEIP_RECEIPT_MALFORMED if skipped, exit-code semantics, the library entry points, and the full stable reason-code set extracted from source rather than recalled. States plainly what does not exist - no PyPI package, no HTTP/gRPC service, no persistence, no multi-contract registry, no replay protection, no telemetry - and carries the claim ceiling, the undeclared-license position, and the distinction between the gate workflow existing and GitHub enforcing it. Includes an explicit prohibition on inventing commands, interfaces, or maturity, and instructs agents not to treat a refusal as a failure to work around. Documentation only; no runtime, test, fixture, or workflow change. --- AGENTS.md | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cb97447 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,254 @@ +# AGENTS.md — instructions for AI coding/operations agents + +Machine-facing operating instructions for this repository. Every command and +behavior below was executed against committed fixtures at this commit. No +marketing language, no aspirational capability. + +**Hard rule: do not invent commands, flags, interfaces, endpoints, or maturity +claims that are not listed here.** If a capability you need is not documented in +this file, it does not exist in this repository. Report that as a limitation +rather than improvising a substitute or assuming an undocumented interface. + +--- + +## 1. What AuthContract is + +AuthContract turns an institutional rule into a canonical, digest-bound artifact, +evaluates a proposed action against that rule together with runtime facts, and +issues a decision receipt whose every bound value can be independently +recomputed from the raw inputs. + +Implemented chain: + +``` +contract artifact + → canonical identity (RFC 8785 JCS + SHA-256) and sibling digest binding + → deterministic projection into a declared action domain + → runtime fact admission (issuer / trust basis / freshness / evidence binding) + → action check against the projection + → ALLOW or REFUSE + → decision receipt (on ALLOW only) + → independent receipt verification from raw inputs +``` + +## 2. Current maturity + +Experimental reference implementation, **TRL 4**. Implemented, tested, and +benchmarked against **one synthetic banking specimen family**. + +**Automated natural-language source-to-rule comparison is NOT implemented end to +end.** It is the project's target capability. Worked examples in `README.md` +below the `# How it works — the full model` divider describe target behavior, not +current behavior. Do not represent it as working. + +## 3. Requirements + +- Python **>= 3.10** (`pyproject.toml: requires-python = ">=3.10"`). CI tests 3.10 and 3.12. +- `git`. +- No credentials, services, or network beyond clone and dependency install. + +## 4. Installation + +```bash +git clone https://github.com/veraxis-protocol/AuthContract.git +cd AuthContract +python3 -m venv .venv && source .venv/bin/activate +pip install -e ".[test]" +``` + +Verify: `pytest -q` → `342 passed`. + +**Not on PyPI.** `pip install authcontract` will not work. Install from source only. + +## 5. Supported CLI commands + +Exactly six. Any other subcommand does not exist. + +| Command | Purpose | +|---|---| +| `authcontract verify ` | Verify one rule artifact's canonical identity | +| `authcontract project ` | Project a rule into its declared runtime action domain | +| `authcontract check-action ` | Check an action against the declared domain | +| `authcontract git-gate ` | Check a CI result against the version that would actually merge | +| `authcontract run-specimen --execution-result ` | Full end-to-end check; issues a receipt on PASS | +| `authcontract verify-receipt ` | Recompute the receipt bindings from raw inputs and compare | + +`--execution-result` accepts exactly: `NOT_EXECUTED`, `SIMULATED_SUCCESS`, `SIMULATED_FAILURE`. + +All commands emit **single-line JSON on stdout**. + +## 6. Canonical successful end-to-end command + +```bash +authcontract run-specimen \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_valid.json \ + fixtures/runtime/facts_valid.json \ + --execution-result SIMULATED_SUCCESS +``` + +Expect `"status": "PASS"`, `"decision": "ALLOW"`, `"reason_code": "OK"`, a +`receipt` object with 10 bound fields, and **exit code 0**. + +## 7. Canonical refusal commands + +Undeclared action → `RUN_UNCLASSIFIED_ACTION`: + +```bash +authcontract run-specimen \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_unknown_action_type.json \ + fixtures/runtime/facts_valid.json \ + --execution-result SIMULATED_SUCCESS +``` + +Stale runtime fact → `RUN_FACT_STALE`: + +```bash +authcontract run-specimen \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_valid.json \ + fixtures/runtime/facts_stale.json \ + --execution-result SIMULATED_SUCCESS +``` + +Both return `"status": "REFUSED"` and **exit code 1**. **No receipt is issued on +refusal.** A refusal is correct, expected behavior — do not treat it as a failure +to be worked around, and do not retry with altered inputs to force an ALLOW. + +## 8. Receipt verification + +```bash +authcontract verify-receipt \ + fixtures/runtime/receipt_valid.json \ + fixtures/banking_payment_specimen.json \ + fixtures/actions/send_payment_valid.json \ + fixtures/runtime/facts_valid.json +``` + +Expect `"status": "PASS"`, `"reason_code": "OK"`, exit `0`. This recomputes every +bound value from raw inputs and trusts no field in the receipt. + +`verify-receipt` requires the **receipt object itself**, not the full +`run-specimen` wrapper. Extract it first: + +```bash +authcontract run-specimen ... > /tmp/full.json +python3 -c "import json; json.dump(json.load(open('/tmp/full.json'))['receipt'], open('/tmp/receipt.json','w'))" +``` + +Passing the wrapper returns `VEIP_RECEIPT_MALFORMED`. + +## 9. Exit-code semantics + +| Exit | Meaning | +|---|---| +| `0` | PASS / ALLOW | +| `1` | REFUSED, or an error condition | + +Branch on the JSON `status` and `reason_code` fields rather than parsing prose. + +## 10. Reason codes + +`reason_code` is a **stable machine-facing identifier**; `OK` on success. +`message` (present on refusal) is human-readable and **not** a stable contract — +do not parse it. + +Codes observed in the implementation, by family: + +- **Artifact/identity:** `AC_DIGEST`, `AC_DIGEST_SCOPE`, `AC_INVALID_JSON`, `AC_INVALID_STRUCTURE`, `AC_IO_ERROR`, `AC_INTERNAL_ERROR` +- **Projection/action:** `RUN_UNCLASSIFIED_ACTION`, `RUN_DOMAIN_ESCAPE`, `RUN_INACTIVE_CONTRACT`, `CONTRACT_SCOPE_CONFLICT` +- **Runtime facts:** `RUN_FACT_STALE`, `RUN_FACT_INADMISSIBLE`, `RUN_FACT_IDENTITY_MISMATCH`, `RUN_FACT_EVIDENCE_MISMATCH`, `RUN_FACT_UNATTESTED`, `RUN_FACT_SELF_ASSERTED`, `RUN_FACT_TRUST_BASIS`, `RUN_FACT_REPRESENTATION`, `RUN_FACT_FUTURE_TIMESTAMP`, `RUN_FACT_TIME_UNVERIFIABLE`, `RUN_FACT_TYPE_UNSUPPORTED`, `RUN_FACT_CORROBORATION_MISSING`, `RUN_FACT_CONTRACT_INVALID` +- **Orchestration/receipt:** `VEIP_REFUSED`, `VEIP_MALFORMED_INPUT`, `VEIP_MISSING_ACTIVATION_ID`, `VEIP_INVALID_EXECUTION_RESULT`, `VEIP_FACT_BUNDLE_INCOMPLETE`, `VEIP_RECEIPT_MALFORMED`, `VEIP_RECEIPT_MISMATCH` +- **Git gate:** `GIT_FAIL`, `GIT_ERROR`, `GIT_UNRESOLVED`, `GIT_NEUTRAL_CONCLUSION`, `GIT_MERGE_RESULT_UNVERIFIED`, `GIT_GATE_REFUSAL` + +## 11. Python library integration + +```python +import json +from authcontract.veip import run_specimen, verify_receipt + +artifact = json.load(open("fixtures/banking_payment_specimen.json")) +action = json.load(open("fixtures/actions/send_payment_valid.json")) +facts = json.load(open("fixtures/runtime/facts_valid.json")) + +result = run_specimen(artifact, action, facts, execution_result="SIMULATED_SUCCESS") +# result.decision -> "ALLOW"; result.reason_code -> "OK" + +if result.decision == "ALLOW": + check = verify_receipt(result.receipt, artifact, action, facts) + # check.status -> "PASS" +``` + +`run_specimen` returns a `RunResult` (`decision`, `reason_code`, `message`, +`receipt`). `verify_receipt` returns a `VerifyResult` (`status`, `reason_code`, +`message`). + +**Refusals are return values, not exceptions.** `run_specimen` does not raise on +an ordinary refusal. Check `.decision` / `.status`; do not wrap these calls in +try/except expecting refusal to surface as an exception. + +Other useful entry points: `authcontract.digest` (`contract_digest`, +`verify_artifact`, `canonical_bytes`), `authcontract.projection` (`project`, +`check_action`, `projection_digest`). + +## 12. GitHub merge-gate workflow + +`.github/workflows/authcontract-gate.yml` exists and runs `authcontract git-gate` +on `pull_request` events. It re-resolves the base ref live and proves the +evaluated commit contains both base and PR head. + +**The workflow's presence does NOT mean GitHub requires it.** Whether a check is +*enforced* — whether branch protection blocks a merge on failure — is separate +repository configuration (branch protection / rulesets), not workflow content. +Do not report the gate as an enforced required status check. If you need to know +what is actually required to merge, read the repository's branch-protection +settings directly. + +## 13. Interfaces that do NOT exist + +Do not attempt these, and do not report them as available: + +- **No PyPI package.** Source install only. +- **No HTTP or gRPC service.** No server, no endpoint, no daemon. In-process library and CLI only. +- **No persistence layer.** Stateless over in-memory inputs. Receipts are not stored for you. +- **No multi-contract registry.** One artifact per invocation; no cross-contract selection or resolution. +- **No replay protection.** Replayed identical requests produce identical receipts — that is determinism, not protection. No nonce, sequence, or single-use semantics. +- **No concurrency or distribution layer.** +- **No telemetry.** +- **No authentication, identity, or PKI subsystem** of production grade. + +## 14. Claim ceiling + +This repository establishes **only** what its measurements demonstrate, bounded +to one synthetic banking specimen family on a single machine and process. It does +**not** establish: production readiness; regulatory or legal correctness; +universal source-to-rule derivation; arbitrary-domain compatibility; security +certification; distributed scalability; formal proof; or comparative superiority +over any other system. + +Do not soften, omit, or paraphrase this ceiling when summarizing the project. + +## 15. Licensing + +**No license is declared.** No `LICENSE` file exists and `pyproject.toml` +declares no license field, so default copyright applies and no usage rights are +granted. Treat this as source-available for evaluation and reading. **Do not +describe it as open source**, and do not assume redistribution or derivative +rights. Direct licensing questions to the repository owner. + +## 16. Prohibition on invention + +If asked to do something this repository does not support: + +1. State plainly that the capability does not exist here. +2. Cite the relevant section above. +3. Do **not** fabricate a command, flag, endpoint, config key, or package name. +4. Do **not** infer capability from the roadmap, from target-behavior examples, + or from the presence of a workflow file. +5. Do **not** weaken or bypass a refusal to produce a desired outcome. + +Further reading: [`README.md`](README.md) · measured evidence +[`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) · maturity +[`docs/TRL-ASSESSMENT.md`](docs/TRL-ASSESSMENT.md) · planned work +[`docs/ROADMAP.md`](docs/ROADMAP.md). From 5db503a81bb9962d758d9679201e255cbf59660f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:44:52 +0000 Subject: [PATCH 2/3] AC-037: add agent usability record and truthful adoption surface Documentation only. authcontract/, tests/, fixtures/, .github/, pyproject.toml and benchmarks/ are byte-identical to main 80777850 (git diff --stat empty). docs/AGENT-USABILITY.md records a fresh-clone agent clean-room test against criteria A-J: 10 PASS, 0 FAIL, 0 NOT EVALUATED. Every AGENTS.md claim was executed rather than asserted, including the negative ones - the five unsupported module names raise ModuleNotFoundError, --help lists exactly the six documented subcommands, both refusal paths omit the receipt, and passing the run-specimen wrapper to verify-receipt returns VEIP_RECEIPT_MALFORMED as documented. The record states plainly that it was produced by the same executor that wrote AGENTS.md, so it evidences that the instructions are accurate and executable, not that an independent agent would follow them. Independent agent reproduction remains absent. Records the decision NOT to add a separate skill file: AGENTS.md already carries the full sequence, and a second surface would either duplicate it and drift - the exact defect AC-036S corrected in README.md - or invent automation scaffolding that does not exist here. README adoption surface added only where the provider state is real, verified against the GitHub API: Issues are enabled, so the issue path is linked; Discussions are disabled, so none is mentioned; the commercial path points to the owner-set homepage veraxis.io. No Discord/Slack, no SLA, no support commitment, no adoption statistics, no certification, no package registry. Contribution status is stated truthfully rather than invented: no contribution process, contributor licence, or review policy exists, so issues are named as the reliable path. Scope-of-support is stated as having no commitment. The star prompt is a single optional human-facing line, conditional on the run having been useful, and appears only in README - never in CLI JSON, receipts, reason codes, CI output, or benchmark JSON. Benchmark DUT guard refuses with exit 2 (DUT DRIFT: 1 file - README.md, a protected DUT path). Deliberately not worked around; weakening it to green a docs PR would defeat the property it exists to provide. 342 passed. --- README.md | 24 +++++++++ docs/AGENT-USABILITY.md | 110 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 docs/AGENT-USABILITY.md diff --git a/README.md b/README.md index 85b18d3..7c9829c 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,30 @@ Measured evidence and its limits: [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) · | Understand the terminology | [`docs/DEVELOPER-LANGUAGE.md`](docs/DEVELOPER-LANGUAGE.md) | | See how this compares to other systems | [`docs/SOTA.md`](docs/SOTA.md) | | Understand the full conceptual model | keep reading below | +| Use AuthContract from an AI coding agent | [`AGENTS.md`](AGENTS.md) | + +--- + +## Getting help, reporting problems, and commercial use + +| | | +|---|---| +| **Found a bug, or a claim that doesn't hold?** | Open a [GitHub issue](https://github.com/veraxis-protocol/AuthContract/issues). Reproduction steps against the committed fixtures are the most useful thing you can include. | +| **Benchmark didn't reproduce?** | Include your OS, Python version, and the `benchmarks/results/` JSON your run produced — the harness records the DUT and harness SHAs it verified. | +| **Commercial or institutional use** | [veraxis.io](https://veraxis.io) | + +**Contributions.** There is no contribution process established yet, and no +contributor licence or review policy exists. Issues are the reliable path today. +If you are considering a substantive contribution, open an issue first so it +isn't wasted effort. + +**A note on scope of support.** This is an experimental reference implementation +maintained as research and engineering evidence. There is no support commitment, +response-time expectation, or maintenance guarantee attached to it. + +If the clean-room run above was useful to you, a GitHub star helps other +engineers evaluating this space find it — entirely optional, and only if it +actually earned one. --- --- diff --git a/docs/AGENT-USABILITY.md b/docs/AGENT-USABILITY.md new file mode 100644 index 0000000..f30f327 --- /dev/null +++ b/docs/AGENT-USABILITY.md @@ -0,0 +1,110 @@ +# Agent usability test record (AC-037) + +Clean-room test of this repository from the perspective of an AI coding / +operations agent, using **only** repository files: `README.md`, `AGENTS.md`, and +the executable interfaces. No hidden coaching, no undocumented commands. + +**This document records observations. It does not certify CURRENT-SDLC Gate F** — +that adjudication belongs to the Engineering Lead. + +## Test conditions + +| | | +|---|---| +| Method | Fresh `git clone` into an empty directory, checkout of the candidate commit | +| Candidate commit | `7e7f28d6d8ba8d94cd42d8f3ff4989bf637068d6` | +| Environment | Linux x86_64, Python 3.11.15, git 2.43.0 | +| Instructions used | `AGENTS.md` and `README.md` only | +| Prior knowledge assumed | None | + +Every command below was executed. Results are pasted from real output. + +--- + +## Criterion matrix + +| # | Criterion | Result | Evidence | +|---|---|---|---| +| A | Determine what AuthContract currently does | **PASS** | `AGENTS.md` §1 states the implemented chain in seven steps; §2 states TRL 4 and that automated natural-language source-to-rule comparison is **not** implemented end to end. | +| B | Install it | **PASS** | `AGENTS.md` §4 commands ran verbatim. `pytest -q` → **342 passed**. | +| C | Execute the successful E2E path | **PASS** | §6 command → `status PASS`, `decision ALLOW`, `reason_code OK`, receipt with **10** bound fields, **exit 0**. | +| D | Intentionally produce REFUSED | **PASS** | §7 command 1 → `REFUSED` / `RUN_UNCLASSIFIED_ACTION`, exit 1. Command 2 → `REFUSED` / `RUN_FACT_STALE`, exit 1. Both confirmed `receipt` absent, matching the documented "no receipt is issued on refusal". | +| E | Verify a receipt | **PASS** | §8 command on the committed fixture → `PASS` / `OK`, exit 0. The documented extraction step also verified: extracting `.receipt` from the wrapper → `PASS` / `OK`. | +| F | Interpret PASS/REFUSED and `reason_code` | **PASS** | §9 exit-code table and §10 reason-code families match observed output. Codes in §10 were extracted from source, not recalled. | +| G | Invoke it from Python | **PASS** | §11 example run verbatim → `decision ALLOW reason OK`, then `status PASS OK`. The documented "refusals are return values, not exceptions" claim was tested directly: a stale-fact run returned `REFUSED` / `RUN_FACT_STALE` with **no exception raised**. | +| H | Determine which interfaces do NOT exist | **PASS** | §13 claims tested rather than assumed: `authcontract.server`, `.api`, `.http`, `.registry`, `.db` all raise `ModuleNotFoundError`. `authcontract --help` lists exactly the six documented subcommands and no others. | +| I | Recognize that workflow presence ≠ enforced branch protection | **PASS** | §12 states the distinction explicitly and instructs the agent not to report the gate as enforced. Independently corroborated: `authcontract-gate.yml` is `on: pull_request` only. | +| J | Recognize the claim ceiling | **PASS** | §14 states the ceiling and instructs against softening it. §15 states no license is declared and instructs against describing the project as open source. | + +**Totals: 10 PASS · 0 FAIL · 0 NOT EVALUATED.** + +--- + +## Verified negative behavior + +A usability claim is only worth as much as its failure modes, so these were +executed rather than asserted: + +- **Wrapper passed to `verify-receipt`.** `AGENTS.md` §8 warns that passing + `run-specimen`'s full JSON wrapper instead of the extracted receipt object + returns `VEIP_RECEIPT_MALFORMED`. Confirmed exactly: + `VEIP_RECEIPT_MALFORMED: receipt missing required field(s): ['activation_id', 'admission_digest', 'contract_digest', 'decision_time', 'exact_action_digest', 'execution_result', 'projection_digest', 'receipt_digest', 'runtime_fact_set_digest']`, exit 1. + This is the same defect the AC-028 clean-room run originally uncovered; it is + now documented before an agent can hit it. +- **No receipt on refusal.** Both refusal paths were checked for a `receipt` + key. Absent in both. +- **Unsupported modules.** Five plausible module names an agent might guess were + imported and all failed, confirming §13 rather than trusting it. + +--- + +## Observations and limitations + +1. **`AGENTS.md` is the only agent surface.** No prior `AGENTS.md`, + `CONTRIBUTING.md`, skill file, or machine-readable usage guidance existed, so + this is additive rather than duplicative. A separate reusable skill file was + **deliberately not added** — see the decision note below. + +2. **The reason-code list is descriptive, not a stability contract.** §10 lists + codes extracted from the implementation at this commit. Nothing in the + repository pins them as a versioned public interface, so an agent should + branch on them but should not assume they are frozen across versions. This is + a gap in the repository, not in `AGENTS.md`. + +3. **Refusal semantics are the most likely agent failure mode.** An agent + optimizing for a successful exit code could plausibly retry a refusal with + altered inputs until it gets `ALLOW`. `AGENTS.md` §7 and §16 explicitly + prohibit this, but the prohibition is instructional — nothing mechanically + prevents it. + +4. **Not tested: an actual third-party agent.** This record was produced by the + same executor that wrote `AGENTS.md`. That is a real limitation on its + evidentiary weight — it demonstrates the instructions are *accurate and + executable*, not that an independent agent *would* follow them. Independent + agent reproduction remains absent, consistent with the TRL 4 assessment in + [`docs/TRL-ASSESSMENT.md`](TRL-ASSESSMENT.md). + +--- + +## Decision: no separate skill file + +AC-037 Phase 2 permits an optional reusable agent skill. **One was not added.** + +`AGENTS.md` already carries the full install → run → refuse → verify → interpret +sequence with real commands and real outputs. A separate skill file would either +duplicate it — creating two surfaces that can drift apart, which is precisely the +class of defect AC-036S corrected in `README.md` — or would have to invent +tool-specific automation scaffolding that does not exist in this repository. + +Recorded explicitly so the omission is understood as a decision rather than an +oversight. + +--- + +## Claim ceiling + +This record establishes only that the documented agent-facing instructions are +accurate and executable at this commit, for one synthetic banking specimen +family, on one machine. It establishes no production readiness, no regulatory or +legal correctness, no arbitrary-domain compatibility, no security certification, +and no independent validation. From 7a3b6296cf69d0244bc0cf41d655db6335360f16 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 16:55:06 +0000 Subject: [PATCH 3/3] AC-038: correct reason-code stability overclaim (U7) AGENTS.md and README.md both described reason_code as a 'stable' machine-facing identifier. That is stronger than the evidence: this repository establishes no versioned public-interface commitment that reason codes survive future releases, and no versioning or pinning mechanism exists. Corrected in both files to the semantics the repository actually supports: reason codes are machine-facing identifiers in the current implementation and are the intended programmatic signal within the documented and tested interface; they are accurate for this commit; cross-version stability is not guaranteed and consumers should re-check on upgrade; message remains non-contractual at any version. No reason code renamed. No runtime behavior changed. No test changed. README and AGENTS.md are the only modified files; authcontract/, tests/, fixtures/, .github/, pyproject.toml and benchmarks/ are byte-identical to main 80777850. 342 passed. --- AGENTS.md | 15 ++++++++++++--- README.md | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cb97447..9dc7687 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -150,9 +150,18 @@ Branch on the JSON `status` and `reason_code` fields rather than parsing prose. ## 10. Reason codes -`reason_code` is a **stable machine-facing identifier**; `OK` on success. -`message` (present on refusal) is human-readable and **not** a stable contract — -do not parse it. +`reason_code` is a **machine-facing identifier** in the current implementation; +`OK` on success. Branch on it rather than on prose — within the currently +documented and tested interface it is the intended programmatic signal. + +**Cross-version stability is not guaranteed.** This repository establishes no +versioned public-interface commitment that reason codes remain unchanged across +future releases; no such versioning or pinning mechanism exists yet. Treat the +set below as accurate for this commit, and re-check it if you upgrade. Do not +represent these codes as a stable API contract. + +`message` (present on refusal) is human-readable and **not** contractual at any +version — do not parse it. Codes observed in the implementation, by family: diff --git a/README.md b/README.md index 7c9829c..da20f99 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ Note that **no receipt is issued on refusal** — a refused decision never produ |---|---| | `status` | `PASS` or `REFUSED` — the outcome of the check | | `decision` | `ALLOW` on a permitted action; absent on refusal | -| `reason_code` | Stable machine-facing identifier (e.g. `RUN_FACT_STALE`). Safe to branch on | +| `reason_code` | Machine-facing identifier (e.g. `RUN_FACT_STALE`). Branch on this rather than on prose — but see the note below on cross-version stability | | `message` | Human-readable explanation of a refusal | | `contract_digest` | Canonical identity (RFC 8785 JCS + SHA-256) of the rule that applied | | `projection_digest` | Identity of the action domain the rule was projected into | @@ -170,6 +170,8 @@ Every digest is recomputable from raw inputs. That is what makes the receipt che Exit codes: `0` pass · `1` refusal. +**On `reason_code` stability.** Reason codes are the intended programmatic signal within the currently documented and tested interface, and are accurate for this commit. This repository does **not** yet establish a versioned public-interface commitment that they remain unchanged across future releases — no versioning or pinning mechanism exists. Re-check them if you upgrade, and do not treat them as a frozen API contract. `message` is human-readable and is not contractual at any version. + --- ## How to integrate it today