Files
Claude 4f04a7b0e9 feat: sign in with a NIP-05 address through the signer its domain advertises
Typing `name@domain` used to give a read-only account. A domain can
advertise a NIP-46 remote signer for the address in its nostr.json
(`nip46`), and the login now uses it, in Amethyst (Android and desktop,
through the shared login) and in amy.

- Quartz: Nip05Client.loadRemoteSigner reads both shapes into a
  Nip05RemoteSigner. Legacy first (nip46[pubkey] -> relays, the address's
  own key signs; what nostr-tools and nsec.app read), then the NIP-46
  appendix's `name=_` announcement (signer key, relays,
  nostrconnect_url). Relays are normalized and capped; a
  nostrconnect_url must be a web page with a `<nostrconnect>` slot.
  NostrConnectURI.fillNostrConnectUrl fills it.
- Commons: Nip05SignerLoginUseCase connects with no secret, or opens the
  signer's page with a nostrconnect:// code through
  RemoteSignerAuthPrompts (the same dialog as auth_url), then requires
  the signer's account to be the address's key (SignerMismatchException).
  AccountSessionManager tries it for `name@domain` before the read-only
  login; LoginViewModel only allows it where remote-signer login is
  supported.
- amy: `amy login name@domain` logs in through the signer and adds
  `nip05` to its output; `--read-only` keeps the old login; pages to
  approve go to stderr. LoginCommand.nip05ClientBuilder is a test seam.

Tests: parser shapes and precedence (quartz), the use case against an
in-process signer (legacy, mismatch refused, the signer's page carrying
the code), AccountSessionManager saving a signing account or the
read-only one, and `amy login bob@signer.example` end to end against a
geode relay with the domain document served from memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgJn7fqMFnv58kvLC1soen
2026-10-20 16:01:44 +00:00
..