From 04cb60195fc33061bee492423141eb6835dfb794 Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Thu, 5 Feb 2026 23:18:54 +0200 Subject: [PATCH 1/8] feat: add CapiscIO.connect() for Let's Encrypt-style setup - Add connect.py with CapiscIO.connect() and CapiscIO.from_env() - Add events.py with EventEmitter for agent observability - AgentIdentity dataclass with emit(), get_badge(), status() methods - Auto-discover agent, generate keys via gRPC, register DID - Update quickstart docs with new one-liner setup - Regenerate proto bindings with Init RPC support --- capiscio_sdk/__init__.py | 13 + capiscio_sdk/_rpc/client.py | 49 +++ .../_rpc/gen/capiscio/v1/badge_pb2.py | 4 +- .../_rpc/gen/capiscio/v1/badge_pb2_grpc.py | 2 +- .../_rpc/gen/capiscio/v1/common_pb2.py | 4 +- capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2.py | 4 +- .../_rpc/gen/capiscio/v1/did_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2.py | 4 +- .../_rpc/gen/capiscio/v1/mcp_pb2_grpc.py | 2 +- .../_rpc/gen/capiscio/v1/registry_pb2.py | 8 +- .../_rpc/gen/capiscio/v1/registry_pb2_grpc.py | 2 +- .../_rpc/gen/capiscio/v1/revocation_pb2.py | 6 +- .../gen/capiscio/v1/revocation_pb2_grpc.py | 2 +- .../_rpc/gen/capiscio/v1/scoring_pb2.py | 6 +- .../_rpc/gen/capiscio/v1/scoring_pb2_grpc.py | 2 +- .../_rpc/gen/capiscio/v1/simpleguard_pb2.py | 26 +- .../gen/capiscio/v1/simpleguard_pb2_grpc.py | 47 ++- .../_rpc/gen/capiscio/v1/trust_pb2.py | 6 +- .../_rpc/gen/capiscio/v1/trust_pb2_grpc.py | 2 +- capiscio_sdk/connect.py | 394 ++++++++++++++++++ capiscio_sdk/events.py | 319 ++++++++++++++ docs/getting-started/quickstart.md | 60 ++- pyproject.toml | 1 + 23 files changed, 922 insertions(+), 43 deletions(-) create mode 100644 capiscio_sdk/connect.py create mode 100644 capiscio_sdk/events.py diff --git a/capiscio_sdk/__init__.py b/capiscio_sdk/__init__.py index 583cf93..98f628c 100644 --- a/capiscio_sdk/__init__.py +++ b/capiscio_sdk/__init__.py @@ -60,6 +60,12 @@ DVGrant, ) +# Easy connect API ("Let's Encrypt" style) +from .connect import CapiscIO, connect, from_env, AgentIdentity + +# Event emission +from .events import EventEmitter + __all__ = [ "__version__", # Security middleware @@ -106,5 +112,12 @@ "finalize_dv_order", "DVOrder", "DVGrant", + # Easy Connect API ("Let's Encrypt" style) + "CapiscIO", + "connect", + "from_env", + "AgentIdentity", + # Event emission + "EventEmitter", ] diff --git a/capiscio_sdk/_rpc/client.py b/capiscio_sdk/_rpc/client.py index d182616..b3b3f11 100644 --- a/capiscio_sdk/_rpc/client.py +++ b/capiscio_sdk/_rpc/client.py @@ -1275,6 +1275,55 @@ def get_key_info(self, key_id: str) -> tuple[Optional[dict], Optional[str]]: "has_private_key": response.has_private_key, "public_key_pem": response.public_key_pem, }, None + + def init( + self, + api_key: str = "", + agent_id: str = "", + server_url: str = "", + output_dir: str = "", + force: bool = False, + metadata: Optional[dict] = None, + ) -> tuple[Optional[dict], Optional[str]]: + """Initialize agent identity - Let's Encrypt style one-call setup. + + Generates key pair, derives DID, registers with server, and creates agent card. + All cryptographic operations are performed by capiscio-core Go library. + + Args: + api_key: API key for server authentication + agent_id: Agent UUID to register DID for + server_url: CapiscIO server URL (default: https://api.capisc.io) + output_dir: Directory for generated files (default: .capiscio) + force: Overwrite existing files + metadata: Additional metadata for agent card + + Returns: + Tuple of (init_result, error_message) + init_result contains: did, agent_id, private_key_path, public_key_path, + agent_card_path, agent_card_json, registered + """ + request = simpleguard_pb2.InitRequest( + api_key=api_key, + agent_id=agent_id, + server_url=server_url, + output_dir=output_dir, + force=force, + metadata=metadata or {}, + ) + response = self._stub.Init(request) + error = response.error_message if response.error_message else None + if error: + return None, error + return { + "did": response.did, + "agent_id": response.agent_id, + "private_key_path": response.private_key_path, + "public_key_path": response.public_key_path, + "agent_card_path": response.agent_card_path, + "agent_card_json": response.agent_card_json, + "registered": response.registered, + }, None class MCPClient: diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2.py index 13cad94..cbbf19a 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/badge.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/badge.proto' ) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py index d04f070..8610bcb 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 +from capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 class BadgeServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/common_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/common_pb2.py index 6d3d214..61b479d 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/common_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/common_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/common.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/common.proto' ) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2.py index 20c5b59..6fc0c5d 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/did.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/did.proto' ) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py index 0862baf..2bc43ee 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import did_pb2 as capiscio_dot_v1_dot_did__pb2 +from capiscio.v1 import did_pb2 as capiscio_dot_v1_dot_did__pb2 class DIDServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2.py index 1cb5121..43a2684 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/mcp.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/mcp.proto' ) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py index cac02f6..7e4e828 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import mcp_pb2 as capiscio_dot_v1_dot_mcp__pb2 +from capiscio.v1 import mcp_pb2 as capiscio_dot_v1_dot_mcp__pb2 class MCPServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py index 609109e..6f18fab 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/registry.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/registry.proto' ) @@ -22,8 +22,8 @@ _sym_db = _symbol_database.Default() -from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 -from capiscio_sdk._rpc.gen.capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 +from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x63\x61piscio/v1/registry.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\x1a\x17\x63\x61piscio/v1/badge.proto\"\xc1\x04\n\x0fRegisteredAgent\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12&\n\x0f\x61gent_card_json\x18\x04 \x01(\tR\ragentCardJson\x12\x30\n\x06status\x18\x05 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x06status\x12.\n\x05\x62\x61\x64ge\x18\x06 \x01(\x0b\x32\x18.capiscio.v1.BadgeClaimsR\x05\x62\x61\x64ge\x12+\n\x06rating\x18\x07 \x01(\x0e\x32\x13.capiscio.v1.RatingR\x06rating\x12;\n\rregistered_at\x18\x08 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x0cregisteredAt\x12\x35\n\nupdated_at\x18\t \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tupdatedAt\x12\"\n\x0c\x63\x61pabilities\x18\n \x03(\tR\x0c\x63\x61pabilities\x12\x12\n\x04tags\x18\x0b \x03(\tR\x04tags\x12\x46\n\x08metadata\x18\x0c \x03(\x0b\x32*.capiscio.v1.RegisteredAgent.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"k\n\x0fGetAgentRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12#\n\rinclude_badge\x18\x02 \x01(\x08R\x0cincludeBadge\x12!\n\x0cverify_badge\x18\x03 \x01(\x08R\x0bverifyBadge\"\x8c\x01\n\x10GetAgentResponse\x12\x32\n\x05\x61gent\x18\x01 \x01(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x05\x61gent\x12\x1f\n\x0b\x62\x61\x64ge_valid\x18\x02 \x01(\x08R\nbadgeValid\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\xff\x02\n\x13SearchAgentsRequest\x12\x14\n\x05query\x18\x01 \x01(\tR\x05query\x12\"\n\x0c\x63\x61pabilities\x18\x02 \x03(\tR\x0c\x63\x61pabilities\x12\x12\n\x04tags\x18\x03 \x03(\tR\x04tags\x12\x37\n\x08operator\x18\x04 \x01(\x0e\x32\x1b.capiscio.v1.SearchOperatorR\x08operator\x12\x32\n\nmin_rating\x18\x05 \x01(\x0e\x32\x13.capiscio.v1.RatingR\tminRating\x12=\n\rstatus_filter\x18\x06 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x0cstatusFilter\x12\x14\n\x05limit\x18\x07 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x08 \x01(\tR\x06\x63ursor\x12\x17\n\x07sort_by\x18\t \x01(\tR\x06sortBy\x12\'\n\x0fsort_descending\x18\n \x01(\x08R\x0esortDescending\"\x8e\x01\n\x14SearchAgentsResponse\x12\x34\n\x06\x61gents\x18\x01 \x03(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x06\x61gents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"\xff\x01\n\x14RegisterAgentRequest\x12&\n\x0f\x61gent_card_json\x18\x01 \x01(\tR\ragentCardJson\x12!\n\x0csigned_badge\x18\x02 \x01(\tR\x0bsignedBadge\x12\x12\n\x04tags\x18\x03 \x03(\tR\x04tags\x12K\n\x08metadata\x18\x04 \x03(\x0b\x32/.capiscio.v1.RegisterAgentRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x80\x01\n\x15RegisterAgentResponse\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x30\n\x06status\x18\x02 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x06status\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\x8d\x02\n\x12UpdateAgentRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12&\n\x0f\x61gent_card_json\x18\x02 \x01(\tR\ragentCardJson\x12!\n\x0csigned_badge\x18\x03 \x01(\tR\x0bsignedBadge\x12\x12\n\x04tags\x18\x04 \x03(\tR\x04tags\x12I\n\x08metadata\x18\x05 \x03(\x0b\x32-.capiscio.v1.UpdateAgentRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"n\n\x13UpdateAgentResponse\x12\x32\n\x05\x61gent\x18\x01 \x01(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x05\x61gent\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"B\n\x16\x44\x65registerAgentRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\"X\n\x17\x44\x65registerAgentResponse\x12\x18\n\x07success\x18\x01 \x01(\x08R\x07success\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"q\n\x19VerifyRegistrationRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12!\n\x0cverify_badge\x18\x02 \x01(\x08R\x0bverifyBadge\x12\x1f\n\x0bverify_keys\x18\x03 \x01(\x08R\nverifyKeys\"\xe5\x01\n\x1aVerifyRegistrationResponse\x12#\n\ris_registered\x18\x01 \x01(\x08R\x0cisRegistered\x12\x1f\n\x0b\x62\x61\x64ge_valid\x18\x02 \x01(\x08R\nbadgeValid\x12\x1d\n\nkeys_valid\x18\x03 \x01(\x08R\tkeysValid\x12=\n\nvalidation\x18\x04 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x05 \x01(\tR\x0c\x65rrorMessage\"\x80\x01\n\x11ListAgentsRequest\x12=\n\rstatus_filter\x18\x01 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x0cstatusFilter\x12\x14\n\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x03 \x01(\tR\x06\x63ursor\"\x8c\x01\n\x12ListAgentsResponse\x12\x34\n\x06\x61gents\x18\x01 \x03(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x06\x61gents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"\x11\n\x0fGetStatsRequest\"\x85\x05\n\x10GetStatsResponse\x12!\n\x0ctotal_agents\x18\x01 \x01(\x05R\x0btotalAgents\x12#\n\ractive_agents\x18\x02 \x01(\x05R\x0c\x61\x63tiveAgents\x12\'\n\x0finactive_agents\x18\x03 \x01(\x05R\x0einactiveAgents\x12)\n\x10suspended_agents\x18\x04 \x01(\x05R\x0fsuspendedAgents\x12%\n\x0epending_agents\x18\x05 \x01(\x05R\rpendingAgents\x12#\n\rbadged_agents\x18\x06 \x01(\x05R\x0c\x62\x61\x64gedAgents\x12[\n\x10\x61gents_by_rating\x18\x07 \x03(\x0b\x32\x31.capiscio.v1.GetStatsResponse.AgentsByRatingEntryR\x0e\x61gentsByRating\x12g\n\x14\x61gents_by_capability\x18\x08 \x03(\x0b\x32\x35.capiscio.v1.GetStatsResponse.AgentsByCapabilityEntryR\x12\x61gentsByCapability\x12\x39\n\x0clast_updated\x18\t \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x0blastUpdated\x1a\x41\n\x13\x41gentsByRatingEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01\x1a\x45\n\x17\x41gentsByCapabilityEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01\"\r\n\x0bPingRequest\"y\n\x0cPingResponse\x12\x16\n\x06status\x18\x01 \x01(\tR\x06status\x12\x18\n\x07version\x18\x02 \x01(\tR\x07version\x12\x37\n\x0bserver_time\x18\x03 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\nserverTime*\x95\x01\n\x0b\x41gentStatus\x12\x1c\n\x18\x41GENT_STATUS_UNSPECIFIED\x10\x00\x12\x17\n\x13\x41GENT_STATUS_ACTIVE\x10\x01\x12\x19\n\x15\x41GENT_STATUS_INACTIVE\x10\x02\x12\x1a\n\x16\x41GENT_STATUS_SUSPENDED\x10\x03\x12\x18\n\x14\x41GENT_STATUS_PENDING\x10\x04*b\n\x0eSearchOperator\x12\x1f\n\x1bSEARCH_OPERATOR_UNSPECIFIED\x10\x00\x12\x17\n\x13SEARCH_OPERATOR_AND\x10\x01\x12\x16\n\x12SEARCH_OPERATOR_OR\x10\x02\x32\xf3\x05\n\x0fRegistryService\x12G\n\x08GetAgent\x12\x1c.capiscio.v1.GetAgentRequest\x1a\x1d.capiscio.v1.GetAgentResponse\x12S\n\x0cSearchAgents\x12 .capiscio.v1.SearchAgentsRequest\x1a!.capiscio.v1.SearchAgentsResponse\x12V\n\rRegisterAgent\x12!.capiscio.v1.RegisterAgentRequest\x1a\".capiscio.v1.RegisterAgentResponse\x12P\n\x0bUpdateAgent\x12\x1f.capiscio.v1.UpdateAgentRequest\x1a .capiscio.v1.UpdateAgentResponse\x12\\\n\x0f\x44\x65registerAgent\x12#.capiscio.v1.DeregisterAgentRequest\x1a$.capiscio.v1.DeregisterAgentResponse\x12\x65\n\x12VerifyRegistration\x12&.capiscio.v1.VerifyRegistrationRequest\x1a\'.capiscio.v1.VerifyRegistrationResponse\x12M\n\nListAgents\x12\x1e.capiscio.v1.ListAgentsRequest\x1a\x1f.capiscio.v1.ListAgentsResponse\x12G\n\x08GetStats\x12\x1c.capiscio.v1.GetStatsRequest\x1a\x1d.capiscio.v1.GetStatsResponse\x12;\n\x04Ping\x12\x18.capiscio.v1.PingRequest\x1a\x19.capiscio.v1.PingResponseB\xb3\x01\n\x0f\x63om.capiscio.v1B\rRegistryProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py index d5f3b6b..d3e33ed 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import registry_pb2 as capiscio_dot_v1_dot_registry__pb2 +from capiscio.v1 import registry_pb2 as capiscio_dot_v1_dot_registry__pb2 class RegistryServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py index 0a94e60..022d8ef 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/revocation.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/revocation.proto' ) @@ -22,7 +22,7 @@ _sym_db = _symbol_database.Default() -from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x63\x61piscio/v1/revocation.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\"\x82\x02\n\x0fRevocationEntry\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\x12\x35\n\x06reason\x18\x02 \x01(\x0e\x32\x1d.capiscio.v1.RevocationReasonR\x06reason\x12\x35\n\nrevoked_at\x18\x03 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\trevokedAt\x12\x35\n\nexpires_at\x18\x04 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\texpiresAt\x12\x16\n\x06issuer\x18\x05 \x01(\tR\x06issuer\x12\x18\n\x07\x63omment\x18\x06 \x01(\tR\x07\x63omment\"\x80\x01\n\x10IsRevokedRequest\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\x12/\n\x07\x61t_time\x18\x02 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x06\x61tTime\x12!\n\x0c\x63heck_remote\x18\x03 \x01(\x08R\x0b\x63heckRemote\"~\n\x11IsRevokedResponse\x12\x1d\n\nis_revoked\x18\x01 \x01(\x08R\tisRevoked\x12\x32\n\x05\x65ntry\x18\x02 \x01(\x0b\x32\x1c.capiscio.v1.RevocationEntryR\x05\x65ntry\x12\x16\n\x06source\x18\x03 \x01(\tR\x06source\"z\n\rRevokeRequest\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\x12\x35\n\x06reason\x18\x02 \x01(\x0e\x32\x1d.capiscio.v1.RevocationReasonR\x06reason\x12\x18\n\x07\x63omment\x18\x03 \x01(\tR\x07\x63omment\"i\n\x0eRevokeResponse\x12\x32\n\x05\x65ntry\x18\x01 \x01(\x0b\x32\x1c.capiscio.v1.RevocationEntryR\x05\x65ntry\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"+\n\x0fUnrevokeRequest\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\"X\n\x10UnrevokeResponse\x12\x1f\n\x0bwas_revoked\x18\x01 \x01(\x08R\nwasRevoked\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"\xb1\x01\n\x16ListRevocationsRequest\x12%\n\x0esubject_filter\x18\x01 \x01(\tR\rsubjectFilter\x12\x42\n\rreason_filter\x18\x02 \x01(\x0e\x32\x1d.capiscio.v1.RevocationReasonR\x0creasonFilter\x12\x14\n\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x04 \x01(\tR\x06\x63ursor\"\x93\x01\n\x17ListRevocationsResponse\x12\x36\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x1c.capiscio.v1.RevocationEntryR\x07\x65ntries\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"_\n\x1a\x46\x65tchRevocationListRequest\x12\x10\n\x03url\x18\x01 \x01(\tR\x03url\x12/\n\x07timeout\x18\x02 \x01(\x0b\x32\x15.capiscio.v1.DurationR\x07timeout\"\xc7\x01\n\x1b\x46\x65tchRevocationListResponse\x12#\n\rentries_added\x18\x01 \x01(\x05R\x0c\x65ntriesAdded\x12\'\n\x0f\x65ntries_updated\x18\x02 \x01(\x05R\x0e\x65ntriesUpdated\x12\x35\n\nfetched_at\x18\x03 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tfetchedAt\x12#\n\rerror_message\x18\x04 \x01(\tR\x0c\x65rrorMessage\"8\n\x11\x43learCacheRequest\x12#\n\rsource_filter\x18\x01 \x01(\tR\x0csourceFilter\"=\n\x12\x43learCacheResponse\x12\'\n\x0f\x65ntries_cleared\x18\x01 \x01(\x05R\x0e\x65ntriesCleared\"\x16\n\x14GetCacheStatsRequest\"\xa9\x03\n\x15GetCacheStatsResponse\x12#\n\rtotal_entries\x18\x01 \x01(\x05R\x0ctotalEntries\x12#\n\rlocal_entries\x18\x02 \x01(\x05R\x0clocalEntries\x12%\n\x0eremote_entries\x18\x03 \x01(\x05R\rremoteEntries\x12\x42\n\x11last_remote_fetch\x18\x04 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x0flastRemoteFetch\x12\x32\n\tcache_ttl\x18\x05 \x01(\x0b\x32\x15.capiscio.v1.DurationR\x08\x63\x61\x63heTtl\x12\x63\n\x11\x65ntries_by_source\x18\x06 \x03(\x0b\x32\x37.capiscio.v1.GetCacheStatsResponse.EntriesBySourceEntryR\x0f\x65ntriesBySource\x1a\x42\n\x14\x45ntriesBySourceEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01*\x81\x02\n\x10RevocationReason\x12!\n\x1dREVOCATION_REASON_UNSPECIFIED\x10\x00\x12$\n REVOCATION_REASON_KEY_COMPROMISE\x10\x01\x12)\n%REVOCATION_REASON_AFFILIATION_CHANGED\x10\x02\x12 \n\x1cREVOCATION_REASON_SUPERSEDED\x10\x03\x12,\n(REVOCATION_REASON_CESSATION_OF_OPERATION\x10\x04\x12)\n%REVOCATION_REASON_PRIVILEGE_WITHDRAWN\x10\x05\x32\xda\x04\n\x11RevocationService\x12J\n\tIsRevoked\x12\x1d.capiscio.v1.IsRevokedRequest\x1a\x1e.capiscio.v1.IsRevokedResponse\x12\x41\n\x06Revoke\x12\x1a.capiscio.v1.RevokeRequest\x1a\x1b.capiscio.v1.RevokeResponse\x12G\n\x08Unrevoke\x12\x1c.capiscio.v1.UnrevokeRequest\x1a\x1d.capiscio.v1.UnrevokeResponse\x12\\\n\x0fListRevocations\x12#.capiscio.v1.ListRevocationsRequest\x1a$.capiscio.v1.ListRevocationsResponse\x12h\n\x13\x46\x65tchRevocationList\x12\'.capiscio.v1.FetchRevocationListRequest\x1a(.capiscio.v1.FetchRevocationListResponse\x12M\n\nClearCache\x12\x1e.capiscio.v1.ClearCacheRequest\x1a\x1f.capiscio.v1.ClearCacheResponse\x12V\n\rGetCacheStats\x12!.capiscio.v1.GetCacheStatsRequest\x1a\".capiscio.v1.GetCacheStatsResponseB\xb5\x01\n\x0f\x63om.capiscio.v1B\x0fRevocationProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py index 5d9c3fd..477711d 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import revocation_pb2 as capiscio_dot_v1_dot_revocation__pb2 +from capiscio.v1 import revocation_pb2 as capiscio_dot_v1_dot_revocation__pb2 class RevocationServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py index fea3be4..7b22a3b 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/scoring.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/scoring.proto' ) @@ -22,7 +22,7 @@ _sym_db = _symbol_database.Default() -from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x63\x61piscio/v1/scoring.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\"\xf3\x01\n\x04Rule\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12\x36\n\x08\x63\x61tegory\x18\x04 \x01(\x0e\x32\x1a.capiscio.v1.ScoreCategoryR\x08\x63\x61tegory\x12\x35\n\x08severity\x18\x05 \x01(\x0e\x32\x19.capiscio.v1.RuleSeverityR\x08severity\x12\x16\n\x06weight\x18\x06 \x01(\x05R\x06weight\x12\x1e\n\nexpression\x18\x07 \x01(\tR\nexpression\"\x8f\x02\n\x07RuleSet\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x12 \n\x0b\x64\x65scription\x18\x04 \x01(\tR\x0b\x64\x65scription\x12\'\n\x05rules\x18\x05 \x03(\x0b\x32\x11.capiscio.v1.RuleR\x05rules\x12>\n\x08metadata\x18\x06 \x03(\x0b\x32\".capiscio.v1.RuleSet.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x82\x02\n\nRuleResult\x12\x17\n\x07rule_id\x18\x01 \x01(\tR\x06ruleId\x12\x16\n\x06passed\x18\x02 \x01(\x08R\x06passed\x12\x18\n\x07message\x18\x03 \x01(\tR\x07message\x12-\n\x12score_contribution\x18\x04 \x01(\x01R\x11scoreContribution\x12>\n\x07\x64\x65tails\x18\x05 \x03(\x0b\x32$.capiscio.v1.RuleResult.DetailsEntryR\x07\x64\x65tails\x1a:\n\x0c\x44\x65tailsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xd6\x01\n\rCategoryScore\x12\x36\n\x08\x63\x61tegory\x18\x01 \x01(\x0e\x32\x1a.capiscio.v1.ScoreCategoryR\x08\x63\x61tegory\x12\x14\n\x05score\x18\x02 \x01(\x01R\x05score\x12!\n\x0crules_passed\x18\x03 \x01(\x05R\x0brulesPassed\x12!\n\x0crules_failed\x18\x04 \x01(\x05R\x0brulesFailed\x12\x31\n\x07results\x18\x05 \x03(\x0b\x32\x17.capiscio.v1.RuleResultR\x07results\"\x97\x03\n\rScoringResult\x12#\n\roverall_score\x18\x01 \x01(\x01R\x0coverallScore\x12+\n\x06rating\x18\x02 \x01(\x0e\x32\x13.capiscio.v1.RatingR\x06rating\x12:\n\ncategories\x18\x03 \x03(\x0b\x32\x1a.capiscio.v1.CategoryScoreR\ncategories\x12:\n\x0crule_results\x18\x04 \x03(\x0b\x32\x17.capiscio.v1.RuleResultR\x0bruleResults\x12=\n\nvalidation\x18\x05 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12\x33\n\tscored_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x08scoredAt\x12\x1e\n\x0brule_set_id\x18\x07 \x01(\tR\truleSetId\x12(\n\x10rule_set_version\x18\x08 \x01(\tR\x0eruleSetVersion\"\x9b\x01\n\x15ScoreAgentCardRequest\x12&\n\x0f\x61gent_card_json\x18\x01 \x01(\tR\ragentCardJson\x12\x1e\n\x0brule_set_id\x18\x02 \x01(\tR\truleSetId\x12:\n\ncategories\x18\x03 \x03(\x0e\x32\x1a.capiscio.v1.ScoreCategoryR\ncategories\"q\n\x16ScoreAgentCardResponse\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32\x1a.capiscio.v1.ScoringResultR\x06result\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"V\n\x13ValidateRuleRequest\x12\x17\n\x07rule_id\x18\x01 \x01(\tR\x06ruleId\x12&\n\x0f\x61gent_card_json\x18\x02 \x01(\tR\ragentCardJson\"l\n\x14ValidateRuleResponse\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x17.capiscio.v1.RuleResultR\x06result\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"C\n\x13ListRuleSetsRequest\x12\x14\n\x05limit\x18\x01 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x02 \x01(\tR\x06\x63ursor\"j\n\x14ListRuleSetsResponse\x12\x31\n\trule_sets\x18\x01 \x03(\x0b\x32\x14.capiscio.v1.RuleSetR\x08ruleSets\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\"=\n\x11GetRuleSetRequest\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x18\n\x07version\x18\x02 \x01(\tR\x07version\"j\n\x12GetRuleSetResponse\x12/\n\x08rule_set\x18\x01 \x01(\x0b\x32\x14.capiscio.v1.RuleSetR\x07ruleSet\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"}\n\x16\x41ggregateScoresRequest\x12\x34\n\x07results\x18\x01 \x03(\x0b\x32\x1a.capiscio.v1.ScoringResultR\x07results\x12-\n\x12\x61ggregation_method\x18\x02 \x01(\tR\x11\x61ggregationMethod\"\xb8\x02\n\x17\x41ggregateScoresResponse\x12\'\n\x0f\x61ggregate_score\x18\x01 \x01(\x01R\x0e\x61ggregateScore\x12>\n\x10\x61ggregate_rating\x18\x02 \x01(\x0e\x32\x13.capiscio.v1.RatingR\x0f\x61ggregateRating\x12m\n\x13\x63\x61tegory_aggregates\x18\x03 \x03(\x0b\x32<.capiscio.v1.AggregateScoresResponse.CategoryAggregatesEntryR\x12\x63\x61tegoryAggregates\x1a\x45\n\x17\x43\x61tegoryAggregatesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x01R\x05value:\x02\x38\x01*\xca\x01\n\rScoreCategory\x12\x1e\n\x1aSCORE_CATEGORY_UNSPECIFIED\x10\x00\x12\x1b\n\x17SCORE_CATEGORY_IDENTITY\x10\x01\x12\x1f\n\x1bSCORE_CATEGORY_CAPABILITIES\x10\x02\x12\x1b\n\x17SCORE_CATEGORY_SECURITY\x10\x03\x12\x1d\n\x19SCORE_CATEGORY_COMPLIANCE\x10\x04\x12\x1f\n\x1bSCORE_CATEGORY_TRANSPARENCY\x10\x05*\x95\x01\n\x0cRuleSeverity\x12\x1d\n\x19RULE_SEVERITY_UNSPECIFIED\x10\x00\x12\x16\n\x12RULE_SEVERITY_INFO\x10\x01\x12\x19\n\x15RULE_SEVERITY_WARNING\x10\x02\x12\x17\n\x13RULE_SEVERITY_ERROR\x10\x03\x12\x1a\n\x16RULE_SEVERITY_CRITICAL\x10\x04\x32\xc2\x03\n\x0eScoringService\x12Y\n\x0eScoreAgentCard\x12\".capiscio.v1.ScoreAgentCardRequest\x1a#.capiscio.v1.ScoreAgentCardResponse\x12S\n\x0cValidateRule\x12 .capiscio.v1.ValidateRuleRequest\x1a!.capiscio.v1.ValidateRuleResponse\x12S\n\x0cListRuleSets\x12 .capiscio.v1.ListRuleSetsRequest\x1a!.capiscio.v1.ListRuleSetsResponse\x12M\n\nGetRuleSet\x12\x1e.capiscio.v1.GetRuleSetRequest\x1a\x1f.capiscio.v1.GetRuleSetResponse\x12\\\n\x0f\x41ggregateScores\x12#.capiscio.v1.AggregateScoresRequest\x1a$.capiscio.v1.AggregateScoresResponseB\xb2\x01\n\x0f\x63om.capiscio.v1B\x0cScoringProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py index 5cc349e..0fa3aeb 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import scoring_pb2 as capiscio_dot_v1_dot_scoring__pb2 +from capiscio.v1 import scoring_pb2 as capiscio_dot_v1_dot_scoring__pb2 class ScoringServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py index cba00f2..67d8f97 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/simpleguard.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/simpleguard.proto' ) @@ -22,11 +22,11 @@ _sym_db = _symbol_database.Default() -from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 -from capiscio_sdk._rpc.gen.capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 +from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x63\x61piscio/v1/simpleguard.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\x1a\x17\x63\x61piscio/v1/trust.proto\"\xf1\x01\n\x0bSignRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x34\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x1c.capiscio.v1.SignatureFormatR\x06\x66ormat\x12?\n\x07headers\x18\x04 \x03(\x0b\x32%.capiscio.v1.SignRequest.HeadersEntryR\x07headers\x1a:\n\x0cHeadersEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"|\n\x0cSignResponse\x12\x1c\n\tsignature\x18\x01 \x01(\x0cR\tsignature\x12)\n\x10signature_string\x18\x02 \x01(\tR\x0fsignatureString\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\x9b\x01\n\rVerifyRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x1c\n\tsignature\x18\x02 \x01(\x0cR\tsignature\x12)\n\x10signature_string\x18\x03 \x01(\tR\x0fsignatureString\x12\'\n\x0f\x65xpected_signer\x18\x04 \x01(\tR\x0e\x65xpectedSigner\"\xc0\x01\n\x0eVerifyResponse\x12\x14\n\x05valid\x18\x01 \x01(\x08R\x05valid\x12\x1d\n\nsigner_did\x18\x02 \x01(\tR\tsignerDid\x12\x15\n\x06key_id\x18\x03 \x01(\tR\x05keyId\x12=\n\nvalidation\x18\x04 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x05 \x01(\tR\x0c\x65rrorMessage\"\xa8\x02\n\x13SignAttachedRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x34\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x1c.capiscio.v1.SignatureFormatR\x06\x66ormat\x12G\n\x07headers\x18\x04 \x03(\x0b\x32-.capiscio.v1.SignAttachedRequest.HeadersEntryR\x07headers\x12%\n\x0e\x64\x65tach_payload\x18\x05 \x01(\x08R\rdetachPayload\x1a:\n\x0cHeadersEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"M\n\x14SignAttachedResponse\x12\x10\n\x03jws\x18\x01 \x01(\tR\x03jws\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"}\n\x15VerifyAttachedRequest\x12\x10\n\x03jws\x18\x01 \x01(\tR\x03jws\x12)\n\x10\x64\x65tached_payload\x18\x02 \x01(\x0cR\x0f\x64\x65tachedPayload\x12\'\n\x0f\x65xpected_signer\x18\x03 \x01(\tR\x0e\x65xpectedSigner\"\xe2\x01\n\x16VerifyAttachedResponse\x12\x14\n\x05valid\x18\x01 \x01(\x08R\x05valid\x12\x18\n\x07payload\x18\x02 \x01(\x0cR\x07payload\x12\x1d\n\nsigner_did\x18\x03 \x01(\tR\tsignerDid\x12\x15\n\x06key_id\x18\x04 \x01(\tR\x05keyId\x12=\n\nvalidation\x18\x05 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x06 \x01(\tR\x0c\x65rrorMessage\"\xf4\x01\n\x16GenerateKeyPairRequest\x12\x37\n\talgorithm\x18\x01 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12M\n\x08metadata\x18\x03 \x03(\x0b\x32\x31.capiscio.v1.GenerateKeyPairRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xb5\x02\n\x17GenerateKeyPairResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\x12\x1f\n\x0bprivate_key\x18\x03 \x01(\x0cR\nprivateKey\x12$\n\x0epublic_key_pem\x18\x04 \x01(\tR\x0cpublicKeyPem\x12&\n\x0fprivate_key_pem\x18\x05 \x01(\tR\rprivateKeyPem\x12\x37\n\talgorithm\x18\x06 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12#\n\rerror_message\x18\x07 \x01(\tR\x0c\x65rrorMessage\x12\x17\n\x07\x64id_key\x18\x08 \x01(\tR\x06\x64idKey\"}\n\x0eLoadKeyRequest\x12\x1b\n\tfile_path\x18\x01 \x01(\tR\x08\x66ilePath\x12.\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x1e\n\npassphrase\x18\x03 \x01(\tR\npassphrase\"\xae\x01\n\x0fLoadKeyResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x02 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12&\n\x0fhas_private_key\x18\x03 \x01(\x08R\rhasPrivateKey\x12#\n\rerror_message\x18\x04 \x01(\tR\x0c\x65rrorMessage\"\xbf\x01\n\x10\x45xportKeyRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x1b\n\tfile_path\x18\x02 \x01(\tR\x08\x66ilePath\x12.\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\'\n\x0finclude_private\x18\x04 \x01(\x08R\x0eincludePrivate\x12\x1e\n\npassphrase\x18\x05 \x01(\tR\npassphrase\"U\n\x11\x45xportKeyResponse\x12\x1b\n\tfile_path\x18\x01 \x01(\tR\x08\x66ilePath\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"*\n\x11GetKeyInfoRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\"\xb5\x03\n\x12GetKeyInfoResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x02 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12&\n\x0fhas_private_key\x18\x03 \x01(\x08R\rhasPrivateKey\x12\x1d\n\npublic_key\x18\x04 \x01(\x0cR\tpublicKey\x12$\n\x0epublic_key_pem\x18\x05 \x01(\tR\x0cpublicKeyPem\x12\x35\n\ncreated_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tcreatedAt\x12I\n\x08metadata\x18\x07 \x03(\x0b\x32-.capiscio.v1.GetKeyInfoResponse.MetadataEntryR\x08metadata\x12#\n\rerror_message\x18\x08 \x01(\tR\x0c\x65rrorMessage\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01*\x8e\x01\n\x0fSignatureFormat\x12 \n\x1cSIGNATURE_FORMAT_UNSPECIFIED\x10\x00\x12 \n\x1cSIGNATURE_FORMAT_JWS_COMPACT\x10\x01\x12\x1d\n\x19SIGNATURE_FORMAT_JWS_JSON\x10\x02\x12\x18\n\x14SIGNATURE_FORMAT_RAW\x10\x03\x32\x83\x05\n\x12SimpleGuardService\x12;\n\x04Sign\x12\x18.capiscio.v1.SignRequest\x1a\x19.capiscio.v1.SignResponse\x12\x41\n\x06Verify\x12\x1a.capiscio.v1.VerifyRequest\x1a\x1b.capiscio.v1.VerifyResponse\x12S\n\x0cSignAttached\x12 .capiscio.v1.SignAttachedRequest\x1a!.capiscio.v1.SignAttachedResponse\x12Y\n\x0eVerifyAttached\x12\".capiscio.v1.VerifyAttachedRequest\x1a#.capiscio.v1.VerifyAttachedResponse\x12\\\n\x0fGenerateKeyPair\x12#.capiscio.v1.GenerateKeyPairRequest\x1a$.capiscio.v1.GenerateKeyPairResponse\x12\x44\n\x07LoadKey\x12\x1b.capiscio.v1.LoadKeyRequest\x1a\x1c.capiscio.v1.LoadKeyResponse\x12J\n\tExportKey\x12\x1d.capiscio.v1.ExportKeyRequest\x1a\x1e.capiscio.v1.ExportKeyResponse\x12M\n\nGetKeyInfo\x12\x1e.capiscio.v1.GetKeyInfoRequest\x1a\x1f.capiscio.v1.GetKeyInfoResponseB\xb6\x01\n\x0f\x63om.capiscio.v1B\x10SimpleguardProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x63\x61piscio/v1/simpleguard.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\x1a\x17\x63\x61piscio/v1/trust.proto\"\xf1\x01\n\x0bSignRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x34\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x1c.capiscio.v1.SignatureFormatR\x06\x66ormat\x12?\n\x07headers\x18\x04 \x03(\x0b\x32%.capiscio.v1.SignRequest.HeadersEntryR\x07headers\x1a:\n\x0cHeadersEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"|\n\x0cSignResponse\x12\x1c\n\tsignature\x18\x01 \x01(\x0cR\tsignature\x12)\n\x10signature_string\x18\x02 \x01(\tR\x0fsignatureString\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\x9b\x01\n\rVerifyRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x1c\n\tsignature\x18\x02 \x01(\x0cR\tsignature\x12)\n\x10signature_string\x18\x03 \x01(\tR\x0fsignatureString\x12\'\n\x0f\x65xpected_signer\x18\x04 \x01(\tR\x0e\x65xpectedSigner\"\xc0\x01\n\x0eVerifyResponse\x12\x14\n\x05valid\x18\x01 \x01(\x08R\x05valid\x12\x1d\n\nsigner_did\x18\x02 \x01(\tR\tsignerDid\x12\x15\n\x06key_id\x18\x03 \x01(\tR\x05keyId\x12=\n\nvalidation\x18\x04 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x05 \x01(\tR\x0c\x65rrorMessage\"\xa8\x02\n\x13SignAttachedRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x34\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x1c.capiscio.v1.SignatureFormatR\x06\x66ormat\x12G\n\x07headers\x18\x04 \x03(\x0b\x32-.capiscio.v1.SignAttachedRequest.HeadersEntryR\x07headers\x12%\n\x0e\x64\x65tach_payload\x18\x05 \x01(\x08R\rdetachPayload\x1a:\n\x0cHeadersEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"M\n\x14SignAttachedResponse\x12\x10\n\x03jws\x18\x01 \x01(\tR\x03jws\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"}\n\x15VerifyAttachedRequest\x12\x10\n\x03jws\x18\x01 \x01(\tR\x03jws\x12)\n\x10\x64\x65tached_payload\x18\x02 \x01(\x0cR\x0f\x64\x65tachedPayload\x12\'\n\x0f\x65xpected_signer\x18\x03 \x01(\tR\x0e\x65xpectedSigner\"\xe2\x01\n\x16VerifyAttachedResponse\x12\x14\n\x05valid\x18\x01 \x01(\x08R\x05valid\x12\x18\n\x07payload\x18\x02 \x01(\x0cR\x07payload\x12\x1d\n\nsigner_did\x18\x03 \x01(\tR\tsignerDid\x12\x15\n\x06key_id\x18\x04 \x01(\tR\x05keyId\x12=\n\nvalidation\x18\x05 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x06 \x01(\tR\x0c\x65rrorMessage\"\xf4\x01\n\x16GenerateKeyPairRequest\x12\x37\n\talgorithm\x18\x01 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12M\n\x08metadata\x18\x03 \x03(\x0b\x32\x31.capiscio.v1.GenerateKeyPairRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xb5\x02\n\x17GenerateKeyPairResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\x12\x1f\n\x0bprivate_key\x18\x03 \x01(\x0cR\nprivateKey\x12$\n\x0epublic_key_pem\x18\x04 \x01(\tR\x0cpublicKeyPem\x12&\n\x0fprivate_key_pem\x18\x05 \x01(\tR\rprivateKeyPem\x12\x37\n\talgorithm\x18\x06 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12#\n\rerror_message\x18\x07 \x01(\tR\x0c\x65rrorMessage\x12\x17\n\x07\x64id_key\x18\x08 \x01(\tR\x06\x64idKey\"}\n\x0eLoadKeyRequest\x12\x1b\n\tfile_path\x18\x01 \x01(\tR\x08\x66ilePath\x12.\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x1e\n\npassphrase\x18\x03 \x01(\tR\npassphrase\"\xae\x01\n\x0fLoadKeyResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x02 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12&\n\x0fhas_private_key\x18\x03 \x01(\x08R\rhasPrivateKey\x12#\n\rerror_message\x18\x04 \x01(\tR\x0c\x65rrorMessage\"\xbf\x01\n\x10\x45xportKeyRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x1b\n\tfile_path\x18\x02 \x01(\tR\x08\x66ilePath\x12.\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\'\n\x0finclude_private\x18\x04 \x01(\x08R\x0eincludePrivate\x12\x1e\n\npassphrase\x18\x05 \x01(\tR\npassphrase\"U\n\x11\x45xportKeyResponse\x12\x1b\n\tfile_path\x18\x01 \x01(\tR\x08\x66ilePath\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"*\n\x11GetKeyInfoRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\"\xb5\x03\n\x12GetKeyInfoResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x02 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12&\n\x0fhas_private_key\x18\x03 \x01(\x08R\rhasPrivateKey\x12\x1d\n\npublic_key\x18\x04 \x01(\x0cR\tpublicKey\x12$\n\x0epublic_key_pem\x18\x05 \x01(\tR\x0cpublicKeyPem\x12\x35\n\ncreated_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tcreatedAt\x12I\n\x08metadata\x18\x07 \x03(\x0b\x32-.capiscio.v1.GetKeyInfoResponse.MetadataEntryR\x08metadata\x12#\n\rerror_message\x18\x08 \x01(\tR\x0c\x65rrorMessage\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xcf\x02\n\x0bInitRequest\x12\x17\n\x07\x61pi_key\x18\x01 \x01(\tR\x06\x61piKey\x12\x19\n\x08\x61gent_id\x18\x02 \x01(\tR\x07\x61gentId\x12\x1d\n\nserver_url\x18\x03 \x01(\tR\tserverUrl\x12\x1d\n\noutput_dir\x18\x04 \x01(\tR\toutputDir\x12\x14\n\x05\x66orce\x18\x05 \x01(\x08R\x05\x66orce\x12\x37\n\talgorithm\x18\x06 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x42\n\x08metadata\x18\x07 \x03(\x0b\x32&.capiscio.v1.InitRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xa2\x02\n\x0cInitResponse\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x19\n\x08\x61gent_id\x18\x02 \x01(\tR\x07\x61gentId\x12(\n\x10private_key_path\x18\x03 \x01(\tR\x0eprivateKeyPath\x12&\n\x0fpublic_key_path\x18\x04 \x01(\tR\rpublicKeyPath\x12&\n\x0f\x61gent_card_path\x18\x05 \x01(\tR\ragentCardPath\x12&\n\x0f\x61gent_card_json\x18\x06 \x01(\tR\ragentCardJson\x12\x1e\n\nregistered\x18\x07 \x01(\x08R\nregistered\x12#\n\rerror_message\x18\x08 \x01(\tR\x0c\x65rrorMessage*\x8e\x01\n\x0fSignatureFormat\x12 \n\x1cSIGNATURE_FORMAT_UNSPECIFIED\x10\x00\x12 \n\x1cSIGNATURE_FORMAT_JWS_COMPACT\x10\x01\x12\x1d\n\x19SIGNATURE_FORMAT_JWS_JSON\x10\x02\x12\x18\n\x14SIGNATURE_FORMAT_RAW\x10\x03\x32\xc0\x05\n\x12SimpleGuardService\x12;\n\x04Sign\x12\x18.capiscio.v1.SignRequest\x1a\x19.capiscio.v1.SignResponse\x12\x41\n\x06Verify\x12\x1a.capiscio.v1.VerifyRequest\x1a\x1b.capiscio.v1.VerifyResponse\x12S\n\x0cSignAttached\x12 .capiscio.v1.SignAttachedRequest\x1a!.capiscio.v1.SignAttachedResponse\x12Y\n\x0eVerifyAttached\x12\".capiscio.v1.VerifyAttachedRequest\x1a#.capiscio.v1.VerifyAttachedResponse\x12\\\n\x0fGenerateKeyPair\x12#.capiscio.v1.GenerateKeyPairRequest\x1a$.capiscio.v1.GenerateKeyPairResponse\x12\x44\n\x07LoadKey\x12\x1b.capiscio.v1.LoadKeyRequest\x1a\x1c.capiscio.v1.LoadKeyResponse\x12J\n\tExportKey\x12\x1d.capiscio.v1.ExportKeyRequest\x1a\x1e.capiscio.v1.ExportKeyResponse\x12M\n\nGetKeyInfo\x12\x1e.capiscio.v1.GetKeyInfoRequest\x1a\x1f.capiscio.v1.GetKeyInfoResponse\x12;\n\x04Init\x12\x18.capiscio.v1.InitRequest\x1a\x19.capiscio.v1.InitResponseB\xb6\x01\n\x0f\x63om.capiscio.v1B\x10SimpleguardProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -42,8 +42,10 @@ _globals['_GENERATEKEYPAIRREQUEST_METADATAENTRY']._serialized_options = b'8\001' _globals['_GETKEYINFORESPONSE_METADATAENTRY']._loaded_options = None _globals['_GETKEYINFORESPONSE_METADATAENTRY']._serialized_options = b'8\001' - _globals['_SIGNATUREFORMAT']._serialized_start=3183 - _globals['_SIGNATUREFORMAT']._serialized_end=3325 + _globals['_INITREQUEST_METADATAENTRY']._loaded_options = None + _globals['_INITREQUEST_METADATAENTRY']._serialized_options = b'8\001' + _globals['_SIGNATUREFORMAT']._serialized_start=3814 + _globals['_SIGNATUREFORMAT']._serialized_end=3956 _globals['_SIGNREQUEST']._serialized_start=98 _globals['_SIGNREQUEST']._serialized_end=339 _globals['_SIGNREQUEST_HEADERSENTRY']._serialized_start=281 @@ -84,6 +86,12 @@ _globals['_GETKEYINFORESPONSE']._serialized_end=3180 _globals['_GETKEYINFORESPONSE_METADATAENTRY']._serialized_start=1740 _globals['_GETKEYINFORESPONSE_METADATAENTRY']._serialized_end=1799 - _globals['_SIMPLEGUARDSERVICE']._serialized_start=3328 - _globals['_SIMPLEGUARDSERVICE']._serialized_end=3971 + _globals['_INITREQUEST']._serialized_start=3183 + _globals['_INITREQUEST']._serialized_end=3518 + _globals['_INITREQUEST_METADATAENTRY']._serialized_start=1740 + _globals['_INITREQUEST_METADATAENTRY']._serialized_end=1799 + _globals['_INITRESPONSE']._serialized_start=3521 + _globals['_INITRESPONSE']._serialized_end=3811 + _globals['_SIMPLEGUARDSERVICE']._serialized_start=3959 + _globals['_SIMPLEGUARDSERVICE']._serialized_end=4663 # @@protoc_insertion_point(module_scope) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py index cc22c5b..addf886 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import simpleguard_pb2 as capiscio_dot_v1_dot_simpleguard__pb2 +from capiscio.v1 import simpleguard_pb2 as capiscio_dot_v1_dot_simpleguard__pb2 class SimpleGuardServiceStub(object): @@ -55,6 +55,11 @@ def __init__(self, channel): request_serializer=capiscio_dot_v1_dot_simpleguard__pb2.GetKeyInfoRequest.SerializeToString, response_deserializer=capiscio_dot_v1_dot_simpleguard__pb2.GetKeyInfoResponse.FromString, _registered_method=True) + self.Init = channel.unary_unary( + '/capiscio.v1.SimpleGuardService/Init', + request_serializer=capiscio_dot_v1_dot_simpleguard__pb2.InitRequest.SerializeToString, + response_deserializer=capiscio_dot_v1_dot_simpleguard__pb2.InitResponse.FromString, + _registered_method=True) class SimpleGuardServiceServicer(object): @@ -117,6 +122,14 @@ def GetKeyInfo(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def Init(self, request, context): + """Initialize agent identity (Let's Encrypt style one-call setup) + Generates key pair, derives DID, registers with server, creates agent card + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def add_SimpleGuardServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -160,6 +173,11 @@ def add_SimpleGuardServiceServicer_to_server(servicer, server): request_deserializer=capiscio_dot_v1_dot_simpleguard__pb2.GetKeyInfoRequest.FromString, response_serializer=capiscio_dot_v1_dot_simpleguard__pb2.GetKeyInfoResponse.SerializeToString, ), + 'Init': grpc.unary_unary_rpc_method_handler( + servicer.Init, + request_deserializer=capiscio_dot_v1_dot_simpleguard__pb2.InitRequest.FromString, + response_serializer=capiscio_dot_v1_dot_simpleguard__pb2.InitResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( 'capiscio.v1.SimpleGuardService', rpc_method_handlers) @@ -387,3 +405,30 @@ def GetKeyInfo(request, timeout, metadata, _registered_method=True) + + @staticmethod + def Init(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/capiscio.v1.SimpleGuardService/Init', + capiscio_dot_v1_dot_simpleguard__pb2.InitRequest.SerializeToString, + capiscio_dot_v1_dot_simpleguard__pb2.InitResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py index 6a56043..b63b47a 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: capiscio/v1/trust.proto -# Protobuf Python Version: 6.33.4 +# Protobuf Python Version: 6.33.5 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -13,7 +13,7 @@ _runtime_version.Domain.PUBLIC, 6, 33, - 4, + 5, '', 'capiscio/v1/trust.proto' ) @@ -22,7 +22,7 @@ _sym_db = _symbol_database.Default() -from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x63\x61piscio/v1/trust.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\"\xa7\x03\n\nTrustedKey\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x03 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x1d\n\npublic_key\x18\x04 \x01(\x0cR\tpublicKey\x12.\n\x06\x66ormat\x18\x05 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x31\n\x08\x61\x64\x64\x65\x64_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x07\x61\x64\x64\x65\x64\x41t\x12\x35\n\nexpires_at\x18\x07 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\texpiresAt\x12\x41\n\x08metadata\x18\x08 \x03(\x0b\x32%.capiscio.v1.TrustedKey.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xf3\x01\n\rAddKeyRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\x12.\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x44\n\x08metadata\x18\x04 \x03(\x0b\x32(.capiscio.v1.AddKeyRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"L\n\x0e\x41\x64\x64KeyResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\";\n\x10RemoveKeyRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\"[\n\x11RemoveKeyResponse\x12!\n\x0ckeys_removed\x18\x01 \x01(\x05R\x0bkeysRemoved\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"8\n\rGetKeyRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\"`\n\x0eGetKeyResponse\x12)\n\x03key\x18\x01 \x01(\x0b\x32\x17.capiscio.v1.TrustedKeyR\x03key\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"^\n\x0fListKeysRequest\x12\x1d\n\ndid_filter\x18\x01 \x01(\tR\tdidFilter\x12\x14\n\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x03 \x01(\tR\x06\x63ursor\"\x81\x01\n\x10ListKeysResponse\x12+\n\x04keys\x18\x01 \x03(\x0b\x32\x17.capiscio.v1.TrustedKeyR\x04keys\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"$\n\x10IsTrustedRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\"]\n\x11IsTrustedResponse\x12\x1d\n\nis_trusted\x18\x01 \x01(\x08R\tisTrusted\x12)\n\x03key\x18\x02 \x01(\x0b\x32\x17.capiscio.v1.TrustedKeyR\x03key\"a\n\x1aImportFromDirectoryRequest\x12%\n\x0e\x64irectory_path\x18\x01 \x01(\tR\rdirectoryPath\x12\x1c\n\trecursive\x18\x02 \x01(\x08R\trecursive\"}\n\x1bImportFromDirectoryResponse\x12#\n\rkeys_imported\x18\x01 \x01(\x05R\x0ckeysImported\x12!\n\x0ckeys_skipped\x18\x02 \x01(\x05R\x0bkeysSkipped\x12\x16\n\x06\x65rrors\x18\x03 \x03(\tR\x06\x65rrors\"q\n\x18\x45xportToDirectoryRequest\x12%\n\x0e\x64irectory_path\x18\x01 \x01(\tR\rdirectoryPath\x12.\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\"e\n\x19\x45xportToDirectoryResponse\x12#\n\rkeys_exported\x18\x01 \x01(\x05R\x0ckeysExported\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\",\n\x10\x43learKeysRequest\x12\x18\n\x07\x63onfirm\x18\x01 \x01(\x08R\x07\x63onfirm\"6\n\x11\x43learKeysResponse\x12!\n\x0ckeys_cleared\x18\x01 \x01(\x05R\x0bkeysCleared*\xbc\x01\n\x0cKeyAlgorithm\x12\x1d\n\x19KEY_ALGORITHM_UNSPECIFIED\x10\x00\x12\x19\n\x15KEY_ALGORITHM_ED25519\x10\x01\x12\x1c\n\x18KEY_ALGORITHM_ECDSA_P256\x10\x02\x12\x1c\n\x18KEY_ALGORITHM_ECDSA_P384\x10\x03\x12\x1a\n\x16KEY_ALGORITHM_RSA_2048\x10\x04\x12\x1a\n\x16KEY_ALGORITHM_RSA_4096\x10\x05*c\n\tKeyFormat\x12\x1a\n\x16KEY_FORMAT_UNSPECIFIED\x10\x00\x12\x12\n\x0eKEY_FORMAT_JWK\x10\x01\x12\x12\n\x0eKEY_FORMAT_PEM\x10\x02\x12\x12\n\x0eKEY_FORMAT_DER\x10\x03\x32\x90\x05\n\x11TrustStoreService\x12\x41\n\x06\x41\x64\x64Key\x12\x1a.capiscio.v1.AddKeyRequest\x1a\x1b.capiscio.v1.AddKeyResponse\x12J\n\tRemoveKey\x12\x1d.capiscio.v1.RemoveKeyRequest\x1a\x1e.capiscio.v1.RemoveKeyResponse\x12\x41\n\x06GetKey\x12\x1a.capiscio.v1.GetKeyRequest\x1a\x1b.capiscio.v1.GetKeyResponse\x12G\n\x08ListKeys\x12\x1c.capiscio.v1.ListKeysRequest\x1a\x1d.capiscio.v1.ListKeysResponse\x12J\n\tIsTrusted\x12\x1d.capiscio.v1.IsTrustedRequest\x1a\x1e.capiscio.v1.IsTrustedResponse\x12h\n\x13ImportFromDirectory\x12\'.capiscio.v1.ImportFromDirectoryRequest\x1a(.capiscio.v1.ImportFromDirectoryResponse\x12\x62\n\x11\x45xportToDirectory\x12%.capiscio.v1.ExportToDirectoryRequest\x1a&.capiscio.v1.ExportToDirectoryResponse\x12\x46\n\x05\x43lear\x12\x1d.capiscio.v1.ClearKeysRequest\x1a\x1e.capiscio.v1.ClearKeysResponseB\xb0\x01\n\x0f\x63om.capiscio.v1B\nTrustProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py index e8a62fc..73e9e92 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio_sdk._rpc.gen.capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 +from capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 class TrustStoreServiceStub(object): diff --git a/capiscio_sdk/connect.py b/capiscio_sdk/connect.py new file mode 100644 index 0000000..fe70f83 --- /dev/null +++ b/capiscio_sdk/connect.py @@ -0,0 +1,394 @@ +""" +CapiscIO Connect - "Let's Encrypt" style agent identity. + +All cryptographic operations (key generation, DID derivation) are performed +by the capiscio-core Go library via gRPC, ensuring consistency across SDKs. + +Usage: + from capiscio_sdk import CapiscIO + + # One-liner to get a production-ready agent + agent = CapiscIO.connect(api_key="sk_live_...") + + # Use the agent + print(agent.did) # did:key:z6Mk... + print(agent.badge) # Current badge (auto-renewed) + agent.emit("task_started", {"task_id": "123"}) +""" + +import os +import json +import logging +import httpx +from pathlib import Path +from typing import Optional, Dict, Any +from dataclasses import dataclass, field + +from ._rpc.client import CapiscioRPCClient +from .errors import ConfigurationError + +logger = logging.getLogger(__name__) + +# Default paths +DEFAULT_CONFIG_DIR = Path.home() / ".capiscio" +DEFAULT_KEYS_DIR = DEFAULT_CONFIG_DIR / "keys" +DEFAULT_CONFIG_FILE = DEFAULT_CONFIG_DIR / "config.toml" + +# Default server URLs +PROD_REGISTRY = "https://registry.capisc.io" +PROD_DASHBOARD = "https://app.capisc.io" + + +@dataclass +class AgentIdentity: + """Represents a fully-configured agent identity.""" + + agent_id: str + did: str + name: str + api_key: str + server_url: str + keys_dir: Path + badge: Optional[str] = None + badge_expires_at: Optional[str] = None + _guard: Any = field(default=None, repr=False) + _keeper: Any = field(default=None, repr=False) + _emitter: Any = field(default=None, repr=False) + + def emit(self, event_type: str, data: Dict[str, Any]) -> bool: + """Emit an event to the registry.""" + if not self._emitter: + from .events import EventEmitter + self._emitter = EventEmitter( + server_url=self.server_url, + api_key=self.api_key, + agent_id=self.agent_id, + ) + return self._emitter.emit(event_type, data) + + def get_badge(self) -> Optional[str]: + """Get current badge (auto-renewed if needed).""" + if self._keeper: + return self._keeper.get_badge() + return self.badge + + def status(self) -> Dict[str, Any]: + """Get agent status including badge validity.""" + return { + "agent_id": self.agent_id, + "did": self.did, + "name": self.name, + "server": self.server_url, + "badge_valid": self.badge is not None, + "badge_expires_at": self.badge_expires_at, + } + + +class CapiscIO: + """ + CapiscIO SDK - "Let's Encrypt" style agent identity. + + Provides seamless agent identity management: + - Auto-creates agents if they don't exist + - Auto-generates and stores cryptographic keys + - Auto-derives and registers DIDs + - Auto-requests and renews badges + + Usage: + agent = CapiscIO.connect(api_key="sk_live_...") + print(agent.did) + """ + + @classmethod + def connect( + cls, + api_key: str, + *, + name: Optional[str] = None, + agent_id: Optional[str] = None, + server_url: str = PROD_REGISTRY, + keys_dir: Optional[Path] = None, + auto_badge: bool = True, + dev_mode: bool = False, + ) -> AgentIdentity: + """ + Connect to CapiscIO and get a fully-configured agent identity. + + This is the main entry point - it handles everything automatically: + 1. Finds or creates the agent + 2. Generates keys if needed + 3. Derives and registers DID + 4. Requests badge (if auto_badge=True) + 5. Sets up auto-renewal + + Args: + api_key: Your CapiscIO API key (sk_live_... or sk_test_...) + name: Agent name (auto-generated if omitted) + agent_id: Specific agent ID to use (auto-discovered if omitted) + server_url: Registry server URL (default: production) + keys_dir: Directory for keys (default: ~/.capiscio/keys/{agent_id}/) + auto_badge: Whether to automatically request a badge + dev_mode: Use self-signed badges (Trust Level 0) + + Returns: + AgentIdentity with full credentials and methods + + Example: + agent = CapiscIO.connect(api_key="sk_live_abc123") + print(f"Agent DID: {agent.did}") + agent.emit("agent_started", {"version": "1.0"}) + """ + connector = _Connector( + api_key=api_key, + name=name, + agent_id=agent_id, + server_url=server_url, + keys_dir=keys_dir, + auto_badge=auto_badge, + dev_mode=dev_mode, + ) + return connector.connect() + + @classmethod + def from_env(cls, **kwargs) -> AgentIdentity: + """ + Connect using environment variables. + + Reads from: + - CAPISCIO_API_KEY (required) + - CAPISCIO_AGENT_ID (optional) + - CAPISCIO_AGENT_NAME (optional) + - CAPISCIO_SERVER_URL (optional, default: production) + - CAPISCIO_DEV_MODE (optional, default: false) + """ + api_key = os.environ.get("CAPISCIO_API_KEY") + if not api_key: + raise ValueError( + "CAPISCIO_API_KEY environment variable is required. " + "Get your API key at https://app.capisc.io" + ) + + return cls.connect( + api_key=api_key, + agent_id=os.environ.get("CAPISCIO_AGENT_ID"), + name=os.environ.get("CAPISCIO_AGENT_NAME"), + server_url=os.environ.get("CAPISCIO_SERVER_URL", PROD_REGISTRY), + dev_mode=os.environ.get("CAPISCIO_DEV_MODE", "").lower() in ("true", "1", "yes"), + **kwargs, + ) + + +class _Connector: + """Internal class that handles the connection logic.""" + + def __init__( + self, + api_key: str, + name: Optional[str], + agent_id: Optional[str], + server_url: str, + keys_dir: Optional[Path], + auto_badge: bool, + dev_mode: bool, + ): + self.api_key = api_key + self.name = name + self.agent_id = agent_id + self.server_url = server_url.rstrip("/") + self.keys_dir = keys_dir + self.auto_badge = auto_badge + self.dev_mode = dev_mode + + # HTTP client for registry API + self._client = httpx.Client( + base_url=self.server_url, + headers={ + "X-Capiscio-Registry-Key": self.api_key, + "Content-Type": "application/json", + }, + timeout=30.0, + ) + + # gRPC client for capiscio-core (crypto operations) + self._rpc_client: Optional[CapiscioRPCClient] = None + + def connect(self) -> AgentIdentity: + """Execute the full connection flow.""" + logger.info("Connecting to CapiscIO...") + + # Step 1: Find or create agent + agent_data = self._ensure_agent() + self.agent_id = agent_data["id"] + self.name = agent_data.get("name") or self.name or f"Agent-{self.agent_id[:8]}" + + logger.info(f"Agent: {self.name} ({self.agent_id})") + + # Step 2: Set up keys directory + if not self.keys_dir: + self.keys_dir = DEFAULT_KEYS_DIR / self.agent_id + self.keys_dir.mkdir(parents=True, exist_ok=True) + + # Step 3: Initialize identity via capiscio-core Init RPC (one call does everything) + did = self._init_identity() + logger.info(f"DID: {did}") + + # Step 4: Set up badge (if auto_badge) + badge = None + badge_expires_at = None + keeper = None + guard = None + + if self.auto_badge and not self.dev_mode: + badge, badge_expires_at, keeper, guard = self._setup_badge() + if badge: + logger.info(f"Badge acquired (expires: {badge_expires_at})") + + return AgentIdentity( + agent_id=self.agent_id, + did=did, + name=self.name, + api_key=self.api_key, + server_url=self.server_url, + keys_dir=self.keys_dir, + badge=badge, + badge_expires_at=badge_expires_at, + _guard=guard, + _keeper=keeper, + ) + + def _ensure_agent(self) -> Dict[str, Any]: + """Find existing agent or create new one.""" + if self.agent_id: + # Fetch specific agent + resp = self._client.get(f"/v1/agents/{self.agent_id}") + if resp.status_code == 200: + data = resp.json() + return data.get("data", data) + elif resp.status_code == 404: + raise ValueError(f"Agent {self.agent_id} not found") + else: + raise RuntimeError(f"Failed to fetch agent: {resp.text}") + + # List agents and find by name or use first one + resp = self._client.get("/v1/agents") + if resp.status_code != 200: + raise RuntimeError(f"Failed to list agents: {resp.text}") + + data = resp.json() + agents = data.get("data", data) if isinstance(data.get("data", data), list) else [] + + # Find by name if specified + if self.name: + for agent in agents: + if agent.get("name") == self.name: + return agent + + # Use first agent if available + if agents: + return agents[0] + + # Create new agent + return self._create_agent() + + def _create_agent(self) -> Dict[str, Any]: + """Create a new agent.""" + name = self.name or f"Agent-{os.urandom(4).hex()}" + + resp = self._client.post("/v1/agents", json={ + "name": name, + "protocol": "a2a", + }) + + if resp.status_code not in (200, 201): + raise RuntimeError(f"Failed to create agent: {resp.text}") + + data = resp.json() + logger.info(f"Created new agent: {name}") + return data.get("data", data) + + def _init_identity(self) -> str: + """Initialize identity via capiscio-core Init RPC. + + This is the "Let's Encrypt" style one-call setup that: + 1. Generates Ed25519 key pair + 2. Derives did:key URI + 3. Registers DID with the server + 4. Creates agent-card.json + + All cryptographic operations are performed by capiscio-core Go library. + """ + did_file_path = self.keys_dir / "did.txt" + private_key_path = self.keys_dir / "private.jwk" + + # Check if we already have a DID and keys (for idempotency) + if did_file_path.exists() and private_key_path.exists(): + logger.debug("Using existing identity from prior init") + return did_file_path.read_text().strip() + + # Connect to capiscio-core gRPC + if not self._rpc_client: + self._rpc_client = CapiscioRPCClient() + self._rpc_client.connect() + + logger.info("Initializing identity via capiscio-core Init RPC...") + + # Call Init RPC - one call does everything + result, error = self._rpc_client.simpleguard.init( + api_key=self.api_key, + agent_id=self.agent_id, + server_url=self.server_url, + output_dir=str(self.keys_dir), + force=False, + ) + + if error: + raise ConfigurationError(f"Failed to initialize identity: {error}") + + did = result["did"] + + # Save DID for future reference (idempotency check) + did_file_path.write_text(did) + + logger.info(f"Identity initialized: {did}") + if result.get("registered"): + logger.info("DID registered with server") + + return did + + def _setup_badge(self): + """Set up BadgeKeeper for automatic badge management.""" + try: + from .badge_keeper import BadgeKeeper + from .simple_guard import SimpleGuard + + # Set up SimpleGuard with correct parameters + guard = SimpleGuard( + base_dir=str(self.keys_dir.parent), + agent_id=self.agent_id, + dev_mode=self.dev_mode, + ) + + # Set up BadgeKeeper with correct parameters + keeper = BadgeKeeper( + api_url=self.server_url, + api_key=self.api_key, + agent_id=self.agent_id, + mode="dev" if self.dev_mode else "ca", + output_file=str(self.keys_dir / "badge.jwt"), + ) + + # Start the keeper and get initial badge + keeper.start() + badge = keeper.get_badge() + expires_at = getattr(keeper, 'badge_expires_at', None) + + return badge, expires_at, keeper, guard + + except Exception as e: + logger.warning(f"Badge setup failed (continuing without badge): {e}") + return None, None, None, None + + +# Convenience alias +connect = CapiscIO.connect +from_env = CapiscIO.from_env diff --git a/capiscio_sdk/events.py b/capiscio_sdk/events.py new file mode 100644 index 0000000..3a2841a --- /dev/null +++ b/capiscio_sdk/events.py @@ -0,0 +1,319 @@ +""" +Event emission for CapiscIO agents. + +Provides a simple interface for emitting events to the CapiscIO registry. +Events are used for observability, auditing, and real-time monitoring. + +Example: + from capiscio_sdk.events import EventEmitter + + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_live_...", + agent_id="my-agent-id", + ) + + emitter.emit("task_started", {"task_id": "123", "input": "..."}) + emitter.emit("tool_call", {"tool": "search", "query": "AI news"}) + emitter.emit("task_completed", {"task_id": "123", "output": "..."}) +""" + +import json +import logging +import time +import uuid +from datetime import datetime, timezone +from typing import Any, Dict, Optional + +import httpx + +logger = logging.getLogger(__name__) + + +class EventEmitter: + """ + Emits events to the CapiscIO registry. + + Events provide visibility into agent behavior for: + - Real-time monitoring in the dashboard + - Audit trails for compliance + - Analytics and debugging + + Attributes: + server_url: Registry server URL + api_key: API key for authentication + agent_id: Agent ID for event attribution + """ + + # Standard event types + EVENT_TASK_STARTED = "task_started" + EVENT_TASK_COMPLETED = "task_completed" + EVENT_TASK_FAILED = "task_failed" + EVENT_TOOL_CALL = "tool_call" + EVENT_TOOL_RESULT = "tool_result" + EVENT_LLM_CALL = "llm_call" + EVENT_LLM_RESPONSE = "llm_response" + EVENT_AGENT_STARTED = "agent_started" + EVENT_AGENT_STOPPED = "agent_stopped" + EVENT_ERROR = "error" + EVENT_WARNING = "warning" + EVENT_INFO = "info" + + def __init__( + self, + server_url: str = "https://registry.capisc.io", + api_key: Optional[str] = None, + agent_id: Optional[str] = None, + agent_name: Optional[str] = None, + batch_size: int = 10, + flush_interval: float = 5.0, + enabled: bool = True, + ): + """ + Initialize the event emitter. + + Args: + server_url: Registry server URL (default: production) + api_key: API key for authentication + agent_id: Agent ID for event attribution + agent_name: Human-readable agent name (for logging) + batch_size: Number of events to batch before sending + flush_interval: Max seconds between flushes + enabled: Whether to actually send events (for testing) + """ + self.server_url = server_url.rstrip("/") + self.api_key = api_key + self.agent_id = agent_id + self.agent_name = agent_name or agent_id + self.batch_size = batch_size + self.flush_interval = flush_interval + self.enabled = enabled + + self._client = httpx.Client(timeout=10.0) + self._batch: list = [] + self._last_flush = time.time() + + # Validate config + if enabled and not api_key: + logger.warning("EventEmitter: No API key provided, events will not be sent") + self.enabled = False + + def emit( + self, + event_type: str, + data: Optional[Dict[str, Any]] = None, + *, + task_id: Optional[str] = None, + correlation_id: Optional[str] = None, + flush: bool = False, + ) -> bool: + """ + Emit an event to the registry. + + Args: + event_type: Type of event (e.g., "task_started", "tool_call") + data: Event-specific data + task_id: Optional task ID for correlation + correlation_id: Optional correlation ID for tracing + flush: Whether to flush immediately (default: batch) + + Returns: + True if event was queued/sent successfully + + Example: + emitter.emit("task_started", { + "task_id": "abc123", + "input": "Research AI trends", + }) + """ + if not self.enabled: + return False + + event = { + "id": str(uuid.uuid4()), + "type": event_type, + "agentId": self.agent_id, + "timestamp": datetime.now(timezone.utc).isoformat(), + "data": data or {}, + } + + if task_id: + event["taskId"] = task_id + if correlation_id: + event["correlationId"] = correlation_id + + self._batch.append(event) + + # Flush if batch is full or flush requested + if flush or len(self._batch) >= self.batch_size: + return self.flush() + + # Flush if interval exceeded + if time.time() - self._last_flush > self.flush_interval: + return self.flush() + + return True + + def flush(self) -> bool: + """ + Send all batched events to the registry. + + Returns: + True if flush was successful + """ + if not self._batch: + return True + + if not self.enabled: + self._batch.clear() + return False + + events_to_send = self._batch.copy() + self._batch.clear() + self._last_flush = time.time() + + try: + headers = { + "Content-Type": "application/json", + "X-Capiscio-Registry-Key": self.api_key, + } + + # Send batch + response = self._client.post( + f"{self.server_url}/v1/events", + headers=headers, + json={"events": events_to_send}, + ) + + if response.status_code in (200, 201, 202): + logger.debug(f"Sent {len(events_to_send)} events") + return True + else: + logger.warning(f"Failed to send events: {response.status_code} {response.text}") + # Re-queue events on failure + self._batch.extend(events_to_send) + return False + + except Exception as e: + logger.error(f"Error sending events: {e}") + # Re-queue events on failure + self._batch.extend(events_to_send) + return False + + def task_started(self, task_id: str, input_text: str, **kwargs) -> bool: + """Convenience method for task_started events.""" + return self.emit( + self.EVENT_TASK_STARTED, + {"input": input_text, **kwargs}, + task_id=task_id, + flush=True, + ) + + def task_completed(self, task_id: str, output: str, **kwargs) -> bool: + """Convenience method for task_completed events.""" + return self.emit( + self.EVENT_TASK_COMPLETED, + {"output": output, **kwargs}, + task_id=task_id, + flush=True, + ) + + def task_failed(self, task_id: str, error: str, **kwargs) -> bool: + """Convenience method for task_failed events.""" + return self.emit( + self.EVENT_TASK_FAILED, + {"error": error, **kwargs}, + task_id=task_id, + flush=True, + ) + + def tool_call(self, tool_name: str, arguments: Dict[str, Any], task_id: Optional[str] = None, **kwargs) -> bool: + """Convenience method for tool_call events.""" + return self.emit( + self.EVENT_TOOL_CALL, + {"tool": tool_name, "arguments": arguments, **kwargs}, + task_id=task_id, + ) + + def tool_result(self, tool_name: str, result: Any, task_id: Optional[str] = None, **kwargs) -> bool: + """Convenience method for tool_result events.""" + return self.emit( + self.EVENT_TOOL_RESULT, + {"tool": tool_name, "result": result, **kwargs}, + task_id=task_id, + ) + + def close(self) -> None: + """Flush remaining events and close the client.""" + self.flush() + self._client.close() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + return False + + +# Global emitter for simple usage +_global_emitter: Optional[EventEmitter] = None + + +def init( + api_key: str, + agent_id: str, + server_url: str = "https://registry.capisc.io", + **kwargs, +) -> EventEmitter: + """ + Initialize the global event emitter. + + Args: + api_key: API key for authentication + agent_id: Agent ID for event attribution + server_url: Registry server URL + + Returns: + The global EventEmitter instance + + Example: + from capiscio_sdk import events + + events.init(api_key="sk_live_...", agent_id="my-agent") + events.emit("task_started", {"task_id": "123"}) + """ + global _global_emitter + _global_emitter = EventEmitter( + server_url=server_url, + api_key=api_key, + agent_id=agent_id, + **kwargs, + ) + return _global_emitter + + +def emit(event_type: str, data: Optional[Dict[str, Any]] = None, **kwargs) -> bool: + """ + Emit an event using the global emitter. + + Must call `init()` first. + + Args: + event_type: Type of event + data: Event data + **kwargs: Additional arguments passed to EventEmitter.emit() + + Returns: + True if event was queued/sent + """ + if _global_emitter is None: + raise RuntimeError("Event emitter not initialized. Call events.init() first.") + return _global_emitter.emit(event_type, data, **kwargs) + + +def flush() -> bool: + """Flush all pending events.""" + if _global_emitter is None: + return False + return _global_emitter.flush() diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index a8bae37..ab205fd 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -1,8 +1,50 @@ # Quick Start -Get your A2A agent protected in **5 minutes** with the CapiscIO Python SDK. +Get your A2A agent up and running with CapiscIO in **under 60 seconds**. -## See the Difference +## Step 1: Get Your Agent Identity (One Line) + +Just like Let's Encrypt made HTTPS easy, CapiscIO makes agent identity easy: + +```python +from capiscio_sdk import CapiscIO + +# One line - handles everything automatically +agent = CapiscIO.connect(api_key="sk_live_...") + +print(agent.did) # did:key:z6Mk... - your agent's identity +print(agent.badge) # Your trust badge +``` + +**What happens automatically:** + +- ✅ Ed25519 key pair generated +- ✅ `did:key` identity derived (RFC-002 compliant) +- ✅ DID registered with CapiscIO registry +- ✅ Agent card created +- ✅ Trust badge requested + +### Using Environment Variables (Recommended for Production) + +```python +from capiscio_sdk import CapiscIO + +# Reads CAPISCIO_API_KEY from environment +agent = CapiscIO.from_env() +``` + +### Two Setup Paths + +| Path | When to Use | Code | +|------|-------------|------| +| **Quick Start** | Getting started, single agent | `CapiscIO.connect(api_key="...")` | +| **UI-First** | Teams, multiple agents | `CapiscIO.connect(api_key="...", agent_id="agt_123")` | + +--- + +## Step 2: Secure Your Agent (Optional but Recommended) + +Now protect your agent from attacks: ### ❌ Without Security @@ -40,7 +82,7 @@ secured_agent = secure(MyAgentExecutor()) ## Prerequisites - Python 3.10 or higher -- An existing A2A agent executor +- A CapiscIO API key ([get one free](https://app.capisc.io)) - Basic familiarity with the [A2A protocol](https://github.com/google/A2A) ## Installation @@ -55,12 +97,18 @@ pip install capiscio-sdk The fastest way to add security to your agent: ```python -from capiscio_sdk import secure +from capiscio_sdk import CapiscIO, secure from my_agent import MyAgentExecutor -# Wrap your agent with security (production defaults) +# 1. Get your agent identity (one line) +agent = CapiscIO.connect(api_key="sk_live_...") + +# 2. Wrap your agent with security (one line) secured_agent = secure(MyAgentExecutor()) +# Your agent now has identity AND security +print(f"Agent DID: {agent.did}") + # Validate an agent card and access scores result = await secured_agent.validate_agent_card(card_url) print(result.compliance.total, result.trust.total, result.availability.total) @@ -68,6 +116,8 @@ print(result.compliance.total, result.trust.total, result.availability.total) That's it! Your agent now has: +- ✅ Cryptographic identity (`did:key`) +- ✅ Trust badge (auto-renewed) - ✅ Message validation - ✅ Protocol compliance checking - ✅ Rate limiting (60 requests/minute) diff --git a/pyproject.toml b/pyproject.toml index 50187dd..d6124bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ dev = [ "types-cachetools>=5.3.0", "fastapi>=0.100.0", "starlette>=0.27.0", + "base58>=2.1.0", # Used in tests for DID verification ] [project.urls] From 4e2681892ab286a6bc8d50d0ce4398ae19e97f92 Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Thu, 5 Feb 2026 23:48:27 +0200 Subject: [PATCH 2/8] fix: require protobuf>=6.33.5 to match generated code --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d6124bd..59698f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ dependencies = [ "cachetools>=5.3.0", "pyjwt[crypto]>=2.8.0", "grpcio>=1.60.0", - "protobuf>=4.25.0", + "protobuf>=6.33.5", ] [project.optional-dependencies] From 7e4d991e46ad2aee687877a0d305f2c5a250447e Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Thu, 5 Feb 2026 23:54:46 +0200 Subject: [PATCH 3/8] fix: address Copilot review comments - Fix BadgeKeeper.get_badge() -> get_current_badge() (2 places) - Fix proto import paths: from capiscio.v1 -> from capiscio_sdk._rpc.gen.capiscio.v1 - Remove unused json imports from connect.py and events.py --- capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py | 4 ++-- capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py | 4 ++-- capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py | 2 +- capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py | 2 +- capiscio_sdk/connect.py | 5 ++--- capiscio_sdk/events.py | 1 - 15 files changed, 17 insertions(+), 19 deletions(-) diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py index 8610bcb..d04f070 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/badge_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 class BadgeServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py index 2bc43ee..0862baf 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/did_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import did_pb2 as capiscio_dot_v1_dot_did__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import did_pb2 as capiscio_dot_v1_dot_did__pb2 class DIDServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py index 7e4e828..cac02f6 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/mcp_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import mcp_pb2 as capiscio_dot_v1_dot_mcp__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import mcp_pb2 as capiscio_dot_v1_dot_mcp__pb2 class MCPServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py index 6f18fab..c116a31 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2.py @@ -22,8 +22,8 @@ _sym_db = _symbol_database.Default() -from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 -from capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import badge_pb2 as capiscio_dot_v1_dot_badge__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x63\x61piscio/v1/registry.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\x1a\x17\x63\x61piscio/v1/badge.proto\"\xc1\x04\n\x0fRegisteredAgent\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12&\n\x0f\x61gent_card_json\x18\x04 \x01(\tR\ragentCardJson\x12\x30\n\x06status\x18\x05 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x06status\x12.\n\x05\x62\x61\x64ge\x18\x06 \x01(\x0b\x32\x18.capiscio.v1.BadgeClaimsR\x05\x62\x61\x64ge\x12+\n\x06rating\x18\x07 \x01(\x0e\x32\x13.capiscio.v1.RatingR\x06rating\x12;\n\rregistered_at\x18\x08 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x0cregisteredAt\x12\x35\n\nupdated_at\x18\t \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tupdatedAt\x12\"\n\x0c\x63\x61pabilities\x18\n \x03(\tR\x0c\x63\x61pabilities\x12\x12\n\x04tags\x18\x0b \x03(\tR\x04tags\x12\x46\n\x08metadata\x18\x0c \x03(\x0b\x32*.capiscio.v1.RegisteredAgent.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"k\n\x0fGetAgentRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12#\n\rinclude_badge\x18\x02 \x01(\x08R\x0cincludeBadge\x12!\n\x0cverify_badge\x18\x03 \x01(\x08R\x0bverifyBadge\"\x8c\x01\n\x10GetAgentResponse\x12\x32\n\x05\x61gent\x18\x01 \x01(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x05\x61gent\x12\x1f\n\x0b\x62\x61\x64ge_valid\x18\x02 \x01(\x08R\nbadgeValid\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\xff\x02\n\x13SearchAgentsRequest\x12\x14\n\x05query\x18\x01 \x01(\tR\x05query\x12\"\n\x0c\x63\x61pabilities\x18\x02 \x03(\tR\x0c\x63\x61pabilities\x12\x12\n\x04tags\x18\x03 \x03(\tR\x04tags\x12\x37\n\x08operator\x18\x04 \x01(\x0e\x32\x1b.capiscio.v1.SearchOperatorR\x08operator\x12\x32\n\nmin_rating\x18\x05 \x01(\x0e\x32\x13.capiscio.v1.RatingR\tminRating\x12=\n\rstatus_filter\x18\x06 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x0cstatusFilter\x12\x14\n\x05limit\x18\x07 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x08 \x01(\tR\x06\x63ursor\x12\x17\n\x07sort_by\x18\t \x01(\tR\x06sortBy\x12\'\n\x0fsort_descending\x18\n \x01(\x08R\x0esortDescending\"\x8e\x01\n\x14SearchAgentsResponse\x12\x34\n\x06\x61gents\x18\x01 \x03(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x06\x61gents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"\xff\x01\n\x14RegisterAgentRequest\x12&\n\x0f\x61gent_card_json\x18\x01 \x01(\tR\ragentCardJson\x12!\n\x0csigned_badge\x18\x02 \x01(\tR\x0bsignedBadge\x12\x12\n\x04tags\x18\x03 \x03(\tR\x04tags\x12K\n\x08metadata\x18\x04 \x03(\x0b\x32/.capiscio.v1.RegisterAgentRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x80\x01\n\x15RegisterAgentResponse\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x30\n\x06status\x18\x02 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x06status\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\x8d\x02\n\x12UpdateAgentRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12&\n\x0f\x61gent_card_json\x18\x02 \x01(\tR\ragentCardJson\x12!\n\x0csigned_badge\x18\x03 \x01(\tR\x0bsignedBadge\x12\x12\n\x04tags\x18\x04 \x03(\tR\x04tags\x12I\n\x08metadata\x18\x05 \x03(\x0b\x32-.capiscio.v1.UpdateAgentRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"n\n\x13UpdateAgentResponse\x12\x32\n\x05\x61gent\x18\x01 \x01(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x05\x61gent\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"B\n\x16\x44\x65registerAgentRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\"X\n\x17\x44\x65registerAgentResponse\x12\x18\n\x07success\x18\x01 \x01(\x08R\x07success\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"q\n\x19VerifyRegistrationRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12!\n\x0cverify_badge\x18\x02 \x01(\x08R\x0bverifyBadge\x12\x1f\n\x0bverify_keys\x18\x03 \x01(\x08R\nverifyKeys\"\xe5\x01\n\x1aVerifyRegistrationResponse\x12#\n\ris_registered\x18\x01 \x01(\x08R\x0cisRegistered\x12\x1f\n\x0b\x62\x61\x64ge_valid\x18\x02 \x01(\x08R\nbadgeValid\x12\x1d\n\nkeys_valid\x18\x03 \x01(\x08R\tkeysValid\x12=\n\nvalidation\x18\x04 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x05 \x01(\tR\x0c\x65rrorMessage\"\x80\x01\n\x11ListAgentsRequest\x12=\n\rstatus_filter\x18\x01 \x01(\x0e\x32\x18.capiscio.v1.AgentStatusR\x0cstatusFilter\x12\x14\n\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x03 \x01(\tR\x06\x63ursor\"\x8c\x01\n\x12ListAgentsResponse\x12\x34\n\x06\x61gents\x18\x01 \x03(\x0b\x32\x1c.capiscio.v1.RegisteredAgentR\x06\x61gents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"\x11\n\x0fGetStatsRequest\"\x85\x05\n\x10GetStatsResponse\x12!\n\x0ctotal_agents\x18\x01 \x01(\x05R\x0btotalAgents\x12#\n\ractive_agents\x18\x02 \x01(\x05R\x0c\x61\x63tiveAgents\x12\'\n\x0finactive_agents\x18\x03 \x01(\x05R\x0einactiveAgents\x12)\n\x10suspended_agents\x18\x04 \x01(\x05R\x0fsuspendedAgents\x12%\n\x0epending_agents\x18\x05 \x01(\x05R\rpendingAgents\x12#\n\rbadged_agents\x18\x06 \x01(\x05R\x0c\x62\x61\x64gedAgents\x12[\n\x10\x61gents_by_rating\x18\x07 \x03(\x0b\x32\x31.capiscio.v1.GetStatsResponse.AgentsByRatingEntryR\x0e\x61gentsByRating\x12g\n\x14\x61gents_by_capability\x18\x08 \x03(\x0b\x32\x35.capiscio.v1.GetStatsResponse.AgentsByCapabilityEntryR\x12\x61gentsByCapability\x12\x39\n\x0clast_updated\x18\t \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x0blastUpdated\x1a\x41\n\x13\x41gentsByRatingEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01\x1a\x45\n\x17\x41gentsByCapabilityEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01\"\r\n\x0bPingRequest\"y\n\x0cPingResponse\x12\x16\n\x06status\x18\x01 \x01(\tR\x06status\x12\x18\n\x07version\x18\x02 \x01(\tR\x07version\x12\x37\n\x0bserver_time\x18\x03 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\nserverTime*\x95\x01\n\x0b\x41gentStatus\x12\x1c\n\x18\x41GENT_STATUS_UNSPECIFIED\x10\x00\x12\x17\n\x13\x41GENT_STATUS_ACTIVE\x10\x01\x12\x19\n\x15\x41GENT_STATUS_INACTIVE\x10\x02\x12\x1a\n\x16\x41GENT_STATUS_SUSPENDED\x10\x03\x12\x18\n\x14\x41GENT_STATUS_PENDING\x10\x04*b\n\x0eSearchOperator\x12\x1f\n\x1bSEARCH_OPERATOR_UNSPECIFIED\x10\x00\x12\x17\n\x13SEARCH_OPERATOR_AND\x10\x01\x12\x16\n\x12SEARCH_OPERATOR_OR\x10\x02\x32\xf3\x05\n\x0fRegistryService\x12G\n\x08GetAgent\x12\x1c.capiscio.v1.GetAgentRequest\x1a\x1d.capiscio.v1.GetAgentResponse\x12S\n\x0cSearchAgents\x12 .capiscio.v1.SearchAgentsRequest\x1a!.capiscio.v1.SearchAgentsResponse\x12V\n\rRegisterAgent\x12!.capiscio.v1.RegisterAgentRequest\x1a\".capiscio.v1.RegisterAgentResponse\x12P\n\x0bUpdateAgent\x12\x1f.capiscio.v1.UpdateAgentRequest\x1a .capiscio.v1.UpdateAgentResponse\x12\\\n\x0f\x44\x65registerAgent\x12#.capiscio.v1.DeregisterAgentRequest\x1a$.capiscio.v1.DeregisterAgentResponse\x12\x65\n\x12VerifyRegistration\x12&.capiscio.v1.VerifyRegistrationRequest\x1a\'.capiscio.v1.VerifyRegistrationResponse\x12M\n\nListAgents\x12\x1e.capiscio.v1.ListAgentsRequest\x1a\x1f.capiscio.v1.ListAgentsResponse\x12G\n\x08GetStats\x12\x1c.capiscio.v1.GetStatsRequest\x1a\x1d.capiscio.v1.GetStatsResponse\x12;\n\x04Ping\x12\x18.capiscio.v1.PingRequest\x1a\x19.capiscio.v1.PingResponseB\xb3\x01\n\x0f\x63om.capiscio.v1B\rRegistryProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py index d3e33ed..d5f3b6b 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/registry_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import registry_pb2 as capiscio_dot_v1_dot_registry__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import registry_pb2 as capiscio_dot_v1_dot_registry__pb2 class RegistryServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py index 022d8ef..f658ad4 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2.py @@ -22,7 +22,7 @@ _sym_db = _symbol_database.Default() -from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x63\x61piscio/v1/revocation.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\"\x82\x02\n\x0fRevocationEntry\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\x12\x35\n\x06reason\x18\x02 \x01(\x0e\x32\x1d.capiscio.v1.RevocationReasonR\x06reason\x12\x35\n\nrevoked_at\x18\x03 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\trevokedAt\x12\x35\n\nexpires_at\x18\x04 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\texpiresAt\x12\x16\n\x06issuer\x18\x05 \x01(\tR\x06issuer\x12\x18\n\x07\x63omment\x18\x06 \x01(\tR\x07\x63omment\"\x80\x01\n\x10IsRevokedRequest\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\x12/\n\x07\x61t_time\x18\x02 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x06\x61tTime\x12!\n\x0c\x63heck_remote\x18\x03 \x01(\x08R\x0b\x63heckRemote\"~\n\x11IsRevokedResponse\x12\x1d\n\nis_revoked\x18\x01 \x01(\x08R\tisRevoked\x12\x32\n\x05\x65ntry\x18\x02 \x01(\x0b\x32\x1c.capiscio.v1.RevocationEntryR\x05\x65ntry\x12\x16\n\x06source\x18\x03 \x01(\tR\x06source\"z\n\rRevokeRequest\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\x12\x35\n\x06reason\x18\x02 \x01(\x0e\x32\x1d.capiscio.v1.RevocationReasonR\x06reason\x12\x18\n\x07\x63omment\x18\x03 \x01(\tR\x07\x63omment\"i\n\x0eRevokeResponse\x12\x32\n\x05\x65ntry\x18\x01 \x01(\x0b\x32\x1c.capiscio.v1.RevocationEntryR\x05\x65ntry\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"+\n\x0fUnrevokeRequest\x12\x18\n\x07subject\x18\x01 \x01(\tR\x07subject\"X\n\x10UnrevokeResponse\x12\x1f\n\x0bwas_revoked\x18\x01 \x01(\x08R\nwasRevoked\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"\xb1\x01\n\x16ListRevocationsRequest\x12%\n\x0esubject_filter\x18\x01 \x01(\tR\rsubjectFilter\x12\x42\n\rreason_filter\x18\x02 \x01(\x0e\x32\x1d.capiscio.v1.RevocationReasonR\x0creasonFilter\x12\x14\n\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x04 \x01(\tR\x06\x63ursor\"\x93\x01\n\x17ListRevocationsResponse\x12\x36\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x1c.capiscio.v1.RevocationEntryR\x07\x65ntries\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"_\n\x1a\x46\x65tchRevocationListRequest\x12\x10\n\x03url\x18\x01 \x01(\tR\x03url\x12/\n\x07timeout\x18\x02 \x01(\x0b\x32\x15.capiscio.v1.DurationR\x07timeout\"\xc7\x01\n\x1b\x46\x65tchRevocationListResponse\x12#\n\rentries_added\x18\x01 \x01(\x05R\x0c\x65ntriesAdded\x12\'\n\x0f\x65ntries_updated\x18\x02 \x01(\x05R\x0e\x65ntriesUpdated\x12\x35\n\nfetched_at\x18\x03 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tfetchedAt\x12#\n\rerror_message\x18\x04 \x01(\tR\x0c\x65rrorMessage\"8\n\x11\x43learCacheRequest\x12#\n\rsource_filter\x18\x01 \x01(\tR\x0csourceFilter\"=\n\x12\x43learCacheResponse\x12\'\n\x0f\x65ntries_cleared\x18\x01 \x01(\x05R\x0e\x65ntriesCleared\"\x16\n\x14GetCacheStatsRequest\"\xa9\x03\n\x15GetCacheStatsResponse\x12#\n\rtotal_entries\x18\x01 \x01(\x05R\x0ctotalEntries\x12#\n\rlocal_entries\x18\x02 \x01(\x05R\x0clocalEntries\x12%\n\x0eremote_entries\x18\x03 \x01(\x05R\rremoteEntries\x12\x42\n\x11last_remote_fetch\x18\x04 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x0flastRemoteFetch\x12\x32\n\tcache_ttl\x18\x05 \x01(\x0b\x32\x15.capiscio.v1.DurationR\x08\x63\x61\x63heTtl\x12\x63\n\x11\x65ntries_by_source\x18\x06 \x03(\x0b\x32\x37.capiscio.v1.GetCacheStatsResponse.EntriesBySourceEntryR\x0f\x65ntriesBySource\x1a\x42\n\x14\x45ntriesBySourceEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x05R\x05value:\x02\x38\x01*\x81\x02\n\x10RevocationReason\x12!\n\x1dREVOCATION_REASON_UNSPECIFIED\x10\x00\x12$\n REVOCATION_REASON_KEY_COMPROMISE\x10\x01\x12)\n%REVOCATION_REASON_AFFILIATION_CHANGED\x10\x02\x12 \n\x1cREVOCATION_REASON_SUPERSEDED\x10\x03\x12,\n(REVOCATION_REASON_CESSATION_OF_OPERATION\x10\x04\x12)\n%REVOCATION_REASON_PRIVILEGE_WITHDRAWN\x10\x05\x32\xda\x04\n\x11RevocationService\x12J\n\tIsRevoked\x12\x1d.capiscio.v1.IsRevokedRequest\x1a\x1e.capiscio.v1.IsRevokedResponse\x12\x41\n\x06Revoke\x12\x1a.capiscio.v1.RevokeRequest\x1a\x1b.capiscio.v1.RevokeResponse\x12G\n\x08Unrevoke\x12\x1c.capiscio.v1.UnrevokeRequest\x1a\x1d.capiscio.v1.UnrevokeResponse\x12\\\n\x0fListRevocations\x12#.capiscio.v1.ListRevocationsRequest\x1a$.capiscio.v1.ListRevocationsResponse\x12h\n\x13\x46\x65tchRevocationList\x12\'.capiscio.v1.FetchRevocationListRequest\x1a(.capiscio.v1.FetchRevocationListResponse\x12M\n\nClearCache\x12\x1e.capiscio.v1.ClearCacheRequest\x1a\x1f.capiscio.v1.ClearCacheResponse\x12V\n\rGetCacheStats\x12!.capiscio.v1.GetCacheStatsRequest\x1a\".capiscio.v1.GetCacheStatsResponseB\xb5\x01\n\x0f\x63om.capiscio.v1B\x0fRevocationProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py index 477711d..5d9c3fd 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/revocation_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import revocation_pb2 as capiscio_dot_v1_dot_revocation__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import revocation_pb2 as capiscio_dot_v1_dot_revocation__pb2 class RevocationServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py index 7b22a3b..8cbd4e4 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2.py @@ -22,7 +22,7 @@ _sym_db = _symbol_database.Default() -from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x63\x61piscio/v1/scoring.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\"\xf3\x01\n\x04Rule\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12\x36\n\x08\x63\x61tegory\x18\x04 \x01(\x0e\x32\x1a.capiscio.v1.ScoreCategoryR\x08\x63\x61tegory\x12\x35\n\x08severity\x18\x05 \x01(\x0e\x32\x19.capiscio.v1.RuleSeverityR\x08severity\x12\x16\n\x06weight\x18\x06 \x01(\x05R\x06weight\x12\x1e\n\nexpression\x18\x07 \x01(\tR\nexpression\"\x8f\x02\n\x07RuleSet\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x12 \n\x0b\x64\x65scription\x18\x04 \x01(\tR\x0b\x64\x65scription\x12\'\n\x05rules\x18\x05 \x03(\x0b\x32\x11.capiscio.v1.RuleR\x05rules\x12>\n\x08metadata\x18\x06 \x03(\x0b\x32\".capiscio.v1.RuleSet.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x82\x02\n\nRuleResult\x12\x17\n\x07rule_id\x18\x01 \x01(\tR\x06ruleId\x12\x16\n\x06passed\x18\x02 \x01(\x08R\x06passed\x12\x18\n\x07message\x18\x03 \x01(\tR\x07message\x12-\n\x12score_contribution\x18\x04 \x01(\x01R\x11scoreContribution\x12>\n\x07\x64\x65tails\x18\x05 \x03(\x0b\x32$.capiscio.v1.RuleResult.DetailsEntryR\x07\x64\x65tails\x1a:\n\x0c\x44\x65tailsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xd6\x01\n\rCategoryScore\x12\x36\n\x08\x63\x61tegory\x18\x01 \x01(\x0e\x32\x1a.capiscio.v1.ScoreCategoryR\x08\x63\x61tegory\x12\x14\n\x05score\x18\x02 \x01(\x01R\x05score\x12!\n\x0crules_passed\x18\x03 \x01(\x05R\x0brulesPassed\x12!\n\x0crules_failed\x18\x04 \x01(\x05R\x0brulesFailed\x12\x31\n\x07results\x18\x05 \x03(\x0b\x32\x17.capiscio.v1.RuleResultR\x07results\"\x97\x03\n\rScoringResult\x12#\n\roverall_score\x18\x01 \x01(\x01R\x0coverallScore\x12+\n\x06rating\x18\x02 \x01(\x0e\x32\x13.capiscio.v1.RatingR\x06rating\x12:\n\ncategories\x18\x03 \x03(\x0b\x32\x1a.capiscio.v1.CategoryScoreR\ncategories\x12:\n\x0crule_results\x18\x04 \x03(\x0b\x32\x17.capiscio.v1.RuleResultR\x0bruleResults\x12=\n\nvalidation\x18\x05 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12\x33\n\tscored_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x08scoredAt\x12\x1e\n\x0brule_set_id\x18\x07 \x01(\tR\truleSetId\x12(\n\x10rule_set_version\x18\x08 \x01(\tR\x0eruleSetVersion\"\x9b\x01\n\x15ScoreAgentCardRequest\x12&\n\x0f\x61gent_card_json\x18\x01 \x01(\tR\ragentCardJson\x12\x1e\n\x0brule_set_id\x18\x02 \x01(\tR\truleSetId\x12:\n\ncategories\x18\x03 \x03(\x0e\x32\x1a.capiscio.v1.ScoreCategoryR\ncategories\"q\n\x16ScoreAgentCardResponse\x12\x32\n\x06result\x18\x01 \x01(\x0b\x32\x1a.capiscio.v1.ScoringResultR\x06result\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"V\n\x13ValidateRuleRequest\x12\x17\n\x07rule_id\x18\x01 \x01(\tR\x06ruleId\x12&\n\x0f\x61gent_card_json\x18\x02 \x01(\tR\ragentCardJson\"l\n\x14ValidateRuleResponse\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x17.capiscio.v1.RuleResultR\x06result\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"C\n\x13ListRuleSetsRequest\x12\x14\n\x05limit\x18\x01 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x02 \x01(\tR\x06\x63ursor\"j\n\x14ListRuleSetsResponse\x12\x31\n\trule_sets\x18\x01 \x03(\x0b\x32\x14.capiscio.v1.RuleSetR\x08ruleSets\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\"=\n\x11GetRuleSetRequest\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x18\n\x07version\x18\x02 \x01(\tR\x07version\"j\n\x12GetRuleSetResponse\x12/\n\x08rule_set\x18\x01 \x01(\x0b\x32\x14.capiscio.v1.RuleSetR\x07ruleSet\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"}\n\x16\x41ggregateScoresRequest\x12\x34\n\x07results\x18\x01 \x03(\x0b\x32\x1a.capiscio.v1.ScoringResultR\x07results\x12-\n\x12\x61ggregation_method\x18\x02 \x01(\tR\x11\x61ggregationMethod\"\xb8\x02\n\x17\x41ggregateScoresResponse\x12\'\n\x0f\x61ggregate_score\x18\x01 \x01(\x01R\x0e\x61ggregateScore\x12>\n\x10\x61ggregate_rating\x18\x02 \x01(\x0e\x32\x13.capiscio.v1.RatingR\x0f\x61ggregateRating\x12m\n\x13\x63\x61tegory_aggregates\x18\x03 \x03(\x0b\x32<.capiscio.v1.AggregateScoresResponse.CategoryAggregatesEntryR\x12\x63\x61tegoryAggregates\x1a\x45\n\x17\x43\x61tegoryAggregatesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\x01R\x05value:\x02\x38\x01*\xca\x01\n\rScoreCategory\x12\x1e\n\x1aSCORE_CATEGORY_UNSPECIFIED\x10\x00\x12\x1b\n\x17SCORE_CATEGORY_IDENTITY\x10\x01\x12\x1f\n\x1bSCORE_CATEGORY_CAPABILITIES\x10\x02\x12\x1b\n\x17SCORE_CATEGORY_SECURITY\x10\x03\x12\x1d\n\x19SCORE_CATEGORY_COMPLIANCE\x10\x04\x12\x1f\n\x1bSCORE_CATEGORY_TRANSPARENCY\x10\x05*\x95\x01\n\x0cRuleSeverity\x12\x1d\n\x19RULE_SEVERITY_UNSPECIFIED\x10\x00\x12\x16\n\x12RULE_SEVERITY_INFO\x10\x01\x12\x19\n\x15RULE_SEVERITY_WARNING\x10\x02\x12\x17\n\x13RULE_SEVERITY_ERROR\x10\x03\x12\x1a\n\x16RULE_SEVERITY_CRITICAL\x10\x04\x32\xc2\x03\n\x0eScoringService\x12Y\n\x0eScoreAgentCard\x12\".capiscio.v1.ScoreAgentCardRequest\x1a#.capiscio.v1.ScoreAgentCardResponse\x12S\n\x0cValidateRule\x12 .capiscio.v1.ValidateRuleRequest\x1a!.capiscio.v1.ValidateRuleResponse\x12S\n\x0cListRuleSets\x12 .capiscio.v1.ListRuleSetsRequest\x1a!.capiscio.v1.ListRuleSetsResponse\x12M\n\nGetRuleSet\x12\x1e.capiscio.v1.GetRuleSetRequest\x1a\x1f.capiscio.v1.GetRuleSetResponse\x12\\\n\x0f\x41ggregateScores\x12#.capiscio.v1.AggregateScoresRequest\x1a$.capiscio.v1.AggregateScoresResponseB\xb2\x01\n\x0f\x63om.capiscio.v1B\x0cScoringProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py index 0fa3aeb..5cc349e 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/scoring_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import scoring_pb2 as capiscio_dot_v1_dot_scoring__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import scoring_pb2 as capiscio_dot_v1_dot_scoring__pb2 class ScoringServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py index 67d8f97..3636eec 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2.py @@ -22,8 +22,8 @@ _sym_db = _symbol_database.Default() -from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 -from capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x63\x61piscio/v1/simpleguard.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\x1a\x17\x63\x61piscio/v1/trust.proto\"\xf1\x01\n\x0bSignRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x34\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x1c.capiscio.v1.SignatureFormatR\x06\x66ormat\x12?\n\x07headers\x18\x04 \x03(\x0b\x32%.capiscio.v1.SignRequest.HeadersEntryR\x07headers\x1a:\n\x0cHeadersEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"|\n\x0cSignResponse\x12\x1c\n\tsignature\x18\x01 \x01(\x0cR\tsignature\x12)\n\x10signature_string\x18\x02 \x01(\tR\x0fsignatureString\x12#\n\rerror_message\x18\x03 \x01(\tR\x0c\x65rrorMessage\"\x9b\x01\n\rVerifyRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x1c\n\tsignature\x18\x02 \x01(\x0cR\tsignature\x12)\n\x10signature_string\x18\x03 \x01(\tR\x0fsignatureString\x12\'\n\x0f\x65xpected_signer\x18\x04 \x01(\tR\x0e\x65xpectedSigner\"\xc0\x01\n\x0eVerifyResponse\x12\x14\n\x05valid\x18\x01 \x01(\x08R\x05valid\x12\x1d\n\nsigner_did\x18\x02 \x01(\tR\tsignerDid\x12\x15\n\x06key_id\x18\x03 \x01(\tR\x05keyId\x12=\n\nvalidation\x18\x04 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x05 \x01(\tR\x0c\x65rrorMessage\"\xa8\x02\n\x13SignAttachedRequest\x12\x18\n\x07payload\x18\x01 \x01(\x0cR\x07payload\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x34\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x1c.capiscio.v1.SignatureFormatR\x06\x66ormat\x12G\n\x07headers\x18\x04 \x03(\x0b\x32-.capiscio.v1.SignAttachedRequest.HeadersEntryR\x07headers\x12%\n\x0e\x64\x65tach_payload\x18\x05 \x01(\x08R\rdetachPayload\x1a:\n\x0cHeadersEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"M\n\x14SignAttachedResponse\x12\x10\n\x03jws\x18\x01 \x01(\tR\x03jws\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"}\n\x15VerifyAttachedRequest\x12\x10\n\x03jws\x18\x01 \x01(\tR\x03jws\x12)\n\x10\x64\x65tached_payload\x18\x02 \x01(\x0cR\x0f\x64\x65tachedPayload\x12\'\n\x0f\x65xpected_signer\x18\x03 \x01(\tR\x0e\x65xpectedSigner\"\xe2\x01\n\x16VerifyAttachedResponse\x12\x14\n\x05valid\x18\x01 \x01(\x08R\x05valid\x12\x18\n\x07payload\x18\x02 \x01(\x0cR\x07payload\x12\x1d\n\nsigner_did\x18\x03 \x01(\tR\tsignerDid\x12\x15\n\x06key_id\x18\x04 \x01(\tR\x05keyId\x12=\n\nvalidation\x18\x05 \x01(\x0b\x32\x1d.capiscio.v1.ValidationResultR\nvalidation\x12#\n\rerror_message\x18\x06 \x01(\tR\x0c\x65rrorMessage\"\xf4\x01\n\x16GenerateKeyPairRequest\x12\x37\n\talgorithm\x18\x01 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12M\n\x08metadata\x18\x03 \x03(\x0b\x32\x31.capiscio.v1.GenerateKeyPairRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xb5\x02\n\x17GenerateKeyPairResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\x12\x1f\n\x0bprivate_key\x18\x03 \x01(\x0cR\nprivateKey\x12$\n\x0epublic_key_pem\x18\x04 \x01(\tR\x0cpublicKeyPem\x12&\n\x0fprivate_key_pem\x18\x05 \x01(\tR\rprivateKeyPem\x12\x37\n\talgorithm\x18\x06 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12#\n\rerror_message\x18\x07 \x01(\tR\x0c\x65rrorMessage\x12\x17\n\x07\x64id_key\x18\x08 \x01(\tR\x06\x64idKey\"}\n\x0eLoadKeyRequest\x12\x1b\n\tfile_path\x18\x01 \x01(\tR\x08\x66ilePath\x12.\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x1e\n\npassphrase\x18\x03 \x01(\tR\npassphrase\"\xae\x01\n\x0fLoadKeyResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x02 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12&\n\x0fhas_private_key\x18\x03 \x01(\x08R\rhasPrivateKey\x12#\n\rerror_message\x18\x04 \x01(\tR\x0c\x65rrorMessage\"\xbf\x01\n\x10\x45xportKeyRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x1b\n\tfile_path\x18\x02 \x01(\tR\x08\x66ilePath\x12.\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\'\n\x0finclude_private\x18\x04 \x01(\x08R\x0eincludePrivate\x12\x1e\n\npassphrase\x18\x05 \x01(\tR\npassphrase\"U\n\x11\x45xportKeyResponse\x12\x1b\n\tfile_path\x18\x01 \x01(\tR\x08\x66ilePath\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"*\n\x11GetKeyInfoRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\"\xb5\x03\n\x12GetKeyInfoResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x02 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12&\n\x0fhas_private_key\x18\x03 \x01(\x08R\rhasPrivateKey\x12\x1d\n\npublic_key\x18\x04 \x01(\x0cR\tpublicKey\x12$\n\x0epublic_key_pem\x18\x05 \x01(\tR\x0cpublicKeyPem\x12\x35\n\ncreated_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\tcreatedAt\x12I\n\x08metadata\x18\x07 \x03(\x0b\x32-.capiscio.v1.GetKeyInfoResponse.MetadataEntryR\x08metadata\x12#\n\rerror_message\x18\x08 \x01(\tR\x0c\x65rrorMessage\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xcf\x02\n\x0bInitRequest\x12\x17\n\x07\x61pi_key\x18\x01 \x01(\tR\x06\x61piKey\x12\x19\n\x08\x61gent_id\x18\x02 \x01(\tR\x07\x61gentId\x12\x1d\n\nserver_url\x18\x03 \x01(\tR\tserverUrl\x12\x1d\n\noutput_dir\x18\x04 \x01(\tR\toutputDir\x12\x14\n\x05\x66orce\x18\x05 \x01(\x08R\x05\x66orce\x12\x37\n\talgorithm\x18\x06 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x42\n\x08metadata\x18\x07 \x03(\x0b\x32&.capiscio.v1.InitRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xa2\x02\n\x0cInitResponse\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x19\n\x08\x61gent_id\x18\x02 \x01(\tR\x07\x61gentId\x12(\n\x10private_key_path\x18\x03 \x01(\tR\x0eprivateKeyPath\x12&\n\x0fpublic_key_path\x18\x04 \x01(\tR\rpublicKeyPath\x12&\n\x0f\x61gent_card_path\x18\x05 \x01(\tR\ragentCardPath\x12&\n\x0f\x61gent_card_json\x18\x06 \x01(\tR\ragentCardJson\x12\x1e\n\nregistered\x18\x07 \x01(\x08R\nregistered\x12#\n\rerror_message\x18\x08 \x01(\tR\x0c\x65rrorMessage*\x8e\x01\n\x0fSignatureFormat\x12 \n\x1cSIGNATURE_FORMAT_UNSPECIFIED\x10\x00\x12 \n\x1cSIGNATURE_FORMAT_JWS_COMPACT\x10\x01\x12\x1d\n\x19SIGNATURE_FORMAT_JWS_JSON\x10\x02\x12\x18\n\x14SIGNATURE_FORMAT_RAW\x10\x03\x32\xc0\x05\n\x12SimpleGuardService\x12;\n\x04Sign\x12\x18.capiscio.v1.SignRequest\x1a\x19.capiscio.v1.SignResponse\x12\x41\n\x06Verify\x12\x1a.capiscio.v1.VerifyRequest\x1a\x1b.capiscio.v1.VerifyResponse\x12S\n\x0cSignAttached\x12 .capiscio.v1.SignAttachedRequest\x1a!.capiscio.v1.SignAttachedResponse\x12Y\n\x0eVerifyAttached\x12\".capiscio.v1.VerifyAttachedRequest\x1a#.capiscio.v1.VerifyAttachedResponse\x12\\\n\x0fGenerateKeyPair\x12#.capiscio.v1.GenerateKeyPairRequest\x1a$.capiscio.v1.GenerateKeyPairResponse\x12\x44\n\x07LoadKey\x12\x1b.capiscio.v1.LoadKeyRequest\x1a\x1c.capiscio.v1.LoadKeyResponse\x12J\n\tExportKey\x12\x1d.capiscio.v1.ExportKeyRequest\x1a\x1e.capiscio.v1.ExportKeyResponse\x12M\n\nGetKeyInfo\x12\x1e.capiscio.v1.GetKeyInfoRequest\x1a\x1f.capiscio.v1.GetKeyInfoResponse\x12;\n\x04Init\x12\x18.capiscio.v1.InitRequest\x1a\x19.capiscio.v1.InitResponseB\xb6\x01\n\x0f\x63om.capiscio.v1B\x10SimpleguardProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py index addf886..80c82ed 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/simpleguard_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import simpleguard_pb2 as capiscio_dot_v1_dot_simpleguard__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import simpleguard_pb2 as capiscio_dot_v1_dot_simpleguard__pb2 class SimpleGuardServiceStub(object): diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py index b63b47a..a286e22 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2.py @@ -22,7 +22,7 @@ _sym_db = _symbol_database.Default() -from capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import common_pb2 as capiscio_dot_v1_dot_common__pb2 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x63\x61piscio/v1/trust.proto\x12\x0b\x63\x61piscio.v1\x1a\x18\x63\x61piscio/v1/common.proto\"\xa7\x03\n\nTrustedKey\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\x12\x37\n\talgorithm\x18\x03 \x01(\x0e\x32\x19.capiscio.v1.KeyAlgorithmR\talgorithm\x12\x1d\n\npublic_key\x18\x04 \x01(\x0cR\tpublicKey\x12.\n\x06\x66ormat\x18\x05 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x31\n\x08\x61\x64\x64\x65\x64_at\x18\x06 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\x07\x61\x64\x64\x65\x64\x41t\x12\x35\n\nexpires_at\x18\x07 \x01(\x0b\x32\x16.capiscio.v1.TimestampR\texpiresAt\x12\x41\n\x08metadata\x18\x08 \x03(\x0b\x32%.capiscio.v1.TrustedKey.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xf3\x01\n\rAddKeyRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\x12.\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\x12\x44\n\x08metadata\x18\x04 \x03(\x0b\x32(.capiscio.v1.AddKeyRequest.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"L\n\x0e\x41\x64\x64KeyResponse\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\";\n\x10RemoveKeyRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\"[\n\x11RemoveKeyResponse\x12!\n\x0ckeys_removed\x18\x01 \x01(\x05R\x0bkeysRemoved\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"8\n\rGetKeyRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\x12\x15\n\x06key_id\x18\x02 \x01(\tR\x05keyId\"`\n\x0eGetKeyResponse\x12)\n\x03key\x18\x01 \x01(\x0b\x32\x17.capiscio.v1.TrustedKeyR\x03key\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\"^\n\x0fListKeysRequest\x12\x1d\n\ndid_filter\x18\x01 \x01(\tR\tdidFilter\x12\x14\n\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n\x06\x63ursor\x18\x03 \x01(\tR\x06\x63ursor\"\x81\x01\n\x10ListKeysResponse\x12+\n\x04keys\x18\x01 \x03(\x0b\x32\x17.capiscio.v1.TrustedKeyR\x04keys\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\tR\nnextCursor\x12\x1f\n\x0btotal_count\x18\x03 \x01(\x05R\ntotalCount\"$\n\x10IsTrustedRequest\x12\x10\n\x03\x64id\x18\x01 \x01(\tR\x03\x64id\"]\n\x11IsTrustedResponse\x12\x1d\n\nis_trusted\x18\x01 \x01(\x08R\tisTrusted\x12)\n\x03key\x18\x02 \x01(\x0b\x32\x17.capiscio.v1.TrustedKeyR\x03key\"a\n\x1aImportFromDirectoryRequest\x12%\n\x0e\x64irectory_path\x18\x01 \x01(\tR\rdirectoryPath\x12\x1c\n\trecursive\x18\x02 \x01(\x08R\trecursive\"}\n\x1bImportFromDirectoryResponse\x12#\n\rkeys_imported\x18\x01 \x01(\x05R\x0ckeysImported\x12!\n\x0ckeys_skipped\x18\x02 \x01(\x05R\x0bkeysSkipped\x12\x16\n\x06\x65rrors\x18\x03 \x03(\tR\x06\x65rrors\"q\n\x18\x45xportToDirectoryRequest\x12%\n\x0e\x64irectory_path\x18\x01 \x01(\tR\rdirectoryPath\x12.\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x16.capiscio.v1.KeyFormatR\x06\x66ormat\"e\n\x19\x45xportToDirectoryResponse\x12#\n\rkeys_exported\x18\x01 \x01(\x05R\x0ckeysExported\x12#\n\rerror_message\x18\x02 \x01(\tR\x0c\x65rrorMessage\",\n\x10\x43learKeysRequest\x12\x18\n\x07\x63onfirm\x18\x01 \x01(\x08R\x07\x63onfirm\"6\n\x11\x43learKeysResponse\x12!\n\x0ckeys_cleared\x18\x01 \x01(\x05R\x0bkeysCleared*\xbc\x01\n\x0cKeyAlgorithm\x12\x1d\n\x19KEY_ALGORITHM_UNSPECIFIED\x10\x00\x12\x19\n\x15KEY_ALGORITHM_ED25519\x10\x01\x12\x1c\n\x18KEY_ALGORITHM_ECDSA_P256\x10\x02\x12\x1c\n\x18KEY_ALGORITHM_ECDSA_P384\x10\x03\x12\x1a\n\x16KEY_ALGORITHM_RSA_2048\x10\x04\x12\x1a\n\x16KEY_ALGORITHM_RSA_4096\x10\x05*c\n\tKeyFormat\x12\x1a\n\x16KEY_FORMAT_UNSPECIFIED\x10\x00\x12\x12\n\x0eKEY_FORMAT_JWK\x10\x01\x12\x12\n\x0eKEY_FORMAT_PEM\x10\x02\x12\x12\n\x0eKEY_FORMAT_DER\x10\x03\x32\x90\x05\n\x11TrustStoreService\x12\x41\n\x06\x41\x64\x64Key\x12\x1a.capiscio.v1.AddKeyRequest\x1a\x1b.capiscio.v1.AddKeyResponse\x12J\n\tRemoveKey\x12\x1d.capiscio.v1.RemoveKeyRequest\x1a\x1e.capiscio.v1.RemoveKeyResponse\x12\x41\n\x06GetKey\x12\x1a.capiscio.v1.GetKeyRequest\x1a\x1b.capiscio.v1.GetKeyResponse\x12G\n\x08ListKeys\x12\x1c.capiscio.v1.ListKeysRequest\x1a\x1d.capiscio.v1.ListKeysResponse\x12J\n\tIsTrusted\x12\x1d.capiscio.v1.IsTrustedRequest\x1a\x1e.capiscio.v1.IsTrustedResponse\x12h\n\x13ImportFromDirectory\x12\'.capiscio.v1.ImportFromDirectoryRequest\x1a(.capiscio.v1.ImportFromDirectoryResponse\x12\x62\n\x11\x45xportToDirectory\x12%.capiscio.v1.ExportToDirectoryRequest\x1a&.capiscio.v1.ExportToDirectoryResponse\x12\x46\n\x05\x43lear\x12\x1d.capiscio.v1.ClearKeysRequest\x1a\x1e.capiscio.v1.ClearKeysResponseB\xb0\x01\n\x0f\x63om.capiscio.v1B\nTrustProtoP\x01ZDgithub.com/capiscio/capiscio-core/pkg/rpc/gen/capiscio/v1;capisciov1\xa2\x02\x03\x43XX\xaa\x02\x0b\x43\x61piscio.V1\xca\x02\x0b\x43\x61piscio\\V1\xe2\x02\x17\x43\x61piscio\\V1\\GPBMetadata\xea\x02\x0c\x43\x61piscio::V1b\x06proto3') diff --git a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py index 73e9e92..e8a62fc 100644 --- a/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py +++ b/capiscio_sdk/_rpc/gen/capiscio/v1/trust_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 +from capiscio_sdk._rpc.gen.capiscio.v1 import trust_pb2 as capiscio_dot_v1_dot_trust__pb2 class TrustStoreServiceStub(object): diff --git a/capiscio_sdk/connect.py b/capiscio_sdk/connect.py index fe70f83..b2dc403 100644 --- a/capiscio_sdk/connect.py +++ b/capiscio_sdk/connect.py @@ -17,7 +17,6 @@ """ import os -import json import logging import httpx from pathlib import Path @@ -69,7 +68,7 @@ def emit(self, event_type: str, data: Dict[str, Any]) -> bool: def get_badge(self) -> Optional[str]: """Get current badge (auto-renewed if needed).""" if self._keeper: - return self._keeper.get_badge() + return self._keeper.get_current_badge() return self.badge def status(self) -> Dict[str, Any]: @@ -379,7 +378,7 @@ def _setup_badge(self): # Start the keeper and get initial badge keeper.start() - badge = keeper.get_badge() + badge = keeper.get_current_badge() expires_at = getattr(keeper, 'badge_expires_at', None) return badge, expires_at, keeper, guard diff --git a/capiscio_sdk/events.py b/capiscio_sdk/events.py index 3a2841a..41325ee 100644 --- a/capiscio_sdk/events.py +++ b/capiscio_sdk/events.py @@ -18,7 +18,6 @@ emitter.emit("task_completed", {"task_id": "123", "output": "..."}) """ -import json import logging import time import uuid From 08a325279d5861e1e03a2bc0d2b529dc1ac38eb0 Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Fri, 6 Feb 2026 00:15:12 +0200 Subject: [PATCH 4/8] test: Add unit tests for connect.py and events.py - Add 32 tests for connect.py (AgentIdentity, CapiscIO.connect, from_env, _Connector) - Add 28 tests for events.py (EventEmitter, global functions) - Improve patch coverage for new Let's Encrypt-style setup feature --- tests/unit/test_connect.py | 472 +++++++++++++++++++++++++++++++++++++ tests/unit/test_events.py | 464 ++++++++++++++++++++++++++++++++++++ 2 files changed, 936 insertions(+) create mode 100644 tests/unit/test_connect.py create mode 100644 tests/unit/test_events.py diff --git a/tests/unit/test_connect.py b/tests/unit/test_connect.py new file mode 100644 index 0000000..0ddcaff --- /dev/null +++ b/tests/unit/test_connect.py @@ -0,0 +1,472 @@ +"""Unit tests for capiscio_sdk.connect module.""" + +import os +import pytest +from pathlib import Path +from unittest.mock import MagicMock, patch, PropertyMock + +from capiscio_sdk.connect import ( + AgentIdentity, + CapiscIO, + _Connector, + DEFAULT_CONFIG_DIR, + DEFAULT_KEYS_DIR, + PROD_REGISTRY, +) + + +class TestAgentIdentity: + """Tests for AgentIdentity dataclass.""" + + def test_init_basic(self): + """Test basic initialization.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + ) + + assert identity.agent_id == "test-agent-123" + assert identity.did == "did:key:z6MkTest" + assert identity.name == "Test Agent" + assert identity.api_key == "sk_test_abc" + assert identity.server_url == "https://registry.capisc.io" + assert identity.keys_dir == Path("/tmp/keys") + assert identity.badge is None + assert identity.badge_expires_at is None + + def test_init_with_badge(self): + """Test initialization with badge.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + badge="eyJhbGciOiJFZERTQSJ9...", + badge_expires_at="2026-02-06T12:00:00Z", + ) + + assert identity.badge == "eyJhbGciOiJFZERTQSJ9..." + assert identity.badge_expires_at == "2026-02-06T12:00:00Z" + + def test_emit_creates_emitter(self): + """Test that emit creates EventEmitter on first call.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + ) + + assert identity._emitter is None + + with patch("capiscio_sdk.events.EventEmitter") as MockEmitter: + mock_instance = MagicMock() + mock_instance.emit.return_value = True + MockEmitter.return_value = mock_instance + + result = identity.emit("test_event", {"key": "value"}) + + MockEmitter.assert_called_once_with( + server_url="https://registry.capisc.io", + api_key="sk_test_abc", + agent_id="test-agent-123", + ) + mock_instance.emit.assert_called_once_with("test_event", {"key": "value"}) + assert result is True + + def test_emit_reuses_emitter(self): + """Test that emit reuses existing EventEmitter.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + ) + + mock_emitter = MagicMock() + mock_emitter.emit.return_value = True + identity._emitter = mock_emitter + + identity.emit("event1", {}) + identity.emit("event2", {}) + + assert mock_emitter.emit.call_count == 2 + + def test_get_badge_with_keeper(self): + """Test get_badge delegates to keeper.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + badge="old-badge", + ) + + mock_keeper = MagicMock() + mock_keeper.get_current_badge.return_value = "new-badge-from-keeper" + identity._keeper = mock_keeper + + result = identity.get_badge() + + mock_keeper.get_current_badge.assert_called_once() + assert result == "new-badge-from-keeper" + + def test_get_badge_without_keeper(self): + """Test get_badge returns stored badge when no keeper.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + badge="stored-badge", + ) + + result = identity.get_badge() + + assert result == "stored-badge" + + def test_status(self): + """Test status returns correct dict.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + badge="test-badge", + badge_expires_at="2026-02-06T12:00:00Z", + ) + + status = identity.status() + + assert status == { + "agent_id": "test-agent-123", + "did": "did:key:z6MkTest", + "name": "Test Agent", + "server": "https://registry.capisc.io", + "badge_valid": True, + "badge_expires_at": "2026-02-06T12:00:00Z", + } + + def test_status_no_badge(self): + """Test status with no badge.""" + identity = AgentIdentity( + agent_id="test-agent-123", + did="did:key:z6MkTest", + name="Test Agent", + api_key="sk_test_abc", + server_url="https://registry.capisc.io", + keys_dir=Path("/tmp/keys"), + ) + + status = identity.status() + + assert status["badge_valid"] is False + assert status["badge_expires_at"] is None + + +class TestCapiscIOConnect: + """Tests for CapiscIO.connect() class method.""" + + def test_connect_calls_connector(self): + """Test that connect creates and runs _Connector.""" + with patch("capiscio_sdk.connect._Connector") as MockConnector: + mock_instance = MagicMock() + mock_identity = AgentIdentity( + agent_id="test-123", + did="did:key:z6MkTest", + name="Test", + api_key="sk_test_abc", + server_url=PROD_REGISTRY, + keys_dir=Path("/tmp/keys"), + ) + mock_instance.connect.return_value = mock_identity + MockConnector.return_value = mock_instance + + result = CapiscIO.connect( + api_key="sk_test_abc", + name="Test Agent", + server_url="https://custom.server.com", + ) + + MockConnector.assert_called_once_with( + api_key="sk_test_abc", + name="Test Agent", + agent_id=None, + server_url="https://custom.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + mock_instance.connect.assert_called_once() + assert result == mock_identity + + +class TestCapiscIOFromEnv: + """Tests for CapiscIO.from_env() class method.""" + + def test_from_env_requires_api_key(self): + """Test that from_env raises without CAPISCIO_API_KEY.""" + with patch.dict(os.environ, {}, clear=True): + # Remove the key if it exists + os.environ.pop("CAPISCIO_API_KEY", None) + + with pytest.raises(ValueError, match="CAPISCIO_API_KEY environment variable is required"): + CapiscIO.from_env() + + def test_from_env_reads_env_vars(self): + """Test that from_env reads all environment variables.""" + env_vars = { + "CAPISCIO_API_KEY": "sk_test_env", + "CAPISCIO_AGENT_ID": "env-agent-id", + "CAPISCIO_AGENT_NAME": "Env Agent", + "CAPISCIO_SERVER_URL": "https://env.server.com", + "CAPISCIO_DEV_MODE": "true", + } + + with patch.dict(os.environ, env_vars, clear=False): + with patch.object(CapiscIO, "connect") as mock_connect: + mock_connect.return_value = MagicMock() + + CapiscIO.from_env() + + mock_connect.assert_called_once_with( + api_key="sk_test_env", + agent_id="env-agent-id", + name="Env Agent", + server_url="https://env.server.com", + dev_mode=True, + ) + + def test_from_env_defaults(self): + """Test from_env uses defaults for missing optional vars.""" + with patch.dict(os.environ, {"CAPISCIO_API_KEY": "sk_test_only"}, clear=False): + # Clear optional vars + for var in ["CAPISCIO_AGENT_ID", "CAPISCIO_AGENT_NAME", "CAPISCIO_SERVER_URL", "CAPISCIO_DEV_MODE"]: + os.environ.pop(var, None) + + with patch.object(CapiscIO, "connect") as mock_connect: + mock_connect.return_value = MagicMock() + + CapiscIO.from_env() + + mock_connect.assert_called_once_with( + api_key="sk_test_only", + agent_id=None, + name=None, + server_url=PROD_REGISTRY, + dev_mode=False, + ) + + @pytest.mark.parametrize("dev_mode_value,expected", [ + ("true", True), + ("True", True), + ("TRUE", True), + ("1", True), + ("yes", True), + ("Yes", True), + ("false", False), + ("0", False), + ("no", False), + ("", False), + ]) + def test_from_env_dev_mode_parsing(self, dev_mode_value, expected): + """Test dev_mode parsing from various string values.""" + with patch.dict(os.environ, { + "CAPISCIO_API_KEY": "sk_test", + "CAPISCIO_DEV_MODE": dev_mode_value, + }, clear=False): + with patch.object(CapiscIO, "connect") as mock_connect: + mock_connect.return_value = MagicMock() + + CapiscIO.from_env() + + call_kwargs = mock_connect.call_args[1] + assert call_kwargs["dev_mode"] == expected + + +class TestConnector: + """Tests for _Connector internal class.""" + + def test_init(self): + """Test _Connector initialization.""" + connector = _Connector( + api_key="sk_test_abc", + name="Test Agent", + agent_id="test-123", + server_url="https://test.server.com", + keys_dir=Path("/custom/keys"), + auto_badge=True, + dev_mode=False, + ) + + assert connector.api_key == "sk_test_abc" + assert connector.name == "Test Agent" + assert connector.agent_id == "test-123" + assert connector.server_url == "https://test.server.com" + assert connector.keys_dir == Path("/custom/keys") + assert connector.auto_badge is True + assert connector.dev_mode is False + + def test_init_strips_trailing_slash(self): + """Test that server_url trailing slash is stripped.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id=None, + server_url="https://test.server.com/", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + assert connector.server_url == "https://test.server.com" + + def test_ensure_agent_with_agent_id(self): + """Test _ensure_agent fetches specific agent.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id="specific-agent-id", + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = {"data": {"id": "specific-agent-id", "name": "My Agent"}} + connector._client.get = MagicMock(return_value=mock_response) + + result = connector._ensure_agent() + + connector._client.get.assert_called_once_with("/v1/agents/specific-agent-id") + assert result == {"id": "specific-agent-id", "name": "My Agent"} + + def test_ensure_agent_not_found(self): + """Test _ensure_agent raises on 404.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id="missing-agent", + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 404 + connector._client.get = MagicMock(return_value=mock_response) + + with pytest.raises(ValueError, match="Agent missing-agent not found"): + connector._ensure_agent() + + def test_ensure_agent_lists_and_finds_by_name(self): + """Test _ensure_agent finds agent by name.""" + connector = _Connector( + api_key="sk_test", + name="Target Agent", + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + "data": [ + {"id": "agent-1", "name": "Other Agent"}, + {"id": "agent-2", "name": "Target Agent"}, + ] + } + connector._client.get = MagicMock(return_value=mock_response) + + result = connector._ensure_agent() + + assert result == {"id": "agent-2", "name": "Target Agent"} + + def test_ensure_agent_uses_first_when_no_name(self): + """Test _ensure_agent uses first agent when no name specified.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + "data": [ + {"id": "first-agent", "name": "First"}, + {"id": "second-agent", "name": "Second"}, + ] + } + connector._client.get = MagicMock(return_value=mock_response) + + result = connector._ensure_agent() + + assert result == {"id": "first-agent", "name": "First"} + + def test_create_agent(self): + """Test _create_agent creates new agent.""" + connector = _Connector( + api_key="sk_test", + name="New Agent", + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 201 + mock_response.json.return_value = {"data": {"id": "new-agent-id", "name": "New Agent"}} + connector._client.post = MagicMock(return_value=mock_response) + + result = connector._create_agent() + + connector._client.post.assert_called_once_with("/v1/agents", json={ + "name": "New Agent", + "protocol": "a2a", + }) + assert result == {"id": "new-agent-id", "name": "New Agent"} + + +class TestDefaultPaths: + """Tests for default path constants.""" + + def test_default_config_dir(self): + """Test DEFAULT_CONFIG_DIR is in home directory.""" + assert DEFAULT_CONFIG_DIR == Path.home() / ".capiscio" + + def test_default_keys_dir(self): + """Test DEFAULT_KEYS_DIR is under config dir.""" + assert DEFAULT_KEYS_DIR == Path.home() / ".capiscio" / "keys" + + def test_prod_registry(self): + """Test PROD_REGISTRY constant.""" + assert PROD_REGISTRY == "https://registry.capisc.io" diff --git a/tests/unit/test_events.py b/tests/unit/test_events.py new file mode 100644 index 0000000..aa7a724 --- /dev/null +++ b/tests/unit/test_events.py @@ -0,0 +1,464 @@ +"""Unit tests for capiscio_sdk.events module.""" + +import pytest +import time +from datetime import datetime, timezone +from unittest.mock import MagicMock, patch + +from capiscio_sdk.events import ( + EventEmitter, + init, + emit, + flush, + _global_emitter, +) + + +class TestEventEmitter: + """Tests for EventEmitter class.""" + + def test_init_basic(self): + """Test basic initialization.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test_abc", + agent_id="test-agent-123", + ) + + assert emitter.server_url == "https://registry.capisc.io" + assert emitter.api_key == "sk_test_abc" + assert emitter.agent_id == "test-agent-123" + assert emitter.enabled is True + assert emitter.batch_size == 10 + assert emitter.flush_interval == 5.0 + + def test_init_strips_trailing_slash(self): + """Test that trailing slash is stripped from server_url.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io/", + api_key="sk_test", + agent_id="test", + ) + + assert emitter.server_url == "https://registry.capisc.io" + + def test_init_disabled_without_api_key(self): + """Test that emitter is disabled without API key.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key=None, + agent_id="test", + ) + + assert emitter.enabled is False + + def test_init_custom_settings(self): + """Test initialization with custom settings.""" + emitter = EventEmitter( + server_url="https://custom.server.com", + api_key="sk_test", + agent_id="test", + agent_name="Custom Agent", + batch_size=5, + flush_interval=10.0, + enabled=False, + ) + + assert emitter.batch_size == 5 + assert emitter.flush_interval == 10.0 + assert emitter.enabled is False + assert emitter.agent_name == "Custom Agent" + + def test_emit_disabled_returns_false(self): + """Test that emit returns False when disabled.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test", + enabled=False, + ) + + result = emitter.emit("test_event", {"key": "value"}) + + assert result is False + assert len(emitter._batch) == 0 + + def test_emit_adds_to_batch(self): + """Test that emit adds event to batch.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + batch_size=10, + ) + + result = emitter.emit("test_event", {"key": "value"}) + + assert result is True + assert len(emitter._batch) == 1 + + event = emitter._batch[0] + assert event["type"] == "test_event" + assert event["agentId"] == "test-agent" + assert event["data"] == {"key": "value"} + assert "id" in event + assert "timestamp" in event + + def test_emit_with_task_id(self): + """Test emit with task_id.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + emitter.emit("test_event", {}, task_id="task-123") + + assert emitter._batch[0]["taskId"] == "task-123" + + def test_emit_with_correlation_id(self): + """Test emit with correlation_id.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + emitter.emit("test_event", {}, correlation_id="corr-456") + + assert emitter._batch[0]["correlationId"] == "corr-456" + + def test_emit_flushes_when_batch_full(self): + """Test that emit flushes when batch is full.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + batch_size=2, + ) + + with patch.object(emitter, "flush", return_value=True) as mock_flush: + emitter.emit("event1", {}) + mock_flush.assert_not_called() + + emitter.emit("event2", {}) + mock_flush.assert_called_once() + + def test_emit_with_flush_flag(self): + """Test emit with flush=True.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "flush", return_value=True) as mock_flush: + emitter.emit("test_event", {}, flush=True) + mock_flush.assert_called_once() + + def test_flush_empty_batch(self): + """Test flush with empty batch.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + result = emitter.flush() + + assert result is True + + def test_flush_sends_events(self): + """Test flush sends events to server.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + # Add events directly to batch + emitter._batch = [ + {"id": "1", "type": "event1", "data": {}}, + {"id": "2", "type": "event2", "data": {}}, + ] + + mock_response = MagicMock() + mock_response.status_code = 200 + + with patch.object(emitter._client, "post", return_value=mock_response) as mock_post: + result = emitter.flush() + + assert result is True + assert len(emitter._batch) == 0 + mock_post.assert_called_once() + + call_kwargs = mock_post.call_args[1] + assert call_kwargs["json"]["events"] == [ + {"id": "1", "type": "event1", "data": {}}, + {"id": "2", "type": "event2", "data": {}}, + ] + assert call_kwargs["headers"]["X-Capiscio-Registry-Key"] == "sk_test" + + def test_flush_requeues_on_failure(self): + """Test that flush requeues events on server error.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + events = [{"id": "1", "type": "event1", "data": {}}] + emitter._batch = events.copy() + + mock_response = MagicMock() + mock_response.status_code = 500 + mock_response.text = "Internal Server Error" + + with patch.object(emitter._client, "post", return_value=mock_response): + result = emitter.flush() + + assert result is False + assert len(emitter._batch) == 1 # Events requeued + + def test_flush_requeues_on_exception(self): + """Test that flush requeues events on exception.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + emitter._batch = [{"id": "1", "type": "event1", "data": {}}] + + with patch.object(emitter._client, "post", side_effect=Exception("Network error")): + result = emitter.flush() + + assert result is False + assert len(emitter._batch) == 1 + + def test_flush_disabled(self): + """Test flush when disabled clears batch.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + enabled=False, + ) + + # Manually add event (bypassing emit's disabled check) + emitter._batch = [{"id": "1", "type": "event1", "data": {}}] + + result = emitter.flush() + + assert result is False + assert len(emitter._batch) == 0 + + def test_task_started(self): + """Test task_started convenience method.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "emit", return_value=True) as mock_emit: + emitter.task_started("task-123", "Process data", extra="info") + + mock_emit.assert_called_once_with( + EventEmitter.EVENT_TASK_STARTED, + {"input": "Process data", "extra": "info"}, + task_id="task-123", + flush=True, + ) + + def test_task_completed(self): + """Test task_completed convenience method.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "emit", return_value=True) as mock_emit: + emitter.task_completed("task-123", "Result data") + + mock_emit.assert_called_once_with( + EventEmitter.EVENT_TASK_COMPLETED, + {"output": "Result data"}, + task_id="task-123", + flush=True, + ) + + def test_task_failed(self): + """Test task_failed convenience method.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "emit", return_value=True) as mock_emit: + emitter.task_failed("task-123", "Error message") + + mock_emit.assert_called_once_with( + EventEmitter.EVENT_TASK_FAILED, + {"error": "Error message"}, + task_id="task-123", + flush=True, + ) + + def test_tool_call(self): + """Test tool_call convenience method.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "emit", return_value=True) as mock_emit: + emitter.tool_call("search", {"query": "test"}, task_id="task-123") + + mock_emit.assert_called_once_with( + EventEmitter.EVENT_TOOL_CALL, + {"tool": "search", "arguments": {"query": "test"}}, + task_id="task-123", + ) + + def test_tool_result(self): + """Test tool_result convenience method.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "emit", return_value=True) as mock_emit: + emitter.tool_result("search", ["result1", "result2"]) + + mock_emit.assert_called_once_with( + EventEmitter.EVENT_TOOL_RESULT, + {"tool": "search", "result": ["result1", "result2"]}, + task_id=None, + ) + + def test_close_flushes_and_closes(self): + """Test close flushes and closes client.""" + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "flush") as mock_flush: + with patch.object(emitter._client, "close") as mock_close: + emitter.close() + + mock_flush.assert_called_once() + mock_close.assert_called_once() + + def test_context_manager(self): + """Test context manager usage.""" + with patch("capiscio_sdk.events.httpx.Client"): + emitter = EventEmitter( + server_url="https://registry.capisc.io", + api_key="sk_test", + agent_id="test-agent", + ) + + with patch.object(emitter, "close") as mock_close: + with emitter as e: + assert e is emitter + + mock_close.assert_called_once() + + def test_event_type_constants(self): + """Test event type constants.""" + assert EventEmitter.EVENT_TASK_STARTED == "task_started" + assert EventEmitter.EVENT_TASK_COMPLETED == "task_completed" + assert EventEmitter.EVENT_TASK_FAILED == "task_failed" + assert EventEmitter.EVENT_TOOL_CALL == "tool_call" + assert EventEmitter.EVENT_TOOL_RESULT == "tool_result" + assert EventEmitter.EVENT_LLM_CALL == "llm_call" + assert EventEmitter.EVENT_LLM_RESPONSE == "llm_response" + assert EventEmitter.EVENT_AGENT_STARTED == "agent_started" + assert EventEmitter.EVENT_AGENT_STOPPED == "agent_stopped" + assert EventEmitter.EVENT_ERROR == "error" + assert EventEmitter.EVENT_WARNING == "warning" + assert EventEmitter.EVENT_INFO == "info" + + +class TestGlobalFunctions: + """Tests for global event functions.""" + + def test_init_creates_global_emitter(self): + """Test init creates global emitter.""" + import capiscio_sdk.events as events_module + + # Reset global emitter + events_module._global_emitter = None + + result = init( + api_key="sk_test", + agent_id="test-agent", + server_url="https://test.server.com", + ) + + assert result is events_module._global_emitter + assert isinstance(result, EventEmitter) + assert result.api_key == "sk_test" + assert result.agent_id == "test-agent" + + # Cleanup + events_module._global_emitter = None + + def test_emit_without_init_raises(self): + """Test emit raises without init.""" + import capiscio_sdk.events as events_module + + # Reset global emitter + events_module._global_emitter = None + + with pytest.raises(RuntimeError, match="Event emitter not initialized"): + emit("test_event", {}) + + def test_emit_with_init(self): + """Test emit works after init.""" + import capiscio_sdk.events as events_module + + # Initialize + events_module._global_emitter = None + init(api_key="sk_test", agent_id="test-agent", enabled=False) + + # Should not raise (even though disabled) + result = emit("test_event", {"key": "value"}) + + assert result is False # Disabled, so returns False + + # Cleanup + events_module._global_emitter = None + + def test_flush_without_init(self): + """Test flush returns False without init.""" + import capiscio_sdk.events as events_module + + events_module._global_emitter = None + + result = flush() + + assert result is False + + def test_flush_with_init(self): + """Test flush works after init.""" + import capiscio_sdk.events as events_module + + events_module._global_emitter = None + emitter = init(api_key="sk_test", agent_id="test-agent") + + with patch.object(emitter, "flush", return_value=True) as mock_flush: + result = flush() + + mock_flush.assert_called_once() + assert result is True + + # Cleanup + events_module._global_emitter = None From 46d87581162082e2163fc301b8a1cc71dd9d1555 Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Fri, 6 Feb 2026 00:17:49 +0200 Subject: [PATCH 5/8] fix: Correct patch path in test_connect_calls_connector --- tests/unit/test_connect.py | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/unit/test_connect.py b/tests/unit/test_connect.py index 0ddcaff..c2fccb9 100644 --- a/tests/unit/test_connect.py +++ b/tests/unit/test_connect.py @@ -185,36 +185,36 @@ class TestCapiscIOConnect: def test_connect_calls_connector(self): """Test that connect creates and runs _Connector.""" - with patch("capiscio_sdk.connect._Connector") as MockConnector: - mock_instance = MagicMock() - mock_identity = AgentIdentity( - agent_id="test-123", - did="did:key:z6MkTest", - name="Test", - api_key="sk_test_abc", - server_url=PROD_REGISTRY, - keys_dir=Path("/tmp/keys"), - ) - mock_instance.connect.return_value = mock_identity - MockConnector.return_value = mock_instance - - result = CapiscIO.connect( - api_key="sk_test_abc", - name="Test Agent", - server_url="https://custom.server.com", - ) - - MockConnector.assert_called_once_with( - api_key="sk_test_abc", - name="Test Agent", - agent_id=None, - server_url="https://custom.server.com", - keys_dir=None, - auto_badge=True, - dev_mode=False, - ) - mock_instance.connect.assert_called_once() - assert result == mock_identity + # Patch the _Connector class where it's defined in the module + with patch.object(_Connector, "__init__", return_value=None) as mock_init: + with patch.object(_Connector, "connect") as mock_connect: + mock_identity = AgentIdentity( + agent_id="test-123", + did="did:key:z6MkTest", + name="Test", + api_key="sk_test_abc", + server_url=PROD_REGISTRY, + keys_dir=Path("/tmp/keys"), + ) + mock_connect.return_value = mock_identity + + result = CapiscIO.connect( + api_key="sk_test_abc", + name="Test Agent", + server_url="https://custom.server.com", + ) + + mock_init.assert_called_once_with( + api_key="sk_test_abc", + name="Test Agent", + agent_id=None, + server_url="https://custom.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + mock_connect.assert_called_once() + assert result == mock_identity class TestCapiscIOFromEnv: From 1fa6edd5e6e3f7e1ebf75eac39440f13a8066ddc Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Fri, 6 Feb 2026 00:24:20 +0200 Subject: [PATCH 6/8] test: Add comprehensive tests for connect.py coverage - Add tests for full connect() flow with/without badge - Add tests for _ensure_agent error paths - Add tests for _create_agent edge cases - Add tests for _init_identity with RPC and existing files - Add tests for _setup_badge success and failure - Coverage improved from 63% to 99% for connect.py --- tests/unit/test_connect.py | 343 +++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) diff --git a/tests/unit/test_connect.py b/tests/unit/test_connect.py index c2fccb9..bf55320 100644 --- a/tests/unit/test_connect.py +++ b/tests/unit/test_connect.py @@ -9,6 +9,7 @@ AgentIdentity, CapiscIO, _Connector, + ConfigurationError, DEFAULT_CONFIG_DIR, DEFAULT_KEYS_DIR, PROD_REGISTRY, @@ -455,6 +456,348 @@ def test_create_agent(self): }) assert result == {"id": "new-agent-id", "name": "New Agent"} + def test_ensure_agent_fetch_error(self): + """Test _ensure_agent raises on server error.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id="some-agent", + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 500 + mock_response.text = "Internal Server Error" + connector._client.get = MagicMock(return_value=mock_response) + + with pytest.raises(RuntimeError, match="Failed to fetch agent"): + connector._ensure_agent() + + def test_ensure_agent_list_error(self): + """Test _ensure_agent raises when listing fails.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 500 + mock_response.text = "Failed to list" + connector._client.get = MagicMock(return_value=mock_response) + + with pytest.raises(RuntimeError, match="Failed to list agents"): + connector._ensure_agent() + + def test_ensure_agent_creates_when_empty(self): + """Test _ensure_agent creates agent when list is empty.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + # First call returns empty list, second call creates + list_response = MagicMock() + list_response.status_code = 200 + list_response.json.return_value = {"data": []} + + create_response = MagicMock() + create_response.status_code = 201 + create_response.json.return_value = {"data": {"id": "new-id", "name": "New"}} + + connector._client.get = MagicMock(return_value=list_response) + connector._client.post = MagicMock(return_value=create_response) + + result = connector._ensure_agent() + + assert result == {"id": "new-id", "name": "New"} + connector._client.post.assert_called_once() + + def test_create_agent_generates_name(self): + """Test _create_agent generates name when not provided.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 201 + mock_response.json.return_value = {"data": {"id": "new-id", "name": "Agent-abc123"}} + connector._client.post = MagicMock(return_value=mock_response) + + result = connector._create_agent() + + # Name should start with "Agent-" + call_args = connector._client.post.call_args + assert call_args[1]["json"]["name"].startswith("Agent-") + + def test_create_agent_failure(self): + """Test _create_agent raises on failure.""" + connector = _Connector( + api_key="sk_test", + name="Test", + agent_id=None, + server_url="https://test.server.com", + keys_dir=None, + auto_badge=True, + dev_mode=False, + ) + + mock_response = MagicMock() + mock_response.status_code = 400 + mock_response.text = "Bad request" + connector._client.post = MagicMock(return_value=mock_response) + + with pytest.raises(RuntimeError, match="Failed to create agent"): + connector._create_agent() + + def test_connect_full_flow(self, tmp_path): + """Test connect() executes full flow.""" + connector = _Connector( + api_key="sk_test", + name="Test Agent", + agent_id=None, + server_url="https://test.server.com", + keys_dir=tmp_path / "keys", + auto_badge=False, # Skip badge setup for simplicity + dev_mode=False, + ) + + # Mock _ensure_agent + connector._ensure_agent = MagicMock(return_value={ + "id": "agent-123", + "name": "Test Agent", + }) + + # Mock _init_identity + connector._init_identity = MagicMock(return_value="did:key:z6MkTest") + + result = connector.connect() + + assert result.agent_id == "agent-123" + assert result.did == "did:key:z6MkTest" + assert result.name == "Test Agent" + assert result.keys_dir == tmp_path / "keys" + connector._ensure_agent.assert_called_once() + connector._init_identity.assert_called_once() + + def test_connect_with_auto_badge(self, tmp_path): + """Test connect() sets up badge when auto_badge=True.""" + connector = _Connector( + api_key="sk_test", + name="Test Agent", + agent_id=None, + server_url="https://test.server.com", + keys_dir=tmp_path / "keys", + auto_badge=True, + dev_mode=False, + ) + + connector._ensure_agent = MagicMock(return_value={ + "id": "agent-123", + "name": "Test Agent", + }) + connector._init_identity = MagicMock(return_value="did:key:z6MkTest") + connector._setup_badge = MagicMock(return_value=( + "badge-jwt", + "2026-12-31T00:00:00Z", + MagicMock(), # keeper + MagicMock(), # guard + )) + + result = connector.connect() + + assert result.badge == "badge-jwt" + assert result.badge_expires_at == "2026-12-31T00:00:00Z" + connector._setup_badge.assert_called_once() + + def test_connect_skips_badge_in_dev_mode(self, tmp_path): + """Test connect() skips badge in dev_mode.""" + connector = _Connector( + api_key="sk_test", + name="Test Agent", + agent_id=None, + server_url="https://test.server.com", + keys_dir=tmp_path / "keys", + auto_badge=True, + dev_mode=True, # Dev mode should skip badge + ) + + connector._ensure_agent = MagicMock(return_value={ + "id": "agent-123", + "name": "Test Agent", + }) + connector._init_identity = MagicMock(return_value="did:key:z6MkTest") + connector._setup_badge = MagicMock() + + result = connector.connect() + + assert result.badge is None + connector._setup_badge.assert_not_called() + + def test_connect_generates_name_from_id(self, tmp_path): + """Test connect() generates name from agent ID when missing.""" + connector = _Connector( + api_key="sk_test", + name=None, + agent_id=None, + server_url="https://test.server.com", + keys_dir=tmp_path / "keys", + auto_badge=False, + dev_mode=False, + ) + + connector._ensure_agent = MagicMock(return_value={ + "id": "agent-123456789", + "name": None, # No name from server + }) + connector._init_identity = MagicMock(return_value="did:key:z6MkTest") + + result = connector.connect() + + # Should generate name from first 8 chars of ID + assert result.name == "Agent-agent-12" + + def test_init_identity_uses_existing(self, tmp_path): + """Test _init_identity returns existing DID if files exist.""" + connector = _Connector( + api_key="sk_test", + name="Test", + agent_id="agent-123", + server_url="https://test.server.com", + keys_dir=tmp_path, + auto_badge=False, + dev_mode=False, + ) + + # Create existing identity files + (tmp_path / "did.txt").write_text("did:key:z6MkExisting") + (tmp_path / "private.jwk").write_text('{"kty":"OKP"}') + + result = connector._init_identity() + + assert result == "did:key:z6MkExisting" + + def test_init_identity_calls_rpc(self, tmp_path): + """Test _init_identity calls capiscio-core RPC.""" + from capiscio_sdk.connect import ConfigurationError + + connector = _Connector( + api_key="sk_test", + name="Test", + agent_id="agent-123", + server_url="https://test.server.com", + keys_dir=tmp_path, + auto_badge=False, + dev_mode=False, + ) + + mock_rpc = MagicMock() + mock_rpc.simpleguard.init.return_value = ( + {"did": "did:key:z6MkNew", "registered": True}, + None, + ) + + with patch("capiscio_sdk.connect.CapiscioRPCClient", return_value=mock_rpc): + result = connector._init_identity() + + assert result == "did:key:z6MkNew" + mock_rpc.connect.assert_called_once() + mock_rpc.simpleguard.init.assert_called_once_with( + api_key="sk_test", + agent_id="agent-123", + server_url="https://test.server.com", + output_dir=str(tmp_path), + force=False, + ) + + def test_init_identity_rpc_error(self, tmp_path): + """Test _init_identity raises on RPC error.""" + from capiscio_sdk.connect import ConfigurationError + + connector = _Connector( + api_key="sk_test", + name="Test", + agent_id="agent-123", + server_url="https://test.server.com", + keys_dir=tmp_path, + auto_badge=False, + dev_mode=False, + ) + + mock_rpc = MagicMock() + mock_rpc.simpleguard.init.return_value = (None, "RPC failed") + + with patch("capiscio_sdk.connect.CapiscioRPCClient", return_value=mock_rpc): + with pytest.raises(ConfigurationError, match="Failed to initialize identity"): + connector._init_identity() + + def test_setup_badge_success(self, tmp_path): + """Test _setup_badge sets up keeper and guard.""" + connector = _Connector( + api_key="sk_test", + name="Test", + agent_id="agent-123", + server_url="https://test.server.com", + keys_dir=tmp_path, + auto_badge=True, + dev_mode=False, + ) + + mock_keeper = MagicMock() + mock_keeper.get_current_badge.return_value = "badge-jwt" + mock_keeper.badge_expires_at = "2026-12-31T00:00:00Z" + + mock_guard = MagicMock() + + with patch("capiscio_sdk.badge_keeper.BadgeKeeper", return_value=mock_keeper): + with patch("capiscio_sdk.simple_guard.SimpleGuard", return_value=mock_guard): + badge, expires, keeper, guard = connector._setup_badge() + + assert badge == "badge-jwt" + assert expires == "2026-12-31T00:00:00Z" + assert keeper == mock_keeper + assert guard == mock_guard + mock_keeper.start.assert_called_once() + mock_keeper.get_current_badge.assert_called_once() + + def test_setup_badge_failure_continues(self, tmp_path): + """Test _setup_badge returns None on failure without raising.""" + connector = _Connector( + api_key="sk_test", + name="Test", + agent_id="agent-123", + server_url="https://test.server.com", + keys_dir=tmp_path, + auto_badge=True, + dev_mode=False, + ) + + with patch("capiscio_sdk.badge_keeper.BadgeKeeper", side_effect=Exception("Setup failed")): + badge, expires, keeper, guard = connector._setup_badge() + + assert badge is None + assert expires is None + assert keeper is None + assert guard is None + class TestDefaultPaths: """Tests for default path constants.""" From 9e6c3d743540a9d3cb9120302cbcd1af8f06e885 Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Fri, 6 Feb 2026 00:32:55 +0200 Subject: [PATCH 7/8] fix: Address Copilot review comments for thread safety and resource cleanup - connect.py: Add AgentIdentity.close() for resource cleanup - connect.py: Add finally block in connect() to close httpx/gRPC clients - connect.py: Sanitize error messages to not expose internal RPC details - connect.py: Fix badge_expires_at attribute access with hasattr - events.py: Add threading.Lock for thread-safe batch operations - events.py: Wrap emit() and flush() batch access with _batch_lock - test_connect.py: Remove unused PropertyMock import - test_events.py: Remove unused imports (time, datetime, timezone, _global_emitter) --- capiscio_sdk/connect.py | 117 ++++++++++++++++++++++++------------- capiscio_sdk/events.py | 22 ++++--- tests/unit/test_connect.py | 2 +- tests/unit/test_events.py | 3 - 4 files changed, 92 insertions(+), 52 deletions(-) diff --git a/capiscio_sdk/connect.py b/capiscio_sdk/connect.py index b2dc403..c731027 100644 --- a/capiscio_sdk/connect.py +++ b/capiscio_sdk/connect.py @@ -81,6 +81,25 @@ def status(self) -> Dict[str, Any]: "badge_valid": self.badge is not None, "badge_expires_at": self.badge_expires_at, } + + def close(self) -> None: + """Clean up resources.""" + if self._emitter: + self._emitter.close() + self._emitter = None + if self._keeper: + try: + self._keeper.stop() + except Exception: + pass + self._keeper = None + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + return False class CapiscIO: @@ -215,45 +234,54 @@ def connect(self) -> AgentIdentity: """Execute the full connection flow.""" logger.info("Connecting to CapiscIO...") - # Step 1: Find or create agent - agent_data = self._ensure_agent() - self.agent_id = agent_data["id"] - self.name = agent_data.get("name") or self.name or f"Agent-{self.agent_id[:8]}" - - logger.info(f"Agent: {self.name} ({self.agent_id})") - - # Step 2: Set up keys directory - if not self.keys_dir: - self.keys_dir = DEFAULT_KEYS_DIR / self.agent_id - self.keys_dir.mkdir(parents=True, exist_ok=True) - - # Step 3: Initialize identity via capiscio-core Init RPC (one call does everything) - did = self._init_identity() - logger.info(f"DID: {did}") - - # Step 4: Set up badge (if auto_badge) - badge = None - badge_expires_at = None - keeper = None - guard = None - - if self.auto_badge and not self.dev_mode: - badge, badge_expires_at, keeper, guard = self._setup_badge() - if badge: - logger.info(f"Badge acquired (expires: {badge_expires_at})") - - return AgentIdentity( - agent_id=self.agent_id, - did=did, - name=self.name, - api_key=self.api_key, - server_url=self.server_url, - keys_dir=self.keys_dir, - badge=badge, - badge_expires_at=badge_expires_at, - _guard=guard, - _keeper=keeper, - ) + try: + # Step 1: Find or create agent + agent_data = self._ensure_agent() + self.agent_id = agent_data["id"] + self.name = agent_data.get("name") or self.name or f"Agent-{self.agent_id[:8]}" + + logger.info(f"Agent: {self.name} ({self.agent_id})") + + # Step 2: Set up keys directory + if not self.keys_dir: + self.keys_dir = DEFAULT_KEYS_DIR / self.agent_id + self.keys_dir.mkdir(parents=True, exist_ok=True) + + # Step 3: Initialize identity via capiscio-core Init RPC (one call does everything) + did = self._init_identity() + logger.info(f"DID: {did}") + + # Step 4: Set up badge (if auto_badge) + badge = None + badge_expires_at = None + keeper = None + guard = None + + if self.auto_badge and not self.dev_mode: + badge, badge_expires_at, keeper, guard = self._setup_badge() + if badge: + logger.info(f"Badge acquired (expires: {badge_expires_at})") + + return AgentIdentity( + agent_id=self.agent_id, + did=did, + name=self.name, + api_key=self.api_key, + server_url=self.server_url, + keys_dir=self.keys_dir, + badge=badge, + badge_expires_at=badge_expires_at, + _guard=guard, + _keeper=keeper, + ) + finally: + # Clean up clients to avoid resource leaks + if self._rpc_client: + try: + self._rpc_client.close() + except Exception: + pass + self._client.close() def _ensure_agent(self) -> Dict[str, Any]: """Find existing agent or create new one.""" @@ -341,7 +369,9 @@ def _init_identity(self) -> str: ) if error: - raise ConfigurationError(f"Failed to initialize identity: {error}") + # Log detailed error for debugging, but avoid exposing it in the exception + logger.error(f"Init RPC failed during identity initialization: {error}") + raise ConfigurationError("Failed to initialize identity. Check logs for details.") did = result["did"] @@ -379,7 +409,12 @@ def _setup_badge(self): # Start the keeper and get initial badge keeper.start() badge = keeper.get_current_badge() - expires_at = getattr(keeper, 'badge_expires_at', None) + # Get expiration from keeper if available, otherwise None + expires_at = None + if hasattr(keeper, 'badge_expires_at'): + expires_at = keeper.badge_expires_at + elif hasattr(keeper, 'get_badge_expiration'): + expires_at = keeper.get_badge_expiration() return badge, expires_at, keeper, guard diff --git a/capiscio_sdk/events.py b/capiscio_sdk/events.py index 41325ee..ec296f2 100644 --- a/capiscio_sdk/events.py +++ b/capiscio_sdk/events.py @@ -19,6 +19,7 @@ """ import logging +import threading import time import uuid from datetime import datetime, timezone @@ -90,6 +91,7 @@ def __init__( self._client = httpx.Client(timeout=10.0) self._batch: list = [] + self._batch_lock = threading.Lock() self._last_flush = time.time() # Validate config @@ -141,10 +143,12 @@ def emit( if correlation_id: event["correlationId"] = correlation_id - self._batch.append(event) + with self._batch_lock: + self._batch.append(event) + should_flush = flush or len(self._batch) >= self.batch_size # Flush if batch is full or flush requested - if flush or len(self._batch) >= self.batch_size: + if should_flush: return self.flush() # Flush if interval exceeded @@ -164,11 +168,13 @@ def flush(self) -> bool: return True if not self.enabled: - self._batch.clear() + with self._batch_lock: + self._batch.clear() return False - events_to_send = self._batch.copy() - self._batch.clear() + with self._batch_lock: + events_to_send = self._batch.copy() + self._batch.clear() self._last_flush = time.time() try: @@ -190,13 +196,15 @@ def flush(self) -> bool: else: logger.warning(f"Failed to send events: {response.status_code} {response.text}") # Re-queue events on failure - self._batch.extend(events_to_send) + with self._batch_lock: + self._batch.extend(events_to_send) return False except Exception as e: logger.error(f"Error sending events: {e}") # Re-queue events on failure - self._batch.extend(events_to_send) + with self._batch_lock: + self._batch.extend(events_to_send) return False def task_started(self, task_id: str, input_text: str, **kwargs) -> bool: diff --git a/tests/unit/test_connect.py b/tests/unit/test_connect.py index bf55320..2ce966d 100644 --- a/tests/unit/test_connect.py +++ b/tests/unit/test_connect.py @@ -3,7 +3,7 @@ import os import pytest from pathlib import Path -from unittest.mock import MagicMock, patch, PropertyMock +from unittest.mock import MagicMock, patch from capiscio_sdk.connect import ( AgentIdentity, diff --git a/tests/unit/test_events.py b/tests/unit/test_events.py index aa7a724..329fecf 100644 --- a/tests/unit/test_events.py +++ b/tests/unit/test_events.py @@ -1,8 +1,6 @@ """Unit tests for capiscio_sdk.events module.""" import pytest -import time -from datetime import datetime, timezone from unittest.mock import MagicMock, patch from capiscio_sdk.events import ( @@ -10,7 +8,6 @@ init, emit, flush, - _global_emitter, ) From 323acc6d37cd81f4fed60963a30a750771eaa4df Mon Sep 17 00:00:00 2001 From: Beon de Nood Date: Fri, 6 Feb 2026 00:37:59 +0200 Subject: [PATCH 8/8] fix: Make RPC mock tests Python 3.10 compatible Directly set _rpc_client on connector instead of patching, avoids naming conflict between capiscio_sdk.connect module and CapiscIO.connect method --- tests/unit/test_connect.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/unit/test_connect.py b/tests/unit/test_connect.py index 2ce966d..5ffdc8e 100644 --- a/tests/unit/test_connect.py +++ b/tests/unit/test_connect.py @@ -715,11 +715,12 @@ def test_init_identity_calls_rpc(self, tmp_path): None, ) - with patch("capiscio_sdk.connect.CapiscioRPCClient", return_value=mock_rpc): - result = connector._init_identity() + # Directly set _rpc_client to skip instantiation (connect.py checks if not self._rpc_client) + connector._rpc_client = mock_rpc + result = connector._init_identity() assert result == "did:key:z6MkNew" - mock_rpc.connect.assert_called_once() + # Note: connect() not called since _rpc_client was preset mock_rpc.simpleguard.init.assert_called_once_with( api_key="sk_test", agent_id="agent-123", @@ -745,9 +746,10 @@ def test_init_identity_rpc_error(self, tmp_path): mock_rpc = MagicMock() mock_rpc.simpleguard.init.return_value = (None, "RPC failed") - with patch("capiscio_sdk.connect.CapiscioRPCClient", return_value=mock_rpc): - with pytest.raises(ConfigurationError, match="Failed to initialize identity"): - connector._init_identity() + # Directly set _rpc_client to skip instantiation (connect.py checks if not self._rpc_client) + connector._rpc_client = mock_rpc + with pytest.raises(ConfigurationError, match="Failed to initialize identity"): + connector._init_identity() def test_setup_badge_success(self, tmp_path): """Test _setup_badge sets up keeper and guard."""