Local edition generates its own credential-wrapping and signing

Task 10180 · Done · Coder · created · updated

Supersedes draft 10156. Security-relevant: a real install's stored AI-provider keys are wrapped with a keypair published in the repo. Reproduction: `infra/local-edition/compose.yml` runs the api with `APP_ENV=local`; without it `apps/api/app/credential_keys.py` has no wrapping key and refuses to store a credential. Under `APP_ENV=local` every secret is wrapped with the published dev keypair and compliance signing uses the published dev P-256 key. Cause: `credential_keys.provider()` accepts a local keypair only in fixture envs; `apps/api/app/local_bootstrap.py::ensure_secrets` generates the session secret and tier-1 key but not the credential keypair or signing key. Fix: have `ensure_secrets` also generate `CREDENTIAL_LOCAL_PRIVATE_KEY` and the compliance signing key on the secrets volume (0600); let `credential_keys.provider()` accept the local keypair when `edition.IS_LOCAL`; drop `APP_ENV: local` from compose and confirm nothing else on the local boot path depends on it (`console_direct`, `auth.session_cookie` warning). Out of scope: the cloud KMS path; any cloud deployment change. Done means: - A fresh `docker compose up -d` with no `APP_ENV` boots and stores a credential. - A unit test pins that a wrapped secret does NOT open with the published dev keypair. - Api suite and `./dc check quick` green.

Outcome

Local edition now generates its own RSA wrapping and P-256 signing keys (0600), refuses the published dev keys, and needs no APP_ENV (proven on the tree image). Quick and api tests green; security lane passed; #6964 merged 1c3320eb1. Dev deploy failed on the runner-workspace fault (draft 10185), not this diff. Memory: none applied.

Pull request

Artifacts

Activity

  • Ready
  • Runner started
  • Runner ended (done)
  • Run
  • Runner started
  • Runner ended (done)
  • Run
  • Runner started
  • Runner ended (done)