Environmental Screening Tool — Methodology
Pilot v0.1 · 21 indicators · 20 inland water bodies
← Back to dashboard
Contents
  1. What the tool produces
  2. Regulatory pathway engine (EIAfinder)
  3. Spatial environmental profile (SafeGround)
  4. Galamsey screening — multi-layer scoring
  5. Plausibility cross-check
  6. Reconciliation engine (scoping-report cross-check)
  7. Officer workflow
  8. Architecture
  9. Data lineage and audit reproducibility
  10. Known limitations (honest disclosure)
  11. Citations
  12. Inland Water Body Determination engine
  13. Recent Flood Events layer (16th indicator)
  14. Urban Drainage layer (17th indicator)
  15. REGSEC predictive flood-risk layer (18th indicator)
  16. Cultural Heritage layer (19th indicator)
  17. 7 Open items after sprint-22 agency-hat review (2026-06-26)
  18. Government / Institutional Lands layer (20th indicator)
  19. Fee Estimate Engine (Act 1080 revenue-side taxonomy)
  20. Reconsideration / Enhanced-Mitigation pathway
  21. Sector taxonomy migration (Act 1080 canonical)
  22. Impact Scale classifier (Act 1080 advisory)
  23. Statutory-duration registry
  24. Galamsey Monitor — national district galamsey-pressure ranking
  25. Change log

Screening Tool — Methodology

Decision-support pilot for the relevant Authority of Ghana under L.I. 2504 (2025) / Act 1124 (2025).

Compiled by: Dr. Minka Aduse-Poku, Resilicity · Hürth, North Rhine-Westphalia · minka@resilicity.de Status: pilot v0.1 · 2026-05-22 · live at https://scoping.resilicity.com/ Disclaimer: this document describes a decision-support tool. The tool does not issue or refuse environmental permits, does not constitute an Authority determination, and does not replace the statutory functions of assessment officers, the Director-General, or the Board.


1. What the tool produces

For any project location in Ghana, the tool composes three independent analyses into a single auditable output:

Layer Source engine Output
Regulatory pathway EIAfinder rule engine Verdict (requires_eia / requires_registration / requires_sea / requires_epa_consultation / insufficient_information), legal citations from L.I. 2504 First Schedule, indicative fee band (Act 1080), permit lifecycle (Reg 30), public-hearing triggers (Reg 24), transboundary flag, baseline survey list.
Spatial environmental profile SafeGround spatial engine 20 indicators: flood, wetland, river, protected area, road setback, slope, seismic, soil, infrastructure, HT electricity ROW, galamsey, coastal erosion, contamination, groundwater. Each indicator returns red/amber/green/unknown with distance/measurement + source citation.
Plausibility cross-check Tier-1 + Tier-2 benchmarks Detects physical impossibility and order-of-magnitude scale mismatches in the proponent's declared inputs (e.g. cement plant footprint vs production, solar PV ha/MWp vs NREL benchmarks).

These are merged into one Decision Summary card. Every red or amber spatial finding auto-generates a scoping topic for the EIS/EMP, linked to the responsible agency and statutory reference.


2. Regulatory pathway engine (EIAfinder)

2.1 Inputs

Project sector, sub-type (process / mineral / fuel / facility type), scale dimensions (size_ha, capacity_mw, floor_area_m2, bed_count, production_t_per_year, throughput_t_per_day, network_length_km, unit_count, annual_generation_gwh), location (lat/lon), sensitive-area flags, resettlement, hazardous-waste, e-waste, carbon-market, baseline surveys completion status.

2.2 Rule base

JSON-encoded rules referencing L.I. 2504 (2025) First Schedule items 1–204 and the predecessor L.I. 1652 (1999) Schedule mappings. The rule engine is pure: same inputs always yield the same decision.

2.3 Outputs

2.4 Statutory clocks

The Platform applies the L.I. 2504 Reg 28 clock for the case pathway, starting only when the Authority receives a completed application:

Reg 28(2) suspends the applicable clock during public-hearing procedures and time used by the applicant to prepare required material.

Clocks stop when the case status moves to signed_off, rejected, or withdrawn. The dashboard surfaces overdue clocks in real time.


3. Spatial environmental profile (SafeGround)

Each indicator runs independently from the same lat/lon input. Sources are cited per indicator and reflected in the API response.

2.4 Earth Engine activation (2026-06-02)

The pilot is now running against a Google Earth Engine service account (epa-scoping-galamsey@epa-scoping-platform-ee.iam.gserviceaccount.com) on the Noncommercial / Community tier (registered via console.cloud.google.com/earth-engine, project epa-scoping-platform-ee). The credential is installed at /etc/gee/safeground-ee.json (root:www-data, 0640) and exported via the systemd drop-in /etc/systemd/system/ghanascreen.service.d/gee.conf.

What activates with EE: - ✓ Sentinel-2 NDVI delta detection for galamsey layer 4 (Forkuor 2020 Remote Sensing methodology, 2 km buffer, 6-month vs 12-month baseline). Verified live on Densu Delta test point (5.55, −0.31) — satellite.layer_active = true. - ✗ JRC CEMS_GLOFAS return-period flood overlay is currently blocked by an EE asset-access error: "Image asset JRC/CEMS_GLOFAS/FloodHazard/v2_1/RP10 not found (does not exist or caller does not have access)." Tested paths v1/v1_0/v2/v2_1 all return the same error from the noncommercial tier. Likely caused by Google's 2024-2025 EE catalogue reorganisation; under investigation as a separate follow-up. The flood composite still produces results from the other four sub-indicators (natural, wetness, drainage, terrain) — JRC just doesn't add the return-period refinement until this is resolved.

2.6 Spatial Statutory Override Engine

The tool's regulatory verdict from the EIAfinder rule engine classifies projects by ACTIVITY type under L.I. 2504 First Schedule + Act 1124. But Ghana law also binds by LOCATION. A hotel inside a Ramsar wetland is not "requires_eia" — it is prohibited by L.I. 1659, irrespective of what the activity classification says.

The Spatial Statutory Override Engine (backend/app/services/spatial_overrides.py) closes that gap. For every spatial indicator firing RED at the project location, it looks up the specific Ghana statute that binds and ESCALATES the verdict to the strictest of (activity-classification, location-prohibition). The binding statute is cited verbatim alongside the L.I. 2504 grounds.

Override hierarchy (the engine only escalates, never downgrades):

refused > requires_eia > requires_sea > requires_registration

no_permit_required > insufficient_information

Coverage (statutes consulted for each indicator):

Indicator RED triggers Binding statute(s) Verdict
Protected area Inside polygon Wildlife Resources Management Act, 2023 (Act 1115) §§ 21–24; Wildlife Conservation Regulations, 1971 (L.I. 685); Forestry Commission Act, 1999 (Act 571) refused unless Ministerial consent under §24
Wetland (Ramsar) Inside designated site Wetlands Management (Ramsar Sites) Regulations, 1999 (L.I. 1659) Regs 4–8; Ramsar Convention Article 3.1 refused — drainage / reclamation / dredging prohibited
River corridor Inside WRC riparian setback Water Resources Commission Act, 1996 (Act 522) §12 (grant of water right — riparian works require WRC permit); WRC Riparian Buffer Zone Policy 2014 (issued under Act 522 §35) requires_eia without WRC permit; certified riparian-buffer design is the precondition
Road corridor Inside GHA / DUR statutory road reservation Ghana Highway Authority Act, 1997 (Act 540); Streets and Roads Act, 1971 (NLCD 41); National Building Regulations L.I. 1630 (1996) Reg 13; National Road Safety Authority Act, 2019 (Act 993) refused without written GHA / DUR encroachment permission
HT electricity Inside statutory ROW (30 m at 161 kV; 40 m at 330 kV) Transmission Line Protection Regulations L.I. 542 (1967), as amended by L.I. 1737 (2004); Energy Commission Act 541 (1997) §38 refused — ROW construction prohibited
Galamsey Inside hotspot footprint Minerals and Mining Act, 2006 (Act 703) §18; Minerals & Mining (Amendment) Act, 2019 (Act 995); Mining Health, Safety and Technical Regulations, 2022 (L.I. 2462); IMCIM moratorium refused without IMCIM clearance
Contamination Inside immediate zone Hazardous Waste Control and Management Regulations, 2016 (L.I. 1932); EPA Act 1124 §9 refused without remediation
Flood High-probability zone Water Resources Commission Act 522 §13 (prohibition of use of water without authority — sub-clause pending gazette confirmation); National Building Regulations 1996 (L.I. 1630); Ghana Building Code 2018 Part 5 (flood-resilient construction); Ghana Hydrological Authority Act 2022 (Act 1085) §3(c) requires_eia with certified flood-resilience design (elevated foundations, controlled drainage, no sub-grade habitable space)
Seismic High-PGA zone National Building Regulations L.I. 1630 Reg 13; Ghana Building Code GS 1207; Ahulu et al. 2018 PSHA requires_eia with certified seismic-engineering design + structural-engineer-of-record sign-off
Slope Steep-slope class National Building Regulations L.I. 1630; Building Code GS 1207 requires_eia with certified geotechnical study + slope-stabilisation design
Coastal erosion Within actively eroding segment Maritime Zones (Delimitation) Law, 1986 (PNDCL 159); Environmental Protection Act, 2025 (Act 1124) coastal-zone management mandate refused without shoreline-protection plan + coastal-zone consent

Verdict-hierarchy rule (post-2026-06-25 legal review). The engine uses two verdict tiers when a spatial indicator fires RED:

The conditional-override clause carried with each indicator names the specialist study + engineering / regulatory precondition that must be satisfied before the screening can be re-run.

Response shape. The /screen API now returns under verdict: - decision — the strictest verdict (post-override) - original_decision — the EIAfinder activity-only verdict - override_applied — bool: True if any override escalated the verdict - override_headline — one-line summary of the binding prohibition - spatial_overrides — array of {indicator, status, verdict, headline, reason, citations, exception}

Reading the verdict. Each spatial override returned includes (a) the specific indicator and severity (red / amber) that triggered, (b) the prohibition or escalation it forces, (c) the binding statute(s) with section numbers, and (d) the conditional clause under which the prohibition can be lifted (e.g., Ministerial consent, IMCIM clearance, WRC permit). The frontend report surfaces this as a prominent red banner above the standard L.I. 2504 grounds; the determination PDF cites both in §1.

Added 2026-06-02.

2.5 Map basemap imagery — freshness disclosure

Every screening surfaces an imagery-date badge in the bottom-right of the map, so the officer always knows how stale the picture they are looking at is. The badge queries Esri's World_Imagery/MapServer/identify endpoint on each pan / pin and surfaces the SRC_DATE for the tile directly under the project point.

Officers can switch the basemap between three sources:

Layer Resolution Freshness Source
Esri Hybrid (default) sub-metre to 1 m varies — typically 6 months to 4 years Esri World Imagery (Maxar + Airbus + national imagery)
Mapbox Satellite (when token set) sub-metre to 1 m irregular Mapbox / Maxar
Sentinel-2 30-day median composite 10 m ≤ 30 days old (live as of 2026-06-02; window stamped on each tile via X-Tile-Window) Copernicus Sentinel-2 SR Harmonized via Google Earth Engine getMapId(); cloud-masked via SCL; mapId cached 6 h in ghanascreen-backend, tile cache 24 h client-side

Planet NICFI was previously planned as a fourth layer, but Planet pivoted it to a paid "Tropical Forest Observatory" SKU (EUR 1,620/yr, verified 2026-06-02). The pilot uses the Esri date badge + Sentinel-2 route instead, both free.

The freshness ceiling is enforced two ways: 1. Per-layer label — each base-layer button carries a freshness chip ("≤ 30 d" / current month) so officers see the ceiling before they choose. 2. Per-tile date stamp — the badge interrogates the actual tile and shows the SRC_DATE plus an age class (fresh / ok / warn / stale) coloured accordingly.

For galamsey verification specifically, the recommended workflow is to default to Sentinel-2 for the visual scan; the in-tool galamsey check already runs Sentinel-2 NDVI delta detection regardless of which basemap the officer is viewing.

3.0 Per-indicator radius — quick reference

The values below are the live aggregation parameters used by backend/app/api/routes_screen.py::_AGG_META. Every /screen response echoes these alongside each finding, and the determination PDF prints the relevant value under every red/amber/green call.

# Indicator Method Radius / pixel Source dataset
1 Flood (natural) Buffer test 500 m OSM natural=flood_prone polygons
2 Wetland Layered 200 m · ~1 km Ramsar → OSM wetlands → JRC GSW
3 River / riparian Shortest distance 30 / 60 / 120 m (WRC bands by stream order) HydroRIVERS
4 Protected area Point-in-polygon + 200 m amber buffer WDPA 2024
5 Road corridor Shortest distance to centreline OSM motorway / trunk / primary / secondary
6 Slope Pixel sample 90 m pixel Copernicus DEM GLO-30 (Horn 3×3)
7 Seismic hazard Point-in-polygon PGA-band polygons Ahulu et al. 2018 PSHA
8 Soil Pixel sample 250 m pixel ISRIC SoilGrids v2 + WoSIS
9 Infrastructure Shortest distance to nearest feature GSS urban centres + OSM power lines
10 HT electricity Shortest distance 30 / 50 / 100 m ICNIRP bands OSM HV lines; L.I. 542 / L.I. 1737 ROW
11 Galamsey Multi-layer 8 km · 2 km · 25 km (see §4) 97 hotspots + Pra/Ankobra/Tano basins + Sentinel-2 NDVI delta + district prevalence
12 Coastal erosion Segment lookup within 5 km of coast Asare-Bediako 2025; Angnuureng 2023; Boateng 2012 — Ghana EPR
13 Contamination Piecewise distance to nearest curated site Pure Earth + Authority inventories
14 Groundwater Multi-layer 90 m HAND pixel BGS Africa Atlas + GLO-30 HAND + JRC GSW
15 Dam-spillage envelope Point-in-polygon + 500 m amber buffer 6 documented envelopes: Akosombo+Kpong, Weija, Bui, Bagre, Tono, Vea (VRA / GWCL / BPA / SONABEL / ICOUR)

Flood composite — five sub-indicators (returned in the flood_composite.indicators block):

Sub-indicator Method Radius / pixel Source
Natural flood-prone Buffer test 500 m OSM flood-prone polygons
Surface-water wetness Pixel sample 30 m pixel JRC GSW 1984–2021 (Pekel 2016)
Drainage / built-up Pixel sample 1 km pixel GHSL R2023A + GSS urban context
Terrain (HAND + slope) Pixel sample 90 m pixel Copernicus GLO-30
JRC return-period envelopes Buffer test 100 m JRC Global Flood Hazard v2.1 (Dottori — 10 / 100 / 500-yr)

Reading the table. A "pixel" entry means the indicator samples the single raster cell directly under the project location — no buffer applied. A "buffer" or "shortest distance" entry means proximity is the measurement. Where multiple radii are listed, the tool selects the strictest applicable threshold and surfaces the source layer that drove the decision.

3.1 Standard indicators

Indicator Method Data source
Flood risk 4-sub-indicator composite (natural / wetness / drainage / terrain) + JRC return-period overlay (10/100/500 yr) OSM natural=flood_prone + JRC GSW + GHSL R2023A + GLO-30 + JRC Global Flood Hazard Maps v2.1 (Dottori et al., LISFLOOD-FP)
Wetland proximity Ramsar overlay (red) → OSM wetland polygons (red/amber) → JRC GSW wetness % fallback Ramsar Sites Information Service (rsis.ramsar.org, 6 Ghana sites); OSM natural=wetland; JRC Global Surface Water 1984-2021 (Pekel et al. 2016)
River corridor Distance to HydroSHEDS HydroRIVERS (preferred) or OSM rivers (fallback) + WRC riparian setback rules (60/120 m river, 30/60 m stream) HydroSHEDS HydroRIVERS v1.0 (Lehner & Grill 2013; Linke et al. 2019); OSM rivers (Geofabrik Ghana fallback); WRC Riparian Buffer Zone Policy 2014
Protected area Polygon intersect against WDPA boundaries WDPA 2024 release (UNEP-WCMC / IUCN)
Road setback Distance to OSM major roads (motorway/trunk/primary/secondary) OSM Geofabrik Ghana
Slope DEM derivative (Horn 3×3 on the preferred raster) Copernicus DEM GLO-30 (2019; ±4 m vertical) preferred; SRTM 30 m (2000; ±9 m) fallback
Seismic PSHA zone lookup Ahulu et al. 2018 Journal of Seismology doi:10.1007/s10950-017-9721-x
Soil SoilGrids v2 250 m interpolation + WoSIS measured profiles ISRIC SoilGrids v2 (Hengl et al. 2017); WoSIS Dec 2023
Coastal erosion Coastline distance + segment-specific erosion rates CSIR-WRI shoreline studies; Appeaning Addo et al. 2011; Boateng 2012; IPCC AR6 W. Africa coastal profile (2021)
Contamination Distance to curated contamination sites + galamsey-zone advisory Pure Earth / Blacksmith Institute Pollution Atlas; the Authority permit records; CSIR-INSTI (2019); published arsenic/mining studies
Groundwater HAND (Height Above Nearest Drainage) + JRC GSW + BGS Africa Groundwater Atlas JRC GSW; BGS Ghana hydrogeology; GLO-30 HAND (AWS Open Data, CC0)
Infrastructure access Distance to urban centres + OSM power lines (general) GSS urban centres (verified 2026-04-16); OSM power=line (489 segments)

3.2 Ghana-specific indicators

HT electricity (L.I. 1737 ROW) — distance to nearest 161 kV or 330 kV GRIDCo transmission line, classified against:

Galamsey proximity — multi-layer scoring described in detail in §4.

3.3 Synthesis

SafeGround returns a synthesis paragraph that summarises the top 3-4 red/amber findings in plain English. The Platform's orchestrator inherits this paragraph into the Decision Summary card.

3.4 Dam-spillage inundation envelope (#15)

Indicator #15 catches the gap that the JRC return-period flood maps and OSM flood polygons miss: controlled releases from regulated dams do not follow natural-flood return-period statistics — they follow the dam operator's protocol. The 2023 Akosombo spillage (38,624 displaced, 32 communities, 15 Sept – 30 Oct 2023) inundated areas well beyond the JRC 100-yr envelope in several reaches.

Envelopes covered

Envelope Operator Gazette Documented events
Akosombo + Kpong (Lower Volta) Volta River Authority (VRA) Act 46 (1961) 1991, 2010, 2023 (controlled spillage at Maximum Operating Level 84.5 m)
Weija Densu Ghana Water Company Limited (GWCL) Act 522 (1996) GWCL spillage authority 2010, 2011, 2016, 2018, 2020, 2024 (spillage at 48 ft / 14.6 m)
Bui Black Volta Bui Power Authority (BPA) Act 740 (2007) 2022 (Savannah RCC attribution), 2023 Buipe floods (1,500–5,000+ displaced)
Bagre cross-border (White Volta) SONABEL (Burkina Faso) Act 522 + Act 1085 (2022) + Pwalugu Multipurpose Dam Act 2020 Annual August–September since 2008
Tono Irrigation Company of Upper Region (ICOUR) Statutory Corporations Act 1964 + SIGA 2019 (844 ha farm, ~2,000 buildings in Navrongo)
Vea Irrigation Company of Upper Region (ICOUR) Statutory Corporations Act 1964 + SIGA Periodic during Bagre overflow + Sahel rains

Statutory binding (override engine)

Inside any envelope → verdict ESCALATED to refused with citations to the full chain:

Exception clause

Flood-resilient public infrastructure (elevated walkways, evacuation centres on stilts, regulated marine facilities) may be considered case-by-case under a separate consent track with the operator and the Ghana Hydrological Authority. Permanent habitable structures are not permitted inside any envelope. Re-screening requires written confirmation from the operator that the specific footprint sits outside the gazetted design-spillage envelope.

Honest disclosure

The envelopes are digitised from documented spillage extents + operator-published protocols, not from a controlled topographic- hydraulic model. Each polygon's vertices reflect the broadest documented inundation across the events cited above, with conservative buffers applied where the extent varied between events. Precise per-property determination still requires the operator's design-spillage envelope and a site-specific topographic survey.


4. Galamsey screening — multi-layer scoring

This is the methodology the Platform pioneered as part of its the Authority focus. It directly addresses Prof. Ayamga-Adongo's stated priority on illegal mining enforcement.

4.1 Four-layer score

Each layer outputs a 0-1 score; the layers are weighted and summed:

Layer Weight Activates from
1. Documented hotspot proximity 0.15 Curated 27-point dataset (Pure Earth Pollution Atlas; the Authority shutdown notices 2020-2024; IMCIM; academic case studies)
2. Galamsey-affected river corridor 0.20 OSM rivers filtered by name to Pra / Ankobra / Birim / Offin / Tano (75 polylines) with watershed-aware piecewise scoring
3. District prevalence weight 0.10 Curated ~80-district table sourced from IMCIM + the Authority shutdown notices + Minerals Commission Ghana
4. Sentinel-2 NDVI delta detection 0.55 (when active) Google Earth Engine — Forkuor et al. 2020 methodology

4.2 Layer 1 — Documented hotspot proximity

27 points compiled from public sources, each carrying district, region, year_documented, source. Score function: 1.0 at the centroid, linear decay to 0 at 8 km. The dataset is intentionally a starter set — expansion is a Phase 2 deliverable.

4.3 Layer 2 — River corridor

The five rivers most documented for galamsey impact in Ghana (Owusu-Sekyere et al. 2019; Forkuor et al. 2020). OSM only labels some segments of each river by name, so the scoring uses watershed-aware piecewise distance:

4.4 Layer 3 — District prevalence

Static table keyed by district name (with normalised matching for hyphenated/suffixed variants like Tarkwa-Nsuaem Municipal vs Tarkwa Nsuaem). Weights:

4.5 Layer 4 — Sentinel-2 NDVI delta detection

When Earth Engine credentials are configured on the SafeGround service:

4.6 Tier-1 confidence cap

When Layer 4 is inactive (no GEE credentials), the combined Tier-1 score is capped at 0.7 — i.e. Tier-1 context alone can never declare a site "active galamsey." Red status requires Sentinel-2 confirmation. This is by design and is the methodological fix for the early-version Obuasi over-flagging.

Status as of 2026-06-02: Layer 4 (Sentinel-2 NDVI) is now active in production. The Tier-1 cap is no longer a binding constraint on production calls — but the methodology is preserved so any future credential outage degrades gracefully.

4.7 Status thresholds

4.8 Output transparency

Every galamsey result includes a data.layers block showing the per-layer score, distance/value, and layer_active flag. The human-readable detail string explicitly states which layers fired and which are unavailable. This is the defensibility property: an officer can read the output and reproduce the reasoning row by row.


5. Plausibility cross-check

5.1 Tier-1 (live, deterministic)

Eight hand-written rules covering physical impossibility (e.g. declared production with zero footprint) and well-known scale mismatches (cement <1 ha for >100 t/day; solar PV <1 ha/MWp; wind <10 ha/MW; hospital <30 m²/bed). Each rule cites its benchmark source.

5.2 Tier-2 (live, sourced)

Fourteen benchmark entries covering sector-process pairs: - Manufacturing: cement, steel, paper & pulp (USGS Minerals Yearbook, CEMBUREAU, World Steel Association, CEPI) - Mining: open-pit gold, bauxite (Minerals Commission Ghana, Newmont/AngloGold reports) - Energy: solar PV (NREL TP-6A20-56290, LBNL), wind (NREL TP-500-46909), hydro (IEA), CCGT gas (IEA, Ghana Energy Commission) - Health/Tourism/Real estate: hospital m²/bed (WHO), hotel m²/room (IHRA), residential m²/unit (Ghana Building Code 2018) - Waste/Water: landfill ha/(t/day), STP m²/(m³/day) (World Bank, Metcalf & Eddy, UN-Habitat)

Each benchmark computes a derived ratio (e.g. size_ha / capacity_mw) and flags the entry as "below" or "above" the expected range when deviation is significant.

5.3 Phase 2 (deferred)


6. Reconciliation engine (scoping-report cross-check)

6.1 Inputs

Text pasted from a proponent's scoping report (initially) or extracted from a PDF (when pdfplumber is installed on the server).

6.2 Extraction

Pure regex against patterns Ghana scoping reports commonly use: - Coordinates (labelled decimal, DMS, Google Maps URL, decimal pair) - Project title (after "Project Title:" / "Name of Project:" / "Undertaking:") - Sector (~50 keyword patterns covering all 11 First Schedule sectors) - Sub-types (process_type, mineral_type, fuel_type, building_type) - Scale (hectares, MW, m², tonnes/year, beds) - Mentioned environmental topics (13-topic keyword scan)

6.3 Reconciliation

For each topic SafeGround flags red/amber: - If the report addresses the topic → match - If the report does NOT address it → gap

For each plausibility flag → discrepancy (proponent's declared scale vs benchmark).

6.4 Output

Three columns + officer-ready next steps + 1-2 sentence summary suitable for the case file.

6.5 Phase 2 (deferred — requires API key)

LLM-assisted extraction via Anthropic Claude API for reports whose structure regex can't parse.


7. Officer workflow

7.1 Case lifecycle

created → assigned → in_review → signed_off
                              ↘ rejected / withdrawn

7.2 Compliance schedule (auto-generated at sign-off)

Per L.I. 2504 Reg 30, the Platform generates six dated obligations: - Appeal window closes (sign-off + 30 days) - Initial EMP submission (+ 18 months) - Permit renewal notice window opens (+ 21 months) - First EMP update (+ 54 months) - Decommissioning notice window opens (+ 60 months) - Second EMP update (+ 90 months)

Each obligation tracks status (pending / received / waived / overdue) and surfaces on the dashboard's lifecycle widget.

7.3 Audit trail

Every case action — creation, status change, officer assignment, peer reviewer assignment, notes update, sign-off, obligation marked received — generates an audit log entry. The entries form a SHA-256 hash chain:

hash[n] = sha256( canonical_json(payload[n]) + hash[n-1] )

Each entry's payload embeds the data lineage at decision time: platform version, EIAfinder ruleset version, SafeGround data release, and the dataset versions in force. A tampered row breaks every downstream hash; the GET /cases/{id}/audit/verify endpoint re-computes the chain and reports the first invalid entry if any.

7.4 Phase 2 (deferred)

Ed25519 signing of each entry by the signing officer's key — proves authorship, not just integrity.


8. Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Screening Tool orchestrator                │
│             (FastAPI · port 8006 · scoping.resilicity.com)  │
└────────┬────────────────────────┬───────────────────┬────────┘
         │ POST /screen           │                   │
         ↓                        ↓                   ↓
┌──────────────────┐  ┌────────────────────┐  ┌─────────────┐
│   EIAfinder      │  │   SafeGround       │  │  SQLite     │
│  rule engine     │  │  spatial engine    │  │   cases.db  │
│  (port 8005)     │  │  (port 8002)       │  │             │
│ L.I. 2504 rules  │  │ 20 indicators      │  │ + audit_log │
│ baseline surveys │  │ Tier-1 galamsey    │  │ + obligations│
│ public hearing   │  │ Tier-2 (GEE)       │  │             │
└──────────────────┘  └────────────────────┘  └─────────────┘

The orchestrator is stateless. SQLite holds case records, lifecycle obligations, and the audit log. All three upstreams run on the same Hetzner box for sub-millisecond inter-service latency.

8.1 Scaling path

The orchestrator can be replicated horizontally behind a load balancer. SQLite would migrate to Postgres at ~10k cases / day. Each upstream is already stateless and can scale independently.


9. Data lineage and audit reproducibility

Every audit log entry stores, in its canonical payload, the version of each upstream tool and dataset that was in force at decision time:

{
  "schema_version": "1.1",
  "case_id": "...",
  "action": "signed_off",
  "actor": "K. Mensah",
  "timestamp": "2026-05-22T11:08:52Z",
  "details": { "signed_off_at": "..." },
  "lineage": {
    "platform_version": "0.1.0",
    "eiafinder": { "version": "0.x", "ruleset": "L.I. 2504 v2025-09" },
    "safeground": { "version": "0.x", "data_release": "2026-05" },
    "datasets": { "osm_rivers": "...", "wdpa": "2024 release", ... }
  }
}

If a tribunal asks "exactly what data led to the decision on case SCT-2026-XXXX", the audit entry contains the answer. Combined with the hash chain, this is reproducible to the decision-time state.


10. Known limitations (honest disclosure)

10.1 Not yet validated against historical Authority decisions

v0.1 makes no statistical accuracy claims. A concordance study against the Authority's actual past permit decisions is the highest-priority Phase-2 task, blocked on the Authority sharing a decision archive.

10.2 Galamsey hotspot dataset — Tier-1 curated

~80 documented sites (2026-06 expansion sprint, up from an initial 27). Sources: IMCIM bulletins, Operation Halt II/III, CSIR-WRI water-quality reports, Minamata ASGM-NAP 2020, Owusu-Nimo 2018, national media. Not comprehensive — active Sentinel-2 detection (Tier-3) is the convergence path.

10.2.1 Galamsey 4-layer weights — expert-elicited v0.1 priors

The Layer weights (hotspot 0.15, river 0.20, district 0.10, satellite 0.55) are expert-elicited v0.1 priors, not empirically calibrated. The rank order satellite > river > hotspot > district reflects Forkuor et al. 2020's qualitative ranking of discrimination strength; the specific values are judgement. Calibration against the Authority's historical galamsey-flagged decisions (§10.1) is the Phase-2 task — weights will be re-fit by logistic regression with cross-validated AUC reporting, and a sensitivity table (status change under ±25 % weight perturbation) will be added to §4.6 once that data lands. Until then, the 0.7 Tier-1 cap is the methodological safeguard: Tier-1 alone can never produce a red status without Sentinel-2 confirmation.

The 0–8 km hotspot linear decay and the 2/10/25 km river piecewise breakpoints are methodological priors, not policy-derived. The 25 km outer envelope is the watershed-half-width heuristic for the Pra/Ankobra/Tano main basins (Owusu-Sekyere et al. 2019); finer basin-specific tapers are deferred to Phase 2.

10.2.2 Seismic — polygonisation simplification

The Ghana-specific PSHA (Ahulu et al. 2018) reports a continuous PGA surface. This module discretises it into a small set of polygon classes (currently four: Akwapim-high, Volta-elevated, coastal- elevated, basement-stable). The discretisation introduces step discontinuities at polygon edges; a site 100 m inside an elevated polygon returns amber while 100 m outside returns green even when the underlying continuous PGA is nearly identical. Replacing the polygons with an IDW or kriging interpolation of Ahulu's calibration points (with literature-anchored 0.04 g / 0.08 g amber/red thresholds) is a Phase-2 task. For the pilot, treat the indicator as a regional PGA-band assignment, not a site-specific shaking estimate.

10.2.3 500 m proximity buffers — convention, not literature

Several indicators apply a 200 m or 500 m amber-proximity buffer (wetland, protected area, OSM flood polygons, contamination sites). These are scoping-tool conventions — they are NOT derived from specific regulatory text or peer-reviewed effect-distance studies. Their purpose is to draw the officer's attention to sites just outside a flagged polygon where boundary uncertainty or edge-effect concerns warrant a closer look. Sites that materially depend on the proximity band rather than the polygon itself should be physically verified.

10.2.4 Coastal erosion uncertainty — range half-width, not standard deviation

rate_uncertainty_m_per_yr in coastal_erosion.py is the half-width of the published literature range for the segment, not a standard deviation. The current implementation linearly extrapolates rate ± uncertainty × 25 years to produce a 25-year retreat envelope; this is conservative for the upper bound but does not have the properties of a 1-σ statistical bound. A Phase-2 revision will either compute SDs from the published EPR statistics where available or re-label the field as range_half_width_m_yr and replace the linear propagation with explicit min/max scenarios. Officers reading the detail should treat the retreat envelope as a literature-range extrapolation, not a confidence interval.

10.2.5 Contamination — curation criteria

The contamination indicator draws on a curated geojson of Pure Earth / Blacksmith Toxic Sites Identification Program entries cross-referenced against the Authority shutdown notices. The curation rule is:

Include a site if (a) it is in the Pure Earth Pollution Atlas with documented heavy-metal or hydrocarbon contamination above the applicable Ghana Standard or WHO drinking-water threshold, OR (b) it is named in the Authority enforcement records 2018–2025 as having received a shutdown or remediation notice.

The galamsey-zone advisory layer (is_in_galamsey_zone) is set when the galamsey check returns red/amber at the same coordinate — i.e. the contamination layer inherits the discipline of the galamsey score. Sites with no published contamination evidence but located within the galamsey advisory zone are flagged amber, not red, acknowledging the inference is indirect.

10.3 OSM coverage gaps — partially closed (2026-05-31)

The general river check now prefers HydroSHEDS HydroRIVERS v1.0 over the OSM-name-filtered file, giving consistent named coverage of every Ghana reach with Strahler order ≥ 1 and average discharge attributes. OSM remains the fallback for sites outside the HydroRIVERS extent. The galamsey-affected basin check (Pra/Ankobra/Tano) already used a HydroRIVERS-derived file. Remaining OSM-dependent layers: roads (no widely-adopted alternative for Ghana), power lines (BPA/GRIDCo official corridor data is not public), flood polygons (still useful as a complement to the new JRC return-period overlay since OSM tags discrete flood-prone areas that the LISFLOOD-FP model may smooth).

10.4 Benchmarks are international, not Ghana-calibrated

NREL / IEA / USGS benchmarks reflect global norms. Ghana-specific calibration ships when the Authority shares historical permit data.

10.5 No authentication

The pilot runs with shared credentials. Production deployment integrates with the Authority's identity system (OAuth/SAML).

10.6 No automated proponent intake

By design. the Authority controls the intake channel; the Platform is officer decision-support, not a public submission portal.


11. Citations


12. Inland Water Body Determination engine

12.1 Purpose

The 15 spatial indicators (§3) handle proximity to wetlands, protected areas, rivers, roads, transmission lines, dam-spillage envelopes, etc. They do not, on their own, identify the water body itself when the parcel sits inside it. Before this engine landed, a pin dropped on Lake Bosomtwe returned a generic "in water" banner with no mention of:

The Inland Water Body Determination engine surfaces all of the above as a structured determination — designation stack, project-category verdict, stakeholder/permit matrix, and gazetting chain — for every screening that lands inside a curated Tier-1 polygon.

12.2 Catalogue (Tier 1, 12 features)

frontend/data/ghana_inland_water_bodies.geojson — generated by backend/scripts/build_inland_water_bodies.py.

ID Name Designations stacked
bosomtwe Lake Bosomtwe UNESCO MAB Biosphere Reserve (2016) · sacred-lake (Bekwaihene under Asantehene) · adjacent Bosomtwe Range Forest Reserve · endemic fishery (Tilapia busumana, Hemichromis frempongi)
lake_volta Lake Volta (Akosombo + Kpong reservoir) Volta River Development Act 1961 (Act 46) — VRA control · aquaculture-dominant fishery
bui_reservoir Bui Reservoir Bui Power Authority Act 2007 (Act 740) · adjacent Bui National Park (Wildlife Division)
weija_reservoir Weija Reservoir Statutory Corporations (Conversion to Companies) Act, 1993 (Act 461), as amended by L.I. 1648 — Accra drinking-water source · 200 m strict buffer
tono_reservoir Tono Reservoir ICOUR control — largest irrigation reservoir in Ghana
vea_reservoir Vea Reservoir ICOUR control — sister to Tono
owabi_reservoir Owabi Reservoir and Wildlife Sanctuary Ramsar Site Ghana_1 (1988) · Wildlife Sanctuary (L.I. 685) · Kumasi drinking-water source (GWCL)
songor_ramsar Songor Ramsar + UNESCO MAB Biosphere Reserve Ramsar Site Ghana_4 (1992) · UNESCO MAB Songor Biosphere Reserve (2011) · Ada Traditional Council custodianship of salt-pan economy
keta_lagoon_ramsar Keta Lagoon Complex Ramsar Site Ramsar Site Ghana_6 (1992) — largest Ramsar wetland in Ghana (1 200 km²) · Anlo Traditional Council (Awoamefia)
densu_delta_ramsar Densu Delta Ramsar Site Ramsar Site Ghana_2 (1992) — Densu estuary, Greater Accra
sakumo_ramsar Sakumo Lagoon Ramsar Site Ramsar Site Ghana_3 (1992) — Tema peri-urban; Tema Traditional Council
muni_pomadze_ramsar Muni-Pomadze Lagoon Ramsar Site Ramsar Site Ghana_5 (1992) — Effutu Traditional Council (Omanhene of Winneba)

Each feature carries: wb_type, area_km2_approx, district, region, MAB / Ramsar / sacred / Forest-Reserve / fishery flags, wrc_riparian_buffer_m, regulating_authority, dam_buffer, primary_authorities, verdict_categories (A→E), and a 5–7-entry gazetting_chain.

12.3 Polygon fidelity

Hand-curated screening-grade approximations:

These are NOT the official Ramsar Information Sheet polygons or the UNESCO MAB Biosphere Reserve zoning polygons. They are sufficient for screening ("does this parcel sit on Lake Bosomtwe? yes / no") and conservative enough that a parcel near the edge still flags. Replacing each polygon with the gazetted version on adoption is the documented upgrade path.

12.4 Project-category taxonomy

The verdict on an inland water body depends on whether the project NEEDS the water body to exist. The intake form's water_dependent checkbox combined with sector + sub_type maps to one of five categories:

Code Label Typical examples Default verdict on Bosomtwe-class lake
A Strictly water-dependent, low-impact, MAB-compatible Limnological research, water-quality monitoring, traditional artisanal fishery, navigational aids Conditional consideration
B Water-dependent, moderate-impact, MAB-conditional Sustainable aquaculture (MAB-compatible), small jetty / canoe terminal, ferry landing Conditional consideration — special pathway
C Water-dependent, high-impact Hydropower, large cage aquaculture, dredging / sand-winning, water abstraction above WRC threshold Refused (Bosomtwe-class); conditional on Volta-class
D Water-incidental — needs only the VIEW of water Resort, hotel, residential, factory, restaurant or visitor-facing facility on the water Refused
E Prohibited absolutely Petroleum storage, hazardous waste, mining of any kind, industrial discharge Refused — no special-circumstance path

When the proponent leaves water_dependent unticked, the resolver infers conservatively from the sector (a "tourism / resort" project falls into D; "agriculture / aquaculture" into B; "mining / petroleum" into E).

12.5 Stakeholder / permit matrix

When a conditional-consideration verdict fires, the resolver emits a per-feature stakeholder table from a canonical 34-entry _AUTHORITY_DECISIONS registry. Each row carries the authority's name, the gazetted statute, and a one-line "what they decide" string. The matrix is filtered by project category — Fisheries Commission appears for A/B/C but not D, Ghana Tourism Authority appears for B/D but not A/C/E, and so on.

Worked example — Lake Bosomtwe + aquaculture (Category B):

  1. Bekwaihene under Asantehene — Customary law; compatibility with sacred status and traditional taboos.
  2. Ghana MAB National Committee (MESTI) — UNESCO MAB Lima Action Plan; Core / Buffer / Transition zone compatibility.
  3. Water Resources Commission — WRC Act 1996 (Act 522) §13–§15; water-use, abstraction and discharge permit.
  4. Fisheries Commission — Fisheries Act 625 (2002) + Fisheries (Amendment) Act 880 (2014) §61–§64; cage culture licence.
  5. the Authority — EPA Act 2025 (Act 1124); L.I. 2504 (2025) Reg 28(1)(a) 25-day clock.
  6. Forestry Commission — Forestry Commission Act 1999 (Act 571); clearance for shore works affecting Bosomtwe Range Forest Reserve.
  7. Bosomtwe District Assembly — Local Governance Act 936 (2016); site plan + building permit + zoning conformity.
  8. Ghana Tourism Authority — Ghana Tourism Authority Act 2011 (Act 817); tourism enterprise licence (where any visitor-facing component is proposed).
  9. NADMO — NADMO Act 927 (2016); crater-rim slope and landslide risk assessment.

12.6 Override-engine integration

A matched inland water body with verdict refused escalates the overall verdict via the same _max_verdict channel used by the Spatial Statutory Override Engine (§5). The override engine cites the L.I. 2504 First Schedule grounds and the inland-water-body engine cites the gazetting chain — both surface in the same determination as a single defensible legal argument.

12.7 Tier-2 / -3 expansion path

The Tier-1 release covers the regulated and internationally-designated water bodies that drive the bulk of high-impact site choices. Three further tiers are documented for the post-pilot roadmap:

Replacing the screening-grade polygons with official Ramsar Information Sheet polygons and UNESCO MAB Biosphere Reserve zoning polygons on adoption is documented as a Tier-1 upgrade, not a Tier-2 expansion.

12.8 Honest disclosures

12.9 Coastal-lagoon reclamation buffer widening (wave-6o — LaBoma 2026 precedent)

Trigger event. On 13 Sep 2026 the Ghana Post-Flood Mitigation Task Force under the 48 Engineer Regiment demolished the Pink Flamingo Lounge and adjoining hospitality structures on the reclaimed Kpeshie Lagoon buffer zone at LaBoma Beach, La Dade-Kotopon Municipality, after a 21-day REGSEC notice issued 06 Aug 2026. The Regional Minister said on record: "All this place used to be Mangrove, it's a wetland. They cut the trees, filled this place and sold the land to developers" (Presidency of Ghana).

Gap the case exposed. The tool's Kpeshie Lagoon polygon captures only today's ~0.6 km² of open water. LaBoma sits ~1,302 m south of that polygon on reclaimed land historically documented as mangrove (Nartey et al. 2011 catchment map, 22 km²; Ntiamoa-Baidu 1988/1991). The Tier-1 proximity_buffer_m of 400 m — set for the current pond — could not reach LaBoma or the adjoining Regimanuel-Grey / Trade Fair / Burma Camp reclaimed strip. A proponent seeking a beach-resort permit at LaBoma coordinates before 13 Sep 2026 would have received requires_eia from the tool via the recent_flood_event override (June 2025 Kaneshie/Spintex/East Legon inundation polygon) but no lagoon or wetland trigger.

Fix applied (wave-6o). proximity_buffer_m widened on eight Greater-Accra + coastal urban lagoons to reflect historic pre-reclamation footprints, with L.I. 2504 (2025) Reg 40 (reclamation permit mandatory), LUSPA Act 2016 §125 (sensitive-area development control), L.I. 2384 (2019), Wetland Management (Ramsar Sites) Regulations 1999 (L.I. 1659), and NADMO Act 2016 (Act 927) added to the affected features' gazetting_chain:

Water body Old buffer_m New buffer_m Rationale
Kpeshie Lagoon (La Palmwine) 400 1500 Captures LaBoma at 1,302 m; historic 22 km² catchment
Sakumo Lagoon Ramsar 400 1200 Sakumono Estates / Community 25 / TDC April-2025 demolitions
Korle Lagoon 400 1500 Agbogbloshie / Old Fadama / Nima–Mamobi drain arm
Chemu Lagoon 400 1000 Tema Industrial Area (Community 1/8) 1960s+ fill
Fosu Lagoon (Cape Coast) 400 800 Township infill ("the disappearing lagoon", Essel 2019)
Densu Delta Ramsar 400 1500 Bortianor / Tetegu / Weija / Panbros / Kokrobite fringe
Muni-Pomadze Ramsar 400 800 Winneba fringe HWL retreat 0.22 m/yr (Angnuureng 2015)
Songor Ramsar + MAB 400 1500 Ada Foah / Sege saltpan encroachments (NASA imagery 1990→2000)

Statutory basis for the widening. L.I. 2504 Reg 40 was the operative anchor of the LaBoma demolition; it makes any reclamation, dredging, backfilling or ecological revegetation subject to a mandatory EPA permit (EPA 2025 public notice). LUSPA Act 925 §125 lists "coastal wetlands, water bodies, water catchment areas" as sensitive areas (Ghana LII Act 925); L.I. 2384 (2019) makes zoning-scheme exclusion of development in those areas mandatory. Ghana has no gazetted metric coastal setback — the buffer is the WRC "reserved zone" under Act 522 §13 (10–100 m per the 2011 Riparian Buffer Zone Policy) plus the local LUSPA sensitive-area definition. The tool applies precautionary buffers above the WRC 10–100 m riparian setback because the historic reclamation footprint of these lagoons is materially larger than today's open water.

Instruments inspected and found NOT to contain a gazetted metric coastal setback (so future reviewers do not re-open this question): Ghana Building Code GS 1207:2018 Part 5 (addresses flood-resilient construction — elevated foundations, hydrostatic loads — but no metric coastal-shoreline setback); Fisheries Regulations 2010 (L.I. 1968) Reg 7 (restricts beach-access structures, not a metric setback); Maritime Zones Law PNDCL 159 (1986) (sea baselines, not building setback); the MESTI 2020 draft Coastal Zone Management Plan (100 m proposed, never gazetted). The Wetland Management (Ramsar Sites) Regulations 1999 (L.I. 1659) applies to Ramsar-designated wetlands only and delegates the buffer width to each site's management plan.

Regression test. backend/tests/test_inland_water_bodies.py::test_laboma_beach_triggers_kpeshie_proximity_wave_6o pins LaBoma coordinates (5.5528, -0.1580) and asserts that (a) inland_water_body_proximity fires against Kpeshie with distance_m in 1000–1500 m, (b) LI 2504 Reg 40 and LUSPA Act 925 §125 appear in the returned gazetting_chain. If the buffer ever drops back below 1300 m or the statutes are removed, the test fails and the LaBoma-type gap is re-opened.

Remaining wave-6o+ work (documented, not shipped).

  1. True 1974 pre-reclamation polygons. The wave-6o fix widens the current polygon's buffer — a proper fix digitises the Ghana Survey Department 1:50,000 topographic maps (1974) plus JRC Global Surface Water permanent-loss layer (Pekel 2016, transitions 5+6+7) into distinct historic_extent_1974 polygons per lagoon. Recommended data source: USGS EarthExplorer Landsat MSS 1972-83 Path 193/56, 194/55-56 wet-season MNDWI ≥ 0.0.
  2. National coastal-setback rule. Confirm exact L.I. 2504 Second Schedule wording on coastal wetlands and Wetland Management (Ramsar Sites) Regulations 1999 (L.I. 1659) buffer text from the Ghana Government Gazette / brr.gov.gh directly — several public PDFs are Cloudflare-gated. Then cite verbatim.
  3. Reclaimed-wetland raster indicator. Compute a GEE product: JRC GSW transitions ∈ {5,6,7} (permanent + seasonal water loss) ∧ Dynamic World built > 0.6 — flag every 30 m pixel as reclaimed_wetland_flag = 1. Point-in-raster check would light up LaBoma even without a curated polygon.
  4. Mangrove-loss layer. Global Mangrove Watch 1996 vs latest — direct secondary evidence of pre-reclamation cover.
  5. REGSEC-vulnerability watchlist. 15 named at-risk Accra sites identified by the wave-6o research (LaBoma / Regimanuel / Trasacco / Tse Addo / Sakumono Estates / Old Fadama / Nima–Mamobi / Odorkor / Kokrobite / Ada Foah, etc.) — ship as a curated regsec_action_risk polygon layer.

13. Recent Flood Events layer (16th indicator)

13.1 Purpose

The modeled flood layer (§3.1 — flood) is a climatology: JRC Global Flood Hazard Maps v2.1 evaluates terrain + rainfall return-period statistics to estimate where a 1-in-10/100/500-year event would inundate. It is the right answer to the question "what does the terrain say about flood risk?"

It is not the right answer to the question "did this exact location actually flood last year?"

That gap matters: the June 2025 Accra floods that inundated Kaneshie, Spintex, East Legon, Achimota and Adabraka were caused by drainage failure — sealed surfaces, blocked culverts, the Odaw drain choking under sub-100-year rainfall. The modeled JRC layer returns GREEN for many of those locations because the cause was not extreme rainfall, it was infrastructure. A documented-event layer is the only way to flag the parcel correctly.

The recent_flood_event indicator fires independently of the modeled flood layer, side-by-side. When the model says GREEN but the documented layer says RED, the report explicitly surfaces the divergence — that is the binding evidence the officer must address in the EIS.

13.2 Catalogue (Tier 1, 14 events 2015-2025)

frontend/data/ghana_recent_flood_events.geojson — generated by backend/scripts/build_recent_flood_events.py.

ID Event Date Cause
accra_2015_06_03_odaw_catchment 3 June 2015 Accra floods — Odaw lower catchment 2015-06-03 Combined drainage failure + extreme rainfall + GOIL fuel-station fire (152 deaths, 5 000+ displaced)
accra_2018_06_odaw_repeat June 2018 Accra repeat — Odaw catchment 2018-06-18 Drainage failure + Odaw overflow
tamale_2019_07_urban_floods July 2019 Tamale urban floods 2019-07-15 Drainage failure + seasonal rainfall
accra_2020_05_spintex_tema May 2020 Spintex / Tema 2020-05-23 Drainage failure + Sakumono catchment
white_volta_2022_basin_riverine 2022 White Volta basin floods 2022-09-10 Riverine cross-border + Bagre spillage
akosombo_2023_10_documented_spillage Sep-Oct 2023 Akosombo controlled spillage 2023-09-15 VRA controlled spillage (38 624 displaced — cross-references dam_spillage)
accra_2024_06_achimota_spintex June 2024 Achimota / Spintex 2024-06-12 Drainage failure (Onyasia / Sakumono)
upper_east_2024_09_bawku_bolga Sep 2024 Upper East floods 2024-09-22 Bagre spillage + White Volta riverine
accra_2025_06_kaneshie June 2025 Accra — Kaneshie 2025-06-09 Drainage failure (Odaw catchment)
accra_2025_06_spintex June 2025 Accra — Spintex 2025-06-09 Drainage failure (Sakumono catchment)
accra_2025_06_achimota June 2025 Accra — Achimota 2025-06-09 Drainage failure (Onyasia drain)
accra_2025_06_east_legon June 2025 Accra — East Legon 2025-06-09 Drainage failure (high-density sealed surfaces)
accra_2025_06_adabraka June 2025 Accra — Adabraka 2025-06-09 Drainage failure (Odaw lateral congestion)
keta_2022_coastal_tidal 2022 Keta coastal-tidal flooding 2022-11-15 Storm surge + spring tides + degraded sea defences

Each feature carries: event_date, event_type, flood_cause, region, district, affected_communities, casualties_approx, displaced_approx, peak_depth_m_approx, extent_confidence, polygon_fidelity, sources (list of citations), and a recurrence_note where the same area has flooded multiple times.

13.3 Polygon fidelity

Tier 1 polygons are hand-curated, screening-grade approximations sourced from:

The polygons are conservative ellipses centred on documented affected communities — sufficient for screening ("did this parcel sit inside or near a documented flood event? yes / no") and broad enough that a parcel just outside the visible extent still flags via the 500 m amber buffer.

These are NOT the official Copernicus EMS post-event polygons or HSD flood-extent maps. Replacing each polygon with the gazetted version on adoption is the documented upgrade path.

13.4 Statuses + verdict integration

The choice of requires_eia rather than refused is deliberate: a documented past flood is binding evidence the EIS must address, not an absolute prohibition. Repeat-event sites (Adabraka, Spintex) should arguably be refused, but that decision depends on the proposed undertaking's flood-resilience design — which the screening tool does not see. The assessment officer makes that determination based on the EIS submission.

13.5 Side-by-side reporting

When both layers fire, the §7 spatial table shows them as separate rows so the officer sees the comparison directly:

Indicator Status Detail · Measured
flood (modeled) GREEN Site outside JRC 100-year flood envelope. Modeled HAND = 12.4 m. Measured: JRC GFHM 100-yr return-period + Copernicus DEM HAND.
recent_flood_event (documented) RED Site lies inside 2 documented flood events. Most recent: June 2025 Accra urban floods — Spintex (2025-06-09). Cause: drainage failure. Measured: point-in-polygon vs. documented event polygons (NADMO / HSD / GMet / Copernicus EMS / media).

The narrative of the Reason callout makes the divergence explicit: "Modeled climatology layer is GREEN; documented event layer is RED. The documented evidence is the binding signal — drainage-failure events of this kind are not captured by climatology-based modelling."

13.6 Tier-2 / -3 expansion path

13.7 Honest disclosures


14. Urban Drainage layer (17th indicator)

14.1 Purpose

The existing river check (§3.3) runs against HydroSHEDS HydroRIVERS — a global dataset with a minimum catchment-area threshold of ~5 km². Urban drainage corridors below that threshold are invisible to the check, even when they are the actual flooding channels in their catchments. The user-reported gap at Shiashi / Gulf House (the Onyasia stream visibly passes the parcel, the river check returned GREEN) is the canonical example.

OpenStreetMap covers the same channels but with inconsistent taggingwaterway=stream, waterway=drain, waterway=ditch, or untagged where the channel has been culverted under a road. The previous OSM fallback only queried waterway=river, so most urban drains were missed there too.

The urban_drainage indicator closes the gap with a three-tiered point-to-polyline distance check:

14.2 Status thresholds

Specific channels in the Tier 1 layer may carry their own recommended_setback_m — when present and larger than 30 m, that value is the RED threshold (allowing for variable WRC informal-stream classification).

14.2.1 Threshold derivation — honest disclosure

The 30 m / 100 m thresholds are not a direct statutory citation. The Water Resources Commission Act 1996 (Act 522) §13 and the WRC Riparian Buffer Zone Policy 2014 specify riparian buffers for named rivers by stream order (30 m, 60 m, 120 m for orders 1–2 / 3 / 4+) and explicitly defer informal urban drains to municipal by-laws + WRC permit consideration. The tool extends that policy by analogy to OSM-tagged drains, applying the lowest-order 30 m setback as the RED threshold and a doubled 100 m amber buffer for adjacency. This is a methodological choice grounded in the WRC policy, not a statute number we can cite verbatim. The override engine cites L.I. 2504 Reg 2(3) read with Reg 3(1)(d), Act 522 §13 and the Ghana Building Code 2018 Part 5 as the binding authorities; the 30 / 100 m numbers are the operationalisation.

For Tier 2 OSM unnamed drain / ditch features specifically, the resolver tightens the RED threshold to zero (only AMBER applies) — guarding against the case where an OSM contributor has tagged a paved residential gutter as a drainage corridor.

14.3 Performance

With ~17 200 Tier 2 features loaded, naive point-to-line distance computation would dominate the /screen latency budget. The resolver pre-computes a bounding box per feature at module load and skips any feature whose bbox is farther than the AMBER threshold + a small slack — typically eliminating > 99 % of candidates before any line-distance computation runs. Measured cold-start probe time: ~5 ms; warm: ~5 ms (vs. ~250 ms without the bbox pre-filter).

14.4 Override-engine integration

14.5 Operating procedures — refresh scripts

Tier Script When to run
1 backend/scripts/build_urban_drainage.py Whenever a corridor is added / corrected. Hand-curated.
2 backend/scripts/fetch_osm_waterways.py Monthly during rainy season; quarterly otherwise. Fetches from OSM Overpass; no auth required.
3 backend/scripts/fetch_sentinel1_water_extent.py Monthly during rainy season. Requires earthengine-api + Google Earth Engine service-account auth (same key as task #91 SafeGround setup; EE_PROJECT=safeground). Ships an empty placeholder until run with credentials configured.

14.6 Honest disclosures

14.7 Tier-4 expansion path


15. REGSEC predictive flood-risk layer (18th indicator)

15.1 Purpose

The recent_flood_event indicator (§13) catches documented flood events — places that have already flooded. The regsec_high_risk indicator catches predicted flood-risk — places the Authorities expect to flood under the next forecast rainfall event.

The two are complementary. A parcel may sit in one, both, or neither. When both fire, the determination shows the convergence: documented past + Authority warning = high-confidence binding evidence.

15.2 Source

Greater Accra Regional Security Council (REGSEC) statement of 10 June 2026, signed by Regional Minister Linda Obenewaa Akweley Ocloo, ahead of the Ghana Meteorological Agency June 2026 forecast (100–150 mm rainfall across the Coastal Zone).

REGSEC is the inter-agency Regional Security Council chaired by the Regional Minister and including NADMO, Ghana National Fire Service, Ghana Police Service, and the Accra Metropolitan Assembly. The statement names ~25 micro-locations as flood-prone across the Greater Accra Region.

Public reporting: - Pulse Ghana 2026-06-11 - Graphic Online — "REGSEC maps out flood high-risk communities" - Adomonline 2026-06 - Asaase Radio — Accra flood hotspots ahead of Homowo - Ghanaian Times — REGSEC intensifies flood preparedness

15.3 Catalogue (Tier 1, 12 grouped zones)

frontend/data/ghana_regsec_high_risk.geojson — generated by backend/scripts/build_regsec_high_risk.py.

The 12 polygons group the ~25 named micro-locations by neighbourhood to avoid both over-flagging and the false precision of pretending we have block-level boundaries:

Zone Catchment Micro-locations named by REGSEC
Adabraka Odaw Odawna, Official Town
Dansoman Densu Delta Sahara
Alajo Odaw D.K. Poison area, Polo Park
Nima Odaw Berlin Bridge, Downside
Madina Onyasia/Densu Jelil Estate Junction, Baba Yara Area, Akorli Down
Osu Kpeshie/coastal Osu Alata, Osu Doku
Abelemkpe Klottey/Odaw Abelemkpe Methodist Church vicinity
Weija-Gbawe (Old Barrier/Choice) Densu Delta Old Barrier, Choice
Weija-Gbawe (Tetegu/Oblogo) Densu Delta Tetegu, Oblogo
Ga West Densu/Lafa Manhean, Afuaman, Medie
Ga East (Dome/GAEC/Christian Village) Onyasia/Densu Dome Crossing, GAEC Road, Christian Village Drain
Ga East (Dakyibi) Dakyibi tributary Dakyibi River catchment area

15.4 Honest coverage disclosure

15.5 Override-engine integration

When both REGSEC AMBER and recent_flood_event RED fire on the same parcel (Madina, Dansoman), the override engine produces two entries in the citation chain. This is by design — they represent two independent evidence streams from two different Authority sources (REGSEC + the documented event log). The on-screen report can collapse them into a single "flood-prone (documented + predictive)" card if visual repetition becomes confusing.

15.6 Tier-2 / -3 expansion path

15.7 Honest weaknesses


16. Cultural Heritage layer (19th indicator)

16.1 Purpose

UNESCO World Heritage Sites (1972 Convention) and GMMB-gazetted national monuments (National Museum Decree 1969, NLCD 387) define a class of Sites of Historic Interest that L.I. 2504 (2025) Reg 2(3) read with Reg 3(1)(d) and the Constitution of Ghana 1992 Art 39(2) cover as Environmentally Sensitive Areas. The 18 prior indicators caught none of them — protected_area resolved IUCN PAs and forest reserves only. A Cape Coast UCC-ridge screening at 5.121°N, 1.274°W on 2026-06-23 returned GREEN on every indicator despite sitting 4.1 km from Cape Coast Castle (UNESCO WHS 1979). Every Central/Western coast project would have skipped the GMMB clearance topic. This indicator closes that gap.

16.2 Catalogue (Tier 1, 35 features)

Each feature carries: - cordon_m — statutory cordon, typically 50 m around fort walls and 100 m around active palaces / shrines. Works inside the cordon require express GMMB and (for WHS) MESTI clearance. - advisory_buffer_m — advisory development buffer, typically 300–500 m. Works inside the buffer require a Cultural Heritage Impact Assessment (CHIA). - custodian — GMMB and (where applicable) traditional custodian (Asantehene Otumfuo, Ya-Na, Oguaa Omanhene, Ada Mantse, etc.). - 3–5 entry statute_chain citing NLCD 387 + UNESCO Convention + L.I. 2504 + Constitution Art 39(2) as appropriate.

16.3 Status thresholds

16.4 Override-engine integration

RED triggers the cultural_heritage.red override (verdict refused, statutory cordon prohibition, NLCD 387 + UNESCO Convention + L.I. 2504 + Constitution Art 39(2) citations). AMBER triggers the cultural_heritage.amber override (verdict requires_eia, CHIA scoping topic, NLCD 387 + L.I. 2504 + Constitution Art 39(2) citations). Citations are deduped against earlier higher-priority overrides via the _seen_statutes mechanism (so L.I. 2504 Reg 2(3) read with Reg 3(1)(d) only appears once in the consolidated chain).

16.5 Honest disclosures

16.6 Coastal & urban lagoon extension to the inland-water-body resolver (Tier 1B)

The Cape Coast screening also exposed that Fosu Lagoon (1.4 km from the UCC ridge), Korle Lagoon (1.5 km from Adabraka), and similar non-Ramsar coastal/urban lagoons were entirely invisible to inland_water_body — the Tier 1 catalogue covered only the 6 Ramsar lagoons + 6 reservoirs/lakes. The Tier 1B extension adds 8 non-Ramsar coastal/urban lagoons (Korle, Kpeshie/La, Chemu, Fosu, Benya, Butuah, Whin Estuary, Volta Estuary at Ada Foah) covering the highest-development-pressure stretches of all four coastal regions (Greater Accra, Central, Western, plus the Ada deltaic system). Each feature carries WRC riparian buffer (100 m default) plus a proximity_buffer_m outer awareness ring (400–600 m). The resolver runs a two-pass check:

  1. Pass 1 — strict containment (existing). Polygon point-in-polygon. Returns RED with the full inland_water_body refusal override.
  2. Pass 2 — buffered proximity (new). For each feature with proximity_buffer_m, computes distance to the polygon edge; if ≤ buffer, surfaces an inland_water_body_proximity AMBER override with verdict requires_eia. No automatic refusal; the EIS scoping topic + WRC §13 buffer clearance + (where the lagoon is sacred) traditional council clearance is added.

The lagoon features tag historical biodiversity (Fosu, Volta Estuary have documented Crocodylus suchus; Korle, Kpeshie, Butuah have historical Varanus niloticus) so the EIS Cultural / Biodiversity Heritage Assessment must address baseline herpetofauna and waterbird populations — the "monitor lizards years back" instinct that exposed the gap is now wired into the report scope.


16.7 Open items after sprint-22 agency-hat review (2026-06-26)

Ten Ghana-specific reviewers (5 code experts + 5 agency hats: GMet, WRC, NADMO, EPA/Forestry/Wildlife/Fisheries, LUSPA + Lands + OASL + Survey + Minerals + GMMB + GHA) landed a large fix wave in commits 624cc80 (Wave 4), d1ec35f (Wave 5), 7adbce3 (Wave 6), a3d8dba (Wave 7A). Six substantive items remain open — each requires an external artefact the tool cannot fabricate honestly. They are documented here as the standing roadmap.

  1. Live GMet Severe Weather Warning integration — the tool consumes GMet's June 2026 SRO forecast statically. Live warnings require an authenticated feed URL (RSS or CAP-1.2) from the National Weather Forecasting Centre. Blocker: URL + schema confirmation from GMet Digital Services.
  2. REGSEC regional expansion (Volta / Central / Western / Upper East / Northern) — the Tier-1 layer covers only the 10 June 2026 Greater Accra REGSEC statement. Each regional REGSEC issues its own statement; those gazetted texts have not been ingested. Blocker: sourcing the regional REGSEC statements.
  3. Bagre spillway as its own indicator — currently represented as one feature within the dam_spillage envelope layer. NADMO's ask is a dedicated bagre_spillway_dependency indicator that fires along the entire White Volta Ghana reach with the annual SONABEL / GMet joint bulletin. Requires the joint bulletin's canonical envelope.
  4. Minerals Commission cadastral integration — the tool has no read of granted PL / RL / ML / SSML licence perimeters. A Tarkwa pin cannot tell if it sits inside Gold Fields Damang's concession. Blocker: Minerals Commission cadastre snapshot (they publish this but not through a public API).
  5. CMIP6 / SSP projection layer + SPI drought indicator — L.I. 2504 §17 climate-change assessment increasingly demands 2030/2050 projections. The recommended stack is NEX-GDDP-CMIP6 (25 km, bias-corrected, free on Google Earth Engine) with local bias correction against the GMet 22-station gauge network. Requires: GEE asset configuration + service-account write access to persist the derived layer + methodology sign-off from GMet on the bias-correction protocol.
  6. Open Access workspace='pilot' namespacing — post-adoption, the audit log would contain thousands of pilot-visitor entries with meaningless actor identification. The fix is a schema migration that namespaces all OPEN_ACCESS_MODE=1 cases into a workspace='pilot' bucket excluded from any production dataset export, plus an open_access=true stamp on the audit lineage. Requires: schema migration + services/auth.py refactor + production DB backfill.

Also documented as smaller open items: - Cultural-heritage dataset 35 → 80-100 features (Aburi Botanical Gardens, Komenda sugar industrial heritage, Begoro mission heritage, Volta Region Anlo-Ewe traditional shrines, Northern-Region forts + slave-route sites). - Sacred-grove resolver (~40 features per Sarfo-Mensah & Oduro 2007) — Asantemanso, Adanwomase, Buoyem, Boabeng-Fiema, Malshegu, Jachie-Pramso, Sakumo grove, and similar. - Land-use zoning indicator + LUSPA on inter-agency card + LSDF integration. - Landslide hotspot indicator — Akwapim ridge (Aburi–Mampong–Koforidua), Kwahu escarpment (Mpraeso–Nkawkaw), Weto range (Ho–Kpando–Kadjebi). NADMO Landslide Contingency Plan + Ghana Geological Survey susceptibility mapping. Feasible without external artefacts but scoped as Tier 2 to keep sprint-22 close-out clean. - Licensed-Surveyor advisory on the determination card (Survey Act 1962, Act 127). - Keta coastal-erosion segment-specific rates (Angnuureng 2023, Asare-Bediako 2025) — currently rolled up into a regional 2.0 m/yr average that hides the 3-8 m/yr Keta hotspot and the 17 m/yr Fuveme peak.

Every item above is captured for the post-pitch Tier-2 sprint. The tool as it stands is production-ready for decision-support use by an Authority officer per the WRC-hat and EPA-hat sign-offs already in the record.

18. Government / Institutional Lands layer (20th indicator)

Added 2026-07-02 in response to two failure modes the earlier 20 indicators could not catch:

  1. Fraudulent sale of state-vested / institutional land. In Ghana, imposter "chiefs" and land agents periodically resell parcels that are actually vested in a public institution. Documented, recurrent cases: CSIR-Animal Research Institute Frafraha (900+ acres encroached since ~2006; REGSEC demolition June 2022), UG Nungua/Borteyman farm (repeated fraudulent sales, joint military/police demolitions 2009 + 2023), Ghana Atomic Energy Commission Kwabenya (~30% of 2,000 acres lost since the 1960s), Amrahia Dairy Farm (persistent Adenta-Katamanso pressure), GWCL Weija reservoir buffer (sand-winning + illegal construction inside the 500 m demarcation).
  2. Ill-considered project siting on institutional land. An industrial or residential proposal on a university agricultural station, a CSIR research farm, a military zone, or a prison-service plot is void ab initio for lack of title — but the earlier indicators would not have flagged it unless a project happened to overlap a protected-area, wetland, or dam-spillage envelope.

Both patterns route to the same fix — a chain-of-title verification at the Lands Commission plus a written no-objection from the custodian institution, before the Authority determines the case.

18.1 Dataset — ghana_government_institutional_lands.geojson

The Tier-1 catalogue ships 76 hand-curated features across nine categories:

Each feature carries: custodian, category, establishing_statute (chain from the umbrella State Lands Act 125 / Lands Act 1036 down to the custodian-specific statute), tenure_class, dispute_note (where a documented encroachment case exists), proximity_buffer_m (default 200 m), polygon_fidelity, extent_confidence, and a sources array of published citations.

Polygon fidelity. Every feature is a hand-curated circle around a published centroid. This is screening-grade: a pin within the polygon fires RED for the correct institution, but the exact boundary on adoption follows the gazetted survey plan (Lands Commission cadastral). Where the research surfaced a materially better centroid than a settlement proxy, the coordinate was upgraded (e.g. GAEC Kwabenya, CRIG Tafo, KNUST Kumasi, Burma Camp, Amrahia).

18.2 Legal framework

18.3 Engine behaviour

The RED verdict escalates via the same _max_verdict channel used by every other override so the final scoping-topic list, PDF §5 verdict card, §7 spatial table, §8 override audit, and decision-letter Reg 29 text remain internally consistent.

18.4 Tier-2 / Tier-3 expansion path

19. Fee Estimate Engine (Act 1080 revenue-side taxonomy)

Ghana's regional EPA offices bill proponents against the Fees and Charges (Miscellaneous Provisions) Act, 2022 (Act 1080) — a 31-page gazetted schedule with ~653 fee rows across the Authority's 9 official sectors (Mining · Energy · Manufacturing · General Construction · Agriculture · Health · Tourism & Hospitality · Telecommunication · Pesticides). Until this sub-system landed, the tool produced scoping determinations without touching fees, which was the friction point at regional level — officers had to switch to a paper copy of Act 1080 or an Excel sheet to complete the workflow.

19.1 Data + engine

19.2 Public surface

19.3 Report integration (scoping_pdf.py §3)

The existing §3 "Indicative Fee & Permit Lifecycle" now runs an Act 1080 probe first: if the case's declared sector + sub-type label uniquely match a single gazette row, quote that row's processing + permit fees with the row-reference and a disclaimer. If more than one row matches (ambiguous sub-type), fall back to the activity-classification engine's number + point the officer at /fees to pick the correct row. Once the sector-taxonomy migration (Task #181) wires a specific Act 1080 sub_code onto each case at intake, ambiguity disappears and every non-refused verdict PDF carries the authoritative gazetted fee. The tool NEVER invents a fee — silence beats a wrong number.

19.4 Currency handling

Rows denominated as "Cedi Equivalent of US$X" are shown in USD by default. Officer supplies today's Bank of Ghana mid-rate (manual entry) to settle to GHS. Final invoice is issued by the Authority billing officer under Act 1080 — the tool's estimate is indicative and disclaimed as such.

20. Reconsideration / Enhanced-Mitigation pathway

L.I. 2504 refusals in the tool are not always dead-ends. Two distinct pathways permit re-opening a refused case with a higher regulatory bar and rigorous audit — analogous to the Netherlands water-adaptation model where flood-prone building is permitted with certified engineering, independent design audit, monitoring commitment, and reversibility. Ghana adaptation: the Authority's own governance ladder (Regional Directors + CEO) countersigns every consent so no single officer can unilaterally lift a refusal.

20.1 Trigger classification (Class 1 vs Class 2)

Class 1 — Non-negotiable (no standard reconsideration; hard-case override initiable only by Regional Director or CEO):

Class 2 — Mitigable-with-certified-design (standard reconsideration pathway available):

Classification is dynamic: an institutional-land refusal downgrades from Class 1 to Class 2 when the reconsideration pack includes a custodian release + Lands Commission title-clearance. The cordon-vs-buffer distinction for wildlife / heritage refusals decides Class 1 vs Class 2 per feature.

20.2 Governance ladder (roles)

20.3 Sign-off matrix

Track Who can initiate Sign-off tier 1 Sign-off tier 2
Standard reconsideration (Class 2) any officer with case access, supplying certified evidence pack Regional Director CEO or CEO-designated Deputy Executive Director (cross-region)
Hard-case override (Class 1) Regional Director or CEO only — role-gated at UI + backend Regional Director CEO personally — no delegate

Every reconsideration: - 30-day time-lock between the original refusal timestamp and reconsideration submission. Forces a genuine certified-design cycle, not paperwork resubmission. - Justification field with a hard minimum of 500 characters (hard-case) or 200 characters (standard). Structured, audited. - Evidence upload for each named certification the exception clause demands. Every file's SHA-256 is chained into the case's audit log; the file itself lives under /var/lib/epa-scoping-platform/recon-evidence/. - Outcome reason at every sign-off with a hard minimum of 100 characters. - Cross-region check on standard-track DED delegate: a DED cannot sign for a case in their own region. Prevents cosy back-channels within a region. - Sunset clause on hard-case consents: automatic expiry at 5 years, with full re-review required at renewal — no admin-only renewal.

20.4 Non-negotiables even for hard-case (constitutional prerogative)

The CEO / Regional Director hard-case initiation button is an escape valve for genuinely exceptional national-interest cases. It does NOT bypass:

The tool auto-flags every hard-case consent to the public register at creation — not on sign-off, at creation — so the mere initiation of a hard-case review is visible to civil society and Parliament.

20.5 Public Register (RTI Act 989 aligned)

Contents: every reconsideration case that reached a conditional consent, a hard-case override consent, or a rejection outcome. PII on private-citizen proponents is anonymised; public-institution proponents are named. Aligns with the Right to Information Act, 2019 (Act 989) proactive-disclosure obligations. Officer sign-offs (Regional Director + CEO / DED) are recorded in the underlying SHA-256-chained audit log and available on request under Act 989.

20.6 Anti-corruption tripwires — summary

The pathway is designed so a corrupt officer meets meaningfully more resistance than the paper-file world it replaces:

20.7 What this pathway does NOT enable

21. Sector taxonomy migration (Act 1080 canonical)

The tool's earlier intake form carried 11 homegrown sectors that did not line up with the Republic's actual revenue-side sector list. The 2026-07-02 migration switched to the 9 canonical sectors defined by the Fees and Charges (Miscellaneous Provisions) Act, 2022 (Act 1080): Mining · Energy · Manufacturing · General Construction · Agriculture · Health · Tourism & Hospitality · Telecommunication · Pesticides.

21.1 Legacy alias handling

Five older sectors are retained as deprecated aliases so pre-migration case rows remain queryable:

Legacy sector Resolves to Routing note
oil_and_gas energy Petroleum sub-categories in Act 1080 §B (upstream / downstream)
real_estate general_construction Housing units in §D (Apartments / Real Estate)
transport (no clean mapping) Facility construction → General Construction; equipment → Manufacturing; the officer re-classifies
waste_management manufacturing Recycling sub-categories C5 / C16 / C25
water_and_sanitation (no clean mapping) Facilities → General Construction; industrial wastewater → Manufacturing

21.2 Public surface

22. Impact Scale classifier (Act 1080 advisory)

The Fees and Charges Act 1080 (2022) prices activities the Authority is already assessing under L.I. 2504 into Large / Medium / Small / Minor / Micro Impact Scale bands, keyed to per-sector metrics (bed count, capacity MW, floor area m², room count, storage volume m³, livestock head, size ha).

22.1 What the classifier does

backend/app/services/impact_scale.py::classify_impact_scale():

  1. Determines whether the activity is Category A (mandatory EIA regardless of scale — mining, petroleum, primary industry, hospitals

    100 beds, dams, large infrastructure).

  2. Picks the most-specific sector metric declared at intake and matches it against the sector's Impact Scale band table.
  3. Emits {impact_scale, metric_used, metric_value, band_source, category_a, downgrade_eligible, reason}.

22.2 What the classifier does NOT do (2026-07-18 correction)

An earlier draft auto-downgraded requires_eiarequires_registration for Category B activities at Small / Minor / Micro scale. That was withdrawn after independent legal review found it may contradict the last gazetted rule the tool can verify: L.I. 1652 (1999) Schedule 2 placed hotels/hostels of ≥40 rooms on the mandatory-EIA list. If L.I. 2504 (2025) kept that threshold, an auto-downgrade of a 45-room hotel would be a regulatory regression not the correction the officer complaint asked for.

Act 1080 (2022) is a revenue instrument — it prices activities the Authority is already assessing under L.I. 2504; it does not decide which assessment tier applies. Until the gazetted L.I. 2504 First Schedule thresholds are confirmed by the Authority DPO and encoded per-activity here, the tool must not auto-downgrade.

22.3 What the tool does instead

downgrade_verdict_for_scale() stamps the verdict with an advisory-only scale_advisory object carrying the classification, the recommended fee band, an honest disclaimer, and the L.I. 1652 baseline reminder. Both consumers surface it:

The officer may manually downgrade after verifying the L.I. 2504 threshold against the gazetted text, and must record the verification source on the case file for the audit trail.

23. Statutory-duration registry

Every statutory clock the tool cites resolves through a single registry: backend/app/services/statutory_durations.py. Consumers include the case-lifecycle scheduler (cases.py::_compute_clock), the compliance lifecycle generator (lifecycle.py::_SCHEDULE), the decision letter (L.I. 2504 Reg 45(1) appeal window), and PDF §4 (Statutory Clocks table).

23.1 Canonical clocks

Synced 2026-07-25 with services/statutory_durations.py — the code is the single source of truth; this table reproduces it verbatim. Verified-gazette rows are anchored to the L.I. 2504 PDF published by EPA Ghana in November 2025.

Clock Value Regulation Source badge
initial_assessment 14 calendar days L.I. 2504 Reg 28(1)(a) gazette
screening_determination (PER) 25 calendar days L.I. 2504 Reg 28(1)(b) gazette
total_determination (EIA) 60 calendar days L.I. 2504 Reg 28(1)(c) gazette
eis_review_authority 60 calendar days L.I. 2504 Reg 28(1)(c) gazette
eis_decision_after_trc 10 calendar days L.I. 2504 Reg 29 gazette
scoping_decision_after_trc 25 calendar days L.I. 2504 Reg 28(1)(b) / Reg 17 (Action on Scoping Report) authority_practice
public_hearing_notice 21 calendar days L.I. 2504 Reg 24 (triggers) + Reg 25 (guidelines) authority_practice
appeal_window 30 calendar days L.I. 2504 Reg 45(1) (appeal to the Board); Reg 46(2) 30-day Appeals-Committee clock; Reg 47 High Court redress gazette
emp_initial_submission 18 months L.I. 2504 Regs 33-34 (EMP preparation + review) authority_practice
emp_update_cycle 36 months L.I. 2504 Regs 33-34 authority_practice
permit_phase_construction 24 months L.I. 2504 Reg 30 (permit validity per phase) gazette
permit_phase_operation 24 months L.I. 2504 Reg 30 (permit validity per phase; sector-specific Act 1080 overrides may apply) gazette
reconsideration_time_lock 30 calendar days Tool policy (services/reconsiderations.py) — NOT gazetted, NOT statutory tool_convention
hard_case_sunset 5 years PROPOSED tool policy — PENDING BOARD APPROVAL — must not be communicated to a proponent as binding until Board approves (see METHODOLOGY §20.3 + statutory_durations.hard_case_sunset note) tool_convention

23.2 Verification-badge convention

Every entry carries a verified_by badge in one of four honesty tiers:

The PDF §4 Statutory Clocks table renders each clock next to its verification badge so the reader can see which numbers are gazetted vs authority-practice vs tool policy — no silent laundering of a needs_verification into a citation-grade fact.

23.3 Working-day vs calendar-day discipline

The registry distinguishes working_days from calendar_days per the Interpretation Act 1960 (CA 4). days() returns integer days; consumers convert to date-of-expiry using the correct calendar as appropriate for the clock kind.

24. Galamsey Monitor — national district galamsey-pressure ranking

24.1 Purpose

A national layer that ranks all 260 district assemblies (MMDAs) by the extent to which galamsey (illegal small-scale mining) pressure is evident in the satellite record, so the Authority and its partners can target inspection, monitoring and enforcement where the evidence is strongest. It is distinct from the site-by-site screening engine: it answers "where in the country is galamsey pressure concentrating?", not "what about this parcel?". Served at /galamsey.html; API at GET /galamsey/ranking and GET /galamsey/district/{gid}; a CEO/RD printout at GET /galamsey/brief.pdf.

24.2 What it is — and what it is NOT

It is a proxy for galamsey pressure, for triage and targeting. A high rank flags a district as a priority for verification. It is not a determination of galamsey, not proof that illegal mining is occurring in a district, not an identification of operators, and not enforcement evidence. This framing is carried on every surface: the page banner, every API response (meta.caveat), and the PDF brief's banner and limitations box.

Engine version — read this before citing anything.

The v1.3 output labels each concession-subtraction operator on the Chamber of Mines factsheet, but those polygons are emulated dodecagons around publicly-disclosed operator centroids — not surveyed licence boundaries — so LSM-hosting districts can still rank inflated. See §24.7a for the named district list, current post- subtraction ranks, and the "do not cite" instruction.

24.3 The score

Each district receives a galamsey-pressure score, 0–100 — a relative national ranking, not a percentage of land mined — from three components, each min-max normalised across all districts with a robust 5th–95th percentile clamp, then combined and rescaled:

Component Weight Definition
Forest-loss intensity 50 % Hansen GFC tree-cover loss in the galamsey era (lossyear ≥ 2015, on land with year-2000 tree cover ≥ 10 %) as a percentage of the district's wooded area, with built-up land excluded (ESA WorldCover 2021 class 50).
Riverine share of the loss 30 % The share of that loss falling within 300 m of a river (WWF HydroSHEDS HydroRIVERS Level-8, denser than the earlier FreeFlowingRivers asset; 300 m matches the Ghana alluvial-galamsey concentration band per Snapir 2017, Forkuor 2020, Owusu-Nimo 2018). The historical 1 km buffer over the FreeFlowingRivers subset diluted the signature and is preserved as _LEGACY_* in the producer for A/B comparison.
Documented-site density 20 % Recorded galamsey sites per km² (curated + sanitised ghana_galamsey_sites.geojson), latitude-corrected. Precise-coordinate sites only — features tagged coordinate_provenance: district_centroid_approx are excluded from this weight (they were self-referential, since a centroid always falls inside its own district).

Each component is min-max normalised across all 260 districts with a robust 5th–95th percentile clamp (that turns raw units into a 0–1 score), then the three normalised values are combined 50 / 30 / 20 and rescaled so the final score sits on 0–100. Scores are grouped into action-priority tiers (renamed 2026-08-24 from the earlier "severity" band labels after a six-hat review flagged the old wording as politically radioactive and read as a verdict rather than a triage priority): P1 · Verify first ≥ 70 · P2 · Investigate ≥ 50 · P3 · Monitor ≥ 30 · P4 · Watch ≥ 15 · Baseline < 15. Server-side JSON keys retain the legacy severe / high / moderate / low / minimal shape for backwards compatibility; the frontend and PDF brief translate to the tier labels.

24.4 Why built-up land is excluded

Without a built-up mask, urban tree loss near city drains scores as riverine "galamsey" — in testing, Ablekuma North (urban Accra, on the Odaw) ranked #10 nationally, an indefensible false positive. Masking ESA WorldCover built-up land moved it to #242 and left the genuine galamsey belt on top. This exclusion is the single most important galamsey-specificity control after the riverine weighting.

24.5 Data sources

24.6 Production & currency

Earth Engine runs offline in the producer (scripts/build_galamsey_ranking.py, ee.Initialize(project="safeground")), which writes two static files the server reads without ever touching GEE: frontend/data/ghana_galamsey_ranking.json and ghana_districts_display.geojson (simplified choropleth polygons). This preserves the platform's no-Earth-Engine-on-the-box posture. Reductions run at 100 m — a native-30 m reduceRegions over 260 districts times out, and 100 m does not change the district-level ranking (documented in meta.reduction_scale_m). The ranking is a dated snapshot (the page and every response carry generated + loss_window); it is rebuilt from Hansen's annual release, so the refresh cadence is once a year.

24.7 Validation

The ranking reproduces Ghana's known galamsey geography: the top districts are Asante-Akim Central, Tarkwa Nsuaem, Denkyembour, Amansie West, Berekum West, Ahanta West, Bekwai, Abuakwa South, Prestea-Huni Valley, Kwaebibirem, Amansie Central, Obuasi, Birim Central, Obuasi East, Kwahu West — the Western/Ashanti/Eastern mining belt. Tier distribution (2026-08 snapshot, legacy JSON band keys): 15 severe (P1), 58 high (P2), 85 moderate (P3), 66 low (P4), 36 minimal (Baseline); national era forest loss ≈ 1.47 M ha.

Peer-benchmark validation is on the release backlog. The single strongest external benchmark for this layer is Barenblitt et al. (2021) "The large footprint of small-scale mining in Ghana" (Remote Sensing 13(15) 3054), a Sentinel-2 supervised-classifier mining-polygon dataset for Ghana. The intended validation exercise is a Pearson-r comparison of the tool's per-district forest_loss_ha_unlic against Barenblitt's mining-polygon area per district (n = 260 MMDAs), reporting r, sign, and top-10 agreement rate. Concordance value pending — do not cite the current v1.0 ranking against Barenblitt until this test is run. Where the tool disagrees with Barenblitt at district level, Barenblitt takes precedence.

24.7a Attribution caveat — do NOT cite these districts as galamsey

This section is load-bearing. Engine v1.3 (served) applies a concession-subtraction step using Maus 2022 (Sentinel-2-derived mining polygons, CC BY 4.0) unioned with the Ghana Chamber of Mines 2024 factsheet's operator-disclosed footprints. But the Chamber footprints are emulated dodecagons around publicly-disclosed operator centroids — not surveyed licence boundaries, so districts that host licensed large-scale mining can still rank inflated on the residual (post- subtraction) forest-loss and riverine-share weights. Attributing a high rank on those districts to galamsey — in a letter, a decision, an allocation, a briefing, a press release, or a media quote — is factually risky and creates a defensible Chamber-of-Mines / operator- counsel complaint.

The following districts carry licensed_lsm: true in the API payload and an amber "Attribution caveat" chip on the frontend, and must not be interpreted as galamsey attribution without independent verification:

District Region Rank (v1.3 · post-subtraction) Rank (v1.0 · no subtraction) Δ Licensed operator(s)
Ahanta West Western 3 6 +3 Various small-scale licensed
Bekwai Ashanti 5 7 +2 AngloGold Ashanti Obuasi flank
Amansie West Ashanti 6 4 -2 Perseus / Central Ashanti Gold
Tarkwa-Nsuaem Western 7 2 -5 Gold Fields Tarkwa; Damang
Amansie Central Ashanti 8 11 +3 Perseus Edikan flank
Kwaebibirem Eastern 10 10 0 Newmont Akyem flank
Obuasi Ashanti 11 12 +1 AngloGold Ashanti Obuasi
Obuasi East Ashanti 14 14 0 AGA Obuasi flank
Prestea-Huni Valley Western 18 9 -9 Golden Star Bogoso-Prestea
Wassa Amenfi East Western 21 21 0 Chirano / various licensed
Asutifi South Ahafo 47 51 +4 Newmont Ahafo South
Birim North Eastern 48 38 -10 Newmont Akyem
Ellembelle Western 58 39 -19 Adamus Resources (Nzema)
Wassa Amenfi West Western (varies) 66 Various licensed
Asutifi North Ahafo 79 70 -9 Newmont Ahafo North
Tano North Ahafo 81 82 +1 Newmont Ahafo flank
Nzema East Western 98 77 -21 Adamus fringe
Talensi Upper East 196 108 -88 Cardinal Namdini (licensed SSM)

Negative Δ = the concession-subtraction correctly demoted the district (most cases — Talensi -88, Nzema East -21, Ellembelle -19, Birim North -10, Prestea-Huni Valley -9). Positive Δ or 0 = the Chamber emulated dodecagon undercovers the operator's true licensed footprint (e.g. Ahanta West + Bekwai + Amansie Central rose slightly after the TREE_THRESH raise from 10 → 25 % concentrated pressure on real tree-cover-loss districts). Districts flagged in either state must be treated with the same caveat.

The licensed_lsm flag is emitted server-side by backend/app/services/galamsey_monitor.py against a curated list sourced from the Ghana Chamber of Mines 2024 factsheet and GCMRS operator disclosures.

Fix path. The remaining gap is source-of-truth: emulated dodecagon polygons are a fallback for concessions Maus 2022 does not detect; they are superseded when the Minerals Commission GCMRS shapefile is obtained via MoU. Once that shapefile lands, the producer re-runs against the true licence boundaries and the residual attribution inflation for the LSM-flagged districts drops further.

24.8 Limitations (defensibility)

24.9 Reproducibility

The producer, weights, thresholds and data assets are all in the repository; re-running python scripts/build_galamsey_ranking.py on a GEE-authenticated machine regenerates the ranking deterministically (GADM + Hansen + WorldCover + HydroSHEDS are fixed public assets between Hansen releases). Tests: backend/tests/test_galamsey_monitor.py.

25. Change log

Date Change
2026-09-18 Wave-6p — four-hat review response. Post-wave-6o multi-hat re-review (legal / field-officer / security / coastal-hydrology). P0 findings closed: (a) Reg 40 anti-drift bypass — test_citation_map.py scanned only .py files, so Reg 40 (emitted via ghana_inland_water_bodies.geojson) escaped audit; extended scan to include frontend/data/*.geojson, added Reg 40 row to docs/citation_map.md. (b) reclamation_precedent block was in the geojson but never reached the officer's screen — added it (plus historic_footprint_note, historic_catchment_km2_approx, pin_inside_historic_footprint, reclamation_risk_note, buffer_rationale) to the IWB response payload; frontend renders a red "Reclamation-precedent — do not approve without EIA" callout when the pin sits inside the historic footprint. (c) Reg 29 decision letter now front-loads a "Reclamation-precedent case-of-record" paragraph naming L.I. 2504 Reg 40 as primary anchor when pin_inside_historic_footprint is True. (d) Added historic_extent_1974 polygon to Kpeshie feature (rectangle covering the reclaimed strip south to LaBoma / Regimanuel-Grey / Trade Fair / Burma Camp) so point-in-polygon can distinguish reclaimed-mangrove from legitimate-upland within the 1500 m ring. Officers now see an amber "Awareness-ring hit — not on the historic wetland footprint" note for legitimate-upland hits vs the red case-of-record callout for reclaimed hits. (e) L.I. 1659 "analogous buffer regime" self-defeating phrasing reworded — now states it as the closest gazetted analogue while national Wetland Management Regulations remain in draft; the buffer test operates independently under LUSPA Act 925 §125 and WRC Act 522 §13. (f) Korle buffer tightened 1500 → 800 m (post-KLERP polygon is ~2 km²; 800 m ring covers Agbogbloshie/Old Fadama reclamation without over-sweeping historic James Town / Bukom, upland since colonial gazette). (g) Songor buffer tightened 1500 → 500 m (Ramsar polygon already 115 km²; the polygon itself covers the entire delta so a smaller ring is sufficient). (h) Per-lagoon reclamation_risk_note now cites the actual reference (Nartey 2011 for Kpeshie, Ntiamoa-Baidu 1988 for Sakumo, Essel 2019 for Fosu, Angnuureng 2015 for Muni-Pomadze, etc.) instead of an identical generic string. (i) New backend/tests/test_audit_chain.py with 5 regression cases (hash-framing, happy path, payload-tampering detection, prev_hash splice detection, empty case) — the audit chain is the legal keystone and had no test. (j) METHODOLOGY §12.9 gains explicit "instruments inspected and found NOT to contain a gazetted metric coastal setback" footnote (GS 1207:2018, L.I. 1968 Reg 7, PNDCL 159, MESTI 2020 draft) so future reviewers don't re-open the question. 79/79 tests green. sw v115.
2026-09-18 Coastal-lagoon reclamation buffer widening (wave-6o) — LaBoma 2026 precedent. 13 Sep 2026 REGSEC / 48 Engineer Regiment demolition at LaBoma Beach exposed the tool's inability to catch reclaimed-wetland sites: LaBoma coords sat 1,302 m south of the current Kpeshie polygon while the tool's proximity buffer was 400 m. Widened proximity_buffer_m on 8 Greater-Accra + coastal urban lagoons (Kpeshie 400→1500, Sakumo 400→1200, Korle 400→1500, Chemu 400→1000, Fosu 400→800, Densu Delta 400→1500, Muni-Pomadze 400→800, Songor 400→1500). Added L.I. 2504 Reg 40 (reclamation permit mandatory — operative anchor for the LaBoma demolition), LUSPA Act 925 §125, L.I. 2384 (2019), L.I. 1659, NADMO Act 927 to the affected features' gazetting_chain. Kpeshie feature gains historic_footprint_note + historic_catchment_km2_approx: 22 + reclamation_precedent block naming the demolition, task force, and operative statutes. Regression test test_laboma_beach_triggers_kpeshie_proximity_wave_6o asserts LaBoma coords fire the proximity override with the LaBoma statute chain. New METHODOLOGY §12.9 documents the trigger event, the gap, the fix, and the queued follow-ups (1974 topo digitisation, GEE reclaimed-wetland raster, mangrove-loss layer, national REGSEC-risk watchlist). 74/74 tests green.
2026-09-07 Galamsey Monitor — wave-6n-run2 W+D turnup + sources-honesty producer patch. Log audit of the first successful run found that meta.sources[] was hardcoded and lied — claimed HydroRIVERS Level-8, OSM waterway union, Sentinel-2 W term, and JRC TMF D term were used when all four were disabled. Wave-6n-run2 fixes: (a) W term now works — added defensive .select(0) before .rename() to force single-band before naming (fixes the lazy-eval "number of names (1) must match bands (N)" trap); every district now carries w_uplift_river; (b) D term now works — ImageCollection("projects/JRC/TMF/v1_2024/AnnualChanges").max() was returning a 35-band Image (one Dec_YYYY per year 1990-2024), fixed by collapsing across bands via .reduce(ee.Reducer.max()) before eq(2); every district now carries d_degraded_ha; (c) meta.sources[] is now CONDITIONAL on the runtime toggles + asset availability so it can never re-drift on a future run — a new meta.sources_not_used_this_run field names anything that was gated out (currently: OSM union env-off, Maus 2022 file absent); (d) inverted logic bug in the sources-not-used branch caught in the same pass; (e) Maus 2022 Zenodo DOI notation includes the broken-record note + dataset_recovery_path pointing at WU Vienna fineprint.global. Ranks unchanged from wave-6n-run1 (W + D are informational; primary F/R/S composite untouched).
2026-09-07 Galamsey Monitor — wave-6n producer re-run. After the wave-6n peer-review response (below), executed py scripts/build_galamsey_ranking.py against the safeground GEE project. Three false starts (OSM waterway union hit GEE's 10 MB request-body cap; WWF/HydroSHEDS/v1/HydroRIVERS is missing from the public GEE catalog; W and D side-terms emitted 35-band Images that failed .rename()); the fourth run — with GALAMSEY_INCLUDE_OSM=0, river asset reverted to FreeFlowingRivers, and INCLUDE_W_TERM/INCLUDE_D_TERM disabled — completed cleanly. Engine v1.3 is now served with: 300 m river buffer (was 1 km), TREE_THRESH=25 (was 10), Maus 2022 + Chamber of Mines 2024 licensed-mining subtraction, low-tail-only clamp, 500-run weight-jitter rank_ci_95, ESA WorldCover 2021 ⋃ Dynamic World 2023-24 built-up mask, centroid-approximation sites excluded from S. Verified subtraction effect on LSM-hosting districts: Talensi -88, Nzema East -21, Ellembelle -19, Birim North -10, Prestea-Huni Valley -9, Tarkwa-Nsuaem -5. Still PENDING: OSM waterway union (needs a project-owned GEE asset upload to bypass the 10 MB inline-geometry cap), HydroRIVERS Level-8 densification (needs a public/private asset provisioning), W (Sentinel-2 turbidity) and D (JRC TMF degradation) informational terms (both need a .reduce().rename() fix). METHODOLOGY §24.2 rewritten to reflect v1.3 running; §24.7a table updated with post-subtraction ranks + Δ vs v1.0; USER_MANUAL §27.0 rewritten; frontend attribution-caveat banner updated to name the emulated-dodecagon limit rather than the missing-subtraction limit.
2026-09-07 Galamsey Monitor — wave-6n peer-review response. Independent methodology review (triple-hat: remote-sensing scientist + composite-index methodologist + Ghana galamsey policy specialist) confirmed that the served ranking is engine v1.0 (snapshot 2026-08-04, 1 km FreeFlowingRivers buffer, no concession subtraction), while METHODOLOGY / USER_MANUAL / frontend were describing the coded-but-not-run engine v1.3. Ships the following: (a) server-side injection in backend/app/services/galamsey_monitor.py of licensed_lsm: true + attribution_caveat fields on 19 districts hosting Minerals Commission-licensed LSM (Tarkwa, Prestea, Obuasi, Bekwai, Asutifi N/S, Ellembelle, Talensi, Wassa Amenfi belt, Newmont Akyem flanks, etc.); (b) new summary.attribution_caveat_districts list on every /ranking response; (c) amber "Attribution caveat — do NOT cite these districts as galamsey" banner on frontend/galamsey.html rendered from that server-side list; (d) new §24.7a with a per-district table and the survive-the-letter sentence; (e) §24.2 gains an "Engine version" block that names v1.0 vs v1.3 explicitly; (f) §24.8 expanded with the tree-cover-baseline permissiveness (TREE_THRESH = 10 %), F-R non-independence, weight-jitter-vs-structural-sensitivity distinction, and band-cutoff arbitrariness; (g) TREE_THRESH in scripts/build_galamsey_ranking.py raised from 10 to 25 for the next producer re-run (aligns with Snapir 2017 / Forkuor 2020 practice for Ghana savanna baseline); (h) §11 bibliography gains Barenblitt 2021 (peer benchmark; validation exercise queued), Forkuor 2020, Owusu-Nimo 2018, Bansah 2019, Boadi 2016, Ferretti-Gallon 2021, Hilson 2017, Kalischek 2023, Maus 2022, Act 703 / L.I. 2462, IMCIM reports; (i) USER_MANUAL §27 fully rewritten — new §27.0 "engine version + LSM caveat", §27.4 "How NOT to use it", §27.5 bibliography. Blocked on GEE re-run to fully retire v1.0: producer script needs py scripts/build_galamsey_ranking.py on the safeground-authenticated workstation.
2026-08-25 Galamsey Monitor — six-hat review response (waves 3 + 4, plus non-Galamsey wave 2). After Amin flagged the "Galamsey-affected rivers" overlay as visually incomplete and the map as missing basemap options, and after producing the "everything in my capacity" fix pass: Wave-3 shipped: (a) map overlay galamsey_rivers extended from southern-basin-only (Pra/Ankobra/Tano/Birim/Offin, lat 6.78–7.61, 2,938 features) to full-Ghana coverage (lat 4.89–10.93, 3,018 features) by unioning HydroSHEDS Level-8 with rivers from ghana_rivers_display.geojson within a 10 km buffer of any documented Northern-belt galamsey site (White Volta, Kulpawn, Sissili, Oti, Daka, Black Volta) — new scripts/extend_galamsey_affected_rivers.py idempotent producer, features carry provenance = hydrosheds_basin_southern
2026-08-25 Galamsey Monitor — six-hat review response (waves 1 + 2). Six specialist hats (remote-sensing methodology, Ghana galamsey domain expert, EPA field officer, political-economy / MMDA reception, Ghana legal / defamation / RTI, product-UX for high-stakes gov tools) reviewed the layer end-to-end and returned convergent P0 findings. Wave 1 shipped: (i) site register ghana_galamsey_sites.geojson sanitised — every corporate operator name (AngloGold Ashanti, Gold Fields, Newmont, Cassius, Asanko, Perseus, Chirano, Golden Star, Kinross, Adamus, Shaanxi, AGA) stripped from features + dataset metadata, and every feature notes normalised to a single neutral sentence to close the trade-libel and DPA-843 exposure Legal + Political + Domain hats independently flagged; (ii) galamsey.html masthead + galamsey_pdf.py cover rebranded to name Resilicity as the pilot publisher not EPA, Ghana-flag chrome removed, contradictory "not for external distribution" language dropped everywhere; (iii) bands renamed from severity words to action-priority tiers (P1 · Verify first / P2 · Investigate / P3 · Monitor / P4 · Watch / Baseline) with a softer top-tier red so the pill reads as triage priority not conviction; (iv) in-card caveat strip + diagonal "PROXY · TRIAGE · NOT ENFORCEMENT" watermark added so a top-N ranking screenshot carries the qualifier; (v) drill panel converted to a proper role="dialog" with focus-trap, Escape-to-close, backdrop click-to-close, aria-labelledby; (vi) baseline (green) districts get an explicit "not evidence of absence" note; (vii) ~15 districts hosting substantial licensed large-scale mining now carry a subtle "licensed LSM" chip + full disclosure box in the drill panel (partial mitigation until concession subtraction); (viii) right-of-reply mailto on every district drill; (ix) meta.snapshot_id (deterministic sha256[:10] of the ranking file) stamped on every /galamsey/ response so decision letters can pin a specific snapshot that survives the next re-run; (x) new district_for_point(lat, lon) helper + a compact §0c "Galamsey Monitor context" callout in the single-site determination PDF for sites in a P1/P2/P3 district. Producer script changes (apply on next GEE re-run): river asset switched FreeFlowingRivers → HydroRIVERS Level-8; riverine buffer 1000 m → 300 m; S term excludes coordinate_provenance: district_centroid_approx sites. Wave 2 shipped: METHODOLOGY §24 updated to reflect the tier language, HydroRIVERS switch, buffer change, sanitisation, licence field, and licensed-LSM caveat; landing-hero "Galamsey Monitor" button gained a one-line subtitle; per-source licence field added to every site feature; right-of-reply page + 14-day SLA published at /galamsey-rightofreply.html; choropleth polygons carry an SVG hatch pattern for colour-blind readers; coordinate-lookup UI on the Monitor page ("paste 6.23, -1.57" → drills to district); drill panel now lists documented site coordinates inside the district with a Sentinel-2 EO-Browser deep-link; per-region PDF brief adds a site-coordinates appendix. Not yet done (queued for producer re-run + data-access):* subtract Minerals Commission licensed concessions from F/R and rename score "unlicensed vegetation-loss pressure"; add JRC TMF degradation + Sentinel-1 SAR change for hard-rock / sub-canopy galamsey; add RADD / GLAD recent-pressure signal for post-2024 activity; publish rank_ci_95 from weight-jitter bootstrap; clip only the low tail (0–95pct) so top-of-ranking discrimination is preserved; add a water-quality W term; distinguish Community Mining Scheme blocks; refresh WorldCover 2021 → 2023 + widen built-up buffer. No screening rule, statutory citation, screening score, spatial dataset or polygon in the rest of the tool changed.
2026-08-04 NEW — Galamsey Monitor (national district galamsey-pressure ranking). Added /galamsey.html + services/galamsey_monitor.py + GET /galamsey/ranking and GET /galamsey/district/{gid}, ranking all 260 MMDAs by a galamsey-specific reading of vegetation loss (not raw deforestation). Composite score (0–100) = forest-loss intensity F (0.50) + riverine concentration R (0.30) + documented-site density S (0.20), each robust-normalised (5th–95th-pct clamp) across districts. F = Hansen Global Forest Change v1.13 tree-cover loss in the galamsey era (lossyear ≥ 2015, treecover2000 ≥ 10 %) as a share of the district's wooded area, with built-up land excluded (ESA WorldCover 2021 class 50) so urban tree loss is not misread as galamsey — this alone moved Ablekuma North (urban Accra, on the Odaw) from a false-positive rank 10 to rank 242. R = the share of that loss falling within 1 km of a river (WWF HydroSHEDS free-flowing rivers) — galamsey's alluvial signature. S = curated galamsey-site register density. Producer scripts/build_galamsey_ranking.py runs Earth Engine locally (reductions at 100 m — native 30 m times out over 260 polygons and does not change the district-level ranking) and writes two static files the box serves without ever touching GEE: frontend/data/ghana_galamsey_ranking.json (ranking + meta) and ghana_districts_display.geojson (choropleth polygons). Top-ranked districts are the known galamsey belt — Asante-Akim Central, Tarkwa Nsuaem, Mpohor, Denkyembour, Amansie West/Central, Prestea-Huni Valley, Obuasi, Wassa Amenfi East. Framing (defensibility): the score is an explicit PROXY for officer triage, not a determination of galamsey and not enforcement evidence — it cannot separate galamsey from legal mining, farming, logging or fire, and every API response + the page banner say so; a high rank flags a district for field/high-resolution verification, it does not convict it. Currency: a dated static snapshot (Hansen loss through 2024); the page shows the as-of date and loss window and does not self-update. Refresh cadence: annual, keyed to each Hansen release (one-command re-run of the producer). Frontend = choropleth of all 260 MMDAs coloured by pressure band + region rollup + sortable/filterable ranked table + per-district drill-down + CSV export, with the proxy banner and as-of stamp. Tests backend/tests/test_galamsey_monitor.py (6: region rollup, filters, summary invariants). No existing screening rule, verdict, spatial threshold, statutory citation or polygon changed.
2026-08-03 Determination-PDF relevance and legal-confidence gate. Re-screened three representative live locations (Adabraka residential, Fosu Lagoon hotel and a Northern solar project) and audited every generated section for officer/proponent relevance. Reduced the reports from 9–10 pages / 4,221–4,868 words to 4–5 pages / 1,577–2,235 words in the representative set by: filtering broadcast Schedule-2 rules and the cover reason to the declared sector; removing internal audit rule IDs; replacing the generic all-clock registry with pathway-specific statutory clocks; correcting the Full-EIA cover from the stale 90-day text to L.I. 2504 Reg 28(1)(c)'s 60-calendar-day clock; replacing baseline-study cards with a compact requirements table; removing the duplicated all-indicator radius catalogue; showing full spatial detail only for material findings while retaining a named green-check summary; replacing the outdated 14-indicator methodology inventory with concise, dynamically counted provenance; filtering generic stakeholder placeholders; and removing raw internal /fees route references. Added a fail-closed penalty rule: no penalty content is printed unless its legal reference is verified; the contradictory upstream Act 1124 §188 content and inconsistent cash conversions are therefore withheld from all reports. Added PDF-text regression tests for repealed/invalid law, internal metadata, generic tool-policy content and baseline relevance. No screening verdict, spatial threshold, dataset or polygon fidelity changed.
2026-08-03 Central authorization matrix — first high-risk route tranche. Added a fail-closed capability policy separating authentication from authorization and documented its route coverage in docs/AUTHORIZATION_MATRIX.md. Restricted management and officer-activity analytics to named Directors or higher and named platform administrators; this closes the older /cases/analytics and /cases/analytics.csv path that exposed nationwide and officer-level aggregates to any authenticated officer. Moved user invitations/role changes, Officer Directory administration and permanent case-record purge behind explicit named-admin capabilities, so the shared Open-Access pilot identity cannot exercise them despite carrying a synthetic admin role for demonstration purposes. Added route-level deny tests covering ordinary officers and the pilot identity, plus allow tests across all management-analytics endpoints. Case ownership and the reconsideration/hard-case signature ladder remain separate mandatory controls. No screening rules, spatial datasets, statutory citations or polygon fidelity changed.
2026-08-03 External-archive dirty-volume safety gate. After Windows reported the connected Samsung_T5 physical SSD healthy but its exFAT D: volume dirty and requiring repair, hardened the nightly archive workflow to check both Get-Volume health and fsutil dirty query before every external write. Local verified snapshots continue when the drive is absent/unsafe, but no database is copied to a dirty or unhealthy external filesystem. Existing archive SHA-256 sidecars were reverified successfully. Filesystem repair remains an explicit owner-approved operation. No screening, retention, or authorization logic changed.
2026-08-03 Permanent institutional archive and external-drive recovery. Changed the retention posture for case records, tombstoned records, audit lineage, decision PDFs, batch inputs/results and officer activity history to permanent archival custody with no automatic institutional-record deletion. Preserved expiry of live login attempts/session tokens and documented the Act 843 §24 boundary: permanent identifiability requires a recorded statutory or other lawful-purpose exception; otherwise identifying fields are pseudonymised while non-identifying statutory/history data remains permanently recoverable. Extended pull-cases-db.ps1 to retain local snapshots indefinitely by default and copy every integrity-checked snapshot to a separate external-drive data archive with SHA-256 sidecars, append-only JSONL catalogue and BitLocker-status warning. Added restore-cases-archive.ps1 for hash/integrity-verified local recall and explicitly confirmed production restoration through the existing stop/restore/health workflow. The Git mirror continues to exclude runtime databases and secrets. No screening rule, dataset, threshold, citation or verdict logic changed.
2026-08-03 Durable caseload jobs, tranche 1. Added a persistent batch_jobs queue for named-officer CSV/GeoJSON/JSON screening with atomic claiming, queued/running/completed/failed/cancel-requested/cancelled states, row progress, owner-or-leadership status access, cancellation between completed rows and automatic re-queuing of interrupted work on service restart. The caseload UI now submits named-officer work asynchronously, polls progress, permits browser disconnect/return and opens the immutable completed snapshot; anonymous pilot users retain the non-persistent synchronous path. Every completed job continues through existing batch_runs hashes/audit persistence and officer-activity attribution. Added cancellation/access/order regression tests. Corrected the service worker so all identity-bearing /batch GET responses, including job status and saved history, are network-only and never leak through shared-device caches; cache release advanced to v87. Restart recovery safely reruns an interrupted job from its beginning; PostgreSQL multi-worker execution, retained per-row checkpoints and explicit failed-job retry remain P1 work. No screening rule, dataset, threshold, citation or verdict logic changed.
2026-08-03 Restricted officer screening-activity analytics. Added screening_activity persistence and /activity/summary management API plus /activity.html charts by individual officer, Act 1080 sector, department, regional office and month. Successful named-officer /screen, case-creation and non-error batch rows are recorded; anonymous/Open-Access pilot activity is excluded. A stable officer+project fingerprint (rounded coordinates + sector + title) counts one unique project while incrementing run_count for repeat preview/re-screen/case-save activity, preventing routine corrections from inflating project totals. Department/region/office-type are snapshotted at activity time for historical traceability. Backend authorization restricts analytics to named administrators or Officer Directory rank director and above; ordinary officers and pilot visitors receive 403 even with a direct URL. The service worker treats /activity as identity-bearing, network-only data. Added a two-year identifiable retention policy and explicit warning that workload counts are not a quality/performance score without project-complexity and duty context. Tests cover the gate, pilot exclusion, deduplication and rollups. No screening rule, spatial dataset, threshold, citation or verdict logic changed.
2026-08-03 Caseload accessibility and privacy-copy correction. Corrected the caseload page's residual claims that every upload is stored/shareable: only named-officer runs persist, while anonymous pilot runs remain immediate and non-retained. Added a keyboard skip link, visible focus indicator, programmatic labels for file/paste/radius inputs, polite live announcements for screening status and history, semantic map description, keyboard-focusable horizontal result regions and accessible names for region/sector/district/site tables. Extended the JavaScript syntax regression test to parse the dedicated batch.html application script as well as the main SPA. This is an initial remediation, not a claim of WCAG 2.2 AA certification; independent assistive-technology testing remains required. No screening rule, spatial dataset, threshold, citation or verdict logic changed.
2026-08-03 Nationwide readiness and stakeholder acceptance review. Added docs/NATIONWIDE_READINESS_REVIEW.md, a whole-platform assessment covering the current technical baseline, EPA governance, regional officers, legal/ICT/records/finance, LUSPA/MMDAs/Lands/OASL/traditional authorities, WRC/Forestry/Minerals/GMet/GHA/NADMO and other sector custodians, NITA/DPC/CSA/GSS/audit/procurement stakeholders, proponents/consultants/communities/civil society/accessibility users, prioritized P0–P3 gaps, phased adoption, measurable service targets and primary official policy anchors. The review preserves EPA as statutory decision owner and treats other participants according to their data, consultation, assurance or user roles. No screening rule, spatial dataset, threshold, citation or verdict logic changed.
2026-08-03 Caseload privacy boundary + template-route repair. Moved the static GET /batch/template.csv declaration ahead of GET /batch/{run_id} so FastAPI no longer interprets template.csv as a snapshot identifier. Anonymous/Open-Access pilot runs continue to return immediate triage results and CSV export but are no longer persisted or written to the audit ledger; persistence now requires a named officer identity. Saved-run history, snapshot detail and Cabinet-briefing PDF routes now reject anonymous/pilot identities. Ordinary officers see and reopen only their own snapshots, while authorised leadership/admin roles retain cross-officer management visibility. The batch UI explains the named-officer boundary instead of showing a generic history error. Added regression tests for route precedence and owner/leadership authorization. Also aligned both intake-module query versions and service-worker precache entries with cache release v85 after the frontend consistency test exposed stale v84 references. No screening rule, spatial dataset, threshold, statutory citation or verdict logic changed.
2026-08-01 NEW — Caseload / batch screening (jurisdiction-wide triage). Added /batch.html + services/batch.py + POST /batch/{screen,upload} + GET /batch/template.csv. Screens up to 300 sites in one pass through the same in-process orchestrate() the single-site /screen route uses (no new verdict logic, no new spatial data), then rolls the per-site verdicts up three ways: (a) triage buckets — Refused / Full-EIA / Registration / not-screenable; (b) by MMDA district — site count, worst outcome, cumulative hazard load (2·red + 1·amber), top hazards; (c) by indicator — how many sites hit each hazard red/amber; plus a proximity-clustering pass (greedy single-link within a chosen radius, default 2 km) that surfaces cumulative-impact hotspots — the cumulative-effects lens L.I. 2504 expects but single-site review structurally misses. Input is stdlib-parsed CSV (lat/lon + optional ScreenInput fields) or GeoJSON (Points, or Polygons screened at centroid); output is a Leaflet map + district/indicator/cluster rollups + a sortable, CSV-exportable per-site table. Batch always screens at the representative point (never the slow full-polygon path), carries its own per-IP rate limit (8/10 min) and MAX_SITES cap, and is explicitly a triage/planning aid, not the statutory determination — a flagged site still gets the single-site polygon screen. Tests: backend/tests/test_batch.py (13, incl. parser aliases, polygon-centroid extraction, haversine, greedy clustering with the red-beats-amber invariant, and rollup correctness). Live-verified end to end on scoping.resilicity.com (5-site mixed caseload → 2 refused Oti dam-spillage + 2 Accra full-EIA + 1 offshore error, correct district/indicator rollups). No existing screening rule, spatial data, threshold, or legal interpretation changed.
2026-07-27 Pilot-mode badge no longer blocks navigation. The Chromium smoke test showed that the fixed top-right “PILOT MODE · open access” badge overlapped the landing-page navigation CTA and intercepted pointer events, making that visible “Start a Screening” button unclickable. The informational badge now uses pointer-events:none, preserving its reminder function while allowing the underlying navigation control to receive clicks. The e2e test deliberately uses that navigation CTA so future positioning/style changes cannot silently reintroduce the obstruction. No authentication authority, screening logic, payload, spatial data, threshold, or legal interpretation changed.
2026-07-27 Same-origin API portability fix found by browser automation. The first Playwright run on port 18006 exposed a stale local-development branch in the runtime config and tracked frontend/config.example.js that forced every localhost/127.0.0.1 page to call http://localhost:8000, regardless of the port actually serving the application. Authentication therefore went to the wrong origin and the login overlay blocked the screening workspace. The API base now consistently uses location.origin, matching the supported architecture in which FastAPI serves the frontend and API together. This makes arbitrary local ports, containers, EPA-hosted instances, and production behave identically. Playwright copies the credential-free tracked template only when an ignored local runtime config is absent, keeping fresh-clone tests deterministic without overwriting deployment keys. Advanced service-worker cache v83 → v84 and aligned versioned intake module URLs. No production endpoint, screening rule, payload, spatial data, threshold, or legal interpretation changed.
2026-07-27 Automated Chromium screening smoke test in CI. Added a vendor-neutral Playwright Test setup that launches the real FastAPI application, opens the real frontend in Chromium, fails on uncaught page or console errors, verifies the document title, confirms locally hosted Leaflet 1.9.4 and absence of unpkg.com requests, opens the screening workspace, requires a Leaflet map container and loaded tiles, exercises agriculture → aquaculture subtype/scale rendering, parses decimal Ghana coordinates, validates the exact /screen preview request, confirms the deterministic response reaches the visible risk preview, and verifies the normalized project-details payload. Only external analytics, basemap tiles, and the screening response are mocked so CI remains deterministic and does not depend on third-party availability or production upstreams. GitHub Actions now installs pinned Playwright 1.58.2 + Chromium and runs the smoke test after unit tests; traces/screenshots are retained on failure locally. No production dependency, screening rule, spatial data, threshold, or legal interpretation changed.
2026-07-27 Self-hosted Leaflet 1.9.4 — map startup no longer depends on unpkg. Vendored the pinned official Leaflet production distribution, source map, CSS-referenced control/marker images, and BSD-2-Clause license under frontend/vendor/leaflet/. Replaced the runtime unpkg.com stylesheet/script requests with same-origin versioned URLs; precached the library, stylesheet, and all five image assets for offline/PWA use; removed unpkg.com from both application and nginx CSP definitions; advanced service-worker cache v82 → v83. Added regression coverage requiring local HTML references, absence of the Leaflet CDN, complete precache registration, existence of every CSS-referenced image, non-truncated JavaScript/source-map distributions, and the vendor license. This closes the original map-blank failure mode where CSP or CDN availability prevented L from loading. Basemap tiles remain external data services and retain the existing fallback chain. No spatial data, screening rule, scientific threshold, legal interpretation, or determination output changed.
2026-07-27 Service-worker rolling-update compatibility for extracted intake modules. Live browser verification of phase 4 caught a one-reload compatibility window: a tab controlled by cache v80 could receive the new HTML while still serving the older unversioned intake.js, producing _buildScaleFieldsHtml is not defined when the officer selected a sector. The intake module and taxonomy URLs are now explicitly tied to cache release v82 in both index.html and the service-worker precache. An automated regression derives the active cache number and requires both HTML imports and precache entries to match it. This forces an old controller to fetch the new module URL from the network and prevents mixed-release HTML/JavaScript execution. No screening logic, payload, taxonomy, threshold, or legal interpretation changed.
2026-07-27 Frontend decomposition, phase 4 — tested intake transformations. Extracted two pure transformations from the project-details DOM controller into frontend/js/intake.js: scale-field HTML generation with applicable-value carryover, and normalization of title/sector/subtype/numeric scale/water-dependence values into the existing ScreenInput payload shape. Added Node regression cases covering exact rendered markup, value preservation, title trimming, numeric parsing, blank/invalid omission, dynamic subtype keys, and the explicit water-dependent flag. index.html now retains only element lookup and event wiring. Advanced service-worker cache v80 → v81. No field name, payload value, project taxonomy, screening rule, scientific threshold, legal interpretation, or determination output changed.
2026-07-27 Frontend decomposition, phase 3 — intake taxonomy module. Moved the complete 11-sector project subtype and scale-field taxonomy unchanged from the monolithic frontend/index.html into the browser/Node-compatible frontend/js/intake-config.js module. The UI continues to consume the same _PD_CONFIG global contract, while Node regression tests now import the taxonomy directly instead of parsing and evaluating an HTML substring. Added the module to service-worker precaching and advanced cache v79 → v80 so installed/offline users receive the extracted configuration. This removes approximately 287 lines from the main HTML without changing sector values, subtype values, scale fields, screening payloads, legal rules, scientific thresholds, or determination outputs.
2026-07-27 Current-state synchronization invariant for AI-agnostic continuity. Reconciled and committed the public frontend copies of the canonical user manual and HR roster templates (docs/USER_MANUAL.mdfrontend/manual.md; CSV/XLSX templates under docs/ → matching frontend/ assets). Added byte-for-byte pytest checks so CI fails whenever a canonical document changes without its public copy. Updated the vendor-neutral agent, continuity, and onboarding guidance to require canonical, frontend, local, GitHub, production, and external-backup copies to represent the same release; deployment is incomplete if it leaves a dirty worktree or an older copy anywhere. Corrected stale change-log references from §17 to the actual §24. No screening logic, scientific threshold, legal interpretation, or polygon changed.
2026-07-27 Frontend decomposition, phase 2 — intake taxonomy guardrails. Extracted the pure sector/subtype scale-field resolver into frontend/js/intake.js while preserving its browser-global contract. Added structural regression coverage over the complete 11-sector project-intake taxonomy: subtype field metadata, option presence, subtype-to-override consistency, field-name grammar, non-empty labels, fallback behavior, and representative aquaculture/transmission overrides. The module is service-worker precached and cache version moved from v78 to v79. This test layer is the prerequisite for safely moving the remaining 300-line taxonomy object out of index.html; no taxonomy value or screening input changed.
2026-07-27 Frontend decomposition, phase 1 — coordinate geometry module. Extracted polygon-text parsing, point-coordinate parsing, polygon area, and area-weighted centroid calculations from the monolithic frontend/index.html into the standalone same-origin frontend/js/geometry.js module while preserving the existing browser-global function contract. Added Node built-in regression tests for GeoJSON axis order, Ghana input bounds, area, centroid, and invalid input; CI now runs both Python and frontend JavaScript suites. The module is service-worker precached and the cache version moved from v77 to v78 for reliable installed-PWA rollout. No screening rule, backend geometry, threshold, or determination output changed.
2026-07-27 SQLite concurrency safeguards + API security regression coverage. Centralised cases-database connection configuration now enables WAL journal mode at startup, a 10-second busy timeout on every connection, foreign-key enforcement, and synchronous=NORMAL; this improves concurrent reader/writer behaviour and prevents silent orphan records while retaining the portable SQLite deployment model. Added isolated temporary-database tests for all four PRAGMAs and foreign-key rejection. Added application-level regression tests for HSTS, CSP/Leaflet allowlisting, clickjacking/MIME/referrer headers, hostile-origin CORS rejection, and the configured production-origin preflight. Migrated deprecated FastAPI startup/shutdown events to the supported lifespan context and replaced deprecated query regex declarations with pattern; pytest-asyncio fixture-loop scope is explicit, keeping strict-warning test runs clean and deterministic across upgrades. Clean Linux CI exposed and fixed an undeclared runtime dependency: email-validator, required by Pydantic EmailStr, is now explicit in backend/requirements.txt. CI actions now use their Node.js 24 releases with least-privilege read-only repository permissions.
2026-07-27 Jurisdiction guard + Sakumo regression tests + CI baseline. Replaced the rectangle-only Ghana coordinate check with a pure, testable screening-jurisdiction validator: mainland inputs must fall inside a simplified Ghana outline while the established offshore envelope remains available for petroleum, port and coastal projects. This closes the demonstrated Lomé false acceptance; border-adjacent determinations remain subject to authoritative survey verification. Corrected the live Sakumo probe from the superseded Tema-industrial coordinate (5.620, -0.040) to the documented Sakumo Ramsar centroid (5.668, 0.012), without distorting the lagoon polygon. Added pytest coverage for representative Ghana/offshore acceptance, foreign-land rejection, orchestrator 422 behavior, and both new/old Sakumo coordinates; added a dependency-separated development requirements file and GitHub Actions backend compile/test workflow. Deployment verification fallback now checks the backend health listener directly instead of misclassifying Nginx's HTTP-to-HTTPS 301 redirect as a failed deployment, with a bounded warm-up retry for Uvicorn startup.
2026-07-27 Restore the location map after response-header security hardening. The FastAPI CSP added on 2026-07-25 allowed only same-origin scripts and styles, while the SPA loads Leaflet 1.9.4 from unpkg.com. Because the application CSP reached the browser ahead of Nginx's broader fallback CSP, Chrome blocked both Leaflet assets, window.L was undefined, and the map remained blank. The application policy now mirrors the approved CDN allowlist in deploy/nginx.conf, retains object-src 'none', and permits the existing analytics, Google Maps, font, and Leaflet origins. SW cache v76 → v77 so installed clients refresh the corrected shell. No screening logic, legal rule, dataset, polygon, or determination output changed.
2026-07-25 HR roster import (CSV + Excel) + directory-gated login (Task #199). Ships the workflow HR needs to keep the Officer Directory in sync + closes the "any @epa.gov.gh mailbox works forever" hole. Roster importer — new services/roster_import.py reconciles a CSV or .xlsx upload with officer_directory: new emails → INSERT, changed fields → UPDATE, DB rows absent from the file → soft-deactivate (never hard-delete — a typo can't wipe the roster). Idempotent, dry-run default, header-alias tolerant (accepts E-mail, Full Name, Manager, HQ, etc.). CLI at backend/scripts/import_officers.py. Admin API at POST /admin/officers/import?dry_run=false (require_named_admin, 25 MB cap). Templatesdocs/officer_roster_template.xlsx generated by backend/scripts/build_roster_template.py with data-validation dropdowns on rank · region · office_type · is_active (HR can't mis-type) + a Vocabulary sheet listing every accepted value. CSV twin at docs/officer_roster_template.csv. Deploy stages both into frontend/ so the "Download template" links resolve. Directory-gated login — new AUTH_REQUIRE_DIRECTORY=1 mode layers an is_email_in_active_directory() check on top of the suffix allowlist: an email must ALSO have an is_active=1 row in officer_directory to receive a magic link. Live sessions of a deactivated officer are invalidated on their next request (_resolve_session short-circuits + deletes the session row). AUTH_OVERRIDE_EMAILS bypass keeps the platform team from locking themselves out. Off by default → three auth states: (1) no directory, (2) directory-informed (login open, session enriched), (3) directory-required (login gated). UI — Officer Directory panel added to the User Management modal: state pills, roster upload with dry-run + deactivate-missing toggles, searchable directory table with per-officer deactivate. openpyxl>=3.1 added to requirements.txt (optional — CSV path works without it, importer returns a friendly "save as CSV" error if openpyxl is missing on the server). SW cache v75 → v76.
2026-07-25 Login ↔ Officer Directory linkage (Task #198). Session now carries rank + department + region + office_type (hq / regional / district) + reporting chain when the directory is enabled and the signed-in email has a row. CurrentUser schema extended with directory_matched · rank · department · office_type · is_hq · phone · office_location · reports_to_email; _user_row_to_current overlays these from officer_directory when OFFICER_DIRECTORY_ENABLED=1. New gates: require_hq_officer (Head Office only) and require_rank_at_least('director') (factory — walks the 9-rank ladder). can_initiate_hard_case now prefers the directory's rank field over users.role when available (more precise, 9 tiers vs 5). Header user-menu chip renders rank · department · Head Office | region · email when matched; falls back to the pre-linkage rendering (region · email) when off / unmatched. Fully backward compatible — every enrichment field defaults to None/False, so with the flag off nothing changes. Idempotent office_type column migration on officer_directory. SW cache v74 → v75.
2026-07-25 Officer Directory + DPA §36 pseudonymisation + audit TOCTOU + rate limits + Reg 29 how-to-respond (Task #197). In response to Amin's explicit ask to build officer tracking of CEO / Directors / Regional Directors / departments / ranks with all @epa.gov.gh emails traceable to the internal hierarchy — built and switched OFF by default until Authority demonstration. Officer Directory (built, off): new officer_directory table (email PK, full_name, department, rank, region, reports_to_email, phone, office_location, joined_at, is_active, notes) + services/officer_directory.py with 9-rank governance ladder (officer → senior_officer → principal_officer → assistant_director → deputy_director → director → regional_director → deputy_executive_director → ceo) + 16-region Ghana vocabulary + chain_of_command() walker. Admin API at /admin/officers* gated by require_named_admin (blocks OPEN_ACCESS_MODE + pilot-visitor identity from minting records even when flag flips). Feature flag OFFICER_DIRECTORY_ENABLED defaults to unset → every route returns HTTP 503 with the explanation "built into the tool but switched off for the pilot". /admin/officers/_meta is always reachable so admins can inspect the switch state. DPA §36 pseudonymisation (built, off): new audit_actor_directory table + optional HMAC-SHA256 pseudonymisation path in services/audit.py::log_event. When AUDIT_PSEUDONYMISE_ACTORS=1 + AUDIT_ACTOR_SALT=<random> are set, the audit chain stores act_<hash> instead of the clear email; the pseudonym→email mapping lives in the deletable directory table. A §36 erasure request drops the mapping — chain integrity preserved (hashes still verify), officer becomes cryptographically unlinkable. Off by default → behaviour unchanged (backward compatible). Audit TOCTOU fix: log_event now takes a per-case asyncio.Lock around the read-hash → compute-hash → INSERT path. Fixes the race where two concurrent writes on the same case would both fetch the same prev_hash and produce a broken chain that verify_chain would flag as tampered. Rate limits (SecAudit HIGH): new shared services/rate_limit.py primitive extracted from the existing screen limiter. /cases/stats gated at 120 IP-calls / 10 min; /tiles/sentinel-* gated at 600 tiles / IP / 10 min (Leaflet pan/zoom = ~40 tiles/view, so a human user is nowhere near the cap but a scripted scraper is instantly throttled). Reg 29 letter how-to-respond section: decision_letter.py now emits a numbered action checklist tailored to the decision — refused case gets the exception-evidence path + 21-day representations + appeal steps; requires_eia gets the consultant + Reg 28(1)(c) 60-day clock; requires_registration gets the PER + Reg 28(1)(b) 25-day clock; no_permit_required + insufficient_information get short guidance blocks. Assigned-officer contact block: letter now names the assigned officer with an enrichment hook that pulls phone + department + office_location when the Officer Directory is enabled. Security-review carry-forwards from prior Wave (still live): require_named_user on POST /cases + GET decision-letter + PDF; require_named_admin on GET /auth/users + /admin/officers*; block_open_access_state_transition on all case state-transitions; _xe() XML-escape on reportlab Paragraph interpolations; escHtml() on frontend case-detail interpolations; CORS allow_headers tightened from ["*"] to explicit list; response-side security headers (CSP + X-Frame-Options=DENY + X-Content-Type-Options + HSTS + Referrer-Policy); PNDCL 159 replaced with Ghana Maritime Authority Act 630 (2002) as the primary coastal-erosion consent instrument; Act 522 §12 → §13 for GWCL + ICOUR abstraction gate; reconsideration time-lock silent-bypass promoted to hard-error on unparseable timestamps.
2026-07-18 Close 7 pending tasks — 2 shipped, 5 closed with rationale (Task #195). SHIPPED: (1) Task #115 Site Intelligence Brief — one-glance officer triage panel at the top of every case-detail view. Aggregates verdict + indicator risk bar (red/amber/green ratio) + clock state (running / paused / overdue) + refuse-driving indicator list + Impact Scale advisory + Presidential-lease-override caveat when the state-vested override fires. Highest daily-use value; officer sees "here's what matters" in under 5 seconds. (2) Task #112 Recent-change confidence classifier — new change_confidence field on the /screen response + SIB display line, classifies each site as HIGH / MEDIUM / LOW based on which dynamic-ground indicators fired RED. HIGH: dam_spillage, recent_flood_event, galamsey, urban_drainage, regsec_high_risk, cultural_heritage (ground here changes materially year-on-year — site-verify before relying on desk data). MEDIUM: flood, wetland, river, coastal_erosion (seasonal variation — confirm which season desk data was gathered). LOW: only static indicators RED (soil, seismic, slope, road-corridor, HT-electricity, government-institutional-lands — desk data likely still accurate). Scoped honestly: uses ONLY the tool's existing indicators — no fake satellite-change score. CLOSED WITH RATIONALE: (3) Task #107 JRC CEMS_GLOFAS — retired. GLOFAS assets are gated on the EE noncommercial-tier under Google's July 2025 access-review policy; the Authority's own EE account may re-enable this on adoption. Documented as an Authority-side migration item. (4) Task #110 Sentinel-1 SAR change-monitoring layer — deferred; requires a scoped design pass on the change-detection algorithm (SAR-diff vs coherence-diff vs deep-learning classifier), out of scope for a punch-list close. Marked as a research spike for the next sprint. (5) Task #111 Esri World Imagery Wayback time-slider — deferred; Esri's Wayback API is rate-limited per IP + tokenised; needs an Esri Developer commercial licence to run at Authority scale. Documented as an Authority-side procurement item. (6) Task #113 Google Open Buildings + ESA WorldCover overlays — deferred; requires new tile-serving endpoints in the separate ghanascreen repo (this repo only proxies), out of scope for this session. Cross-repo work item. (7) Task #114 VIIRS night-lights + FIRMS active fires — same as #113 (ghanascreen-side tile endpoints), deferred as cross-repo work. SW cache v72 → v73.
2026-07-18 CEO + Head of Field Operations dual-hat review — Waves 1 + 2 shipped (commits 0c93493, 8f943a3). Every code-fixable item raised in the two-hat review, applied end-to-end. CEO concerns addressed: (1) Public Register now enforces a 7-day comms/legal cooling-off window before conditional-consent or rejection outcomes appear on the journalist-scraped JSON/CSV feed — the SHA-256 audit chain still records the sign-off moment as truth and RTI Act 989 requests are satisfied from t=0. (2) Presidential-lease-override caveat added to state-vested-land refusals (spatial_overrides.py::government_institutional_lands.red.presidential_lease_caveat). Officer must cross-check with Legal for a live Executive Instrument (e.g. E.I. 144 of 2022 for Achimota Forest) before communicating a refusal to a proponent who may hold a valid Presidential lease. (3) Softer refusal-language: PDF banner "RECOMMENDED VERDICT: REFUSE" → "SCREENING INDICATORS SUGGEST REFUSAL IS LIKELY"; project-narrative opening reworded to decision-support voice. (4) Hard-case 5-year sunset flagged PENDING BOARD APPROVALstatutory_durations.hard_case_sunset now carries an explicit note that the sunset is a proposed tool policy, not statutory, and must not be communicated to a proponent as a binding legal deadline until the Board approves it (and ideally causes it to be gazetted as a directive under Act 1124 §43). (5) Draft CEO press statement + 10-question Q&A briefing at docs/CEO_PRESS_STATEMENT_DRAFT.md — ready for CEO + Comms review, intended for reactive issuance if the tool becomes public knowledge before formal adoption. Field-Ops concerns addressed: (1) L.I. 2504 Reg 28(2) clock suspension modelled end-to-end. New clock_paused_at / clock_paused_until / clock_paused_reason / clock_paused_by / clock_paused_days_total columns on cases (idempotent migration). _compute_clock respects pauses — elapsed freezes at pause moment; accumulated pause days subtract on resume. New POST /cases/{id}/clock/pause + /resume routes. Reason codes: public_hearing · applicant_preparation · trc_scheduling · cross_agency_consult · supervisor_override. Both actions chain to the audit log. Frontend clock-pause panel on every case-detail with reason picker (min 20-char note) + resume date picker. (2) Case-clone bypass detection tightened. Was: same lat/lon + same sector — false-positived in Tema / Suame Magazine / Adabraka. Now: same lat/lon PLUS (same proponent title OR same sub_type). Co-resident businesses no longer flagged as resubmissions. (3) Co-resident case lookup: GET /cases/{id}/coresident + frontend purple panel on case-detail lists other cases within 50m of the pinned coordinate. Solves industrial-park + multi-tenant lookup. (4) Hard-case prepared-by field in OpenReconInput — desk officer's identity is recorded in the audit chain alongside the RD/CEO who submitted, preventing "RD just clicked submit for me" laundering. Total-clock schema bumped 90 → 60 (gazetted L.I. 2504 Reg 28(1)(c)). SW cache v70 → v71. Deferred (Authority-side, cannot fix in code): infrastructure migration, named auth on, DPO citation review, historical-decisions corpus validation, Board approval of governance change, MoU with Resilicity.
2026-07-18 Legal citation audit — priority-fix sweep. Independent citation-verification pass (research agent + gazetted-text cross-check) confirmed several inaccuracies and applied corrections. CONFIRMED WRONG → FIXED: (1) Public Lands Act, 1962 (Act 125)State Lands Act, 1962 (Act 125) — the gazetted short title of Act 125 is State Lands Act, not Public Lands Act (Public Lands (Leasehold) Act 1962 is a different statute, Act 126). ~28 occurrences fixed across spatial_overrides.py, reconsiderations.py, government_institutional_lands.py, build_government_institutional_lands.py, ghana_government_institutional_lands.geojson, METHODOLOGY.md, USER_MANUAL.md. (2) Environmental Protection Authority Act, 2025 (Act 1124)Environmental Protection Act, 2025 (Act 1124) — the Act creates the Authority; the Act itself is the Environmental Protection Act. Fixed in decision_letter.py, statutory_durations.py, methodology.md. Short-form EPA Act 1124 (2025) retained where it appears (established convention). (3) Maritime Zones (Delimitation) Act, 2009 (Act 791)Maritime Zones (Delimitation) Law, 1986 (PNDCL 159) — Ghana Act 791 (2009) is the Ghana Revenue Authority Act, NOT the Maritime Zones Act. Ghana's maritime-jurisdiction statute is PNDCL 159 (1986) defining 12 nm territorial sea + 200 nm EEZ + continental shelf. Fixed in spatial_overrides.py (coastal-erosion citation) + METHODOLOGY.md table. (4) Act 522 §12 (functions of the Commission) mis-attribution — §12 actually vests water resources in the President, not WRC functions. The tool now cites the WRC Buffer Zone Policy 2014 under Act 522 §35(f) (regulation-making power) with §13 (prohibition of use of water without authority) as the water-use gate. (5) Act 522 §13(2)(c) — reserved zones in floodplains reframed to Act 522 §13 — prohibition of use of water without authority (sub-clause tagged pending gazette confirmation); the flood-zone mapping mandate correctly rests with Act 1085 §3(c) (also tagged pending confirmation). (6) Minerals and Mining Act 703 §18 (mis-attributed as "forest-reserve mining prohibition") reframed — §18 concerns compensation/permits ancillary to mineral rights; forest-reserve prohibition is preserved as an Act 703 clause with the specific section pending DPO confirmation. Act 703 §82 (mis-attributed as "coastal sand-mining prohibition") reframed to Part V (§§81-99) small-scale mining licensing regime with Beach Sand Mining Regulations 2013 (L.I. 2182) cited alongside for coastal sand-winning specifics. (7) Lands Act 2020 (Act 1036) §§17-24 reframed to Act 1036 [state-vested provisions pending gazette section confirmation] — §§17-24 in Act 1036 span customary/allodial interests; state-vested provisions sit later (around §§235-244) but the exact range needs gazette DPO confirmation before it can be quoted. VERIFIED CORRECT (no change needed): Act 46 (Volta River Development), Act 481 (OASL), Act 522 §35 (WRC regulation-making), Act 571 §17 (Forestry Commission — the tool correctly identifies this as Forestry Commission Act, not as an EPA statute), Act 588 (GAEC operations), Act 691 (NPA downstream) + Act 821 (Petroleum Commission upstream) — both current, Act 740 (Bui Power Authority), Act 843 (Data Protection), Act 895 (Nuclear Regulatory Authority), Act 989 (RTI), Act 992 (Companies), Act 1036 (Land Act — title, not sections), Act 1080 (Fees and Charges — all fee-schedule rows), Act 1085 (Ghana Hydrological Authority — headline citation), Act 1115 (Wildlife Resources Management), Act 1124 (Environmental Protection — the Act), Constitution Art 258 (Lands Commission), L.I. 542 (1967) + L.I. 1737 (2004) (HT ROW — already correct years in tool). NEEDS_VERIFICATION (kept as-is with pending-badge language where appropriate): every L.I. 2504 (2025) regulation cite (Reg 3(1)(b), 4, 5, 17, 28, 29, 30) — gazetted text not yet publicly indexed on brr.gov.gh or GhaLII; L.I. 2504 Reg 45(1) appeal-window; Act 1115 §§21-24 specifics; Act 1085 §3(c) sub-clause; specific ROW widths in L.I. 542 / L.I. 1737. These carry verified='needs_verification' or [pending gazette confirmation] annotations rather than being asserted as gazette-cited.
2026-07-18 5-hat thorough review + 45-room-hotel honesty fix (commit 2bd72d6, sw v70). Auditor + Practitioner + Engineer + Legal + Documentation review with critical fixes applied and live-verified. Reconsideration integrity: new require_named_user_for_recon gate in auth.py blocks OPEN_ACCESS_MODE and the pilot-visitor@ identity on every recon mutation — open (standard + hard-case), evidence upload, and all three sign-off tiers (RD / CEO-or-DED / CEO-personal). Legally-material state transitions cannot be exercised by a shared demo identity and forged into the SHA-256 audit chain. Verified live: POST /cases/*/reconsideration returns 403 with the OPEN_ACCESS explanation. 45-room-hotel honesty fix: verdict['scale_advisory'] was populated by impact_scale.downgrade_verdict_for_scale() but no consumer read it — silent regression risk. Both consumers now surface it: PDF §1 renders an amber _scale_advisory_callout above the reasons cards; frontend §1 buildIntegratedBody renders the equivalent inline block. Copy explains fee-band ≠ assessment tier + L.I. 1652 40-room baseline reminder; auto-downgrade REMAINS withdrawn (see §22). Dashboard sector filter: rebuilt as Act 1080 canonical optgroup + legacy optgroup so filter values match the 9 canonical sectors while pre-migration case rows remain filterable. Case-clone bypass detection: create_case scans ~50 m + same sector for prior refused / requires_eia / rejected / withdrawn cases and stamps two audit events (case_created with possible_prior_negatives, plus a separate case_clone_flag action) so the tamper-evident chain records whether a case is a potential resubmission. Non-fatal — advisory only, officer decides how to proceed. Also earlier this cycle: hardened evidence upload (25 MB cap, Path.name basename + regex sanitisation + resolve-into-dir verification, path-traversal-safe); dropped project_title from the public-register projection (PII, RTI Act 989 conservative anonymisation); refusal-timestamp lookup now filters on action LIKE '%refus%' OR action LIKE '%decision%' with fallback to case.created_at; sign-off outcome='approved' blocked unless all required_kinds uploaded (evidence-completeness gate); cross-region enforcement extended to BOTH regional_director and ceo_or_delegate DED tiers and fails closed when case_region or signer_region is null; open_reconsideration + add_evidence + submit_signoff all now call audit.log_event() with structured payload — hard-fail on error to preserve tamper-evidence. New methodology sections §21 (Sector Migration), §22 (Impact Scale), §23 (Statutory Durations) added and the Change Log renumbered to §24.
2026-07-02 Act 1080 Fee Estimate Engine + Reconsideration/Hard-Case Override pathway + Public Register. See §19 and §20 for the full specification. Act 1080 wiring: encoded the gazetted Ghana EPA Fees and Charges (653 rows across 9 sectors) at backend/data/act_1080_fee_schedule.json from Amin's authoritative source; built services/fees_engine.py with search + estimate, exposed at /fees (standalone Officer Fee Lookup, ungated) + JSON API. PDF §3 now runs an Act 1080 probe first — quotes gazette-authoritative fee when a case's sector + sub-type uniquely match a single row; falls back to the activity-classification engine's number + a /fees pointer when ambiguous. Never invents a fee. Reconsideration pathway: new schema (reconsiderations + reconsideration_evidence + reconsideration_signoffs); services/reconsiderations.py with Class-1-vs-Class-2 classifier that reads exception clauses directly from spatial_overrides._SPATIAL_OVERRIDES (no separate registry — spatial_overrides stays the single source of truth); evidence-kind parser matches exception-clause text against a 16-kind canonical taxonomy. Hard-case override: role-gated to Regional Directors + CEO only via auth.require_hard_case_initiator. Sign-off is Regional Director + CEO personally (no delegate on hard-cases); standard track allows the CEO's designated Deputy Executive Director with a cross-region check. 30-day time-lock; 5-year sunset on hard-case consents. Public Register: /register HTML + /api/register.{json,csv} — RTI Act 989 aligned; auto-publishes every hard-case at creation, standard-track cases on approval; anonymises private-citizen PII. Governance ladder roles added to users table: officer · regional_director · deputy_executive_director · ceo · admin. All commits on main (Fee engine 4e49ae0 + Reconsideration d6c9478). Live-verified 2026-07-02 on scoping.resilicity.com. Frontend button-wiring (Reconsider / Hard-Case buttons on case-detail with role-gated visibility) deferred to the next session — backend is complete.
2026-07-02 Environmental-Assessment readiness review sprint — three-agent parallel audit (regulatory citations · technical wire-integrity · deployment/security/docs) applied. Regulatory — corrected §-numbers on WRC Act 522 (§16 → §12 riparian, §18 → §13(2)(c) flood, with WRC Riparian Buffer Zone Policy 2014 issued under §35); fixed ICOUR statute (Companies Code 1963 Act 179 was repealed by Companies Act 2019 Act 992); fixed GIDA prefix (NRCD 85 → SMCD 85); GACL corrected from Act 749 to L.I. 1913 (2007) under Statutory Corporations (Conversion to Companies) Act 1993 Act 461; Public Health Act 2012 numbered (Act 851); METHODOLOGY §11 verdict-hierarchy table refreshed to match the post-Wave-5 legal-review two-tier logic (refused hard prohibitions vs requires_eia with certified-design exceptions). Technical — 20/20 wire-check pass verified (resolver + override + SCOPING_TOPIC + PDF label + frontend card all present for every indicator); orchestrator upstream_status key mismatch recent_flood_eventsrecent_flood_event fixed; two silent except Exception: pass blocks in IWB override-write path replaced with upstream_status records; institutional-lands catalogue extended 71 → 76 features (added Kumasi International + Tamale International + Takoradi shared civil-military airfield + Wa + Sunyani airports). Deployment/security/docsDATA_PROTECTION.md §8 corrected to match the actual implementation (passwordless magic-link URL tokens via secrets.token_hex(32), NOT OTP; two-layer per-email 5/hour + per-IP 20/hour rate limits, NOT a 15-min lockout) + v1.1 change-log row; USER_MANUAL.md §2 now leads with the pilot Open-Access banner; AI_CONTINUITY.md broken-path reference to backend/app/middleware/auth.py fixed → backend/app/services/auth.py; bump_indicator_count.py extended to catch hyphenated 19-indicator form + additional target files (ONBOARDING, COLLABORATOR_BRIEF, AGENTS, PORTABILITY, capitalised "Eighteen"); 19 additional substitutions swept across docs. SW cache v64 → v65. Live-verified via curl probes on GAEC Kwabenya, Achimota, Odaw catchment.
2026-07-02 Government / Institutional Lands indicator (20th) — screening for fraudulent land-sale hot-spots and ill-considered siting on state-vested land. In response to Amin's own product ask ("Please research into University farms and other similar government Lands to help people to know about such places in case someone sells or wants to sell it to them or a project is proposed on it, so they will be flagged"). New components: (a) frontend/data/ghana_government_institutional_lands.geojson — 71 hand-curated features across universities (24), CSIR research stations (12), COCOBOD/CRIG (3, incl. Bole 6,277 ha), MoFA farms + irrigation (6), military installations (8, public-knowledge only), prison service (4), teaching hospitals (6), and special statutory reservations (8) + the high-dispute additions Achimota Forest Reserve (E.I. 144 of 2022), GWCL Weija (~3,300 ha reservoir, supplies 80% of Accra), GWCL Owabi (Ramsar Site), GWCL Kpong, TDC Tema (63 km²). Each carries custodian, category, establishing_statute, tenure_class, dispute_note (where documented — SEVERE flag on CSIR-ARI Frafraha, UG Nungua/Borteyman, GAEC Kwabenya, Amrahia Dairy Farm, Weija/Owabi buffer, Aveyime Rice / Prairie Volta), proximity_buffer_m (default 200 m), polygon_fidelity, extent_confidence, and gazetted sources. (b) services/government_institutional_lands.py — resolver with Franklin PIP + edge-distance buffer per the shared _geo module. (c) Override engine spatial_overrides.py — new government_institutional_lands.red (verdict refused) + .amber (verdict requires_eia). RED cites Lands Act 2020 Act 1036 [state-vested provisions pending gazette section confirmation] + Public Lands Act 1962 Act 125 + Constitution Art 258 + OASL Act 1994 Act 481 + L.I. 2504 Reg 2(3) read with Reg 3(1)(d) + the custodian-specific establishing statute carried on the matched feature. Routes to custodian + Lands Commission (Public and Vested Land Management Division) + Attorney-General's Office + OASL as appropriate. (d) orchestrator.py — wired as check government_institutional_lands, added SCOPING_TOPIC entry (State-vested land chain-of-title verification), and added the key to _SENSITIVITY_RED_KEYS so RED promotes EIAfinder sensitive_area=True before the override escalates to refused. (e) scoping_pdf.py _INDICATOR_LABEL gains the row label "Government / institutional lands (state-vested)". (f) Frontend _CHECK_META gains the 20th indicator card + the map-overlay layer with a distinct dark-slate polygon fill and a custodian-aware popup that surfaces name + custodian + statute + tenure + dispute note. (g) bump_indicator_count.py sweep: 19 substitutions across CEO 1-pager, handout, walkthrough script, frontend HTML, manual, methodology page, README, USER_MANUAL.
2026-06-23 Cultural Heritage indicator (19th) + coastal/urban lagoon extension (Tier 1B). Closes the gap exposed by an Adabraka (Korle Lagoon, ~1 km) and Cape Coast UCC-ridge (Fosu Lagoon ~1.4 km, Cape Coast Castle UNESCO WHS ~4 km) screening pair on 2026-06-23, where every indicator returned GREEN despite both pins sitting on or near nationally significant heritage and lagoon ecosystems. (a) New ghana_cultural_heritage.geojson — 35 hand-curated point features covering 16 UNESCO WHS Forts and Castles components (1979 inscription) including Cape Coast Castle, Elmina Castle, Fort St. Jago, Fort Vredenburgh, Fort William Anomabu, Fort Amsterdam, Fort Patience, Fort Good Hope, Fort San Sebastian, Fort Metal Cross, Fort St. Anthony, Fort Apollonia, Christiansborg Castle, James Fort, Ussher Fort, Fort Prinzenstein; 10 Asante Traditional Buildings WHS components (1980 inscription); 9 GMMB-gazetted national monuments (Larabanga Mosque, Du Bois Centre, Nkrumah Mausoleum, Manhyia Palace, National Cultural Centre Kumasi, Salaga Slave Market, Yendi Gbewaa Palace, Nalerigu Defensive Wall, Assin Manso). Each feature carries cordon_m + advisory_buffer_m + custodian + statute_chain. (b) services/cultural_heritage.py — nearest-neighbour resolver; RED inside cordon, AMBER inside advisory buffer, GREEN beyond; detail string names the nearest site + distance + designation + custodian so officers can verify negative results. (c) Override engine spatial_overrides.py — added cultural_heritage.red (verdict refused, NLCD 387 + 1972 Convention + L.I. 2504 + Constitution Art 39(2)) and cultural_heritage.amber (verdict requires_eia, CHIA scoping topic). Citations dedup against higher-priority overrides. (d) PDF + frontend wired to render cultural_heritage indicator card (icon: stadium/heritage building). (e) Tier 1B lagoon extension: 8 new coastal/urban lagoons added to ghana_inland_water_bodies.geojson (Korle, Kpeshie/La, Chemu, Fosu, Benya, Butuah, Whin Estuary, Volta Estuary at Ada Foah) — each tagged with WRC riparian buffer (100 m) + proximity_buffer_m (400–600 m awareness ring), traditional custodian, historical biodiversity (Crocodylus suchus, Varanus niloticus where documented). inland_water_bodies.py resolver gains distance-to-polygon proximity detection: Pass 1 = strict containment (existing RED behaviour preserved), Pass 2 = buffered proximity (new AMBER inland_water_body_proximity override surfaces requires_eia + WRC §13 buffer-clearance scoping topic). (f) Bumped indicator count 18 → 19 via bump_indicator_count.py sweep (17 substitutions across CEO 1-pager, handout, walkthrough script, frontend HTML, manual, methodology page, README, USER_MANUAL). SW v55 → v56. Total IWB catalogue: 20 features. Total cultural_heritage features: 35.
2026-06-09 Inland Water Body Determination engine (Tier 1, 12 features). The previous in-water short-circuit returned a binary "in water → refused" banner that was correct for the open Gulf of Guinea but lost regulatory substance on Ghana's designated inland water bodies. A real Lake Bosomtwe screening (2026-06-09) returned a generic verdict without flagging the UNESCO MAB Biosphere Reserve, the sacred Ashanti custodianship, the Bosomtwe Range Forest Reserve, or the endemic Tilapia busumana / Hemichromis frempongi fishery. This release replaces that short-circuit with a structured determination. New components: (a) frontend/data/ghana_inland_water_bodies.geojson — 12 hand-curated polygons covering Lake Bosomtwe (UNESCO MAB Biosphere Reserve 2016 + sacred + Forest Reserve + endemic fishery), Lake Volta (Akosombo + Kpong reservoir, VRA Act 1961, aquaculture-dominant), Bui reservoir (BPA Act 740 + Bui National Park boundary), Weija reservoir (GWCL drinking-water source, 200 m strict buffer), Tono and Vea reservoirs (ICOUR irrigation), Owabi reservoir (Ramsar + drinking water + Wildlife Sanctuary), and the five Greater-Accra / Central / Volta Ramsar lagoons (Songor, Keta, Densu Delta, Sakumo, Muni-Pomadze). Each feature carries: MAB status + reserve name + designated year, Ramsar site ID + designated year, sacred status + traditional custodian + taboos, adjacent Forest Reserve, regulating authority + statute, fishery status + endemic species, WRC riparian buffer width, ordered primary_authorities list, verdict_categories map A → E, and a 4-6 entry gazetting_chain. Polygons are screening-grade approximations (Bosomtwe is a true 32-vertex circle on the crater; reservoirs are centroid-radius envelopes at conservative radii; Ramsar lagoons are simplified ellipses at gazetted centroid + known length/width) — replacing each with the official Ramsar Information Sheet polygon or MAB Biosphere zoning polygon is the documented upgrade path on adoption. (b) services/inland_water_bodies.py — ray-cast point-in-polygon resolver, project-category classifier (A: water-dependent low-impact → research, monitoring, artisanal fishery, navigation; B: water-dependent moderate-impact → small jetty, ferry, MAB-compatible aquaculture; C: water-dependent high-impact → hydropower, large cage aquaculture, dredging; D: water-incidental → resort, hotel, residential, factory; E: prohibited absolutely → petroleum, hazardous waste, mining), per-feature verdict lookup, and a stakeholder/permit matrix generator that pulls from a 34-entry _AUTHORITY_DECISIONS table (each authority carries decides + statute + applies_to category filter, so a resort gets a 7-row Bosomtwe matrix while an aquaculture project gets the 9-row version including Fisheries Commission + Wildlife Division). (c) schemas/screening.pyScreenInput.water_dependent: Optional[bool] lets the proponent declare water-dependence; ScreenOutput.inland_water_body: dict | None carries the structured determination. (d) Orchestrator wires the resolver after the SafeGround spatial profile; when a hit fires it escalates the verdict via the existing _max_verdict channel so the override-engine contract stays consistent. (e) Frontend: intake form gains a water-dependent checkbox under the project-details panel with explanatory copy ("Tick this if the project NEEDS the water body to exist"). Report renderer ships a new buildInlandWaterBodyCardHtml that renders the verdict badge, narrative (with bold statute markers expanded), designation stack as a bulleted list, project-category panel with typical examples (rendered as inline pills) and an "inferred vs declared" disclosure, the stakeholder/permit matrix as a 4-column table (#, Authority, Statute, What they decide), and a collapsible gazetting chain. Card colour-codes by verdict — refused is red, conditional consideration is amber, conditional special-pathway is the conditional amber. SW cache bumped v44 → v45. Worked Bosomtwe verification: centroid pin at 6.5000 N, 1.4133 W with tourism → resort returns matched Lake Bosomtwe, verdict refused, 8-authority stakeholder matrix (Bekwaihene under Asantehene · Ghana MAB National Committee · WRC · the Authority · Forestry Commission · Bosomtwe District Assembly · Ghana Tourism Authority · NADMO), 4-entry designation stack (UNESCO MAB + sacred + Forest Reserve + endemic fishery), 6-statute gazetting chain. Same pin with water_dependent=true + sector=agriculture + sub_type=aquaculture returns category B "Water-dependent, moderate-impact" with verdict conditional_consideration_special_pathway and the 9-authority matrix that now includes Fisheries Commission. Tier-2 / -3 expansion path: sacred ponds (Tadane, Sonu, Bomfobiri sanctuary lakes); additional coastal lagoons (Nungua, Korle, Fosu, Amansuri); project-type gating on the WRC riparian buffer for the major rivers (Pra, Ankobra, Tano, Densu, Birim, Ofin). Honest disclosure: traditional-council attributions follow published proceedings of the Asantehene's, Bekwaihene's, and Effutu Traditional Councils; replacing them with direct council secretariat confirmations on adoption is a documented step.
2026-06-02 Dam-spillage screening indicator (#15). Added a 15th spatial indicator dedicated to dam-controlled inundation envelopes — the gap exposed by the 2023 Akosombo spillage (38,624 displaced across 32 communities). New components: (a) ghana_dam_spillage_envelopes.geojson carries six envelopes — Akosombo + Kpong (Lower Volta corridor, 35-vertex polygon spanning the 2023 controlled-spillage extent from the dam to the Volta estuary, widths 1.5-4.5 km), Weija Densu (Ga South Municipal floodplain to Densu Delta), Bui Black Volta (Bui dam to Buipe / White Volta confluence), Bagre cross-border (White Volta Burkina Faso entry to Buipe), Tono (Kassena-Nankana / Navrongo plains), Vea (Bolgatanga lowlands). Each polygon tagged with operator, statutory Act, design basis, documented events, communities affected, districts affected, source citation, and screening-grade quality disclosure. (b) services/dam_spillage.py runs point-in-polygon — red inside envelope, amber within 500 m, green beyond. Returns the full statutory citation chain when red. (c) Wired into the Spatial Statutory Override Engine as dam_spillage.red → verdict refused, citing Volta River Development Act 1961 (Act 46), Water Resources Commission Act 1996 (Act 522) §13, Environmental Assessment Regulations 2025 (L.I. 2504) Reg 3(1)(b), Ghana Hydrological Authority Act, 2022 (Act 1085) §3(c), Ghana Building Code 2018 Part 5, Lands Act 2020 (Act 1036) §3, Bui Power Authority Act 2007 (Act 740). Exception clause allows flood-resilient public infrastructure (elevated walkways, evacuation centres) under a separate consent track with the operator + Ghana Hydrological Authority. (d) Added to sensitivity_red_keys so red here promotes EIAfinder sensitive_area=True before the override escalates to refused. (e) Frontend: 15th _CHECK_META entry; toggleable dam_spillage_envelopes overlay coloured per operator (Akosombo cyan, Weija orange, Bui yellow, Bagre red, Tono green, Vea dark green); SW cache bumped v29 → v30. Sources: VRA controlled-spillage update Sept-Oct 2023, NADMO displacement bulletins, Imani Africa 2024 critique, Akosombo Spillage Committee Report 2025, PMC peer-reviewed Densu floodplain study (PMC11019054), GWCL spillage notices 2018-2024, Bui Power Authority + Savannah RCC 2022/2023 reports, SONABEL annual Bagre release notifications, ICOUR/SIGA profiles, Ghana DREF MDRGH018 Upper East flood report, FloodList Oct 2019. Honest disclosure: envelopes are digitised from documented spillage extents + operator-published protocols, not from a controlled topographic-hydraulic model; precise per-property determination still requires the operator's design-spillage envelope + a site-specific topographic survey.
2026-06-02 Pre-EPA-handoff correctness + migration-readiness sprint. Fourteen items shipped: (1) Polygon Phase 1b — sample-grid worst-case aggregation across up to 25 polygon points per indicator (centroid + 8 boundary + interior grid for parcels ≥ 5 ha); response now carries polygon_aggregation provenance. (2) Galamsey district prevalence expanded from 91 → 128 districts (+37 documented activity districts cited from IMCIM, Operation Halt II/III, CSIR-WRI water-quality reports, Minamata ASGM-NAP 2020, Owusu-Nimo 2018; coastal sand-mining districts capped at 0.5 under M&MA Act 703 §82). (3) Road corridor check made CLASS-AWARE per Ghana Highway Authority Act 540 + Streets and Roads Act 1971 (NLCD 41) — per-segment ROW (motorway 45 m / trunk 30 m / primary 22.5 m / secondary 15 m / tertiary 9 m / urban collector 12.5 m / urban local 6 m); detail string names the road, its class, and the ROW threshold driving the verdict. (4) 330 kV HV grid dataset expanded with 5 recently-commissioned GRIDCo corridors (Anwomaso–Kintampo 2023; Kintampo–Tamale–Bolgatanga 2024-25; Bui–Kumasi 2020; Aboadze–Prestea 2022; Volta–Tema 2023) digitised from NIPMP 2024 — flagged screening-grade until GRIDCo route plans land. (5) /screen async refactor — shared process-wide httpx.AsyncClient pool replaces per-request client (50-150 ms TLS-handshake savings per call); shutdown_upstream_client() hooked into FastAPI shutdown. (6) Systemd hardening — three new hardened unit files (epa-scoping-platform, ghanascreen, eiafinder) running as dedicated epascoping user with NoNewPrivileges, ProtectSystem=strict, MemoryDenyWriteExecute, RestrictAddressFamilies, SystemCallFilter; deploy/harden-systemd.sh migrates a root-running install. (7) DATA_PROTECTION.md per Ghana DPA Act 843 — controllership, lawful basis, retention, data-subject rights, cross-border transfers, breach notification; controllership transfers to the Authority on adoption. (8) PDF refusal banner softened from "REFUSED — PERMIT NOT ISSUED" to "RECOMMENDED VERDICT: REFUSE" + decision-support sub-line. (9) Configuration separation — hardcoded /opt/ paths and resilicity.com URLs replaced by env-var defaults with portable fallback chain. (10) Docker-compose stack + Dockerfile + nginx.docker.conf — alternative deployment path for the Authority. (11) DEPLOYMENT-RUNBOOK.md — Ubuntu 22.04+ step-by-step from bare VM to live HTTPS. (12) Data-handover scripts — restore-cases-db.sh, export-audit-trail.sh (chain-integrity verifying), reset-demo-data.sh (preserves admin + ruleset, wipes test cases). (13) MIGRATION-RUNBOOK.md — phased EPA-side preparation, data transfer, DNS cutover, Resilicity decommission, rollback procedure, sign-off matrix. (14) ARCHITECTURE.md — one-pager system diagram + dependency list + scaling notes for the Authority's architects.
2026-05-31 Demo-readiness sprint: SQL-injection close in precedent finder; officer-scope gate on all single-case routes; CORS preflight tightened; anonymous /screen rate-limited (30/IP/10 min); per-IP cap on /auth/request; Reg 30 appeal paragraph + diagonal DRAFT watermark added to Reg 29 decision letter; refused + requires_sea decision branches mapped end-to-end.
2026-05-31 Indicator-portfolio upgrades: (1) Slope preferred raster swapped from SRTM (2000, ±9 m) to Copernicus DEM GLO-30 (2019, ±4 m) — halves vertical error per Simard 2024 + Tandfonline 2024 benchmarks; affects #6 slope, #1 flood terrain sub-indicator, and #11 groundwater HAND. (2) River check preferred dataset swapped from OSM-name-filtered to HydroSHEDS HydroRIVERS v1.0 (Lehner & Grill 2013; Linke et al. 2019) — solves §10.3 named-coverage gap. (3) Flood composite gained a 5th sub-indicator: JRC Global Flood Hazard Maps v2.1 (Dottori et al.) querying the 10 / 100 / 500-year return-period envelopes via Earth Engine — adds quantified return-period reporting that L.I. 2504 scoping calls for. (4) Wetland check gained a Ramsar Sites Information Service overlay — Ghana's 6 designated Ramsar Sites (Owabi, Densu Delta, Sakumo, Songor, Muni-Pomadze, Keta Lagoon Complex) pre-empt OSM/JRC with red status and a Convention Article 3.2 citation.
2026-05-22 Galamsey multi-layer methodology activated (hotspot + river + district + Sentinel-2 placeholder); confidence cap at 0.7 without Tier-2; district-name normalisation.
2026-05-22 Audit log schema v1.1 — data lineage embedded in every entry.
2026-05-22 Tier-2 plausibility benchmark engine activated (14 sector-process pairs).
2026-05-22 Compliance schedule auto-generation on case sign-off (L.I. 2504 Reg 30).
2026-05-22 Hash-chained audit trail.
2026-05-22 HT electricity ROW screening (L.I. 1737).
2026-05-22 Officer case-management workflow with 25/90-day clocks.
2026-05-22 Reconciliation engine for proponent scoping reports.
2026-05-22 Tool deployed at scoping.resilicity.com.