Overview
Every service in the iOS app follows the same pattern:- A Protocol defines the interface
- A Real implementation (e.g.,
CognitoAuthService) talks to the backend - A Fake implementation returns canned data for previews and tests
- All services are
@Observableand injected via@Environment
AppBootstrap
Responsibility: Cold-start phase gating. AppBootstrap orchestrates the app launch sequence, ensuring services initialize in the correct order before the UI becomes interactive.If any phase fails (e.g., maintenance mode detected), AppBootstrap halts and shows the appropriate blocking screen. The user never sees a partially initialized app.
AuthService
Protocol:AuthService
Real implementation: CognitoAuthService
Handles all Cognito-based authentication flows.
Admin detection
Admin status is determined by checking the JWT token’scognito:groups claim. If the user belongs to the admin group, AppUser.isAdmin is true.
Admin detection is read-only on the client. The backend enforces admin permissions independently via its own JWT validation.
LiveActivityService (facade)
Protocol:LiveActivityService
Real implementation: RealLiveActivityService
The facade composes three managers and exposes a unified API to the rest of the app. Views and other services interact with LiveActivityService — never with the managers directly.
NotificationService
Protocol:NotificationService
Real implementation: RealNotificationService
Handles push notification permissions and device registration with dual token management.
Dual tokens
The app manages two distinct APNs tokens:
Both tokens are registered with the backend on launch and whenever they rotate.
ScheduleService
Protocol:ScheduleService
Real implementation: RealScheduleService
Fetches and caches match schedules.
DataSource protocol + ViewSubscriber modifier
A generic pattern for data that needs to be fetched, cached, and optionally polled.DataSource protocol
ViewSubscriber modifier
A SwiftUI view modifier that binds aDataSource to a view’s lifecycle.
LiveMatchesDataSource
ScheduleDataSource
MatchCacheStore
Three-layer cache for match data with intelligent invalidation.Cache layers
Hydration on launch
loadFromDisk() is called during AppBootstrap to hydrate the in-memory cache from disk before other boot tasks run. This means the app can render cached schedules immediately, even before the first network response arrives.
TTL by state
ImageCacheService
Protocol:ImageCacheService
Real implementation: RealImageCacheService
Two-tier image cache for team logos and assets.
The disk cache uses the app group container so both the main app and the widget target can access cached images. This avoids duplicate downloads for team logos shown in Live Activities.
AppConfigService
Protocol:AppConfigService
Real implementation: RealAppConfigService
Checks app configuration on launch.
AdminService
Protocol:AdminService
Real implementation: RealAdminService
Debug-only service for controlling fake mode.
This service is only available in debug builds. It connects to
fake-api.sightscreen.app for testing.