high priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

CredentialValidator.validatePassword(String password) returns a PasswordValidationResult with individual boolean fields: hasMinLength, hasUppercase, hasDigit, hasSpecialChar
CredentialValidator.isPasswordValid(String password) returns true only when all four constraints pass
Minimum length is exactly 8 characters (7 = fail, 8 = pass)
Uppercase: at least one character in [A-Z]
Digit: at least one character in [0-9]
Special character: at least one of !@#$%^&*()_+-=[]{}|;':",./<>?
Each failing constraint has a corresponding localization key in PasswordValidationResult (e.g., errorKeys: List<String>)
Empty string returns all four constraints as false
isPasswordValid is a pure function consistent with validatePassword — isPasswordValid(p) == validatePassword(p).allPassed
Function is pure, synchronous, and has no side effects

Technical Requirements

frameworks
Flutter
Dart
data models
PasswordValidationResult (hasMinLength: bool, hasUppercase: bool, hasDigit: bool, hasSpecialChar: bool, allPassed: bool, errorKeys: List<String>)
ValidationResult (from task-004)
performance requirements
Executes synchronously under 1ms per call
Safe against inputs up to 1000 characters without performance degradation
security requirements
Password value must never be logged, even partially
Do not trim or normalize the password before validation — validate exactly what the user typed
Constraint rules must match the rules configured in Supabase Auth dashboard to prevent server-side rejection after client-side approval
ui components
PasswordStrengthIndicator widget (future consumer of per-rule results)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Extend CredentialValidator from task-004 by adding the password methods as additional static members. Define the special character set as a constant String in the class to make it easy to update if Supabase Auth rules change. The per-rule result pattern is particularly valuable for this app: users with cognitive disabilities (NHF requirement) benefit from seeing exactly which rule is still unmet rather than a generic 'invalid password' message — design the PasswordValidationResult to directly drive a checklist UI widget. Ensure the special character set in the validator exactly mirrors what is configured in the Supabase project's Auth settings to prevent the common bug of client saying valid but server rejecting.

Testing Requirements

Unit tests using flutter_test: (1) password '1234567' (7 chars) — hasMinLength false, others may pass; (2) 'password' — hasMinLength true, hasUppercase false, hasDigit false, hasSpecialChar false; (3) 'Password1!' — all four true, allPassed true; (4) empty string — all false; (5) 'AAAAAAAA' — hasUppercase true, others false; (6) isPasswordValid returns true iff allPassed is true — verify consistency for 20 sample passwords. Test that localization error keys are non-null strings for each failing constraint.

Component
Credential Validator
service low
Epic Risks (2)
high impact low prob integration

Supabase client initialization may fail silently in certain Flutter environments if environment variables are missing or the anon key is rotated, leading to runtime null-pointer errors throughout the auth layer.

Mitigation & Contingency

Mitigation: Add explicit assertion checks during app startup that verify the Supabase client is initialized before the router resolves. Document required --dart-define keys in the project README and add a CI step that validates their presence.

Contingency: Implement a fallback initialization error screen with a clear message and a retry button. Log initialization failures to crash reporting immediately.

medium impact medium prob technical

The flutter_secure_storage package behaviour differs between iOS Keychain and Android Keystore implementations. On Android, biometric-enrolled devices may require additional authentication to read stored tokens, causing unexpected session read failures.

Mitigation & Contingency

Mitigation: Test the repository on Android devices with and without biometric enrollment early in development. Use accessibility options in flutter_secure_storage to configure whether biometric authentication is required for storage access.

Contingency: If biometric-gated storage causes regressions, fall back to a non-biometric storage option for session tokens (reserving biometric-gated storage for higher-sensitivity credentials only).