Skip to content

feat(wells): classification (Approach B) + fix 413 on well hydration - #29

Open
prayaslashkari wants to merge 10 commits into
developmentfrom
feat/wells-classification
Open

feat(wells): classification (Approach B) + fix 413 on well hydration#29
prayaslashkari wants to merge 10 commits into
developmentfrom
feat/wells-classification

Conversation

@prayaslashkari

@prayaslashkari prayaslashkari commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds well classification (Approach B) to the Well filter and fixes a 413 Content Too Large error that blocked statewide well queries. See issue #25 for the classification design.

Note: this branch is stacked on the material-grouping and aquifer commits, so the diff also includes feat(material) and feat(aquifers) until those land. The two commits below are what's new here.

1. Well classification (Approach B) — 7bdc4ba

Replaces the hardcoded two-option "Well Source" dropdown (Illinois/Maine) with a live, grouped classification fetched from hydrologykg, each state by its own native field:

  • Illinois by il_isgs:wellPurpose (active/plugged twins collapsed into one option).
  • Maine by both me_mgs:ofWellType (construction) and me_mgs:hasUse (use).

Behavior:

  • No state chosen → all groups shown under section headers (Illinois · Purpose, Maine · Type, Maine · Use); picking a category self-scopes to its state.
  • A chosen region state collapses the list to that state's groups.
  • Selection semantics: OR within a field, AND across Maine type + use, OR (UNION) across states.

Categories are encoded as tokens (field||iri1 iri2 …) so the query builder stays stateless. Reuses the grouped FlatSelect and useMaterialTypes discovery pattern.

Files: constants/wellClassifications.ts (new), engine/templates/wells.ts (new, buildWellCategoryFilter), 3 discovery queries in engine/templates/regions.ts, hooks/useDiscoveryQueries.ts (useWellClassifications), components/QueryEditor/WellFilters.tsx, types/query.ts, plus fusedQueries.ts/hydrate.ts/prebuiltQueries.ts/EntityBlock.tsx wiring.

2. Fix 413 on well hydration — ebc6dda

Statewide well queries hydrated by inlining ~20k+ IRIs into a VALUES ?well { … } clause → 1.5 MB POST body → hydrologykg returns 413 (surfacing as a CORS error, since the 413 response omits Access-Control-Allow-Origin). Measured FRINK limit: ≤1 MB → 200, ≥2 MB → 413.

Fix mirrors the existing samples solution: new buildFusedWellQuery re-derives the well set inside the single federated query (reusing buildFusedWhereBody, which already applies the region + well-category filters) and projects geometry + attributes directly. Wells route through it on the federation endpoint; dead buildWellsByIri removed.

Verified live (real generated query): request body 2.9 KB (was 1.5 MB) → HTTP 200, 751 Maine wells near landfill/DoD sites with geometry + attributes. 413 is now impossible by construction.

Verification

  • tsc --noEmit, npm run build, engine lint: clean.
  • Discovery queries + filter semantics live-tested (OR/AND/UNION; Illinois plugged-collapse 33→21 options).
  • Fused well query live-tested end to end.

Known follow-ups (filed separately)

image

Bucket each material type into one of the four direct coso:MaterialSample
subclasses (Biota / Solid Material / Water / Air) resolved in SPARQL via a
priority VALUES + MIN(?bucketPrio); unmatched types fall to 'Other'.
FlatSelect renders sticky section headers, flat fallback when no groups.
Aquifers are now a first-class entity in the analysis-question builder and a
toggleable map layer, for Maine and Illinois (8,441 aquifers; ME 4,972, IL 3,469).

- Filter: aquifers join the fused S2-cell query engine as an entity Type (the
  spatial container you relate samples/wells/facilities to), with a
  Sand & gravel / Bedrock type filter. Endpoint routing, hydrate, and
  natural-language phrasing wired through.
- Overlay: real aquifer boundaries as a static, toggleable layer. Geometry is
  precomputed by scripts/precompute_aquifers.py from each state's authoritative
  ArcGIS source (Maine Geological Survey, Illinois State Geological Survey) and
  shipped as a content-hashed Vite asset so it is cache-safe. Colored by kind
  with a WCAG 3:1 stroke; popup shows type and yield.
- Docs: gwml2 namespace + counts in SCHEMA.md, verified queries in
  docs/aquifer-queries.md, aquifer colors added to the contrast audit.

Verified live against the FRINK federation/hydrologykg endpoints and both
ArcGIS services.
…h B)

Replace the hardcoded ISGS/MGS source dropdown with a live, grouped
classification fetched from hydrologykg: Illinois by wellPurpose, Maine by
both ofWellType and hasUse. Categories are encoded as tokens so the query
builder stays stateless; selection is OR within a field, AND across Maine
type+use, OR (UNION) across states. Illinois active/plugged twins collapse
into one option. No state chosen shows all groups; picking one self-scopes.
Statewide well queries hydrated by inlining ~20k+ IRIs into a VALUES clause,
producing a ~1.5MB POST body that hydrologykg rejects with 413 (surfacing as a
CORS error since the error response omits ACAO). Mirror the samples fix: add
buildFusedWellQuery, which re-derives the well set inside the single federated
query (reusing buildFusedWhereBody, which already applies region + well-category
filters) and projects geometry + attributes directly. Route wells through it in
hydrateStep on the federation endpoint; drop the now-dead buildWellsByIri.
Request body is now ~3KB regardless of result size.
@railway-app

railway-app Bot commented Aug 20, 2026

Copy link
Copy Markdown

This PR was not deployed automatically as @prayaslashkari does not have access to the Railway project.

In order to get automatic PR deploys, please add @prayaslashkari to your workspace on Railway.

@prayaslashkari

Copy link
Copy Markdown
Collaborator Author

FRINK retired https://frink.apps.renci.org/<kg>/sparql; all five knowledge
graphs now return 503 there and are served from https://apps.okn.us/<kg>/sparql
instead. Reported by David Kedrowski, who hit the same break in his notebooks.

Verified all five endpoints live on the new host (200, CORS *), and replayed
the real pipeline through planPipeline/executePipeline against them: 7 of 8
prebuilt queries succeed and all discovery queries return live data rather
than falling back to hardcoded constants.

The Indiana downstream prebuilt still fails, but with a QLever memory-limit
error ("Tried to allocate 819.2 MB, but only 743.3 MB were available"), not a
routing failure. Tracked separately.
fix(endpoints): move SPARQL endpoints from FRINK to apps.okn.us
The app deploys on Railway from main, but the repo still carried a Render
blueprint from the publish workflow and no mention of Railway anywhere. The
stale file was actively misleading about where production runs.

Removes render.yaml, documents the real deploy target in the README, and adds
the W35 changelog covering this and the FRINK endpoint migration.
chore: drop stale render.yaml, document Railway as the deploy target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant