# The home page, executed

Everything the home page shows as a call, run end to end against a live Craton
environment, and every figure it prints checked against what came back.

This page is not a tutorial — [the quickstart](../../docs/quickstart.md) is. It
exists so the landing page cannot lie: the block below is extracted verbatim
and executed on every change to Craton, and it fails if the object in the hero
panel is not the object those calls create, or if the backtest strip beneath it
is not the history the archive replays today.

## What you need

* `curl` and `python3`. Nothing else.
* `CEDE_BASE_URL` — the environment to run against, no trailing slash.
* `CEDE_API_KEY` is optional: the block signs up for one if it is unset.

```sh
export CEDE_BASE_URL="https://…"
```

<!-- cede:runnable -->

```bash
set -euo pipefail

: "${CEDE_BASE_URL:?export CEDE_BASE_URL first — the environment to run the home page against}"

# Read one field out of a JSON document on stdin: `field a.b.0.c`.
field() {
  python3 -c 'import json, sys
document = json.load(sys.stdin)
for step in sys.argv[1].split("."):
    document = document[int(step)] if step.isdigit() else document[step]
print(document)' "$1"
}

# 1 — Is this environment serving? No credential needed for this one.
curl -sS --fail-with-body "$CEDE_BASE_URL/health" | field status

# 2 — "→ Get an API key" on the home page is this call, and nothing else:
#     self-service, no human in the loop, the secret shown once.
if [ -z "${CEDE_API_KEY:-}" ]; then
  account=$(curl -sS --fail-with-body -X POST "$CEDE_BASE_URL/signup")
  CEDE_API_KEY=$(printf '%s' "$account" | field api_key.secret)
  export CEDE_API_KEY
  printf 'signed up: %s on the %s plan\n' \
    "$(printf '%s' "$account" | field id)" \
    "$(printf '%s' "$account" | field plan)"
fi

# 3 — The object in the hero panel, written out exactly as the page prints it,
#     less the id the server assigns. A Kanto earthquake box: exposure, peril
#     with the box, limit and attachment, and the index that decides the
#     payout.
cat > kanto-eq-box.json <<'JSON'
{
  "schema_version": "0.1.0",
  "status": "analysed",
  "exposure": {
    "kind": "location_schedule",
    "currency": "JPY",
    "locations": [
      { "ref": "LOC-0001",
        "address_as_given": "2-16-1 Konan, Minato-ku, Tokyo 108-0075",
        "latitude": 35.6284, "longitude": 139.7387,
        "geocode": { "resolution": "rooftop", "confidence": 0.96 },
        "occupancy": "warehouse", "construction": "reinforced_concrete",
        "year_built": 2011,
        "values": { "building": { "amount": 8400000000, "currency": "JPY" } } }
    ],
    "source_fidelity": { "unmapped_columns": [], "guessed_units": [], "ambiguous_rows": [] }
  },
  "peril": {
    "code": "earthquake",
    "region": {
      "description": "Kanto earthquake box: 34.9-36.2N, 139.0-140.6E.",
      "bounding_geometry": {
        "type": "Polygon",
        "coordinates": [[[139.0, 34.9], [140.6, 34.9], [140.6, 36.2],
                         [139.0, 36.2], [139.0, 34.9]]]
      }
    }
  },
  "financial_structure": {
    "limit": { "amount": 2000000000, "currency": "JPY" },
    "attachment": { "value": 6.0, "unit": "M", "index_ref": "kanto-eq-box-magnitude" }
  },
  "trigger": {
    "type": "parametric_cat_in_a_box",
    "index": {
      "name": "kanto-eq-box-magnitude",
      "version": "1.0.0",
      "description": "Largest catalogue magnitude inside the Kanto box, shallower than the depth threshold.",
      "measurement": { "variable": "catalogue_preferred_magnitude", "unit": "M", "statistic": "max" },
      "aggregation_window": { "duration": "PT72H", "alignment": "event" },
      "thresholds": [
        { "label": "attachment", "level": 6.0, "unit": "M" },
        { "label": "exhaustion", "level": 7.0, "unit": "M" },
        { "label": "max_focal_depth", "level": 100, "unit": "km" }
      ],
      "payout_function": {
        "type": "step",
        "points": [ { "level": 6.0, "payout_ratio": 0.25 },
                    { "level": 6.5, "payout_ratio": 0.5 },
                    { "level": 7.0, "payout_ratio": 1 } ],
        "maximum_payout_ratio": 1
      }
    },
    "data_sources": [
      { "id": "usgs-eq-kanto",
        "name": "USGS ANSS Comprehensive Earthquake Catalog - Kanto extract",
        "kind": "quake_catalogue",
        "version": "2026-08-10", "vintage": "2026-08-10" }
    ]
  },
  "period": {
    "inception": "2026-04-01T00:00:00+09:00",
    "expiry": "2027-04-01T00:00:00+09:00",
    "timezone": "Asia/Tokyo"
  }
}
JSON

# 4 — The one-line curl beside the hero panel. What it answers with IS the
#     hero panel.
object=$(curl -sS --fail-with-body -H "Authorization: Bearer $CEDE_API_KEY" -H "Content-Type: application/json" --data-binary @kanto-eq-box.json "$CEDE_BASE_URL/objects")
printf '%s' "$object" > object.json
object_id=$(printf '%s' "$object" | field id)
echo "object: $object_id"

# 5 — Cut a structure from it: the object's own terms, addressable on their
#     own so a backtest has something to run against.
structure=$(curl -sS --fail-with-body -X POST -H "Authorization: Bearer $CEDE_API_KEY" "$CEDE_BASE_URL/objects/$object_id/structures")
structure_id=$(printf '%s' "$structure" | field id)
echo "structure: $structure_id"

# 6 — Replay it over the pinned archive. A job, like every verb.
job_id=$(curl -sS --fail-with-body -X POST -H "Authorization: Bearer $CEDE_API_KEY" "$CEDE_BASE_URL/structures/$structure_id/backtest" | field id)

state=unknown
for _ in $(seq 1 300); do
  job=$(curl -sS --fail-with-body \
    -H "Authorization: Bearer $CEDE_API_KEY" \
    "$CEDE_BASE_URL/jobs/$job_id")
  state=$(printf '%s' "$job" | field status)
  case "$state" in succeeded|failed) break ;; esac
  sleep 0.2
done
if [ "$state" != succeeded ]; then
  printf 'backtest did not succeed: %s\n' "$job" >&2
  exit 1
fi

artifact_path=$(printf '%s' "$job" | field result.backtest.links.self)
curl -sS --fail-with-body \
  -H "Authorization: Bearer $CEDE_API_KEY" \
  "$CEDE_BASE_URL$artifact_path" > backtest.json

# 7 — Every figure the home page prints, as the page prints it. If the live
#     answer and this block disagree, the page is out of date and this example
#     is red — which is the whole point of it.
cat > published.json <<'JSON'
{
  "feed": { "id": "usgs-eq-kanto", "version": "2026-08-10" },
  "run_id": "backtest-v0:ccb03cc66a311880",
  "window": { "from_year": 1986, "to_year": 2025, "years": 40 },
  "statistics": {
    "triggering_years": 6,
    "trigger_frequency": 0.15,
    "burn_rate": 0.04375,
    "limit": { "amount": 2000000000, "currency": "JPY" },
    "largest_annual_payout": { "amount": 1000000000, "currency": "JPY" },
    "total_payout": { "amount": 3500000000, "currency": "JPY" }
  },
  "years": [
    [1986, 0, null, null],
    [1987, 0.5, "usp0003bbq", 6.7],
    [1988, 0, null, null],
    [1989, 0.25, "usp0003sp0", 6.1],
    [1990, 0.25, "usp0004a05", 6.3],
    [1991, 0, null, null],
    [1992, 0, null, null],
    [1993, 0, null, null],
    [1994, 0, null, null],
    [1995, 0, null, null],
    [1996, 0, null, null],
    [1997, 0, null, null],
    [1998, 0, null, null],
    [1999, 0, null, null],
    [2000, 0.25, "usp0009tvj", 6.2],
    [2001, 0, null, null],
    [2002, 0, null, null],
    [2003, 0, null, null],
    [2004, 0, null, null],
    [2005, 0, null, null],
    [2006, 0, null, null],
    [2007, 0, null, null],
    [2008, 0, null, null],
    [2009, 0, null, null],
    [2010, 0, null, null],
    [2011, 0.25, "usp000hzsk", 6.2],
    [2012, 0, null, null],
    [2013, 0, null, null],
    [2014, 0, null, null],
    [2015, 0, null, null],
    [2016, 0, null, null],
    [2017, 0, null, null],
    [2018, 0, null, null],
    [2019, 0, null, null],
    [2020, 0, null, null],
    [2021, 0, null, null],
    [2022, 0, null, null],
    [2023, 0.25, "us7000k46f", 6.1],
    [2024, 0, null, null],
    [2025, 0, null, null]
  ]
}
JSON

python3 - <<'PYTHON'
import json

published = json.load(open("published.json"))
sent = json.load(open("kanto-eq-box.json"))
stored = json.load(open("object.json"))
artifact = json.load(open("backtest.json"))

failures = []

def same(what, expected, actual):
    if expected != actual:
        failures.append(f"{what}: page says {expected!r}, the API answered {actual!r}")

# The hero panel is the stored object, and the stored object is what the
# documented call sent, plus the id the server assigned.
same("the object the API stored",
     {**sent, "id": stored.get("id")}, stored)

same("run_id", published["run_id"], artifact["run_id"])
same("window", published["window"],
     {k: artifact["window"][k] for k in ("from_year", "to_year", "years")})
same("feed", published["feed"],
     {"id": artifact["data_coverage"]["archive"]["feed"],
      "version": artifact["data_coverage"]["archive"]["version"]})

statistics = artifact["statistics"]
for name in ("triggering_years", "trigger_frequency", "limit",
             "largest_annual_payout", "total_payout"):
    same(name, published["statistics"][name], statistics[name])
same("burn_rate", published["statistics"]["burn_rate"],
     statistics["burning_cost"]["burn_rate"])

# The strip, bar by bar: forty years, each with the payout ratio the page
# draws and the occurrence it names.
live = []
for year in artifact["years"]:
    occurrence = year["occurrences"][0] if year["occurrences"] else None
    live.append([year["year"], year["payout_ratio"],
                 occurrence["event_id"] if occurrence else None,
                 occurrence["magnitude"] if occurrence else None])
same("the backtest strip, year by year", published["years"], live)

if failures:
    print("HOME PAGE IS OUT OF DATE:")
    for failure in failures:
        print(" -", failure)
    raise SystemExit(1)

print(f"home page: {len(published['years'])} seasons, "
      f"{published['statistics']['triggering_years']} of them paid, "
      f"burn rate {published['statistics']['burn_rate']} of limit — "
      f"every published figure matches {artifact['run_id']}")
PYTHON
```

## What this proves, and what it does not

It proves that the calls printed on the home page are the calls that produce
what the home page shows, on the environment it is pointed at, today. Both
halves are load-bearing: the object in the hero panel is compared to the object
the API stored, and every number under the backtest strip is compared to the
artifact the archive replays.

It does not prove the page's prose, its rate card or its registry sample. Those
are copy, and copy is judged by the perimeter scan and by a human, not by a
`curl`.
