Files
amethyst/quartz
Claude 89198ab24e refactor(marmot,cli): lift shared logic into quartz/commons
Five extractions so the Amethyst UI and the new amy CLI share one
implementation for each piece of Marmot/identity behaviour instead of
reimplementing it per platform.

quartz additions:
- MarmotGroupData.bootstrap(..) + withMergedRelays(..): factory for the
  metadata shape every inviter stamps on a fresh group and the outbox-
  merge rule every admin commit carries forward.
- KeyPackageFetcher: (a) pure fetchRelaysFor union of target kind:10051,
  target outbox, my outbox; (b) one-shot fetchKeyPackage; (c) publish-
  side resolveKeyPackagePublishRelays.
- resolveUserHexOrNull: single entry point for npub / nprofile / 64-hex
  / NIP-05 identifiers. Uses the existing Nip19Parser + Nip05Client
  infra so NIP-05 resolution is live over HTTP.

commons additions:
- MarmotManager.leafIndexOf(..): pubkey -> leaf index lookup used by
  every removeMember caller.
- MarmotManager.addMember(nostrGroupId, keyPackageEvent, relays):
  convenience overload that lifts the base64 decode into the manager.
- MarmotManager.buildTextMessage(..) returning a TextMessageBundle;
  optionally persists the outbound inner event (CLI needs persist,
  Amethyst relies on LocalCache loopback).
- MarmotIngest.ingest(event): routes kind:1059 / kind:445 through
  unwrap -> processWelcome / processGroupEvent -> persist the decrypted
  application message. Deliberately platform-agnostic.

Retrofits:
- Account.addMarmotGroupMember and fetchKeyPackageAndAddMember now take
  a KeyPackageEvent directly; Account.keyPackagePublishRelays delegates
  to KeyPackageFetcher.
- AccountViewModel.updateMarmotGroupMetadata uses bootstrap + merged.
- AccountViewModel.sendMarmotGroupMessage builds the kind:9 template via
  buildTextMessage(persistOwn = false) to avoid double-persisting.
- AccountSessionManager's NIP-05 login branch delegates to
  resolveUserHexOrNull; no more hand-rolled Nip05Id / nip05Client.get.
- CLI Context exposes nip05Client and requireUserHex; syncIncoming now
  calls MarmotManager.ingest; all command sites use KeyPackageFetcher
  + the shared identifier resolver. Npubs util deleted.

https://claude.ai/code/session_01M6dCKAF5Y1VyHGZPjzwDXq
2026-04-21 20:43:00 +00:00
..