Secret columns are stored sealed with AES-256-GCM.
internal/seal: a keyring read fromserver.secret_key_file(outsideserver.root, mode 0600). Every value is sealed with associated data<table>.<column>:<row key>, so a value copied to another row or column does not open. The key file is re-read when it changes; a bad file fails closed.- The store seals CI secrets, webhook secrets, mirror tokens and push device tokens. Push devices are looked up by a SHA-256 of the token (migration 0066
push_token_hash). gitbayd serverefuses to start without the key file. It seals any value still in clear, or under a retired key, before it listens, and refuses to start if that fails.gitbayd admin secrets init|rotate|check. init refuses an existing file; run as root, it gives the file to the owner ofserver.root. rotate reseals every value under a new key in one transaction and drops the old keys only after confirming. check exits 1 if any value does not open.- The store sets
synchronous(FULL)explicitly; rotation relies on the reseal commit being durable. - The e2e harness gives each instance a key file. The backup test checks that the archive holds the value sealed and does not hold the key.
deploy/install.shcreates the key on first install. Admin and Architecture pages; #273 leaves Known-Gaps; CHANGELOG with an upgrade note.
Before deploying to bay1: gitbayd admin secrets init as root, then copy /etc/gitbay/secret.key off the host. Downgrading after values are sealed is not supported.
Stacked on !489 (build-failure-report), which is stacked on the web UX MRs.
Closes #273