Skip to content

Commit 763b591

Browse files
committed
release: v0.3.0 - real framework integrations, security hardening, CI/CD
Minor version bump (0.2.5 -> 0.3.0) bundling seven previously merged but unreleased pull requests. Security: - CRITICAL: delegation chain auth bypass fix (PR #45). Parent tokens and capability attenuation are now strictly verified on every delegation verify. - SSRF hardening on agent discovery, DID resolution, credential fetch (PR #47). - Timing-safe comparisons for signature and token equality checks (PR #47). - Seven REST API router exception paths no longer leak internals to clients (PR #47). Added: - Real LangChain integration using BaseCallbackHandler (PR #42). - Real OpenAI Agents SDK integration via MCPServerStdio (PR #48). - Real CrewAI integration via MCPServerAdapter (PR #51). Fixed: - Article 43 Annex III conformity assessment now correctly differentiates categories that require a notified body versus permitted self-assessment (PR #46). - EAS schema UID derivation matches the on-chain EAS encoding (PR #50). - Attested event decoding prefers web3.py ABI decoding with a hardened topic-signature fallback (PR #50). - tests/conftest.py blockchain_service_mock now emits an Attested log with the correct topic[0] so the hardened decoder is exercised end to end. Infrastructure: - GitHub Actions CI/CD: pytest matrix (py 3.10 through 3.13), ruff, mypy, bandit, pip-audit, plus a PyPI publish workflow on release creation (PR #49). - Default pytest addopts now include "-p no:logfire" so that transitive installs of opentelemetry-sdk (via CrewAI) do not abort collection with ImportError: cannot import name 'ReadableLogRecord'. Files updated: pyproject.toml (0.2.5 -> 0.3.0, addopts), attestix/__init__.py (0.2.4 -> 0.3.0), server.json (0.2.4 -> 0.3.0), CHANGELOG.md (0.3.0 section), tests/conftest.py (Attested log mock). All 358 tests pass, 1 skipped. twine check on wheel and sdist: PASSED.
1 parent 4be8eb9 commit 763b591

5 files changed

Lines changed: 102 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,84 @@ All notable changes to Attestix are documented here.
44

55
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [0.3.0] - 2026-04-17
8+
9+
Security hardening release bundling seven previously merged but unreleased
10+
pull requests (PR #45 through PR #51). The release ships a critical delegation
11+
auth bypass fix, corrects Article 43 Annex III conformity logic, lands three
12+
real framework integrations (LangChain, OpenAI Agents SDK, CrewAI), and adds
13+
GitHub Actions CI/CD.
14+
15+
Minor version bump (0.2.5 -> 0.3.0) because the batch contains security
16+
fixes, new public integration surfaces, and an Article 43 behavior change.
17+
No breaking API changes for MCP tool callers.
18+
19+
### Security
20+
21+
- **CRITICAL: delegation chain auth bypass fixed** (PR #45). Parent tokens in
22+
a delegation chain are now fully verified and capability attenuation is
23+
strictly enforced. Previously a malicious delegate could craft a child
24+
token whose claimed capabilities exceeded those of the parent. Any
25+
long-lived delegation tokens issued prior to this release should be
26+
reviewed and re-issued.
27+
- **SSRF hardening** (PR #47). Agent discovery, DID resolution, and credential
28+
fetch paths now go through the centralized SSRF guard (private IP blocking,
29+
metadata endpoint blocking, DNS rebind defense) on every outbound request.
30+
- **Timing-safe comparisons** (PR #47). Signature and token equality checks
31+
switched to constant-time comparison (`hmac.compare_digest`) to remove a
32+
timing oracle on credential and delegation verification.
33+
- **API error sanitization** (PR #47). Seven REST API router exception paths
34+
no longer leak stack traces, file paths, or internal type names to
35+
clients; errors are now structured and safe by default.
36+
37+
### Added
38+
39+
- **Real LangChain integration** (PR #42, released now). `integrations/langchain/`
40+
ships an actual `BaseCallbackHandler` subclass that logs every LLM, chain,
41+
and tool event into the Attestix audit trail. Replaces the previous
42+
example-only shim.
43+
- **Real OpenAI Agents SDK integration** (PR #48). `integrations/openai_agents/`
44+
uses `MCPServerStdio` to connect the OpenAI Agents runtime directly to the
45+
Attestix MCP server, exposing all 47 tools as native agent capabilities.
46+
- **Real CrewAI integration** (PR #51). `integrations/crewai/` uses
47+
`MCPServerAdapter` so CrewAI crews can load Attestix tools the same way
48+
they load any other MCP toolset.
49+
50+
### Fixed
51+
52+
- **Article 43 Annex III conformity assessment correctness** (PR #46). The
53+
compliance service now differentiates between Annex III categories when
54+
deciding whether self-assessment is permitted versus notified-body
55+
assessment being required. High-risk systems covered by Annex III point 1
56+
(biometrics) and similar categories are blocked from self-assessment per
57+
the Act.
58+
- **EAS schema UID derivation** (PR #50). On-chain schema UID is now derived
59+
using the exact encoding EAS itself uses (schema string, resolver address,
60+
revocable flag), matching anchors created on-chain with anchors looked up
61+
on-chain. Previously mismatched schema UIDs could cause
62+
`isAttestationValid` lookups to miss.
63+
- **Attested event decoding hardened** (PR #50). `_extract_attestation_uid`
64+
now prefers web3.py's ABI-level `events.Attested().process_log` and falls
65+
back to a topic-signature match on `keccak("Attested(address,address,bytes32,bytes32)")`.
66+
Removes reliance on fragile byte offsets when reading receipt logs.
67+
- **Test mock log shape** (this release). `tests/conftest.py`
68+
`blockchain_service_mock` now emits an Attested-event-shaped log with the
69+
correct topic[0] signature so the hardened decoder path is exercised end
70+
to end in CI.
71+
72+
### Infrastructure
73+
74+
- **GitHub Actions CI/CD** (PR #49). New `.github/workflows/` pipelines run
75+
a pytest matrix (Python 3.10, 3.11, 3.12, 3.13) on pull requests, plus
76+
`ruff`, `mypy`, `bandit`, and `pip-audit` jobs. A separate release
77+
workflow publishes to PyPI on tag push when `PYPI_API_TOKEN` is set as a
78+
repo secret.
79+
- **pytest plugin compatibility** (this release). Default `addopts` now
80+
includes `-p no:logfire` so that transitive installs of
81+
`opentelemetry-sdk` (pulled via CrewAI) do not abort collection with
82+
`ImportError: cannot import name 'ReadableLogRecord'` when the installed
83+
`logfire` version targets a different otel ABI.
84+
785
## [0.2.3] - 2026-02-27
886

987
### Added

attestix/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
- attestix.blockchain: Merkle trees and EAS anchoring
1919
"""
2020

21-
__version__ = "0.2.4"
21+
__version__ = "0.3.0"
2222

2323
# Re-export submodules for convenient access
2424
from attestix import services

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "attestix"
7-
version = "0.2.5"
7+
version = "0.3.0"
88
description = "Attestix - Attestation Infrastructure for AI Agents. DID-based agent identity, W3C Verifiable Credentials, EU AI Act compliance, delegation chains, and reputation scoring. 47 MCP tools across 9 modules."
99
readme = "README.md"
1010
license = {file = "LICENSE"}
@@ -106,6 +106,11 @@ py-modules = ["main", "cli", "config", "errors"]
106106
[tool.pytest.ini_options]
107107
asyncio_mode = "auto"
108108
testpaths = ["tests"]
109+
# Disable the Pydantic logfire plugin by default. When CrewAI (or other deps)
110+
# pull in an opentelemetry-sdk version that is incompatible with the installed
111+
# logfire, the plugin raises ImportError at collection time and aborts the
112+
# whole suite. We do not need logfire for our tests.
113+
addopts = "-p no:logfire"
109114
markers = [
110115
"live_blockchain: requires funded Base Sepolia wallet (deselect with -m 'not live_blockchain')",
111116
]

server.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
"url": "https://github.com/VibeTensor/attestix",
88
"source": "github"
99
},
10-
"version": "0.2.4",
10+
"version": "0.3.0",
1111
"packages": [
1212
{
1313
"registryType": "pypi",
1414
"identifier": "attestix",
15-
"version": "0.2.4",
15+
"version": "0.3.0",
1616
"transport": {
1717
"type": "stdio"
1818
}

tests/conftest.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,26 @@ def blockchain_service_mock():
142142
mock_w3.eth.max_priority_fee = 100000000 # 0.1 gwei
143143
mock_w3.eth.get_balance.return_value = 10**18 # 1 ETH
144144
mock_w3.eth.get_transaction_count.return_value = 0
145+
146+
# Build a realistic Attested event log so _extract_attestation_uid
147+
# can decode it. Topic[0] must be keccak("Attested(address,address,bytes32,bytes32)").
148+
# The single non-indexed uid bytes32 sits at the first 32 bytes of data.
149+
from web3 import Web3 as _Web3
150+
_attested_sig = bytes(
151+
_Web3.keccak(text="Attested(address,address,bytes32,bytes32)")
152+
)
153+
_fake_uid = b"\x01" * 32 # deterministic non-zero UID
145154
mock_w3.eth.wait_for_transaction_receipt.return_value = {
146155
"status": 1,
147156
"blockNumber": 12345,
148157
"gasUsed": 187000,
149158
"logs": [{
150-
"data": b"\x00" * 32 + b"\x01" * 32,
151-
"topics": [b"\x00" * 32, b"\xaa" * 32],
159+
"data": _fake_uid,
160+
"topics": [
161+
_attested_sig,
162+
b"\x00" * 12 + bytes.fromhex("11" * 20), # recipient
163+
b"\x00" * 12 + bytes.fromhex("11" * 20), # attester
164+
],
152165
}],
153166
}
154167
mock_w3.from_wei = lambda val, unit: val / 10**18 if unit == "ether" else val / 10**9

0 commit comments

Comments
 (0)