> ## Documentation Index
> Fetch the complete documentation index at: https://285e39fd5e337e58f16290.sightscreen.app/llms.txt
> Use this file to discover all available pages before exploring further.

# System context

> High-level diagram of all systems and how they connect in the Sightscreen platform.

## System context diagram

This shows every system and external service in play, and the connections between them.

```mermaid theme={null}
graph TB
    iOS["iOS App<br/>(SwiftUI, ActivityKit, Live Activities)"]
    Pavilion["Admin iOS App (Pavilion)<br/>(match management, monitoring)"]
    Backend["Backend API<br/>(Express / TypeScript / Node.js)"]

    SportMonks["SportMonks Cricket API<br/>(fixture data, live scores)"]
    MockSM["mock-sportmonks<br/>(replay testing service)"]
    DynamoDB["AWS DynamoDB<br/>(all persistent storage)"]
    Cognito["AWS Cognito<br/>(user auth, JWT tokens)"]
    APNs["Apple APNs<br/>(push notifications,<br/>Live Activity updates)"]

    iOS <-->|REST API| Backend
    Pavilion <-->|REST API| Backend
    Backend -->|"Poller 1: all matches<br/>(ScorePoller)"| SportMonks
    Backend -->|"Poller 2: marquee league<br/>(MarqueePoller, ball data)"| SportMonks
    Backend -->|"Push via LACoordinator"| APNs
    Backend <-->|Read / Write| DynamoDB
    Backend <-->|Auth / Token verification| Cognito
    APNs -->|Notifications + Live Activities| iOS
    MockSM -.->|Replays recorded matches| Backend
```

## How data flows

<Steps>
  <Step title="Ingest">
    Two pollers fetch data from SportMonks. **ScorePoller** polls all active matches on a schedule with Cockatiel resilience (timeout, circuit breaker, retry). **MarqueePoller** polls the marquee league at higher frequency with ball-by-ball data included.
  </Step>

  <Step title="Detect">
    Raw score data flows into **MatchEventBus**, which routes it through the event detection pipeline. **Tier0EventDetector** catches high-priority events (wickets, milestones). **Tier1EventDetector** catches routine updates (score changes, over completions). Events pass through **CooldownFilter** and **StalenessFilter** to suppress duplicates and stale data.
  </Step>

  <Step title="Build">
    **DisplayStateBuilder** constructs a **UnifiedDisplayState** from the current match data, ready for both API responses and APNs payloads.
  </Step>

  <Step title="Deliver">
    **LACoordinator** receives prioritized events and coordinates delivery through **ApnsDeliveryService** to all subscribed devices. Priority determines APNs priority header (5 vs 10).
  </Step>

  <Step title="Serve">
    The iOS app also makes direct REST API calls to the backend for on-demand data — fixture lists, match details, standings, etc. **HubDataService** builds data for the admin UI.
  </Step>
</Steps>

## Connection details

| Connection            | Protocol   | Auth                                  | Notes                                                                |
| --------------------- | ---------- | ------------------------------------- | -------------------------------------------------------------------- |
| iOS to Backend        | HTTPS REST | Cognito JWT in `Authorization` header | All endpoints require auth except health check                       |
| Pavilion to Backend   | HTTPS REST | Cognito JWT                           | Admin-scoped token with elevated permissions                         |
| Backend to SportMonks | HTTPS REST | API key in query params               | Rate-limited, polled on intervals with Cockatiel resilience          |
| Backend to DynamoDB   | AWS SDK    | IAM role                              | All persistent storage goes here                                     |
| Backend to Cognito    | AWS SDK    | IAM role                              | Token verification, user pool management                             |
| Backend to APNs       | HTTP/2     | JWT-based APNs auth token             | Delivered via LACoordinator through ApnsDeliveryService              |
| mock-sportmonks       | HTTPS REST | None                                  | Local service that replays recorded SportMonks responses for testing |

<Tip>
  If push notifications stop working, check the APNs auth token expiry first. These tokens are short-lived and need periodic refresh.
</Tip>
