Skip to content

fix(bootstrap): two-step encoding for procedures and deployments + NWS canonical refactor#6

Merged
Sam-Bolling merged 4 commits into
mainfrom
fix/sml-content-type-and-shape
May 10, 2026
Merged

fix(bootstrap): two-step encoding for procedures and deployments + NWS canonical refactor#6
Sam-Bolling merged 4 commits into
mainfrom
fix/sml-content-type-and-shape

Conversation

@Sam-Bolling
Copy link
Copy Markdown

Fixes #5.

What this PR delivers (E.1 vertical slice)

Layer Change
publishers/bootstrap_helpers.py ensure_procedure and ensure_deployment now mirror ensure_system: POST geo+json stub → optional PUT application/sml+json body. force_sml extended to both. New _warn_if_sml_fields_in_stub guardrail (lenient warn / strict RuntimeError via OS4CSAPI_STRICT_BOOTSTRAP=1).
publishers/nws/bootstrap_nws.py Canonical refactor: PROCEDURE_BODY split into _procedure_stub + _procedure_sml; _deploy_root / _deploy_group documentation arrays moved into matching _deploy_root_sml / _deploy_group_sml companions; force_sml plumbed into all three create calls.
tests/test_bootstrap_roundtrip.py 4 offline guardrail tests + 2 network-gated SensorML roundtrip tests for procedure and deployment.
docs/research/Silent_SensorML_Field_Loss_Engineering_Report_2026-05-06.md 11-section engineering report.

Verification

  • pytest tests/test_bootstrap_roundtrip.py against https://129-80-248-53.sslip.io/csapi-go-upstream/6 passed. Marker keywords and identifiers round-trip end-to-end on both procedures and deployments.
  • Pre-fix DB audit (2026-04-29): procedures 0/12, deployments 0/62, systems 34/38 SensorML preservation.
  • OS4CSAPI_STRICT_BOOTSTRAP=1 strict-mode smoke: NWS stubs are clean, SML bodies have expected SensorML keys.

Out of scope — tracked as E.2 follow-up

The other 9 publishers (aviation_wx, coops, iss, ndbc, opensky, usgs_eq, usgs_nims, usgs_water) still use the single-POST pattern for procedures and deployments. They are unblocked by this PR — helpers are backward-compatible: omit sml_body and behavior is unchanged — and will be refactored in a follow-up batch using NWS as the reference template.

Recovery for already-deployed environments

After this lands:

python -m publishers.nws.bootstrap_nws --force-sml

will PUT the (now correct) SensorML bodies against existing procedure / deployment records without rebuilding identity, links, or datastreams.

References

ensure_procedure and ensure_deployment now mirror ensure_system: POST a
geo+json stub (uid/name/description/geometry/featureType/validTime),
then optionally PUT a SensorML body with Content-Type:
application/sml+json against /resource/{id}.

Also adds _warn_if_sml_fields_in_stub: a closed-set guardrail that warns
(or raises, when OS4CSAPI_STRICT_BOOTSTRAP=1) if a stub body still
carries SensorML-only fields under properties.

force_sml=True now applies to procedures and deployments as well as
systems, allowing in-place recovery for records that were created with
the old single-POST shape.

Background: pre-strict CSAPI servers returned HTTP 201 and silently
dropped SensorML metadata on procedures/deployments. Strict upstream
(connected-systems-go after a467aba) returns HTTP 400. Either way, the
bug was on the client.

Refs: #5
Replaces PROCEDURE_BODY (single mixed-encoding dict) with _procedure_stub
and _procedure_sml; strips documentation arrays from _deploy_root and
_deploy_group stubs and adds matching _deploy_root_sml /
_deploy_group_sml; threads force_sml through procedure and deployment
create calls so --force-sml now repairs them in place.

NWS is the canonical example for the same refactor that needs to land
across the other 9 publishers (E.2 follow-up).

Refs: #5
Four offline tests cover SML_ONLY_FIELDS membership and the
_warn_if_sml_fields_in_stub guardrail in both lenient and strict modes.

Two network-gated tests POST a procedure / deployment with marker
keywords + identifiers, GET them back as application/sml+json, and
assert the marker fields survive. Enable by setting
OS4CSAPI_TEST_BASE_URL / OS4CSAPI_TEST_USER / OS4CSAPI_TEST_PASS.

Verified: 6/6 passing against
https://129-80-248-53.sslip.io/csapi-go-upstream/.

Refs: #5
11-section report covering symptom, discovery, root cause, evidence,
the fix, verification, recovery operations, lessons, cross-references,
and timeline.

Refs: #5
@Sam-Bolling Sam-Bolling merged commit d8c4058 into main May 10, 2026
@Sam-Bolling Sam-Bolling deleted the fix/sml-content-type-and-shape branch May 10, 2026 01:28
Sam-Bolling added a commit that referenced this pull request May 10, 2026
…atalog

Honest assessment of strict-parsing migration work to date:
- What is genuinely improving (portability, OGC 23-001 conformance,
  empirical schema documented, helper infrastructure validated).
- What is NOT improving (metadata loss on the wire, no automated tests,
  copy-paste mechanical pattern, inline workaround comments).
- Comprehensive catalog of 4 P1/P2 upstream csapi-go-v2 defects + 2
  informational items, each with reproducer, current workaround, and
  expiry condition:
    #1 P1 procedure SML asymmetric typo (c2ab201 incomplete)
    #2 P1 system SML rejects characteristics/capabilities
    #3 P2 system SML returns 500 on typeOf
    #4 P2 datastream rejects SWE Time referenceTime
    #5 P3 datastream rejects top-level uid
    #6 informational deployment parent@link encoding

Recommendations: extract sml_builders helper, add contract tests, file
upstream issues, track metadata loss explicitly, choose OSH posture.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant