From e1a7ba92f79340bfd0cba873dcd37303aef0294a Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Tue, 8 Sep 2026 01:26:53 +0700 Subject: [PATCH 1/3] docs(site): reshape the remaining Base Registry tutorials Apply the tutorial-shape rules to the six Base Registry tutorials that follow the first two: every screen keeps a command or a line to check, role and route inventories move to the configure and reference pages, generated files are no longer reprinted, and headings name the action. Every transcript was replayed on the current development build. Two claims did not hold and are corrected: a repeated data import prints the checkpoint's cumulative count rather than zero, and a list without orderby is sorted by the assigned identifier, so the paging order is not the creation order. Signed-off-by: Jeremi Joslin --- .../build-a-breg-production-candidate.mdx | 6 +- .../extend-a-registry-with-a-module.mdx | 27 +-- .../query-a-spatial-registry-from-qgis.mdx | 31 ++- .../docs/tutorials/query-breg-client.mdx | 33 ++- .../tutorials/review-registry-changes.mdx | 205 ++++++------------ .../send-registry-events-to-a-webhook.mdx | 2 +- 6 files changed, 105 insertions(+), 199 deletions(-) diff --git a/docs/site/src/content/docs/tutorials/build-a-breg-production-candidate.mdx b/docs/site/src/content/docs/tutorials/build-a-breg-production-candidate.mdx index 82ec68626..eb6fa5ecd 100644 --- a/docs/site/src/content/docs/tutorials/build-a-breg-production-candidate.mdx +++ b/docs/site/src/content/docs/tutorials/build-a-breg-production-candidate.mdx @@ -5,7 +5,7 @@ status: current owner: registry-docs source_repos: - registry-stack -last_reviewed: "2026-09-04" +last_reviewed: "2026-09-08" doc_type: tutorial persona: - data publisher @@ -28,7 +28,7 @@ from there. outcome="A package built from your project, signed with a local key, and accepted by bregctl verify under a trust anchor you wrote." time="About 30 minutes" level="Production build with synthetic data and local keys" - prerequisites={['bregctl 0.26.1 from Create and query your first registry', 'Docker', 'OpenSSL 3']} + prerequisites={['The bregctl from Create and query your first registry', 'Docker', 'OpenSSL 3']} /> ## Before you start @@ -152,7 +152,7 @@ package, or a repository. They exist for this exercise and are deleted in the cl The runtime connects to PostgreSQL over TLS only, and the schema test uses the same connection code, so the container needs a server certificate. Create a small certificate authority and a certificate -for `localhost`, then start the PostgreSQL 17 image the quickstart launcher uses, on port 5433 so it +for `localhost`, then start a PostgreSQL 17 container on port 5433 so it stays clear of a PostgreSQL you may already run: ```sh diff --git a/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx b/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx index 4712d5ca4..f0f938e3f 100644 --- a/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx +++ b/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx @@ -5,7 +5,7 @@ status: current owner: registry-docs source_repos: - registry-stack -last_reviewed: "2026-09-07" +last_reviewed: "2026-09-08" doc_type: tutorial persona: - data publisher @@ -73,14 +73,12 @@ Authoring check passed. ``` This is the project the first tutorial started as a registry, so the entity, fields, and profiles are -the ones you used over HTTP: `registry.yaml`, one module under `modules/`, `tests/journeys.yaml`, -`dev-clients.yaml`, `runtime.example.yaml`, and a `README.md` that lists them. +the ones you used over HTTP, in the files [init wrote](../first-breg/#what-init-wrote). The `revision` line is the digest of the compiled project; it changes with every edit you make. A finding is advice the compiler attaches to a result that succeeded: an error stops a command, a finding does not. The first says the `operator` profile can list every row, which is intended for a registry-wide operations team, -and the second says the `evidence-source` profile can look up any record by its code; -the project's `record-reader` profile shows the claim-bound row restriction that closes either one. +and the second says the `evidence-source` profile can look up any record by its code. Every command in this tutorial repeats both findings, so treat them as expected and read past them to the result. {/* Evidence: crates/registry-bregctl/src/lib.rs, init_files() and check(); crates/registry-breg/src/access.rs. */} @@ -89,26 +87,19 @@ Every command in this tutorial repeats both findings, so treat them as expected A module is a separate file that contributes to the model, so a reusable part of a registry can be reviewed and versioned apart from the project that adopts it. -Open `tutorial-work/project/modules/record-notes/module.yaml`. -Written out as block mappings (the file keeps each field on one line), it declares one optional field on the -entity the project owns: +Open `tutorial-work/project/modules/record-notes/module.yaml` and find its version and the one field it +declares on the entity the project owns: ```yaml -id: record-notes version: 0.1.0 -extendEntities: - - entity: record - fields: - - id: internal-note - type: string - maxLength: 500 - classification: internal +``` + +```yaml + - {id: internal-note, type: string, maxLength: 500, classification: internal} ``` A field without `required: true` is optional, so existing records stay valid and a create may omit it. Its classification matches the entity's default, `internal`. -A more sensitive value such as `restricted` adds a further finding, `access.profile.higher_classification`, -once a grant exposes the field; it asks you to confirm the profile's scope and purpose first. Now open `tutorial-work/project/registry.yaml` and find the `modules` entry at the end of the file: diff --git a/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx b/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx index 329d6bbb3..13a81ba19 100644 --- a/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx +++ b/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx @@ -5,7 +5,7 @@ status: current owner: registry-docs source_repos: - registry-stack -last_reviewed: "2026-09-07" +last_reviewed: "2026-09-08" doc_type: tutorial persona: - data publisher @@ -34,7 +34,7 @@ normal API, and see the new Point after QGIS renews its Registry Mint credential 'The binaries from Create and query your first registry, and git', 'QGIS 4.2.1 with GDAL 3.12.4', 'Running Docker, and two terminals', - 'OpenSSL, Python 3.11 or later, and uv', + 'OpenSSL and Python 3.11 or later', 'A text editor', ]} /> @@ -127,11 +127,10 @@ display to **Extents** and confirm that the longitude span is less than `0.24` d 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`. +latitude degrees, and a world view exceeds it, so Base Registry Engine refuses the query with +`query.invalid`. The smaller view leaves room for QGIS decimal serialization and for canvas +aspect-ratio changes. The cap limits how much of the map one query may ask for, not which records +you may see; that is the profile's row boundary, which you meet in the next steps. {/* Evidence: products/breg/acceptance/spatial-service-sites/registry.yaml; crates/registry-breg/src/query.rs, parse_bbox(); @@ -180,15 +179,11 @@ messages. The quickstart creates the secret file with owner-only permissions. 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. +Every `zone` value is `central`: the installation credential carries a `service_zones: central` +claim, and the profile's row boundary returns only records whose `zone` matches it. The bounding +box is a filter inside that boundary, not the boundary itself. Base Registry Engine applies the +same scope, purpose, row, and field rules to the QGIS-compatible route as to native reads; the +[API reference](../../reference/breg-api/#spatial-adapter) covers the route and its paging limits. {/* Evidence: crates/registry-breg/src/api/gis.rs, collections(), collection(), items(), authorize_gis_collection(), parse_items_query() and query_options(); @@ -272,8 +267,8 @@ Imported the input. 1 item committed. 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 `0 items committed` with -`complete` at `true`. The operator token stays in an owner-only file and is never copied into QGIS. +second time with the same checkpoint, it sends nothing and prints the same summary, because the +counts come from the checkpoint. The operator token stays in an owner-only file and is never copied into QGIS. {/* Evidence: crates/registry-bregctl/src/lib.rs; products/breg/quickstart/support/quickstart.py, store_token(); diff --git a/docs/site/src/content/docs/tutorials/query-breg-client.mdx b/docs/site/src/content/docs/tutorials/query-breg-client.mdx index b7a70b8d1..6c0fb083e 100644 --- a/docs/site/src/content/docs/tutorials/query-breg-client.mdx +++ b/docs/site/src/content/docs/tutorials/query-breg-client.mdx @@ -5,7 +5,7 @@ status: current owner: registry-docs source_repos: - registry-stack -last_reviewed: "2026-09-07" +last_reviewed: "2026-09-08" doc_type: tutorial persona: - consumer or verifier @@ -16,14 +16,12 @@ standards_referenced: import QuickstartMeta from '../../../components/QuickstartMeta.astro'; -This tutorial needs a registry on Registry Stack v0.26.1 or later and a client package at exactly -that registry's version. The unified client packages start at v0.26.1: against a v0.26.0 registry -there is no Base Registry Engine client package to install. The unified Registry Stack client gives -an application one method for each Base Registry Engine operation, in Python and in Node. In this -tutorial you install the published package, read the record you created in the first tutorial, -create a record with an idempotency key, page through the collection with a continuation, and -inspect a refused write. Every step shows both languages; follow the one your application uses, or run both against -the same registry. +The unified Registry Stack client gives an application one method for each Base Registry Engine +operation, in Python and in Node. In this tutorial you install the published package at your +registry's version, read the record you created in the first tutorial, create a record with an +idempotency key, page through the collection with a continuation, and inspect a refused write. +Every step shows both languages; follow the one your application uses, or run both against the +same registry. Date: Tue, 8 Sep 2026 09:58:08 +0700 Subject: [PATCH 2/3] docs(site): restore uv and qualify the repeated-findings claims The spatial quickstart launcher requires uv, so the QGIS prerequisites name it again. The module and review-changes pages say every check repeats the findings, but each page later shows a refused check that prints errors and no findings, so the claim now applies to checks that pass. Signed-off-by: Jeremi Joslin --- .../content/docs/tutorials/extend-a-registry-with-a-module.mdx | 3 ++- .../docs/tutorials/query-a-spatial-registry-from-qgis.mdx | 2 +- .../src/content/docs/tutorials/review-registry-changes.mdx | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx b/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx index f0f938e3f..f43db293e 100644 --- a/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx +++ b/docs/site/src/content/docs/tutorials/extend-a-registry-with-a-module.mdx @@ -79,7 +79,8 @@ The `revision` line is the digest of the compiled project; it changes with every A finding is advice the compiler attaches to a result that succeeded: an error stops a command, a finding does not. The first says the `operator` profile can list every row, which is intended for a registry-wide operations team, and the second says the `evidence-source` profile can look up any record by its code. -Every command in this tutorial repeats both findings, so treat them as expected and read past them to the result. +Every command in this tutorial that succeeds repeats both findings, so treat them as expected and read past them to the result. +A check that is refused prints its errors instead, and you will meet one when you change the module. {/* Evidence: crates/registry-bregctl/src/lib.rs, init_files() and check(); crates/registry-breg/src/access.rs. */} diff --git a/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx b/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx index 13a81ba19..e5b899336 100644 --- a/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx +++ b/docs/site/src/content/docs/tutorials/query-a-spatial-registry-from-qgis.mdx @@ -34,7 +34,7 @@ normal API, and see the new Point after QGIS renews its Registry Mint credential 'The binaries from Create and query your first registry, and git', 'QGIS 4.2.1 with GDAL 3.12.4', 'Running Docker, and two terminals', - 'OpenSSL and Python 3.11 or later', + 'OpenSSL, Python 3.11 or later, and uv', 'A text editor', ]} /> diff --git a/docs/site/src/content/docs/tutorials/review-registry-changes.mdx b/docs/site/src/content/docs/tutorials/review-registry-changes.mdx index f4b2e087f..480108724 100644 --- a/docs/site/src/content/docs/tutorials/review-registry-changes.mdx +++ b/docs/site/src/content/docs/tutorials/review-registry-changes.mdx @@ -116,7 +116,8 @@ The example's `asset-operator` and `site-planner` profiles admit any authenticat right purpose and can list every row, and the three remaining codes say the same of other grants. Leave the findings as they are for this tutorial; `--deny-findings` turns them into failures when you want a project held to that bar. -Every check in this tutorial repeats them, so read past them to the summary line. +Every check that passes in this tutorial repeats them, so read past them to the summary line. +A check that is refused prints its errors instead, and you will meet one at the end. ## Explain the workflow From 05096142451b14ff64117a382390a7e3b0c4de79 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Tue, 8 Sep 2026 10:43:48 +0700 Subject: [PATCH 3/3] docs(site): separate profile eligibility from row authority in the findings summary The four correction profiles each declare a required scope, so they are absent from the no_required_scope group, and two of them are granted no list operation at all. The summary said the other three codes said the same of other grants, which read as though any authenticated caller could select every profile and list every row. Signed-off-by: Jeremi Joslin --- .../content/docs/tutorials/review-registry-changes.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/site/src/content/docs/tutorials/review-registry-changes.mdx b/docs/site/src/content/docs/tutorials/review-registry-changes.mdx index 480108724..cf964b05a 100644 --- a/docs/site/src/content/docs/tutorials/review-registry-changes.mdx +++ b/docs/site/src/content/docs/tutorials/review-registry-changes.mdx @@ -112,8 +112,12 @@ Authoring check passed. ``` Findings are advisories, not failures. -The example's `asset-operator` and `site-planner` profiles admit any authenticated caller with the -right purpose and can list every row, and the three remaining codes say the same of other grants. +The first code is about who may select a profile: `asset-operator` and `site-planner` declare no +required scope, so any authenticated caller with the right purpose qualifies. +Each `correction-` profile declares a scope of its own, which is why none of them appear in that group. +The three remaining codes are about row authority instead. +They name grants that hold no claim-bound row restriction, within the operations and fields each +grant allows, and a grant that includes `list` can therefore list every row. Leave the findings as they are for this tutorial; `--deny-findings` turns them into failures when you want a project held to that bar. Every check that passes in this tutorial repeats them, so read past them to the summary line.