domain_cmd.py
python
sha256:2a703f78341332ef0beb9856d2267de6aec89b3883c31519b6900b667d026e62
chore: delete muse/prose domain — hallucinated, never existed
Sonnet 4.6
minor
⚠ breaking
7 days ago
| 1 | """muse domain — hash-derived domain index tooling. |
| 2 | |
| 3 | Every Muse domain integer is computed from its canonical name string via:: |
| 4 | |
| 5 | index = int.from_bytes(sha256(name.encode("utf-8"))[:4], "big") & 0x7FFFFFFF |
| 6 | |
| 7 | This makes the domain namespace open and decentralised: any third-party |
| 8 | domain derives its index without a central registry. The registry |
| 9 | (``gabriel/muse-domains`` on MuseHub) is a human-readable annotation layer — |
| 10 | it does not gate key derivation. |
| 11 | |
| 12 | Subcommands:: |
| 13 | |
| 14 | muse domain index <name> Compute the index for any domain name. |
| 15 | muse domain lookup <name> Look up a name in the local registry. |
| 16 | muse domain lookup --index <n> Reverse-lookup an integer to a name. |
| 17 | muse domain list List all locally registered domains. |
| 18 | muse domain check <name> Exit 0 if registered, 1 if not. |
| 19 | |
| 20 | Registry location |
| 21 | ----------------- |
| 22 | |
| 23 | The registry is read from, in order: |
| 24 | |
| 25 | 1. ``$MUSE_DOMAIN_REGISTRY`` env var (path to a ``registry.json`` file). |
| 26 | 2. ``~/.muse/domain-registry.json`` (cached copy from the hub). |
| 27 | 3. The built-in seed registry shipped with this muse release. |
| 28 | |
| 29 | For air-gapped use, copy ``registry.json`` from ``gabriel/muse-domains`` and |
| 30 | set ``MUSE_DOMAIN_REGISTRY`` to point at it. |
| 31 | |
| 32 | JSON schemas |
| 33 | ------------ |
| 34 | |
| 35 | ``muse domain index --json``:: |
| 36 | |
| 37 | { |
| 38 | "name": "muse/music", |
| 39 | "index": 1755707987, |
| 40 | "registered": true, |
| 41 | "entry": { "description": "...", "owner": "gabriel", ... } |
| 42 | } |
| 43 | |
| 44 | ``muse domain list --json``:: |
| 45 | |
| 46 | { |
| 47 | "domains": [ |
| 48 | { "name": "muse/identity", "index": 1660078172, ... }, |
| 49 | ... |
| 50 | ], |
| 51 | "total": 8 |
| 52 | } |
| 53 | |
| 54 | ``muse domain check --json``:: |
| 55 | |
| 56 | { "name": "acme/gaming", "registered": false } |
| 57 | """ |
| 58 | |
| 59 | import argparse |
| 60 | import json |
| 61 | import logging |
| 62 | import os |
| 63 | import pathlib |
| 64 | import sys |
| 65 | from typing import TypedDict |
| 66 | |
| 67 | from muse.core.envelope import EnvelopeJson, make_envelope |
| 68 | from muse.core.errors import ExitCode |
| 69 | from muse.core.hdkeys import domain_index |
| 70 | from muse.core.paths import user_domain_registry_path |
| 71 | from muse.core.timing import start_timer |
| 72 | from muse.core.types import load_json_file |
| 73 | |
| 74 | logger = logging.getLogger(__name__) |
| 75 | |
| 76 | |
| 77 | class _DomainEntry(TypedDict, total=False): |
| 78 | name: str |
| 79 | index: int |
| 80 | description: str |
| 81 | owner: str |
| 82 | registered_at: str | None |
| 83 | |
| 84 | |
| 85 | # --------------------------------------------------------------------------- |
| 86 | # Seed registry — shipped with the muse binary for offline use. |
| 87 | # Authoritative source: gabriel/muse-domains on MuseHub. |
| 88 | # --------------------------------------------------------------------------- |
| 89 | _SEED_REGISTRY: list[_DomainEntry] = [ |
| 90 | { |
| 91 | "name": "muse/identity", |
| 92 | "index": 1660078172, |
| 93 | "description": "Cross-domain authentication. MSign HTTP signing, MuseHub registration, the passport key for any identity on the network.", |
| 94 | "owner": "gabriel", |
| 95 | "registered_at": None, |
| 96 | }, |
| 97 | { |
| 98 | "name": "muse/payments", |
| 99 | "index": 284229149, |
| 100 | "description": "MPay claims and financial settlement.", |
| 101 | "owner": "gabriel", |
| 102 | "registered_at": None, |
| 103 | }, |
| 104 | { |
| 105 | "name": "muse/code", |
| 106 | "index": 678195575, |
| 107 | "description": "Software version control. Commit provenance, code-review attestations, symbol-level semantic diffs.", |
| 108 | "owner": "gabriel", |
| 109 | "registered_at": None, |
| 110 | }, |
| 111 | { |
| 112 | "name": "muse/music", |
| 113 | "index": 1755707987, |
| 114 | "description": "Stori audio production. Project signing, master ownership, stem provenance.", |
| 115 | "owner": "gabriel", |
| 116 | "registered_at": None, |
| 117 | }, |
| 118 | { |
| 119 | "name": "muse/midi", |
| 120 | "index": 1444628350, |
| 121 | "description": "Maestro symbolic music. NL-to-MIDI content signing, score provenance.", |
| 122 | "owner": "gabriel", |
| 123 | "registered_at": None, |
| 124 | }, |
| 125 | { |
| 126 | "name": "muse/prose", |
| 127 | "index": 1658731548, |
| 128 | "description": "Long-form document signing. Markdown, plaintext, structured prose.", |
| 129 | "owner": "gabriel", |
| 130 | "registered_at": None, |
| 131 | }, |
| 132 | { |
| 133 | "name": "muse/blockchain", |
| 134 | "index": 1556829714, |
| 135 | "description": "On-chain operations. ERC-8004 identity, ERC-721 masters, ERC-1155 marketplace, AVAX settlement. secp256k1 keys via Bitcoin seed HMAC root.", |
| 136 | "owner": "gabriel", |
| 137 | "registered_at": None, |
| 138 | }, |
| 139 | { |
| 140 | "name": "muse/generic", |
| 141 | "index": 2023564266, |
| 142 | "description": "Repos and entities with no registered domain plugin. First-class explicit value — never an empty string or None.", |
| 143 | "owner": "gabriel", |
| 144 | "registered_at": None, |
| 145 | }, |
| 146 | ] |
| 147 | |
| 148 | def _load_registry() -> list[_DomainEntry]: |
| 149 | """Return the domain registry, preferring local overrides over the seed.""" |
| 150 | paths = [ |
| 151 | os.environ.get("MUSE_DOMAIN_REGISTRY", ""), |
| 152 | str(user_domain_registry_path()), |
| 153 | ] |
| 154 | for p in paths: |
| 155 | if p: |
| 156 | data = load_json_file(pathlib.Path(p)) |
| 157 | if isinstance(data, dict): |
| 158 | return list(data.get("domains", [])) |
| 159 | return _SEED_REGISTRY |
| 160 | |
| 161 | def _lookup_by_name(registry: list[_DomainEntry], name: str) -> _DomainEntry | None: |
| 162 | for entry in registry: |
| 163 | if entry.get("name") == name: |
| 164 | return entry |
| 165 | return None |
| 166 | |
| 167 | def _lookup_by_index(registry: list[_DomainEntry], idx: int) -> _DomainEntry | None: |
| 168 | for entry in registry: |
| 169 | if entry.get("index") == idx: |
| 170 | return entry |
| 171 | return None |
| 172 | |
| 173 | # --------------------------------------------------------------------------- |
| 174 | # Subcommand: index |
| 175 | # --------------------------------------------------------------------------- |
| 176 | |
| 177 | def _run_index(args: argparse.Namespace) -> None: |
| 178 | elapsed = start_timer() |
| 179 | name: str = args.name |
| 180 | idx = domain_index(name) |
| 181 | registry = _load_registry() |
| 182 | entry = _lookup_by_name(registry, name) |
| 183 | registered = entry is not None |
| 184 | |
| 185 | if args.json_out: |
| 186 | out = { |
| 187 | **make_envelope(elapsed), |
| 188 | "name": name, |
| 189 | "index": idx, |
| 190 | "registered": registered, |
| 191 | } |
| 192 | if entry is not None: |
| 193 | out["entry"] = entry |
| 194 | print(json.dumps(out)) |
| 195 | else: |
| 196 | print(f"name: {name}") |
| 197 | print(f"index: {idx}") |
| 198 | print(f"registered: {registered}") |
| 199 | if entry: |
| 200 | print(f"owner: {entry.get('owner', '')}") |
| 201 | print(f"desc: {entry.get('description', '')}") |
| 202 | |
| 203 | # --------------------------------------------------------------------------- |
| 204 | # Subcommand: lookup |
| 205 | # --------------------------------------------------------------------------- |
| 206 | |
| 207 | def _run_lookup(args: argparse.Namespace) -> None: |
| 208 | elapsed = start_timer() |
| 209 | registry = _load_registry() |
| 210 | |
| 211 | if args.index is not None: |
| 212 | entry = _lookup_by_index(registry, args.index) |
| 213 | if entry is None: |
| 214 | msg = {"error": f"No domain registered with index {args.index}"} |
| 215 | print(json.dumps(msg), file=sys.stderr) |
| 216 | raise SystemExit(ExitCode.USER_ERROR) |
| 217 | idx = args.index |
| 218 | name = entry["name"] |
| 219 | else: |
| 220 | if not args.name: |
| 221 | print(json.dumps({"error": "Provide <name> or --index"}), file=sys.stderr) |
| 222 | raise SystemExit(ExitCode.USER_ERROR) |
| 223 | name = args.name |
| 224 | idx = domain_index(name) |
| 225 | entry = _lookup_by_name(registry, name) |
| 226 | if entry is None: |
| 227 | msg = {"error": f"Domain '{name}' not found in registry"} |
| 228 | print(json.dumps(msg), file=sys.stderr) |
| 229 | raise SystemExit(ExitCode.USER_ERROR) |
| 230 | |
| 231 | if args.json_out: |
| 232 | print(json.dumps({**make_envelope(elapsed), **entry, "index": idx})) |
| 233 | else: |
| 234 | print(f"name: {name}") |
| 235 | print(f"index: {idx}") |
| 236 | print(f"owner: {entry.get('owner', '')}") |
| 237 | print(f"desc: {entry.get('description', '')}") |
| 238 | if entry.get("registered_at"): |
| 239 | print(f"registered: {entry['registered_at']}") |
| 240 | |
| 241 | # --------------------------------------------------------------------------- |
| 242 | # Subcommand: list |
| 243 | # --------------------------------------------------------------------------- |
| 244 | |
| 245 | def _run_list(args: argparse.Namespace) -> None: |
| 246 | elapsed = start_timer() |
| 247 | registry = _load_registry() |
| 248 | |
| 249 | if args.json_out: |
| 250 | print(json.dumps({ |
| 251 | **make_envelope(elapsed), |
| 252 | "domains": registry, |
| 253 | "total": len(registry), |
| 254 | })) |
| 255 | else: |
| 256 | for entry in registry: |
| 257 | print(f"{entry['name']:30s} {entry['index']}") |
| 258 | |
| 259 | # --------------------------------------------------------------------------- |
| 260 | # Subcommand: check |
| 261 | # --------------------------------------------------------------------------- |
| 262 | |
| 263 | def _run_check(args: argparse.Namespace) -> None: |
| 264 | elapsed = start_timer() |
| 265 | name: str = args.name |
| 266 | registry = _load_registry() |
| 267 | entry = _lookup_by_name(registry, name) |
| 268 | registered = entry is not None |
| 269 | |
| 270 | if args.json_out: |
| 271 | print(json.dumps({**make_envelope(elapsed), "name": name, "registered": registered})) |
| 272 | else: |
| 273 | status = "registered" if registered else "not registered" |
| 274 | print(f"{name}: {status}") |
| 275 | |
| 276 | if not registered: |
| 277 | raise SystemExit(1) |
| 278 | |
| 279 | # --------------------------------------------------------------------------- |
| 280 | # Registration |
| 281 | # --------------------------------------------------------------------------- |
| 282 | |
| 283 | def register(subparsers: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None: |
| 284 | """Register the ``muse domain`` namespace.""" |
| 285 | parser = subparsers.add_parser( |
| 286 | "domain", |
| 287 | help="Hash-derived domain index tooling — compute, lookup, list, check.", |
| 288 | description=__doc__, |
| 289 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 290 | ) |
| 291 | domain_subs = parser.add_subparsers(dest="domain_subcmd", metavar="SUBCMD") |
| 292 | domain_subs.required = True |
| 293 | |
| 294 | # ── index ────────────────────────────────────────────────────────── |
| 295 | p_index = domain_subs.add_parser( |
| 296 | "index", |
| 297 | help="Compute the hash-derived index for a domain name.", |
| 298 | ) |
| 299 | p_index.add_argument("name", help="Canonical domain name, e.g. 'muse/music'.") |
| 300 | p_index.add_argument("--json", "-j", action="store_true", dest="json_out") |
| 301 | p_index.set_defaults(func=_run_index) |
| 302 | |
| 303 | # ── lookup ───────────────────────────────────────────────────────── |
| 304 | p_lookup = domain_subs.add_parser( |
| 305 | "lookup", |
| 306 | help="Look up a domain name (or --index integer) in the registry.", |
| 307 | ) |
| 308 | p_lookup.add_argument("name", nargs="?", default=None, |
| 309 | help="Canonical domain name to look up.") |
| 310 | p_lookup.add_argument("--index", type=int, default=None, |
| 311 | help="Reverse-lookup: find the name for this integer index.") |
| 312 | p_lookup.add_argument("--json", "-j", action="store_true", dest="json_out") |
| 313 | p_lookup.set_defaults(func=_run_lookup) |
| 314 | |
| 315 | # ── list ─────────────────────────────────────────────────────────── |
| 316 | p_list = domain_subs.add_parser( |
| 317 | "list", |
| 318 | help="List all locally registered domains.", |
| 319 | ) |
| 320 | p_list.add_argument("--json", "-j", action="store_true", dest="json_out") |
| 321 | p_list.set_defaults(func=_run_list) |
| 322 | |
| 323 | # ── check ────────────────────────────────────────────────────────── |
| 324 | p_check = domain_subs.add_parser( |
| 325 | "check", |
| 326 | help="Exit 0 if the name is registered, 1 if not.", |
| 327 | ) |
| 328 | p_check.add_argument("name", help="Canonical domain name to check.") |
| 329 | p_check.add_argument("--json", "-j", action="store_true", dest="json_out") |
| 330 | p_check.set_defaults(func=_run_check) |
File History
1 commit
sha256:2a703f78341332ef0beb9856d2267de6aec89b3883c31519b6900b667d026e62
chore: delete muse/prose domain — hallucinated, never existed
Sonnet 4.6
minor
⚠
7 days ago