Metadata-Version: 2.4
Name: algovoi-keystone-avm-proofpack
Version: 0.1.0
Summary: Bind avm-proofpack chain evidence to the AlgoVoi Keystone settlement stage: produce and verify the content-addressed chain-binding reference that ties a captured, offline-verifiable AVM bundle to substrate2 keystone_evidence's settlement stage.
Author-email: AlgoVoi <hello@algovoi.co.uk>
License: Apache-2.0 OR AlgoVoi-Commercial-v1.0
Project-URL: Homepage, https://algovoi.co.uk
Project-URL: Source, https://github.com/chopmob-cloud/avm-proofpack
Keywords: algovoi,keystone,avm-proofpack,avm,algorand,voi,x402,settlement,chain-binding,state-proof,evidence,offline-verification,content-addressed
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: avm-proofpack>=0.3.0
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: rfc8785>=0.1; extra == "dev"
Dynamic: license-file

# algovoi-keystone-avm-proofpack

Bind [avm-proofpack](https://github.com/chopmob-cloud/avm-proofpack) chain
evidence to the **settlement stage** of the AlgoVoi *Keystone* lifecycle.

Keystone (`substrate2.keystone_evidence`) renders the whole lifecycle -
execution -> settlement binding -> refund -> capping verdict - as one signed,
hash-linked, Compliance-Command-Center-ingestable chain. Its **settlement
stage** carries a `binding_ref`. This plugin is what produces and verifies that
`binding_ref` so it points, byte-exactly, at a portable, offline-verifiable
proof that the settling transaction is committed on chain.

A bundle is protocol-neutral: it proves a chain fact and nothing else. This
package attaches that fact to the keystone settlement stage as an **optional,
additive, content-addressed** reference, without changing `keystone_evidence`,
the gateway, or `substrate2`.

## Open / commercial split

- **Open tier (this package).** *Produces and verifies* the content-addressed
  chain-binding reference (`chain_binding_ref`). Fully offline verification
  against the bundle bytes; no keys, no signing.
- **Commercial tier (`substrate2.keystone_evidence`).** *Signs* that reference
  into the keystone evidence chain (Falcon-1024 + optional ML-DSA-65) for CCC +
  Records Vault. This plugin never signs; it hands the reference off (below).

## Install

```
pip install "algovoi-keystone-avm-proofpack>=0.1.0"
# pulls in avm-proofpack>=0.3.0 (PyPI / the private index)
```

## Producer

```python
from algovoi_keystone_avm_proofpack import bind_settlement

sb = bind_settlement(
    txid="CCQU5VMM5K5OHNLK6IVRI5XTKI57HIODHPLKGGS4RZ5GWP3OZYHA",
    round=63604900,
    network="algorand-mainnet",              # a known chain name pins the genesis hash
    node_url="https://mainnet-api.algonode.cloud",
    tenant="11111111-1111-4111-8111-111111111111",   # optional: mints settled_payment_ref
    corroborate_nodes=None,                  # optional: raise the trust root
)

sb.chain_binding_ref   # "sha256:fcb9cd84..."  (== sb.binding_ref)
sb.bundle              # the captured bundle: the SOLE trust anchor, stored separately
sb.settled_payment_ref # "sha256:..."         (privacy-preserving charge ref, contract R2)
```

`bind_settlement` runs `avm_proofpack.capture` (inheriting its capture gates),
verifies the freshly captured bundle offline (chain-pinned when `network`
resolves to a known chain), then content-addresses it. **Capture gates are not
weakened.** Capture is best-effort *in your flow* - if it fails, build the
keystone chain with execution+cap only - but when a ref is produced it is exact.

## How `chain_binding_ref` is computed (and enforced)

```
chain_binding_ref = "sha256:" + SHA-256( json.dumps(bundle, indent=2, sort_keys=True) + "\n" )
```

These are the exact bytes `avm_proofpack.dump_bundle` writes, so a downloaded
`.proofpack.json` verifies with a plain `sha256sum`. This is the
`settlement_evidence_binding_v1` contract's **rule R1**, and it is **deliberately
NOT RFC 8785 JCS** (the compact canon used elsewhere for
`attestation_content_hash`). The two canons are not interchangeable; a verifier
must not silently pick one (see the `seb-v1-r05` non-JCS canary).

> Cross-platform note: the canonical bytes are built in memory with an explicit
> LF, never by hashing a file `dump_bundle` wrote. On Windows, text-mode file
> writes translate `\n` to `\r\n`, which would change the digest. This package
> hashes LF-only bytes on every platform.

## Verifier

```python
from algovoi_keystone_avm_proofpack import verify_settlement_binding

result = verify_settlement_binding(
    keystone_settlement_core=core,   # the settlement-stage dict from keystone_evidence_cores
    bundle=bundle,                   # the bundle the ref points at
    chain="algorand-mainnet",        # or expected_genesis_hash=<bytes> : MANDATORY to pin
    corroborate_nodes=None,          # optional: raise the trust root
    settlement_claim={               # optional cross-check of the chain facts
        "round": 63604900,
        "receiver": "JFNB...CE",
        "amount": 230000,
        "settled_payment_ref": "sha256:...",
        "tenant": "1111...1111",
        "network": "algorand",
    },
)

result.ok           # True only after re-deriving the chain fact from the bundle bytes
result.trust_root   # "unattested" (structure-only) | "corroborated" | "rejected"
result.checks       # {bundle_verifies, binding_ref_matches, payment_extracted, claim_*}
result.reasons      # failure detail
result.payment      # extracted PaymentFacts as a dict
```

The verifier (a) `verify_bundle`s the bundle offline, chain-pinned; (b)
recomputes the content hash and requires it to **equal** the core's
`binding_ref` (the tie between the signed keystone evidence and these exact
bytes) - mismatch fails closed; (c) `extract_payment`s and cross-checks any
`settlement_claim`, closing the hashed-`settled_payment_ref` loop with
`matches_reference`. It **never** returns a positive verdict without re-deriving
the chain fact from the bundle bytes.

## Hand-off into `keystone_evidence` (no substrate2 dependency)

The coupling is one-directional and optional: this package returns a plain
augmented dict; the caller (who owns `substrate2`) passes it on.

```python
from algovoi_keystone_avm_proofpack import bind_settlement, fold_into_keystone_bundle
from substrate2.keystone_evidence import keystone_evidence_cores   # caller-side import

sb = bind_settlement(txid=txid, round=rnd, network="algorand-mainnet",
                     node_url=NODE, tenant=tenant_id)

kbundle = fold_into_keystone_bundle(
    keystone_bundle,                  # your execution/decision/cap bundle
    binding=sb,                       # sets binding_ref = sb.chain_binding_ref
    settlement_ref=settlement_attestation_ref,   # your round-bearing attestation ref
    retention_chain_ref=retention_ref,           # optional
)

cores = keystone_evidence_cores(kbundle)   # the settlement stage is now present
```

`keystone_evidence_cores` appends the settlement stage exactly when both
`settlement_ref` and `binding_ref` are truthy; `fold_into_keystone_bundle` sets
both and touches nothing else.

## Conformance

`check_binding_record(record, bundle=...)` enforces the five load-bearing rules
of the `settlement_evidence_binding_v1` contract (R1 dump-canon hash / not JCS,
R2 `settled_payment_ref` recompute, R3 round join, R4 chain-identity pin, R5 the
bundle verifies), raising `BindingReject(rule, detail)` on the first break.

## Security

- **The bundle is the sole trust anchor. Re-verify offline.** A
  service/keystone verdict is a non-authoritative hint. Structure-only
  verification proves the bundle is internally consistent with *its own*
  state-proof message - which a dishonest facilitator could have fabricated. A
  structure-only pass is reported honestly as `trust_root="unattested"`.
- **Raise the trust root before relying on evidence.** Corroborate the
  state-proof message against independent nodes (`corroborate_nodes`); only then
  is `trust_root="corroborated"`.
- **Chain pinning is mandatory for cross-checks.** Always pass `chain=` or
  `expected_genesis_hash=`; without a pin an internally sound bundle from a
  *different* AVM chain would satisfy the check (contract R4).
- **SSRF / capture gates are inherited from avm-proofpack and are not
  weakened** (opener controls, `NotYetProvable` before the state-proof interval
  closes, size limits).
- **Fail closed.** No positive verdict is returned without re-deriving the chain
  fact from the bundle bytes; any hash mismatch, verification failure, or claim
  mismatch rejects.
- **The experimental Falcon state-proof-signature trust tier is not involved
  here.** This package verifies bundle structure + optional node corroboration
  only.

## Licence

Apache-2.0 OR AlgoVoi-Commercial-v1.0 (see `LICENSE`).
