Skip to content

Publishing, subscriptions and exact reads

Experimental pilot API. https://ophiolite.dev/docs/ is the documentation site, not a project-service API endpoint. Your deployment operator supplies the service address and scoped credentials. No public hosted endpoint, anonymous data service or stable SDK is implied here.

The authoritative definitions are WorkspaceService and its messages in proto/arraybridge.proto. Python tools use generated gRPC bindings; they do not access the server database.

RPC Request Role
RegisterExternalSource ExternalSource Register publisher identity, adapter and permission to retain project copies
PublishExternalSnapshot ExternalPublish Publish validated snapshot with source version, expected revision and command ID
GetAsset AssetRead Read authorized asset metadata; revision zero selects current head
GetExternalSnapshot AssetRead Read numerical payload; consumers use the exact announced revision
WatchAsset AssetRef Receive a stream of committed-state revision hints
GetAssetChanges AssetChangesRequest Read project changes after a durable cursor, with pagination

ExternalPublish carries project_id, source_id, source_key, monotonic source_version, mapping_version, expected_revision, command_id and snapshot. Creation uses expected revision zero; stale writes fail. The connector persists publication intent before sending it and retries the same recorded command after interruption. Do not create a fresh command ID for every network retry.

The current publisher records this intent in its local SQLite journal. The project service owns access, asset identity, publication order and history. Registering a source with snapshots_permitted=true is an explicit rights attestation; do not set it without the necessary rights.

source capture -> journal -> authorized publish -> committed project revision
|
database commit notification
|
WatchAsset stream
|
consumer bridge
|
HTTP long-poll notice
|
QGIS GUI <- prepared layers <- worker: exact read / verify / cache / contours

WatchAsset first sends the current authorized state, then changes. Each notice contains the asset reference, revision and availability. Intermediate revisions may coalesce. Reconnecting reconciles the latest state; this is not an exactly-once event history. Consumers that must process every change need cursor-based reads and an appropriate replay/recovery policy.

Commit notifications now wake the scalar-map stream instead of periodically reading the database for a changed revision. ResInsight source capture still polls. Access/credential checks and reconnection work also remain; streaming does not mean zero idle cost.

This is a loopback pilot adapter, not a general public REST API. Remote access uses a private tunnel. Every request needs its separate bridge capability in Authorization: Bearer …; the bridge uses a project credential for upstream reads. Do not put either secret in a URL, diagram, QGIS project or source-controlled configuration.

GET route Result
/head Current authorized asset ID, revision string and representation key
/events?after=13 Wait up to about 20 seconds, returning early for a changed state; result has the same fields as head
/snapshot?revision=13 Exact authorized revision, representation key, manifest and base64 GeoTIFF

A timeout response can report the same revision; the consumer waits again. Reauthorize notice delivery and payload reads even when data is cached. Compare both publication revision and representation key before deciding that no download is needed. Verify the raster hash and manifest before applying layers. No arbitrary per-request conversion is accepted: the bridge’s configured policy chooses the representation.

Current bounds are 16 native asset watchers per server process and, by default, eight waiting event requests plus four data requests per bridge. Admission failures return 503; bridge responses can also return 401 for invalid capability, 403 for upstream access failure, and 400 for invalid requests/conversion policy. Use bounded retries/backoff for transient failures; surface access and configuration failures instead of looping silently. These limits establish a bounded pilot, not multi-tenant scale qualification.

Network I/O, conversion and contour preparation run outside the QGIS GUI thread. Apply prepared layers using host-supported GUI APIs. One preparation worker bounds concurrent work; do not start one download thread per notification. Workers still consume CPU and memory. Third-party APIs may require some source capture or destination application on their own main thread; declare those limits per connector rather than promising universal freeze-free behavior.

Use TLS for remote gRPC or the qualified loopback SSH tunnel. The existing Python client rejects other plain-text remote endpoints. Revocation prevents future authorized reads but cannot erase already exported files.

Data contract · Python tooling and SDK status.