Nostr WoT
NostrNIPTooling

nak 0.21.0 читает списки релеев и разрешает пути petname

Описание релиза пустое, поэтому единственным источником сведений о нём остаётся diff. Выделяются два добавления: новая подкоманда для списков релеев NIP-65 и разрешение путей petname, встроенное в общий разборщик публичных ключей, а не в одну команду.

Nostr WoT Newsroom

Статья5 мин чтения

Материал подготовлен редакцией Nostr WoT на основе указанных первоисточников и опубликован автоматически, без индивидуальной проверки человеком.

nak 0.21.0 читает списки релеев и разрешает пути petname

nak, инструмент командной строки для Nostr, получил тег v0.21.0 3 октября 2026 года. Текст публикации пуст, поэтому семнадцать коммитов с момента v0.20.7 остаются единственным свидетельством того, что изменилось. Два из них добавляют возможности, а не исправляют поведение, и оба опираются на спецификации, о которых этот сайт уже писал.

Команда для списков релеев NIP-65

55707c26 добавляет relays.go, файл на 58 строк, который регистрирует новую подкоманду верхнего уровня. Строка её описания задаёт область применения: prints the nip65 relays for a given pubkey, one relay per line.

Она принимает публичный ключ как аргумент или через стандартный ввод и печатает по одному URL релея на строку. Два флага сужают вывод, и каждый снабжён псевдонимом, называющим вторую половину словаря NIP-65:

text
--inbox, --read     only print relays marked as inbox/read
--outbox, --write   only print relays marked as outbox/write

Логику фильтра стоит читать буквально, потому что совмещённый случай не является объединением. Передача обоих флагов требует обеих отметок на одном релее:

go
if wantInbox && wantOutbox {
    if !(rl.Inbox && rl.Outbox) {
        continue
    }
}

Поэтому --inbox --outbox печатает только те релеи, которые обслуживают оба направления, что по NIP-65 даёт неразмеченный тег r, а если не передать ни одного флага, выводится весь список. Вместе два флага сужают набор, а не расширяют его, и это важно, когда вывод подаётся на шаг публикации.

Названия направлений соответствуют роли, описанной в руководстве по маршрутизации NIP-65, опубликованном сегодня же: из исходящих релеев автора забирают его события, а во входящие релеи получателя доставляют события с его упоминанием. Команда делает обе цели пригодными для скриптов без разбора события kind 10002 вручную.

Пути petname, в общем разборщике

Пути petname из NIP-02 появляются в два этапа, и второй исправляет первый. Это та возможность, которую добавили в NIP-02 в редакции, описанной 20 сентября, и ограничили до ASCII в продолжении три дня спустя.

4011cba5 не добавляет команду. Он меняет общий разборщик: parsePubKey получает второй аргумент, публичный ключ, относительно которого ведётся разрешение, и передаёт всё, что начинается с тильды, в новый resolvePetnamePath.

go
func parsePubKey(value string, from nostr.PubKey) (nostr.PubKey, error) {
	value = strings.TrimPrefix(value, "nostr:")

	if strings.HasPrefix(value, "~") {
		return resolvePetnamePath(value, from)
	}

Этот помощник вызывает sys.ResolvePetnamePath с тайм-аутом в пять секунд. Его комментарий описывает механизм и приводит смешанную форму, которую допускает NIP-02: путь ~erin/david/frank проходит по списку подписок каждого имени в цепочке, а первое имя может быть вместо этого идентификатором NIP-05, как в [email protected]/david/frank. Поскольку нижележащий поиск профиля скрывает ошибки NIP-05, неудачное разрешение перепроверяется через nip05.QueryIdentifier, чтобы проблема DNS или HTTP сообщалась как она есть, а не как неразрешимый petname. Коммит обновляет все места вызова и добавляет 239 строк тестов.

Чего этот этап не решает, так это от какого ключа начинается относительный путь. Pull request #220, влитый 25 сентября, добавляет petname_cli.go и обёртку parsePubKeyForCommand, которая классифицирует корень:

go
absolute := hexErr == nil || nip05.IsValidIdentifier(parts[0]) ||
    (nip19Err == nil && (prefix == "npub" || prefix == "nprofile"))

Путь, укоренённый в шестнадцатеричном публичном ключе, корректном идентификаторе NIP-05 либо в npub или nprofile, считается абсолютным, и комментарий фиксирует, почему этот случай выделен: Absolute roots must also work without access to a signing key. Только относительный путь вызывает gatherKeyerFromArguments и берёт публичный ключ этого подписывающего за точку отсчёта. Чтение наружу от того, кого можно назвать, не требует ключа, а путь, начинающийся от ваших собственных подписок, требует.

Тот же pull request исправляет проблему порядка аргументов. Вызов в init применяет deferPetnameFlags ко всему дереву команд и заменяет каждый флаг, несущий публичные ключи, обёрткой, которая сохраняет исходную строку и разрешает её лишь после разбора всех флагов. Комментарий объясняет причину: флаг подписывающего, например --sec, может стоять в командной строке после флага petname, а разрешению нужен подписывающий. Он добавляет ещё 169 строк тестов.

Автодополнение и три меньших исправления

5f28b21c выставляет EnableShellCompletion: true на корневой команде, что открывает nak completion bash, zsh и fish. В README добавлены три пути установки для оболочек, чей пакет этого не делает.

Три исправления поведения узки, но каждое закрывает случай, когда инструмент делал что-то бесполезное вместо того, чтобы сообщить о проблеме:

  • 30551476 добавляет --github к nak event, и строка описания объясняет причину: treat empty stdin as no stdin at all, as GitHub Actions always opens it. В этой среде всегда открытый, но пустой стандартный ввод нельзя было отличить от ввода по конвейеру.
  • nak key encrypt с единственным аргументом теперь завершается с ошибкой no password given or key piped on stdin, если стандартный ввод не является конвейером, вместо того чтобы читать этот одинокий аргумент как пароль, не имея ключа, к которому его применить.
  • blossom убирает Required: true из флага --server, так что сервер можно задать на уровне подкоманды, а его отсутствие теперь даёт no server specified. blossom upload получает --auto, который разрешает медиасерверы, объявленные текущим пользователем. nsite download принимает указатель nevent1 или naddr1 наряду с URL сайта и забирает данные с релеев записи автора и по подсказкам, которые несёт указатель.

Что это значит на практике

Оба добавления убирают по одному шагу, который прежде делали руками все, кто пишет скрипты для Nostr. Ответ на вопрос, куда публиковать и откуда читать, больше не требует получать и разбирать событие kind 10002, а путь по подпискам можно написать там, где раньше стояла шестнадцатеричная строка из 64 символов. Ни то, ни другое не меняет спецификаций: это инструмент догоняет NIP-02 и NIP-65 в том виде, в каком они уже существуют. Правило абсолютного корня стоит запомнить, потому что путь petname, начинающийся от ваших собственных подписок, попросит ключ.

Источники

Каждое утверждение в этом материале ссылается на первоисточник.

  1. nak v0.21.0 — fiatjaf/nak (3 октября 2026 г.)
  2. Сравнение v0.20.7...v0.21.0 — fiatjaf/nak (3 октября 2026 г.)
  3. nak relays — fiatjaf/nak (1 октября 2026 г.)
  4. petname support in parsePubKey() — fiatjaf/nak (17 сентября 2026 г.)
  5. Pull request #220: Resolve relative petnames using the selected signer — fiatjaf/nak (25 сентября 2026 г.)
  6. enable shell completion generation — fiatjaf/nak (1 октября 2026 г.)
  7. Correct nak event behaviour if 0 lines received from an open stdin — fiatjaf/nak (25 сентября 2026 г.)

Ещё от редакции

Будьте в курсе

Получайте новости о выпущенных версиях Nostr WoT, новых функциях и интеграциях.

Вы будете получать рассылку на русском языке.

Мы сохраняем ваш адрес электронной почты и предпочитаемый язык для отправки рассылки.

Рассылки