From d1f9f0e5c905da50f901a1055c246a868a3f8c25 Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Tue, 17 Mar 2026 22:26:30 -0400 Subject: [PATCH] fix: remove ghost APIs, fix stale versions, correct scoring model --- docs/concepts/scoring.md | 156 +++++++------------- docs/getting-started/cicd/2-action.md | 4 +- docs/getting-started/complete-workflow.md | 20 +-- docs/getting-started/index.md | 4 +- docs/getting-started/secure/2-sdk.md | 6 +- docs/getting-started/secure/5-production.md | 2 +- docs/getting-started/validate/1-intro.md | 2 +- docs/getting-started/validate/2-install.md | 6 +- docs/getting-started/validate/4-reports.md | 2 +- docs/how-to/integrations/langchain.md | 19 ++- docs/identity/index.md | 3 - docs/index.md | 16 +- docs/overview/index.md | 67 ++++----- docs/reference/cli/index.md | 40 +++-- docs/reference/sdk-python/badge.md | 30 ++-- docs/reference/server/api.md | 1 - docs/reference/server/index.md | 3 +- docs/reference/wrappers/node.md | 2 +- docs/reference/wrappers/python.md | 2 +- docs/trust/index.md | 62 ++++---- 20 files changed, 206 insertions(+), 241 deletions(-) diff --git a/docs/concepts/scoring.md b/docs/concepts/scoring.md index 0eba110..46ee11d 100644 --- a/docs/concepts/scoring.md +++ b/docs/concepts/scoring.md @@ -80,57 +80,50 @@ Each dimension has its own detailed breakdown, rating enum, and independent scor ### Scoring Breakdown -The compliance score uses a **60/20/15/5 weighting** across four categories: +The compliance score uses a **penalty-based model** starting at 100 points. Each violation deducts a fixed penalty: -#### Core Fields (60 points) +#### Core Fields -Checks for presence of all 9 required A2A v0.3.0 fields: +Checks for presence of all required A2A fields: -| Field | Points | Purpose | -|-------|--------|---------| -| `protocolVersion` | 6.67 | Declares A2A version (e.g., "0.3.0") | -| `name` | 6.67 | Agent display name | -| `description` | 6.67 | Agent description | -| `url` | 6.67 | Agent base URL | -| `version` | 6.67 | Agent semantic version | -| `capabilities` | 6.67 | Supported capabilities | -| `defaultInputModes` | 6.67 | Accepted MIME types | -| `defaultOutputModes` | 6.67 | Response MIME types | -| `skills` | 6.67 | Available skills array | +| Violation | Penalty | Example | +|-----------|---------|---------| +| Missing critical field | -20 | No `url` or `name` | +| Missing important field | -15 | No `protocolVersion` | +| Missing recommended field | -10 | No `capabilities` | +| Missing optional field | -5 | No `provider` | -**Penalty:** Each missing field costs 6.67 points. - -#### Skills Quality (20 points) +#### Skills Quality Evaluates the quality of the skills array: -- **Skills present** (10 points) - At least one skill defined -- **Required fields** (5 points) - All skills have `id`, `name`, `description` -- **Tags present** (5 points) - All skills have at least one tag - -**Penalties:** -- -2 points per skill missing required fields -- -1 point per skill without tags - -#### Format Compliance (15 points) +| Violation | Penalty | +|-----------|---------| +| No skills defined | -10 | +| Missing required skill fields (`id`, `name`, `description`) | -2 per skill | +| Skills without tags | -1 per skill | -Validates proper formatting across the agent card: +#### Format Compliance -- **Valid semver** (3 points) - `version` follows semantic versioning (e.g., `1.0.0`) -- **Valid protocol version** (3 points) - `protocolVersion` is `0.3.0` -- **Valid URL** (3 points) - `url` is a proper HTTPS URL -- **Valid transports** (3 points) - Transport protocols are `JSONRPC`, `GRPC`, or `HTTP+JSON` -- **Valid MIME types** (3 points) - Input/output modes are valid MIME types +Validates proper formatting: -**Special penalty:** -10 points for invalid MIME types (security risk) +| Violation | Penalty | +|-----------|---------| +| Invalid MIME types | -10 | +| Invalid URL format | -5 | +| Invalid semver | -5 | +| Invalid protocol version | -5 | +| Invalid transport | -2 | -#### Data Quality (5 points) +#### Data Quality -Checks for data integrity and security: +Checks for data integrity: -- **No duplicate skill IDs** (2 points) - Each skill has a unique identifier -- **Field lengths valid** (2 points) - Names, descriptions within reasonable limits -- **No SSRF risks** (1 point) - URLs don't point to internal/private networks +| Violation | Penalty | +|-----------|---------| +| Duplicate skill IDs | -2 | +| Field length violations | -2 | +| SSRF-risk URLs | -1 | ### Rating Levels @@ -152,64 +145,32 @@ Checks for data integrity and security: --- -## ๐Ÿ” Dimension 2: Trust (100 points + multiplier) +## ๐Ÿ” Dimension 2: Trust (100 points) **What it measures:** How trustworthy and secure is this agent? Can users verify its authenticity? -**Why it matters:** Trust is critical for adoption. Without signatures, users can't verify your agent's identity. Security claims without proof get penalized. - -### The Trust Confidence Multiplier ๐Ÿ”‘ - -**Revolutionary concept:** The presence and validity of cryptographic signatures affects ALL trust claims via a confidence multiplier: - -- **โœ… Valid JWS signature**: `1.0x` multiplier (full trust) -- **โšช No signature**: `0.6x` multiplier (unverified claims) -- **โŒ Invalid signature**: `0.4x` multiplier (active distrust) - -**Why this matters:** An agent claiming strong security without signatures gets reduced trust. This prevents "trust washing" where agents make security claims they can't prove. - -### Scoring Breakdown - -The trust score uses a **40/25/20/15 weighting** across four categories: - -#### Signatures (40 points + confidence key) +**Why it matters:** Trust is critical for adoption. Without signatures, users can't verify your agent's identity. -The foundation of trust: +### Scoring Model -- **Valid signature present** (30 points) - JWS signature verified -- **Multiple signatures** (+3 points) - Redundant verification -- **Comprehensive coverage** (+4 points) - Signature covers all critical fields -- **Recent signature** (+3 points) - Signed within last 90 days +Trust scoring uses a **discrete assignment model** based on the agent card's signature state: -**Penalties:** -- **Invalid signature** (-15 points + 0.4x multiplier) - Worse than no signature! -- **Expired signature** (-10 points + 0.6x multiplier) +| Signature State | Score | Description | +|----------------|-------|-------------| +| Valid signature from trusted issuer | **100** | Fully verified | +| Valid signature, no trusted issuers configured | **80** | Signature valid but no issuer list | +| Valid signature, issuer not in trusted list | **60** | Signature valid but issuer unknown | +| No signature | **20** | Unverified claims | +| Invalid signature | **0** | Active red flag | -#### Provider Information (25 points) +The signature state is the dominant factor. Additional agent card metadata (provider info, security schemes, documentation URLs) contributes to the validation report details but the trust score is primarily driven by signature validity. -Who is behind this agent? +### What Affects Trust -- **Organization specified** (10 points) - `provider.organization` present -- **Provider URL** (10 points) - `provider.url` present and uses HTTPS -- **URL reachable** (+5 bonus) - Provider website responds *(requires live testing)* - -#### Security Practices (20 points) - -How secure is the implementation? - -- **HTTPS-only endpoints** (10 points) - All URLs use HTTPS -- **Security schemes declared** (5 points) - `securitySchemes` defined in agent card -- **Strong authentication** (5 points) - OAuth2, OpenID Connect, or similar - -**Penalty:** -10 points for any HTTP URLs (major security risk) - -#### Documentation (15 points) - -Transparency and user support: - -- **Documentation URL** (5 points) - `documentationUrl` provided -- **Terms of Service** (5 points) - `termsOfServiceUrl` provided -- **Privacy Policy** (5 points) - `privacyPolicyUrl` provided +- **Cryptographic signatures** โ€” JWS-signed agent cards receive significantly higher scores +- **Trusted issuers** โ€” Configuring a trusted issuer list and matching against it yields the highest score +- **HTTPS-only endpoints** โ€” HTTP URLs are flagged as security risks +- **Provider information** โ€” Organization and URL presence improves trust indicators ### Rating Levels @@ -221,23 +182,12 @@ Transparency and user support: | 20-39 | **Low Trust** | Minimal security indicators | | <20 | **Untrusted** | Security red flags present | -### Example: Confidence Multiplier in Action - -**Scenario:** Agent card claims strong security (OAuth2, HTTPS-only, security schemes) = 40 raw points - -- **With valid signature**: `40 ร— 1.0 = 40 points` โœ… (Claims verified) -- **Without signature**: `40 ร— 0.6 = 24 points` โš ๏ธ (Unverified claims) -- **Invalid signature**: `40 ร— 0.4 = 16 points` โŒ (Active red flag) - -The same security features are worth **167% more** with a valid signature! - ### Common Issues -- โŒ No cryptographic signatures (reduces trust by 40%) -- โŒ Missing provider information -- โŒ No documentation or privacy policy URLs -- โŒ Using HTTP instead of HTTPS -- โŒ No security schemes declared +- โŒ No cryptographic signatures (score drops to 20) +- โŒ Invalid signature (score drops to 0) +- โŒ Using HTTP instead of HTTPS (flagged in validation report) +- โŒ Missing provider information (noted in trust details) --- @@ -494,7 +444,7 @@ The old `result.score` property still exists but returns `compliance.total` and Yes. If live testing is not performed, `availability.total` is `None` and `availability.rating` is `AvailabilityRating.NOT_TESTED`. ??? question "Why does my trust score seem low?" - If you have security features but no signature, the 0.6x confidence multiplier reduces your score by 40%. Add JWS signatures to achieve full trust potential. + Without a valid cryptographic signature, the trust score is capped at 20. Adding JWS signatures is the single most impactful change for trust scores. If your signature is valid but you see 60, your issuer may not be in the verifier's trusted issuer list. ??? question "What if I only care about one dimension?" You can ignore the others, but we recommend considering all three. An agent with perfect compliance but zero trust is still a security risk. diff --git a/docs/getting-started/cicd/2-action.md b/docs/getting-started/cicd/2-action.md index 9f0d1ed..ceeeeec 100644 --- a/docs/getting-started/cicd/2-action.md +++ b/docs/getting-started/cicd/2-action.md @@ -68,7 +68,7 @@ cat > agent-card.json << 'EOF' "description": "A sample A2A agent", "url": "https://example.com/agent", "version": "1.0.0", - "protocolVersion": "0.2.0", + "protocolVersion": "0.3.0", "provider": { "organization": "My Company" }, @@ -101,7 +101,7 @@ When the action runs, you'll see output like: ``` โœ… A2A AGENT VALIDATION PASSED Score: 75/100 -Version: 0.2.0 +Version: 0.3.0 Agent passed with warnings ISSUES FOUND: diff --git a/docs/getting-started/complete-workflow.md b/docs/getting-started/complete-workflow.md index a4ee4ee..0fc6007 100644 --- a/docs/getting-started/complete-workflow.md +++ b/docs/getting-started/complete-workflow.md @@ -1,8 +1,7 @@ # End-to-End Tutorial This tutorial walks through the complete CapiscIO workflow: from creating an A2A agent to deploying it with trust badge enforcement. @@ -31,7 +30,7 @@ pip install capiscio npm install -g capiscio # Verify installation -capiscio version +capiscio --version ``` --- @@ -184,7 +183,7 @@ curl -X POST http://localhost:8080/v1/api-keys \ Save the returned API key securely: ```bash -export CAPISCIO_API_KEY="cpsc_live_xxx" +export CAPISCIO_API_KEY="sk_live_xxx" ``` ### 3.4 Register Your Agent @@ -260,7 +259,7 @@ Badges expire quickly (5 minutes by default). Use the badge keeper daemon: ```bash capiscio badge keep \ - --ca-url "http://localhost:8080" \ + --ca "http://localhost:8080" \ --agent-id "$AGENT_ID" \ --api-key "$CAPISCIO_API_KEY" \ --domain "my-agent.example.com" \ @@ -364,17 +363,18 @@ For simpler deployments, use the SDK middleware instead of the gateway: ```python from fastapi import FastAPI -from capiscio_sdk import CapiscioMiddleware, SecurityConfig +from capiscio_sdk import SimpleGuard, SecurityConfig +from capiscio_sdk.integrations.fastapi import CapiscioMiddleware app = FastAPI() +guard = SimpleGuard() + # Add badge verification middleware app.add_middleware( CapiscioMiddleware, - config=SecurityConfig.production( - trusted_issuers=["https://registry.capisc.io"], - min_trust_level=2, - ), + guard=guard, + config=SecurityConfig.production(), ) @app.post("/task") diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index cf1f9d2..f7d94de 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -182,8 +182,8 @@ If you need more control, you can still do things step-by-step: # Generate keys only (no server registration) capiscio key gen --out-priv private.jwk --out-pub public.jwk -# Derive DID from existing key -capiscio key did --in public.jwk +# Show DID derived from generated key +capiscio key gen --show-did ``` See the [CLI Reference](../reference/cli/index.md) for all options. diff --git a/docs/getting-started/secure/2-sdk.md b/docs/getting-started/secure/2-sdk.md index 796e448..1932d64 100644 --- a/docs/getting-started/secure/2-sdk.md +++ b/docs/getting-started/secure/2-sdk.md @@ -23,7 +23,7 @@ python -c "import capiscio_sdk; print(capiscio_sdk.__version__)" Expected output: ``` -0.2.0 +2.5.0 ``` --- @@ -56,7 +56,7 @@ async def get_agent_card(): "description": "An A2A agent with CapiscIO security", "url": "http://localhost:8000", "version": "1.0.0", - "protocolVersion": "0.2.0", + "protocolVersion": "0.3.0", "provider": { "organization": "My Company" }, @@ -124,7 +124,7 @@ async def get_agent_card(): "description": "An A2A agent with CapiscIO security", "url": "http://localhost:8000", "version": "1.0.0", - "protocolVersion": "0.2.0", + "protocolVersion": "0.3.0", "provider": {"organization": "My Company"}, "capabilities": {"streaming": False, "pushNotifications": False}, "public_keys": [ diff --git a/docs/getting-started/secure/5-production.md b/docs/getting-started/secure/5-production.md index 7497f71..62cf07a 100644 --- a/docs/getting-started/secure/5-production.md +++ b/docs/getting-started/secure/5-production.md @@ -57,7 +57,7 @@ Create a proper `agent-card.json`: "description": "Production A2A agent for My Company", "url": "https://agent.mycompany.com", "version": "1.0.0", - "protocolVersion": "0.2.0", + "protocolVersion": "0.3.0", "provider": { "organization": "My Company Inc.", "url": "https://mycompany.com" diff --git a/docs/getting-started/validate/1-intro.md b/docs/getting-started/validate/1-intro.md index 38ba0d0..ff16aba 100644 --- a/docs/getting-started/validate/1-intro.md +++ b/docs/getting-started/validate/1-intro.md @@ -54,7 +54,7 @@ Here's a minimal example: { "name": "My Agent", "url": "https://example.com/agent", - "protocolVersion": "0.2.0" + "protocolVersion": "0.3.0" } ``` diff --git a/docs/getting-started/validate/2-install.md b/docs/getting-started/validate/2-install.md index faea39d..3d0c2a0 100644 --- a/docs/getting-started/validate/2-install.md +++ b/docs/getting-started/validate/2-install.md @@ -25,7 +25,7 @@ The CapiscIO CLI is available for Node.js and Python. Choose your preferred plat Expected output: ``` - capiscio/2.1.x (darwin-arm64) + capiscio/2.5.0 (darwin-arm64) ``` === "pip (Python)" @@ -42,7 +42,7 @@ The CapiscIO CLI is available for Node.js and Python. Choose your preferred plat Expected output: ``` - capiscio/2.1.x (darwin-arm64) + capiscio/2.5.0 (darwin-arm64) ``` === "Go (Direct)" @@ -142,7 +142,7 @@ cat > agent-card.json << 'EOF' "description": "A sample A2A agent for learning CapiscIO", "url": "https://example.com/agent", "version": "1.0.0", - "protocolVersion": "0.2.0", + "protocolVersion": "0.3.0", "provider": { "organization": "My Company" }, diff --git a/docs/getting-started/validate/4-reports.md b/docs/getting-started/validate/4-reports.md index b6dd76f..1241ccb 100644 --- a/docs/getting-started/validate/4-reports.md +++ b/docs/getting-started/validate/4-reports.md @@ -55,7 +55,7 @@ Our sample agent card scores 75/100. Let's improve it: "description": "A sample A2A agent for learning CapiscIO", "url": "https://example.com/agent", "version": "1.0.0", - "protocolVersion": "0.2.0", + "protocolVersion": "0.3.0", "provider": { "organization": "My Company", "url": "https://mycompany.com" diff --git a/docs/how-to/integrations/langchain.md b/docs/how-to/integrations/langchain.md index 2ed13e7..c74ccd7 100644 --- a/docs/how-to/integrations/langchain.md +++ b/docs/how-to/integrations/langchain.md @@ -63,8 +63,12 @@ guard = CapiscioGuard(mode="log") # Log only โ€” good for development | Mode | On missing/invalid badge | |------|--------------------------| | `block` | Raises `CapiscioTrustError` | -| `monitor` | Logs warning, adds `capiscio_warnings` to input, continues | -| `log` | Logs info, adds `capiscio_warnings` to input, continues | +| `monitor` | Logs warning, sets `verified=False` and `warnings` in `CapiscioRequestContext`, continues | +| `log` | Logs info, sets `verified=False` and `warnings` in `CapiscioRequestContext`, continues | + +In all modes the guard is a **pure passthrough** โ€” it returns the input unchanged. +Verification metadata is stored in the `CapiscioRequestContext` context variable, +not in the output. --- @@ -208,6 +212,17 @@ set_capiscio_context(CapiscioRequestContext( )) ``` +After guard execution, read the verification result from the same context: + +```python +from langchain_capiscio import get_capiscio_context + +ctx = get_capiscio_context() +ctx.verified # True if badge was valid +ctx.claims # Decoded badge claims dict +ctx.warnings # List of warning strings (monitor/log modes), or None +``` + --- ## Full Example: A2A Agent with Trust + Events diff --git a/docs/identity/index.md b/docs/identity/index.md index ae95105..ae90877 100644 --- a/docs/identity/index.md +++ b/docs/identity/index.md @@ -219,9 +219,6 @@ cat .capiscio/did.txt # Validate that identity is properly configured capiscio validate agent-card.json - -# Resolve any DID -capiscio identity resolve did:key:z6Mk... ``` --- diff --git a/docs/index.md b/docs/index.md index 6a32508..4354e86 100644 --- a/docs/index.md +++ b/docs/index.md @@ -137,16 +137,20 @@ Every feature works in **three commands or less**. === "Sign Requests" ```python - from capiscio_sdk import sign_request - signed = sign_request(request, badge) + from capiscio_sdk import SimpleGuard + + guard = SimpleGuard() + headers = guard.make_headers({"sub": agent_did}) ``` -=== "Protect APIs" +=== "Verify Badges" ```python - @guard.protect(min_trust_level=2) - async def handle_task(request): - pass # Only trusted agents reach here + from capiscio_sdk import verify_badge + + result = verify_badge(token, trusted_issuers=["https://registry.capisc.io"]) + if result.valid: + print(f"Trusted: {result.claims.subject}") ``` === "Guard MCP Tools" diff --git a/docs/overview/index.md b/docs/overview/index.md index c80a46e..505f79c 100644 --- a/docs/overview/index.md +++ b/docs/overview/index.md @@ -36,11 +36,11 @@ capiscio validate agent-card.json # โœ… Score: 95/100 (A+) # Generate cryptographic keys -capiscio key gen --did did:key +capiscio key gen --show-did # โœ… did:key:z6Mk... # Issue a trust badge -capiscio badge issue --level 0 --self-sign +capiscio badge issue --self-sign # โœ… Badge written to badge.jwt ``` @@ -60,25 +60,20 @@ capiscio badge issue --level 0 --self-sign **What it does:** Runtime security enforcement for your agent. ```python -from capiscio_sdk import SimpleGuard, sign_request, verify_request - -# 1. Protect your endpoints -guard = SimpleGuard(min_trust_level=2) - -@app.post("/task") -@guard.protect -async def handle_task(request): - # Only Level 2+ agents reach here - caller = guard.get_caller_identity(request) - return await process_task(request) - -# 2. Sign your outbound requests -signed = await sign_request(request, badge=my_badge) - -# 3. Verify incoming requests -result = await verify_request(request) -if result.trust_level >= 2: - allow_access() +from capiscio_sdk import SimpleGuard, verify_badge + +# 1. Sign outbound requests +guard = SimpleGuard() +headers = guard.make_headers({"sub": agent_did}) + +# 2. Verify incoming badges +result = verify_badge( + token, + trusted_issuers=["https://registry.capisc.io"], +) +if result.valid: + print(f"Verified: {result.claims.subject}") + print(f"Trust Level: {result.claims.trust_level.value}") ``` **Use cases:** @@ -130,8 +125,8 @@ Here's how trust flows through a typical interaction: |:----:|--------------|------| | **1** | Generate DID and cryptographic keypair | `capiscio key gen` | | **2** | Registry issues trust badge (Level 0-4) | `capiscio badge issue` | -| **3** | Sign outbound requests with badge | `sign_request()` | -| **4** | Verify signature and enforce trust level | `@guard.protect` | +| **3** | Sign outbound requests with badge | `guard.sign_outbound()` | +| **4** | Verify incoming badge and check trust level | `verify_badge()` | --- @@ -150,17 +145,19 @@ CapiscIO uses a 5-level trust hierarchy (RFC-002 ยง5): **The key insight:** Higher levels require more verification but enable more sensitive operations. ```python -# Development: Accept any cryptographic identity -@guard.protect(min_trust_level=0) -async def public_endpoint(): ... - -# Production: Require verified domain -@guard.protect(min_trust_level=2) -async def internal_api(): ... - -# Enterprise: Require verified organization -@guard.protect(min_trust_level=3) -async def financial_operation(): ... +from capiscio_sdk import verify_badge, TrustLevel + +# Verify a badge and check trust level +result = verify_badge(token, trusted_issuers=["https://registry.capisc.io"]) + +if result.valid: + level = int(result.claims.trust_level.value) + if level >= 2: + # Domain-verified agent โ€” allow production access + pass + elif level >= 3: + # Org-verified agent โ€” allow enterprise operations + pass ``` --- @@ -184,7 +181,7 @@ Depending on your use case: ```python from capiscio_sdk import SimpleGuard - guard = SimpleGuard(min_trust_level=2) + guard = SimpleGuard() ``` === "Protect MCP Tools" diff --git a/docs/reference/cli/index.md b/docs/reference/cli/index.md index 3cb3949..3462dad 100644 --- a/docs/reference/cli/index.md +++ b/docs/reference/cli/index.md @@ -1,9 +1,7 @@ # CLI Reference The `capiscio` CLI provides commands for validating Agent Cards, managing cryptographic keys, issuing trust badges, and running the security gateway. @@ -343,7 +341,7 @@ capiscio badge request [flags] | `--ca` | `string` | `https://registry.capisc.io` | Certificate Authority URL | | `--api-key` | `string` | *(none)* | API key for CA authentication | | `--out` | `string` | *(stdout)* | Output file path for the badge | -| `--ttl` | `duration` | `5m` | Requested badge TTL | +| `--ttl` | `int` | `300` | Requested badge TTL in seconds | | `--audience` | `string` | *(none)* | Audience restriction (comma-separated URLs) | ### Examples @@ -355,12 +353,12 @@ capiscio badge request \ --key ./private.jwk \ --api-key "$CAPISCIO_API_KEY" -# Request badge with specific TTL and audience +# Request badge with specific TTL (seconds) and audience capiscio badge request \ --did "did:web:example.com:agents:my-agent" \ --key ./private.jwk \ --api-key "$CAPISCIO_API_KEY" \ - --ttl 10m \ + --ttl 600 \ --audience "https://api.example.com" # Save badge to file @@ -409,10 +407,10 @@ capiscio badge dv create [flags] | Flag | Type | Description | |------|------|-------------| -| `--domain` | `string` | Domain to validate | -| `--method` | `string` | Validation method: `dns` or `http` | +| `--domain` | `string` | Domain to validate (required) | +| `--challenge-type` | `string` | Challenge type: `http-01` or `dns-01` (default: `http-01`) | +| `--key` | `string` | Path to private key file (JWK, required) | | `--ca` | `string` | CA URL (default: https://registry.capisc.io) | -| `--api-key` | `string` | API key for authentication | **Example:** @@ -420,8 +418,8 @@ capiscio badge dv create [flags] # Start DNS-based DV challenge capiscio badge dv create \ --domain example.com \ - --method dns \ - --api-key "$CAPISCIO_API_KEY" + --challenge-type dns-01 \ + --key ./private.jwk # Output: Challenge created # DNS TXT Record: _capiscio-challenge.example.com @@ -433,20 +431,20 @@ capiscio badge dv create \ Check the status of a pending DV challenge. ```bash -capiscio badge dv status [challenge-id] [flags] +capiscio badge dv status [flags] ``` **Flags:** | Flag | Type | Description | |------|------|-------------| +| `--order-id` | `string` | DV order ID (UUID, required) | | `--ca` | `string` | CA URL | -| `--api-key` | `string` | API key for authentication | **Example:** ```bash -capiscio badge dv status ch_abc123 --api-key "$CAPISCIO_API_KEY" +capiscio badge dv status --order-id ch_abc123 # Output: # Status: pending @@ -461,25 +459,23 @@ capiscio badge dv status ch_abc123 --api-key "$CAPISCIO_API_KEY" Complete the DV process after placing the challenge record. The CA will verify the challenge and issue a Level 2 badge. ```bash -capiscio badge dv finalize [challenge-id] [flags] +capiscio badge dv finalize [flags] ``` **Flags:** | Flag | Type | Description | |------|------|-------------| +| `--order-id` | `string` | DV order ID (UUID, required) | | `--ca` | `string` | CA URL | -| `--api-key` | `string` | API key for authentication | -| `--key` | `string` | Private key for badge signing | | `--out` | `string` | Output file for badge | **Example:** ```bash # After placing DNS TXT record, finalize the challenge -capiscio badge dv finalize ch_abc123 \ - --api-key "$CAPISCIO_API_KEY" \ - --key ./private.jwk \ +capiscio badge dv finalize \ + --order-id ch_abc123 \ --out ./dv-badge.jwt # Output: @@ -491,11 +487,11 @@ capiscio badge dv finalize ch_abc123 \ ### DV Workflow ``` -1. Create challenge: capiscio badge dv create --domain example.com --method dns +1. Create challenge: capiscio badge dv create --domain example.com --challenge-type dns-01 --key ./private.jwk 2. Add DNS TXT record: _capiscio-challenge.example.com โ†’ 3. Wait for DNS propagation (usually 1-5 minutes) -4. Check status: capiscio badge dv status -5. Finalize: capiscio badge dv finalize --key ./private.jwk +4. Check status: capiscio badge dv status --order-id +5. Finalize: capiscio badge dv finalize --order-id ``` --- diff --git a/docs/reference/sdk-python/badge.md b/docs/reference/sdk-python/badge.md index a75fa74..8bea629 100644 --- a/docs/reference/sdk-python/badge.md +++ b/docs/reference/sdk-python/badge.md @@ -52,6 +52,8 @@ def verify_badge( skip_revocation_check: bool = False, skip_agent_status_check: bool = False, public_key_jwk: Optional[str] = None, + fail_open: bool = False, + stale_threshold_seconds: int = 300, options: Optional[VerifyOptions] = None, ) -> VerifyResult ``` @@ -67,6 +69,8 @@ def verify_badge( | `skip_revocation_check` | `bool` | Skip revocation check (testing only) | | `skip_agent_status_check` | `bool` | Skip agent status check (testing only) | | `public_key_jwk` | `str` | Override public key for offline verification | +| `fail_open` | `bool` | If `True`, treat verification errors as valid (use with caution) | +| `stale_threshold_seconds` | `int` | Max staleness for cached revocation data (default: 300) | | `options` | `VerifyOptions` | Alternative to individual parameters | **Returns:** `VerifyResult` with validation status and claims. @@ -216,13 +220,9 @@ token = request_badge_sync( Parsed badge claims from a Trust Badge token. -!!! warning "SDK vs RFC-002 Implementation Gap" - The current SDK `badge.py` dataclass has limited fields. RFC-002 ยง4.3 specifies additional required claims (`ial`, `key`, `cnf`) that may be added in future SDK versions. - ```python @dataclass class BadgeClaims: - # Currently implemented in SDK v2.3.1: jti: str # Unique badge identifier (UUID) issuer: str # Badge issuer URL (CA) - maps to `iss` subject: str # Agent DID (did:key or did:web) - maps to `sub` @@ -230,18 +230,12 @@ class BadgeClaims: expires_at: datetime # When expires - maps to `exp` trust_level: TrustLevel # From `vc.credentialSubject.level` domain: str # Agent's verified domain - agent_name: str # Human-readable name - audience: List[str] # Intended audience URLs - maps to `aud` - - # RFC-002 ยง4.3 required (check for SDK updates): - # ial: str # Identity Assurance Level ("0" or "1") - # key: dict # Agent's public key (JWK) - # cnf: dict # Confirmation claim (required for IAL-1) + agent_name: str = "" # Human-readable name + audience: List[str] = [] # Intended audience URLs - maps to `aud` + ial: str = "0" # Identity Assurance Level ("0" or "1", per RFC-002) + raw_claims: Optional[dict] = None # Original decoded claims dict ``` -!!! note "RFC-002 ยง4.3 Required Claims" - Per RFC-002 ยง4.3, these claims are REQUIRED: `jti`, `iss`, `sub`, `iat`, `exp`, `ial`, `key`, `vc`. The `cnf` claim is required only for IAL-1 badges (proof of possession). - **Properties:** | Property | Type | Description | @@ -249,6 +243,8 @@ class BadgeClaims: | `agent_id` | `str` | Extracted agent ID from subject DID | | `is_expired` | `bool` | Whether badge has expired | | `is_not_yet_valid` | `bool` | Whether badge is not yet valid | +| `has_key_binding` | `bool` | Whether badge has a confirmation key (IAL-1) | +| `confirmation_key` | `Optional[dict]` | The confirmation key JWK, if present | **Methods:** @@ -289,6 +285,8 @@ class VerifyOptions: skip_revocation_check: bool = False skip_agent_status_check: bool = False public_key_jwk: Optional[str] = None + fail_open: bool = False + stale_threshold_seconds: int = 300 ``` **Example:** @@ -426,8 +424,8 @@ def require_trust_level(token: str, min_level: TrustLevel) -> bool: if not result.valid: return False - # TrustLevel enum values are integers 0-4, can compare directly - return result.claims.trust_level.value >= min_level.value + # TrustLevel enum values are strings "0"-"4", compare as integers + return int(result.claims.trust_level.value) >= int(min_level.value) # Usage if require_trust_level(token, TrustLevel.LEVEL_2): diff --git a/docs/reference/server/api.md b/docs/reference/server/api.md index a658538..629a5da 100644 --- a/docs/reference/server/api.md +++ b/docs/reference/server/api.md @@ -1,7 +1,6 @@ # API Reference diff --git a/docs/reference/server/index.md b/docs/reference/server/index.md index eab4564..c644d2a 100644 --- a/docs/reference/server/index.md +++ b/docs/reference/server/index.md @@ -1,7 +1,6 @@ # capiscio-server Reference @@ -11,7 +10,7 @@ The **capiscio-server** is a commercial backend API server that powers the Capis capiscio-server is a commercial product available to enterprise customers. [Contact Sales](mailto:sales@capisc.io) for licensing options. !!! info "Version" - Current version: **v0.1.0** (pre-release) + Current version: **v2.5.0** ## Overview diff --git a/docs/reference/wrappers/node.md b/docs/reference/wrappers/node.md index 872974f..92cb4ed 100644 --- a/docs/reference/wrappers/node.md +++ b/docs/reference/wrappers/node.md @@ -87,7 +87,7 @@ Add validation to your `package.json`: "validate:json": "capiscio validate agent-card.json --json" }, "devDependencies": { - "capiscio": "^2.3.1" + "capiscio": "^2.5.0" } } ``` diff --git a/docs/reference/wrappers/python.md b/docs/reference/wrappers/python.md index ab1ab80..be0937c 100644 --- a/docs/reference/wrappers/python.md +++ b/docs/reference/wrappers/python.md @@ -15,7 +15,7 @@ pip install capiscio Or with a specific version: ```bash -pip install capiscio==2.3.1 +pip install capiscio==2.5.0 ``` --- diff --git a/docs/trust/index.md b/docs/trust/index.md index 5849816..a2855f9 100644 --- a/docs/trust/index.md +++ b/docs/trust/index.md @@ -84,8 +84,11 @@ No registration needed. You immediately get a `did:key` identity at Trust Level ### Level 1: Registered (REG) ```bash -# Registered badges require account registration with CapiscIO Registry -capiscio badge request --did did:web:example.com:agents:myagent --key ./private.jwk --ca https://registry.capisc.io --api-key YOUR_API_KEY +# Registered badges require an API key and agent identity +capiscio badge request \ + --did did:web:example.com:agents:myagent \ + --key ./private.jwk \ + --api-key "$CAPISCIO_API_KEY" ``` For internal agents and early development. @@ -93,7 +96,11 @@ For internal agents and early development. ### Level 2: Domain Validated (DV) ```bash -capiscio badge request --level 2 --domain example.com +# Start DV challenge for your domain +capiscio badge dv create \ + --domain example.com \ + --challenge-type dns-01 \ + --key ./private.jwk ``` CapiscIO will ask you to: @@ -113,16 +120,7 @@ Saved to: ./capiscio_keys/badge.jwt ### Levels 3-4: Organization/Extended Validation -These require manual review. Start the process: - -```bash -capiscio badge request --level 3 -``` - -You'll be guided through: -- Business registration documents -- Domain ownership proof -- Legal entity verification +These require manual review. Contact CapiscIO to start the process. --- @@ -210,39 +208,51 @@ sequenceDiagram ### In Your Agent (Python SDK) ```python -from capiscio_sdk import SimpleGuard +from capiscio_sdk import verify_badge, TrustLevel -# Require at least Level 2 for production -guard = SimpleGuard( - min_trust_level=2, - badge_path="./capiscio_keys/badge.jwt" +# Verify incoming badge and check trust level +result = verify_badge( + token, + trusted_issuers=["https://registry.capisc.io"], ) -# Requests from Level 0-1 agents will be rejected +if result.valid: + level = int(result.claims.trust_level.value) + if level < 2: + # Reject agents below Level 2 for production + raise HTTPException(403, "Insufficient trust level") ``` ### In the CLI ```bash -# Validate and check trust level -capiscio validate agent-card.json --min-trust-level 2 - # Verify a specific badge capiscio badge verify ./badge.jwt + +# Verify and accept self-signed badges (development only) +capiscio badge verify ./badge.jwt --accept-self-signed ``` ### Trust Level Policies -Define different requirements for different operations: +Implement different requirements for different operations: ```python -guard = SimpleGuard( - trust_policies={ +from capiscio_sdk import verify_badge + +def check_access(token: str, operation: str) -> bool: + """Enforce trust level policies per operation.""" + result = verify_badge(token, trusted_issuers=["https://registry.capisc.io"]) + if not result.valid: + return False + + level = int(result.claims.trust_level.value) + policies = { "read": 0, # Anyone can read "write": 2, # Domain-validated for writes "admin": 3, # Org-validated for admin } -) + return level >= policies.get(operation, 4) ``` ---