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
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
- Does OSH currently intend to implement the
deployedSystems association and deployment-scoped endpoints? Is this a known roadmap item?
- 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:
- Persist
deployedSystems@link (array) on Deployment resources
- Persist
deployment@link on DataStream resources
- Implement
/deployments/{id}/datastreams and /deployments/{id}/systems endpoints
Option B — Accurately document current capabilities:
- Remove
conf/deployment from /conformance if deployedSystems won't be supported (or add a note)
- 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:
Summary
OSH advertises the CSAPI Part 1
deploymentandsubdeploymentconformance classes and Part 2datastreamclass, but three deployment-association mechanisms specified by those classes are non-functional:deployedSystems@linkon Deploymentdeployment@linkon DataStream/deployments/{id}/datastreamsendpoint"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:
platform@linkon Deployment/deployments/{id}/subdeployments)deployedSystemUIDsas custom string propertyEnvironment
https://os4csapi-osh.duckdns.org/sensorhub/apiapplication/geo+json) and SensorML-JSON (application/sml+json)urllib(raw HTTP, no SDK)Advertised Conformance Classes
GET /conformancereturns (deployment/datastream relevant subset):The server claims
conf/deployment— the class that requiresdeployedSystemsassociation support per OGC 23-001 §8.5 Table 10.Reproduction: Issue 1 —
deployedSystems@linksilently droppedRequest
Response to POST
Read-back
{ "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@linkis completely absent from the response. The 3-system array was silently discarded.Also tested
Reproduction: Issue 2 —
deployment@linksilently dropped on DataStreamRequest
Response to PUT
Read-back
Response contains no
deployment@linkfield. The field was accepted (204) but not persisted.Reproduction: Issue 3 — Deployment-scoped endpoints return 400
Tested on multiple deployment IDs (
0420= SNET with subdeployments,043g= leaf node). Same result.Observed pattern
OSH persists
@linkfields that follow its internal parent→child hierarchy:platform@linkon Deploymentsystem@linkon DataStreamdeployedSystems@linkon Deploymentdeployment@linkon DataStreamThis suggests OSH treats deployments and systems as separate, non-intersecting trees with
platform@linkas 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:
For an acoustic sensor network with 3 nodes × 7 datastreams × N observations, the inability to scope by deployment means:
Questions for maintainers
deployedSystemsassociation and deployment-scoped endpoints? Is this a known roadmap item?/conformancebe updated to not advertiseconf/deploymentif the requireddeployedSystemsassociation isn't supported?@linkfields 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:
deployedSystems@link(array) on Deployment resourcesdeployment@linkon DataStream resources/deployments/{id}/datastreamsand/deployments/{id}/systemsendpointsOption B — Accurately document current capabilities:
conf/deploymentfrom/conformanceifdeployedSystemswon't be supported (or add a note)@linkfields with HTTP 422 instead of silently accepting themEither option resolves the immediate pain point (silent data loss on write).
Evidence
Detailed probe reports with full HTTP transcripts:
OSH_DeployedSystems_Conformance_Probe.md—deployedSystems@linkprobe methodology and resultsOSH_Deployment_Link_Persistence_Gap.md—deployment@linkprobe + cumulative three-mechanism failure analysis