A failed staging-only deploy exposed the multiline staging SSH key in Gitea logs and then stopped because root-run deployment validation conflicted with deploy-owned mode-0600 env files. Public staging never switched from the previous SHA; production was not involved.
Immediate containment completed
rotated the staging ED25519 key in Gitea and GitHub
verified the new key before revoking the old authorized key
proved the old key no longer authenticates and deleted the old local key
No production workflow, key, migration, or deployment was changed or triggered.
## Incident
A failed staging-only deploy exposed the multiline staging SSH key in Gitea logs and then stopped because root-run deployment validation conflicted with deploy-owned mode-0600 env files. Public staging never switched from the previous SHA; production was not involved.
## Immediate containment completed
- rotated the staging ED25519 key in Gitea and GitHub
- verified the new key before revoking the old authorized key
- proved the old key no longer authenticates and deleted the old local key
- deleted 28 potentially affected Gitea deploy/migration runs
- retained the successful quality gate and immutable image manifest, which never received the SSH secret
## Code changes
- store staging SSH secret as one unwrapped base64 line
- decode only into a mode-0600 temporary key and validate with `ssh-keygen`
- reject direct multiline secret injection in contract tests
- make deploy/migration validate env ownership against the deployment tree owner
- preserve owner/gid when rollout atomically replaces `.env.staging`
- record BUG-128 and ERR-094; document the base64 secret contract
## Verification
- staging workflow contracts: 31/31
- personal report focused: 142/142
- explicit owner validator regression: pass
- YAML and shell syntax: pass
- TypeScript and targeted ESLint: pass
- mandatory pre-work: pass
- strict SSH with rotated key: pass
- remote env owner/mode: deploy:deploy 0600
- complete Docker fixtures: pending PR quality-gate runner (local Docker CLI unavailable)
No production workflow, key, migration, or deployment was changed or triggered.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Incident
A failed staging-only deploy exposed the multiline staging SSH key in Gitea logs and then stopped because root-run deployment validation conflicted with deploy-owned mode-0600 env files. Public staging never switched from the previous SHA; production was not involved.
Immediate containment completed
Code changes
ssh-keygen.env.stagingVerification
No production workflow, key, migration, or deployment was changed or triggered.