trusted proxy, TOTP replay protection, new tests

- Trusted proxy config option for proxy-aware IP extraction
  used by rate limiting and audit logs; validates proxy IP
  before trusting X-Forwarded-For / X-Real-IP headers
- TOTP replay protection via counter-based validation to
  reject reused codes within the same time step (±30s)
- RateLimit middleware updated to extract client IP from
  proxy headers without IP spoofing risk
- New tests for ClientIP proxy logic (spoofed headers,
  fallback) and extended rate-limit proxy coverage
- HTMX error banner script integrated into web UI base
- .gitignore updated for mciasdb build artifact

Security: resolves CRIT-01 (TOTP replay attack) and
DEF-03 (proxy-unaware rate limiting); gRPC TOTP
enrollment aligned with REST via StorePendingTOTP

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 17:44:01 -07:00
parent f262ca7b4e
commit ec7c966ad2
31 changed files with 799 additions and 250 deletions

View File

@@ -303,7 +303,7 @@ func TestE2EAdminAccountManagement(t *testing.T) {
// Set roles.
resp3 := e.do(t, "PUT", "/v1/accounts/"+carolUUID+"/roles", map[string][]string{
"roles": {"reader"},
"roles": {"user"},
}, adminToken)
mustStatus(t, resp3, http.StatusNoContent)
_ = resp3.Body.Close()
@@ -315,8 +315,8 @@ func TestE2EAdminAccountManagement(t *testing.T) {
Roles []string `json:"roles"`
}
decodeJSON(t, resp4, &rolesResp)
if len(rolesResp.Roles) != 1 || rolesResp.Roles[0] != "reader" {
t.Errorf("roles = %v, want [reader]", rolesResp.Roles)
if len(rolesResp.Roles) != 1 || rolesResp.Roles[0] != "user" {
t.Errorf("roles = %v, want [user]", rolesResp.Roles)
}
// Delete account.