Skip to content

Commit a6d61d9

Browse files
authored
fix: persist and recover did:key identity in dev mode (#44)
* fix: persist and recover did:key identity in dev mode When private.pem already exists on disk, _load_or_generate_keys() loaded the key but never recovered the did:key identity, leaving agent_id stuck at the placeholder 'local-dev-agent'. Fix: persist did:key to capiscio_keys/did_key.txt on first generation, read it back on subsequent loads. No cross-repo changes needed. * test: add unit tests for did:key persistence and recovery
1 parent 8445e98 commit a6d61d9

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

capiscio_sdk/simple_guard.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ def _load_or_generate_keys(self) -> None:
300300
else:
301301
raise ConfigurationError(f"capiscio_keys directory not found at {self.keys_dir}")
302302

303+
did_key_path = self.keys_dir / "did_key.txt"
304+
303305
if private_key_path.exists():
304306
# Load existing key via gRPC
305307
key_info, error = self._client.simpleguard.load_key(str(private_key_path))
@@ -308,6 +310,11 @@ def _load_or_generate_keys(self) -> None:
308310
# Update signing kid to match the loaded key
309311
self.signing_kid = key_info["key_id"]
310312
logger.info(f"Loaded key: {self.signing_kid}")
313+
314+
# Recover did:key identity from sidecar file if in dev mode
315+
if self.dev_mode and not self._explicit_agent_id and did_key_path.exists():
316+
self.agent_id = did_key_path.read_text().strip()
317+
logger.info(f"Dev Mode: Recovered did:key identity: {self.agent_id}")
311318
elif self.dev_mode:
312319
logger.info("Dev Mode: Generating Ed25519 keypair via gRPC")
313320

@@ -323,6 +330,8 @@ def _load_or_generate_keys(self) -> None:
323330
if did_key and not self._explicit_agent_id:
324331
self.agent_id = did_key
325332
logger.info(f"Dev Mode: Using did:key identity: {self.agent_id}")
333+
# Persist did:key for recovery on subsequent loads
334+
did_key_path.write_text(did_key)
326335

327336
# Save private key
328337
with open(private_key_path, "w") as f:

tests/unit/test_simple_guard.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,58 @@ def test_legacy_agent_card_with_deprecation_warning(self, temp_workspace, mock_r
121121
guard.close()
122122

123123

124+
class TestSimpleGuardDidKeyRecovery:
125+
"""Tests for dev mode did:key persistence and recovery."""
126+
127+
def test_dev_mode_persists_did_key_on_generate(self, temp_workspace, mock_rpc_client):
128+
"""Test that dev_mode persists did:key to sidecar file on first generation."""
129+
mock_rpc_client.simpleguard.generate_key_pair.return_value = ({
130+
"key_id": "test-key",
131+
"did_key": "did:key:z6MkTestGeneratedKey",
132+
"private_key_pem": "-----BEGIN PRIVATE KEY-----\ntest\n-----END PRIVATE KEY-----",
133+
"public_key_pem": "-----BEGIN PUBLIC KEY-----\ntest\n-----END PUBLIC KEY-----",
134+
}, None)
135+
136+
guard = SimpleGuard(dev_mode=True)
137+
138+
assert guard.agent_id == "did:key:z6MkTestGeneratedKey"
139+
did_key_path = temp_workspace / "capiscio_keys" / "did_key.txt"
140+
assert did_key_path.exists()
141+
assert did_key_path.read_text() == "did:key:z6MkTestGeneratedKey"
142+
143+
guard.close()
144+
145+
def test_dev_mode_recovers_did_key_on_load(self, temp_workspace, mock_rpc_client):
146+
"""Test that dev_mode recovers did:key from sidecar file when key exists."""
147+
keys_dir = temp_workspace / "capiscio_keys"
148+
keys_dir.mkdir(parents=True)
149+
(keys_dir / "trusted").mkdir()
150+
(keys_dir / "private.pem").write_text("mock key")
151+
(keys_dir / "public.pem").write_text("mock pub")
152+
(keys_dir / "did_key.txt").write_text("did:key:z6MkRecoveredKey")
153+
154+
guard = SimpleGuard(dev_mode=True)
155+
156+
assert guard.agent_id == "did:key:z6MkRecoveredKey"
157+
mock_rpc_client.simpleguard.generate_key_pair.assert_not_called()
158+
159+
guard.close()
160+
161+
def test_dev_mode_explicit_agent_id_ignores_sidecar(self, temp_workspace, mock_rpc_client):
162+
"""Test that explicit agent_id is not overridden by sidecar did_key.txt."""
163+
keys_dir = temp_workspace / "capiscio_keys"
164+
keys_dir.mkdir(parents=True)
165+
(keys_dir / "trusted").mkdir()
166+
(keys_dir / "private.pem").write_text("mock key")
167+
(keys_dir / "did_key.txt").write_text("did:key:z6MkShouldBeIgnored")
168+
169+
guard = SimpleGuard(dev_mode=True, agent_id="did:web:example.com:myagent")
170+
171+
assert guard.agent_id == "did:web:example.com:myagent"
172+
173+
guard.close()
174+
175+
124176
class TestSimpleGuardSigning:
125177
"""Tests for SimpleGuard signing operations."""
126178

0 commit comments

Comments
 (0)