Skip to content
Registry StackDocsDevelopment (unreleased)

Query a spatial registry from QGIS

For the data publisher and operator

View as Markdown

If you are evaluating Base Registry Engine’s spatial read path, this tutorial starts a synthetic service-site registry on PostGIS and connects QGIS as a read-only installation client. PostGIS is the PostgreSQL extension that adds geometry types and spatial predicates. Base Registry Engine requires it only when a profile that lists records also declares a bounding box query, and the --spatial launcher flag supplies it by starting a PostGIS image in place of the plain PostgreSQL one. You will display authorized Point records, pan within a bounded map area, import one record through the normal API, and see the new Point after QGIS renews its Registry Mint credential.

Outcome
One protected QGIS Point layer that pages, pans, renews its credential, and refreshes after an authenticated Base Registry Engine write.
Time
About 35 minutes, plus the PostGIS image download
Level
Local evaluation with synthetic data on loopback
Prerequisites
The checkout and binaries from Create and query your first registryQGIS 4.2.1 with GDAL 3.12.4Running Docker, and two terminalsOpenSSL, Python 3.11 or later, and uvA text editor

Create and query your first registry installs breg, bregctl, and mint and clones the repository at the tag that matches them. Open a terminal at the root of that breg-tutorial checkout and confirm the binaries answer:

Terminal window
bregctl --version
mint --version

Run every shell command from the root of that clone. Keep two terminals open: the first runs Base Registry Engine and Registry Mint, while the second performs the refresh write. What this tutorial adds to that setup is QGIS, which needs a desktop session.

In the first terminal, start the spatial quickstart:

Terminal window
products/breg/quickstart/run.sh --installed --spatial

The --installed flag makes the launcher use the breg, bregctl, and mint you installed rather than building them from the checkout. The launcher first prints == Using installed breg, bregctl, and mint from PATH with the three paths it resolved. The first run also downloads the pinned PostGIS image. Wait for this banner; the ports, the operator token suffix, and the absolute paths vary:

Base Registry Engine spatial service-site quickstart is ready.
Base Registry Engine: http://127.0.0.1:<breg-port>
Registry Mint: http://127.0.0.1:<mint-port>
Project: <clone>/products/breg/quickstart/.run/project
Runtime config: <clone>/products/breg/quickstart/.run/runtime.yaml
QGIS OAPIF URL: http://127.0.0.1:<breg-port>/v1/gis
Collection: service-site.installation-map-reader
QGIS client id: qgis-installation-central
QGIS secret: <clone>/products/breg/quickstart/.run/secrets/qgis-client-secret
Operator token: <clone>/products/breg/quickstart/.run/secrets/operator-token-<suffix>
Map token: <clone>/products/breg/quickstart/.run/secrets/map-token
Logs: <clone>/products/breg/quickstart/.run/logs

This tutorial uses the QGIS OAPIF URL, the collection, the client id, and the client secret. The operator and map tokens are the launcher’s own short-lived credentials; the import step mints a fresh one instead of reusing them.

Leave the first terminal running. The launcher has compiled, tested, packaged, and applied the synthetic service-site project. It has also seeded Point records and checked native JSON, GeoJSON, and the QGIS-compatible collection route. QGIS calls this provider OAPIF, short for Open Geospatial Consortium (OGC) API Features. Base Registry Engine exposes only the compatibility routes named in this tutorial and publishes an empty conformance list.

Start an empty QGIS project. Select the project coordinate reference system control in the bottom-right corner and choose OGC:CRS84 (WGS 84 (CRS84)).

In the QGIS Locator, enter go 100.55,13.75 and select the result in the current project coordinate reference system. Set the status-bar Scale to 1:5000. Switch the coordinate display to Extents and confirm that the longitude span is less than 0.24 degrees and the latitude span is less than 0.19 degrees.

The installation-map-reader profile caps a bounding box at 0.25 longitude degrees by 0.20 latitude degrees. The cap limits how much of the map one query may ask for. It does not decide which records you may see: that is the profile’s row boundary, which compares each record’s zone with the service_zones claim in the installation credential. The smaller view leaves room for QGIS decimal serialization and for canvas aspect-ratio changes. A world view exceeds the cap and Base Registry Engine refuses the query with query.invalid.

  1. Open Settings > Options > Authentication > Configurations, then select Add a new authentication configuration. Set a QGIS master password if prompted.
  2. Name the configuration Base Registry Engine spatial quickstart. Set Resource URL to the printed Base Registry Engine origin without /v1/gis.
  3. Select OAuth2 authentication, Grant flow: Client Credentials, and Resource access token method: Header.
  4. Set Token URL to http://127.0.0.1:<mint-port>/token, using the printed Registry Mint port. Set Client ID to qgis-installation-central.
  5. Open the printed qgis-client-secret file in a local editor and copy its value into Client secret. Leave Scope empty and leave Persist between launches off, then save the configuration.

The client secret stays in QGIS’s authentication database. A saved QGIS project refers to the configuration by its authcfg identifier; the secret and bearer token do not belong in the layer URL or project file.

  1. Open Layer > Data Source Manager > WFS / OGC API - Features, then select New.
  2. Name the connection Base Registry Engine spatial quickstart. Set URL to the printed QGIS OAPIF URL and select the saved OAuth2 configuration under Authentication.
  3. Keep GET and feature paging enabled. Set Page size to 25, then save the connection.
  4. Select the connection under Server Connections and select Connect.
  5. Select service-site.installation-map-reader, enable Only request features overlapping the view extent, and select Add.

QGIS draws Point features near the map center. Press F6 to open the attribute table. The table includes id, label, mapLabel, nativeId, serviceKind, siteCode, and zone.

The installation credential carries a service_zones: central claim, so the collection returns only records whose zone is central. The layer is read-only, requests at most 25 records per page, and sends the visible extent as a bounding box. Base Registry Engine applies the same scope, purpose, row, and field rules to the QGIS-compatible route as it applies to native reads.

The bounding box is a filter inside that row boundary, not the boundary itself. If you leave Only request features overlapping the view extent off, QGIS sends no bounding box and pages through every record the row boundary allows, 25 at a time; the server allows at most 100 records per page on this collection.

Close the attribute table and use the QGIS pan tool to move a short distance east or west. Keep the status-bar extent within the longitude and latitude spans used in the earlier map setup.

The visible Points move and reload. If QGIS reports query.invalid, reduce the scale value to 1:2500, return to 100.55,13.75, and reload the layer with F5.

The /v1/gis surface supplies the route shape QGIS needs, including collection discovery, absolute paging links, and GeoJSON features. Its conformance list is empty because Base Registry Engine does not claim full Open Geospatial Consortium API Features conformance.

Import a Point through Base Registry Engine

Section titled “Import a Point through Base Registry Engine”

Keep QGIS open. In the second terminal, validate and import the supplied refresh record:

Terminal window
spatial_run="$PWD/products/breg/quickstart/.run"
spatial_input="$PWD/products/breg/acceptance/spatial-service-sites/fixtures/qgis-refresh-service-site.jsonl"
bregctl data validate \
--package "$spatial_run/build/package" \
--entity service-site --profile service-site-admin --operation create \
--input "$spatial_input"
spatial_refresh_token="$spatial_run/secrets/refresh-token-$(openssl rand -hex 8)"
mint token \
--url "$(cat "$spatial_run/mint-origin")/token" \
--client-id generic-quickstart \
--key "$spatial_run/keys/operator/signing-p256-private-jwk" |
python3 products/breg/quickstart/support/quickstart.py \
store-token --out "$spatial_refresh_token"
bregctl data import \
--package "$spatial_run/build/package" \
--breg-url "$(cat "$spatial_run/breg-origin")" \
--access-token-file "$spatial_refresh_token" \
--entity service-site --profile service-site-admin --operation create \
--input "$spatial_input" \
--checkpoint "$spatial_run/qgis-refresh-checkpoint.json"

The two summaries look like this; the digests depend on the project:

data validate succeeded
package revision: sha256:<package-revision>
schema fingerprint: sha256:<schema-fingerprint>
entity: service-site
profile: service-site-admin
operation: create
input bytes: 305
items: 1
chunks: 1
maximum items: 100
maximum bytes: 262144
data import succeeded
package revision: sha256:<package-revision>
schema fingerprint: sha256:<schema-fingerprint>
entity: service-site
profile: service-site-admin
operation: create
input bytes: 305
items: 1
completed chunks: 1
committed items: 1
complete: true

Run the block as one unit: every token the spatial quickstart mints, including the operator token this block requests, expires after 60 seconds. The checkpoint records each committed chunk, so an interrupted import resumes without sending a completed chunk again. If you run the import a second time with the same checkpoint, it sends nothing and reports committed items: 0 with complete: true. The operator token stays in an owner-only file and is never copied into QGIS.

Return to QGIS, select the layer, and press F5. Open the attribute table with F6. Use Select features using an expression with this expression:

"siteCode" = 'SVC-QGIS-REFRESH'

Select the matching feature and move the selection to the top. QGIS shows one record with these values:

label QGIS refresh example
mapLabel SVC-QGIS-REFRESH
serviceKind clinic
siteCode SVC-QGIS-REFRESH
zone central

Wait at least 95 seconds, then pan within the bounded extent and press F5 again. The protected layer reloads without asking you to paste a token. Spatial quickstart access tokens last 60 seconds; QGIS uses the stored client credential to request a replacement from Registry Mint.

Close the QGIS project. In the first terminal, press Ctrl+C. The launcher stops Base Registry Engine, Registry Mint, and the disposable database container. The files under products/breg/quickstart/.run/ remain until the next quickstart replaces them.

If you do not plan to repeat the tutorial, remove the QGIS server connection and OAuth2 configuration so the disposable client secret does not remain in your QGIS authentication database.

  • A local Base Registry Engine package with synthetic CRS84 Point records and PostGIS-backed bbox reads
  • A protected QGIS layer using an OAuth2 client credential stored outside the project file
  • A row-bounded map layer whose queries stay inside the profile’s bounding box cap, with page size 25 and flat authorized attributes
  • An authenticated API write that appeared after QGIS Refresh
  • A protected layer reload after the short-lived access token expired
SymptomCauseFix
The first run takes several minutes on Apple SiliconThe pinned PostGIS image uses linux/amd64, so Docker Desktop may run it under emulationLeave the launcher running; later runs reuse the downloaded image
The launcher exits before the banner and names breg, bregctl, or mint as required in --installed modeThe installer’s directory is not on your PATH, or you skipped one of the installers in Create and query your first registryAdd ~/.local/bin to PATH in this terminal, rerun the installer you skipped, then start the launcher again
QGIS reports query.invalid while adding or panning the layerThe visible extent exceeds the profile’s bounding box cap, often after QGIS adjusts the canvas aspect ratioReturn to 100.55,13.75, set scale to 1:2500, confirm the displayed spans are less than 0.24 and 0.19, then press F5
QGIS asks for credentials or reports an OAuth2 errorThe token URL, client ID, secret, or authentication selection does not match the current quickstartConfirm the printed ports, use client ID qgis-installation-central, copy the current owner-only secret, leave Scope empty, and keep the first terminal running
The connection opens but no Point appearsThe project starts at a world extent or outside the synthetic fixture areaSet project CRS to OGC:CRS84, locate 100.55,13.75, reduce the scale, and reload
Refresh does not add SVC-QGIS-REFRESHThe import did not complete, QGIS still has an attribute filter, or the layer cache has not reloadedConfirm complete: true, clear table filters, select the layer, and press F5