Catalog PyPI
PACKAGE EXPLORERView in registry

aigentsy-verify

PyPI

Standalone offline verification for AiGentsy ProofPack v2 bundles, attestations, and policy_layer display

aigentsyed25519merkleproof-bundletransparency-logverification
Versions collected1
Direct dependencies2From release 1.6.3
Last observed21 Oct, 10:48 UTC

README

Version 1.6.3 documentation

aigentsy-verify

Standalone offline verification for AiGentsy proof bundles and attestations. Zero dependency on AiGentsy's runtime.

Install

pip install aigentsy-verify

Adapter-backed replay availability. aigentsy-verify@1.4.0 on PyPI was built before adapter.py was on disk and therefore did not perform adapter-backed replay. Fixed in aigentsy-verify@1.5.0 — the published 1.5.0 wheel includes adapter.py and the full 7-step adapter-backed replay path works from pip install aigentsy-verify==1.5.0. The 5-step bundle-verification path is byte-identical to 1.4.0.

CLI

Verify a bundle offline (default — no network calls):

aigentsy-verify bundle proofpack.json
# Bundle steps run without an STH key. Adapter-backed replay is
# available from `aigentsy-verify==1.5.0` (the 1.4.0 wheel was missing
# adapter.py; fixed in 1.5.0).

Bundle verification with public key fetch:

aigentsy-verify bundle proofpack.json --fetch-key
# All bundle steps PASS when the bundle is well-formed.

JSON output for scripting:

aigentsy-verify bundle proofpack.json --json

Strict mode (fails if STH signature is skipped):

aigentsy-verify bundle proofpack.json --strict --fetch-key

Download and verify a real ProofPack:

curl -o proofpack.json https://aigentsy-ame-runtime.onrender.com/protocol/proofs/demo_deal_08effb15193a/export
aigentsy-verify bundle proofpack.json --fetch-key

Python SDK — Verify in 60 Seconds

from aigentsy_verify import verify_bundle, verify_attestation, fetch_public_key
import json, urllib.request

# 1. Fetch public key (cache this — it rarely changes)
public_key = fetch_public_key()

# 2. Verify a proof bundle
bundle = json.load(open("bundle.json"))
result = verify_bundle(bundle, public_key_base64=public_key)
print(result["verified"])  # True or False

# 3. Verify an attestation
resp = json.loads(urllib.request.urlopen(
    "https://aigentsy-ame-runtime.onrender.com/protocol/agents/AGENT_ID/attestation"
).read())
ok = verify_attestation(resp["attestation"], resp["signature"], public_key)
print(ok)  # True or False

Verify a Proof Bundle

import json
from aigentsy_verify import verify_bundle, fetch_public_key

# Load a bundle (from file, API, or any source)
with open("bundle.json") as f:
    bundle = json.load(f)

# Fetch the public key (once — cache it)
public_key = fetch_public_key()

# Verify — returns per-step results
result = verify_bundle(bundle, public_key_base64=public_key)

print(result["verified"])  # True or False
for step, detail in result["steps"].items():
    print(f"  {step}: {'PASS' if detail['passed'] else 'SKIP' if detail.get('skipped') else 'FAIL'}")

Verify an Attestation

import json, urllib.request
from aigentsy_verify import verify_attestation, fetch_public_key

# Fetch attestation from AiGentsy
resp = json.loads(urllib.request.urlopen(
    "https://aigentsy-ame-runtime.onrender.com/protocol/agents/AGENT_ID/attestation"
).read())

# Fetch public key
public_key = fetch_public_key()

# Verify signature
ok = verify_attestation(
    resp["attestation"],
    resp["signature"],
    public_key,
)
print(f"Attestation valid: {ok}")

Sample Artifacts

The tests/fixtures/ directory contains sample artifacts you can verify immediately:

# Clone and verify offline
python -c "
import json
from aigentsy_verify import verify_bundle, verify_attestation

bundle = json.load(open('tests/fixtures/sample_bundle.json'))
print('Bundle:', verify_bundle(bundle)['verified'])

att = json.load(open('tests/fixtures/sample_attestation.json'))
print('Attestation:', verify_attestation(att['attestation'], att['signature'], att['public_key_base64']))
"

Sample fixtures include a test Ed25519 key pair — they verify without network access.

Public Key

The production Ed25519 public key is served at:

https://aigentsy-ame-runtime.onrender.com/protocol/merkle/public-key

Load it programmatically:

from aigentsy_verify import fetch_public_key
key = fetch_public_key()  # returns base64-encoded Ed25519 public key

Or from a local file:

from aigentsy_verify import load_public_key_from_file
key = load_public_key_from_file("log_public_key.json")

Bundle Verification (5 steps in verify_bundle)

StepWhat it checksRequired?
1. Bundle hashSHA-256 of canonical JSON matches claimed hashYes
2. Event chainEach event's hash and prev_hash link are correctYes
3. Merkle inclusionRFC 6962 proof path from leaf to rootIf present
4. STH signatureEd25519 signature on signed tree headIf key provided
5. Cross-referenceMerkle root matches STH root hashIf both present

(ProofPack spec_version 3.0.0 adds a sixth actor_signatures step that verifies per-event actor signatures; older bundles remain byte-identical at 5 steps.)

Adapter-backed Replay (source-current, 7 checks in verify_adapter_replay)

When a ProofPack carries an embedded adapter_evaluation (adapter contracts), the source verifier replays every claim it makes. Each check returns a status code; the overall adapter_replay_status is ok only if every step is ok.

StepWhat it checksStatus field
1. SchemaEmbedded adapter_contract declaration passes the on-disk schemaadapter_contract_schema_status
2. Contract hashsha256(canonical(declaration)) matches contract_hashcontract_hash_status
3. Input-schema hashsha256(canonical(input_schema)) matches input_schema_hashinput_schema_hash_status
4. Normalized inputsEvery key in normalized_policy_inputs is in allowed_policy_fieldsnormalized_policy_inputs_status
5. Validator declarationDeclared validator_name + validator_version are present and consistent with the evaluation resultadapter_validator_status
6. Policy replayA REJECTED event's matched_rule actually fires against its own evaluated inputspolicy_replay_status
7. Overall verdictAggregate ok only if every check above is okadapter_replay_status

Per-check status codes (verbatim from source):

  • ok — check passed
  • legacy_no_adapter — the event predates adapter contracts; no replay required
  • schema_fail — adapter contract declaration failed schema validation
  • contract_hash_mismatch — recomputed contract hash does not match claimed value
  • input_schema_hash_mismatch — recomputed input-schema hash does not match claimed value
  • normalized_inputs_not_in_allowed_policy_fields — claim referenced a field not declared by the contract
  • validator_declaration_missing — required validator metadata absent
  • validator_result_inconsistent — validator result contradicts the declared validator
  • matched_rule_does_not_fire_against_evaluated_inputs — the rule the runtime claims matched does not fire on replay
  • adapter_evaluation_shape_invalid — top-level shape of adapter_evaluation is malformed

The 7-step adapter-backed replay path is available from the published wheel starting with aigentsy-verify==1.5.0. The 1.4.0 wheel was missing adapter.py; that gap is closed in 1.5.0 (see install note at the top).

API

verify_bundle(bundle, public_key_base64="", sth=None) -> dict

Complete 5-step verification. Returns {"verified": bool, "steps": {...}}.

verify_attestation(attestation, signature_base64, public_key_base64) -> bool

Verify an Ed25519-signed outcome attestation.

verify_inclusion(leaf_hash, leaf_index, tree_size, proof, expected_root) -> bool

Verify an RFC 6962 Merkle inclusion proof.

verify_sth_signature(sth, public_key_base64) -> bool

Verify a signed tree head signature.

verify_consistency(old_size, new_size, old_root, new_root, proof) -> bool

Verify an RFC 6962 Merkle consistency proof (append-only guarantee).

verify_anchor_receipt(receipt) -> tuple[bool, dict]

Verify an STH anchor receipt's digest integrity. Returns (passed, details).

fetch_public_key(url=...) -> str

Fetch the Ed25519 public key from AiGentsy's runtime.

load_public_key_from_file(path) -> str

Load the public key from a local JSON file.

compute_bundle_hash(deal_id, proofs, events, merkle_inclusion) -> str

Compute the SHA-256 bundle hash.

verify_event_chain(events) -> dict

Verify event hash integrity and prev_hash chain linkage.

verify_adapter_replay(bundle) -> dict

Adapter-backed replay over an embedded adapter_evaluation. Returns the seven per-check status fields plus the overall adapter_replay_status. Available in the published wheel from aigentsy-verify==1.5.0 (the 1.4.0 wheel did not include adapter.py).

Resources

License

Licensed under the Apache License 2.0. The full license terms are included in the LICENSE file distributed with this package.

Swarm decision evidence (1.6.3)

The strict profile adds a swarm_decision step.

Earlier releases could only report the runtime's export-time swarm snapshot: it is re-evaluated when the bundle is exported, reads the enforcement flag at that moment, and lives outside bundle_hash. It is an observation, and 1.6.3 labels it as one.

swarm_decision reads the committed record instead — the swarm_decision context on a CONSEQUENCE_AUTHORIZED event inside bundle["events"], which bundle_hash covers and the event chain hash-links. The step reports validity and authentication strength separately:

strengthMeaning
authenticatedvalid, and a trusted anchor covers this record's own event: bundle hash and event chain verify; Merkle inclusion, the STH signature under the log key you supplied, and cross-reference pass; the anchored leaf binds to exactly one event; that event is this decision or a later one whose hash chain commits back through it; and the record's event_id is unique in the bundle
integrity_boundvalid, and bundle hash + event chain verify, but no trusted anchor covers this record — unanchored, anchored only at an earlier event, an unbound or ambiguous anchor, or a non-unique event_id
unprovenvalid record, but the surrounding integrity steps did not verify
invalida definitive contradiction — rejected regardless of anchoring
noneno decision record present

Four general checks passing does not by itself make a decision authenticated: an anchor commits to the chain up to its own leaf and says nothing about what follows it. Strength is per record — each carries event_index (its position in the chain) and, where relevant, anchor_relationship — and the step reports the weakest record.

A definitive contradiction (recomputed digest mismatch, unsupported context_version, wrong types, identity or deal correlation mismatch, designation disagreement, a policy_hash that is not the hash of the swarm policy its policy_event_id names, an ambiguous or missing named policy, or a policy_hash stated with no policy_event_id) fails the step and is never softened by a missing anchor. The swarm policy_hash is distinct from any outer mandate or acceptance policy_hash in the same payload. Absence is not failure: bundles produced before this context keep their existing results and gain no enforcement claim.

Distinguishing values matter. evaluated: false with applicable/satisfied as null means the gate did not evaluate — it never reads as a negative result. An unknown or missing enforcement value is reported as unproven and is never coerced into a proven off.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
1.6.315 Sept 20262

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 21 Oct, 10:48 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:0a17c0ecacc9dfb71e452e0522a67760d1cdd158a4fb2ddf63e7c7dd73b366bb