4 / 8
CLI и Store
Прошлые главы объяснили, что хранится и кто что может увидеть. Эта — про то, чем вы на самом деле пользуетесь день за днём, сидя за терминалом.
Store: единственное место, где секрет живёт в памяти
internal/store.Store — прослойка между зашифрованным файлом и всем
остальным (CLI, TUI, MCP-сервер). Делает она три вещи:
- ленивая расшифровка — файл расшифровывается один раз за процесс, при
первом обращении (
load(), под флагомloaded), а не при каждом чтении; Set/Delete— меняют карту значений в памяти и сразу перезаписывают весьsecrets_fileцеликом черезEncrypt(глава 2) — не точечно, а всем файлом за раз;Run— запускает внешнюю команду, подставив каждый секрет в её окружение черезexec.Cmd.Env, и пишет запись в audit-лог (глава 6).
Всё остальное в проекте — тонкая обвязка вокруг этих трёх операций.
Команды
athanor init
athanor init [--own-key] [--secrets-file PATH]
Создаёт athanor.yaml в текущей директории. Если
~/.config/athanor/identity.txt ещё нет — генерирует новую пару ключей age
и предупреждает про бэкап; если уже есть — переиспользует её (отсюда и "один
ключ на все проекты" из главы 2). --own-key
создаёт identity локально в проекте (./identity.txt) вместо общей — для
случаев, когда нужна более сильная изоляция. --secrets-file меняет путь по
умолчанию (./secrets.enc.yaml) — например, чтобы сразу указать на файл,
общий с другим проектом.
athanor key backup
Печатает содержимое identity-файла в stdout с предупреждением — и больше ничего умного не делает, намеренно. Единственная задача этой команды — дать вам сырой текст, который вы сами положите в менеджер паролей или на бумагу.
athanor add NAME [--expose]
athanor add DB_PASSWORD
value for DB_PASSWORD (hidden): ***
Saved DB_PASSWORD (expose=false)
Значение никогда не передаётся аргументом команды — только через
скрытый ввод (term.ReadPassword, если stdin — терминал; иначе обычная
строка из stdin, для случаев вроде echo "val" | athanor add KEY). Дело не
в перестраховке: аргументы командной строки видны через ps любому
процессу в системе, а скрытый ввод и stdin этого избегают.
Для нового имени expose по умолчанию равен false. При обновлении
существующего секрета отсутствие флага сохраняет прежнюю политику; явный
--expose включает выдачу через get_secret. Чтобы снова выключить её,
измените expose в манифесте на false.
athanor list
Печатает имена секретов и их expose-статус — никогда значения. Тот же
принцип, что и у самого манифеста: список секретов не секретен, секретны
только их значения.
athanor run -- COMMAND [ARGS...]
athanor run -- npm run dev
Всё после -- — argv команды, а не строка shell. Секреты подставляются в
окружение процесса и никуда больше. Это ровно тот же механизм, что и у
run_with_secrets в MCP — просто вызванный человеком напрямую из
терминала, без агента-посредника.
Контрольный вопрос. Почему athanor add не принимает значение секрета
аргументом командной строки (athanor add KEY value), а всегда запрашивает
его отдельно?
Ответ: аргументы команды видны любому локальному процессу через ps —
значение оказалось бы в открытом виде в списке процессов, пусть и ненадолго.
Скрытый ввод и stdin этого не допускают.