Skip to content

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

@Sam-Bolling

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:

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