ca2a-runtime 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ca2a_runtime-0.3.1/.clusterfuzzlite/Dockerfile +5 -0
- ca2a_runtime-0.3.1/.clusterfuzzlite/README.md +60 -0
- ca2a_runtime-0.3.1/.clusterfuzzlite/build.sh +29 -0
- ca2a_runtime-0.3.1/.clusterfuzzlite/fuzz_attestation_parsers.py +62 -0
- ca2a_runtime-0.3.1/.clusterfuzzlite/fuzz_canonical_json.py +89 -0
- ca2a_runtime-0.3.1/.clusterfuzzlite/fuzz_wire_documents.py +92 -0
- ca2a_runtime-0.3.1/.github/dependabot.yml +39 -0
- ca2a_runtime-0.3.1/.github/workflows/cflite_batch.yml +36 -0
- ca2a_runtime-0.3.1/.github/workflows/cflite_pr.yml +43 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/docker.yml +2 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/require-maintainer-approval.yml +5 -2
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/CHANGELOG.md +21 -1
- ca2a_runtime-0.3.1/Dockerfile +40 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/PKG-INFO +1 -1
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/index.md +2 -2
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/pyproject.toml +1 -1
- ca2a_runtime-0.3.1/requirements/build.in +6 -0
- ca2a_runtime-0.3.1/requirements/build.txt +26 -0
- ca2a_runtime-0.3.1/requirements/runtime.in +12 -0
- ca2a_runtime-0.3.1/requirements/runtime.txt +620 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/canonical.py +9 -2
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/challenge.py +10 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/delegation/credential.py +7 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/tdx.py +22 -6
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/server.py +6 -1
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/dag.py +4 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_canonical.py +13 -0
- {ca2a_runtime-0.3.0/tests → ca2a_runtime-0.3.1/tests/unit}/test_challenge.py +18 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_container_release.py +25 -3
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_example_rejection_with_proof.py +17 -8
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_live_call.py +29 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_release_artifacts.py +1 -1
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_tdx.py +62 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_trace_binding.py +11 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_verify.py +13 -0
- ca2a_runtime-0.3.0/.github/dependabot.yml +0 -23
- ca2a_runtime-0.3.0/Dockerfile +0 -30
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.dockerignore +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/CODEOWNERS +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/actionlint.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/ci.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/codeql.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/contributor-check.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/docs.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/limitations-parity.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/release-drafter.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/release.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/sbom.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/scorecard.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/vouch-check.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.github/workflows/vouch-command.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/.gitignore +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/ADOPTERS.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/CHARTER.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/CNAME +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/CODE_OF_CONDUCT.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/CONTRIBUTING.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/GOVERNANCE.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/LICENSE +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/LIMITATIONS.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/MAINTAINERS.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/NOTICE +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/PRIVACY.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/ROADMAP.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/SECURITY.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/SPONSORS.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/benchmarks/.gitkeep +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/SPEC.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/assets/icon.svg +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/assets/og.png +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/concepts.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/configuration.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/hardware-validation.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/mutual-hardware-acceptance.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/quickstart.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/attestation.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/call-graph.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/cedar-policy.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/component-model.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/conformance.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/delegation-chain.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/error-codes.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/failure-modes.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/mutual-attestation.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/profile.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/provenance-dag.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/response-authentication.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/response-binding-requirements.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/sealed-channel.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/threat-model.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/trace-a2a-profile.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/transport.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/spec/verification-library.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/tutorials/authoring-a-delegation-credential.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/tutorials/emit-and-verify-provenance.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/tutorials/integrating-with-a2a.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/tutorials/reproducing-the-claims.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/docs/tutorials/verify-a-delegation-chain.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/a2a-sdk/loopback.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/a2a-sdk/requirements.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/cross-operator-delegation/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/cross-operator-delegation/ca2a-config.yaml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/cross-operator-delegation/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/cross-operator-delegation/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/cross-operator-delegation/demo.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/cross-operator-delegation/policy.cedar +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/minimal/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/minimal/ca2a-config.yaml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/minimal/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/rejection-with-proof/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/rejection-with-proof/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/rejection-with-proof/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/rejection-with-proof/demo.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/trace-dag/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/examples/trace-dag/demo.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim1-attenuation-soundness/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim1-attenuation-soundness/run.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim2-cross-chain-replay/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim2-cross-chain-replay/run.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim3-scope-policy-intersection/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim3-scope-policy-intersection/run.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim4-sealed-payload-confidentiality/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim4-sealed-payload-confidentiality/run.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim5-provenance-dag-integrity/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim5-provenance-dag-integrity/run.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim6-cross-operator-attestation/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/claim6-cross-operator-attestation/run.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/ca2a-attested-peer-azure-2026-07-27/bridge.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/ca2a-attested-peer-azure-2026-07-27/transcript.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/ca2a-cross-tee-2026-07-27/snp_client.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/ca2a-cross-tee-2026-07-27/tdx_peer.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/ca2a-cross-tee-2026-07-27/transcript.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/mutual-snp-2026-09-17/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/mutual-snp-2026-09-17/a-to-b.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/mutual-snp-2026-09-17/b-to-a.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/experiments/hardware-validation/mutual-snp-2026-09-17/controls.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/governance/ca2a-enforcement.yaml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/hooks/seo.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/mkdocs.yml +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/overrides/main.html +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/agt-overrides.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/agt.in +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/agt.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/dev.in +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/dev.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/docs.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/release.in +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements/release.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/requirements-docs.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/robots.txt +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/scripts/gen_action_fixtures.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/scripts/gen_agt_evidence.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/scripts/gen_example_chain.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/agent_manifest.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/attestation.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/benchmarks.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/bootstrap.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/cedar.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/channel/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/channel/sealed.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/cli.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/config.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/delegation/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/delegation/holder.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/delegation/revocation.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/errors.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/hardware_acceptance.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/node.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/peer.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/policy.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/provenance.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/response.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/base.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/binding.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/sev_snp.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/software.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/tpm.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/tee/tsm.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/trace_binding.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/_b64url.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/a2a_adapter.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/a2a_sdk.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/client.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/constants.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_runtime/transport/wire.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/sev_snp.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/tdx.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/tpm.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/tpm_roots.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/src/ca2a_verify/verify.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/committed_blobs.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/conformance/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/conformance/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/conformance/conftest.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/conformance/test_action_fixture_bundles.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/conformance/test_profile_conformance.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/conftest.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/a2a/send_message_ca2a.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-001-verified/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-001-verified/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-001-verified/expected.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-002-parent-hash-mismatch/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-002-parent-hash-mismatch/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-002-parent-hash-mismatch/expected.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-006-policy-denial/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-006-policy-denial/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-006-policy-denial/expected.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-010-scope-escalation/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-010-scope-escalation/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-010-scope-escalation/expected.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-012-credential-expired/chain.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-012-credential-expired/dag.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/action/action-012-credential-expired/expected.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/ak.pub +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/akcert_0x01C101D0.der +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/nonce.hex +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/pcrs.bin +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/quote.msg +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/hardware/azure-vtpm-2026-07-27/quote.sig +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/response-mac-v1.json +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/sev_snp/amd_milan_cert_chain.pem +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/tdx/intel_sgx_root_ca.pem +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/tpm/bare-rsa-prefix-0016/README.md +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/tpm/bare-rsa-prefix-0016/ak-chain.pem +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/tpm/bare-rsa-prefix-0016/attest.hex +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/tpm/bare-rsa-prefix-0016/signature.hex +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/fixtures/tpm/bare-rsa-prefix-0016/trusted-root.pem +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/__init__.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/conftest.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_a2a_adapter.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_a2a_sdk_bridge.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_a2a_sdk_loopback.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_agent_manifest_cose.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_bootstrap.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_cedar.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_channel_and_tee.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_claim1_attenuation.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_claim2_replay.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_claim3_scope_policy.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_claim4_sealed.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_claim5_provenance.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_claim6_cross_operator.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_cli_start.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_committed_examples_verify.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_config.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_delegation.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_dependency_security_floors.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_docs_quickstart.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_documented_experiments.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_errors.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_hardware_acceptance.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_holder_binding.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_lineage_cli.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_mutual_attestation.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_peer.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_peer_request.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_provenance.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_response_authentication.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_revocation.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_sealed_channel.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_sev_snp.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_snp_tdx_attest.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_tpm.py +0 -0
- {ca2a_runtime-0.3.0 → ca2a_runtime-0.3.1}/tests/unit/test_tpm_attest.py +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Fuzzing
|
|
2
|
+
|
|
3
|
+
Coverage-guided fuzzing via [ClusterFuzzLite](https://google.github.io/clusterfuzzlite/),
|
|
4
|
+
running Atheris against the input cA2A reads before it has decided to trust the
|
|
5
|
+
party that sent it. Mirrors the setup in agentrust-io/agent-manifest and
|
|
6
|
+
agentrust-io/cmcp.
|
|
7
|
+
|
|
8
|
+
## What is fuzzed
|
|
9
|
+
|
|
10
|
+
| Target | Surface |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `fuzz_wire_documents.py` | JSON from outside: the A2A request `PeerNode.handle` serves (delegation chain, holder proof, caller offer, sealed payload), the authenticated-response envelope, a revocation snapshot, and the chain and TRACE DAG documents the offline verifier loads. |
|
|
13
|
+
| `fuzz_attestation_parsers.py` | TDX quote, SEV-SNP report, TPM quote and TPMT_SIGNATURE parsing, plus `verify_challenge` over caller-supplied challenge text. |
|
|
14
|
+
| `fuzz_canonical_json.py` | The RFC 8785 bytes every credential, holder proof, revocation statement and response MAC is computed over. |
|
|
15
|
+
|
|
16
|
+
## The properties
|
|
17
|
+
|
|
18
|
+
The wire and parser targets assert that each surface fails closed: it returns,
|
|
19
|
+
or raises the error family it documents (`CA2AError`, and `AttestationFailed`
|
|
20
|
+
for evidence). A `TypeError`, `struct.error`, `AttributeError` or
|
|
21
|
+
`RecursionError` escaping means a caller written against the documented
|
|
22
|
+
exception will not catch it, and on the reference server the connection drops
|
|
23
|
+
with no response.
|
|
24
|
+
|
|
25
|
+
`fuzz_canonical_json.py` asserts a round trip: parsing the canonical output must
|
|
26
|
+
reproduce the input exactly, and integers outside +/-(2**53 - 1) must be
|
|
27
|
+
refused. cA2A's data model has no floats, so the comparison is exact.
|
|
28
|
+
|
|
29
|
+
## Standing when added
|
|
30
|
+
|
|
31
|
+
A local plain-Python run of each `TestOneInput` (Atheris does not install on the
|
|
32
|
+
Windows machine it was written on) found three escapes that are fixed in the
|
|
33
|
+
same change, with regression tests: `TdxQuote.parse` raising `struct.error` on a
|
|
34
|
+
quote whose signature section is shorter than its declared contents,
|
|
35
|
+
`verify_challenge` raising `TypeError` on a non-ASCII MAC, and
|
|
36
|
+
`DelegationCredential.from_dict` raising `TypeError` on a hop that is not an
|
|
37
|
+
object.
|
|
38
|
+
|
|
39
|
+
## Bundling gotcha
|
|
40
|
+
|
|
41
|
+
`compile_python_fuzzer` bundles each target with PyInstaller, which follows
|
|
42
|
+
static imports only and bundles code, not package data. `build.sh` passes
|
|
43
|
+
`--collect-submodules=email` for the lazy `email.mime` import in the
|
|
44
|
+
cryptography and pydantic stacks, and `--collect-data` for `agentrust_trace`,
|
|
45
|
+
whose TRACE schema `ca2a_verify.dag` loads at import time.
|
|
46
|
+
|
|
47
|
+
## Running locally
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
git clone https://github.com/google/clusterfuzzlite --depth 1 /tmp/clusterfuzzlite
|
|
51
|
+
python /tmp/clusterfuzzlite/infra/helper.py build_image --external $PWD
|
|
52
|
+
python /tmp/clusterfuzzlite/infra/helper.py build_fuzzers --external --sanitizer address $PWD
|
|
53
|
+
python /tmp/clusterfuzzlite/infra/helper.py run_fuzzer --external $PWD fuzz_wire_documents
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## In CI
|
|
57
|
+
|
|
58
|
+
`cflite_pr.yml` fuzzes code the pull request touched, for five minutes.
|
|
59
|
+
`cflite_batch.yml` runs every target for thirty minutes, nightly. Both are
|
|
60
|
+
read-only and time out at 45 minutes; the oss-fuzz base image build dominates.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash -eu
|
|
2
|
+
# Build the fuzz targets for ClusterFuzzLite.
|
|
3
|
+
#
|
|
4
|
+
# Installed rather than put on the path so the targets exercise the same import
|
|
5
|
+
# surface a consumer gets. Third-party dependencies come from the same
|
|
6
|
+
# hash-pinned locks the container image uses, and the package goes in with
|
|
7
|
+
# --no-deps and without build isolation, so nothing here resolves unpinned.
|
|
8
|
+
|
|
9
|
+
cd "$SRC/ca2a"
|
|
10
|
+
pip3 install --no-cache-dir --require-hashes -r requirements/build.txt
|
|
11
|
+
pip3 install --no-cache-dir --require-hashes -r requirements/runtime.txt
|
|
12
|
+
pip3 install --no-cache-dir --no-deps --no-build-isolation .
|
|
13
|
+
|
|
14
|
+
# compile_python_fuzzer bundles each target with PyInstaller, which follows
|
|
15
|
+
# static imports only and bundles code, not package data.
|
|
16
|
+
PYI_ARGS=(
|
|
17
|
+
# The cryptography and pydantic stacks reach email.mime lazily; without this
|
|
18
|
+
# the bundled target dies with ModuleNotFoundError, which libFuzzer reports
|
|
19
|
+
# as a crash in the target.
|
|
20
|
+
--collect-submodules=email
|
|
21
|
+
# ca2a_verify.dag validates records against the TRACE JSON schema, which
|
|
22
|
+
# agentrust_trace loads from inside its package at import time.
|
|
23
|
+
--collect-data=agentrust_trace
|
|
24
|
+
--collect-data=agent_manifest
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
for target in "$SRC"/ca2a/.clusterfuzzlite/fuzz_*.py; do
|
|
28
|
+
compile_python_fuzzer "$target" "${PYI_ARGS[@]}"
|
|
29
|
+
done
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""Fuzz the attestation evidence parsers.
|
|
3
|
+
|
|
4
|
+
A callee reads a caller's evidence (``raw_evidence`` in a ``caller_offer``)
|
|
5
|
+
before deciding to trust anything about it, and an auditor feeds recorded
|
|
6
|
+
quotes to ``ca2a_verify`` offline. These parsers read that binary at fixed
|
|
7
|
+
offsets under declared lengths the blob itself supplies: a TDX quote with four
|
|
8
|
+
nested size fields, an SNP report, a TPM quote and a TPMT_SIGNATURE.
|
|
9
|
+
|
|
10
|
+
The property is that each fails closed: it returns, or raises
|
|
11
|
+
AttestationFailed, the error the verifier documents. A struct.error, IndexError
|
|
12
|
+
or OverflowError reaching the caller means a declared length was believed. That
|
|
13
|
+
is the bug this target was written against: TdxQuote.parse used to raise
|
|
14
|
+
struct.error on a quote whose signature section was shorter than it claimed.
|
|
15
|
+
|
|
16
|
+
The challenge verifier is included because its input, the offer nonce and the
|
|
17
|
+
holder proof's challenge, is caller text read before anything authenticates it.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
import atheris
|
|
23
|
+
|
|
24
|
+
with atheris.instrument_imports():
|
|
25
|
+
from ca2a_runtime.challenge import verify_challenge
|
|
26
|
+
from ca2a_runtime.errors import AttestationFailed
|
|
27
|
+
from ca2a_runtime.tee.sev_snp import SevSnpReport
|
|
28
|
+
from ca2a_runtime.tee.tdx import TdxQuote
|
|
29
|
+
from ca2a_runtime.tee.tpm import TpmQuote
|
|
30
|
+
from ca2a_verify.tpm import parse_tpmt_signature
|
|
31
|
+
|
|
32
|
+
_SECRET = b"\x00" * 32
|
|
33
|
+
|
|
34
|
+
_PARSERS = [
|
|
35
|
+
TdxQuote.parse,
|
|
36
|
+
SevSnpReport.parse,
|
|
37
|
+
TpmQuote.parse,
|
|
38
|
+
parse_tpmt_signature,
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def TestOneInput(data: bytes) -> None:
|
|
43
|
+
if not data:
|
|
44
|
+
return
|
|
45
|
+
fdp = atheris.FuzzedDataProvider(data)
|
|
46
|
+
choice = fdp.ConsumeIntInRange(0, len(_PARSERS))
|
|
47
|
+
try:
|
|
48
|
+
if choice == len(_PARSERS):
|
|
49
|
+
verify_challenge(_SECRET, fdp.ConsumeUnicode(fdp.remaining_bytes()))
|
|
50
|
+
else:
|
|
51
|
+
_PARSERS[choice](fdp.ConsumeBytes(fdp.remaining_bytes()))
|
|
52
|
+
except AttestationFailed:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def main() -> None:
|
|
57
|
+
atheris.Setup(sys.argv, TestOneInput)
|
|
58
|
+
atheris.Fuzz()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
main()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""Fuzz the RFC 8785 canonicalizer for the invariant its signatures depend on.
|
|
3
|
+
|
|
4
|
+
canonicalize() produces the bytes every delegation credential, holder proof,
|
|
5
|
+
revocation statement and response MAC is computed over, so the bytes must be a
|
|
6
|
+
faithful, lossless encoding of the input. The property asserted is a round trip:
|
|
7
|
+
parsing the canonical output back must reproduce the input exactly.
|
|
8
|
+
|
|
9
|
+
A crash-only check would pass over the bugs that matter here. The ones found in
|
|
10
|
+
sibling canonicalizers were silent: two distinct keys serialized as one key
|
|
11
|
+
twice, a parser kept one of the pair, and a field vanished from a document whose
|
|
12
|
+
signature claimed to cover it.
|
|
13
|
+
|
|
14
|
+
Structure is built from the fuzz data rather than by mutating JSON text, so the
|
|
15
|
+
budget goes on key and value shapes (combining marks, surrogate pairs, control
|
|
16
|
+
characters, integers straddling 2**53) rather than on producing valid JSON.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
import atheris
|
|
23
|
+
|
|
24
|
+
with atheris.instrument_imports():
|
|
25
|
+
from ca2a_runtime.canonical import canonicalize
|
|
26
|
+
|
|
27
|
+
_MAX_DEPTH = 4
|
|
28
|
+
_MAX_ITEMS = 6
|
|
29
|
+
_SAFE = 2**53 - 1
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _build(fdp, depth=0):
|
|
33
|
+
if depth >= _MAX_DEPTH or fdp.remaining_bytes() == 0:
|
|
34
|
+
return fdp.ConsumeUnicodeNoSurrogates(16)
|
|
35
|
+
kind = fdp.ConsumeIntInRange(0, 6)
|
|
36
|
+
if kind == 0:
|
|
37
|
+
return None
|
|
38
|
+
if kind == 1:
|
|
39
|
+
return fdp.ConsumeBool()
|
|
40
|
+
if kind == 2:
|
|
41
|
+
# Straddle the safe-integer boundary: outside it canonicalize() must
|
|
42
|
+
# refuse rather than emit digits a conforming verifier would not.
|
|
43
|
+
return fdp.ConsumeIntInRange(-(2**54), 2**54)
|
|
44
|
+
if kind == 3:
|
|
45
|
+
return fdp.ConsumeUnicodeNoSurrogates(64)
|
|
46
|
+
if kind == 4:
|
|
47
|
+
return [_build(fdp, depth + 1) for _ in range(fdp.ConsumeIntInRange(0, _MAX_ITEMS))]
|
|
48
|
+
return {
|
|
49
|
+
fdp.ConsumeUnicodeNoSurrogates(24): _build(fdp, depth + 1)
|
|
50
|
+
for _ in range(fdp.ConsumeIntInRange(0, _MAX_ITEMS))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _has_unsafe_int(value):
|
|
55
|
+
if isinstance(value, bool):
|
|
56
|
+
return False
|
|
57
|
+
if isinstance(value, int):
|
|
58
|
+
return not -_SAFE <= value <= _SAFE
|
|
59
|
+
if isinstance(value, dict):
|
|
60
|
+
return any(_has_unsafe_int(v) for v in value.values())
|
|
61
|
+
if isinstance(value, list):
|
|
62
|
+
return any(_has_unsafe_int(v) for v in value)
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def TestOneInput(data: bytes) -> None:
|
|
67
|
+
fdp = atheris.FuzzedDataProvider(data)
|
|
68
|
+
value = _build(fdp)
|
|
69
|
+
try:
|
|
70
|
+
out = canonicalize(value)
|
|
71
|
+
except ValueError:
|
|
72
|
+
# Declared: integers outside the RFC 8785 safe domain, and only those.
|
|
73
|
+
assert _has_unsafe_int(value), "canonicalize() refused an in-domain value"
|
|
74
|
+
return
|
|
75
|
+
assert not _has_unsafe_int(value), "an out-of-domain integer was serialized"
|
|
76
|
+
|
|
77
|
+
# cA2A's data model has no floats, so every number re-parses as the int it
|
|
78
|
+
# was and the round trip can be asserted exactly, bools included.
|
|
79
|
+
assert json.loads(out) == value, f"canonical bytes did not round-trip: {out!r}"
|
|
80
|
+
assert canonicalize(json.loads(out)) == out, "canonical form is not a fixed point"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def main() -> None:
|
|
84
|
+
atheris.Setup(sys.argv, TestOneInput)
|
|
85
|
+
atheris.Fuzz()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""Fuzz the JSON documents cA2A accepts from outside.
|
|
3
|
+
|
|
4
|
+
Each surface takes arbitrary JSON from a party that has not been authenticated
|
|
5
|
+
yet, and each documents one error family for anything malformed:
|
|
6
|
+
|
|
7
|
+
- the A2A request a callee serves (``PeerNode.handle``), which parses the
|
|
8
|
+
delegation chain, holder proof, caller offer and sealed payload, then runs
|
|
9
|
+
the inbound pipeline up to the first refusal: CA2AError;
|
|
10
|
+
- the authenticated-response envelope (``response.decode``):
|
|
11
|
+
ResponseAuthenticationFailed, a CA2AError;
|
|
12
|
+
- a revocation snapshot (``RevocationSnapshot.from_dict``): InvalidRevocation;
|
|
13
|
+
- a delegation chain document and a TRACE DAG handed to the offline verifier:
|
|
14
|
+
CA2AError.
|
|
15
|
+
|
|
16
|
+
Anything else escaping (TypeError, AttributeError, KeyError, UnicodeError,
|
|
17
|
+
RecursionError) is a crash: on the live path it drops the connection with no
|
|
18
|
+
response, and offline it escapes the verifier's contract. The input is decoded
|
|
19
|
+
the way the reference server decodes a body, so what reaches the parsers is
|
|
20
|
+
exactly what the wire can deliver.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import contextlib
|
|
24
|
+
import json
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
import atheris
|
|
28
|
+
|
|
29
|
+
with atheris.instrument_imports():
|
|
30
|
+
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
31
|
+
|
|
32
|
+
from ca2a_runtime import response
|
|
33
|
+
from ca2a_runtime.delegation import RevocationSnapshot
|
|
34
|
+
from ca2a_runtime.errors import CA2AError
|
|
35
|
+
from ca2a_runtime.node import PeerNode
|
|
36
|
+
from ca2a_runtime.policy import LocalPolicy
|
|
37
|
+
from ca2a_verify.dag import verify_trace_dag
|
|
38
|
+
from ca2a_verify.verify import _parse_chain, verify_delegation_chain
|
|
39
|
+
|
|
40
|
+
_ROOT = Ed25519PrivateKey.from_private_bytes(b"\x01" * 32).public_key().public_bytes_raw().hex()
|
|
41
|
+
_NODE = PeerNode(LocalPolicy.of(["read", "write"]), trusted_root_issuers={_ROOT})
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _handle(doc):
|
|
45
|
+
if isinstance(doc, dict):
|
|
46
|
+
_NODE.handle(doc)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _revocations(doc):
|
|
50
|
+
RevocationSnapshot.from_dict(doc)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _chain(doc):
|
|
54
|
+
verify_delegation_chain(_parse_chain(doc), trusted_root_issuers={_ROOT})
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _dag(doc):
|
|
58
|
+
if isinstance(doc, dict):
|
|
59
|
+
doc = doc.get("records", doc)
|
|
60
|
+
if isinstance(doc, list) and doc:
|
|
61
|
+
verify_trace_dag(doc, trusted_keys=[])
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
_JSON_TARGETS = [_handle, _revocations, _chain, _dag]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def TestOneInput(data: bytes) -> None:
|
|
68
|
+
if not data:
|
|
69
|
+
return
|
|
70
|
+
fdp = atheris.FuzzedDataProvider(data)
|
|
71
|
+
choice = fdp.ConsumeIntInRange(0, len(_JSON_TARGETS))
|
|
72
|
+
raw = fdp.ConsumeBytes(fdp.remaining_bytes())
|
|
73
|
+
if choice == len(_JSON_TARGETS):
|
|
74
|
+
with contextlib.suppress(CA2AError):
|
|
75
|
+
response.decode(raw)
|
|
76
|
+
return
|
|
77
|
+
try:
|
|
78
|
+
doc = json.loads(raw)
|
|
79
|
+
except (ValueError, RecursionError):
|
|
80
|
+
# The reference server answers 400 before any parser runs.
|
|
81
|
+
return
|
|
82
|
+
with contextlib.suppress(CA2AError):
|
|
83
|
+
_JSON_TARGETS[choice](doc)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def main() -> None:
|
|
87
|
+
atheris.Setup(sys.argv, TestOneInput)
|
|
88
|
+
atheris.Fuzz()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
main()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
day: "monday"
|
|
8
|
+
open-pull-requests-limit: 5
|
|
9
|
+
ignore:
|
|
10
|
+
- dependency-name: "*"
|
|
11
|
+
update-types:
|
|
12
|
+
- "version-update:semver-major"
|
|
13
|
+
|
|
14
|
+
- package-ecosystem: "github-actions"
|
|
15
|
+
directory: "/"
|
|
16
|
+
schedule:
|
|
17
|
+
interval: "weekly"
|
|
18
|
+
day: "monday"
|
|
19
|
+
open-pull-requests-limit: 5
|
|
20
|
+
groups:
|
|
21
|
+
codeql-action:
|
|
22
|
+
patterns:
|
|
23
|
+
- "github/codeql-action*"
|
|
24
|
+
|
|
25
|
+
# Refreshes the digest the Dockerfile pins its base image to. Without this the
|
|
26
|
+
# pin would hold the image at whatever it was on the day it was written.
|
|
27
|
+
- package-ecosystem: "docker"
|
|
28
|
+
directory: "/"
|
|
29
|
+
schedule:
|
|
30
|
+
interval: "weekly"
|
|
31
|
+
day: "monday"
|
|
32
|
+
open-pull-requests-limit: 5
|
|
33
|
+
# Digest refreshes and 3.11 patch releases only. Moving the image to a new
|
|
34
|
+
# Python minor is a deliberate change with its own PR and test run.
|
|
35
|
+
ignore:
|
|
36
|
+
- dependency-name: "python"
|
|
37
|
+
update-types:
|
|
38
|
+
- "version-update:semver-major"
|
|
39
|
+
- "version-update:semver-minor"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: ClusterFuzzLite batch
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# 04:40 UTC daily, off the hour and off agent-manifest's 04:20 slot.
|
|
6
|
+
- cron: '40 4 * * *'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions: read-all
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: cflite-batch
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
fuzz:
|
|
17
|
+
name: Batch fuzz
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 45
|
|
20
|
+
steps:
|
|
21
|
+
- name: Build fuzzers
|
|
22
|
+
uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1
|
|
23
|
+
with:
|
|
24
|
+
language: python
|
|
25
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
sanitizer: address
|
|
27
|
+
|
|
28
|
+
- name: Run fuzzers
|
|
29
|
+
uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1
|
|
30
|
+
with:
|
|
31
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
+
# Every target, not just what changed. Thirty minutes of fuzzing
|
|
33
|
+
# leaves room for the base image build inside the 45 minute timeout.
|
|
34
|
+
fuzz-seconds: 1800
|
|
35
|
+
mode: batch
|
|
36
|
+
sanitizer: address
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: ClusterFuzzLite PR
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- 'src/**'
|
|
7
|
+
- 'requirements/build.txt'
|
|
8
|
+
- 'requirements/runtime.txt'
|
|
9
|
+
- '.clusterfuzzlite/**'
|
|
10
|
+
- '.github/workflows/cflite_pr.yml'
|
|
11
|
+
|
|
12
|
+
# Read-only. Findings surface in the job log and the uploaded crash artifact
|
|
13
|
+
# rather than as code-scanning alerts, so no security-events: write is needed.
|
|
14
|
+
permissions: read-all
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: cflite-pr-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
fuzz:
|
|
22
|
+
name: Fuzz changed code
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 45
|
|
25
|
+
steps:
|
|
26
|
+
# Only the address sanitizer. The targets are pure Python under Atheris,
|
|
27
|
+
# where undefined-behaviour instrumentation has nothing to instrument.
|
|
28
|
+
- name: Build fuzzers
|
|
29
|
+
uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1
|
|
30
|
+
with:
|
|
31
|
+
language: python
|
|
32
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
33
|
+
sanitizer: address
|
|
34
|
+
|
|
35
|
+
- name: Run fuzzers
|
|
36
|
+
uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1
|
|
37
|
+
with:
|
|
38
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
39
|
+
fuzz-seconds: 300
|
|
40
|
+
# code-change fuzzes only what the PR touched, which is what keeps
|
|
41
|
+
# this inside a PR's time budget. The nightly batch covers the rest.
|
|
42
|
+
mode: code-change
|
|
43
|
+
sanitizer: address
|
|
@@ -13,12 +13,15 @@ on:
|
|
|
13
13
|
|
|
14
14
|
permissions:
|
|
15
15
|
contents: read
|
|
16
|
-
pull-requests: read
|
|
17
|
-
statuses: write
|
|
18
16
|
|
|
19
17
|
jobs:
|
|
20
18
|
gate:
|
|
21
19
|
runs-on: ubuntu-latest
|
|
20
|
+
# Reads the PR and its reviews, then fails the job if no maintainer
|
|
21
|
+
# approved the head commit. It writes nothing, so no write scope.
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
pull-requests: read
|
|
22
25
|
if: github.event.pull_request.base.ref == 'main'
|
|
23
26
|
steps:
|
|
24
27
|
- name: Check for maintainer approval
|
|
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.1] - 2026-09-26
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Malformed input from outside now fails with the documented error instead of
|
|
15
|
+
escaping as a Python exception. `TdxQuote.parse` confines reads to the declared
|
|
16
|
+
signature section and checks each nested length (it raised `struct.error` on a
|
|
17
|
+
short section); `verify_challenge` refuses a MAC that is not 64 lowercase hex
|
|
18
|
+
(a non-ASCII one raised `TypeError`); `DelegationCredential.from_dict` and
|
|
19
|
+
`verify_trace_dag` refuse entries that are not objects; the reference server
|
|
20
|
+
answers 400 to bodies that hit the JSON parser's nesting or integer-digit
|
|
21
|
+
limits instead of dropping the connection (#202).
|
|
22
|
+
- `canonicalize` refuses non-string object keys. It coerced them with `str()`, so
|
|
23
|
+
`{1: "a", "1": "b"}` serialized one key twice (#202).
|
|
24
|
+
- The container image installs its dependencies from hash-pinned locks
|
|
25
|
+
(`requirements/runtime.txt`, `requirements/build.txt`) and pins the base image
|
|
26
|
+
by digest. ClusterFuzzLite targets cover the wire documents, the attestation
|
|
27
|
+
parsers and the canonicalizer (#202).
|
|
28
|
+
|
|
10
29
|
## [0.3.0] - 2026-09-25
|
|
11
30
|
|
|
12
31
|
### Changed
|
|
@@ -391,7 +410,8 @@ built/stubbed boundary.
|
|
|
391
410
|
- The sealed channel does not by itself establish the enclave-held-private-key property; that is a hardware attestation guarantee that lands with real-hardware validation.
|
|
392
411
|
- Alpha schemas: the delegation credential and TRACE link schemas are not yet stable or versioned, and peer attestation evidence is not yet RATS/EAT conformant.
|
|
393
412
|
|
|
394
|
-
[Unreleased]: https://github.com/agentrust-io/ca2a/compare/v0.3.
|
|
413
|
+
[Unreleased]: https://github.com/agentrust-io/ca2a/compare/v0.3.1...main
|
|
414
|
+
[0.3.1]: https://github.com/agentrust-io/ca2a/compare/v0.3.0...v0.3.1
|
|
395
415
|
[0.3.0]: https://github.com/agentrust-io/ca2a/compare/v0.2.0...v0.3.0
|
|
396
416
|
[0.2.0]: https://github.com/agentrust-io/ca2a/compare/v0.1.0a1...v0.2.0
|
|
397
417
|
[0.1.0a1]: https://github.com/agentrust-io/ca2a/releases/tag/v0.1.0a1
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Base image pinned by its multi-arch index digest, so a re-pushed tag cannot
|
|
2
|
+
# change what is built. Refresh the digest and the tag together.
|
|
3
|
+
FROM python:3.11.15-slim-bookworm@sha256:d29f48a31a8b408ed19272ca1e7b10ebae13b240a27e862d3d4217c528e2e0c3 AS builder
|
|
4
|
+
|
|
5
|
+
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
|
6
|
+
PIP_NO_CACHE_DIR=1
|
|
7
|
+
|
|
8
|
+
WORKDIR /build
|
|
9
|
+
COPY requirements/build.txt ./requirements/build.txt
|
|
10
|
+
# The build backend comes from a hash-pinned lock, and the wheel is built
|
|
11
|
+
# without build isolation so pip does not fetch an unpinned hatchling of its own.
|
|
12
|
+
RUN python -m pip install --require-hashes -r requirements/build.txt
|
|
13
|
+
COPY pyproject.toml README.md LICENSE NOTICE ./
|
|
14
|
+
COPY src ./src
|
|
15
|
+
RUN python -m pip wheel --no-deps --no-build-isolation --wheel-dir /wheels .
|
|
16
|
+
|
|
17
|
+
FROM python:3.11.15-slim-bookworm@sha256:d29f48a31a8b408ed19272ca1e7b10ebae13b240a27e862d3d4217c528e2e0c3 AS runtime
|
|
18
|
+
|
|
19
|
+
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
|
20
|
+
PIP_NO_CACHE_DIR=1 \
|
|
21
|
+
PYTHONUNBUFFERED=1
|
|
22
|
+
|
|
23
|
+
RUN groupadd --gid 10001 ca2a \
|
|
24
|
+
&& useradd --uid 10001 --gid 10001 --no-create-home --home-dir /var/lib/ca2a ca2a \
|
|
25
|
+
&& install -d -o ca2a -g ca2a /var/lib/ca2a /etc/ca2a
|
|
26
|
+
|
|
27
|
+
# Third-party runtime dependencies from the hash-pinned lock, then the locally
|
|
28
|
+
# built wheel with --no-deps, so nothing in the image is resolved unpinned.
|
|
29
|
+
COPY requirements/runtime.txt /tmp/runtime.txt
|
|
30
|
+
COPY --from=builder /wheels /wheels
|
|
31
|
+
RUN python -m pip install --require-hashes -r /tmp/runtime.txt \
|
|
32
|
+
&& python -m pip install --no-deps /wheels/ca2a_runtime-*.whl \
|
|
33
|
+
&& rm -rf /wheels /tmp/runtime.txt
|
|
34
|
+
|
|
35
|
+
USER 10001:10001
|
|
36
|
+
WORKDIR /var/lib/ca2a
|
|
37
|
+
EXPOSE 8443
|
|
38
|
+
|
|
39
|
+
ENTRYPOINT ["ca2a"]
|
|
40
|
+
CMD ["--help"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ca2a-runtime
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Confidential agent-to-agent runtime: attested, attenuated delegation and sealed peer channels for A2A
|
|
5
5
|
Project-URL: Homepage, https://github.com/agentrust-io/ca2a
|
|
6
6
|
Project-URL: Repository, https://github.com/agentrust-io/ca2a
|
|
@@ -16,7 +16,7 @@ cA2A is a profile on A2A that adds signed attenuated delegation, peer appraisal,
|
|
|
16
16
|
[What this proves, and what it does not](LIMITATIONS.md){ .md-button }
|
|
17
17
|
|
|
18
18
|
!!! tip "TL;DR"
|
|
19
|
-
[ca2a-runtime](https://pypi.org/project/ca2a-runtime/) 0.3.
|
|
19
|
+
[ca2a-runtime](https://pypi.org/project/ca2a-runtime/) 0.3.1 (MIT developer preview; the PyPI name `ca2a` belongs to an unrelated project) rejects scope escalation offline with no hardware or running peer. SEV-SNP and TDX appraisal ran on real Azure and GCP evidence, including an Azure SEV-SNP peer calling a GCP TDX peer on 2026-07-27, but peer appraisal is one-directional so far and binding the seal to a verified measurement on a live call is on the roadmap.
|
|
20
20
|
|
|
21
21
|
<div class="grid cards" markdown>
|
|
22
22
|
|
|
@@ -71,4 +71,4 @@ Software and hardware modes provide different assurance. Peer appraisal has been
|
|
|
71
71
|
|
|
72
72
|
For the architecture and trust boundaries, read [How It Works](docs/concepts.md). The normative profile, with the delegation chain, sealed channel, and conformance rules, is in [Profile](docs/spec/profile.md).
|
|
73
73
|
|
|
74
|
-
**Status:** ca2a-runtime 0.3.
|
|
74
|
+
**Status:** ca2a-runtime 0.3.1 developer preview · MIT · hosting at the Agentic AI Foundation proposed, not accepted · Sponsored by OPAQUE, which funds the engineering, infrastructure and confidential-computing work behind these projects.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ca2a-runtime"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Confidential agent-to-agent runtime: attested, attenuated delegation and sealed peer channels for A2A"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Build backend for the container image's builder stage. The wheel is built with
|
|
2
|
+
# --no-build-isolation so pip does not fetch hatchling unpinned into a throwaway
|
|
3
|
+
# environment. Compile with:
|
|
4
|
+
# uv pip compile requirements/build.in --generate-hashes --universal \
|
|
5
|
+
# --python-version 3.11 -o requirements/build.txt
|
|
6
|
+
hatchling
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# This file was autogenerated by uv via the following command:
|
|
2
|
+
# uv pip compile requirements/build.in --generate-hashes --universal --python-version 3.11 -o requirements/build.txt
|
|
3
|
+
hatchling==1.32.4 \
|
|
4
|
+
--hash=sha256:08ecf7548fb48205e7f213d70c71e67b8271b7242093dc3f1da578b42c734a2c \
|
|
5
|
+
--hash=sha256:c4468f73144c054d2aab4ef0f0378c43b9878bf07f8ffd6b79690e970d375f07
|
|
6
|
+
# via -r requirements/build.in
|
|
7
|
+
packaging==26.3 \
|
|
8
|
+
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
|
|
9
|
+
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
|
|
10
|
+
# via hatchling
|
|
11
|
+
pathspec==1.1.1 \
|
|
12
|
+
--hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \
|
|
13
|
+
--hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189
|
|
14
|
+
# via hatchling
|
|
15
|
+
pluggy==1.6.0 \
|
|
16
|
+
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
|
|
17
|
+
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
|
|
18
|
+
# via hatchling
|
|
19
|
+
tomlkit==0.15.1 \
|
|
20
|
+
--hash=sha256:177a05aece5a8ca5266fd3c448abb47b8d352f09d477d3ca8332db4d89b24304 \
|
|
21
|
+
--hash=sha256:e25bbf38843005246210a12982776f27f99cb9be67160e14434d0c0d21ee1e97
|
|
22
|
+
# via hatchling
|
|
23
|
+
trove-classifiers==2026.9.21.13 \
|
|
24
|
+
--hash=sha256:0a9ebc8d4e2f3e8a22848c5258033035bec17a3012ac3fea16dbaa764489eb71 \
|
|
25
|
+
--hash=sha256:8b1ff4f9c191b1040b71c37f1e445ab99732911e3cd91de52838453a854d7a17
|
|
26
|
+
# via hatchling
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Runtime dependencies for the container image, mirroring [project.dependencies]
|
|
2
|
+
# in pyproject.toml. The Dockerfile installs this lock with --require-hashes and
|
|
3
|
+
# then adds the locally built ca2a-runtime wheel with --no-deps, so nothing in
|
|
4
|
+
# the image is fetched unpinned. Keep it in step with pyproject.toml. Compile with:
|
|
5
|
+
# uv pip compile requirements/runtime.in --generate-hashes --universal \
|
|
6
|
+
# --python-version 3.11 -o requirements/runtime.txt
|
|
7
|
+
cryptography>=50.0
|
|
8
|
+
pyyaml>=6.0
|
|
9
|
+
cedarpy==4.8.7
|
|
10
|
+
agentrust-trace>=0.5
|
|
11
|
+
agent-manifest>=0.11.1
|
|
12
|
+
rfc8785>=0.1
|