asap-protocol 2.5.5__tar.gz → 2.5.7__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.
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/CHANGELOG.md +113 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/PKG-INFO +10 -8
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/README.md +9 -7
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/pyproject.toml +15 -5
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/__init__.py +1 -1
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/capabilities.py +8 -3
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/identity.py +80 -33
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/registry/auto_registration.py +20 -1
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/testing/compliance.py +11 -2
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/agent_routes.py +23 -5
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/capability_routes.py +11 -1
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/rate_limit.py +9 -3
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/webhook.py +16 -1
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/.gitignore +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/LICENSE +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/agent.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/artifact.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/conversation.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/manifest.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/message.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/state_snapshot.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/entities/task.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/envelope.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/examples/shellclaw-jetson-capabilities.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/parts/data_part.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/parts/file_part.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/parts/resource_part.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/parts/template_part.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/parts/text_part.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/artifact_notify.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/mcp_resource_data.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/mcp_resource_fetch.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/mcp_tool_call.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/mcp_tool_result.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/message_send.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/state_query.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/state_restore.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/task_cancel.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/task_request.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/task_response.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/schemas/payloads/task_update.schema.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/auth_middleware.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/capability_map.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/config.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/errors.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/jwt_extractor.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/mcp/protected_server.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/openapi/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/openapi/approval.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/openapi/capability_mapper.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/openapi/factory.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/openapi/handler.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/adapters/openapi/spec_loader.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/_scope_parse.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/agent_jwt.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/agent_jwt_session.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/approval.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/introspection.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/jti_replay_cache.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/jwks.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/middleware.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/oauth2.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/oidc.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/scopes.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/self_auth.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/webauthn.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/auth/webauthn_store.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/_compat.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/audit_export.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/compliance_check.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/delegation.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/keys.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/manifest.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/repl.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/schemas.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/cli/trace.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/client/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/client/cache.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/client/http_client.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/client/market.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/client/revocation.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/client/trust.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/crypto/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/crypto/keys.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/crypto/models.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/crypto/signing.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/crypto/trust.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/crypto/trust_levels.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/discovery/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/discovery/dnssd.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/discovery/health.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/discovery/registry.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/discovery/validation.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/discovery/wellknown.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/audit.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/delegation.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/delegation_storage.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/hooks.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/metering.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/sla.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/sla_storage.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/economics/storage.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/errors.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/README.md +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/a2h_approval.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/agent_failover.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/auth_patterns.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/coordinator.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/echo_agent.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/error_recovery.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/long_running.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/mcp_client_demo.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/mcp_integration.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/multi_step_workflow.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/orchestration.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/rate_limiting.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/run_demo.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/secure_agent.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/secure_handler.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/state_migration.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/storage_backends.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/streaming_agent.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/streaming_response.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/v1_3_0_showcase.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/examples/v1_4_0_showcase.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/handlers/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/handlers/hitl.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/_base.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/a2h.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/crewai.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/langchain.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/llamaindex.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/openclaw.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/pydanticai.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/smolagents.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/integrations/vercel_ai.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/auth_middleware.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/capability_map.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/config.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/errors.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/jwt_extractor.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/auth/protected_server.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/client.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/protocol.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/serve.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/server.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/mcp/server_runner.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/base.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/constants.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/entities.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/enums.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/envelope.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/ids.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/parts.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/payloads.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/types.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/models/validators.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/dashboards/README.md +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/dashboards/asap-detailed.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/dashboards/asap-red.json +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/logging.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/metrics.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/trace_parser.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/trace_ui.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/observability/tracing.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/registry/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/registry/anti_spam.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/registry/bot_pr.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/registry/receipt_cache.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/schemas.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/machine.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/metering.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/snapshot.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/stores/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/stores/_sqlite_base.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/stores/_sync_bridge.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/stores/memory.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/state/stores/sqlite.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/testing/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/testing/asgi_factory.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/testing/assertions.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/testing/fixtures.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/testing/mocks.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/_auth_helpers.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/_request_handler.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/_state_deps.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/cache.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/challenge.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/circuit_breaker.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/client/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/client/_core.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/client/_discovery.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/client/_helpers.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/client/_send.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/compression.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/delegation_api.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/errors.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/escalation_routes.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/executors.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/handlers.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/jsonrpc.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/lambda_codec.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/middleware.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/mtls.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/routes/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/routes/audit.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/routes/health.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/routes/jsonrpc.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/routes/websocket.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/server.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/sla_api.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/usage_api.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/validators.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/websocket.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/_ack.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/_actions.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/_dispatch.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/_errors.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/_recv.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/client.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/codecs.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/pool.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/transport/ws/server.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/utils/__init__.py +0 -0
- {asap_protocol-2.5.5 → asap_protocol-2.5.7}/src/asap/utils/sanitization.py +0 -0
|
@@ -16,6 +16,119 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## [2.5.7] - 2026-10-11
|
|
20
|
+
|
|
21
|
+
**Quality & coverage patch** — correct batch HTTP rate-limit accounting,
|
|
22
|
+
transitive dependency overrides for CI security gates, `apps/web` audit-ci
|
|
23
|
+
enforcement, and consolidated regression tests on `main` via
|
|
24
|
+
[#395](https://github.com/asap-protocol/asap-protocol/pull/395)–[#399](https://github.com/asap-protocol/asap-protocol/pull/399).
|
|
25
|
+
This is **not** Formal Spec & Interop. npm `@asap-protocol/*` packages remain
|
|
26
|
+
at **2.4.1**. PyPI `asap-compliance` remains **1.3.0**.
|
|
27
|
+
Tag [`v2.5.7`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.7)
|
|
28
|
+
· PyPI `asap-protocol==2.5.7`.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Batch rate limits (#394)** — ``ASAPRateLimiter.check_n`` passes ``cost=n`` to
|
|
33
|
+
the moving-window strategy instead of ``n`` separate unit-cost ``hit`` calls,
|
|
34
|
+
so multi-item requests consume the correct quota.
|
|
35
|
+
|
|
36
|
+
### Security
|
|
37
|
+
|
|
38
|
+
- **Transitive Python deps** — ``uv`` override pins for advisories on optional
|
|
39
|
+
integration paths (``multidict``, ``pydantic-ai``, ``werkzeug``, ``fsspec``)
|
|
40
|
+
so CI ``pip-audit`` stays green ([#394](https://github.com/asap-protocol/asap-protocol/pull/394)
|
|
41
|
+
train).
|
|
42
|
+
- **`apps/web` npm audit** — CI uses ``audit-ci`` with ``audit-ci.jsonc``;
|
|
43
|
+
production overrides bump ``sharp`` and ``source-map-js``
|
|
44
|
+
([#394](https://github.com/asap-protocol/asap-protocol/pull/394) train).
|
|
45
|
+
|
|
46
|
+
### Quality
|
|
47
|
+
|
|
48
|
+
- **Transport & auth regression tests (#395, #397, #394)** — stale-key grants and
|
|
49
|
+
409 races, WebSocket token bursts and snapshot replace, streamed limits and
|
|
50
|
+
ceremony retry paths.
|
|
51
|
+
- **Registry & compliance harness (#389)** — endpoint rewrite, webhook DNS match,
|
|
52
|
+
compliance preflight edges.
|
|
53
|
+
- **Identity, economics, ingress (#398, #399)** — JWT middleware and metering
|
|
54
|
+
bridges, SSRF and ingress policy, adapter storage edges.
|
|
55
|
+
|
|
56
|
+
### Migration
|
|
57
|
+
|
|
58
|
+
- **v2.5.6 → v2.5.7**: See [migration guide](docs/migration.md#upgrading-from-v256-to-v257).
|
|
59
|
+
No wire-protocol or manifest schema breaking changes. Operators relying on
|
|
60
|
+
batch endpoints should expect slightly stricter rate limiting when ``check_n``
|
|
61
|
+
is used (intended behavior).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## [2.5.6] - 2026-10-01
|
|
66
|
+
|
|
67
|
+
**Security & quality patch** — Lite Registry IssueOps envelope and endpoint SSRF
|
|
68
|
+
hardening, compliance harness open-redirect SSRF, constrained capability execute,
|
|
69
|
+
Agent JWT rotate-key lifecycle race, dependency bumps, and consolidated regression
|
|
70
|
+
tests on `development` via [#354](https://github.com/asap-protocol/asap-protocol/pull/354)–[#379](https://github.com/asap-protocol/asap-protocol/pull/379).
|
|
71
|
+
This is **not** Formal Spec & Interop. npm `@asap-protocol/*` packages remain
|
|
72
|
+
at **2.4.1**. PyPI `asap-compliance` remains **1.3.0**.
|
|
73
|
+
Tag [`v2.5.6`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.6)
|
|
74
|
+
· PyPI `asap-protocol==2.5.6`.
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
|
|
78
|
+
- **Lite Registry IssueOps envelope (#354)** — `save_registry` again writes a
|
|
79
|
+
`LiteRegistry` object (`version`, `updated_at`, `agents`) so
|
|
80
|
+
`discover_from_registry` and Python validation keep working after
|
|
81
|
+
registration/removal. CI `validate_registry.py` and auto-merge eligibility
|
|
82
|
+
now reject a bare root array on production `registry.json` (fixture dry-runs
|
|
83
|
+
use `--allow-agents-array`).
|
|
84
|
+
|
|
85
|
+
- **Agent JWT rotate-key lifecycle (#372)** — lifecycle persistence uses
|
|
86
|
+
compare-and-set on `expected_public_key` so stale snapshots cannot undo
|
|
87
|
+
`POST /asap/agent/rotate-key`.
|
|
88
|
+
|
|
89
|
+
### Security
|
|
90
|
+
|
|
91
|
+
- **Capability execute omitted arguments (#373)** — ``CapabilityRegistry.check_grant``
|
|
92
|
+
and ``POST /asap/capability/execute`` treat a missing ``arguments`` object
|
|
93
|
+
as empty when the grant has constraints. Constrained fields stay required,
|
|
94
|
+
so omitting the object no longer skips the allowlist.
|
|
95
|
+
|
|
96
|
+
- **Compliance harness open-redirect SSRF (#370)** — ``run_compliance_harness_v2_from_url``
|
|
97
|
+
no longer sets ``follow_redirects=True``. Auto-registration
|
|
98
|
+
(``POST /registry/agents``) allowlists the harness base URL once, then the
|
|
99
|
+
harness preflight and checks use that client; a public agent could
|
|
100
|
+
``302`` to ``http://169.254.169.254/`` (or another blocked hop) and the
|
|
101
|
+
registry-bot would fetch it. Same fail-closed policy as
|
|
102
|
+
``fetch_manifest_at_url``. ``asap compliance-check`` against a hostile
|
|
103
|
+
URL is covered by the same client.
|
|
104
|
+
|
|
105
|
+
- **IssueOps registry endpoint SSRF (#371)** — `process_registration` rejects HTTP
|
|
106
|
+
and WebSocket endpoints that resolve to private, loopback, cloud-metadata, or
|
|
107
|
+
NAT64-embedded private hosts before writing `registry.json`. Manifest fetch was
|
|
108
|
+
already allowlisted; the advertised agent URLs were not, so a public signed
|
|
109
|
+
manifest could list `http://169.254.169.254/` and SDK `MarketClient.run`
|
|
110
|
+
would dial IMDS.
|
|
111
|
+
|
|
112
|
+
### Changed
|
|
113
|
+
|
|
114
|
+
- **GitHub Actions deps (#374)** — grouped bump for CI and release workflows.
|
|
115
|
+
- **`apps/web` npm deps (#375)** — grouped production and dev dependency updates.
|
|
116
|
+
|
|
117
|
+
### Quality
|
|
118
|
+
|
|
119
|
+
- **Consolidated regression tests (#376–#379)** — SSRF and web policy coverage,
|
|
120
|
+
transport binding/nonce/validation edges, streaming registration and SLA idle
|
|
121
|
+
windows, and auth lifecycle/session gates.
|
|
122
|
+
|
|
123
|
+
### Migration
|
|
124
|
+
|
|
125
|
+
- **v2.5.5 → v2.5.6**: See [migration guide](docs/migration.md#upgrading-from-v255-to-v256).
|
|
126
|
+
No wire-protocol or manifest schema breaking changes. Capability clients with
|
|
127
|
+
constrained grants must send an ``arguments`` object (may be empty). Registry
|
|
128
|
+
operators must keep `registry.json` as a `LiteRegistry` envelope.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
19
132
|
## [2.5.5] - 2026-09-11
|
|
20
133
|
|
|
21
134
|
**Security & quality patch** — OpenAPI path-parameter climb, Lite Registry
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: asap-protocol
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.7
|
|
4
4
|
Summary: Async Simple Agent Protocol - A streamlined protocol for agent-to-agent communication
|
|
5
5
|
Project-URL: Homepage, https://github.com/asap-protocol/asap-protocol
|
|
6
6
|
Project-URL: Documentation, https://asap-protocol.github.io/asap-protocol
|
|
@@ -99,9 +99,9 @@ Description-Content-Type: text/markdown
|
|
|
99
99
|
|
|
100
100
|
> A production-ready protocol for agent-to-agent communication and task coordination.
|
|
101
101
|
|
|
102
|
-
**Quick Info**: [`v2.5.
|
|
102
|
+
**Quick Info**: [`v2.5.7`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.7) · PyPI [`asap-protocol`](https://pypi.org/project/asap-protocol/) | `Apache 2.0` | `Python 3.13+` | [Documentation](docs/index.md) | [Changelog](CHANGELOG.md)
|
|
103
103
|
|
|
104
|
-
> 📦 **Install** — [`asap-protocol` **2.5.
|
|
104
|
+
> 📦 **Install** — [`asap-protocol` **2.5.7** on PyPI](https://pypi.org/project/asap-protocol/) (Python) · [`@asap-protocol/client` on npm](https://www.npmjs.com/package/@asap-protocol/client) (TypeScript)
|
|
105
105
|
|
|
106
106
|
🚀 **Live now** our [**agentic marketplace**](https://asap-protocol.com/) — browse agents, register yours, request verification.
|
|
107
107
|
|
|
@@ -156,16 +156,16 @@ ASAP meets agents where they run — optional Python extras, npm tool bridges, a
|
|
|
156
156
|
We recommend using [uv](https://github.com/astral-sh/uv) for dependency management:
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
|
-
uv add asap-protocol # latest on PyPI (currently 2.5.
|
|
159
|
+
uv add asap-protocol # latest on PyPI (currently 2.5.7)
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
Or with pip:
|
|
163
163
|
|
|
164
164
|
```bash
|
|
165
|
-
pip install asap-protocol==2.5.
|
|
165
|
+
pip install asap-protocol==2.5.7
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
**TypeScript** (npm, **`2.4.1`** — unchanged for v2.5.
|
|
168
|
+
**TypeScript** (npm, **`2.4.1`** — unchanged for v2.5.7; `@asap-protocol/mcp-auth` HTTP middleware still deferred):
|
|
169
169
|
|
|
170
170
|
- [`@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client) — [SDK docs](docs/sdks/typescript.md)
|
|
171
171
|
- [`@asap-protocol/mastra`](https://www.npmjs.com/package/@asap-protocol/mastra) — [docs](docs/integrations/mastra.md) · [demo](apps/example-mastra/README.md)
|
|
@@ -177,7 +177,7 @@ npm install @asap-protocol/mastra@2.4.1 @asap-protocol/client @mastra/core zod
|
|
|
177
177
|
npm install @asap-protocol/openai-agents@2.4.1 @asap-protocol/client @openai/agents zod
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
-
**Python v2.5.
|
|
180
|
+
**Python v2.5.7** (quality & coverage patch) is **shipped** — see [Migration (v2.5.6 → v2.5.7)](docs/migration.md#upgrading-from-v256-to-v257). Dist Loop starters remain: [Build for agents](docs/guides/build-for-agents.md) · [starters](examples/starters/README.md).
|
|
181
181
|
|
|
182
182
|
## Quick Start
|
|
183
183
|
|
|
@@ -265,6 +265,8 @@ High-level only — see **[Changelog](https://github.com/asap-protocol/asap-prot
|
|
|
265
265
|
|
|
266
266
|
| Version | What shipped |
|
|
267
267
|
| :-- | :-- |
|
|
268
|
+
| **v2.5.7** | **Quality & coverage patch** — **[GitHub Release `v2.5.7`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.7)** · batch rate-limit `check_n` fix, CI security gate deps + `apps/web` audit-ci, consolidated regression tests ([#395](https://github.com/asap-protocol/asap-protocol/pull/395)–[#399](https://github.com/asap-protocol/asap-protocol/pull/399)). npm `@asap-protocol/*` remain **2.4.1**. See [CHANGELOG](CHANGELOG.md#257---2026-10-11) and [Migration (v2.5.6 → v2.5.7)](docs/migration.md#upgrading-from-v256-to-v257) |
|
|
269
|
+
| **v2.5.6** | **Security & quality patch** — **[GitHub Release `v2.5.6`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.6)** · Lite Registry IssueOps envelope + endpoint SSRF, compliance open-redirect SSRF, constrained capability execute, rotate-key lifecycle race, deps + regression tests. npm `@asap-protocol/*` remain **2.4.1**. See [CHANGELOG](CHANGELOG.md#256---2026-10-01) and [Migration (v2.5.5 → v2.5.6)](docs/migration.md#upgrading-from-v255-to-v256) |
|
|
268
270
|
| **v2.5.5** | **Security & quality patch** — **[GitHub Release `v2.5.5`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.5)** · OpenAPI path-param climb, registry URN overwrite guard, marketplace SSRF DNS pin, capability-replace consent, fail-closed reactivate, Agent JWT persist/revoke races. npm `@asap-protocol/*` remain **2.4.1**. See [CHANGELOG](CHANGELOG.md#255---2026-09-11) and [Migration (v2.5.4 → v2.5.5)](docs/migration.md#upgrading-from-v254-to-v255) |
|
|
269
271
|
| **v2.5.4** | **Distribution Loop** — **[GitHub Release `v2.5.4`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.4)** · thin starters (`examples/starters/`), [Build for agents](docs/guides/build-for-agents.md), homepage agent-first CTAs, telemetry ops (no public metrics UI). See [CHANGELOG](CHANGELOG.md#254---2026-07-18), [PRD](product/prd/prd-v2.5.4-distribution-loop.md), and [Migration (v2.5.3 → v2.5.4)](docs/migration.md#upgrading-from-v253-to-v254) |
|
|
270
272
|
| **v2.5.3** | **Adapter Lab II** — **[GitHub Release `v2.5.3`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.3)** · workflow OpenAPI connectors + security guide, experimental MAF / NeMo guides, JSON-safe `-32602`, MCP example client DX. See [CHANGELOG](CHANGELOG.md#253---2026-07-14), [PRD](product/prd/prd-v2.5.3-adapter-lab-ii.md), and [Migration (v2.5.2 → v2.5.3)](docs/migration.md#upgrading-from-v252-to-v253) |
|
|
@@ -289,7 +291,7 @@ High-level only — see **[Changelog](https://github.com/asap-protocol/asap-prot
|
|
|
289
291
|
|
|
290
292
|
The [agentic marketplace](https://asap-protocol.com/) and Lite Registry are live. The **v2.5.x train** focuses on interop and adoption:
|
|
291
293
|
|
|
292
|
-
- **Formal Spec & Interop** — RFC, introspection, privacy (PRD [prd-v2.5.5-formal-spec-interop.md](product/prd/prd-v2.5.5-formal-spec-interop.md); library **2.5.
|
|
294
|
+
- **Formal Spec & Interop** — RFC, introspection, privacy (PRD [prd-v2.5.5-formal-spec-interop.md](product/prd/prd-v2.5.5-formal-spec-interop.md); library **2.5.7** is the quality/coverage patch above)
|
|
293
295
|
- **`@asap-protocol/mcp-auth`** (npm) — HTTP/SSE MCP middleware
|
|
294
296
|
- **Formal spec track** — introspection, privacy, cross-protocol interop on the path to v3.0 economy
|
|
295
297
|
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
> A production-ready protocol for agent-to-agent communication and task coordination.
|
|
9
9
|
|
|
10
|
-
**Quick Info**: [`v2.5.
|
|
10
|
+
**Quick Info**: [`v2.5.7`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.7) · PyPI [`asap-protocol`](https://pypi.org/project/asap-protocol/) | `Apache 2.0` | `Python 3.13+` | [Documentation](docs/index.md) | [Changelog](CHANGELOG.md)
|
|
11
11
|
|
|
12
|
-
> 📦 **Install** — [`asap-protocol` **2.5.
|
|
12
|
+
> 📦 **Install** — [`asap-protocol` **2.5.7** on PyPI](https://pypi.org/project/asap-protocol/) (Python) · [`@asap-protocol/client` on npm](https://www.npmjs.com/package/@asap-protocol/client) (TypeScript)
|
|
13
13
|
|
|
14
14
|
🚀 **Live now** our [**agentic marketplace**](https://asap-protocol.com/) — browse agents, register yours, request verification.
|
|
15
15
|
|
|
@@ -64,16 +64,16 @@ ASAP meets agents where they run — optional Python extras, npm tool bridges, a
|
|
|
64
64
|
We recommend using [uv](https://github.com/astral-sh/uv) for dependency management:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
-
uv add asap-protocol # latest on PyPI (currently 2.5.
|
|
67
|
+
uv add asap-protocol # latest on PyPI (currently 2.5.7)
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
Or with pip:
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
|
-
pip install asap-protocol==2.5.
|
|
73
|
+
pip install asap-protocol==2.5.7
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
**TypeScript** (npm, **`2.4.1`** — unchanged for v2.5.
|
|
76
|
+
**TypeScript** (npm, **`2.4.1`** — unchanged for v2.5.7; `@asap-protocol/mcp-auth` HTTP middleware still deferred):
|
|
77
77
|
|
|
78
78
|
- [`@asap-protocol/client`](https://www.npmjs.com/package/@asap-protocol/client) — [SDK docs](docs/sdks/typescript.md)
|
|
79
79
|
- [`@asap-protocol/mastra`](https://www.npmjs.com/package/@asap-protocol/mastra) — [docs](docs/integrations/mastra.md) · [demo](apps/example-mastra/README.md)
|
|
@@ -85,7 +85,7 @@ npm install @asap-protocol/mastra@2.4.1 @asap-protocol/client @mastra/core zod
|
|
|
85
85
|
npm install @asap-protocol/openai-agents@2.4.1 @asap-protocol/client @openai/agents zod
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
**Python v2.5.
|
|
88
|
+
**Python v2.5.7** (quality & coverage patch) is **shipped** — see [Migration (v2.5.6 → v2.5.7)](docs/migration.md#upgrading-from-v256-to-v257). Dist Loop starters remain: [Build for agents](docs/guides/build-for-agents.md) · [starters](examples/starters/README.md).
|
|
89
89
|
|
|
90
90
|
## Quick Start
|
|
91
91
|
|
|
@@ -173,6 +173,8 @@ High-level only — see **[Changelog](https://github.com/asap-protocol/asap-prot
|
|
|
173
173
|
|
|
174
174
|
| Version | What shipped |
|
|
175
175
|
| :-- | :-- |
|
|
176
|
+
| **v2.5.7** | **Quality & coverage patch** — **[GitHub Release `v2.5.7`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.7)** · batch rate-limit `check_n` fix, CI security gate deps + `apps/web` audit-ci, consolidated regression tests ([#395](https://github.com/asap-protocol/asap-protocol/pull/395)–[#399](https://github.com/asap-protocol/asap-protocol/pull/399)). npm `@asap-protocol/*` remain **2.4.1**. See [CHANGELOG](CHANGELOG.md#257---2026-10-11) and [Migration (v2.5.6 → v2.5.7)](docs/migration.md#upgrading-from-v256-to-v257) |
|
|
177
|
+
| **v2.5.6** | **Security & quality patch** — **[GitHub Release `v2.5.6`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.6)** · Lite Registry IssueOps envelope + endpoint SSRF, compliance open-redirect SSRF, constrained capability execute, rotate-key lifecycle race, deps + regression tests. npm `@asap-protocol/*` remain **2.4.1**. See [CHANGELOG](CHANGELOG.md#256---2026-10-01) and [Migration (v2.5.5 → v2.5.6)](docs/migration.md#upgrading-from-v255-to-v256) |
|
|
176
178
|
| **v2.5.5** | **Security & quality patch** — **[GitHub Release `v2.5.5`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.5)** · OpenAPI path-param climb, registry URN overwrite guard, marketplace SSRF DNS pin, capability-replace consent, fail-closed reactivate, Agent JWT persist/revoke races. npm `@asap-protocol/*` remain **2.4.1**. See [CHANGELOG](CHANGELOG.md#255---2026-09-11) and [Migration (v2.5.4 → v2.5.5)](docs/migration.md#upgrading-from-v254-to-v255) |
|
|
177
179
|
| **v2.5.4** | **Distribution Loop** — **[GitHub Release `v2.5.4`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.4)** · thin starters (`examples/starters/`), [Build for agents](docs/guides/build-for-agents.md), homepage agent-first CTAs, telemetry ops (no public metrics UI). See [CHANGELOG](CHANGELOG.md#254---2026-07-18), [PRD](product/prd/prd-v2.5.4-distribution-loop.md), and [Migration (v2.5.3 → v2.5.4)](docs/migration.md#upgrading-from-v253-to-v254) |
|
|
178
180
|
| **v2.5.3** | **Adapter Lab II** — **[GitHub Release `v2.5.3`](https://github.com/asap-protocol/asap-protocol/releases/tag/v2.5.3)** · workflow OpenAPI connectors + security guide, experimental MAF / NeMo guides, JSON-safe `-32602`, MCP example client DX. See [CHANGELOG](CHANGELOG.md#253---2026-07-14), [PRD](product/prd/prd-v2.5.3-adapter-lab-ii.md), and [Migration (v2.5.2 → v2.5.3)](docs/migration.md#upgrading-from-v252-to-v253) |
|
|
@@ -197,7 +199,7 @@ High-level only — see **[Changelog](https://github.com/asap-protocol/asap-prot
|
|
|
197
199
|
|
|
198
200
|
The [agentic marketplace](https://asap-protocol.com/) and Lite Registry are live. The **v2.5.x train** focuses on interop and adoption:
|
|
199
201
|
|
|
200
|
-
- **Formal Spec & Interop** — RFC, introspection, privacy (PRD [prd-v2.5.5-formal-spec-interop.md](product/prd/prd-v2.5.5-formal-spec-interop.md); library **2.5.
|
|
202
|
+
- **Formal Spec & Interop** — RFC, introspection, privacy (PRD [prd-v2.5.5-formal-spec-interop.md](product/prd/prd-v2.5.5-formal-spec-interop.md); library **2.5.7** is the quality/coverage patch above)
|
|
201
203
|
- **`@asap-protocol/mcp-auth`** (npm) — HTTP/SSE MCP middleware
|
|
202
204
|
- **Formal spec track** — introspection, privacy, cross-protocol interop on the path to v3.0 economy
|
|
203
205
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "asap-protocol"
|
|
3
|
-
version = "2.5.
|
|
3
|
+
version = "2.5.7"
|
|
4
4
|
description = "Async Simple Agent Protocol - A streamlined protocol for agent-to-agent communication"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "ASAP Protocol Contributors"}
|
|
@@ -122,7 +122,8 @@ Issues = "https://github.com/asap-protocol/asap-protocol/issues"
|
|
|
122
122
|
"PyPI" = "https://pypi.org/project/asap-protocol/"
|
|
123
123
|
|
|
124
124
|
# Override transitive dependencies for security fixes:
|
|
125
|
-
# - pyjwt>=2.
|
|
125
|
+
# - pyjwt>=2.14.0 for PYSEC-2026-4140–4152 (prior: CVE-2026-32597 baseline at 2.12.0)
|
|
126
|
+
# - anyio>=4.14.2 for PYSEC-2026-4024 / PYSEC-2026-4025
|
|
126
127
|
# - aiohttp>=3.14.3,<4 for PYSEC-2026-3545/3546/3547 (prior: CVE-2026-34993 / CVE-2026-47265 at >=3.14.0)
|
|
127
128
|
# - zeroconf>=0.149.5 for CVE-2026-47180/47183/47184 ([dns-sd] extra)
|
|
128
129
|
# - pyasn1>=0.6.4 for CVE-2026-30922 / CVE-2026-59885 / CVE-2026-59886 / PYSEC-2026-3455/3456/3457 (transitive, auth/JWT stack)
|
|
@@ -137,7 +138,7 @@ Issues = "https://github.com/asap-protocol/asap-protocol/issues"
|
|
|
137
138
|
# - pygments>=2.20.0 for CVE-2026-4539
|
|
138
139
|
# - langsmith>=0.8.18 for GHSA-f4xh-w4cj-qxq8 (prior: CVE-2026-45134 at >=0.8.0)
|
|
139
140
|
# - langchain-core>=1.3.3 for CVE-2026-44843
|
|
140
|
-
# - urllib3>=2.
|
|
141
|
+
# - urllib3>=2.8.0 for PYSEC-2026-4175–4177 (prior: CVE-2026-44431 / CVE-2026-44432 at >=2.7.0)
|
|
141
142
|
# - pip>=26.2 for PYSEC-2026-3721 (prior: PYSEC-2026-196 / CVE-2026-6357 at >=26.1.2)
|
|
142
143
|
# - h2>=4.4.1 for PYSEC-2026-3628 (HTTP/2 HPACK; transitive via httpx[http2])
|
|
143
144
|
# - python-dotenv>=1.2.2 for CVE-2026-28684 (transitive, e.g. pydantic-settings / uvicorn stacks)
|
|
@@ -152,10 +153,15 @@ Issues = "https://github.com/asap-protocol/asap-protocol/issues"
|
|
|
152
153
|
# - setuptools>=83.0.0 for PYSEC-2026-3447 (transitive build/tooling path)
|
|
153
154
|
# - pyopenssl>=26.4.0 for cryptography 50 ABI (webauthn extra; GEN_EMAIL / PKCS7)
|
|
154
155
|
# - mkdocs-material>=9.7.7 for PYSEC-2026-3864 / CVE-2026-73295 (DOM XSS in search.suggest)
|
|
156
|
+
# - multidict>=6.9.1 for CVE-2026-104874
|
|
157
|
+
# - pydantic-ai>=1.107.7,<2 for CVE-2026-107287–107291
|
|
158
|
+
# - werkzeug>=3.1.9 for CVE-2026-102598
|
|
159
|
+
# - fsspec>=2026.6.0 for CVE-2026-104851
|
|
155
160
|
[tool.uv]
|
|
156
161
|
override-dependencies = [
|
|
157
162
|
"aiohttp>=3.14.3,<4",
|
|
158
|
-
"
|
|
163
|
+
"anyio>=4.14.2",
|
|
164
|
+
"pyjwt>=2.14.0,<3",
|
|
159
165
|
"pyasn1>=0.6.4",
|
|
160
166
|
"tinytag>=2.2.1",
|
|
161
167
|
"cryptography>=50.0.0,<51",
|
|
@@ -168,7 +174,7 @@ override-dependencies = [
|
|
|
168
174
|
"pygments>=2.20.0",
|
|
169
175
|
"langsmith>=0.8.18",
|
|
170
176
|
"langchain-core>=1.3.3",
|
|
171
|
-
"urllib3>=2.
|
|
177
|
+
"urllib3>=2.8.0",
|
|
172
178
|
"pip>=26.2",
|
|
173
179
|
"zeroconf>=0.149.5",
|
|
174
180
|
"python-dotenv>=1.2.2",
|
|
@@ -184,6 +190,10 @@ override-dependencies = [
|
|
|
184
190
|
"h2>=4.4.1",
|
|
185
191
|
"pyopenssl>=26.4.0",
|
|
186
192
|
"mkdocs-material>=9.7.7",
|
|
193
|
+
"multidict>=6.9.1",
|
|
194
|
+
"pydantic-ai>=1.107.7,<2",
|
|
195
|
+
"werkzeug>=3.1.9",
|
|
196
|
+
"fsspec>=2026.6.0",
|
|
187
197
|
]
|
|
188
198
|
|
|
189
199
|
[project.scripts]
|
|
@@ -228,7 +228,12 @@ class CapabilityRegistry:
|
|
|
228
228
|
capability: str,
|
|
229
229
|
arguments: dict[str, Any] | None = None,
|
|
230
230
|
) -> GrantCheckResult:
|
|
231
|
-
"""Return whether *agent_id* may invoke *capability* with *arguments*.
|
|
231
|
+
"""Return whether *agent_id* may invoke *capability* with *arguments*.
|
|
232
|
+
|
|
233
|
+
Constrained grants treat omitted ``arguments`` as ``{}``. Each
|
|
234
|
+
constrained field is required, so a caller cannot skip the allowlist
|
|
235
|
+
by leaving the object out of the execute body.
|
|
236
|
+
"""
|
|
232
237
|
agent_grants = self._grants.get(agent_id, {})
|
|
233
238
|
g = agent_grants.get(capability)
|
|
234
239
|
|
|
@@ -241,8 +246,8 @@ class CapabilityRegistry:
|
|
|
241
246
|
if g.expires_at is not None and datetime.now(timezone.utc) > g.expires_at:
|
|
242
247
|
return GrantCheckResult(allowed=False, violations=[], grant=g)
|
|
243
248
|
|
|
244
|
-
if g.constraints
|
|
245
|
-
violations = validate_constraints(g.constraints, arguments)
|
|
249
|
+
if g.constraints:
|
|
250
|
+
violations = validate_constraints(g.constraints, arguments or {})
|
|
246
251
|
if violations:
|
|
247
252
|
return GrantCheckResult(allowed=False, violations=violations, grant=g)
|
|
248
253
|
|
|
@@ -36,6 +36,17 @@ class RevokedAgentOverwriteError(ValueError):
|
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
class StaleAgentPublicKeyError(ValueError):
|
|
40
|
+
"""Raised when ``save`` would persist against a rotated public key.
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
>>> raise StaleAgentPublicKeyError(
|
|
44
|
+
... "refusing to overwrite agent 'a1': stored public_key thumbprint "
|
|
45
|
+
... "'abc' != expected 'def'"
|
|
46
|
+
... )
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
39
50
|
def validate_okp_public_key(value: dict[str, Any]) -> dict[str, Any]:
|
|
40
51
|
"""Validate that the dict represents a valid OKP (Ed25519) public JWK."""
|
|
41
52
|
try:
|
|
@@ -103,24 +114,23 @@ class AgentSession(ASAPBaseModel):
|
|
|
103
114
|
class AgentStore(Protocol):
|
|
104
115
|
"""Persistence layer for agent sessions under a host."""
|
|
105
116
|
|
|
106
|
-
async def save(
|
|
117
|
+
async def save(
|
|
118
|
+
self,
|
|
119
|
+
agent: AgentSession,
|
|
120
|
+
*,
|
|
121
|
+
expected_public_key: dict[str, Any] | None = None,
|
|
122
|
+
) -> None:
|
|
107
123
|
"""Persist or replace an agent session.
|
|
108
124
|
|
|
109
125
|
Must refuse replacing a ``revoked`` row with a non-revoked snapshot by
|
|
110
|
-
raising :class:`RevokedAgentOverwriteError`.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
-- reject when rowcount == 0 and the stored status is revoked
|
|
116
|
-
|
|
117
|
-
Do **not** implement this as get → await I/O → overwrite: that TOCTOU
|
|
118
|
-
can resurrect a revoked agent (#324 / LIFE-005). Same class as
|
|
119
|
-
``NonceStore.check_and_mark``. Persisting an already-revoked snapshot
|
|
120
|
-
remains allowed.
|
|
126
|
+
raising :class:`RevokedAgentOverwriteError`. When *expected_public_key*
|
|
127
|
+
is set, raise :class:`StaleAgentPublicKeyError` if the stored JWK
|
|
128
|
+
thumbprint no longer matches (concurrent rotate-key). Check and write
|
|
129
|
+
must be one compare-and-set; do not get → await I/O → overwrite
|
|
130
|
+
(#324 / LIFE-005). Persisting an already-revoked snapshot is allowed.
|
|
121
131
|
|
|
122
132
|
Example:
|
|
123
|
-
>>> await store.save(session)
|
|
133
|
+
>>> await store.save(session, expected_public_key=session.public_key)
|
|
124
134
|
"""
|
|
125
135
|
...
|
|
126
136
|
|
|
@@ -256,23 +266,48 @@ class InMemoryHostStore:
|
|
|
256
266
|
await self._agent_store.revoke_by_host(host_id)
|
|
257
267
|
|
|
258
268
|
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
def _cas_public_key_row(
|
|
270
|
+
existing: AgentSession,
|
|
271
|
+
agent: AgentSession,
|
|
272
|
+
expected_public_key: dict[str, Any],
|
|
273
|
+
) -> AgentSession:
|
|
274
|
+
"""Return the row to persist, or raise if the stored JWK already rotated."""
|
|
275
|
+
try:
|
|
276
|
+
stored_tp = jwk_thumbprint_sha256(existing.public_key)
|
|
277
|
+
incoming_tp = jwk_thumbprint_sha256(agent.public_key)
|
|
278
|
+
expected_tp = jwk_thumbprint_sha256(expected_public_key)
|
|
279
|
+
except (KeyError, TypeError, ValueError) as exc:
|
|
280
|
+
msg = f"cannot compare public_key thumbprints for agent {agent.agent_id!r}: {exc}"
|
|
281
|
+
raise StaleAgentPublicKeyError(msg) from exc
|
|
282
|
+
if stored_tp != expected_tp:
|
|
283
|
+
msg = (
|
|
284
|
+
f"refusing to overwrite agent {agent.agent_id!r}: stored public_key "
|
|
285
|
+
f"thumbprint {stored_tp!r} != expected {expected_tp!r}"
|
|
286
|
+
)
|
|
287
|
+
raise StaleAgentPublicKeyError(msg)
|
|
288
|
+
if incoming_tp != expected_tp:
|
|
289
|
+
return existing.model_copy(update={"public_key": agent.public_key})
|
|
290
|
+
return agent
|
|
261
291
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
"""
|
|
292
|
+
|
|
293
|
+
class InMemoryAgentStore:
|
|
294
|
+
"""In-memory AgentStore; save refuses revoked→live and stale-key overwrites."""
|
|
265
295
|
|
|
266
296
|
def __init__(self) -> None:
|
|
267
297
|
self._agents: dict[str, AgentSession] = {}
|
|
268
298
|
|
|
269
|
-
async def save(
|
|
270
|
-
|
|
299
|
+
async def save(
|
|
300
|
+
self,
|
|
301
|
+
agent: AgentSession,
|
|
302
|
+
*,
|
|
303
|
+
expected_public_key: dict[str, Any] | None = None,
|
|
304
|
+
) -> None:
|
|
305
|
+
"""Persist a session. Refuse revoked→live; CAS public_key when expected.
|
|
271
306
|
|
|
272
307
|
Example:
|
|
273
|
-
>>> await store.save(session)
|
|
308
|
+
>>> await store.save(session, expected_public_key=session.public_key)
|
|
274
309
|
"""
|
|
275
|
-
# No await between the revoked check and the write (LIFE-005 / #324).
|
|
310
|
+
# No await between the revoked/key check and the write (LIFE-005 / #324).
|
|
276
311
|
existing = self._agents.get(agent.agent_id)
|
|
277
312
|
if existing is not None and existing.status == "revoked" and agent.status != "revoked":
|
|
278
313
|
msg = (
|
|
@@ -280,6 +315,8 @@ class InMemoryAgentStore:
|
|
|
280
315
|
f"with status {agent.status!r}"
|
|
281
316
|
)
|
|
282
317
|
raise RevokedAgentOverwriteError(msg)
|
|
318
|
+
if expected_public_key is not None and existing is not None:
|
|
319
|
+
agent = _cas_public_key_row(existing, agent, expected_public_key)
|
|
283
320
|
self._agents[agent.agent_id] = agent
|
|
284
321
|
|
|
285
322
|
async def touch_if_current(
|
|
@@ -330,23 +367,33 @@ class InMemoryAgentStore:
|
|
|
330
367
|
await self.revoke(aid)
|
|
331
368
|
|
|
332
369
|
|
|
333
|
-
async def save_agent_unless_revoked(
|
|
370
|
+
async def save_agent_unless_revoked(
|
|
371
|
+
agent_store: AgentStore,
|
|
372
|
+
agent: AgentSession,
|
|
373
|
+
*,
|
|
374
|
+
expected_public_key: dict[str, Any] | None = None,
|
|
375
|
+
) -> None:
|
|
334
376
|
"""Persist *agent* through :meth:`AgentStore.save` (refuse-revoked contract).
|
|
335
377
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
``NonceStore.check_and_mark``).
|
|
378
|
+
Pass *expected_public_key* so a concurrent rotate-key is not reverted by a
|
|
379
|
+
stale lifecycle snapshot. Atomic refuse-revoked/key CAS belongs inside
|
|
380
|
+
``save``.
|
|
340
381
|
|
|
341
382
|
Example:
|
|
342
|
-
>>> await save_agent_unless_revoked(
|
|
383
|
+
>>> await save_agent_unless_revoked(
|
|
384
|
+
... store, rotated_session, expected_public_key=old_jwk
|
|
385
|
+
... )
|
|
343
386
|
"""
|
|
344
|
-
|
|
345
|
-
|
|
387
|
+
if expected_public_key is None:
|
|
388
|
+
await agent_store.save(agent)
|
|
389
|
+
return
|
|
390
|
+
try:
|
|
391
|
+
await agent_store.save(agent, expected_public_key=expected_public_key)
|
|
392
|
+
except TypeError as exc:
|
|
393
|
+
if "expected_public_key" not in str(exc):
|
|
394
|
+
raise
|
|
395
|
+
await agent_store.save(agent)
|
|
346
396
|
|
|
347
|
-
# ---------------------------------------------------------------------------
|
|
348
|
-
# Agent session lifecycle (session TTL, max lifetime, absolute lifetime)
|
|
349
|
-
# ---------------------------------------------------------------------------
|
|
350
397
|
|
|
351
398
|
ExpiryStatus = Literal["active", "expired", "revoked"]
|
|
352
399
|
|
|
@@ -27,7 +27,7 @@ from asap.registry.anti_spam import TRUST_LEVEL_SELF_SIGNED, auto_register_verif
|
|
|
27
27
|
from asap.registry.bot_pr import BotPRResult, BotPRSettings, open_registry_pull_request
|
|
28
28
|
from asap.testing.compliance import ComplianceReport, run_compliance_harness_v2_from_url
|
|
29
29
|
from asap.transport.rate_limit import RateLimitExceeded
|
|
30
|
-
from asap.transport.webhook import validate_callback_url
|
|
30
|
+
from asap.transport.webhook import validate_agent_endpoint_url, validate_callback_url
|
|
31
31
|
|
|
32
32
|
logger = logging.getLogger(__name__)
|
|
33
33
|
|
|
@@ -136,6 +136,21 @@ async def fetch_manifest_at_url(client: httpx.AsyncClient, manifest_url: str) ->
|
|
|
136
136
|
raise ManifestValidationError(str(exc), field="signature") from exc
|
|
137
137
|
|
|
138
138
|
|
|
139
|
+
async def _validate_persisted_registry_endpoints(manifest: Manifest) -> None:
|
|
140
|
+
"""Reject private/metadata hosts on every URL stored in ``registry.json``."""
|
|
141
|
+
for label, url in (
|
|
142
|
+
("HTTP", manifest.endpoints.asap),
|
|
143
|
+
*([("WebSocket", manifest.endpoints.events)] if manifest.endpoints.events else []),
|
|
144
|
+
):
|
|
145
|
+
try:
|
|
146
|
+
await validate_agent_endpoint_url(url, require_https=True)
|
|
147
|
+
except WebhookURLValidationError as exc:
|
|
148
|
+
raise HTTPException(
|
|
149
|
+
status_code=400,
|
|
150
|
+
detail=f"{label} endpoint blocked: {exc}",
|
|
151
|
+
) from exc
|
|
152
|
+
|
|
153
|
+
|
|
139
154
|
def _build_registry_entry(manifest: Manifest, manifest_url: str) -> RegistryEntry:
|
|
140
155
|
endpoints: dict[str, str] = {
|
|
141
156
|
"http": manifest.endpoints.asap,
|
|
@@ -243,6 +258,8 @@ def create_auto_registration_router(config: AutoRegistrationConfig | None = None
|
|
|
243
258
|
detail=f"Harness base URL blocked: {exc}",
|
|
244
259
|
) from exc
|
|
245
260
|
|
|
261
|
+
# Harness HTTP client does not follow redirects. This allowlist is
|
|
262
|
+
# one-shot; following Location would skip SSRF checks (IMDS/link-local).
|
|
246
263
|
report = await _run_harness(harness_url)
|
|
247
264
|
if report.score < 1.0:
|
|
248
265
|
failed = [c.model_dump(mode="json") for c in report.checks if not c.passed]
|
|
@@ -255,6 +272,8 @@ def create_auto_registration_router(config: AutoRegistrationConfig | None = None
|
|
|
255
272
|
).model_dump(mode="json"),
|
|
256
273
|
)
|
|
257
274
|
|
|
275
|
+
await _validate_persisted_registry_endpoints(manifest)
|
|
276
|
+
|
|
258
277
|
entry = _build_registry_entry(manifest, manifest_url_str)
|
|
259
278
|
|
|
260
279
|
try:
|
|
@@ -419,6 +419,13 @@ async def run_compliance_harness_v2_from_url(
|
|
|
419
419
|
Raises:
|
|
420
420
|
httpx.ConnectError: If the TCP connection cannot be established (preflight ``GET /``).
|
|
421
421
|
httpx.TimeoutException: If the preflight request times out.
|
|
422
|
+
|
|
423
|
+
Note:
|
|
424
|
+
Redirects are not followed. Auto-registration validates the harness
|
|
425
|
+
URL once, then calls this runner; following ``Location`` would let a
|
|
426
|
+
public agent bounce the registry-bot (or ``asap compliance-check``)
|
|
427
|
+
onto link-local/IMDS targets after that check. Same policy as
|
|
428
|
+
``fetch_manifest_at_url``.
|
|
422
429
|
"""
|
|
423
430
|
normalized = base_url.rstrip("/")
|
|
424
431
|
timeout_cfg = Timeout(request_timeout)
|
|
@@ -426,14 +433,16 @@ async def run_compliance_harness_v2_from_url(
|
|
|
426
433
|
base_url=normalized,
|
|
427
434
|
timeout=timeout_cfg,
|
|
428
435
|
headers=default_headers,
|
|
429
|
-
follow_redirects=
|
|
436
|
+
follow_redirects=False,
|
|
430
437
|
) as client:
|
|
431
438
|
# Fail fast on unreachable hosts so callers (e.g. CLI) can treat as transport error,
|
|
432
439
|
# instead of a synthetic all-failed report from per-check exception handlers.
|
|
433
440
|
try:
|
|
434
|
-
await client.get("/")
|
|
441
|
+
preflight = await client.get("/")
|
|
435
442
|
except httpx.ConnectError:
|
|
436
443
|
raise
|
|
437
444
|
except httpx.TimeoutException:
|
|
438
445
|
raise
|
|
446
|
+
if 300 <= preflight.status_code < 400:
|
|
447
|
+
preflight.raise_for_status()
|
|
439
448
|
return await run_compliance_harness_with_client(client, categories=categories)
|