Accessibility Preferences
Data Entity
Description
Stores user-controlled accessibility settings including font scale factor, contrast mode, and haptic feedback configuration. Persisted locally for low-latency access and synced to Supabase for cross-device consistency. Consumed by all UI components that adapt to user visual and motor needs.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Surrogate primary key. Generated client-side (UUID v4) to support optimistic offline writes before Supabase sync. | PKrequiredunique |
user_id |
uuid |
Foreign key referencing the authenticated Supabase user. One record per user enforced by unique index. Matches the user_id on the peer_mentor and user_preferences records for the same account. | requiredunique |
font_scale_factor |
decimal |
Multiplicative scale applied to all typographic tokens in the design system. A value of 1.0 represents the default type scale. Bounded within the range [0.8, 2.0] to prevent layout breakage while supporting WCAG 2.2 AA resize requirements (text up to 200%). | required |
contrast_mode |
enum |
Active contrast mode selection. 'standard' applies the default design token color scheme. 'high_contrast' switches foreground/background pairs to the high-contrast token set (minimum 7:1 ratio, WCAG AAA). 'inverted' applies a full luminance inversion for users with photosensitivity. | required |
haptic_feedback_enabled |
boolean |
When true, the app emits haptic feedback on significant interactions (form submission confirmation, tab switches, error states). When false, all programmatic haptic calls are suppressed. Respected by all HapticFeedback.* call sites throughout the Flutter widget tree. | required |
reduce_motion_enabled |
boolean |
When true, suppresses non-essential animations (Wrapped slide transitions, badge celebration overlays, chart animations). Mirrors the OS-level reduce-motion accessibility preference but is independently configurable within the app. Consumed by wrapped-animation-controller and summary-accessibility-provider. | required |
screen_reader_mode_hint |
boolean |
Cached flag indicating whether a screen reader (VoiceOver or TalkBack) was active the last time the app was foregrounded. Not a user-configurable setting — written by screen-reader-detection-service on each resume. Used to enable additional semantic verbosity even when the OS reports reader as off (covers race conditions at startup). | required |
sensitive_field_warning_suppressed |
boolean |
When true, the sensitive-field-warning-dialog is suppressed for the current session. Maps to the SensitiveFieldPrivacyGuard per-session suppression flag for the linked user_preferences record. Persisted here so the suppression survives app restarts while still being user-revocable. | required |
updated_at |
datetime |
UTC timestamp of the most recent local modification to any field in this record. Updated by the client on every write before sync. Used by the sync layer to detect drift between local and remote state. | required |
synced_at |
datetime |
UTC timestamp of the last successful Supabase write for this record. Null if the record has never been synced (offline-only). When synced_at < updated_at, the record has pending unsynced changes and the sync layer should re-attempt. | - |
created_at |
datetime |
UTC timestamp of initial record creation. Set once on first write; never updated. Used to derive user onboarding age for analytics and to order records in audit queries. | required |
Database Indexes
idx_accessibility_preferences_user_id
Columns: user_id
idx_accessibility_preferences_updated_at
Columns: updated_at
idx_accessibility_preferences_sync_pending
Columns: user_id, updated_at, synced_at
Validation Rules
font_scale_factor_range
error
Validation failed
font_scale_factor_range_update
error
Validation failed
contrast_mode_enum_check
error
Validation failed
contrast_mode_enum_check_update
error
Validation failed
synced_at_not_after_future
error
Validation failed
user_id_immutable
error
Validation failed
wcag_contrast_mode_consistency
warning
Validation failed
Business Rules
one_record_per_user
Each authenticated user has exactly one accessibility_preferences row. Enforced by the unique index on user_id. On first login the record is created with all defaults. Subsequent calls use upsert semantics (INSERT … ON CONFLICT (user_id) DO UPDATE).
local_write_before_sync
All preference mutations are written to local storage first (local-storage-adapter) to provide immediate UI response. The sync to Supabase is performed asynchronously. If sync fails, the local record is retained and retried on next app foreground event.
propagate_to_design_token_system
When contrast_mode or font_scale_factor changes, the design-token-provider and token-accessibility-enforcer must be notified synchronously so that all mounted widgets rebuild with the new visual parameters. This is handled via Riverpod's invalidation mechanism on the accessibility preferences provider.
screen_reader_hint_auto_update
The screen_reader_mode_hint field is not user-editable. It is written automatically by screen-reader-detection-service on every AppLifecycleState.resumed event. Manual updates via the settings UI are blocked.
cascade_delete_on_user_removal
When a Supabase auth user is deleted (account removal or GDPR erasure), the accessibility_preferences row is deleted via CASCADE. No soft-delete is required because this is a configuration record with no audit obligation beyond the user's account lifetime.
cross_device_sync_on_session_resume
On session resume (app foreground after background) the local record's updated_at is compared against the Supabase remote record's updated_at. The more recent value wins (last-write-wins). Conflict resolution always favours the record with the higher updated_at timestamp.
rls_user_scope
Supabase Row Level Security restricts all SELECT, INSERT, UPDATE, and DELETE operations to rows where user_id equals auth.uid(). No user may read or modify another user's accessibility preferences.
CRUD Operations
Storage Configuration
Entity Relationships
The screen reader active state in accessibility_preferences determines whether the sensitive field privacy guard applies disclosure warnings defined in sensitive_field_definition records
Each user has exactly one accessibility preferences record controlling font scale, contrast mode, and haptic feedback settings