# Crashlytics JSON contract

The Crashlytics page reads `assets/crashlytics.json`. This document defines the schema.

## Top-level fields

| Field | Type | Description |
|-------|------|-------------|
| `generated_at` | ISO 8601 string | When this snapshot was produced |
| `app_version` | string | Latest app version covered |
| `platform` | "Android" / "iOS" | Platform |
| `data_source` | "sample" / "csv" / "bigquery" / "reports-api" | Origin of the data; the page renders a banner when `sample` |
| `period_days` | integer | Look-back window (typically 30) |
| `summary` | object | KPI block (see below) |
| `trend` | object | Time-series for the trend chart |
| `by_version` | array | Per-version breakdown |
| `by_os` | array | Per-OS-version breakdown |
| `by_country` | array | Per-country breakdown |
| `top_issues` | array | Top crashes (cap at 25) |
| `anrs` | array | Top ANRs |

## summary

| Field | Type | Note |
|-------|------|------|
| `crash_free_users_pct` | number | 0-100, primary KPI |
| `crash_free_sessions_pct` | number | 0-100 |
| `total_crashes` | integer | Over `period_days` |
| `users_affected` | integer | Distinct users |
| `total_sessions` | integer | Total app sessions |
| `anr_rate_pct` | number | 0-100 |
| `anrs_total` | integer | ANR occurrences |
| `trend_pct_vs_prev` | number | + / - delta vs previous period |
| `open_issues` | integer | Issues not yet resolved |
| `regressions` | integer | Issues that re-opened |

## top_issues[]

| Field | Type | Note |
|-------|------|------|
| `id` | string | Crashlytics issue ID |
| `rank` | integer | 1-based |
| `title` | string | Exception class — `java.lang.NullPointerException` etc. |
| `subtitle` | string | File:line + brief description |
| `users_affected` | integer | |
| `crash_count` | integer | |
| `first_seen` | YYYY-MM-DD | |
| `last_seen` | YYYY-MM-DD | |
| `versions_affected` | string[] | |
| `os_affected` | string[] | |
| `matched_finding_id` | string | Optional — F001-F237 from the static review; enables cross-linking |
| `stack_top` | string[] | First 1-3 stack frames |
| `console_url` | string | Deep link to Firebase Console |

## How to populate

Three ways; pick the one that fits your operations.

1. **Manual export** — In the Firebase Console, Crashlytics → "Export issues" → CSV. Run `scripts/import-crashlytics.py` to convert. Commit the resulting `assets/crashlytics.json`.

2. **CI scheduled job** — A nightly GitHub Action / Azure Pipeline that calls the Crashlytics Reports API server-side, writes `crashlytics.json`, commits it, and re-deploys.

3. **Live endpoint** — Deploy `scripts/crashlytics-cloud-function.js` and have the page fetch the function's URL instead of the bundled JSON. Update `<script>` `CRASHLYTICS_URL` in `crashlytics.html`.
