Skip to content

Deployment associations silently dropped despite advertising conf/deployment: deployedSystems@link, deployment@link, and deployment-scoped endpoints #1

Description

@Sam-Bolling

Summary

OSH advertises the CSAPI Part 1 deployment and subdeployment conformance classes and Part 2 datastream class, but three deployment-association mechanisms specified by those classes are non-functional:

# Mechanism Spec Reference Behavior
1 deployedSystems@link on Deployment OGC 23-001 §8.5 Table 10 (required) POST/PUT accepted → field silently dropped on GET
2 deployment@link on DataStream OGC 23-002 §7.3.2 (optional, but should persist if submitted) PUT returns 204 → field silently dropped on GET
3 /deployments/{id}/datastreams endpoint OGC 23-002 Annex A.2 Req 8–9 HTTP 400 "Invalid resource name: 'datastreams'"

The core issue is that fields are accepted without error but silently discarded. The server returns success codes (201/204) while not persisting the data, which makes the failure invisible to clients until they read it back.

What does work

For context, these related mechanisms do work correctly:

Mechanism Status
platform@link on Deployment ✅ Persists and returns correctly
Subdeployment hierarchy (/deployments/{id}/subdeployments) ✅ Works
Deployment CRUD (create, read, update, delete) ✅ Works
deployedSystemUIDs as custom string property ✅ Persists (but this is a workaround, not the spec-defined link format)

Environment

  • Server: OSH (OpenSensorHub) CSAPI instance on Oracle Cloud
  • API root: https://os4csapi-osh.duckdns.org/sensorhub/api
  • Date tested: 2026-03-02
  • Encodings tested: GeoJSON (application/geo+json) and SensorML-JSON (application/sml+json)
  • Client tooling: Python urllib (raw HTTP, no SDK)

Advertised Conformance Classes

GET /conformance returns (deployment/datastream relevant subset):

http://www.opengis.net/spec/ogcapi-connectedsystems-1/1.0/conf/deployment
http://www.opengis.net/spec/ogcapi-connectedsystems-1/1.0/conf/subdeployment
http://www.opengis.net/spec/ogcapi-connectedsystems-1/1.0/conf/create-replace-delete
http://www.opengis.net/spec/ogcapi-connectedsystems-2/1.0/conf/datastream
http://www.opengis.net/spec/ogcapi-connectedsystems-2/1.0/conf/create-replace-delete

The server claims conf/deployment — the class that requires deployedSystems association support per OGC 23-001 §8.5 Table 10.


Reproduction: Issue 1 — deployedSystems@link silently dropped

Request

POST /sensorhub/api/deployments HTTP/1.1
Content-Type: application/geo+json
Authorization: Basic ****

{
  "type": "Feature",
  "geometry": { "type": "Point", "coordinates": [-110.25, 31.64] },
  "properties": {
    "featureType": "sosa:Deployment",
    "uid": "urn:test:probe:deployed-systems-conformance:001",
    "name": "PROBE: deployedSystems conformance test",
    "validTime": ["2026-03-01T00:00:00Z", ".."],
    "deployedSystems@link": [
      {
        "href": "/sensorhub/api/systems/040g",
        "uid": "urn:os4csapi:system:set:ft-huachuca:001",
        "type": "application/geo+json"
      },
      {
        "href": "/sensorhub/api/systems/0410",
        "uid": "urn:os4csapi:system:monitoring-site-node:ft-huachuca:001",
        "type": "application/geo+json"
      },
      {
        "href": "/sensorhub/api/systems/041g",
        "uid": "urn:os4csapi:system:relay:vhf-repeater:ft-huachuca:001",
        "type": "application/geo+json"
      }
    ]
  }
}

Response to POST

HTTP 201 Created
Location: .../deployments/043g

Read-back

GET /sensorhub/api/deployments/043g HTTP/1.1
Accept: application/geo+json
{
  "type": "Feature",
  "id": "043g",
  "geometry": { "type": "Point", "coordinates": [-110.25, 31.64] },
  "properties": {
    "uid": "urn:test:probe:deployed-systems-conformance:001",
    "featureType": "sosa:Deployment",
    "name": "PROBE: deployedSystems conformance test",
    "validTime": ["2026-03-01T00:00:00Z", ".."]
  },
  "links": [...]
}

deployedSystems@link is completely absent from the response. The 3-system array was silently discarded.

Also tested

GET /sensorhub/api/deployments/043g/deployedSystems → 400 "Invalid resource name: 'deployedSystems'"
GET /sensorhub/api/deployments/043g/systems          → 400 "Invalid resource name: 'systems'"

Reproduction: Issue 2 — deployment@link silently dropped on DataStream

Request

PUT /sensorhub/api/systems/0420/datastreams/0430 HTTP/1.1
Content-Type: application/json
Authorization: Basic ****

{
  "name": "AZ-MA-1 Classification Probabilities",
  "...(original fields)...": "...",
  "schema": { "...(required by OSH for PUT)..." },
  "deployment@link": {
    "href": "/sensorhub/api/deployments/043g",
    "title": "PROBE-TEST-MARKER",
    "uid": "urn:os4csapi:deployment:node:ft-huachuca:alpha:001",
    "type": "application/geo+json"
  }
}

Response to PUT

HTTP 204 No Content

Read-back

GET /sensorhub/api/systems/0420/datastreams/0430 HTTP/1.1
Accept: application/json

Response contains no deployment@link field. The field was accepted (204) but not persisted.


Reproduction: Issue 3 — Deployment-scoped endpoints return 400

GET /sensorhub/api/deployments/0420/datastreams HTTP/1.1
→ 400 {"status": 400, "message": "Invalid resource name: 'datastreams'"}

GET /sensorhub/api/deployments/0420/systems HTTP/1.1
→ 400 {"status": 400, "message": "Invalid resource name: 'systems'"}

GET /sensorhub/api/deployments/043g/datastreams HTTP/1.1
→ 400 {"status": 400, "message": "Invalid resource name: 'datastreams'"}

Tested on multiple deployment IDs (0420 = SNET with subdeployments, 043g = leaf node). Same result.


Observed pattern

OSH persists @link fields that follow its internal parent→child hierarchy:

Field Direction Persists?
platform@link on Deployment Deployment → System (bridge) ✅ Yes
system@link on DataStream DataStream → System (parent) ✅ Yes (read-only)
deployedSystems@link on Deployment Deployment → Systems (cross-cutting) ❌ Dropped
deployment@link on DataStream DataStream → Deployment (cross-cutting) ❌ Dropped

This suggests OSH treats deployments and systems as separate, non-intersecting trees with platform@link as the sole bridge — and does not yet implement the cross-cutting associations the spec defines.


Impact

This blocks the "deployment-first" operational workflow that CSAPI was designed to enable:

Spec-intended workflow (broken):
  GET /deployments/{nodeId}/datastreams → node's datastreams directly

Current workaround (functional but indirect):
  GET /deployments/{nodeId}            → read platform@link
  GET /systems/{systemId}/datastreams  → all system's datastreams (no deployment scoping)

For an acoustic sensor network with 3 nodes × 7 datastreams × N observations, the inability to scope by deployment means:

  • No per-node data filtering via API
  • No temporal deployment window scoping (when a sensor moves between nodes)
  • Clients must do N+1 API calls + client-side join instead of one deployment-scoped query

Questions for maintainers

  1. Does OSH currently intend to implement the deployedSystems association and deployment-scoped endpoints? Is this a known roadmap item?
  2. If not yet intended:
    • Could /conformance be updated to not advertise conf/deployment if the required deployedSystems association isn't supported?
    • Could unsupported @link fields be rejected with a 4xx error rather than silently dropped? The silent-acceptance pattern makes the gap invisible to clients.

Suggested resolution

Option A — Implement the missing associations:

  1. Persist deployedSystems@link (array) on Deployment resources
  2. Persist deployment@link on DataStream resources
  3. Implement /deployments/{id}/datastreams and /deployments/{id}/systems endpoints

Option B — Accurately document current capabilities:

  1. Remove conf/deployment from /conformance if deployedSystems won't be supported (or add a note)
  2. Reject unsupported @link fields with HTTP 422 instead of silently accepting them

Either option resolves the immediate pain point (silent data loss on write).


Evidence

Detailed probe reports with full HTTP transcripts:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions