critical priority low complexity infrastructure pending frontend specialist Tier 0

Acceptance Criteria

WcagSemanticsLabelResolver is a ConsumerWidget (not StatelessWidget) to enable future Riverpod integration without API changes
Constructor accepts: required `String labelKey`, optional `String? hintKey`, required `Widget child`
All constructor parameters are `final` and the constructor has a `const`-compatible signature
The stub build method wraps `child` in Flutter's `Semantics` widget with placeholder label and hint (e.g., the raw labelKey/hintKey strings) until real resolution is implemented in task-006
The class is exported from the component's public barrel file so it can be imported cleanly from other modules
The file is placed in the correct layer directory consistent with the project's architecture (e.g., `lib/shared/widgets/accessibility/` or equivalent)
No analyzer warnings or lint violations (`dart analyze` passes cleanly)
A brief doc comment on the class describes its WCAG 2.2 AA purpose and the labelKey/hintKey parameters
The stub compiles and can be dropped into a screen as a widget without errors

Technical Requirements

frameworks
Flutter
Riverpod
data models
OrganizationLabelMap
LabelKey
performance requirements
The scaffolded widget must add zero overhead beyond Flutter's own Semantics widget — no additional builds, providers, or computations in the stub phase
security requirements
The public API must not expose internal provider or resolver references — only labelKey, hintKey, and child are part of the external contract
ui components
WcagSemanticsLabelResolver (ConsumerWidget, stub)
Flutter Semantics widget (internal delegate)

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Prefer ConsumerWidget over StatelessWidget from the start — retrofitting Riverpod onto a StatelessWidget later requires adding the `ref` parameter to build(), which is a breaking API change for callers. The scaffold pattern: `class WcagSemanticsLabelResolver extends ConsumerWidget { const WcagSemanticsLabelResolver({super.key, required this.labelKey, this.hintKey, required this.child}); final String labelKey; final String? hintKey; final Widget child; @override Widget build(BuildContext context, WidgetRef ref) { return Semantics(label: labelKey, hint: hintKey, child: child); } }`. The stub intentionally uses raw keys as labels — this will be replaced in task-006.

Place the file at the agreed accessibility widget path and add an export to the barrel. Do not implement provider reads in this task — that is task-006's scope.

Testing Requirements

A single smoke test using flutter_test: pump WcagSemanticsLabelResolver with a known labelKey and a Text child, assert the widget tree contains a Semantics node and the child Text widget renders. This confirms the scaffold compiles and wraps correctly. Full semantic validation is deferred to task-007. The test should run in under 100ms.

Component
WCAG Semantics Label Resolver
infrastructure low
Epic Risks (3)
high impact medium prob integration

WcagSemanticsLabelResolver's Semantics wrappers may conflict with Semantics nodes already defined by existing accessible widgets (e.g., accessible-bottom-navigation, activity-wizard-semantics), causing duplicate or contradictory screen reader announcements that fail WCAG 2.2 AA criteria.

Mitigation & Contingency

Mitigation: Audit all existing Semantics-annotated widgets in the accessibility feature before implementing WcagSemanticsLabelResolver. Define a clear hierarchy rule: WcagSemanticsLabelResolver always merges with, never replaces, existing Semantics nodes. Use Flutter's debugSemantics output in CI to detect conflicts automatically.

Contingency: If conflicts are discovered in testing, introduce a resolverMode parameter to WcagSemanticsLabelResolver allowing it to operate in 'override' or 'merge' mode per call site; coordinate with the Screen Reader Support feature team to align Semantics strategies.

medium impact medium prob technical

If TerminologyAwareTextWidget subscribes to the full terminology map provider rather than the per-key labelProvider family, a single label update will trigger a full widget-tree rebuild across all screens simultaneously, causing jank on devices used by older peer mentors.

Mitigation & Contingency

Mitigation: Implement TerminologyAwareTextWidget using ref.watch(labelProvider(key)) on the per-key family provider from TerminologyRiverpodProviders so that only widgets bound to the changed key rebuild. Verify with Flutter DevTools 'rebuild tracking' in widget tests.

Contingency: If full-map subscriptions slip through code review, add a Riverpod lint rule that flags direct organizationLabelsNotifierProvider subscriptions inside widget build methods and enforces the per-key family pattern.

medium impact low prob security

The TerminologyAdminPreviewScreen requires coordinator-level access, but if role checks rely solely on client-side guard logic without matching Supabase RLS policies, a peer mentor could potentially access the admin preview by manipulating navigation state.

Mitigation & Contingency

Mitigation: Protect the admin preview route with a server-validated role guard that re-fetches the user's role from Supabase on screen initialization, not just from local state. Add a Supabase RLS policy that restricts label map read access for the admin preview endpoint to coordinator and admin roles only.

Contingency: If unauthorized access is discovered in testing, immediately add a middleware role assertion that redirects non-coordinators to the no-access screen and logs the unauthorized navigation attempt for audit.