feat(e2e): bunyip-e2e-bootstrap --enable-2fa enrolls a preset TOTP secret (BUNYIP-359) #367
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/BUNYIP-359-bootstrap-2fa"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
BUNYIP-359: add an opt-in
--enable-2fatobunyip-e2e-bootstrapthat enrolls a PRESET TOTP secret, so a re-seeded E2E account keeps a stable, known secret and the shared ForgejoE2E_*_TOTP_SECRETnever has to be rotated on a staging wipe.Why
Enabling 2FA was interactive-only:
TotpService::begin_setupmints a fresh random secret andconfirm_setupneeds a live code. So every wipe + re-seed forced a manual hub enrollment and a secret rotation. The recent staging-wipe incident had to run the account with 2FA off to avoid that.Changes
TotpService::enroll_preset(user_id, base32_secret)(crates/bunyip-domain/src/services/totp.rs): decode the preset base32 (normalized to the encodingbegin_setupemits), sanity-check it builds a usable TOTP, then encrypt + store it via the SAME AES-256-GCM key set and the sameupsert_totp+mark_verifiedwrites asbegin_setup+confirm_setup. The stored secret verifies through the normal login path. Documented as non-interactive-provisioning-only (no possession proof); never called from a handler.--enable-2faflag (bunyip-api/src/bin/bunyip_e2e_bootstrap.rs): opt-in (default off). ReadsBUNYIP_E2E_TOTP_SECRET(fail-loud if unset), builds theTotpServicefrom the same config the API uses (TOTP_ENCRYPTION_KEY+app_name), and enrolls it on every seeded account (E2E_ACCOUNT_EMAILS). Run in the API container so the key matches. Idempotent.docs/e2e.mdprovisioning + 2FA steps now prefer--enable-2fawith a stable preset secret; manual UI enrollment kept as the alternative.Decisions (from the issue)
E2E_*_TOTP_SECRET).Testing
just check-containerforbunyip-domain+bunyip-api:fmtclean,clippy --all-targets -- -D warningsclean, tests pass (bin template test green). No DB-backed unit test added: the service's test module is pure (no#[sqlx::test]harness to mirror), andenroll_presetreuses the already-testedencrypt+ repository writes; the end-to-end proof is the E2E suite once staging is re-seeded with--enable-2fa.