Подпись защищает не канал загрузки, а саму метаинформацию сборки. Даже если CDN или S3 отдаст подменённый manifest, клиент отклонит его до проверки файлов.

Signed envelope

SignedEnvelope связывает одной Ed25519-подписью:
  • тип payload;
  • key_id публичного ключа;
  • монотонное generation;
  • длину и точные protobuf bytes payload.
Подмена типа, номера поколения или любого байта manifest нарушает подпись. key_id является коротким SHA-256 идентификатором публичного ключа и не содержит секретных данных.

Подготовка ключа

Команда создаёт 32-byte Ed25519 seed в hex. Делать это нужно один раз на защищённой операторской машине.
Publisher читает seed локально, создаёт manifest.envelope.pb, загружает его рядом с прежним manifest.json и не добавляет сам ключ в upload plan. Если настроен [control_plane], тот же envelope устанавливается через authenticated admin gRPC либо общий volume только после успешного завершения S3-транзакции.
Не генерируйте production-ключ при запуске контейнера. Потеря seed без заранее подготовленного следующего ключа блокирует выпуск новых доверенных сборок; утечка требует немедленной ротации и отзыва ключа.

Поколения

release.generation увеличивается при каждой новой публикации. Launcher хранит последнее принятое поколение и не принимает более старое, даже если его подпись математически корректна. Повторять номер для другого содержимого нельзя.

Ротация

Ротация выполняется офлайн через wraithbound-keyctl, а не через админку:
  1. Создайте следующий private key и экспортируйте его public key.
  2. Командой registry-add --state active добавьте public key в keys.json.
  3. Разверните реестр с двумя active ключами, продолжая подписывать bundle прежним ключом.
  4. Выпустите launcher, который принял обновлённый bundle.
  5. Замените mounted private key сервиса на новый. Launcher-server проверит, что он присутствует в реестре со статусом active.
  6. Переведите старый key ID в retiring, а после переходного периода — в revoked.
Каждое изменение реестра увеличивает generation. Новый JSON сначала пишется во временный файл; при Windows-замене существующая версия сохраняется как backup до успешной активации. Точные команды и порядок ротации описаны в tools/keyctl/README.md. Корневой ключ trust bundle должен быть отделён от online manifest key. Текущий первый этап использует единый ключ сервиса; перед production rollout требуется закрепить offline root public key в проверяющих native binaries.