Wire admin portal URL from config repository into service
epic-no-access-screen-access-control-task-003 — Connect AccessDenialService to the no-access config repository (052-no-access-config-repository) so that getAdminPortalUrl() returns the environment-specific admin portal URL. Ensure the URL is read lazily and cached after first access to avoid repeated repository calls.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Implement lazy caching with a nullable instance field: String? _cachedAdminPortalUrl. In getAdminPortalUrl(): if (_cachedAdminPortalUrl != null) return _cachedAdminPortalUrl!; final url = await _configRepository.getAdminPortalUrl(); _cachedAdminPortalUrl = url; return url;. This pattern is idiomatic Dart and avoids over-engineering with a separate cache abstraction.
Add a simple HTTPS validation assert in debug mode: assert(url.startsWith('https://'), 'Admin portal URL must use HTTPS'). Do not use static fields for the cache — this would make the cache survive service recreation, breaking test isolation and environment switching.
Testing Requirements
Unit tests using flutter_test and mocktail. Mock INoAccessConfigRepository. Test scenarios: (1) first call invokes repository and returns URL, (2) second call returns cached value and repository mock was called exactly once (verify(mockRepo.getAdminPortalUrl()).called(1) total across both calls), (3) repository throws → exception propagates through getAdminPortalUrl(). No integration tests needed for this isolated wiring task.
If the GoRouter redirect callback evaluates the no-access route itself as a blocked destination, it will trigger an infinite redirect loop, crashing the navigator.
Mitigation & Contingency
Mitigation: Add an explicit guard condition in the redirect callback: return null (no redirect) when the current location is already the no-access route or the logout route. Write a dedicated unit test covering this exact scenario.
Contingency: If the redirect loop is detected in production, deploy a hotfix that adds the null-return guard; the feature can be toggled off via the existing feature-flag infrastructure while the fix is prepared.
The access-denial-service may read role state before authentication completes (e.g. during app resume), causing a temporary false-positive block that redirects valid peer-mentor users to the no-access screen.
Mitigation & Contingency
Mitigation: Subscribe to the role-state-manager's loading/ready lifecycle and only evaluate role-based access once the RBAC state is confirmed as loaded. Return a 'pending' state that causes the guard to defer rather than redirect.
Contingency: Add a retry mechanism: if a user lands on the no-access screen but their role subsequently resolves as non-blocked, automatically navigate them to the role-based home screen.