fix: hub-scope the identity key HD derivation path (musehub#221)
Prior to this fix, muse_path()/derive_identity_key() had no per-hub level in the HD path -- the identity key at rotation index 0 was bit-for-bit identical regardless of which hub it was registered with. Confirmed live against a real ~/.muse/identity.toml: localhost:1337 and musehub.ai had identical fingerprints and hd_path, both at index 0.
- hdkeys.py: new hub_index(canonical_hostname) function (same sha256-hash-and-mask pattern as domain_index/agent_id_to_slot). muse_path()/derive_key()/derive_identity_key() gain an optional hub parameter -- None reproduces the original six-level path byte-for-byte (every non-identity domain is unaffected); a real hub index inserts a seventh hardened level between role' and index'. - keypair.py: derive_hd_public_info() threads the new hub parameter through to derive_identity_key(). - auth.py: muse auth keygen/recover/rotate now compute and pass hub=hub_index(hostname) for every real identity-key derivation. rotate detects whether the EXISTING key is pre-#221 (six-level) or already hub-scoped (seven-level) and re-derives the old key under whichever scheme it actually was registered with, so the challenge-response deregistration step still signs with the right key -- only the NEW post-rotation key is always hub-scoped going forward. security-check's fingerprint-verification does the same legacy-vs-scoped detection. - path_cmd.py: muse path annotate now parses both six-level and seven-level (hub-scoped) paths and reports hub_idx/hub_scoped in its output. - hub_scoping_migration.py (new) + migrate_cmd.py: muse migrate hub-scoping [--dry-run] [--no-register] detects six-level identity-domain entries in identity.toml, re-derives each at a hub-scoped path, and re-registers with that specific hub. Mirrors the existing domain-integers migration exactly. - app.py: registered migrate_cmd.register() -- this was never wired up before (a separate, pre-existing latent bug found in the course of this fix; muse migrate domain-integers was unreachable via the real CLI despite being fully implemented and documented). - Updated 5 existing tests whose fixtures assumed the old bug as correct behavior (most notably test_10_recoveries_different_hubs, which explicitly asserted "same mnemonic -> same fingerprint regardless of hub" -- that assertion was the vulnerability). - Added 52 new tests (test_migrate_hub_scoping.py, test_path_annotate.py) covering path detection, mapping, key re-derivation, scanning, dry-run/live migration, CLI smoke, and adversarial inputs.
1165 tests across every affected area (auth, hdkeys, migrate, agent signing, keychain, security-zeroing, path annotate) pass.
Semantic Changes
278 symbols
Files Changed
+3
~11
1194 in snapshot
0 comments
muse hub commit comment sha256:c08228badabf977083c0a945db5b8d1fd5292edab0d0726ebf6c349d1692d528 --body "your comment"
No comments yet. Be the first to start the discussion.