-
Notifications
You must be signed in to change notification settings - Fork 0
feat: SimpleGuard Enforcement Strategy (v0.3.0) #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,182 +1,82 @@ | ||
| # CapiscIO SDK (Python) | ||
|
|
||
| **Runtime security middleware for A2A (Agent-to-Agent) protocol agents** | ||
| **Enforcement-First Security for A2A Agents.** | ||
|
|
||
| [](https://badge.fury.io/py/capiscio-sdk) | ||
| [](https://opensource.org/licenses/Apache-2.0) | ||
| [](https://www.python.org/downloads/) | ||
|
|
||
| ## What is CapiscIO SDK? | ||
| **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**. | ||
|
|
||
| CapiscIO SDK provides **always-on runtime protection** for agents using the [A2A (Agent-to-Agent) protocol](https://github.com/google/A2A). It wraps your agent executor to validate incoming requests, verify signatures, and protect against malicious actors—all without requiring peer cooperation. | ||
| ## 🚀 The 60-Second Upgrade | ||
|
|
||
| ### Key Features | ||
|
|
||
| - ✅ **Message validation** - Schema and protocol compliance checking | ||
| - ✅ **Signature verification** - JWS/JWKS cryptographic validation (RFC 7515) | ||
| - ✅ **Upstream protection** - Validate agents you call | ||
| - ✅ **Downstream protection** - Validate agents calling you | ||
| - ✅ **Rate limiting** - Token bucket algorithm | ||
| - ✅ **Caching** - Performance-optimized validation results | ||
| - ✅ **Three integration patterns** - Minimal, explicit, or decorator | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| pip install capiscio-sdk | ||
| ``` | ||
|
|
||
| ## Quick Start | ||
|
|
||
|
|
||
| ### Pattern 1: Minimal (One-liner with Preset) | ||
| Turn any FastAPI application into a Verified A2A Agent in 3 lines of code. | ||
|
|
||
| ```python | ||
| from capiscio_sdk import secure, SecurityConfig | ||
| from a2a.server.request_handlers import DefaultRequestHandler | ||
| from a2a.server.tasks import InMemoryTaskStore | ||
|
|
||
| # Wrap your agent with security (production defaults) | ||
| agent = secure(MyAgentExecutor(), SecurityConfig.production()) | ||
|
|
||
| # Use in A2A request handler | ||
| handler = DefaultRequestHandler( | ||
| agent_executor=agent, | ||
| task_store=InMemoryTaskStore() | ||
| ) | ||
|
|
||
| # Access validation results (three-dimensional scoring) | ||
| result = await agent.validate_agent_card(card_url) | ||
| print(result.compliance.total, result.trust.total, result.availability.total) | ||
| ``` | ||
| from fastapi import FastAPI | ||
| from capiscio_sdk.simple_guard import SimpleGuard | ||
| from capiscio_sdk.integrations.fastapi import CapiscioMiddleware | ||
|
|
||
| ### Pattern 2: Granular Control | ||
| # 1. Initialize Guard (Auto-generates keys in dev_mode) | ||
| guard = SimpleGuard(dev_mode=True) | ||
|
|
||
| ```python | ||
| from capiscio_sdk import CapiscIOSecurityExecutor, SecurityConfig | ||
|
|
||
| # Start with a preset, customize what matters to you | ||
| config = SecurityConfig.production() | ||
| config.downstream.rate_limit_requests_per_minute = 100 # Higher rate limit | ||
| config.downstream.require_signatures = True # Enforce signatures | ||
| config.upstream.test_endpoints = True # Test before calling | ||
| config.fail_mode = "monitor" # Log but don't block yet | ||
|
|
||
| secure_agent = CapiscIOSecurityExecutor( | ||
| delegate=MyAgentExecutor(), | ||
| config=config | ||
| ) | ||
| ``` | ||
| app = FastAPI() | ||
|
|
||
| ### Pattern 3: Environment-Driven (12-Factor App) | ||
| # 2. Add Enforcement Middleware | ||
| app.add_middleware(CapiscioMiddleware, guard=guard) | ||
|
|
||
| ```python | ||
| from capiscio_sdk import secure_agent, SecurityConfig | ||
| from a2a import AgentExecutor, RequestContext, EventQueue | ||
|
|
||
| @secure_agent(config=SecurityConfig.from_env()) | ||
| class MyAgentExecutor(AgentExecutor): | ||
| async def execute(self, context: RequestContext, event_queue: EventQueue): | ||
| # Your agent logic - config loaded from env vars | ||
| pass | ||
|
|
||
| # Already secured - use directly! | ||
| handler = DefaultRequestHandler(agent_executor=MyAgentExecutor()) | ||
| @app.post("/agent/task") | ||
| async def handle_task(request: Request): | ||
|
Comment on lines
+16
to
+29
|
||
| # 🔒 Only reachable if Identity + Integrity are verified | ||
| caller = request.state.agent_id | ||
| return {"status": "accepted", "verified_caller": caller} | ||
| ``` | ||
|
|
||
| **All 16 configuration options documented in the [Configuration Guide](https://docs.capisc.io/sdk-python/guides/configuration/).** | ||
|
|
||
| ## Why CapiscIO? | ||
|
|
||
| ### The Problem | ||
| ## 🛡️ What You Get (Out of the Box) | ||
|
|
||
| When building A2A agents, you face security risks from: | ||
| - **Malicious downstream agents** sending invalid/malicious requests | ||
| - **Broken upstream dependencies** with invalid agent cards | ||
| - **Protocol violations** causing runtime failures | ||
| - **Missing signatures** with no authenticity verification | ||
| 1. **Zero-Config Identity**: | ||
| * Auto-generates **Ed25519** keys and `agent-card.json` on first run. | ||
| * No manual key management required for development. | ||
|
|
||
| ### The Solution | ||
| 2. **Payload Integrity**: | ||
| * Enforces **SHA-256 Body Hash (`bh`)** verification. | ||
| * Blocks tampered payloads instantly (returns `403 Forbidden`). | ||
|
|
||
| CapiscIO wraps your agent executor and provides: | ||
| 3. **Replay Protection**: | ||
| * Enforces strict **60-second** token expiration (`exp`). | ||
| * Prevents replay attacks and ensures freshness. | ||
|
|
||
| 1. **Downstream Protection** - Validates all incoming requests | ||
| 2. **Upstream Protection** - Validates agents you call | ||
| 3. **Always-On** - Works without peer cooperation | ||
| 4. **Performance** - Caching and parallel validation | ||
| 5. **Three-Dimensional Scoring** - Compliance, trust, and availability insights | ||
| 4. **Performance Telemetry**: | ||
| * Adds `<1ms` overhead. | ||
| * Includes `Server-Timing` headers for transparent monitoring. | ||
|
|
||
| ## Configuration | ||
|
|
||
| ### Presets | ||
|
|
||
| ```python | ||
| # Development - Permissive, verbose logging | ||
| SecurityConfig.development() | ||
| ## Installation | ||
|
|
||
| # Production - Balanced (default) | ||
| SecurityConfig.production() | ||
| ```bash | ||
| pip install capiscio-sdk | ||
| ``` | ||
|
|
||
| # Strict - Maximum security | ||
| SecurityConfig.strict() | ||
| ## How It Works | ||
|
|
||
| # From environment variables | ||
| SecurityConfig.from_env() | ||
| ``` | ||
| ### 1. The Handshake | ||
| CapiscIO enforces the **A2A Trust Protocol**: | ||
| * **Sender**: Signs the request body (JWS + Body Hash). | ||
| * **Receiver**: Verifies the signature and re-hashes the body to ensure integrity. | ||
|
|
||
| ### Custom Configuration | ||
| ### 2. The "Customs Officer" | ||
| The `SimpleGuard` acts as a local authority. It manages your agent's "Passport" (Agent Card) and verifies the "Visas" (Tokens) of incoming requests. | ||
|
|
||
| ```python | ||
| from capiscio_sdk import SecurityConfig, DownstreamConfig, UpstreamConfig | ||
|
|
||
| config = SecurityConfig( | ||
| downstream=DownstreamConfig( | ||
| validate_schema=True, | ||
| verify_signatures=True, | ||
| require_signatures=False, | ||
| enable_rate_limiting=True, | ||
| rate_limit_requests_per_minute=100 | ||
| ), | ||
| upstream=UpstreamConfig( | ||
| validate_agent_cards=True, | ||
| verify_signatures=True, | ||
| cache_validation=True, | ||
| cache_timeout=3600 # seconds | ||
| ), | ||
| fail_mode="block", # "block" | "monitor" | "log" | ||
| timeout_ms=5000 | ||
| ) | ||
| ### 3. Telemetry | ||
| Every response includes a `Server-Timing` header showing exactly how fast the verification was: | ||
| ```http | ||
| Server-Timing: capiscio-auth;dur=0.618;desc="CapiscIO Verification" | ||
| ``` | ||
|
|
||
| ## Documentation | ||
|
|
||
| - [Quickstart Guide](docs/quickstart.md) | ||
| - [Configuration Reference](docs/configuration.md) | ||
| - [API Documentation](docs/api-reference.md) | ||
| - [Examples](examples/) | ||
|
|
||
| ## Roadmap | ||
|
|
||
| - **V1.0** (Q4 2025) - Core middleware (this package) | ||
| - **V2.0** (Q2 2026) - Extension protocol (validation feedback) | ||
| - **V3.0** (Q3 2026) - Platform integration (trust network) | ||
| - **V4.0** (Q4 2026) - Enterprise features (policies, audit logs) | ||
|
|
||
| ## Contributing | ||
|
|
||
| We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. | ||
| - [Official Documentation](https://docs.capisc.io) | ||
| - [A2A Protocol Spec](https://github.com/google/A2A) | ||
|
|
||
| ## License | ||
|
|
||
| Apache License 2.0 - see [LICENSE](LICENSE) for details. | ||
|
|
||
| ## About A2A | ||
|
|
||
| The [Agent-to-Agent (A2A) protocol](https://github.com/google/A2A) is an open standard for agent interoperability, supported by Google and 50+ partners including Salesforce, ServiceNow, SAP, Intuit, and more. CapiscIO provides the security layer for production A2A deployments. | ||
|
|
||
| ## Support | ||
|
|
||
| - **Issues:** [GitHub Issues](https://github.com/capiscio/capiscio-sdk-python/issues) | ||
| - **Discussions:** [GitHub Discussions](https://github.com/capiscio/capiscio-sdk-python/discussions) | ||
| - **Documentation:** [docs.capisc.io](https://docs.capisc.io) | ||
| - **Website:** [capisc.io](https://capisc.io) | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,7 +4,8 @@ | |||||||
|
|
||||||||
| | Version | Supported | | ||||||||
| | ------- | ------------------ | | ||||||||
| | 0.1.x | :white_check_mark: | | ||||||||
| | 0.2.x | :white_check_mark: | | ||||||||
|
||||||||
| | 0.2.x | :white_check_mark: | | |
| | 0.3.x | :white_check_mark: | | |
| | 0.2.x | :warning: (Deprecated, security fixes only) | |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,73 @@ | ||||||||||||||||||||||||||||||||||||||||||
| """FastAPI integration for Capiscio SimpleGuard.""" | ||||||||||||||||||||||||||||||||||||||||||
| from typing import Callable, Awaitable, Any, Dict | ||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||
| from starlette.middleware.base import BaseHTTPMiddleware | ||||||||||||||||||||||||||||||||||||||||||
| from starlette.requests import Request | ||||||||||||||||||||||||||||||||||||||||||
| from starlette.responses import JSONResponse, Response | ||||||||||||||||||||||||||||||||||||||||||
| from starlette.types import ASGIApp | ||||||||||||||||||||||||||||||||||||||||||
| except ImportError: | ||||||||||||||||||||||||||||||||||||||||||
| raise ImportError("FastAPI/Starlette is required for this integration. Install with 'pip install fastapi'.") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from ..simple_guard import SimpleGuard | ||||||||||||||||||||||||||||||||||||||||||
| from ..errors import VerificationError | ||||||||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| class CapiscioMiddleware(BaseHTTPMiddleware): | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
| Middleware to enforce A2A identity verification on incoming requests. | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, app: ASGIApp, guard: SimpleGuard) -> None: | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, app: ASGIApp, guard: SimpleGuard) -> None: | |
| def __init__(self, app: ASGIApp, guard: SimpleGuard) -> None: | |
| """ | |
| Initialize the CapiscioMiddleware. | |
| Args: | |
| app (ASGIApp): The ASGI application to wrap. | |
| guard (SimpleGuard): Instance of SimpleGuard used to verify incoming requests. | |
| This middleware enforces A2A identity verification on incoming requests using the provided guard. | |
| """ |
Copilot
AI
Nov 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The dispatch method lacks a docstring. This is the main method of the middleware and should document its behavior, including:
- What it does (verifies incoming requests)
- Parameters (
request,call_next) - Return value
- Exceptions or error responses (401 for missing auth, 403 for invalid auth)
- Side effects (modifies
request.state)
| ) -> Response: | |
| ) -> Response: | |
| """ | |
| Verifies incoming requests for A2A identity using Capiscio SimpleGuard. | |
| Parameters: | |
| request (Request): The incoming HTTP request. | |
| call_next (Callable[[Request], Awaitable[Response]]): The next middleware or endpoint handler. | |
| Returns: | |
| Response: The HTTP response, either an error (401/403) or the result of the downstream handler. | |
| Error Responses: | |
| - 401: If the X-Capiscio-JWS header is missing. | |
| - 403: If the authentication/verification fails. | |
| Side Effects: | |
| - Modifies request.state by injecting agent claims and agent_id if verification succeeds. | |
| - Resets the request body receive channel for downstream handlers. | |
| """ |
Copilot
AI
Nov 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation detected on lines 40-42. These lines have extra indentation (one extra space) compared to the surrounding code at the same level. They should align with the if statement on line 39.
| return JSONResponse( | |
| {"error": "Missing X-Capiscio-JWS header. This endpoint is protected by CapiscIO."}, | |
| status_code=401 | |
| ) | |
| return JSONResponse( | |
| {"error": "Missing X-Capiscio-JWS header. This endpoint is protected by CapiscIO."}, | |
| status_code=401 | |
| ) |
Copilot
AI
Nov 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accessing the private attribute request._receive is fragile and not part of the public API. This implementation detail may break with future Starlette/FastAPI versions. Consider using a more robust approach, such as storing the body in request.state for downstream handlers to access if needed, or using Starlette's built-in body caching mechanisms.
| # Reset the receive channel so downstream can read the body | |
| async def receive() -> Dict[str, Any]: | |
| return {"type": "http.request", "body": body_bytes, "more_body": False} | |
| request._receive = receive | |
| # Store the body in request.state for downstream access | |
| request.state.body_bytes = body_bytes | |
| # Downstream handlers can access the body via request.state.body_bytes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The CHANGELOG lists the release date as "2025-11-22" (November 2025), but the current date context indicates it's November 2025. This appears to be a future date used during development. Consider updating this to the actual release date when the PR is merged, or use "Unreleased" until an official release is made.