capiscio-sdk 0.2.0__tar.gz → 0.3.0__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.
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/CHANGELOG.md +21 -7
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/CONTRIBUTING.md +1 -1
- capiscio_sdk-0.3.0/PKG-INFO +126 -0
- capiscio_sdk-0.3.0/README.md +82 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/RELEASE_GUIDE.md +1 -1
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/SECURITY.md +3 -2
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/__init__.py +2 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/config.py +1 -1
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/errors.py +11 -1
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/executor.py +17 -0
- capiscio_sdk-0.3.0/capiscio_sdk/integrations/fastapi.py +73 -0
- capiscio_sdk-0.3.0/capiscio_sdk/simple_guard.py +354 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/types.py +1 -1
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/getting-started/concepts.md +5 -5
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/getting-started/installation.md +2 -2
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/getting-started/quickstart.md +2 -2
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/guides/configuration.md +4 -4
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/index.md +7 -7
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/javascripts/extra.js +1 -1
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/stylesheets/extra.css +1 -1
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/examples/README.md +3 -3
- capiscio_sdk-0.3.0/examples/secure_ping_pong/README.md +47 -0
- capiscio_sdk-0.3.0/examples/secure_ping_pong/client.py +122 -0
- capiscio_sdk-0.3.0/examples/secure_ping_pong/server.py +30 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/examples/simple_agent/README.md +3 -3
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/examples/simple_agent/agent_executor.py +2 -2
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/examples/simple_agent/requirements.txt +1 -1
- capiscio_sdk-0.3.0/mkdocs.yml +63 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/pyproject.toml +7 -1
- capiscio_sdk-0.3.0/tests/unit/test_fastapi_integration.py +71 -0
- capiscio_sdk-0.3.0/tests/unit/test_simple_guard.py +154 -0
- capiscio_sdk-0.2.0/PKG-INFO +0 -221
- capiscio_sdk-0.2.0/README.md +0 -182
- capiscio_sdk-0.2.0/mkdocs.yml +0 -289
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/.github/markdown-link-check-config.json +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/.github/workflows/docs.yml +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/.github/workflows/pr-checks.yml +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/.github/workflows/publish.yml +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/.gitignore +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/.python-version +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/LICENSE +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/QUICK_REFERENCE.md +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/infrastructure/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/infrastructure/cache.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/infrastructure/rate_limiter.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/py.typed +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/scoring/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/scoring/availability.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/scoring/compliance.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/scoring/trust.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/scoring/types.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/agent_card.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/certificate.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/message.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/protocol.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/semver.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/signature.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/capiscio_sdk/validators/url_security.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/assets/.!58931!favicon.ico +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/assets/favicon.ico +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/assets/logo.png +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/guides/scoring.md +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/includes/abbreviations.md +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/docs/stylesheets/unified.css +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/examples/simple_agent/main.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/examples/simple_agent/test_client.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/e2e/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/integration/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/integration/test_real_executor.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/__init__.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_agent_card.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_cache.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_certificate.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_config.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_errors.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_executor.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_message_validator.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_protocol_validator.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_rate_limiter.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_semver_validator.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_signature_validator.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_types.py +0 -0
- {capiscio_sdk-0.2.0 → capiscio_sdk-0.3.0}/tests/unit/test_url_security.py +0 -0
|
@@ -90,13 +90,27 @@ pip install capiscio-sdk==0.1.0
|
|
|
90
90
|
|
|
91
91
|
## [Unreleased]
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
93
|
+
## [0.3.0] - 2025-11-22
|
|
94
|
+
|
|
95
|
+
### Added
|
|
96
|
+
- **SimpleGuard Security Strategy**:
|
|
97
|
+
- **Identity**: Ed25519 JWS signature verification (`X-Capiscio-JWS` header).
|
|
98
|
+
- **Integrity**: SHA-256 Body Hash verification (`bh` claim) to prevent payload tampering.
|
|
99
|
+
- **Freshness**: Replay protection using `exp` (expiration) and `iat` (issued at) claims with a 60-second window.
|
|
100
|
+
- **Zero Config**: Secure by default with minimal setup.
|
|
101
|
+
- **FastAPI Integration**:
|
|
102
|
+
- `CapiscioMiddleware`: Automatic request validation and identity injection into `request.state.agent_id`.
|
|
103
|
+
- `Server-Timing` header support for telemetry (verification time).
|
|
104
|
+
- **Telemetry**:
|
|
105
|
+
- Added `dur` (duration) metric to `Server-Timing` header for monitoring security overhead.
|
|
106
|
+
- **Documentation**:
|
|
107
|
+
- Updated `README.md` with "Enforcement First" strategy.
|
|
108
|
+
- Updated `SECURITY.md` with threat model and verification steps.
|
|
109
|
+
- Added `examples/secure_ping_pong` demo.
|
|
110
|
+
|
|
111
|
+
### Changed
|
|
112
|
+
- **Breaking Change**: Shifted from "Validation" focus to "Enforcement" focus.
|
|
113
|
+
- Updated `pyproject.toml` dependencies to include `cryptography` and `pyjwt`.
|
|
100
114
|
|
|
101
115
|
### Planned for v1.0.0
|
|
102
116
|
- Full A2A v1.0 compliance
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: capiscio-sdk
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Runtime security middleware for A2A agents
|
|
5
|
+
Project-URL: Homepage, https://capisc.io
|
|
6
|
+
Project-URL: Documentation, https://docs.capisc.io/sdk-python
|
|
7
|
+
Project-URL: Repository, https://github.com/capiscio/capiscio-sdk-python
|
|
8
|
+
Project-URL: Issues, https://github.com/capiscio/capiscio-sdk-python/issues
|
|
9
|
+
Author-email: Capiscio Team <team@capisc.io>
|
|
10
|
+
License: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: a2a,agent,agent-to-agent,middleware,security,validation
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: a2a-sdk>=0.1.0
|
|
25
|
+
Requires-Dist: cachetools>=5.3.0
|
|
26
|
+
Requires-Dist: cryptography>=42.0.0
|
|
27
|
+
Requires-Dist: httpx>=0.27.0
|
|
28
|
+
Requires-Dist: pydantic>=2.0.0
|
|
29
|
+
Requires-Dist: pyjwt[crypto]>=2.8.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: black>=24.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: mypy>=1.9.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: starlette>=0.27.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: types-cachetools>=5.3.0; extra == 'dev'
|
|
40
|
+
Provides-Extra: web
|
|
41
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'web'
|
|
42
|
+
Requires-Dist: starlette>=0.27.0; extra == 'web'
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# CapiscIO SDK (Python)
|
|
46
|
+
|
|
47
|
+
**Enforcement-First Security for A2A Agents.**
|
|
48
|
+
|
|
49
|
+
[](https://badge.fury.io/py/capiscio-sdk)
|
|
50
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
51
|
+
[](https://www.python.org/downloads/)
|
|
52
|
+
|
|
53
|
+
**CapiscIO** is the "Customs Officer" for your AI Agent. It provides military-grade Identity and Integrity enforcement for the [Agent-to-Agent (A2A) Protocol](https://github.com/google/A2A) with **zero configuration**.
|
|
54
|
+
|
|
55
|
+
## 🚀 The 60-Second Upgrade
|
|
56
|
+
|
|
57
|
+
Turn any FastAPI application into a Verified A2A Agent in 3 lines of code.
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from fastapi import FastAPI
|
|
61
|
+
from capiscio_sdk.simple_guard import SimpleGuard
|
|
62
|
+
from capiscio_sdk.integrations.fastapi import CapiscioMiddleware
|
|
63
|
+
|
|
64
|
+
# 1. Initialize Guard (Auto-generates keys in dev_mode)
|
|
65
|
+
guard = SimpleGuard(dev_mode=True)
|
|
66
|
+
|
|
67
|
+
app = FastAPI()
|
|
68
|
+
|
|
69
|
+
# 2. Add Enforcement Middleware
|
|
70
|
+
app.add_middleware(CapiscioMiddleware, guard=guard)
|
|
71
|
+
|
|
72
|
+
@app.post("/agent/task")
|
|
73
|
+
async def handle_task(request: Request):
|
|
74
|
+
# 🔒 Only reachable if Identity + Integrity are verified
|
|
75
|
+
caller = request.state.agent_id
|
|
76
|
+
return {"status": "accepted", "verified_caller": caller}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 🛡️ What You Get (Out of the Box)
|
|
80
|
+
|
|
81
|
+
1. **Zero-Config Identity**:
|
|
82
|
+
* Auto-generates **Ed25519** keys and `agent-card.json` on first run.
|
|
83
|
+
* No manual key management required for development.
|
|
84
|
+
|
|
85
|
+
2. **Payload Integrity**:
|
|
86
|
+
* Enforces **SHA-256 Body Hash (`bh`)** verification.
|
|
87
|
+
* Blocks tampered payloads instantly (returns `403 Forbidden`).
|
|
88
|
+
|
|
89
|
+
3. **Replay Protection**:
|
|
90
|
+
* Enforces strict **60-second** token expiration (`exp`).
|
|
91
|
+
* Prevents replay attacks and ensures freshness.
|
|
92
|
+
|
|
93
|
+
4. **Performance Telemetry**:
|
|
94
|
+
* Adds `<1ms` overhead.
|
|
95
|
+
* Includes `Server-Timing` headers for transparent monitoring.
|
|
96
|
+
|
|
97
|
+
## Installation
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install capiscio-sdk
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## How It Works
|
|
104
|
+
|
|
105
|
+
### 1. The Handshake
|
|
106
|
+
CapiscIO enforces the **A2A Trust Protocol**:
|
|
107
|
+
* **Sender**: Signs the request body (JWS + Body Hash).
|
|
108
|
+
* **Receiver**: Verifies the signature and re-hashes the body to ensure integrity.
|
|
109
|
+
|
|
110
|
+
### 2. The "Customs Officer"
|
|
111
|
+
The `SimpleGuard` acts as a local authority. It manages your agent's "Passport" (Agent Card) and verifies the "Visas" (Tokens) of incoming requests.
|
|
112
|
+
|
|
113
|
+
### 3. Telemetry
|
|
114
|
+
Every response includes a `Server-Timing` header showing exactly how fast the verification was:
|
|
115
|
+
```http
|
|
116
|
+
Server-Timing: capiscio-auth;dur=0.618;desc="CapiscIO Verification"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Documentation
|
|
120
|
+
|
|
121
|
+
- [Official Documentation](https://docs.capisc.io)
|
|
122
|
+
- [A2A Protocol Spec](https://github.com/google/A2A)
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
Apache License 2.0 - see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# CapiscIO SDK (Python)
|
|
2
|
+
|
|
3
|
+
**Enforcement-First Security for A2A Agents.**
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/py/capiscio-sdk)
|
|
6
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
7
|
+
[](https://www.python.org/downloads/)
|
|
8
|
+
|
|
9
|
+
**CapiscIO** is the "Customs Officer" for your AI Agent. It provides military-grade Identity and Integrity enforcement for the [Agent-to-Agent (A2A) Protocol](https://github.com/google/A2A) with **zero configuration**.
|
|
10
|
+
|
|
11
|
+
## 🚀 The 60-Second Upgrade
|
|
12
|
+
|
|
13
|
+
Turn any FastAPI application into a Verified A2A Agent in 3 lines of code.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from fastapi import FastAPI
|
|
17
|
+
from capiscio_sdk.simple_guard import SimpleGuard
|
|
18
|
+
from capiscio_sdk.integrations.fastapi import CapiscioMiddleware
|
|
19
|
+
|
|
20
|
+
# 1. Initialize Guard (Auto-generates keys in dev_mode)
|
|
21
|
+
guard = SimpleGuard(dev_mode=True)
|
|
22
|
+
|
|
23
|
+
app = FastAPI()
|
|
24
|
+
|
|
25
|
+
# 2. Add Enforcement Middleware
|
|
26
|
+
app.add_middleware(CapiscioMiddleware, guard=guard)
|
|
27
|
+
|
|
28
|
+
@app.post("/agent/task")
|
|
29
|
+
async def handle_task(request: Request):
|
|
30
|
+
# 🔒 Only reachable if Identity + Integrity are verified
|
|
31
|
+
caller = request.state.agent_id
|
|
32
|
+
return {"status": "accepted", "verified_caller": caller}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🛡️ What You Get (Out of the Box)
|
|
36
|
+
|
|
37
|
+
1. **Zero-Config Identity**:
|
|
38
|
+
* Auto-generates **Ed25519** keys and `agent-card.json` on first run.
|
|
39
|
+
* No manual key management required for development.
|
|
40
|
+
|
|
41
|
+
2. **Payload Integrity**:
|
|
42
|
+
* Enforces **SHA-256 Body Hash (`bh`)** verification.
|
|
43
|
+
* Blocks tampered payloads instantly (returns `403 Forbidden`).
|
|
44
|
+
|
|
45
|
+
3. **Replay Protection**:
|
|
46
|
+
* Enforces strict **60-second** token expiration (`exp`).
|
|
47
|
+
* Prevents replay attacks and ensures freshness.
|
|
48
|
+
|
|
49
|
+
4. **Performance Telemetry**:
|
|
50
|
+
* Adds `<1ms` overhead.
|
|
51
|
+
* Includes `Server-Timing` headers for transparent monitoring.
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install capiscio-sdk
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## How It Works
|
|
60
|
+
|
|
61
|
+
### 1. The Handshake
|
|
62
|
+
CapiscIO enforces the **A2A Trust Protocol**:
|
|
63
|
+
* **Sender**: Signs the request body (JWS + Body Hash).
|
|
64
|
+
* **Receiver**: Verifies the signature and re-hashes the body to ensure integrity.
|
|
65
|
+
|
|
66
|
+
### 2. The "Customs Officer"
|
|
67
|
+
The `SimpleGuard` acts as a local authority. It manages your agent's "Passport" (Agent Card) and verifies the "Visas" (Tokens) of incoming requests.
|
|
68
|
+
|
|
69
|
+
### 3. Telemetry
|
|
70
|
+
Every response includes a `Server-Timing` header showing exactly how fast the verification was:
|
|
71
|
+
```http
|
|
72
|
+
Server-Timing: capiscio-auth;dur=0.618;desc="CapiscIO Verification"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Documentation
|
|
76
|
+
|
|
77
|
+
- [Official Documentation](https://docs.capisc.io)
|
|
78
|
+
- [A2A Protocol Spec](https://github.com/google/A2A)
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
Apache License 2.0 - see [LICENSE](LICENSE) for details.
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Supported |
|
|
6
6
|
| ------- | ------------------ |
|
|
7
|
-
| 0.
|
|
7
|
+
| 0.2.x | :white_check_mark: |
|
|
8
|
+
| 0.1.x | :x: |
|
|
8
9
|
|
|
9
10
|
## Reporting a Vulnerability
|
|
10
11
|
|
|
@@ -32,7 +33,7 @@ Include:
|
|
|
32
33
|
|
|
33
34
|
## Security Best Practices
|
|
34
35
|
|
|
35
|
-
When using CapiscIO
|
|
36
|
+
When using the CapiscIO Python SDK:
|
|
36
37
|
|
|
37
38
|
1. **Keep dependencies updated**
|
|
38
39
|
```bash
|
|
@@ -12,6 +12,7 @@ __version__ = "0.2.0"
|
|
|
12
12
|
|
|
13
13
|
# Core exports
|
|
14
14
|
from .executor import CapiscioSecurityExecutor, secure, secure_agent
|
|
15
|
+
from .simple_guard import SimpleGuard
|
|
15
16
|
from .config import SecurityConfig, DownstreamConfig, UpstreamConfig
|
|
16
17
|
from .errors import (
|
|
17
18
|
CapiscioSecurityError,
|
|
@@ -25,6 +26,7 @@ from .types import ValidationResult, ValidationIssue, ValidationSeverity
|
|
|
25
26
|
__all__ = [
|
|
26
27
|
"__version__",
|
|
27
28
|
"CapiscioSecurityExecutor",
|
|
29
|
+
"SimpleGuard",
|
|
28
30
|
"secure",
|
|
29
31
|
"secure_agent",
|
|
30
32
|
"SecurityConfig",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Error types for Capiscio
|
|
1
|
+
"""Error types for Capiscio Python SDK."""
|
|
2
2
|
from typing import Optional, List, Dict, Any
|
|
3
3
|
from .types import ValidationResult
|
|
4
4
|
|
|
@@ -67,3 +67,13 @@ class CapiscioTimeoutError(CapiscioSecurityError):
|
|
|
67
67
|
"""Operation timed out."""
|
|
68
68
|
|
|
69
69
|
pass
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ConfigurationError(CapiscioSecurityError):
|
|
73
|
+
"""Missing keys or invalid paths (SimpleGuard)."""
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class VerificationError(CapiscioSecurityError):
|
|
78
|
+
"""Invalid signature, expired token, or untrusted key (SimpleGuard)."""
|
|
79
|
+
pass
|
|
@@ -138,6 +138,23 @@ class CapiscioSecurityExecutor:
|
|
|
138
138
|
# Cancellation just passes through - no security checks needed
|
|
139
139
|
await self.delegate.cancel(context, event_queue)
|
|
140
140
|
|
|
141
|
+
async def validate_agent_card(self, url: str) -> ValidationResult:
|
|
142
|
+
"""
|
|
143
|
+
Validate an agent card from a URL.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
url: URL to the agent card or agent root
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
ValidationResult with scores
|
|
150
|
+
"""
|
|
151
|
+
from .validators.agent_card import AgentCardValidator
|
|
152
|
+
validator = AgentCardValidator()
|
|
153
|
+
try:
|
|
154
|
+
return await validator.fetch_and_validate(url)
|
|
155
|
+
finally:
|
|
156
|
+
await validator.http_client.aclose()
|
|
157
|
+
|
|
141
158
|
def _validate_message(self, message: Dict[str, Any]) -> ValidationResult:
|
|
142
159
|
"""Validate message with caching."""
|
|
143
160
|
# Try cache first
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""FastAPI integration for Capiscio SimpleGuard."""
|
|
2
|
+
from typing import Callable, Awaitable, Any, Dict
|
|
3
|
+
try:
|
|
4
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
5
|
+
from starlette.requests import Request
|
|
6
|
+
from starlette.responses import JSONResponse, Response
|
|
7
|
+
from starlette.types import ASGIApp
|
|
8
|
+
except ImportError:
|
|
9
|
+
raise ImportError("FastAPI/Starlette is required for this integration. Install with 'pip install fastapi'.")
|
|
10
|
+
|
|
11
|
+
from ..simple_guard import SimpleGuard
|
|
12
|
+
from ..errors import VerificationError
|
|
13
|
+
import time
|
|
14
|
+
|
|
15
|
+
class CapiscioMiddleware(BaseHTTPMiddleware):
|
|
16
|
+
"""
|
|
17
|
+
Middleware to enforce A2A identity verification on incoming requests.
|
|
18
|
+
"""
|
|
19
|
+
def __init__(self, app: ASGIApp, guard: SimpleGuard) -> None:
|
|
20
|
+
super().__init__(app)
|
|
21
|
+
self.guard = guard
|
|
22
|
+
|
|
23
|
+
async def dispatch(
|
|
24
|
+
self,
|
|
25
|
+
request: Request,
|
|
26
|
+
call_next: Callable[[Request], Awaitable[Response]]
|
|
27
|
+
) -> Response:
|
|
28
|
+
# Allow health checks or public endpoints if needed
|
|
29
|
+
# For now, we assume everything under /agent/ needs protection
|
|
30
|
+
# But let's just check for the header.
|
|
31
|
+
|
|
32
|
+
if request.method == "OPTIONS":
|
|
33
|
+
return await call_next(request)
|
|
34
|
+
|
|
35
|
+
auth_header = request.headers.get("X-Capiscio-JWS")
|
|
36
|
+
|
|
37
|
+
# If no header, we might let it pass but mark as unverified?
|
|
38
|
+
# The mandate says: "Returns 401 (missing) or 403 (invalid)."
|
|
39
|
+
if not auth_header:
|
|
40
|
+
return JSONResponse(
|
|
41
|
+
{"error": "Missing X-Capiscio-JWS header. This endpoint is protected by CapiscIO."},
|
|
42
|
+
status_code=401
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
start_time = time.perf_counter()
|
|
46
|
+
try:
|
|
47
|
+
# Read the body for integrity check
|
|
48
|
+
body_bytes = await request.body()
|
|
49
|
+
|
|
50
|
+
# Verify the JWS with body
|
|
51
|
+
payload = self.guard.verify_inbound(auth_header, body=body_bytes)
|
|
52
|
+
|
|
53
|
+
# Reset the receive channel so downstream can read the body
|
|
54
|
+
async def receive() -> Dict[str, Any]:
|
|
55
|
+
return {"type": "http.request", "body": body_bytes, "more_body": False}
|
|
56
|
+
request._receive = receive
|
|
57
|
+
|
|
58
|
+
# Inject claims into request.state
|
|
59
|
+
request.state.agent = payload
|
|
60
|
+
request.state.agent_id = payload.get("iss")
|
|
61
|
+
|
|
62
|
+
except VerificationError as e:
|
|
63
|
+
return JSONResponse({"error": f"Access Denied: {str(e)}"}, status_code=403)
|
|
64
|
+
|
|
65
|
+
verification_duration = (time.perf_counter() - start_time) * 1000
|
|
66
|
+
|
|
67
|
+
response = await call_next(request)
|
|
68
|
+
|
|
69
|
+
# Add Server-Timing header (standard for performance metrics)
|
|
70
|
+
# Syntax: metric_name;dur=123.4;desc="Description"
|
|
71
|
+
response.headers["Server-Timing"] = f"capiscio-auth;dur={verification_duration:.3f};desc=\"CapiscIO Verification\""
|
|
72
|
+
|
|
73
|
+
return response
|