Skip to content

Commit 7e45e0d

Browse files
committed
Document sampling features live-server lessons
1 parent aa06a1d commit 7e45e0d

3 files changed

Lines changed: 623 additions & 0 deletions

File tree

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# pygeoapi Sampling Features System-Filter Defect
2+
3+
**Document date:** June 4, 2026
4+
5+
**Purpose:** Record the remaining `pygeoapi/52North` defect observed after public `samplingFeatures` population was restored on the Oracle-hosted demo environment. This note is intentionally narrow. It documents the defect, the observed evidence, the likely query-path cause, and the acceptance target for a future code fix.
6+
7+
## Summary
8+
9+
The public `pygeoapi/52North` deployment now exposes populated top-level and item-level `samplingFeatures` data, but the nested system traversal path still fails:
10+
11+
- `GET /samplingFeatures` returns populated results
12+
- `GET /samplingFeatures/{id}` returns populated item results
13+
- `GET /systems/{id}/samplingFeatures` returns an empty collection for seeded systems that do have associated sampling features
14+
15+
This should be treated as a remaining query-path defect, not as a data-population gap.
16+
17+
## Observed evidence
18+
19+
As verified on June 4, 2026:
20+
21+
- top-level public collection was populated after repair and bulk indexing
22+
- individual item reads worked for newly indexed public sampling features
23+
- nested `systems/{id}/samplingFeatures` remained empty for known seeded systems
24+
- top-level filtering by `system=<id>` also returned empty results for those same seeded systems
25+
26+
These two failing paths strongly suggest that the nested traversal and the top-level `system` filter share the same broken filter logic.
27+
28+
## Why this is not a data-absence problem
29+
30+
The same deployment demonstrated all of the following at the same time:
31+
32+
- sampling-feature documents existed in Elasticsearch
33+
- the documents were readable through the public top-level collection
34+
- individual item reads worked through the public API
35+
- the seeded system identifiers were known and stable
36+
37+
That combination rules out the earlier "empty demo data" explanation for this specific route. The remaining issue is the query logic used to associate sampling features with their parent systems.
38+
39+
## Likely cause
40+
41+
The observed Elasticsearch mapping for the `sampling_features` index included:
42+
43+
- `system` as a `text` field
44+
- `system.keyword` as an exact-match `keyword` subfield
45+
46+
The server-side query path appears to filter against `system` rather than `system.keyword`.
47+
48+
That is a bad fit for exact system-ID matching because:
49+
50+
- the system IDs are hyphenated slugs
51+
- the `text` analyzer tokenizes those values
52+
- exact parent-system lookups should use the `keyword` subfield instead
53+
54+
The nested route behavior and the top-level `?system=` behavior both match this diagnosis.
55+
56+
## Probable fix direction
57+
58+
The future code fix should keep the existing multi-value filter shape but route the filter to the exact-match field.
59+
60+
In practical terms, the likely change is:
61+
62+
- keep a `terms`-style filter if the API layer passes `system` as a list
63+
- target `system.keyword` rather than `system`
64+
65+
This note intentionally does not prescribe a specific patch beyond that direction. The owning repo should implement and verify the fix in its own test suite and deployment process.
66+
67+
## Acceptance target for the fix
68+
69+
Treat the defect as fixed only when all of the following succeed for a seeded or otherwise known-associated system:
70+
71+
1. `GET /samplingFeatures?system=<system-id>` returns non-empty results.
72+
2. `GET /systems/{id}/samplingFeatures` returns non-empty results.
73+
3. Results from both paths are consistent for the same system.
74+
4. Top-level `GET /samplingFeatures` still works.
75+
5. Direct `GET /samplingFeatures/{id}` item reads still work.
76+
6. Paging still works on both the filtered top-level path and the nested path.
77+
78+
## Recommended follow-up
79+
80+
- Open or update a `csapi-pygeoapi` issue with this note as the evidence summary.
81+
- Add an automated regression test for both:
82+
- `GET /samplingFeatures?system=<id>`
83+
- `GET /systems/{id}/samplingFeatures`
84+
- Keep this defect separate from demo-data stewardship work. The demo population issue was remediated; this remaining issue is code-path behavior.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Public Sampling Features Seeding and Verification Runbook
2+
3+
**Document date:** June 4, 2026
4+
5+
**Purpose:** Provide a repeatable operational runbook for maintaining public `samplingFeatures` readiness across the Oracle-hosted CSAPI demo deployments. This runbook is based on the June 4, 2026 live remediation work and is intended to prevent future drift into empty, misleading, or partially readable public `samplingFeatures` surfaces.
6+
7+
## Scope
8+
9+
This runbook is for operational stewardship of public demo data. It is not a standards interpretation document and it is not a replacement for implementation-specific bug fixing.
10+
11+
Use it when a public deployment:
12+
13+
- exposes `samplingFeatures` routes but returns empty collections
14+
- accepts create operations without dependable readback
15+
- shows divergence between top-level, item-level, and nested traversal paths
16+
- needs a richer public demo surface for downstream integration testing
17+
18+
## Readiness target
19+
20+
Before a public deployment should be described as ready for positive `samplingFeatures` interoperability work, it should satisfy all of the following:
21+
22+
1. `GET /samplingFeatures` returns `200` and a non-empty collection.
23+
2. `GET /samplingFeatures/{id}` works for at least one public item.
24+
3. `GET /systems/{id}/samplingFeatures` works for at least one system that should have associated sampling features.
25+
4. At least one returned sampling feature includes:
26+
- geometry
27+
- `uid`
28+
- `name`
29+
- `featureType`
30+
5. Post-write verification is possible where create is supported.
31+
32+
## Seed-corpus pattern
33+
34+
Prefer a contextual seed corpus over anonymous generated points.
35+
36+
### Recommended seed families
37+
38+
The June 4, 2026 remediation used these ten families:
39+
40+
- desert weather
41+
- coastal buoy
42+
- river gauge
43+
- indoor thermometry
44+
- airport meteorology
45+
- estuary water quality
46+
- acoustic array
47+
- urban air monitoring
48+
- agricultural field monitoring
49+
- wildfire-edge monitoring
50+
51+
### Recommended seed properties
52+
53+
Each family should include:
54+
55+
- one stable seed system
56+
- 100 or more spatially distributed sampling features
57+
- deterministic UIDs
58+
- deterministic item numbering
59+
- realistic names and descriptions
60+
- stable `featureType`
61+
- stable `sampledFeature@link`
62+
63+
The goal is not random bulk volume. The goal is reusable, plausible, and inspectable public test data.
64+
65+
## Verification sequence
66+
67+
Run these checks in order.
68+
69+
### 1. Collection presence
70+
71+
Verify:
72+
73+
- top-level `GET /samplingFeatures`
74+
- collection count or feature length
75+
- paging with `limit`
76+
77+
This answers whether public data is present at all.
78+
79+
### 2. Item readback
80+
81+
Pick one known item ID from the public collection and verify:
82+
83+
- `GET /samplingFeatures/{id}`
84+
85+
This confirms that the collection is not exposing references to unreadable items.
86+
87+
### 3. Nested traversal
88+
89+
Pick one known parent system and verify:
90+
91+
- `GET /systems/{id}/samplingFeatures`
92+
93+
This must be checked separately. Do not assume that a working top-level collection implies a working nested traversal path.
94+
95+
### 4. Filtered top-level behavior
96+
97+
If the implementation supports filtering by parent system, verify:
98+
99+
- `GET /samplingFeatures?system=<id>`
100+
101+
This is particularly important because some stacks can expose working top-level collections while still breaking the parent-system filter path.
102+
103+
### 5. Create-readback verification
104+
105+
Where create is supported:
106+
107+
1. create a known sampling feature under a known system
108+
2. record the returned ID or `Location`
109+
3. verify direct item readback
110+
4. verify top-level collection visibility
111+
5. verify nested collection visibility
112+
113+
Do not treat the status code as sufficient evidence by itself.
114+
115+
## Write-path guardrails
116+
117+
The June 4, 2026 live work showed that write-path status codes can be misleading.
118+
119+
- A create may persist even when the server returns an error.
120+
- A create may return success while the read path still cannot expose the new resource correctly.
121+
122+
Because of that, every write-path check should be treated as a postcondition check, not a status-only check.
123+
124+
## Backing-store repair boundary
125+
126+
Some deployments may require backing-store repair rather than API-only remediation.
127+
128+
Examples of when that boundary has been crossed:
129+
130+
- public create returns success but readback remains broken
131+
- documents exist in the backing store but lack the representation branch expected by the API read path
132+
- top-level and item reads behave differently for the same resource family
133+
134+
When this happens:
135+
136+
- document the backing-store contract
137+
- repair documents in a controlled way
138+
- rerun the full readback sequence after repair
139+
140+
Do not treat backing-store repair as a substitute for fixing a genuine API query-path bug.
141+
142+
## Distinguish operational state from implementation defects
143+
144+
Keep these categories separate:
145+
146+
- **Operational/data-state issue:** route exists but is empty or thinly seeded
147+
- **Implementation defect:** route, filter, traversal, representation, or readback logic is wrong
148+
149+
The same deployment can have both at once. The runbook should not blur them together.
150+
151+
## Minimum reporting after a maintenance pass
152+
153+
After any seeding or repair pass, record:
154+
155+
- deployment URL
156+
- date and time
157+
- top-level collection count
158+
- item-read verification result
159+
- nested-traversal verification result
160+
- filtered top-level verification result, if applicable
161+
- whether create-readback was exercised
162+
- any remaining route-specific defects
163+
164+
## Recommended follow-up integration
165+
166+
- Add these checks to live public smoke-test workflows.
167+
- Keep the seed corpus versioned and idempotent.
168+
- Preserve stable batch identifiers so cleanup and refresh remain possible.
169+
- Re-run this checklist after deployment rebuilds, proxy changes, or data refreshes.

0 commit comments

Comments
 (0)