trails/openspec/changes/sops-age-split-cd/specs/secret-management/spec.md
Ullrich Schäfer 57094323d2
SOPS+age secrets, split CD workflows, GitHub OAuth for Grafana
Secrets:
- Add .sops.yaml with age encryption config
- Add encrypted secrets.app.env (app secrets) and secrets.infra.env (Grafana OAuth)
- CD decrypts at deploy time with AGE_SECRET_KEY — all other secrets
  move out of GitHub Actions into version-controlled encrypted files

Split CD:
- cd-apps.yml: triggered by apps/packages changes, builds Docker images, deploys apps
- cd-infra.yml: triggered by infrastructure/ changes, copies configs, restarts services
- Remove monolithic cd.yml

Grafana auth:
- GitHub OAuth (trails-cool org), disable login form
- Remove Caddy basic_auth block and all GRAFANA_* env vars/secrets

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:28:04 +01:00

758 B

ADDED Requirements

Requirement: Encrypted secrets in repository

Production secrets SHALL be stored as a SOPS-encrypted file in the repository, decryptable only with a single age private key.

Scenario: Edit secrets

  • WHEN a developer runs sops infrastructure/secrets.env
  • THEN the file is decrypted in a temporary editor, and re-encrypted on save

Scenario: CD decryption

  • WHEN the CD workflow runs
  • THEN the encrypted secrets file is decrypted using the AGE_SECRET_KEY GitHub secret and provided to docker-compose as an env file

Scenario: Secret audit trail

  • WHEN a secret is changed
  • THEN the change appears in git history as a diff of the encrypted file with a commit message describing what changed