gabriel / muse public
feat BREAKING task/hd-only-keygen #1 / 1
gabriel · 165 days ago · Apr 16, 2026 · Diff

feat: HD-only keygen — remove JBOK, add agent derivation and recover

- Delete generate_keypair() (JBOK random keys) from keypair.py - Add agent_id_to_slot() to hdkeys.py: sha256(handle)[:4] & 0x7FFFFFFF - run_keygen: no --hd flag; human path generates fresh 24-word mnemonic; agent path derives from operator mnemonic via derive_agent_sub_seed() - run_recover: re-derives same key from BIP39 mnemonic (human or agent) - identity.py: provisioned_by_fingerprint field added to IdentityEntry - Fix run_recover bugs: use .get('handle','') and check validate_mnemonic() return value - Write test_hd_keygen_unified.py: 44 tests for agent_id_to_slot, human keygen, agent keygen, run_recover, no-JBOK, integration flow - Update test_cmd_auth_keygen_hd.py: remove --hd flags, fix 12→24 word defaults

sha256:910a8d48bf685659fdcaf595d029bb56512f8f75aaf3c41a942f2004fdd3f413 sha
+85 ~28 −3 symbols
sha256:fefe5476212ea6a736ae6632137562dde2b3571c297d32ed30aa8766b6f20ae6 snapshot
+85
symbols added
~28
symbols modified
−3
symbols removed
0
dead code introduced
Semantic Changes 116 symbols
~ tests/test_hd_keygen_unified.py .py 80 symbols added
+ TestAgentIdToSlot class class TestAgentIdToSlot L75–115
+ test_deterministic method method test_deterministic L88–91
+ test_distinct_handles_likely_distinct_slots method method test_distinct_handles_likely_distinct_slots L93–97
+ test_empty_string_handled method method test_empty_string_handled L107–110
+ test_in_valid_bip32_range method method test_in_valid_bip32_range L82–86
+ test_known_vector method method test_known_vector L99–105
+ test_returns_int method method test_returns_int L78–80
+ test_unicode_handle method method test_unicode_handle L112–115
+ TestAgentKeygen class class TestAgentKeygen L259–375
+ _setup_operator method method _setup_operator L262–269
+ test_agent_json_has_hd_path method method test_agent_json_has_hd_path L295–305
+ test_agent_json_has_provisioned_by method method test_agent_json_has_provisioned_by L307–316
+ test_agent_key_deterministic method method test_agent_key_deterministic L360–375
+ test_agent_key_different_from_human_key method method test_agent_key_different_from_human_key L318–333
+ test_agent_keygen_exits_zero method method test_agent_keygen_exits_zero L271–276
+ test_agent_keygen_without_operator_exits_nonzero method method test_agent_keygen_without_operator_exits_nonzero L352–358
+ test_agent_pem_at_expected_path method method test_agent_pem_at_expected_path L278–284
+ test_agent_pem_mode_600 method method test_agent_pem_mode_600 L286–293
+ test_two_agents_have_distinct_keys method method test_two_agents_have_distinct_keys L335–350
+ TestDeriveAgentSubSeed class class TestDeriveAgentSubSeed L383–420
+ test_deterministic method method test_deterministic L392–397
+ test_different_domains_different_sub_seeds method method test_different_domains_different_sub_seeds L408–414
+ test_different_slots_different_sub_seeds method method test_different_slots_different_sub_seeds L399–406
+ test_returns_64_bytes method method test_returns_64_bytes L386–390
+ test_sub_seed_differs_from_parent_seed method method test_sub_seed_differs_from_parent_seed L416–420
+ TestHumanKeygen class class TestHumanKeygen L146–251
+ test_default_24_word_mnemonic method method test_default_24_word_mnemonic L171–185
+ test_exits_zero method method test_exits_zero L149–153
+ test_force_overwrites_existing method method test_force_overwrites_existing L231–236
+ test_identity_toml_has_mnemonic method method test_identity_toml_has_mnemonic L210–220
+ test_identity_toml_key_source_hd method method test_identity_toml_key_source_hd L222–229
+ test_json_has_key_source_hd method method test_json_has_key_source_hd L187–193
+ test_json_mnemonic_word_count_24 method method test_json_mnemonic_word_count_24 L203–208
+ test_json_no_mnemonic_in_stdout method method test_json_no_mnemonic_in_stdout L195–201
+ test_no_force_rejects_existing method method test_no_force_rejects_existing L238–243
+ test_pem_mode_600 method method test_pem_mode_600 L162–169
+ test_pem_written method method test_pem_written L155–160
+ test_strength_128_gives_12_words method method test_strength_128_gives_12_words L245–251
+ TestIntegrationFlow class class TestIntegrationFlow L512–558
+ test_operator_then_agent_then_recover method method test_operator_then_agent_then_recover L515–550
+ test_slot_stability_across_keygen_invocations method method test_slot_stability_across_keygen_invocations L552–558
+ TestNoJbok class class TestNoJbok L123–138
+ test_generate_hd_keypair_exists method method test_generate_hd_keypair_exists L136–138
+ test_generate_keypair_not_importable method method test_generate_keypair_not_importable L132–134
+ test_generate_keypair_not_in_module method method test_generate_keypair_not_in_module L126–130
+ TestRunRecover class class TestRunRecover L428–504
+ _do_recover method method _do_recover L431–440
+ test_recover_exits_zero method method test_recover_exits_zero L442–446
+ test_recover_invalid_mnemonic_exits_nonzero method method test_recover_invalid_mnemonic_exits_nonzero L482–486
+ test_recover_json_has_fingerprint method method test_recover_json_has_fingerprint L497–504
+ test_recover_pem_mode_600 method method test_recover_pem_mode_600 L488–495
+ test_recover_produces_same_fingerprint_as_keygen method method test_recover_produces_same_fingerprint_as_keygen L456–480
+ test_recover_writes_pem method method test_recover_writes_pem L448–454
+ _HOSTNAME variable variable _HOSTNAME L41–41
+ _HUB variable variable _HUB L40–40
+ _TEST_MNEMONIC_12 variable variable _TEST_MNEMONIC_12 L43–43
+ _keygen function function _keygen L61–67
+ _patch_home function function _patch_home L51–58
+ CliRunner import import CliRunner L22–22
+ DOMAIN_IDENTITY import import DOMAIN_IDENTITY L26–26
+ ENTITY_AGENT import import ENTITY_AGENT L26–26
+ ENTITY_HUMAN import import ENTITY_HUMAN L26–26
+ MUSE_PURPOSE import import MUSE_PURPOSE L26–26
+ ROLE_SIGN import import ROLE_SIGN L26–26
+ agent_id_to_slot import import agent_id_to_slot L26–26
+ annotations import import annotations L12–12
+ base64 import import base64 L14–14
+ derive_agent_sub_seed import import derive_agent_sub_seed L26–26
+ derive_identity_key import import derive_identity_key L26–26
+ hashlib import import hashlib L15–15
+ id_module import import id_module L24–24
+ json import import json L16–16
+ kp_module import import kp_module L23–23
+ load_pem_private_key import import load_pem_private_key L20–20
+ mnemonic_to_seed import import mnemonic_to_seed L25–25
+ muse_path import import muse_path L26–26
+ pathlib import import pathlib L17–17
+ pytest import import pytest L19–19
+ validate_mnemonic import import validate_mnemonic L25–25
+ runner variable variable runner L38–38
~ muse/cli/commands/auth.py .py 1 symbol added, 2 symbols modified
+ run_recover function function run_recover L850–949
~ muse/core/hdkeys.py .py 2 symbols added, 1 symbol modified
+ agent_id_to_slot function function agent_id_to_slot L339–371
+ hashlib import import hashlib L186–186
~ muse/core/identity.py .py 2 symbols modified
~ muse/core/keypair.py .py 1 symbol removed
− generate_keypair function function generate_keypair L156–182
← Older Oldest on task/hd-only-keygen
All commits
Newer → Latest on task/hd-only-keygen

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:910a8d48bf685659fdcaf595d029bb56512f8f75aaf3c41a942f2004fdd3f413 --body "your comment"