diff --git a/capiscio_sdk/__init__.py b/capiscio_sdk/__init__.py index 3f1d190..474f809 100644 --- a/capiscio_sdk/__init__.py +++ b/capiscio_sdk/__init__.py @@ -14,7 +14,7 @@ >>> result = validate_agent_card(card_dict) # Uses Go core """ -__version__ = "2.7.1" +__version__ = "2.7.2" # Core exports from .executor import CapiscioSecurityExecutor, secure, secure_agent diff --git a/capiscio_sdk/connect.py b/capiscio_sdk/connect.py index 69edec2..e9a35d5 100644 --- a/capiscio_sdk/connect.py +++ b/capiscio_sdk/connect.py @@ -212,6 +212,24 @@ class AgentIdentity: _keeper: Any = field(default=None, repr=False) _emitter: Any = field(default=None, repr=False) + @property + def guard(self) -> "SimpleGuard": + """Access the SimpleGuard instance for signing/verifying. + + Reuses the identity's keys_dir and DID so the guard operates + with the same key material that connect() provisioned. + """ + if self._guard is None: + from .simple_guard import SimpleGuard + self._guard = SimpleGuard( + agent_id=self.did or self.agent_id, + base_dir=str(self.keys_dir), + signing_kid=self.did, + badge_token=self.badge_jws, + keys_preloaded=True, + ) + return self._guard + def emit(self, event_type: str, data: Dict[str, Any]) -> bool: """Emit an event to the registry.""" if not self._emitter: diff --git a/capiscio_sdk/simple_guard.py b/capiscio_sdk/simple_guard.py index d23908b..63ae4e3 100644 --- a/capiscio_sdk/simple_guard.py +++ b/capiscio_sdk/simple_guard.py @@ -213,13 +213,13 @@ def __exit__(self, exc_type, exc_val, exc_tb) -> None: def _resolve_project_root(self, base_dir: Optional[Union[str, Path]]) -> Path: """Resolve the project root directory. - When agent_id is provided explicitly, uses base_dir (or cwd) directly - without walking up the tree looking for agent-card.json. + When agent_id is provided explicitly or dev_mode is True, uses base_dir + (or cwd) directly without walking up the tree looking for agent-card.json. """ current = Path(base_dir or os.getcwd()).resolve() - # When identity params are provided, don't walk looking for agent-card.json - if self._explicit_agent_id: + # When identity params are provided or in dev_mode, don't walk looking for agent-card.json + if self._explicit_agent_id or self.dev_mode: return current search_path = current @@ -246,7 +246,16 @@ def _resolve_identity(self) -> None: logger.info(f"Using explicit agent_id: {self.agent_id}") return - # Case 3: Legacy agent-card.json (deprecated path) + # Case 3: Dev mode — placeholder until key generation + # (checked before legacy agent-card.json so dev_mode isn't + # broken by an A2A agent-card.json that lacks public_keys) + if self.dev_mode: + logger.info("Dev Mode: Will generate did:key identity from keypair") + self.agent_id = "local-dev-agent" + self.signing_kid = "local-dev-key" + return + + # Case 4: Legacy agent-card.json (deprecated path) agent_card_path = self.project_root / "agent-card.json" if agent_card_path.exists(): logger.warning( @@ -269,13 +278,6 @@ def _resolve_identity(self) -> None: except Exception as e: raise ConfigurationError(f"Failed to load agent-card.json: {e}") return - - # Case 4: Dev mode — placeholder until key generation - if self.dev_mode: - logger.info("Dev Mode: Will generate did:key identity from keypair") - self.agent_id = "local-dev-agent" - self.signing_kid = "local-dev-key" - return raise ConfigurationError( "No agent identity configured. Either:\n" diff --git a/pyproject.toml b/pyproject.toml index 292899c..782b2e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "capiscio-sdk" -version = "2.7.1" +version = "2.7.2" description = "Runtime security middleware for A2A agents" readme = "README.md" requires-python = ">=3.10"