# glofas-flood-depth-la-plata: governed folia/0.1 recipe.
#
# THE STATIC-CATALOG DEMAND FIXTURE (tickets sdk/050 + sdk/051). 100-year river
# flood depth over a window on the Rio de la Plata estuary, read from @jrc/glofas-flood-hazard.
# The dataset's only registry distribution is a Portolan STATIC catalog on Source Cooperative
# (registry/datasets/jrc/glofas-flood-hazard/distributions/source-coop.yaml + the catalog source
# record registry/sources/source-coop/nlebovits.yaml, `search: static`): a self-contained STAC
# tree on object storage with NO /search server. Resolving the `@jrc/glofas-flood-hazard` source
# layer therefore exercises the catalog-search resolver's SECOND search backend (client-side
# `collection.json` walk + versions.json sha256 pins), the thing sdk/050 M1 lands.
#
# STATUS (2026-07-22). The full path landed: sdk/050 (static walk + versions.json pins) and
# sdk/051 (catalog_raster, the plain catalog raster read). The recipe RAN end-to-end on
# 2026-07-22 (mean 5.27 m over the flooded footprint, sha256-pinned lock). It currently FAILS
# LOUDLY at resolve with a MANIFEST DRIFT error — correct behavior: the upstream versions.json
# is stale (objects republished 2026-06-17 at 55.4 MB; manifest still pins 21.9 MB), so the
# engine refuses to mint a lock naming bytes it would not execute. Goes green again when
# upstream regenerates versions.json (see README, and the upstream-issue list in
# docs/platform_research/portolan/README.md).
#
# METHOD. One source layer selects the `depth-rp100` STAC collection (collection id -> canonical
# band key via the distribution's band_mapping) over a param-driven bbox. Depth is Float32 meters,
# NoData -9999; 0 = modeled dry, >0 = modeled inundation. A raster_calc mask keeps only the flooded
# (>0) pixels as valid, so the terminal `type: answer` layer (op: summary, ADR-0071 D2) reports the
# mean depth OVER THE FLOODED SET: the honest "how deep is the 100-yr flood where it floods"
# number, not a dry-pixel-diluted average.
#
# SPELLING (ADR-0074 D3 + sdk/051 decision 2). The source layer names `op: catalog_raster`
# EXPLICITLY: the automatic `ref:` desugar targets imagery_composite (the index compositor)
# and single-band non-imagery reads are exactly what catalog_raster exists for. The explicit
# source-op spelling is the sanctioned form for this op until the D3 auto-desugar decision;
# it is exempt from the deprecated-alias warning.

spec_version: folia/0.1
name: glofas-flood-depth-la-plata
version: "0.1.0"
description: >
  100-year river flood depth over a Rio de la Plata window, read from the JRC GloFAS global flood
  hazard maps published as a Portolan STATIC catalog on Source Cooperative. The single source layer
  resolves through the catalog-search static search backend (collection walk + versions.json sha256
  pins); a flooded-pixel mask feeds a terminal answer layer reporting the mean modeled inundation
  depth. The demand fixture for sdk/050 (static-catalog search backend).

parameters:
  bbox:
    type: array
    items: number
    description: >
      AOI bounding box [w, s, e, n] in WGS84 lon/lat. Default is the byte-verified ground-truth
      window on the Rio de la Plata estuary near Buenos Aires / La Plata (probe 2026-07-21).
    default: [-58.05, -34.95, -57.85, -34.80]
    min_items: 4
    max_items: 4

layers:

  # ── SOURCE: the 100-yr flood-depth raster. ──
  # Explicit `op: catalog_raster` (sdk/051): the PLAIN catalog raster read — no index math, no
  # temporal reduction, no imagery search policy. `bands: [depth-rp100]` maps to the item asset
  # "data" via the distribution band_mapping; the resolution walks the `search: static` Portolan
  # tree (sdk/050) and pins each tile's versions.json sha256. A bbox spanning several
  # 10x10-degree tiles mosaics FIRST-WINS in pinned-HREF order (pure key material).
  # (051 design decision 2: the op is named explicitly; automatic `ref:` desugar for
  # non-imagery datasets is a separate ADR-0074 D3 decision.)
  source/depth-rp100:
    type: raster
    description: >
      GloFAS CEMS-GLOFAS v2.1.2 modeled 100-year-return-period river flood water depth (meters,
      Float32, NoData -9999), 90 m, EPSG:4326, over the AOI. One COG per 10x10-degree tile; the
      resolver enumerates the tile(s) the bbox touches by walking the depth-rp100 collection.
    compute:
      op: catalog_raster
      params:
        uri: "@jrc/glofas-flood-hazard"
        bands: [depth-rp100]
        bbox: { param: bbox }
        resolution: 90
        # temporal here is NOT temporal math (this op has none; the static walk ignores it):
        # distribution SELECTION routes by time-coverage window, so the request window must
        # sit inside the distribution's verified coverage. For a static product that means
        # its release/vintage window (CEMS-GLOFAS v2.1.2 = 2016-2021). Making temporal truly
        # optional = the atemporal-request follow-up in ticket 051.
        temporal: ["2016-01-01", "2021-12-31"]

  # ── COMPUTE: keep only the flooded pixels. ──
  # depth > 0 = modeled inundation; elsewhere -> NaN (b1 / 0.0 yields NaN per the calc VM's
  # divide-by-zero semantics), which basic_stats skips. So the downstream mean is the mean depth
  # WHERE THE FLOOD REACHES, not diluted by the modeled-dry 0-depth pixels. Any -9999 NoData the
  # read leaves in place also fails the >0 test and drops out.
  compute/flooded-depth:
    type: raster
    description: >
      The 100-yr depth raster masked to its flooded (>0 m) footprint. Modeled-dry and NoData pixels
      become NaN. This is the "show your work" layer behind the flooded-depth answer.
    compute:
      op: raster_calc
      inputs:
        raster: { layer: source/depth-rp100 }
      params:
        expression: "where(b1 > 0.0, b1, b1 / 0.0)"
        output_band: depth_flooded

  # ── ANSWER: the mean flooded depth (ADR-0071 type: stats answer). ──
  answer/flood-depth:
    type: answer
    description: >
      Mean / min / max / count of modeled 100-yr flood depth over the flooded footprint in the AOI.
      Terminal `type: answer` layer -> Data::Answer(AnswerDoc) via op: summary (builtin:summary@1).
      `count` is the flooded-pixel count; `mean` is the mean inundation depth in meters.
    compute:
      op: summary
      inputs:
        raster: { layer: compute/flooded-depth }
      params:
        stats: [mean, min, max, count]

outputs:
  flood_depth:
    layer: answer/flood-depth
    value_kind: answer
    description: Mean 100-yr flood depth over the flooded footprint (meters). THE answer.
  flooded_depth:
    layer: compute/flooded-depth
    value_kind: raster
    description: The depth raster masked to its flooded footprint (show-your-work).

extensions:
  folia/category: events-hazards
  folia/themes: [hydrology, hazards]
  folia/family: flood-hazard-exposure
  folia/license:
    recipe: Apache-2.0
    output_dataset: CC-BY-4.0
    upstream_data:
      - { source: jrc-glofas-flood-hazard, license: CC-BY-4.0 }
  # Static-catalog demand fixture for sdk/050 (products/sdk/tickets/050-static-catalog-search-backend.md).
  # Registered by the portolan-integration-probe (2026-07-21). Ground truth byte-verified vs rasterio.
