Skip to content

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

Open
Sam-Bolling wants to merge 4 commits intomainfrom
fix/sml-content-type-and-shape
Open

fix(bootstrap): two-step encoding for procedures and deployments + NWS canonical refactor#6
Sam-Bolling wants to merge 4 commits intomainfrom
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
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