Metadata-Version: 2.4
Name: keel-verifier
Version: 1.0.0
Summary: Independent verifier for Keel governance evidence
Author: Keel API, Inc.
License: MIT License
        
        Copyright (c) 2026 Keel API, Inc.
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://keelapi.com/verify
Project-URL: Documentation, https://docs.keelapi.com/11-running-keel-verify
Project-URL: Repository, https://github.com/keelapi/keel-verifier
Project-URL: Changelog, https://github.com/keelapi/keel-verifier/releases
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=42
Dynamic: license-file

# keel-verifier

Independent verifier for Keel governance evidence.

It runs locally, requires no access to Keel, and makes no outbound network calls unless you explicitly ask it to fetch a public key or key manifest URL.

## Quick Start

```bash
python -m pip install keel-verifier
keel-verify export --help
```

From a checkout:

```bash
python -m pip install -e .
python -m keel_verifier --help
```

The v0.2.0 invocation pattern still works:

```bash
python -m keel_verifier sample/export.json --self-attested
```

## What It Verifies

`keel-verify export` verifies a signed compliance export in three layers:

1. The export bytes match the signed manifest `content_hash`.
2. The manifest Ed25519 signature verifies against a trusted key.
3. Optional Phase C/D checks walk bundled chain entries and verify closure records.

`keel-verify checkpoint` verifies integrity checkpoint JSON artifacts: the `chain_heads` composite hash, the Ed25519 checkpoint signature, and an embedded RFC 3161 timestamp MessageImprint when present.

## Obtaining a Signed Export

Request an audit export from Keel's compliance export API and include chain entries when you want full lifecycle walking:

```bash
curl -sS -X POST "https://api.keelapi.com/v1/compliance/exports?include_chain_entries=true"   -H "Authorization: Bearer $KEEL_API_KEY"   -H "Content-Type: application/json"   -d '{"project_id":"<project_uuid>","format":"json"}'
```

Download both artifacts returned by the export workflow:

- the export payload, for example `export.json`
- the signed manifest, for example `manifest.json`

Then run:

```bash
keel-verify export export.json manifest.json --walk-events --verify-closure
```

The flag form used by the internal verifier is also supported:

```bash
keel-verify export --export-file export.json --manifest manifest.json --walk-events --verify-closure
```

## Chain Walking

`--walk-events` parses `audit_export_bundle` files with `schema_version=2` and `include_chain_entries=true`.

It groups entries by `chain_scope`, sorts by `sequence_number`, recomputes every `record_hash`, verifies `prev_hash` continuity inside the export window, and fails closed on unknown `chain_format_version` values.

Schema version 1 exports remain backward compatible. They can still be verified at the export-signature layer, but they do not contain chain entries to walk.

## Closure Verification

`--verify-closure` verifies `permit.closed` entries.

For `closure_v1`, it verifies the closure Ed25519 signature and cross-references provider/client response digests against the bundled lifecycle events.

For `closure_v2`, it also verifies `dispatch_request_digest_v1` against the permit's `binding_request_hash`, proving that the dispatch-time request body is the one covered by the closure record.

Closure verification uses public keys with purpose `permit_binding_signing`. Pass a manifest explicitly when needed:

```bash
keel-verify export export.json manifest.json   --key-manifest permit-binding-keys.json   --walk-events   --verify-closure
```

The bundled trust root lives at `keel_verifier/data/trust_root.json`. It includes the production export and checkpoint signing keys currently served by `https://api.keelapi.com/v1/compliance/keys`. The production permit-binding endpoint returned 404 on 2026-05-07, so maintainers should refresh the bundled manifest when `https://api.keelapi.com/v1/integrity/permit-binding-public-keys` is live.

## Tampering Matrix

The verifier emits stable `WALK_*` failure codes, including:

- `WALK_RECORD_HASH_MISMATCH`
- `WALK_PREV_HASH_DISCONTINUITY`
- `WALK_SEQUENCE_INVERSION`
- `WALK_UNKNOWN_CHAIN_FORMAT`
- `WALK_CLOSURE_SIGNATURE_INVALID`
- `WALK_CLOSURE_DIGEST_MISMATCH`
- `WALK_CLOSURE_DIGEST_MISSING`
- `WALK_CLOSURE_DISPATCH_DIGEST_MISMATCH`
- `WALK_UNKNOWN_CLOSURE_FORMAT`

The authoritative matrix is maintained in the Keel docs: https://docs.keelapi.com/12-tampering-detection-matrix

## Trust Model

There are two useful kinds of verification:

- Self-attested: the file agrees with itself. This proves internal consistency only.
- Trust-root verified: the artifact verifies against a key you trust, such as the bundled production trust root, a pinned public key, or a manifest fetched and saved out-of-band.

Trust sources, strongest first:

| Mode | Flags | Notes |
| --- | --- | --- |
| Pinned key | `--expected-public-key ed25519:...` or `--public-key ed25519:...` | Strongest when obtained out-of-band. |
| Key manifest | `--key-manifest keys.json` | Supports key rotation and active windows. |
| Key manifest URL | `--key-manifest-url URL` | Explicit network fetch. |
| Bundled trust root | none | Default. No phone-home. |
| Self-attested | `--self-attested` | Development/sample mode only. |

`--public-key-url` is also supported for checkpoint verification against the single live checkpoint public-key endpoint.

## CLI Examples

```bash
keel-verify export export.json manifest.json
keel-verify export export.json manifest.json --walk-events
keel-verify export export.json manifest.json --walk-events --verify-closure
keel-verify checkpoint checkpoint.json
python -m keel_verifier sample/export.json --self-attested
python -m keel_verifier sample/export.json --json --self-attested
```

Exit code `0` means verified. Exit code `1` means verification failed. Exit code `2` means bad usage.

## Network Behavior

The verifier does not phone home. It reaches the network only when you pass `--public-key-url` or `--key-manifest-url`.

There is no telemetry.

## Library Use

```python
from keel_verifier import verify, verify_export_walk_events, verify_closure_record

result = verify("sample/export.json", self_attested=True)
if not result.ok:
    raise SystemExit(result.error)
```

## Versioning

v1.0.0 syncs the public verifier with the Phase A/B/C/D internal verifier. v0.2.0 users can keep using `python -m keel_verifier <artifact>`.

## License

MIT. See `LICENSE`.
