- TWO_FACTOR_ALLOW_LOG_DELIVERY production opt-in REMOVED: plaintext codes are written to the stdout log ([2FA]/[VERIFY]) only in dev/test builds as a local DEV ONLY feature while email/SMS delivery (P6) is implemented. Production builds have no delivery channel and code issuance fails closed (503) under any configuration — no silent log-based code leak - verification/2FA codes hashed at rest (HMAC-SHA256 via TWO_FACTOR_PEPPER, CHAR(64)); [VERIFY] dev log relay; per-user brute-force budget; password_reset purpose clears lockout for self-service recovery; dummy-bcrypt on login no-user path kills timing oracle - sabredav weak-password list + entropy gate; .env.example ships fail-closed DAV_ADMIN_PASSWORD - delete-account re-auth (current_password + fresh 2FA code when enforced) - prod-tag suite (run-prod-tag-tests.sh) compiles and runs the production 2FA issuance gate: production ALWAYS reports no delivery channel and refuses issuance after the pepper check - startup_checks_test SNAPSHOT_ENC_KEY values built at runtime so gitleaks sees no secret-shaped literals - env-docs parity updated (flag removed, 38 vars)
78 lines
4.1 KiB
Go
78 lines
4.1 KiB
Go
//go:build !dev
|
|
|
|
package user
|
|
|
|
// Tests for the PRODUCTION 2FA issuance gate (twofa_prod.go).
|
|
//
|
|
// LIMITATION (documented — M17): twofa_prod.go is compiled only in a genuine
|
|
// production build (`!dev && !test`). Under BOTH required test runs — the
|
|
// "test,dev" run and the "test,!dev" prod-shape run — the dev/test variant
|
|
// (twofa_dev.go, build tag `dev || test`) is the compiled function and its
|
|
// fail-closed branches (no TWO_FACTOR_PEPPER → refuse; no delivery channel →
|
|
// 503) are unreachable. These tests compile in every `!dev` build and run
|
|
// their assertions ONLY when the prod variant marker reports the real prod
|
|
// functions are live; under the test tag they skip with the same documented
|
|
// rationale the payments package uses (twofa_delivery_prod_test.go).
|
|
//
|
|
// CLOSING THE GAP: run-prod-tag-tests.sh (backend/) runs `go test -tags
|
|
// "!dev,!test" ./handlers/user/` — the ONLY build configuration where
|
|
// twofa_prod.go compiles AND twofaProdVariant is true, so the assertions below
|
|
// actually execute there. The `if !twofaProdVariant { t.Skip(...) }` guards
|
|
// MUST stay: under the CI "test,!dev" matrix the dev/test variants are still
|
|
// the compiled functions (the `test` tag matches `dev || test`), so without
|
|
// the guards those runs would FAIL rather than skip.
|
|
//
|
|
// DELIVERY POSTURE (current): stdout-log delivery of 2FA codes is a
|
|
// DEV/TEST-ONLY local feature. A production build has NO delivery channel of
|
|
// any kind — email/SMS is not wired yet (P6) and there is deliberately no
|
|
// production opt-in to log delivery — so code issuance fails closed
|
|
// unconditionally (after the pepper check) and twoFADeliveryAvailable is
|
|
// always false.
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
// TestTwoFAEnsureIssueAllowed_ProdPredicate pins the production issuance gate:
|
|
// it fails closed without TWO_FACTOR_PEPPER (an unsalted digest in the 1M code
|
|
// space would be offline-brute-forceable) and, with the pepper set, STILL fails
|
|
// closed because a production build has no delivery channel (email/SMS unwired,
|
|
// stdout-log delivery is dev/test-only) — issuance can never succeed until a
|
|
// real transport lands.
|
|
func TestTwoFAEnsureIssueAllowed_ProdPredicate(t *testing.T) {
|
|
if !twofaProdVariant {
|
|
t.Skip("twoFAEnsureIssueAllowed() is the dev/test build's always-allowed variant (twofa_dev.go, `dev || test`); the prod fail-closed branches are unreachable under the test tag — see the file header for the documented limitation")
|
|
}
|
|
|
|
os.Unsetenv(twoFAPepperEnv)
|
|
if err := twoFAEnsureIssueAllowed(); err == nil {
|
|
t.Error("expected issuance refused without TWO_FACTOR_PEPPER in a production build")
|
|
} else if err.Error() != "TWO_FACTOR_PEPPER is not set; refusing to issue a 2FA code (an unsalted digest would be offline-brute-forceable)" {
|
|
t.Errorf("expected the pepper-required error without the pepper, got %v", err)
|
|
}
|
|
|
|
// With the pepper set, a production build STILL refuses: there is no
|
|
// delivery channel (email/SMS unwired, P6; stdout-log delivery is a
|
|
// dev/test-only local feature and there is no production opt-in).
|
|
os.Setenv(twoFAPepperEnv, "test-pepper")
|
|
if err := twoFAEnsureIssueAllowed(); err == nil {
|
|
t.Error("expected issuance refused in a production build with no delivery channel (email/SMS unwired, log delivery dev/test-only)")
|
|
} else if err != errTwoFADeliveryUnavailable {
|
|
t.Errorf("expected errTwoFADeliveryUnavailable with no channel, got %v", err)
|
|
}
|
|
}
|
|
|
|
// TestTwoFADeliveryAvailable_ProdPredicate pins the production delivery
|
|
// predicate: a production build ALWAYS reports no delivery channel — stdout-log
|
|
// delivery is a dev/test-only local feature, never a production channel.
|
|
func TestTwoFADeliveryAvailable_ProdPredicate(t *testing.T) {
|
|
if !twofaProdVariant {
|
|
t.Skip("twoFADeliveryAvailable() is the dev/test build's trivially-true variant (twofa_dev.go, `dev || test`); the always-false production predicate is unreachable under the test tag — see the file header for the documented limitation")
|
|
}
|
|
|
|
if twoFADeliveryAvailable() {
|
|
t.Error("a production build must ALWAYS report NO 2FA delivery channel (email/SMS unwired; stdout-log delivery is dev/test-only)")
|
|
}
|
|
}
|