From 6c7f457bcf5a40328f184e5fd1a4d1fc4e5dbe68 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Thu, 6 Aug 2026 16:00:12 +0700 Subject: [PATCH 01/10] Bootstrap Digital Registries 3.0.0-alpha.2 Signed-off-by: Jeremi Joslin --- README.md | 90 +--- api/README.md | 9 + ...registries_BB_Data_API_template-1.3.0.json | 0 ...registries_BB_Data_API_template-1.3.0.yaml | 0 ...stries_BB_Database_API_template-1.3.0.json | 0 ...stries_BB_Database_API_template-1.3.0.yaml | 0 ...registries_BB_Data_API_template-1.3.0.json | 0 ...es_BB_Database_API_template-1.3.0 (1).json | 0 ...stries_BB_Database_API_template-1.3.0.json | 0 ...stries_BB_Database_API_template-1.3.0.yaml | 0 api/readme.txt | 15 - examples/README.md | 12 +- examples/eRegistrations/README.md | 9 +- examples/mockoon/README.md | 7 +- spec/.gitbook/assets/api-families.svg | 256 +++++++++++ .../Registries-3.0.0-alpha.1.svg} | 0 spec/1-version-history/README.md | 44 +- spec/1-version-history/release-notes.md | 2 +- ...security-and-interoperability-standards.md | 75 --- spec/10-other-resources/README.md | 28 -- spec/10-workflows.md | 45 ++ spec/11-testing.md | 75 +++ spec/12-other-resources/README.md | 44 ++ .../historical/future-considerations.md} | 8 +- .../historical/key-decision-log.md} | 10 +- spec/12-other-resources/migration-from-3.0.md | 88 ++++ spec/12-other-resources/references.md | 28 ++ spec/2-description-and-scope.md | 76 +++ spec/2-description.md | 31 -- spec/3-terminology.md | 64 ++- spec/4-conformance.md | 33 ++ spec/4-key-digital-functionalities.md | 66 --- spec/5-api-families/access-transparency.md | 35 ++ spec/5-api-families/aggregate-data.md | 31 ++ spec/5-api-families/consultation.md | 39 ++ spec/5-api-families/evidence.md | 33 ++ spec/5-api-families/identity-federation.md | 29 ++ spec/5-api-families/notification.md | 34 ++ spec/5-api-families/provisioning.md | 36 ++ spec/5-api-families/write.md | 33 ++ spec/5-cross-cutting-requirements.md | 29 -- spec/5-key-functionalities.md | 36 ++ spec/6-functional-requirements.md | 435 ++++-------------- spec/7-cross-functional-requirements.md | 20 + spec/7-data-structures.md | 48 -- spec/8-data-structures.md | 90 ++++ spec/8-service-apis.md | 101 ---- spec/9-service-interfaces.md | 53 +++ spec/9-workflows.md | 156 ------- spec/README.md | 33 +- spec/SUMMARY.md | 27 +- test/README.md | 5 + 52 files changed, 1366 insertions(+), 1052 deletions(-) create mode 100644 api/README.md rename api/{ => legacy/generated-crud}/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json (100%) rename api/{ => legacy/generated-crud}/GovStack_Digital_registries_BB_Data_API_template-1.3.0.yaml (100%) rename api/{ => legacy/generated-crud}/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json (100%) rename api/{ => legacy/generated-crud}/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml (100%) rename {spec/.gitbook/assets => api/legacy/generated-crud/gitbook-copies}/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json (100%) rename {spec/.gitbook/assets => api/legacy/generated-crud/gitbook-copies}/GovStack_Digital_registries_BB_Database_API_template-1.3.0 (1).json (100%) rename {spec/.gitbook/assets => api/legacy/generated-crud/gitbook-copies}/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json (100%) rename {spec/.gitbook/assets => api/legacy/generated-crud/gitbook-copies}/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml (100%) delete mode 100644 api/readme.txt create mode 100644 spec/.gitbook/assets/api-families.svg rename spec/.gitbook/assets/{Registries.svg => historical/Registries-3.0.0-alpha.1.svg} (100%) delete mode 100644 spec/10-other-resources/10.5-cross-functional-security-and-interoperability-standards.md delete mode 100644 spec/10-other-resources/README.md create mode 100644 spec/10-workflows.md create mode 100644 spec/11-testing.md create mode 100644 spec/12-other-resources/README.md rename spec/{12-future-consideration.md => 12-other-resources/historical/future-considerations.md} (99%) rename spec/{11-key-decision-log.md => 12-other-resources/historical/key-decision-log.md} (98%) create mode 100644 spec/12-other-resources/migration-from-3.0.md create mode 100644 spec/12-other-resources/references.md create mode 100644 spec/2-description-and-scope.md delete mode 100644 spec/2-description.md create mode 100644 spec/4-conformance.md delete mode 100644 spec/4-key-digital-functionalities.md create mode 100644 spec/5-api-families/access-transparency.md create mode 100644 spec/5-api-families/aggregate-data.md create mode 100644 spec/5-api-families/consultation.md create mode 100644 spec/5-api-families/evidence.md create mode 100644 spec/5-api-families/identity-federation.md create mode 100644 spec/5-api-families/notification.md create mode 100644 spec/5-api-families/provisioning.md create mode 100644 spec/5-api-families/write.md delete mode 100644 spec/5-cross-cutting-requirements.md create mode 100644 spec/5-key-functionalities.md create mode 100644 spec/7-cross-functional-requirements.md delete mode 100644 spec/7-data-structures.md create mode 100644 spec/8-data-structures.md delete mode 100644 spec/8-service-apis.md create mode 100644 spec/9-service-interfaces.md delete mode 100644 spec/9-workflows.md create mode 100644 test/README.md diff --git a/README.md b/README.md index 83a3949..82a05bb 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,28 @@ -# GovStack Building Block Template +# GovStack Digital Registries Building Block -This template is intended to be used by the various GovStack building block -repos. Each building block repo will have at least 4 main sections, outlined in -the directory structure below. +This repository contains the Digital Registries Building Block specification, interface contracts, conformance tests, and implementation examples. -## Gitbook and the published "Building Block Specifications" document +## Specification status -Note that pushes to the `main` branch will automatically trigger a Gitbook build -and deployment from the `/spec` directory. +The `3.0.0-alpha.2` specification defines a domain-neutral Registry Core with mandatory Consultation Retrieve and additional optional capability families. Its requirements are classified as DRAFT and do not establish a GovStack certification claim. -## Repo Structure +Start with the [Digital Registries Building Block Specification](spec/README.md). -```sh -README.md -/spec # the markdown files which are used to build the specification in GitBook -/api # the openapi specification -/test # the test plan and tests - plan.md -/examples # examples for deploying, configuring, and testing applications which implement the behaviors specified by this building block - /application-a - README.md # instructions for deployment/testing - docker-compose.yaml # example deployment file - db - web - adaptor - security-server - Caddyfile # example config for "adaptor" - Dockerfile # dockerfile to build "adaptor" - /application-b - /application-c -``` +## Repository structure -## Test data +| Path | Contents | Current status | +|---|---|---| +| `spec/` | Human-readable specification published through GitBook | 3.0.0-alpha.2 draft | +| `api/` | Machine-readable service contracts | Previous generated CRUD contracts retained as legacy; no 3.0.0-alpha.2 contract published | +| `test/` | Conformance and contract tests | Previous generated CRUD tests retained as legacy; draft scenarios are documented in `spec/11-testing.md` | +| `examples/` | Product and integration examples | Historical examples; not evidence of 3.0.0-alpha.2 conformance | -In order to properly call the tests, a file with input data has been created. +## Alpha coverage -The data must exist in tested software before running the tests. +The alpha publishes the proposed scope, terminology, Base Registry Profile, DRAFT Core and Retrieve requirements, conceptual Record model, workflow, verification intent, and migration from the previous `DRS-1` through `DRS-37` requirements. -This data are compatible with the data used in the tests and they are stored in -the `openAPI` folder in the `test-data.json`. +It does not publish a canonical OpenAPI contract or executable conformance suite. No implementation can claim conformance with this alpha. -## Run Cucumber tests +## Publication -Cucumber-js is used to execute test harness to check compability of application -api with BB test definitions. - -### Mock server - -Launch the mock server from examples/mock folder. The instruction is located in -'examples/mock' folder in file README.md - -### Cucumber tests - -To install project's dependencies, navigate to folder 'test' and execute the -following command: - -``` -yarn install -``` - -Then to execute all tests scenarios use the following command: - -``` -yarn test -``` - -or - -``` -npx cucumber-js -``` - -To execute specific test scenario use the following command: - -``` -npx cucumber-js features/ -``` - -example: - -``` -npx cucumber-js features/data_update_or_create.feature -``` +GitBook publishes content from the `spec/` directory according to `.gitbook.yaml`. The navigation source is [spec/SUMMARY.md](spec/SUMMARY.md). diff --git a/api/README.md b/api/README.md new file mode 100644 index 0000000..a30c674 --- /dev/null +++ b/api/README.md @@ -0,0 +1,9 @@ +# API artifacts + +The JSON and YAML files under `legacy/generated-crud/` describe the generated CRUD interface from earlier Digital Registries releases. They are retained for migration analysis and are not service contracts for the 3.0.0-alpha.2 specification. + +The `gitbook-copies/` subdirectory contains additional copies previously embedded as publication assets. They remain separated from current API artifacts because their content is not identical in every case. + +In particular, the legacy interface does not provide the `consultation.retrieve` operation, which retrieves a Record directly by its stable Record Identifier. Its `POST /read` operation performs search-by-example instead. + +No canonical OpenAPI contract for the 3.0.0-alpha.2 specification is published. An implementation therefore cannot claim API-contract conformance with this alpha. diff --git a/api/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json b/api/legacy/generated-crud/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json similarity index 100% rename from api/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json rename to api/legacy/generated-crud/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json diff --git a/api/GovStack_Digital_registries_BB_Data_API_template-1.3.0.yaml b/api/legacy/generated-crud/GovStack_Digital_registries_BB_Data_API_template-1.3.0.yaml similarity index 100% rename from api/GovStack_Digital_registries_BB_Data_API_template-1.3.0.yaml rename to api/legacy/generated-crud/GovStack_Digital_registries_BB_Data_API_template-1.3.0.yaml diff --git a/api/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json b/api/legacy/generated-crud/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json similarity index 100% rename from api/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json rename to api/legacy/generated-crud/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json diff --git a/api/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml b/api/legacy/generated-crud/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml similarity index 100% rename from api/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml rename to api/legacy/generated-crud/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml diff --git a/spec/.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json b/api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json similarity index 100% rename from spec/.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json rename to api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json diff --git a/spec/.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0 (1).json b/api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Database_API_template-1.3.0 (1).json similarity index 100% rename from spec/.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0 (1).json rename to api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Database_API_template-1.3.0 (1).json diff --git a/spec/.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json b/api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json similarity index 100% rename from spec/.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json rename to api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Database_API_template-1.3.0.json diff --git a/spec/.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml b/api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml similarity index 100% rename from spec/.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml rename to api/legacy/generated-crud/gitbook-copies/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml diff --git a/api/readme.txt b/api/readme.txt deleted file mode 100644 index 083ec06..0000000 --- a/api/readme.txt +++ /dev/null @@ -1,15 +0,0 @@ -Digital Registries Building Block API Definitions -This repository holds OpenAPI definitions for Digital Registries BB - one of the building blocks that have been developed by the GovStack expert working groups. - -Each building block API definition must be stored in a json file that is compatible with the OpenAPI 3.0 standard - -Acknowledgement -This specification was prepared by a team comprising Frank Grozel (UNCTAD), Ingmar Vali (UNCTAD), Tambet Artma (Centre of Registers and Information Systems), Saurav Bhattarai (GIZ), Dr Ramkumar (ITU), Rauno Kulla (UNCTAD). - -Status -Current status of the specification is RC.1.3. - -Reference -UNCTAD eRegistrations: https://digitalgovernment.world/ -UNCTAD https://unctad.org/ -Use Cases: https://solutions.dial.community/building_blocks/digital_registries diff --git a/examples/README.md b/examples/README.md index eef9a50..11273dd 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,11 +1,7 @@ -# Software applications that fulfill the behaviours specified by this building block +# Historical implementation examples -List of products: -# 1. Generic Database Builder -License: proprietary license with one time support fee by UNCTAD https://digitalgovernment.world/online-single-windows/ -Test the example BB in Govstack Sandbox here: https://gdb.er4.ext.egovstack.net/ -Register as a user and apply for authorization here: https://er4.ext.egovstack.net/en/services-new/2c92808f83cd620801841e55dc010000 +The examples in this directory demonstrate products and test environments developed against earlier Digital Registries requirements and generated CRUD APIs. +They are retained for migration and implementation research. They do not demonstrate conformance with the 3.0.0-alpha.2 Base Registry Profile. - -NB! Should you know any products that fulfill fully or partly the requirements of this BB, please leave a comment here: https://solutions.dial.community/govstack/issue +Any future example intended as conformance evidence needs to identify the specification and capability profile it implements and be verified by the corresponding conformance tests. diff --git a/examples/eRegistrations/README.md b/examples/eRegistrations/README.md index 0f503fb..f874ecb 100644 --- a/examples/eRegistrations/README.md +++ b/examples/eRegistrations/README.md @@ -1,4 +1,7 @@ -eRegistrations Digital Registries system is a no-code application meant to offer intuitive database/register creation and management functionalities. -Govstack demo instance Open API description: -https://gdb.er3.ext.egovstack.net/swagger/ +# eRegistrations historical example +> This example targets the previous generated CRUD specification. It is not evidence of conformance with the 3.0.0-alpha.2 Base Registry Profile. + +eRegistrations Digital Registries system is a no-code application meant to offer intuitive database/register creation and management functionalities. + +The previously documented public demo endpoint is no longer available. diff --git a/examples/mockoon/README.md b/examples/mockoon/README.md index 7da36b3..8f0d4bc 100644 --- a/examples/mockoon/README.md +++ b/examples/mockoon/README.md @@ -1,5 +1,8 @@ -# Mockoon API -This is a mock application which performs the whole OpenAPI spec for Digital Registries BB +# Mockoon legacy API + +> This mock targets the previous generated CRUD OpenAPI files. It is not a 3.0.0-alpha.2 Registry mock or conformance target. + +This is a mock application for the legacy Digital Registries OpenAPI surface. ## Setup diff --git a/spec/.gitbook/assets/api-families.svg b/spec/.gitbook/assets/api-families.svg new file mode 100644 index 0000000..cb5d616 --- /dev/null +++ b/spec/.gitbook/assets/api-families.svg @@ -0,0 +1,256 @@ + + + + + + + + + + The Digital Registries Building Block + + + Eight capability families with candidate interface bindings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DIGITAL + REGISTRIES + + BUILDING BLOCK + + + + + + + + PROVISIONING + registry as a system + + + OpenAPI + + + + + + + + CONSULTATION + records, read + + + OpenAPI + + + + OGC API + + + + + + + + EVIDENCE + signed attestations, S2S or wallet + + + OpenID4VC + + + + OpenAPI + + + + + + + + WRITE + records, direct or governed + + + OpenAPI + + + + + + + + NOTIFICATION + change events, subscribe, deliver + + + OpenAPI + + + + AsyncAPI + + + + + + + + AGGREGATE DATA + statistics over records + + + OpenAPI + + + + SDMX + + + + + + + + ACCESS TRANSPARENCY + access log to principal + + + OpenAPI + + + + + + + + IDENTITY FEDERATION + sectoral user authentication + + + OpenID Connect + + + + + + The target Base Registry Profile combines Registry Core with Consultation Retrieve. + + + diff --git a/spec/.gitbook/assets/Registries.svg b/spec/.gitbook/assets/historical/Registries-3.0.0-alpha.1.svg similarity index 100% rename from spec/.gitbook/assets/Registries.svg rename to spec/.gitbook/assets/historical/Registries-3.0.0-alpha.1.svg diff --git a/spec/1-version-history/README.md b/spec/1-version-history/README.md index f411f8d..964c815 100644 --- a/spec/1-version-history/README.md +++ b/spec/1-version-history/README.md @@ -1,9 +1,45 @@ --- -description: >- - The version history table describes the major changes to the specifications - between published versions. +description: Major changes to the Digital Registries Building Block specification. --- # 1 Version History -
VersionAuthorsComment
0.7Frank Grozel, Ingmar Vali, Tambet Artma, Saurav Bhattarai, Dr. P. S. Ramkumar, Rauno Kulla.Initial Revision
0.8

Frank Grozel, Ingmar Vali, Tambet Artma, Saurav Bhattarai, Dr. P. S. Ramkumar, Rauno Kulla.

Reviewers:

Neil Roy, Aare Lapõnin, Amy Darling

Applied feedback from technical review
0.9

Ingmar Vali, Sebastian Leidig, Frank Grozel, Tambet Artma

Technical Reviewers: Tony Shannon, Saša Kovačević, Riham Moawad, Riham Fahmi, Aare Laponin, Manish Srivastava, Palab Saha, Surendra Singh Sucharia, Arvind Gupta, Gayatri. P., Shivank Singh Chauhan, Gavin Lyons


Reviewers: Steve Conrad, Wes Brown, Valeria Tafoya

Future consideration section analysis and conversion to requirements.
Fine tuning, and chapter reorganization.
1.0
May 2023

Ingmar Vali

Reviewers: Steve Conrad, Wes Brown, Valeria Tafoya

Final edits to align content to specification template for GovStack 1.0 release
2.0
(previously known as 23Q4)
November 2023
Authors:
Sebastian Leidig, Steve Conrad, Łukasz Ruzicki, Damian Borowiecki, Karolina Kopacz, and Paweł Gesek

Reviewer:
Sebastian Leidig

Editors:
Steve Conrad, Valeria Tafoya
Structural Updates to Cross Cutting Requirements.
Move of section on standards from previously in section 7.1 to section 5.3
Section 8 - Service APIs significantly updated with renamed endpoints and changes to APIs
Publishing of test suite
3.0.0-alpha
June 2026


Coordinators:
Dr. Bimal Kumar, Xilene Siquero, Sebastian Leidig


Authors:
Janet Ngugi, Vivek Rana, Chinenye Ifebirinachi, Ananya Jha, Umang Gupta


Editors:
Ali González-García, and David Higgins

This version reflects the comprehensive upgrade of the specifications aligned to the enhanced scope, architectural patterns, cross-cutting requirements, and interoperability standards introduced in GovStack Architecture 2.1.
+| Version | Contributors | Comment | +|---|---|---| +| 0.7, 0.8, and 0.9 | Initial authors and reviewers listed below | Initial drafts and technical review. | +| 1.0, May 2023 | Ingmar Vali; reviewers Steve Conrad, Wes Brown, and Valeria Tafoya | First GovStack 1.0-aligned release. | +| 2.0, November 2023 | Authors and editors listed below | Updated cross-cutting requirements, service APIs, and the test suite. Breaking change. | +| 3.0.0-alpha.1, June 2026 | Coordinators, authors, and editors listed below | Expanded scope and alignment work for GovStack Architecture 2.x. Public alpha release. | +| 3.0.0-alpha.2, August 2026 | Digital Registries Working Group | Reframed the alpha as a domain-neutral Registry Core with mandatory Consultation Retrieve and additional capability families. Breaking prerelease change. | + +## Contributors by release + +### Versions 0.7 and 0.8 + +Authors: Frank Grozel, Ingmar Vali, Tambet Artma, Saurav Bhattarai, Dr. P. S. Ramkumar, and Rauno Kulla. + +Version 0.8 reviewers: Neil Roy, Aare Lapõnin, and Amy Darling. + +### Version 0.9 + +Authors: Ingmar Vali, Sebastian Leidig, Frank Grozel, and Tambet Artma. + +Technical reviewers: Tony Shannon, Saša Kovačević, Riham Moawad, Riham Fahmi, Aare Laponin, Manish Srivastava, Palab Saha, Surendra Singh Sucharia, Arvind Gupta, Gayatri P., Shivank Singh Chauhan, and Gavin Lyons. + +Reviewers: Steve Conrad, Wes Brown, and Valeria Tafoya. + +### Version 2.0 + +Authors: Sebastian Leidig, Steve Conrad, Łukasz Ruzicki, Damian Borowiecki, Karolina Kopacz, and Paweł Gesek. + +Reviewer: Sebastian Leidig. Editors: Steve Conrad and Valeria Tafoya. + +### Version 3.0.0-alpha.1 + +Coordinators: Dr. Bimal Kumar, Xilene Siquero, and Sebastian Leidig. + +Authors: Janet Ngugi, Vivek Rana, Chinenye Ifebirinachi, Ananya Jha, Umang Gupta, Leonora Smart-Abbey, and Jeremi Joslin. + +Editors: Ali González-García and David Higgins. + +The detailed change record is preserved in the [Release Notes](release-notes.md). diff --git a/spec/1-version-history/release-notes.md b/spec/1-version-history/release-notes.md index a44bc03..7f9e912 100644 --- a/spec/1-version-history/release-notes.md +++ b/spec/1-version-history/release-notes.md @@ -4,7 +4,7 @@ *** -### **v3.0.0-alpha** +### **v3.0.0-alpha.1** _Release date: June 2026_ diff --git a/spec/10-other-resources/10.5-cross-functional-security-and-interoperability-standards.md b/spec/10-other-resources/10.5-cross-functional-security-and-interoperability-standards.md deleted file mode 100644 index 88d8a73..0000000 --- a/spec/10-other-resources/10.5-cross-functional-security-and-interoperability-standards.md +++ /dev/null @@ -1,75 +0,0 @@ -# 10.5 Cross Functional Security and Interoperability Standards - -This section defines the security and interoperability standards that govern the design, implementation, and operation of the Digital Registries Building Block. These standards provide the normative frameworks from which cross-cutting and functional requirements are derived. - -## **10.5.1 NIST Cybersecurity Framework (CSF)** - -The Digital Registries Building Block is governed by the [NIST Cybersecurity Framework (CSF)](https://www.nist.gov/cyberframework) as the primary, overarching security framework. The NIST CSF provides a risk-based, process-oriented approach to cybersecurity and establishes the five core functions used to guide security decisions across the full system lifecycle: - -* Identify

Protect

Detect

Respond

Recover - -All architectural choices, security controls, and operational practices for Digital Registries are expected to be aligned with these functions. - -## **10.5.2 GovStack Digital Platform Security Framework (GIZ / ITU / DIAL)** - -The Digital Registries Building Block adheres to the [GovStack Digital Platform Security Framework](https://docs.google.com/document/d/11Jofvxb418iCvKGzCJuOAvSUFF2eMGowJkn5ooe_k6Y/edit?usp=sharing), jointly developed by GIZ, ITU, and DIAL, which translates international cybersecurity best practices into a GovStack-specific security model. - -When applied to Digital Registries, the framework guides how registry data is protected, accessed, monitored, and governed throughout its lifecycle. In particular, the framework: - -* core security domains,

defines clearly numbered security issues and concerns that can be mapped directly to registry capabilities and integrations.

and shared terminology used consistently across all GovStack Building Blocks. - -It serves as the authoritative reference for interpreting and applying security standards within the GovStack ecosystem. - -## **10.5.3 Controlled Unclassified Information (CUI) assumption** - -For the purpose of security design and risk management, the Digital Registries Building Block assumes that the maximum sensitivity level of information processed is Controlled Unclassified Information (CUI). - -This conservative assumption ensures that registries remain suitable for cross-sector and whole-of-government use, including contexts involving personal, institutional, or sensitive reference data. - -## **10.5.4 NIST SP 800-171 Rev.2 — Protection of CUI** - -In alignment with the CUI assumption, the Digital Registries Building Block follows [NIST Special Publication 800-171 Rev.2](https://csrc.nist.gov/pubs/sp/800/171/r2/upd1/final), which defines security requirements for protecting CUI in non-federal systems and organizations. - -This standard informs the selection and structuring of security controls related to: - -* access control,

identification and authentication,

audit and accountability,

configuration management,

incident response,

system and communications protection. - -## **10.5.5 Interoperability-by-Design principle** - -The Digital Registries Building Block follows an interoperability-by-design standard, whereby systems are designed to interoperate through clearly defined interfaces, shared semantics, and mediated integration, rather than direct point-to-point coupling. - -This principle is grounded in: - -* separation of concerns between building blocks,

use of standard APIs,

and mediation through dedicated integration components. - -This approach aligns with whole-of-government and multi-sector interoperability objectives. - -## **10.5.6 Semantic interoperability standards** - -Semantic interoperability for Digital Registries is governed by the use of standardized terminologies, code sets, and controlled vocabularies, ensuring that data exchanged across systems preserves its meaning and context. - -Where applicable, internationally recognized domain standards (e.g. health, agriculture, population statistics) are used, and local terminologies are mapped to shared reference vocabularies. - -## **10.5.7 Privacy-by-Design and data protection principles** - -The Digital Registries Building Block is guided by privacy-by-design principles, including: - -* data minimization,

purpose limitation,

separation of identity and domain data, and

proportional access to registry information. - -These principles ensure that registry infrastructure remains neutral, reusable, and compliant with diverse legal and regulatory environments. - -## **10.5.8 Whole-of-Government reuse standard** - -Digital Registries are treated as foundational, reusable digital public infrastructure components, intended for cross-sector and whole-of-government use. This standard emphasizes: avoidance of duplicated registries, consistent identification and reference mechanisms, and long-term sustainability of shared digital assets. - -## **10.5.9 API description standard (OpenAPI)** - -The use of OpenAPI provides a clear and machine-readable description of APIs, making it easier for different systems and teams to understand how to connect to each other. - -This common contract supports consistent implementation and enables automation for documentation, testing, validation, and the application of security and access controls across the platform. - -Multiple OpenAPI versions are accepted for the following reasons: - -* OpenAPI 3.0.0 / 3.0.1 are widely adopted and supported by existing government platforms, API gateways, and tooling. Allowing these versions ensures backward compatibility and lowers adoption barriers for countries with existing infrastructure.

OpenAPI 3.1.0 aligns fully with JSON Schema 2020-12, enabling more precise data validation, clearer schema definitions, and improved support for future interoperability needs. It represents the forward-looking and preferred evolution of the specification. - - OpenAPI Version [3.0.0](https://spec.openapis.org/oas/v3.0.0), [3.0.1](https://spec.openapis.org/oas/v3.0.1), [3.1.0](https://spec.openapis.org/oas/v3.1.0). diff --git a/spec/10-other-resources/README.md b/spec/10-other-resources/README.md deleted file mode 100644 index 29b11b3..0000000 --- a/spec/10-other-resources/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -description: >- - This section links to any external documents that may be relevant, such as - standards documents or other descriptions of this Building Block that may be - useful. ---- - -# 10 Other Resources - -## 10.1 Key Decision Log - -[A historical log of key decisions regarding this Building Block](https://govstack-global.atlassian.net/wiki/spaces/GH/pages/183402507/Key+Decision+Log+Digital+Registries). - -## 10.2 Future Considerations - -[A list of topics that may be relevant to future versions of this Building Block](https://govstack-global.atlassian.net/wiki/spaces/GH/pages/183468052/Future+Considerations+Digital+Registries). - -## **10.3** Out-of-Scope Assumptions - -[A list of functions out of the scope of this Building Block](https://govstack-global.atlassian.net/l/cp/pjfzm0LF). - -## **10.4** Schema Examples - -[Schema Examples from Data Structures for this Building Block](https://govstack-global.atlassian.net/l/cp/xmpNSkQt). - -## 10.5 Cross Functional Security and Interoperability Standards - -[This section](10.5-cross-functional-security-and-interoperability-standards.md) defines the security and interoperability standards that govern the design, implementation, and operation of the Digital Registries Building Block. These standards provide the normative frameworks from which cross-cutting and functional requirements are derived. diff --git a/spec/10-workflows.md b/spec/10-workflows.md new file mode 100644 index 0000000..85fdd00 --- /dev/null +++ b/spec/10-workflows.md @@ -0,0 +1,45 @@ +--- +description: Base Registry Profile interaction and outcomes. +--- + +# 10 Workflows + +## 10.1 Retrieve the current permitted Record representation + +This workflow describes externally observable behaviour. It does not prescribe internal services, databases, policy engines, gateways, or deployment topology. + +### Actors + +- **API Consumer:** requests a Record it is authorised to use. +- **Registry implementation:** resolves the current Record revision and returns the permitted representation. +- **Access decision service:** optional component used by the implementation to evaluate access and disclosure policy. + +### Preconditions + +1. The Registry publishes the identity metadata required by Registry Core. +2. The API Consumer has the credentials and request context required by the deployment. +3. The current Record representation identifies its schema, semantic model, revision, lifecycle state, and minimum provenance. +4. The implementation can determine the permitted representation for the API Consumer and request context. + +### Interaction + +1. The API Consumer requests the current representation using a Record Identifier. +2. The Registry authenticates the caller and evaluates access and disclosure policy. +3. If the policy permits access, the Registry resolves the current revision and lifecycle state. +4. The Registry constructs the permitted representation, including the Record context required by Registry Core. +5. The Registry returns the permitted representation or the applicable problem response. + +### Outcomes + +| Condition | Observable outcome | +|---|---| +| Current Record is accessible | Current permitted representation is returned. | +| Consumer has narrower disclosure rights | A valid filtered or redacted representation is returned. | +| Identifier is unknown | The implementation returns its unknown-identifier problem response. | +| Consumer may not learn whether a protected Record exists | The response is indistinguishable under the published contract from the unknown-identifier response, including security-relevant headers and non-Record-specific problem values. Independently generated correlation values may differ, and no Record-specific data is returned. | + +### Postconditions + +- The Record is not modified by the operation. +- The returned representation identifies the same Record Identifier requested by the consumer. +- A successful response identifies the Registry, current revision, lifecycle state, schema, semantic model, Registry Authority, and recording time. diff --git a/spec/11-testing.md b/spec/11-testing.md new file mode 100644 index 0000000..110e4cf --- /dev/null +++ b/spec/11-testing.md @@ -0,0 +1,75 @@ +--- +description: Proposed verification for the Base Registry Profile. +--- + +# 11 Testing + +## 11.1 Test maturity + +The requirements and tests in this release are DRAFT. The scenarios below define deterministic verification intent. No executable conformance suite is published for this release. + +Legacy Cucumber tests under `test/openAPI` exercise the previous generated CRUD interface. They are retained as migration evidence and are not a conformance suite for this release. + +## 11.2 Required fixtures + +A candidate implementation provides non-production fixtures for: + +- machine-readable service metadata; +- two distinct current Records in the same Registry; +- a current Record accessible to two consumers with different disclosure rights; +- evidence of the identifier lifecycle across successive revisions and retired Records; +- an unknown Record Identifier; +- a protected Record whose existence must not be disclosed; and +- each lifecycle state the Registry exposes through Retrieve. + +Testers use synthetic fixtures rather than real personal or confidential data. + +## 11.3 Requirement traceability + +| Requirement | Verification item | Expected result | +|---|---|---| +| `fr-core#req-1` | Inspect machine-readable service metadata and identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, Digital Registries specification version, and CFR version are present. | +| `fr-core#req-2` | Retrieve two distinct Records | Each response includes the Registry Identifier and a different Record Identifier; each identifier pair is unique. | +| `fr-core#req-3` | Inspect the identifier policy and lifecycle evidence | A Record Identifier remains unchanged across revisions and lifecycle states, is not shared, and is not reassigned after retirement. | +| `fr-core#req-4` | Validate a retrieved representation | Schema and semantic-model references resolve, and schema validation succeeds. | +| `fr-core#req-5` | Retrieve fixtures across exposed lifecycle states | Each response identifies the current revision and a lifecycle state permitted by its declared schema. | +| `fr-core#req-6` | Retrieve a known accessible Record | Registry Authority identifier and recording time are present. | +| `fr-consultation#req-1` | Retrieve a known accessible Record | Current permitted representation is returned with required Record context. | +| `fr-consultation#req-2` | Retrieve the same Record as two consumers | Each response contains only the projection permitted to that consumer. | +| `fr-consultation#req-3` | Retrieve unknown and protected identifiers as the same consumer | Status or error category, security-relevant headers, stable problem type or code, response schema, and non-Record-specific problem values match; any differing correlation values are independent of Record existence; neither response contains Record-specific data. | + +The abbreviated references in this table use the full `govstack-bb-digital-registries` namespaces defined in [Functional Requirements](6-functional-requirements.md). + +## 11.4 Behaviour scenarios + +```gherkin +Feature: Retrieve the current permitted Registry Record + + Scenario: Authorised consumer retrieves a current Record + Given a current Record with a stable Record Identifier + And an API Consumer authorised to receive its standard representation + When the consumer retrieves the Record by that identifier + Then the Registry returns the current permitted representation + And the representation identifies its Registry, revision, lifecycle state, schema, semantic model, Registry Authority, and recording time + And the retrieval does not modify the Record + + Scenario: Consumers receive different permitted representations + Given two API Consumers with different disclosure entitlements + When each consumer retrieves the same Record + Then each response contains only the fields and metadata permitted for that consumer + + Scenario: A protected Record cannot be enumerated through errors + Given a consumer that is not authorised to know whether a protected Record exists + And an unknown Record Identifier + When the consumer requests the protected and unknown Record Identifiers + Then both responses use the same status or error category + And both responses use the same security-relevant headers, stable problem type or code, response schema, and non-Record-specific problem values + And any differing correlation values are generated independently of Record existence + And neither response contains Record-specific data +``` + +## 11.5 Evidence retained for audit + +Verification evidence identifies the Digital Registries specification version and the `govstack-cfr-2.1.0` baseline tested. It also includes fixture definitions, requests, responses, schema-validation results, identifier-lifecycle evidence, and a traceability report mapping every evaluated requirement to a pass or fail result. + +No fixed response-time threshold, container technology, administrative user interface, Information Mediator header, or test tool is part of the target Base Registry Profile. diff --git a/spec/12-other-resources/README.md b/spec/12-other-resources/README.md new file mode 100644 index 0000000..68baf34 --- /dev/null +++ b/spec/12-other-resources/README.md @@ -0,0 +1,44 @@ +--- +description: Coverage, decisions, migration material, and references. +--- + +# 12 Other Resources + +## 12.1 Coverage and limitations + +The 3.0.0-alpha.2 specification provides a minimum Registry model and DRAFT requirements. It does not provide a certification-ready API contract. + +| Included in this release | Not specified in this release | +|---|---| +| Registry scope and exclusions | Final capability-discovery format | +| Base Registry Profile | Canonical HTTP path and JSON schema | +| Registry Core DRAFT requirements | Retrieval of historical revisions | +| Consultation Retrieve DRAFT requirements | Optional-family requirements and tests | +| Conceptual external data model | Named multi-family conformance profiles | +| Retrieve workflow and verification intent | Domain-specific semantic models | +| Complete disposition of previous DRS requirements | Jurisdiction-specific governance or legal compliance | + +## 12.2 Specification decisions + +- The specification defines the external service behaviour of a Digital Registries implementation for records under a Registry Authority's declared scope. It does not prescribe a database platform. +- The proposed Base Registry Profile consists of Registry Core plus Consultation Retrieve. +- Retrieve returns a permitted representation and does not imply public or complete-record access. +- List, Search, Record Match, and GIS Query are distinct optional Consultation sub-patterns. +- Additional API families remain informative until each has requirements, a contract, and tests. +- Internal storage, administrative UI, deployment topology, multi-tenancy, and automatic API generation are implementation choices. +- Domain data models are selected and declared by the Registry Authority rather than standardised by the Building Block. +- Authentication protecting Registry APIs is distinct from the optional Identity Federation family. + +## 12.3 Migration and history + +- [Migration from the 3.0.0-alpha.1 Draft](migration-from-3.0.md) records the disposition of every previous DRS requirement. +- [Release Notes](../1-version-history/release-notes.md) preserve detailed historical contributors and changes. +- [Historical Key Decision Log](historical/key-decision-log.md) and [Historical Future Considerations](historical/future-considerations.md) are retained as working-group history. They are not part of conformance for this release. + +The OpenAPI files under `api/legacy/generated-crud/` and Cucumber scenarios under `test/openAPI/` describe the previous generated CRUD interface. They are legacy artifacts and are not service contracts or conformance tests for this release. + +## 12.4 Reference architecture and implementation guidance + +Actors, organisational responsibilities, domain governance, semantic choices, and multi-Building-Block deployment patterns belong in a Registry Reference Architecture or implementation guide. They are useful to adopters but do not alter the technical conformance contract in this specification. + +See [References](references.md) for standards and related GovStack material. diff --git a/spec/12-future-consideration.md b/spec/12-other-resources/historical/future-considerations.md similarity index 99% rename from spec/12-future-consideration.md rename to spec/12-other-resources/historical/future-considerations.md index 07b1b2c..be479a2 100644 --- a/spec/12-future-consideration.md +++ b/spec/12-other-resources/historical/future-considerations.md @@ -1,4 +1,10 @@ -# 12 Future Consideration +--- +description: Archived future-consideration backlog from earlier Digital Registries versions. +--- + +# Historical Future Considerations + +> **Archived and non-normative.** This page preserves an earlier working-group backlog. Statements and proposed requirements on this page are not part of the current specification. 12.1 Integration with a blockchain solution to guarantee the integrity of the data and logs. The function would notice unauthorized changes in data. This option may be available with a fee therefore should be optional. diff --git a/spec/11-key-decision-log.md b/spec/12-other-resources/historical/key-decision-log.md similarity index 98% rename from spec/11-key-decision-log.md rename to spec/12-other-resources/historical/key-decision-log.md index 92ca04e..d5115f8 100644 --- a/spec/11-key-decision-log.md +++ b/spec/12-other-resources/historical/key-decision-log.md @@ -1,4 +1,10 @@ -# 11 Key Decision Log +--- +description: Archived decision discussions from earlier Digital Registries versions. +--- + +# Historical Key Decision Log + +> **Archived and non-normative.** This page preserves decision discussions from earlier Digital Registries versions. It does not define requirements, scope, or conformance for the current specification. * The UNCTAD’s Generic Database Builder (eRegistrations) system will be used as a reference system in describing the functional requirements. * 23.09.2021 - WG meeting, based on review recommendations made by Architecture WG, we decided to add API services or IT-specialists to create/modify/delete registry database schema. @@ -11,7 +17,7 @@ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1. Incorporated in V1 | | |

2. Key Digital Functionalities.

I would add here capability to manage access to the Registry data

|

Yes, see requirement DRS-6

Modifications to be absorbed in this version


Sharing data with others is a function that was added to the requirements. See DRS-33

| -|

2. Key Digital Functionalities.

currently, my impression is that the Registration BB is optimised for entering and processing data and not for retrieval and usage. I see it as a missing capability requirement.

|

Registration BB functionality is described in another document. Pull (read) data functionality in Registration BB improved.


Modifications to be absorbed in this version:

1. add arrows to the drawing to reflect the two-way communication.

See data retrieval API Open API services descriptions for more information.



| +|

2. Key Digital Functionalities.

currently, my impression is that the Registration BB is optimised for entering and processing data and not for retrieval and usage. I see it as a missing capability requirement.

|

Registration BB functionality is described in another document. Pull (read) data functionality in Registration BB improved.


Modifications to be absorbed in this version:

1. add arrows to the drawing to reflect the two-way communication.

See data retrieval API Open API services descriptions for more information.



| |

DRS-2. Foreign keys.

I am not sure, I can understand the way how FK-s suppose to work (see comment below in Appendix 2)

|

Databases in this concept are stored as tables, thus the foreign key works the same as in a structured database. In the Digital Registries user interface it must be possible to open another database by clicking on the ID of one database and all corresponding records from the other database will open. In API, the developers can decide how to use the Foreign key to improve the UX.


Modifications to be absorbed in this version:

We improved the functionality description.

| |

DRS-3

1. does it includes Dropbox option to select from List of Values (LOV)? How can I define List values and how can I attach it to field in a form?

2. Does it includes option for hierarchy of List of Values, where selected value in one LOV defines subset of allowable options in another LOV?

|

1. yes, catalog/select values are used, however this is managed by client UI (Registration BB). Digital registries is storing data/ key of the list element. Catalogs are managed in Registration BB/ other BB.

2. Sub-catalogues function and the control could be added to Registration BB when required by the Use Case. Digital Registries BB contains Enum list validation option.

Modifications acceptable but to be taken up in future version

| |

6.

I was talking about the REST endpoint URL. The URL has a placeholder for version (marked as {version}). I believe it to be the version of the API being called, but the document throughout talks about DB schema version, and no mention of this version being the version of the API. That could create confusions on what the parameter "version" is.

|


Thank you for the clarification. Will be implemented in this version.

The system generates default API method endpoints automatically after each publish of the database schema. A new API service version is generated after each schema publish. Database schema version and API versions are in sync. I hope this clarifies the confusion.

| diff --git a/spec/12-other-resources/migration-from-3.0.md b/spec/12-other-resources/migration-from-3.0.md new file mode 100644 index 0000000..0523f24 --- /dev/null +++ b/spec/12-other-resources/migration-from-3.0.md @@ -0,0 +1,88 @@ +--- +description: Disposition of requirements from the previous 3.0.0-alpha.1 draft. +--- + +# Migration from the 3.0.0-alpha.1 Draft + +## Purpose + +The 3.0.0-alpha.2 revision replaces the previous flat `DRS-1` through `DRS-37` requirement set. This ledger preserves traceability and explains whether each concept is retained, moved, inherited, converted to guidance, or retired. + +The old identifiers are not reused. New DRAFT requirements use the `govstack-bb-digital-registries-fr-*` namespaces. + +The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data#req-7` from RECOMMENDED to REQUIRED. Those elevations are not carried forward. The inherited requirements apply with their `govstack-cfr-2.1.0` classifiers and applicability conditions. + +## Requirement disposition + +| Previous requirement | Disposition | +|---|---| +| DRS-1 Create Registries | Registry identity, authority, classification, and lifecycle metadata inform Registry Core. Registry creation and schema configuration move to optional Provisioning. Storage-profile choices are retired. | +| DRS-2 Multiple Databases | Mandatory multi-database, foreign-key, graph, and UI-navigation behaviour is retired. Relationships belong to the selected semantic model or implementation guidance. | +| DRS-3 Database Schema | Schema declaration and validation are retained conceptually. Schema authoring and field configuration move to optional Provisioning. The fixed field-type and UI-widget catalogue is retired. | +| DRS-4 Publishing and Versioning | Schema lifecycle and compatibility remain relevant to future Provisioning. Schema publication is decoupled from automatic endpoint-version generation. Deletion of old schemas is not carried forward. | +| DRS-5 APIs | Split across Consultation, Write, Notification, and Provisioning. Automatic creation, copying, hiding, and deletion of CRUD endpoints is retired. | +| DRS-6 Authorisation and Access Control | General authentication and access control inherit from GovStack CFR. Policy-based permitted representations are retained in Consultation. RBAC, ABAC, PBAC, consent, and anonymous-role internals are not prescribed. | +| DRS-7 Logging and Auditing | Record revision and provenance inform Registry Core. Principal-facing access history moves to Access Transparency. Generic security logging inherits from CFR. Blockchain is not a conformance mechanism. | +| DRS-8 Personal Data Usage | Access-event concepts move to Access Transparency. The fixed `PersonalDataID` log structure and optional device fingerprint are not retained. | +| DRS-9 Database Views | Saved views may inform optional List or Search. Open-data publication requires an explicit disclosure policy and is not equated with anonymous access. | +| DRS-10 Export Schema | Moves to optional Provisioning. File formats will be defined by an applicable binding or guide. | +| DRS-11 Import Schema | Moves to optional Provisioning. File formats will be defined by an applicable binding or guide. | +| DRS-12 Service Usage Statistics | Generic monitoring inherits from CFR. Administrative analytics are implementation guidance. Logging every search term is not a default requirement. | +| DRS-13 Personal Data Field | Sensitivity and classification metadata remain relevant through CFR and declared schemas. UI-specific field marking is retired. | +| DRS-14 Personal Data Identifier | Stable identifier concepts are retained, while Record, foundational, functional, and domain identifiers are distinguished. Federation behaviour moves to Identity Federation. | +| DRS-15 Secret Field | Classification, encryption, and transport security inherit from CFR. Policy-driven redaction is retained in Consultation. The credit-card and mandatory Information Mediator examples are removed. | +| DRS-16 Read Schema in UI | Machine-readable schema declaration is retained. Administrative UI presentation is implementation guidance. | +| DRS-17 Field Properties and Triggers | Validation constraints inform schemas and optional Provisioning. UI widgets, database relationships, and embedded trigger scripting are implementation choices. | +| DRS-18 Per-Database Encryption Key | Retired. Applications must not need a Registry encryption key to read data. Cryptography, key management, and rotation inherit from CFR. | +| DRS-19 Automated Data Exchange | Change events move to Notification. Cross-system orchestration and mapping tools belong to neighbouring BBs or implementation guidance. | +| DRS-20 Schema Templates | Registry templates and marketplaces are implementation guidance, not interoperability requirements. | +| DRS-21 View Data | Record access moves to Consultation and audit visibility to Access Transparency. Grid, detail, and document views are implementation choices. | +| DRS-22 Edit Data | Record mutation moves to Write. Deletion inherits CFR lifecycle rules where applicable. Editing UI behaviour is implementation guidance. | +| DRS-23 Search Helpers | Filtering, full-text search, and ordering move to optional List and Search sub-patterns. UI behaviour is not retained. | +| DRS-24 Import Data | Bulk import moves to optional Provisioning or an applicable Write profile. CSV and spreadsheet UI behaviour is guidance. | +| DRS-25 Export Data | Bulk export moves to optional Provisioning or Consultation profiles. General portability inherits from CFR. | +| DRS-26 Statistical Queries | Moves to optional Aggregate Data. Dashboards and report designers are implementation guidance. | +| DRS-27 Share Data | Controlled disclosure informs Consultation, Evidence, and consent integration. Email, links, QR codes, watermarks, and anonymous sharing are implementation choices. | +| DRS-28 Create Registry by API | Duplicate of the provisioning aspect of DRS-1. Moves to optional Provisioning. | +| DRS-29 Multiple Registries by API | Duplicate of DRS-2. Mandatory multi-tenancy is retired. | +| DRS-30 Publish Registry by API | Duplicate of DRS-4. Moves to optional Provisioning. | +| DRS-31 Modify APIs | Duplicate of DRS-5. Only abstract capability declaration is retained; generated-API product behaviour is retired. | +| DRS-32 Schema and API Discovery | Machine-readable contract and capability discovery are retained as design goals. Full schema administration is optional Provisioning. The discovery format is not specified in this release. | +| DRS-33 Applicant CRUD | Split across mandatory Consultation Retrieve, optional Consultation sub-patterns, and optional Write. The Applicant CRUD framing is retired. | +| DRS-34 Swagger Service List | Machine-readable service contracts are retained. Swagger UI and live production examples are not conformance requirements. Protocol-native bindings depend on the GovStack framework update. | +| DRS-35 Personal Data Usage API | Duplicate of DRS-8. Moves to Access Transparency and is generalised from a person-specific identifier to a Record Principal. | +| DRS-36 Statistical Queries API | Moves to optional Aggregate Data. | +| DRS-37 Data Owner Access Log | Duplicate of DRS-8 and DRS-35. Moves to Access Transparency and is generalised to a Record Principal. | + +## Replacement index + +The following DRAFT requirements carry forward the interoperability intent that remains in the Base Registry Profile. A previous requirement can map to more than one replacement because the earlier product-oriented clauses combined several concerns. + +| Current target | Principal predecessors | +|---|---| +| `fr-core#req-1` Registry service metadata | DRS-1, DRS-32, DRS-34 | +| `fr-core#req-2` Record identification | DRS-14, DRS-33 | +| `fr-core#req-3` Record Identifier preservation | DRS-14, DRS-33 | +| `fr-core#req-4` Schema and semantic-model identification | DRS-3, DRS-4, DRS-16, DRS-17, DRS-32, DRS-34 | +| `fr-core#req-5` Revision and lifecycle-state identification | DRS-4, DRS-7, DRS-14 | +| `fr-core#req-6` Minimum provenance | DRS-7, DRS-21, DRS-33 | +| `fr-consultation#req-1` Retrieve by identifier | DRS-5, DRS-21, DRS-33 | +| `fr-consultation#req-2` Permitted representation | DRS-6, DRS-15, DRS-21, DRS-27, DRS-33 | +| `fr-consultation#req-3` Protected-existence handling | DRS-6, DRS-15, DRS-33 | + +Concepts moved to capability families without requirements in this release retain no normative force. Provisioning carries DRS-1, DRS-3, DRS-4, DRS-10, DRS-11, DRS-17, DRS-24, DRS-28, and DRS-30. Consultation List or Search carries DRS-9 and DRS-23. Write carries DRS-22 and relevant parts of DRS-24. Notification carries DRS-19. Aggregate Data carries DRS-26 and DRS-36. Access Transparency carries DRS-8, DRS-35, and DRS-37. Evidence and Identity Federation carry the relevant disclosure and identifier-federation aspects of DRS-14 and DRS-27. + +All remaining retired or guidance-only clauses have the exact disposition recorded in the table above. + +## Legacy service contracts and tests + +The previous artifacts are not suitable as contracts for this release: + +- there is no Retrieve-by-Identifier operation; `POST /read` performs search-by-example; +- embedded API versions disagree with filenames and with one another; +- JSON, YAML, documentation, and tests disagree on endpoint names and casing; +- tests send an Information Mediator-specific header while the contracts declare different security metadata; +- examples and fixtures assume one postpartum-care schema; and +- tests do not cover authorisation-sensitive errors, redaction, lifecycle states, revisions, or provenance. + +Their behavioural intent is preserved where useful in the workflow and testing chapters. The old paths and schemas have no conformance effect in this release. diff --git a/spec/12-other-resources/references.md b/spec/12-other-resources/references.md new file mode 100644 index 0000000..0f3cca7 --- /dev/null +++ b/spec/12-other-resources/references.md @@ -0,0 +1,28 @@ +--- +description: Standards and related material relevant to Digital Registries. +--- + +# References + +## GovStack + +- [GovStack Architecture and Cross-Functional Requirements](https://specs.govstack.global/architecture) +- [GovStack Specification Framework](https://specs.govstack.global/architecture/5-specification-framework) + +## Interface and domain standards + +These references inform the capability direction. Only the requirements and canonical service contracts published by this specification determine conformance. + +- [OpenAPI Specification](https://spec.openapis.org/oas/) +- [AsyncAPI Specification 3.0.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0) +- [OGC API Features](https://ogcapi.ogc.org/features/) +- [SDMX Technical Specifications](https://sdmx.org/sdmx_tech_standards/sdmx-technical-specification/) +- [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) +- [OpenID Foundation specifications](https://openid.net/developers/specs/) +- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) +- [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) +- [MOSIP Custom Handle Implementation Guide](https://docs.mosip.io/1.2.0/id-lifecycle-management/identity-issuance/id-repository/custom-handle) + +## Historical material + +The detailed 3.0.0-alpha.1 [Release Notes](../1-version-history/release-notes.md), [Key Decision Log](historical/key-decision-log.md), and [Future Considerations](historical/future-considerations.md) are preserved for traceability. They do not add requirements to this release. diff --git a/spec/2-description-and-scope.md b/spec/2-description-and-scope.md new file mode 100644 index 0000000..cf0a676 --- /dev/null +++ b/spec/2-description-and-scope.md @@ -0,0 +1,76 @@ +--- +description: Purpose, scope, architecture, and exclusions of the Digital Registries Building Block. +--- + +# 2 Description and Scope + +## 2.1 Purpose + +The GovStack Common Terminology defines the general concept of a Registry. A Digital Registries implementation exposes records for which a named authority accepts responsibility within a defined scope. Examples include business registrations, land titles, vehicle registrations, professional licences, programme enrolments, and civil events. + +The Digital Registries Building Block defines the external behaviour that allows applications and other Building Blocks to use those records consistently. It separates that interoperability contract from the implementation's database technology, internal modules, administrative tools, and deployment model. + +In this context, authoritative does not mean that a Record is necessarily complete or error-free. It means that a named Registry Authority is institutionally responsible for maintaining it within the declared scope. + +## 2.2 Scope + +This specification covers: + +- identification and description of a registry; +- stable identification and lifecycle representation of registry records; +- retrieval of the current permitted representation of a record; +- declaration of schemas, semantic models, supported capabilities, and protocol bindings; +- registry-specific revision and provenance information; and +- optional capabilities for provisioning, additional consultation patterns, evidence, writing, notifications, aggregate data, access transparency, and identity federation. + +The same specification can be applied to registries containing records about persons, organisations, places, assets, or events. Domain-specific meaning remains in a declared semantic model rather than being fixed by this Building Block. + +## 2.3 Architectural approach + +The specification separates four concerns: + +1. **Operations** describe what an API consumer can ask the registry to do. +2. **Common metadata** identifies the registry, record, revision, lifecycle state, schema, and provenance relevant to an operation. +3. **Semantic models** define the meaning of domain data. +4. **Bindings** map operations to HTTP, event-driven messaging, or an established industry protocol. + +This separation lets an existing national registry, a commercial product, an open-source platform, or an adaptor conform to the same external contract without sharing an internal architecture. + +## 2.4 Deployment and composition + +An implementation may operate one registry or many registries. It may be centralised or distributed, and may use relational, document, graph, event-sourced, or other storage approaches. These choices do not affect conformance unless they change externally observable behaviour. + +A Registry can operate independently. Where other GovStack Building Blocks are deployed, they can provide complementary capabilities such as citizen-facing intake, workflow orchestration, organisational data exchange, consent management, digital signatures, wallets, identity services, or geospatial processing. + +## 2.5 Boundaries with neighbouring Building Blocks + +A Registry can integrate with neighbouring Building Blocks without transferring its responsibility for authoritative records. + +| Neighbouring Building Block | Boundary | +|---|---| +| Registration | Registration can collect submissions and manage an intake process. The Registry accepts an approved result, a governed change request, or declared state transitions according to its Write profile. | +| Workflow | Workflow coordinates a process across components. The Registry controls which record transitions it accepts and remains responsible for the resulting authoritative state. | +| Information Mediator | Information Mediator can provide cross-organisation addressing, routing, and transport controls. The Registry owns its operations, disclosure decisions, and records. | +| Consent | Consent can provide evidence or policy signals used in a disclosure decision. The Registry enforces the decision applicable to each request and supports other lawful bases where relevant. | +| E-Signature | E-Signature can perform signing operations. The Registry remains responsible for the meaning, issuance, status, and lifecycle of Registry Evidence. | +| Wallet | A Wallet can hold and present credentials issued through Evidence. The Registry remains the source of the asserted facts and is not required to operate a Wallet. | +| Identity | Identity can authenticate users or provide foundational identity services. A sectoral Registry remains responsible for its functional identifiers. Identity Federation does not replace API access control. | +| GIS | GIS can provide geospatial processing and visualisation. A spatial Registry remains responsible for its records and can expose an OGC-aligned GIS Query capability. | + +These integrations are optional unless a selected capability profile states otherwise. + +## 2.6 Out of scope + +This specification does not prescribe: + +- the legal act or governance process that establishes a Registry Authority; +- a universal domain data model; +- a database management system or storage topology; +- a no-code registry builder, administrative web interface, or form designer; +- mandatory multi-tenancy or automatic generation of CRUD APIs; +- the citizen-facing intake and approval process for registration; +- a general-purpose workflow, rules, analytics, reporting, or data-exchange platform; +- a national foundational identifier; or +- jurisdiction-specific legal compliance or security control frameworks. + +Reference architectures and implementation guides may explain how these concerns are addressed in particular domains or jurisdictions without making them part of base Registry conformance. diff --git a/spec/2-description.md b/spec/2-description.md deleted file mode 100644 index e093236..0000000 --- a/spec/2-description.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -description: This section provides context for this Building Block. ---- - -# 2 Description - -The **Digital Registries Building Block (BB)** is a trusted, authoritative service for uniquely identifiable records about entities such as persons, organisations, places, assets, and events. It is designed to act as the **single source of truth** within the GovStack ecosystem, ensuring consistency, reliability, and accountability in the use of registry data. - -The Digital Registries BB enables other Building Blocks, government institutions, and external systems to capture, validate, store, search, distribute, and access registry record in a secure and standardised and uniquely identifiable manner. By abstracting the complexity of underlying databases, it exposes consistent service APIs that allow seamless integration and reuse across multiple domains and applications. This can involve logically assembling a record from multiple underlying databases. The Building Block also ensures audit-able logs of changes to the data and registry structures. - -The Digital Registries BB provides functionality to maintain registry data and administer and create registries. As such it is a **generic, domain-agnostic solution**. It can be applied across multiple sectors and contexts, including but not limited to: - -* Civil registration (births, deaths, marriages, etc.) -* Ownership of property, vehicles, and other assets -* Health and medical information -* Banking and commercial transactions -* Education and qualifications -* Land surveys and manufacturing details - -Given the diversity of such information, this Building Block provides services useful to abstract the structure, linkages, and grouping of information into various records and collections such as financial, legal, medical, social, educational, commercial, etc., as needed. - -The Digital Registries BB works in close coordination with other GovStack components: - -* **Registration BB** – an interface for citizens (applicants) and/or government officials (operators) to manage the life-cycle of claims in a registry. -* **Foundational ID BB** – for uniquely identifying entities. -* **Workflow BB** – for orchestrating business processes tied to registry data. -* **Information Mediator / Consent & Authorisation** – for secure, policy-driven data exchange across organisations. - -The Digital Registries Building Block is an optional Building Block for other GovStack Building Blocks that have the need to store information. Any traditional database platform could be used alone or in combination with Digital Registries Building Block. The Digital Registries Building Block can operate as a standalone service and could be implemented as one centralized instance per domain, containing multiple registries in one instance, or many instances per domain, each database in its own server. - -
diff --git a/spec/3-terminology.md b/spec/3-terminology.md index 98aede1..eabcaab 100644 --- a/spec/3-terminology.md +++ b/spec/3-terminology.md @@ -1,43 +1,31 @@ --- -description: 'Terminology used within this specification:' +description: Terms with a specific meaning in this specification. --- # 3 Terminology -{% hint style="info" %} -We recognise there are common terms across GovStack. We define these [here](https://specs.govstack.global/architecture/2-common-terminology). -{% endhint %} - -In addition the following terms are specific to the Digital Registries Building Block. - -### **Administrator/Analyst** - -The administrator/analyst is responsible for designing, configuring, or modifying the registry, its rules, schemas, workflows, or policies. - -### **Asserter** - -An entity that asserts a claim. The asserter provides information or statements that are to be recorded, verified, or trusted. - -### **Applicant** - -An entity (person, organization, or system) that requests the registration of claims in a registry. The applicant is not yet registered, they are in the process of applying. - -### **Automation** - -A background, database-level process that moves or transforms data within the registry system (e.g., copying, synchronizing, recalculating fields) without direct human intervention. - -### **Operator** - -A registrar or staff of a registrar that processes, reviews, and handles the applicant’s submission. The operator carries out the procedural and system steps. - -### **Registrar** - -An entity (or authority) authorized by the registry governance to receive, validate, and record claims submitted by applicants. - -### **Rules engine** - -A tool transforming business rules relating to a registry, defined by a human analyst, into machine-readable statements. - -### **Trigger** - -A record-level automation. When a trigger event occurs on a record (e.g., insert, update, delete), this trigger logic runs a specified action (validation, notification, field update) automatically. +This specification uses the [GovStack Common Terminology](https://specs.govstack.global/architecture/2-common-terminology). The following terms have a specific meaning for Digital Registries. + +| Term | Definition | +|---|---| +| API Consumer | A system authorised to invoke a Registry service interface. | +| API Family | A coherent group of operations that provides one Registry capability. | +| Authoritative Source | A source for which a named authority accepts responsibility within a declared domain and scope. Authoritative does not imply error-free. | +| Binding | A mapping of abstract operations to a transport or established protocol. | +| Capability Claim | A declaration that an implementation supports a specified API family, sub-pattern, and binding and meets the requirements attached to that claim. | +| Conformance Profile | A defined combination of core requirements and capability claims. | +| Functional Identifier | An identifier issued and lifecycle-managed for a sector-specific purpose, such as a farmer, student, health, or professional identifier. | +| Lifecycle State | The current state of a Record under the vocabulary defined by its declared representation schema. | +| Permitted Representation | The record data and metadata an API consumer is authorised to receive. It may be filtered or redacted and need not contain the complete stored record. | +| Record | The Registry's representation of an entity, place, asset, or event within its declared scope. | +| Record Identifier | A stable identifier assigned to a record within a Registry. | +| Record Principal | A person or organisation with a recognised relationship to a record, such as its subject, owner, title holder, director, or credential holder. | +| Record Revision | A representation of a record at a defined point in its change history. | +| Registry Authority | The institution accountable for the Registry and its declared authoritative scope. | +| Registry Core | Behaviour and metadata required of every conformant Registry implementation. | +| Registry Identifier | A globally unique and stable identifier for a Registry. | +| Registry Operator | The organisation that operates an implementation on behalf of, or as, the Registry Authority. | +| Relying Service | A service that relies on authentication or claims provided through the Identity Federation family. | +| Schema | A machine-readable definition of the structure and validation constraints of records or messages. | +| Semantic Model | The vocabulary and domain meaning of data carried in a Registry record. | +| Sub-pattern | An independently claimable capability within an API family. | diff --git a/spec/4-conformance.md b/spec/4-conformance.md new file mode 100644 index 0000000..53ae15b --- /dev/null +++ b/spec/4-conformance.md @@ -0,0 +1,33 @@ +--- +description: Draft minimum conformance and future capability model for Digital Registries. +--- + +# 4 Conformance + +## 4.1 Requirement maturity + +All requirements in the 3.0.0-alpha.2 specification are classified as DRAFT. They do not create a certification obligation. + +## 4.2 Target Base Registry Profile + +The provisional name for the target minimum conformance claim is the **Base Registry Profile**. Its formal treatment as a profile, and the conditional applicability of additional capabilities, depend on equivalent support in the GovStack Common Requirements Framework. It is not claimable in this alpha because its requirements are DRAFT and no canonical contract or executable test suite is published. + +Once approved, an implementation claiming this profile: + +1. satisfies the Registry Core requirements; +2. implements the Consultation Retrieve sub-pattern; +3. identifies the Digital Registries specification version it implements; +4. returns records under an identified schema and published semantic model; and +5. satisfies the applicable GovStack Cross-Functional Requirements. + +Retrieve does not imply public access or disclosure of the complete stored record. It means that an authorised API consumer can request a record by its stable identifier and receive the current permitted representation or a policy-appropriate error response. + +## 4.3 Future additional capability claims + +After the Common Requirements Framework supports conditional capability applicability, an approved Digital Registries release may allow an implementation to claim additional families and Consultation sub-patterns. Once claimed, every applicable REQUIRED requirement, operation, contract, and test for that capability becomes part of its conformance claim. + +Capabilities described only for architectural context, without approved requirements, contracts, and tests, are not claimable in this release. + +## 4.4 Adaptors + +An existing registry does not need to replace its internal software to conform. An adaptor may translate an existing interface into the operations, metadata, outcomes, and bindings required by a claimed profile. Conformance applies to the resulting external behaviour. diff --git a/spec/4-key-digital-functionalities.md b/spec/4-key-digital-functionalities.md deleted file mode 100644 index 7817d97..0000000 --- a/spec/4-key-digital-functionalities.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -description: >- - Key Digital Functionalities describe the core (required) functions that this - Building Block must be able to perform. ---- - -# 4 Key Digital Functionalities - -The Digital Registries Building Block (BB) provides foundational capabilities to create and manage authoritative registries in a modular, domain-agnostic way. It enables storage, management, and governance of records about entities (persons, organisations, places, assets, events) with standardised CRUD operations, schema and record versioning (audit trails), and interoperability. - -Digital Registries Building Block is a multi-tenant platform where users can create and manage new registry databases. Each registry created within the system automatically generates OpenAPI-compliant services for interoperability. - -The Digital Registry System does not contain data capturing and workflow functionality, however, if a user interface for making new registration requests and processing such requests is needed, then Digital Registries can be combined with other GovStack building blocks (e.g. the [Registration Building Block](https://github.com/GovStackWorkingGroup/bb-registration/tree/1.0-QA)) in a plug-and-play fashion. - -## 4.1 Administrative/Analyst Functions - -The first user of the Building Block is an **Administrator/Analyst** who is building a new registry. The Analyst is the person who is building the new registry database, changing the existing database configuration, or simply administering the API user authorization. The Administrator/analyst is using a web user interface. - -The key functions of the Building Block for Analysts are: - -### Registry lifecycle management - -1. Create a new registry/database (via API or Web UI). -2. Publish, deprecate, or archive registry versions. -3. Create and configure the schema of the register and publish (API or Web UI); -4. Modify schema and publish a new schema/API version with backward-compatibility guidance. -5. Define validation rules, deduplication, and data quality controls. -6. Import/export registry database schema; - -### Data management - -8. Enter, view, and update records (via API or Web UI). -9. Support soft deletion and archival of records. -10. Bulk import/export of data from/to external files. -11. Policy-based masking and redaction for sensitive attributes. -12. Share data with other users via e-mail, or via a unique and secure Uniform Resource Locator (URL) sharing can be field level or record level. - -### Interoperability - -12. Auto-generate REST/GraphQL/OpenAPI services per registry. -13. Integrate with external systems through the Information Mediator BB. -14. Emit domain events (create/update/delete) via Pub/Sub for downstream consumers. - -### Monitoring and analytics - -15. View statistics on registry usage, performance, and data quality. -16. Generate dashboards and administrative reports. -17. Inspect transaction log of registry data operations (API or Web user interface); - -## 4.2 Applicant Functions - -**Applicants** do not access the Registry BB directly. They interact via sectoral applications or other GovStack BBs: - -* Registration BB (UI for data capture, modification, validation). -* Workflow BB (approvals/authorisations). -* Information Mediator BB (secure API mediation). -* Security & Consent BB (authentication, authorisation, consent). - -The key functions of the Building Block for Applicants through those applications are: - -1. Search and query data from the register; -2. Read authoritative records (with policy-driven masking). -3. Request creation, update, or deletion of records where allowed; mediated services invoke Registry APIs on their behalf. -4. Validate record existence in a specified registry (e.g., verify an identifier or ownership). -5. Access statistics when exposed to external users. -6. Subscribe to registry events via mediated services (e.g., External or cross-domain consumers must subscribe to registry events via mediated services exposed through the Information Mediator BB (or an IM-managed Event Gateway); internal consumers within the same trust boundary may subscribe directly to the internal event bus, subject to RBAC/ABAC policy, tenant isolation, and audit). diff --git a/spec/5-api-families/access-transparency.md b/spec/5-api-families/access-transparency.md new file mode 100644 index 0000000..f290001 --- /dev/null +++ b/spec/5-api-families/access-transparency.md @@ -0,0 +1,35 @@ +--- +description: Permitted outward views of access to Registry Records. +--- + +# Access Transparency + +> **Status:** Informative and not claimable in this release. No Access Transparency requirements, entitlement model, event schema, contract, or tests are published. + +## Purpose and applicability + +Access Transparency enables an entitled Record Principal to obtain a permitted view of access to a related Record. It applies where law or policy grants a person or organisation an access-history right. + +A Record Principal can be a subject, owner, title holder, director, beneficiary, or credential holder. The relationship alone does not create a universal entitlement. The adopting jurisdiction defines the applicable right, delegation rules, and period for which the relationship is relevant. + +## Candidate capability areas + +| Area | Outcome | +|---|---| +| Access-history retrieval | Returns permitted entries for a Record and time range. | +| Filtering and pagination | Narrows a potentially large history by declared criteria. | +| Entry interpretation | Describes the accessing organisation or permitted actor category, time, operation, and declared purpose where disclosure allows. | + +## Capability boundary + +Internal security and audit logging is a cross-functional concern. Access Transparency is the outward-facing service derived from permitted audit information. Its representation can omit actor identities or operational details where disclosure would create a privacy, security, or investigation risk. + +A complete profile needs to define entitlement, relationship verification, delegation, outward event vocabulary, retention, correction handling, and disclosure restrictions. + +## Candidate binding + +Synchronous HTTP described by OpenAPI is the candidate general binding. No outward event schema or API contract is selected in this release. + +## Example + +A company director requests the permitted access history for the company's registration Record and sees which organisations consulted it during a defined period. diff --git a/spec/5-api-families/aggregate-data.md b/spec/5-api-families/aggregate-data.md new file mode 100644 index 0000000..155f12c --- /dev/null +++ b/spec/5-api-families/aggregate-data.md @@ -0,0 +1,31 @@ +--- +description: Approved statistics derived from Registry Records. +--- + +# Aggregate Data + +> **Status:** Informative and not claimable in this release. No Aggregate Data requirements, statistical model, contract, or tests are published. + +## Purpose and applicability + +Aggregate Data provides approved statistics derived from Registry Records, such as counts, distributions, or time series. It applies when the Registry itself publishes statistical outputs. In other deployments, a national statistics service or open-data platform can own that responsibility instead. + +## Candidate capability areas + +| Area | Outcome | +|---|---| +| Aggregate query | Returns an approved result for declared dimensions, measures, population, and time scope. | +| Dataset metadata | Describes definitions, units, provenance, release policy, and applicable disclosure controls. | +| Published release | Returns an identified statistical release or revision. | + +## Capability boundary + +Aggregate Data is not Record-level [Consultation](consultation.md), a mandatory analytics engine, or a dashboard. It is not automatically public. Aggregation is not itself anonymisation, and a complete profile needs to address disclosure thresholds, suppression, legal controls, revisions, and indicators of applied protection. + +## Candidate bindings + +Synchronous HTTP described by OpenAPI is a candidate general binding. SDMX is a candidate semantic and interchange standard where outputs need to participate in national or international statistical ecosystems. This release selects neither binding. + +## Example + +A vehicle Registry publishes quarterly counts by vehicle class and region under a statistical release policy that suppresses disclosive small cells. diff --git a/spec/5-api-families/consultation.md b/spec/5-api-families/consultation.md new file mode 100644 index 0000000..6b6faed --- /dev/null +++ b/spec/5-api-families/consultation.md @@ -0,0 +1,39 @@ +--- +description: Read capabilities for permitted Registry information. +--- + +# Consultation + +> **Status:** Retrieve is part of the target Base Registry Profile. List, Search, Record Match, and GIS Query are informative and not claimable in this release. + +## Purpose and applicability + +Consultation enables an authorised API Consumer to obtain a permitted representation of Registry information. It applies when a consumer needs current information from the authoritative source rather than a portable signed assertion or a derived statistic. + +Retrieve is the minimum read capability. It lets a consumer that already knows a Record Identifier obtain the current permitted representation without requiring the Registry to expose enumeration or discovery by personal or domain attributes. + +## Capability patterns + +| Pattern | Outcome | +|---|---| +| `consultation.retrieve` | Returns the current permitted representation of one Record identified by its stable Record Identifier. | +| List | Returns a bounded, paginated collection, optionally filtered by declared attributes. | +| Search | Finds Records using declared attribute predicates. | +| Record Match | Returns possible matching Records with confidence information under a declared matching profile. It does not make an authoritative identity or acceptance decision. | +| GIS Query | Applies spatial predicates to geometric attributes maintained by the Registry. | + +## Capability boundary + +Consultation returns live Registry information. [Evidence](evidence.md) produces a signed assertion with its own validity and status. [Aggregate Data](aggregate-data.md) returns derived statistics rather than Record representations. + +The Retrieve requirements define permitted representations and protected-existence handling. Later List, Search, Match, and GIS Query profiles will need their own disclosure, pagination, query-limit, and result-interpretation rules. + +## Bindings and current coverage + +Synchronous HTTP described by OpenAPI is the candidate general binding. OGC API Features is a candidate additional binding for GIS Query. This release defines only the abstract Retrieve operation and does not publish a canonical HTTP contract. + +See [Functional Requirements](../6-functional-requirements.md#63-consultation-retrieve), [Service Interfaces](../9-service-interfaces.md), [Workflows](../10-workflows.md), and [Testing](../11-testing.md). + +## Example + +A licensing service retrieves the current permitted representation of a business registration by its Record Identifier. The Registry returns only the fields and metadata that service is authorised to receive. diff --git a/spec/5-api-families/evidence.md b/spec/5-api-families/evidence.md new file mode 100644 index 0000000..1a5686a --- /dev/null +++ b/spec/5-api-families/evidence.md @@ -0,0 +1,33 @@ +--- +description: Signed assertions derived from authoritative Registry information. +--- + +# Evidence + +> **Status:** Informative and not claimable in this release. No Evidence requirements, credential profile, contract, or tests are published. + +## Purpose and applicability + +Evidence enables a Registry Authority to issue a signed assertion derived from authoritative Registry information without disclosing the underlying Record. It applies when a fact needs to be portable, independently verifiable, or more narrowly disclosed than a live Record representation. + +## Delivery modes + +| Mode | Outcome | +|---|---| +| Direct attestation | A verifier requests a defined assertion and receives a signed result directly from the issuer. | +| Wallet-mediated credential | The issuer delivers a credential to a holder-controlled wallet for later presentation to a verifier. | +| Status and trust metadata | A verifier obtains the information needed to evaluate issuer trust, proof validity, schema, and current Evidence status. | + +Evidence can express a narrowly scoped fact, including a yes-or-no assertion, or a defined set of claims. A complete profile needs to define claim minimisation, subject binding, validity, status, revocation or supersession, and verifier trust discovery. + +## Capability boundary + +[Consultation](consultation.md) returns current Registry information. Evidence produces a signed assertion whose validity and status are interpreted under an Evidence profile. A Wallet can hold and present a credential but is not the authoritative source. An E-Signature service can perform cryptographic operations, while the Registry Authority remains responsible for the meaning of the assertion. + +## Candidate bindings + +OpenID for Verifiable Credential Issuance and Presentation and the W3C Verifiable Credentials model are candidates for wallet-mediated Evidence. An OpenAPI operation returning a signed attestation is a candidate for direct delivery. This release does not select a credential format or status mechanism. + +## Example + +A professional Registry issues proof that a licence is currently valid without disclosing the practitioner's address or the complete licence Record. diff --git a/spec/5-api-families/identity-federation.md b/spec/5-api-families/identity-federation.md new file mode 100644 index 0000000..6d5be2b --- /dev/null +++ b/spec/5-api-families/identity-federation.md @@ -0,0 +1,29 @@ +--- +description: Sectoral subject authentication and authorised claim release. +--- + +# Identity Federation + +> **Status:** Informative and not claimable in this release. No Identity Federation requirements, claim profile, protocol profile, or tests are published. + +## Purpose and applicability + +Identity Federation enables a sectoral Registry containing Records about people, or a service acting for its authority, to authenticate the person represented by a Registry Record to a Relying Service and release authorised claims. It applies to sector populations such as farmers, students, health-service users, or licensed professionals. + +## Registry-specific concerns + +A profile needs to define the relationship between the authenticated subject and the Registry Record, the lifecycle of the functional identifier, authorised claim release, subject-identifier policy, suspension or termination of the sector relationship, assurance expectations, and issuer topology. + +The functional identifier remains issued and lifecycle-managed by the responsible Registry Authority. OpenID Connect transports authentication and claims; it does not create or govern that identifier. An applicable OpenID Connect binding also follows its rules for issuer-scoped subject identifiers. A later profile can define when pairwise subject identifiers are used to limit correlation. + +## Capability boundary + +Identity Federation is an outward-facing service to a Relying Service. It is separate from authentication and authorisation used to protect Registry APIs. It does not issue or replace foundational identity. An Identity service can provide upstream authentication or identity proofing without taking ownership of the sectoral identifier. + +## Candidate binding + +OpenID Connect Core and Discovery are the candidate protocol specifications. The protocol's existing operations remain authoritative; a Registry profile would add only Registry-specific claims, assurance, subject-binding, and lifecycle rules. + +## Example + +A professional Registry authenticates a licensed practitioner to a continuing-education service and releases an authorised claim that identifies the relevant professional sector. diff --git a/spec/5-api-families/notification.md b/spec/5-api-families/notification.md new file mode 100644 index 0000000..eb8b1be --- /dev/null +++ b/spec/5-api-families/notification.md @@ -0,0 +1,34 @@ +--- +description: Authorised delivery of Registry change events. +--- + +# Notification + +> **Status:** Informative and not claimable in this release. No Notification requirements, event schema, delivery profile, or tests are published. + +## Purpose and applicability + +Notification informs authorised subscribers that Registry state changed. It applies when downstream systems need timely cache invalidation, propagation, or processing and cannot rely on polling Consultation. + +## Candidate capability areas + +| Area | Outcome | +|---|---| +| Subscription | Establishes and manages an authorised interest in declared event types or Records. | +| Filtering | Limits delivery according to an approved scope. | +| Delivery | Sends a change event through the selected binding. | +| Recovery | Supports acknowledgement, retry, deduplication, or replay according to a declared delivery profile. | + +A change event is not necessarily the authoritative Record. A consumer that needs the current permitted representation uses [Consultation](consultation.md). Notification is also distinct from internal security and audit logging. + +## Data and policy considerations + +A complete profile needs to define event identifiers, Registry and Record context, revision references, event types, occurrence and publication time, subscription authorisation, minimisation, ordering, duplicate handling, delivery guarantees, and replay. + +## Candidate bindings + +OpenAPI webhooks are candidates for HTTP push. AsyncAPI is a candidate description format for event-driven transports such as AMQP, MQTT, Kafka, or WebSockets. A Messaging or Information Mediator component can carry events without owning their Registry meaning. + +## Example + +A benefits service subscribes to permitted civil-status changes. After receiving an event, it retrieves the current permitted Record representation before updating its own decision state. diff --git a/spec/5-api-families/provisioning.md b/spec/5-api-families/provisioning.md new file mode 100644 index 0000000..545bcfe --- /dev/null +++ b/spec/5-api-families/provisioning.md @@ -0,0 +1,36 @@ +--- +description: Programmatic configuration and publication of a Registry service. +--- + +# Provisioning + +> **Status:** Informative and not claimable in this release. No Provisioning requirements, contract, or tests are published. + +## Purpose and applicability + +Provisioning configures a Registry service and publishes its externally visible contracts. It is useful where schemas, capabilities, bindings, or controlled bulk data flows are administered programmatically. + +Many authoritative registries do not need this family. Their authority and schema may be established by law, governance, or an operational process outside an API. + +## Candidate capability areas + +| Area | Outcome | +|---|---| +| Metadata administration | Creates or revises the Registry's machine-readable identity and capability declarations through an administrative interface. Registry Core separately requires publication of the current service metadata. | +| Schema lifecycle | Publishes, revises, or retires a representation schema under defined compatibility rules. | +| Interface publication | Declares supported families, sub-patterns, bindings, and access conditions. | +| Bulk transfer | Initiates a controlled import or export of data and metadata. | + +These areas do not require dynamic database creation, a no-code builder, an administrative user interface, or a particular storage engine. Provisioning manages metadata programmatically; it does not make the Core publication requirement optional. It also does not perform the legal or governance act that establishes a Registry Authority. + +## Data and policy considerations + +A complete profile needs to address administrative authorisation, schema compatibility, publication lifecycle, bulk-operation validation, provenance, and failure recovery. Those decisions are not defined in this release. + +## Candidate binding + +Synchronous HTTP described by OpenAPI is a candidate for administrative operations. Long-running bulk work may require an asynchronous job or messaging pattern. No binding is selected in this release. + +## Example + +A programme administrator publishes a revised benefit-record schema and its compatibility metadata before applications begin sending Records that use the revision. diff --git a/spec/5-api-families/write.md b/spec/5-api-families/write.md new file mode 100644 index 0000000..69cbbe7 --- /dev/null +++ b/spec/5-api-families/write.md @@ -0,0 +1,33 @@ +--- +description: Authorised creation and revision of Registry Records. +--- + +# Write + +> **Status:** Informative and not claimable in this release. No Write requirements, transition model, contract, or tests are published. + +## Purpose and applicability + +Write creates a Record or accepts a new authoritative revision. It applies when the Registry exposes mutation to authorised external actors rather than receiving all changes through internal administration or offline processes. + +## Capability patterns + +| Pattern | Outcome | +|---|---| +| Direct write | An actor authorised for the relevant transition commits a final change without a Registry-managed approval workflow. | +| Governed write | A proposed change becomes authoritative only after the required review or approval process. | +| Correction | A subject or authorised actor requests correction through the governed path defined for that Registry. | + +A complete Write profile needs to define accepted transitions, validation, transition-specific authorisation, idempotency, concurrency, provenance, correction, retirement, and any legally defined deletion behaviour. + +## Capability boundary + +The Registry Authority remains responsible for accepted transitions and the resulting authoritative state. A Registration, Workflow, or sector-specific service can own intake and approval and then submit an approved result. Write does not require the Registry to implement a general workflow engine. + +## Candidate binding + +Synchronous HTTP described by OpenAPI is the candidate general binding. Governed or long-running changes may also require an asynchronous status pattern. No binding or job model is selected in this release. + +## Example + +After completing its approval process, a land-transfer service submits the approved ownership change. The land Registry validates the transition and records a new authoritative revision. diff --git a/spec/5-cross-cutting-requirements.md b/spec/5-cross-cutting-requirements.md deleted file mode 100644 index 10eb93e..0000000 --- a/spec/5-cross-cutting-requirements.md +++ /dev/null @@ -1,29 +0,0 @@ -# 5 Cross Functional Requirements - -## **5.1 Requirements** - -The Cross Functional Requirements described in this section are an extension of the Cross Functional Requirements defined in the govstack-cfr-architecture-2-1 [Architecture specification](https://govstack.gitbook.io/specification/v/1-0/architecture-and-nonfunctional-requirements) and govstack-cfr-security-2-1 [Security requirements](https://govstack.gitbook.io/specification/v/1-0/security-requirements). - -This section highlights cross-functional requirements for the Digital Registries Building Block and in addition, describes any supplementary cross cutting to the Architecture Building Block cross-cutting requirements. - -## **5.2 Supplementary/Elevated Cross Cutting Requirements** - -### Comply with high quality data protection principles - -`govstack-bb-registries-cfr-data#req-4` - -[Govstack-cfr-data#req-4](https://specs.govstack.global/architecture/6-cross-functional-requirements/6.6-data#id-4-comply-with-high-quality-data-protection-principles-recommended-extensible-auditable-previously-5). From **\[RECOMMENDED EXTENSIBLE AUDITABLE]** to **\[REQUIRED EXTENSIBLE AUDITABLE].** This was updated due to the level of data being held in Registries mandating this control. - -### Deleting records preserves logical records unless hard deletion is mandated by law - -`govstack-bb-registries-cfr-data#req-7` - -[Govstack-cfr-data#req-7](https://specs.govstack.global/architecture/6-cross-functional-requirements/6.6-data#id-7-deleting-records-preserves-logical-records-unless-hard-deletion-is-mandated-by-law-recommended-rep). From **\[RECOMMENDED REPLACEABLE AUDITABLE]** to **\[REQUIRED REPLACEABLE AUDITABLE].** This was updated due to the level of data being held in Registries mandating this control. - - - -{% hint style="info" %} -There are a number of standards that are especially relevant to Digital Registries that should be considered in an implementation our guidance on these can be found [here](10-other-resources/10.5-cross-functional-security-and-interoperability-standards.md). -{% endhint %} - - diff --git a/spec/5-key-functionalities.md b/spec/5-key-functionalities.md new file mode 100644 index 0000000..8c4d5ae --- /dev/null +++ b/spec/5-key-functionalities.md @@ -0,0 +1,36 @@ +--- +description: Capability families provided by the Digital Registries Building Block. +--- + +# 5 Key Functionalities: API Families + +The Digital Registries Building Block groups its externally visible capabilities into eight families. A family describes an adopter outcome and a coherent trust boundary. It does not prescribe an internal module, product architecture, or transport. + +Only **Consultation Retrieve** is part of the target Base Registry Profile. The other Consultation sub-patterns and seven other families are informative in this release. They are not claimable because they do not yet have approved requirements, contracts, and tests. + +
Digital Registries Building Block capability families
Registry Core provides the shared foundation. The target Base Registry Profile adds Consultation Retrieve.
+ +## 5.1 Family catalogue + +| Family | Adopter outcome | Capability patterns | Status in this release | +|---|---|---|---| +| [Consultation](5-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, List, Search, Record Match, GIS Query | Retrieve is in the target Base Registry Profile; other patterns are informative. | +| [Provisioning](5-api-families/provisioning.md) | Configure a Registry service and publish its externally visible contracts. | Service metadata, schemas, capability publication, bulk transfer | Informative | +| [Evidence](5-api-families/evidence.md) | Obtain a signed assertion derived from authoritative Registry information. | Direct attestation, wallet-mediated credential, status | Informative | +| [Write](5-api-families/write.md) | Create a Record or accept a new authoritative revision. | Direct write, governed write, correction | Informative | +| [Notification](5-api-families/notification.md) | Inform authorised subscribers that Registry state changed. | Subscribe, filter, deliver, retry, replay | Informative | +| [Aggregate Data](5-api-families/aggregate-data.md) | Obtain approved statistics derived from Registry Records. | Aggregate query, dataset metadata, published release | Informative | +| [Access Transparency](5-api-families/access-transparency.md) | Obtain a permitted view of access to a related Record. | Access-history consultation | Informative | +| [Identity Federation](5-api-families/identity-federation.md) | Authenticate a person represented by a sectoral Registry Record to a Relying Service and release authorised claims. | OpenID Provider and claim release | Informative | + +## 5.2 Selecting families + +An adopter selects capabilities from the Registry's institutional responsibilities and consumer needs, not from the feature list of a particular product. Useful questions include: + +- Does the Registry expose only current Records, or also search, mutation, events, evidence, statistics, or subject authentication? +- Which actors can invoke each capability, and what may each actor learn? +- Does the Registry own an approval process, or accept an approved result from another service? +- Does the consumer need live Registry information, a portable proof, or notification that state changed? +- Which sector semantic model and protocol binding fit the participating systems? + +Each family page states its boundary and maturity. Candidate operations and bindings on informative pages are design inputs, not implementation obligations. diff --git a/spec/6-functional-requirements.md b/spec/6-functional-requirements.md index ee655bb..853b75e 100644 --- a/spec/6-functional-requirements.md +++ b/spec/6-functional-requirements.md @@ -1,424 +1,155 @@ --- -description: This section lists the technical capabilities of this Building Block. +description: Draft Registry Core and Consultation Retrieve requirements. --- # 6 Functional Requirements -## Introduction - -This page translates the key functionalities of the Digital Registries Building Block into a clear set of functional requirements. These are the specific capabilities that any implementation of the building block must support to be considered compliant with the GovStack standard - -For technical teams, these requirements serve as a specification for development. For government stakeholders, they provide a checklist to evaluate solutions. - -In short, this list describes what a **Digital Registry** must be able to _do_. It’s the checklist for building or buying a system that meets GovStack standards. - -## 6.1 Administrative/Analyst Functions - -#### **DRS-1:** **Create Registries** - -The Digital Registry BB shall enable authorised users to create new registry schemas, each identified by: (REQUIRED): - -1. Name of the database; -2. A unique short code / name; -3. A structured schema definition as specified in (see DRS-3). -4. Registry metadata (domain, owner department, retention policy, classification Open/Restricted/Confidential) -5. Lifecycle state: Draft-> Published ->Archived -6. Default indexing & Storage profile (row store / column store / document store) - -#### **DRS-2: Multiple Databases** - -* Analysts can create multiple databases in one system instance. - * Links can be: - * **Foreign key** (Strict) - * **Soft link** (UUID reference; no FK constraint) - * **Graph relationship** (NEW: parent-child, many-to-many edges) -* Analysts can configure which databases and which fields are linked. In this document and foreign key function, we consider databases as database tables that can be linked with one another. See the [example illustration](https://github.com/GovStackWorkingGroup/bb-digital-registries/blob/23Q4/spec/.gitbook/assets/Database%20Foreign%20key.png). - * **User story**: As a user, I can browse database content (Data) in the user interface and when databases are linked, then I can click and move from one database/table to another where the corresponding linked data will open in the user interface. -* In the Digital Registries Data user interface, it should be possible to open another database by clicking on the record ID in one database and all corresponding records from the other Database will open. -* It is required to have at least two levels of IDs (database ID and field ID) to link the databases. See the example API in [Appendix 2](https://github.com/GovStackWorkingGroup/bb-digital-registries/blob/23Q4/spec/.gitbook/assets/appendix2.json). - * **Example**: In one registry database we store information about Mother and Child records. In the second registry database, we store information about payments made for the mother. The system must enable a foreign key link between the payment database to the Mother and child record database. Users can click in the payment database record user interface to the Mother ID field and the system user interface should open the corresponding record in the Mother and Child database. (REQUIRED) -* **Reference Integrity Rules**: - * Cascade delete - * Restrict delete - * Orphan tolerance - -#### **DRS-3: Database Schema** - -* Analysts have the option to add fields to the database schema. Fields of the database must contain at least the following elements (REQUIRED): - - 1. Field name; - 2. Field type, at least with the following types: - 1. Text; - 2. Number; - 3. Boolean; - 4. Date/time; - 5. Date; - 6. Time; - 7. File (pdf, doc, etc.). File extensions/types must be configurable; - 8. List/Array/Edit grid (sub-table/array of values inside a field); - 9. JSON object / Block container (optional, to group fields visually); - 10. List of Values/Catalog (holding value and key). - 11. Database/Cluster encoding UTF-8 for multi language support (Optional) - 12. GeoPoint (lat/long) (optional) - 13. GeoShape (polygon, boundary)(optional) - - 3\. Field properties (see more in DRS-17) - -#### **DRS-4:** **Publishing and Versioning** - -* Analysts have the option to publish the database. Publishing will reveal the database to users. (REQUIRED) -* Publish uses versioning. Each publish request creates a new version of the database schema and API services. -* Old database schemas must be made available to the users. -* Data stored in the old database versions must be usable in old versions and in new versions. -* Analysts can delete database schema versions. Same version API services must be deleted at the same time. -* Change impact analysis: - * Breaking changes identified automatically - * Warnings shown to analyst - -#### **DRS-5: APIs** - -* Analysts must be able to configure the API services per registry database. (REQUIRED) - * The system automatically creates API services to: - * create data. - * read data. - * update data. - * delete data. - * Bulk operations (batch create/update/delete) - * validate data (if exists). - * update or create data. - * archive data - * Schema Introspection (replies with the schema (tables/fields/types/relations) in a machine-readable form) -* Analysts can hide/disable API services. -* Analysts can delete API services. -* Analysts can copy API services. -* Analysts can create view (Read data) custom API services. -* Field-level masking applied dynamically (Optional) (DRS-9) -* Subscription API (event-based) -* An analyst must be able to mark a field as secret (DRS-15) -* An analyst must be able to mark a field as PersonalDataID (DRS-14) -* The system generates the API data structure from the dynamic database structure automatically each time a publish is done. - -#### **DRS-6: Authorization and Access Control** - -* Authorization to (REQUIRED) - - 1. create and manage databases. - 2. API usage per service, per record, per data field. - 3. access to DATA. - - Analysts have the option to manage user rights of a database and data via API and via a user interface. -* RBAC (roles) -* ABAC (attributes) -* PBAC (policy-based access control) -* Consent-based access -* **Delegated access** (guardian, parent, representative) -* **Cross-registry access templates** -* **Data minimization rules** (only minimum required fields returned) -* **Condition-based dynamic restrictions** Example: Show fields only if “CaseStatus=APPROVED” -* "Any logged-in user" role must be available -* "Anonymous" user role must be available -* Attribute Based Access Control (ABAC) logic could be used (API, Schema, data fields, record filter, users) -* Per user, per group of users option must be available. - * Group is a set of users in a role - * Role is a set of rights - -#### **DRS-7: Logging and Auditing** - -1. The system must log all data processing in the database. (REQUIRED) - 1. Schema changes must be logged - 2. Data processing (Create, Read, Update, Delete) must be logged - 3. Logs must be visible and searchable to the Analyst via the User Interface - 4. Every data owner (e.g. physical person) has the option to see who has processed his/her data (PersonalData). The function is a standard function for all registries ([DRS-14 API example](https://github.com/GovStackWorkingGroup/bb-digital-registries/blob/23Q4/api/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json)) -2. Change logs are protected with the highest level of integrity (chaining of logs) -3. Database logs could be logged with an external blockchain for additional security (optional) - -#### **DRS-8: Personal Data usage. (REQUIRED)** - -1. The System must automatically store all data read requests and store these in the log table. - * Covers data read events via User Interface and via APIs - * Personal Data logs are stored with PersonalData data tag, storing at least the following information. - * Log ID - * Data record ID - * Field ID - * PersonalDataID (unique and unchangeable identifier of a person) - * Reader ID- who read the data - * Reader name- name or initial of a person - * When - the moment when the Personal Data was read - * The Personal Data report is visible only for Analysts to see all data read logs and Data Owners (physical persons) to see their own personal data usage log. Input is PersonalDataID field - * PersonalData report is usable as an API service (read) - * System has API for PersonalData reports. API is per registry(database) - * System must log Personal Data log read events to the log table. - * Legal justification (if required by law) - * Consent reference (if applicable) - * Data viewer’s role, org, location, Device fingerprint (optional) - -#### **DRS-9: Analysts must be able to create views of a database. (OPTIONAL)** - -* View is a selection of data from a database -* View can be opened as OPEN DATA (anonymous user) -* View can be created, and it can be as a base for an API service (Custom API) -* View is not for changing or deleting data, only for reading -* View rights are managed by the user rights management system - -#### **DRS-10** - -The option export database schema to JSON/YAML file, (optional: XLS file format) (REQUIRED) - -#### **DRS-11** - -The option to import database schema from JSON/YAML file. (REQUIRED); The option to import database schema from XLS file. (OPTIONAL) - -#### **DRS-12** - -* Service usage statistics (OPTIONAL) - * System must record all API service usage information. - * System must record all searches made in the Registry User Interface and via APIs. - -#### **DRS-13** - -* An analyst must be able to mark a field as PersonalData log object (This field contains personal data). (OPTIONAL) - -#### **DRS-14** - -An analyst must be able to mark a field as PersonalDataID. This is the data owner’s ID. (OPTIONAL) - -* Multiple identifiers (national ID, passport, local ID) -* Identifier validation rules -* Identifier linking to external registries -* Immutable identifier enforcement - -#### **DRS-15** - -An analyst must be able to mark a field as secret - -* This field contains secret data (credit card number). E.g. secret data (card data) must be encrypted while at REST. -* Information in transit between the Building Blocks is secured with encryption. Information in Transit is described and governed by Information Mediator Building Block. (REQUIRED) - -#### **DRS-16** +## 6.1 Reading the requirements -* Analyst has the option to read database schema in the web User Interface. (REQUIRED) +This release contains only requirements that support the target Base Registry Profile. Additional families are described in [Key Functionalities](5-key-functionalities.md) but have no requirements or conformance effect in this release. -#### **DRS-17** +Each requirement follows the GovStack Requirements Model. `DRAFT` means that the requirement is available for review but is not included in certification. Requirement identifiers are permanently reserved even while the requirement is DRAFT. -* Analyst has capabilities to configure database field properties (REQUIRED) - 1. API-related field properties - 1. Validation options: required, unique, max, min - 2. blinded/encrypted (DRS-15, DRS-22) - 2. User Interface related field properties: - * field mask, format - * read-only - * personal data - * enum list selection - * blinded/encrypted (DRS-22) - * multiple value/array. User can add more values (e.g. multi select from catalog list) to the same field. Multiple values are - * array type field - * validation options- Required, Unique, max, min - * Foreign keys (to link other databases in the same ecosystem). See the example schema in [Appendix 2](https://github.com/GovStackWorkingGroup/bb-digital-registries/blob/23Q4/spec/.gitbook/assets/appendix2.json) - * Triggers to automate field content-related actions - * create IDs - * merge fields - * add prefix - * suffix - * conditional logic - * trigger will be activated if certain condition(s) are true - * transform-upper/lower case/ javascript) - * Triggers are automated when a record is created/changed. A trigger is a record-level automation +## 6.2 Registry Core -#### **DRS-18** +Registry Core requirements apply globally rather than to one Key Functionality. -Analyst has the capability to add an encryption key per database. (REQUIRED) +### #1 Publish Registry service metadata -* Encryption key is used to encrypt and decrypt data (DRS-17). -* Encryption key can be used by applications to read encrypted data. Each database has a unique encryption key defined by the analyst. -* Encryption key is blinded in the User Interface. -* If applications want to read encrypted data via API they must know the encryption key. Data is decrypted in the user interface. +`govstack-bb-digital-registries-fr-core#req-1` -#### **DRS-19** +`DRAFT EXTENSIBLE AUDITABLE` -Analyst has the capabilities to automate data exchange between databases internally and externally via API. (REQUIRED) +An implementation publishes machine-readable service metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, the Digital Registries specification version, and the GovStack CFR version it implements. -1. Automation is triggered automatically after a pre-configured time interval as a loop (finishes when all corresponding records have been processed). -2. Automation processes one record at a time. -3. Automation has configurable conditions (business rules in Rules Engine). E.g. IF field A = 123 then true. Conditions can be grouped with AND and OR operators. -4. Automation is configured by mapping (input, output) registry data fields to: - 1. another database in the same instance. - 2. API in an external database. -5. Mapping involves: - 1. query part (input) - 2. answer part (output) -6. Webhook triggers (Multi-Registry Orchestration ) +**Purpose:** An adopter can determine which Registry and authority stand behind a service and which complete set of requirements applies. -Mapping can be done from many to one and one to many. Mapping may have a transformation option to convert data to another format. E.g. est->EST; Expected outcome: Automation can be activated automatically when certain conditions are true and the system sends data to another database or to an external API. +**Prerequisite:** The Registry Authority and authoritative scope have been established by the adopting organisation. -#### **DRS-20** +**Verification:** Inspect the published service metadata, validate that all required values are present, and review evidence that the Registry Identifier is not shared with another Registry or changed between service revisions. -Analyst may have capabilities to use database schema templates so that the registry creation is faster. (OPTIONAL) +### #2 Identify each returned Record -1. Schema templates can be shared in the same instance (internal marketplace). -2. Schema templates can be shared in a marketplace. -3. Schema templates can be imported and exported. -4. Full registry + schema + views + API configs -5. Domain templates: Health Registry, Business Registry, Farmer Registry (Optional) -6. Versioned template repository +`govstack-bb-digital-registries-fr-core#req-2` -#### **DRS-21** +`DRAFT EXTENSIBLE OBSERVABLE` -Analyst has a view to see all data in the registry. (REQUIRED) +Every returned Record representation includes the Registry Identifier and a Record Identifier that is unique within that Registry. Together, the two identifiers uniquely identify the Record. -1. Two main views: - 1. Main registry records grid view. - 2. Record detail view. -2. See data; -3. See documents(open if image, download if other type); -4. Data log view (changes (create, update, delete). Data before and after). -5. Data read view (information about who has looked at/exported the data). Data and data reader information is stored in the log registry. +**Purpose:** Consumers can distinguish Records from different Registries and refer to one Record without depending on mutable domain attributes. -#### **DRS-22** +**Prerequisite:** A Record has been accepted into the Registry. -Analyst has a view to edit data in the registry. (REQUIRED) Two main views: +**Verification:** Retrieve two distinct Record fixtures and verify that each response carries the expected Registry Identifier and a different Record Identifier. -1. Main grid (inline editing). -2. Detail record edit view: - 1. Edit data; - 2. Remove/add documents (upload). - 3. blinded/encrypted +### #3 Preserve Record Identifiers -Analyst has option to delete data in the registry. All data changes are logged. +`govstack-bb-digital-registries-fr-core#req-3` -#### **DRS-23** +`DRAFT EXTENSIBLE AUDITABLE` -Analyst can use additional functions to simplify data searching (REQUIRED) +An implementation keeps a Record Identifier unchanged throughout that Record's lifecycle and revisions and never reassigns the identifier to a different Record. -* Filtering by search criteria by field content. -* Full-text data search. -* Order by each data field. +**Purpose:** A Record reference remains unambiguous after changes, retirement, archival, or deletion. -#### **DRS-24** +**Prerequisite:** The implementation has a documented Record Identifier lifecycle policy. -Import data to the registry. Analyst has the option to import information into the database. Import formats are: JSON, CSV, XLS. (REQUIRED) +**Verification:** Review the identifier policy and evidence showing that successive revisions retain the same identifier, distinct Records do not share an identifier, and retired identifiers are not returned to the allocation pool. -#### **DRS-25** +### #4 Identify the Record schema and semantic model -Export data from the registry. Analyst has the option to export selected/filtered data from a registry to CSV/XLS, JSON. (REQUIRED) +`govstack-bb-digital-registries-fr-core#req-4` -#### **DRS-26** +`DRAFT EXTENSIBLE OBSERVABLE` -Statistical queries. The system should have the ability to (REQUIRED): +Every returned Record representation identifies a resolvable machine-readable schema and the published semantic model that govern its domain data. -1. Produce standard statistical reports - 1. System must show statistics of all registered items in the registry, with various criteria for filtering. For example: - 1. Details of registered people - 2. Details of registered services - 3. Time series: Change in registration of people/services over time - 4. Details of change to data elements (audit logs) - 2. Generate customizable reports based on the fields registered in the registry. -2. Allow the analyst/user to analyze data collected in the system in various ways: - 1. (Option) Develop functionality to allow custom dashboards for analysts to analyze data within databases. - 2. Provide APIs for extracting data from databases to analyze in external data analytics systems (e.g. Tableau). +**Purpose:** Consumers can validate the structure of a representation and interpret its domain meaning without knowledge of the implementation's internal storage. -#### **DRS-27** +**Prerequisite:** The Registry Authority has selected the applicable schema and semantic model. -Users can share data with other users. Share data with other users via e-mail, or via a unique and secure URL. Sharing must be at a record level and field level. Data sharing can be turned off in the authorization module. Data can be shared with anonymous users. The data shared with anonymous users is Open Data. (REQUIRED) +**Verification:** Retrieve a Record, resolve the declared schema, validate the representation, and resolve the semantic-model identifier to its published definition. -1. Time-bound secure links -2. Consent-required links -3. Role-restricted link sharing -4. QR code sharing -5. Download watermarking -6. View-only mode (no export) +### #5 Identify the current revision and lifecycle state -#### **DRS-28** +`govstack-bb-digital-registries-fr-core#req-5` -Developer has the option to create a new registry database by sending data via API (REQUIRED). Developer is a user who is using API interface. +`DRAFT EXTENSIBLE OBSERVABLE` -1. Name of the database; -2. A short name; -3. Schema of the database (see DRS-3). +Every returned Record representation identifies its current revision and a lifecycle state permitted by the representation's declared schema. -#### **DRS-29** +**Purpose:** Consumers can distinguish the current representation from earlier revisions and interpret its declared state. -Developer can create multiple registry databases into one system instance. (REQUIRED) +**Prerequisite:** The selected representation schema defines the supported lifecycle-state vocabulary. -#### **DRS-30** +**Verification:** Retrieve fixtures in each lifecycle state exposed through Consultation, validate each state against the declared schema, and verify that each response identifies a current revision. -Developer has the option to publish the database. Publishing will reveal the database to users. (REQUIRED) +### #6 Provide minimum Record provenance -#### **DRS-31** +`govstack-bb-digital-registries-fr-core#req-6` -Developer must be able to modify API services per registry database. (REQUIRED) +`DRAFT EXTENSIBLE OBSERVABLE` -1. The system generates the API data structure from the dynamic database structure automatically each time a publish is done. -2. The system automatically creates API services to: - 1. create data; - 2. read data; - 3. update data; - 4. delete data; - 5. validate data (if exists); - 6. update or create data. -3. Developer can hide API services; -4. Developer can delete API services; -5. Developer can copy API services; -6. Developer can create custom API services. +Every returned Record representation identifies the Registry Authority as the responsible source and provides the time at which the current revision was recorded. -#### **DRS-32** +**Purpose:** A consumer can assess the institutional source and currency of the authoritative information. -Developer has the option to read database schema via API. Developer has the option to read the list API services available per Database. (REQUIRED) +**Prerequisite:** The Registry captures provenance for each accepted revision. -## 6.2 Applicant Functions +**Verification:** Retrieve a Record and verify that the representation contains the Registry Authority identifier and recording time. Additional protected provenance details are outside this minimum requirement. -#### **DRS-33** +## 6.3 Consultation Retrieve -Building Block must enable client systems to process (CRUD) the database records via Open API services. (REQUIRED) +The following requirements link to the Consultation Key Functionality intended for the Base Registry Profile. -* Applicant can search data -* Applicant can create data -* Applicant can read data -* Applicant can update data -* Applicant can delete data -* Applicant can create or update data. +### #1 Retrieve the current Record by identifier -Building Block authorizes client systems and users to process data +`govstack-bb-digital-registries-fr-consultation#req-1` -#### **DRS-34** +`DRAFT EXTENSIBLE OBSERVABLE` -Building Block has the Open API service list (Swagger) to visualize all API services and API service versions. (REQUIRED) +`KF: Consultation` -Client systems must be able to see all API service descriptions including: +Given a valid Record Identifier and an authorised request, an implementation returns the current permitted representation of that Record without modifying the Record. -* Description of each field. -* Example data of each field. +**Purpose:** An API consumer that already knows a Record Identifier can obtain authoritative Registry information without using search or enumeration. -If possible then the example must be real so that whoever is looking at the API specifications can test the example data in the service (try it). +**Prerequisite:** An authorised API consumer and an accessible Record fixture exist. -#### **DRS-35** +**Verification:** Retrieve a known Record by identifier, verify the Registry and Record identifiers, current revision, lifecycle state, schema, semantic model, minimum provenance, and permitted domain data, and confirm that a subsequent Retrieve returns the same revision when no intervening change occurred. -System has an API for PersonalData usage report. (REQUIRED) +### #2 Apply disclosure rules to the returned representation -1. API input must be configurable by the analyst. Input must be a unique identifier of the data owner(e.g. personal identification number) -2. If the registry database schema is designed to store personal data then the analyst must be able to link the personal data to the owner of personal data (e.g. citizen). +`govstack-bb-digital-registries-fr-consultation#req-2` -#### **DRS-36** +`DRAFT EXTENSIBLE OBSERVABLE` -Statistical queries via API. (OPTIONAL) +`KF: Consultation` -1. System should make data accessible through the API - 1. Registration Data - 2. Program Data -2. API should allow querying data with multiple parameters - 1. Date, time ranges - 2. Registered Program -3. Only authorized data should be available through the API. +An implementation returns only the Record fields and metadata permitted for the authenticated API consumer and request context. -#### **DRS-37** +**Purpose:** Retrieve does not become an entitlement to the complete stored Record. -Using viewing event logs- every data owner has the right to see who has looked at their personal data. (REQUIRED) +**Prerequisite:** At least two test consumers have different disclosure entitlements for the same Record. -1. Data owner is a physical person whose personal data is stored in the registry -2. Data owner has the right to access data reading/processing event logs of the personal data they own. Personal data in a registry is marked accordingly (PersonalData) by the analyst -3. PersonalData logs are visible via API or via User Interface (PersonalData report). +**Verification:** Retrieve the same Record using both consumers and verify that each receives only its permitted projection and that omitted values are not exposed through errors or metadata returned to the consumer. -## Building Block Components +### #3 Hide protected Record existence -The Building Block has a user interface to query and consult the registry data but in most cases, the Applicants are using the end client applications like Registration Building Block to access the registry. Any Building Block can query data from Digital Registries Building Block via APIs if authorization is given. +`govstack-bb-digital-registries-fr-consultation#req-3` -![Digital registries functional components](<.gitbook/assets/image3 (1) (1).png>) +`DRAFT EXTENSIBLE OBSERVABLE` + +`KF: Consultation` + +For an API consumer that is not authorised to learn whether a protected Record exists, an implementation returns an error response that is indistinguishable under the published Retrieve contract from the response for an unknown Record Identifier. This includes the same status or error category, security-relevant headers, stable problem type or code, response schema, and non-Record-specific problem values. Per-request correlation values may differ when they are generated independently of Record existence. The response contains no Record-specific data. + +**Purpose:** An unauthorised consumer cannot enumerate protected Record Identifiers through the Retrieve error contract. + +**Prerequisite:** An unknown Record Identifier and a protected Record Identifier are available as test fixtures for the same consumer. + +**Verification:** Retrieve both identifiers as that consumer and compare the status or error category, security-relevant headers, problem type or code, response schema, non-Record-specific problem values, and data fields. Verify that any differing correlation values are independent of Record existence and that neither response exposes Record-specific data. + +## 6.4 Deferred capabilities + +No requirement identifier is assigned to Provisioning, additional Consultation sub-patterns, Evidence, Write, Notification, Aggregate Data, Access Transparency, or Identity Federation in this release. diff --git a/spec/7-cross-functional-requirements.md b/spec/7-cross-functional-requirements.md new file mode 100644 index 0000000..3a8e5c7 --- /dev/null +++ b/spec/7-cross-functional-requirements.md @@ -0,0 +1,20 @@ +--- +description: Cross-functional requirements inherited by Digital Registries. +--- + +# 7 Cross-Functional Requirements + +`govstack-bb-digital-registries-3.0.0-alpha.2 extends govstack-cfr-2.1.0` + +Every requirement from `govstack-cfr-2.1.0` applies according to its classifier and any applicability condition stated in that requirement, without being repeated in this specification. + +The inherited requirements cover, among other concerns: + +- authentication, authorisation, transport security, encryption, secrets, and security logging; +- API documentation, observability, availability, deployment, and maintainability; +- Unicode, timestamps, data formats, validation, portability, provenance, retention, and sensitivity classification; and +- use and publication of appropriate domain schemas and standards. + +This release defines no additional Registry-specific cross-functional requirement. In particular, it does not impose a jurisdiction-specific security framework, a universal legal basis for data processing, or one deletion policy on every type of Registry. + +Registry-specific behaviour that produces direct business value, such as the permitted representation returned by Consultation, remains in [Functional Requirements](6-functional-requirements.md) rather than being hidden in this chapter. diff --git a/spec/7-data-structures.md b/spec/7-data-structures.md deleted file mode 100644 index 854fd36..0000000 --- a/spec/7-data-structures.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -description: >- - This section provides information on the core data structures/data models that - are used by this Building Block. ---- - -# 7 Data Structures - -## 7.1 Resource Model - -The resource model shows the relationship between data objects that are used by this Building Block. - -```mermaid -erDiagram - DATABASE||--o{ DATA: has - DATABASE { - int id - varchar name - json schema - numeric version } - DATA ||--|{ AUDIT-LOG: creates - DATA { - int id - varchar registry-number - varchar field-type - varchar value - } - AUDIT-LOG { - varchar old-value - varchar new-value } - DATABASE ||--|{ SCHEMA: has - SCHEMA { - int id - varchar path } - SCHEMA ||--|{ DATA: contains -``` - -## 7.2 Data Structures - -The Data Structures provide detail for the Resource Model defined above. This section will list the core/required fields for each resource. - -### 7.2.1 Minimum Required Data - -**Description:** The Data Structures can be extended for a particular use case, but they must always contain, at the minimum, the fields defined here. - -**Fields:** - -
NameTypeDescriptionNotes
Database IDintegerUnique identifier of a database.Required
Database namevarcharName that will define the database content. Name is public.Required
Schema IDintegerDatabase schema IDRequired
Database schemajson objectDatabase schema. See example in Chapters 7.3.1 and 7.3.2.Required
VersionnumericDatabase version. Each change in schema will produce the next version of the database and API services.Required
Data IDintegerData element unique identifier.Required
Registry numbervarcharAdditional registry identifier. Unique identifier in the registry.Required
Field typevarcharField type: datetime, date, boolean, text, number, file.Required
Field valuedatetime, date, boolean, text, numberField value, data stored in the field.Required
Audit log old valuedatetime, date, boolean, text, numberField value before change.Required
Audit log new valuedatetime, date, boolean, text, numberField value after the change.Required
diff --git a/spec/8-data-structures.md b/spec/8-data-structures.md new file mode 100644 index 0000000..7387ce8 --- /dev/null +++ b/spec/8-data-structures.md @@ -0,0 +1,90 @@ +--- +description: Conceptual external data model for the Base Registry Profile. +--- + +# 8 Data Structures + +## 8.1 Scope + +This chapter describes the information that crosses the Base Registry Profile boundary. It does not prescribe database tables, field storage, entity-attribute-value structures, or an internal audit-log implementation. + +The names below are conceptual. This release does not define exact JSON property names or a canonical schema. + +## 8.2 Conceptual model + +```mermaid +erDiagram + REGISTRY ||--o{ RECORD : maintains + SCHEMA ||--o{ RECORD_REPRESENTATION : governs + RECORD ||--|{ RECORD_REVISION : has + RECORD_REVISION ||--o{ RECORD_REPRESENTATION : permits + + REGISTRY { + string registryIdentifier + string name + string authority + string specificationVersion + string cfrVersion + } + RECORD { + string recordIdentifier + } + RECORD_REVISION { + string revisionIdentifier + string lifecycleState + datetime recordedAt + string authorityIdentifier + } + RECORD_REPRESENTATION { + string registryIdentifier + string recordIdentifier + string revisionIdentifier + string lifecycleState + string schemaReference + string semanticModelReference + string authorityIdentifier + datetime recordedAt + object domainData + } +``` + +## 8.3 Registry metadata + +| Concept | Purpose | +|---|---| +| Registry Identifier | Globally unique and stable identifier for the Registry. | +| Registry Name | Human-readable name used by adopters and consumers. | +| Registry Authority | Institution accountable for the declared authoritative scope. | +| Specification Version | Digital Registries specification implemented by the service. | +| CFR Version | GovStack Common Requirements Framework version implemented by the service. | + +The capability-discovery format is not specified in this release. + +## 8.4 Record representation + +| Concept | Purpose | +|---|---| +| Registry Identifier | Identifies the Registry that returned the representation. | +| Record Identifier | Stable reference to the Record within the Registry. | +| Revision Identifier | Identifies the current revision represented by the response. | +| Lifecycle State | State permitted by the declared representation schema. | +| Schema Reference | Resolves to the machine-readable structure used to validate domain data. | +| Semantic Model Reference | Identifies the vocabulary or domain model used to interpret the data. | +| Minimum Provenance | Identifies the Registry Authority as the responsible source and the time at which the current revision was recorded. | +| Domain Data | The authorised projection of domain-specific Record content. | + +The permitted representation may omit or redact domain data and additional protected provenance. The Registry Core requirements identify which metadata is present in every returned representation. The applicable representation schema accounts for permitted omissions so that the response remains unambiguous and valid. + +## 8.5 Revisions and lifecycle + +The Base Registry Profile retrieves the current revision. It does not include an operation for retrieving historical revisions. + +The declared representation schema defines the supported lifecycle-state vocabulary. Terms such as active, inactive, superseded, archived, and deleted are examples, not a mandatory enumeration in this release. + +The Record Identifier remains stable when a new revision is accepted. Revision identifiers distinguish successive representations of the same Record. + +## 8.6 Domain semantics and extensions + +The Digital Registries Building Block does not define a universal person, business, parcel, vehicle, health, or programme schema. Each returned representation identifies its machine-readable schema and published semantic model. An adopter can use an appropriate sector model and map national extensions explicitly. + +Extensions do not change the meaning of required Registry metadata. Rules for unknown fields, compatibility, and schema evolution are not defined in this release. diff --git a/spec/8-service-apis.md b/spec/8-service-apis.md deleted file mode 100644 index c628590..0000000 --- a/spec/8-service-apis.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -description: >- - This section provides a reference for APIs that should be implemented by this - Building Block. ---- - -# 8 Service APIs - -The APIs defined here establish a blueprint for how the Building Block will interact with other Building Blocks. Additional APIs may be implemented by the Building Block, but the listed APIs define a minimal set of functionality that should be provided by any implementation of this Building Block. - -The [GovStack non-functional requirements document](https://govstack.gitbook.io/specification/v/1.0/architecture-and-nonfunctional-requirements/6-onboarding) provides additional information on how 'adaptors' may be used to translate an existing API to the patterns described here. This section also provides guidance on how candidate products are tested and how GovStack validates a product's API against the API specifications defined here. - -The tests for the Digital Registries Building Block can be found in [this GitHub repository](../test/openAPI). - -The Digital Registries Building Block may contain multiple registries/databases. The dynamic nature of the database structure requires a standard set of automatically generated APIs for all databases hosted on the platform. The system generates default API method endpoints automatically after each publication of the database schema. A new API service version is generated after each schema publish. Database schema version and API versions are in sync. - -The naming convention and structure of the API endpoint are the following: - -/{information type}/{registry acronym or code}/{version}/{API method as a name}. - -Example 1: ​/api/data​/cr​/1.0​/create - -Example 2: ​/api/v1/database/modify - -Each registry contains a unique set of data and the Building Block enables an Analyst to change the data storage structure/schema on the fly. In the following example API descriptions are generated for one example dataset for the Postpartum Infant Care Program registry, where the Caretaker and infant child are registered and a registration ID is issued. - -![Example registry database logical data model.](<.gitbook/assets/Logical datamodel MCTS (1).JPG>) - -![Example registry database Json schema.](<.gitbook/assets/image4 (1) (1) (1).png>) - -Digital Registries Building Block is expected to host the following API services for each database hosted on the platform. - -The API is built using a representational state transfer ([REST](https://restfulapi.net/)) software architectural style and described in [Open API 3 standard](https://swagger.io/specification/) using [YAML](https://yaml.org/) (a human-readable data-serialization language). Request and response body is in [JSON](https://www.json.org/json-en.html) (lightweight data-interchange format). - -## 8.1 Administrative/Analyst Functions - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}" method="get" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/read" method="post" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/update" method="put" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/updateEntries" method="put" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/updateOrCreate" method="post" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -## 8.2 Applicant Functions - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/exists" method="post" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/{id}/delete" method="delete" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/{uuid}/readValue/{field}.{ext}" method="get" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/mypersonalDataUsage" method="get" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml" path="/database/{id}" method="get" %} -[GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml](.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml" path="/database/{id}" method="delete" %} -[GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml](.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml" path="/database/modify" method="post" %} -[GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml](.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml" path="/databases" method="get" %} -[GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml](.gitbook/assets/GovStack_Digital_registries_BB_Database_API_template-1.3.0.yaml) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}" method="get" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/mcts/createEntries" method="post" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} - -{% openapi src=".gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json" path="/data/{registryName}/{versionNumber}/read" method="post" %} -[GovStack_Digital_registries_BB_Data_API_template-1.3.0.json](.gitbook/assets/GovStack_Digital_registries_BB_Data_API_template-1.3.0.json) -{% endopenapi %} diff --git a/spec/9-service-interfaces.md b/spec/9-service-interfaces.md new file mode 100644 index 0000000..a3e0221 --- /dev/null +++ b/spec/9-service-interfaces.md @@ -0,0 +1,53 @@ +--- +description: Abstract operation and proposed HTTP binding for Consultation Retrieve. +--- + +# 9 Service Interfaces + +## 9.1 Current coverage + +This release defines the semantics of one operation, `consultation.retrieve`. It does not define an HTTP path or exact JSON property names. + +The previous generated CRUD OpenAPI files are legacy artifacts. They are not contracts for this release and do not contain a Retrieve-by-Identifier operation. + +## 9.2 Abstract Retrieve operation + +| Element | Definition | +|---|---| +| Operation identifier | `consultation.retrieve` | +| Purpose | Obtain the current permitted representation of one Record. | +| Required input | Record Identifier. | +| Request context | Authentication and authorisation information required by the deployment and inherited CFR requirements. | +| Success output | Current permitted Record representation described in [Data Structures](8-data-structures.md). | +| Unsuccessful output | Problem response without protected Record data and with the protected-existence handling required by `fr-consultation#req-3`. | +| Excluded behaviour | List, Search, Record Match, GIS Query, historical-revision retrieval, and individual stored-field retrieval. | + +## 9.3 Proposed HTTP binding + +The initial binding is synchronous HTTP over HTTPS and will be described by an OpenAPI contract. The contract will use the shared GovStack API components for problem details and other cross-BB structures once those components and their consumption rules are ratified. + +No canonical OpenAPI file is published in this release. A future contract needs to define: + +- resource path and API versioning; +- exact Registry and Record metadata property names; +- schema resolution and content negotiation; +- conditional retrieval and revision identifiers; +- policy-compliant mapping of unknown, unauthorised, inactive, and superseded outcomes; and +- contract examples that do not assume a person registry. + +## 9.4 Candidate bindings for later capabilities + +The following standards are informative candidates for capabilities that are not claimable in this release. This table does not establish a required version or profile. + +| Capability | Candidate specification | +|---|---| +| Provisioning and general HTTP operations | OpenAPI | +| Consultation Retrieve, List, Search, and Record Match | OpenAPI | +| GIS Query | OGC API Features | +| Wallet-mediated Evidence | OpenID for Verifiable Credential Issuance and Presentation; W3C Verifiable Credentials | +| Direct Evidence | OpenAPI with a signed credential or attestation format | +| Write | OpenAPI | +| Notification | OpenAPI webhooks for HTTP push; AsyncAPI for event-driven bindings | +| Aggregate Data | OpenAPI; SDMX for statistical exchange | +| Access Transparency | OpenAPI | +| Identity Federation | OpenID Connect Core and Discovery | diff --git a/spec/9-workflows.md b/spec/9-workflows.md deleted file mode 100644 index 9c2f85c..0000000 --- a/spec/9-workflows.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -description: >- - This section provides a detailed view of how this Building Block will interact - with other Building Blocks to support common use cases. ---- - -# 9 Internal Workflows - -## 9.1 Administrative/Analyst Functions - -The Digital Registries building block facilitates the foloowing main internal workflows: - -\ -9.1.1 Create a registry database in User Interface - -9.1.2 Process registry data in User Interface - -9.1.3 Create registry database in API interface - -### 9.1.1 User Story 1 - Create registry database in user interface - -As an Administrator/Analyst I want to use a web user interface to create a register database (example registry use case - social security program) so that I can configure and launch the registry database instantly to be used by internet users and client systems (e.g. Registration Building Block, Information Mediator Building Block) via web interface and API. - -**Actors**: Analyst - An administrator user who is creating/changing the registry database schema. The main actor/user in these requirements is the Analyst. - -**Preconditions**: - -1. User is authenticated; -2. User is authorized as an admin; -3. User interface is a web interface; -4. User has internet; -5. System has electricity. - -**Process:** - -1. Create a new registry database project. -2. Define the database fields. -3. Publish the database. -4. Validate/configure the API services. -5. Manage user rights to access the database and APIs. - - - -**Post conditions:** - -1. System contains a database that is ready to process new data. -2. System has API services to CRUD (Create, Read, Update, Delete) data (and API to validate if data exist). -3. User can enter data to the registry via web user interface (UI). -4. User can see log information in the UI. -5. User can see statistics in the UI. -6. User can give authorization to use the database and process data. -7. System contains a database that is ready to process new data. -8. System has API services to CRUD data (and API to validate if data exist). -9. User can enter data to the registry via web UI. -10. User can see log information in the UI. -11. User can see statistics in the UI. -12. User can give authorization to use the database and process data. - -### 9.1.2 User Story 2 - Process registry data in User Interface - -As an Administrator/Analyst, I want to process (Create, Read, Update, Delete) registry data so that I do not have to know the query language. - -**Actors** - -* Analyst: the main actor in these requirements is the Analyst/Administrator. -* Data owner: a physical person whose personal data is stored in the registry. - -**Preconditions:** - -1. Analyst is authenticated and authorized to use the Building Block and process data in the database; -2. The user interface is a web interface; -3. User has internet; -4. System has electricity. - -**Process**: - -1. Analyst searches a record via search or filter function; -2. Analyst selects a record; -3. Analyst processes a record; -4. System stores changes to the Change Log database. - -**Postconditions**: - -Processing changes by Analyst are done and log for change is created. - -### 9.1.3 User Story 3- Create registry database in API interface - -As an IT developer, I want to Create/update/delete registry database schema via API services. - -**Actors** - -* IT developer (Developer): Main actor in these requirements is planning to open a new business program and web form to capture applicants' data. Captured data must be registered in the registry. In this use case, a Developer is any user who is using API services to create and manage registries database. - -**Preconditions**: - -1. Developer is using API with a client system or a script that is connected to Information Mediator Building Block. Client system is any Building Block that is using API services via Information Mediator; -2. IT Developer (Information Mediator organization) has been given authorization to Create/update/delete database schema via API services. -3. Developer has internet; -4. System has electricity. - -**Process**: - -1. Developer uses a client system to edit the registry database in the Building Block. Developer can: - 1. Create database schema; - 2. Read database schema; - 3. Modify database schema; - 4. Delete database schema and all data in it. - -**Postconditions**: - -1. When Developer is authorized to use Building Block API then the Digital Registries Building Block allows processing CRUD (Create, Read, Update, Delete) schema of a registry, and all authorized users can; -2. When Developer is not authorized to process/CRUD the database schema, the system allows to process schema of all databases where an anonymous user has been allowed to edit the database schema (simplification for GovStack Sandbox instance); -3. When a user has no authorization, one can not create nor change (CRUD) any schema in the Building Block. - - - -## 9.2 Applicant Functions - -9.2.1 Process data in API interface - -### 9.2.1 User Story 4 - Process data in API interface - -As an Applicant, I want to process CRUD (Create, Read, Update, Delete) data in the registry database. - -**Actors**: - -* Applicant - The main actor in these requirements is an applicant via the client system. In this use case applicant is any user who is using a client system (Registration Building Block). For example, a Health Care worker is an applicant in this user story; a mother, using the Registration Building Block. An example client system in this document is Registration Building Block. - -**Preconditions**: - -1. Applicant is using client system (e.g. Registration Building Block) that is connected to Information Mediator Building Block; -2. Client system has been given authorization to access Registry to process (CRUD) information; -3. Applicant has been given authorization to access Registry to process (CRUD) information; -4. Applicants are registered in the system and able to use authentication. Applicant is Authenticated by client system or Security Building Block (Authentication). -5. Applicant has internet; -6. System has electricity. - -**Process**: - -1. Applicant uses a client system to process data in the registry - * Applicant can create data; - * Applicant can read data; - * Applicant can update data; - * Applicant can delete data; - * Applicant can create or update data; - * Applicant can validate data. -2. System logs all processing events in the dedicated audit registry. - -**Postconditions**: - -1. When Applicant is authenticated by a client system (e.g. Registration Building Block) the registry allows processing (CRUD) information from the registry. All users who are authenticated can read data. -2. When a user is not authenticated in the system, the system allows processing (CRUD) data from all databases where an anonymous user has been allowed to process data. -3. When a user has no authorization, one can not process (CRUD) any information in the registry. - -### - diff --git a/spec/README.md b/spec/README.md index 6949124..a072f74 100644 --- a/spec/README.md +++ b/spec/README.md @@ -1,23 +1,34 @@ --- -description: Version 3.0-alpha; June 2026 +description: Version 3.0.0-alpha.2 --- # Digital Registries Building Block Specification -_**Coordinating authors:**_\ -Dr. Bimal Kumar, Xilene Siquero, and Sebastian Leidig (Aam Digital) +`govstack-bb-digital-registries-3.0.0-alpha.2 extends govstack-cfr-2.1.0` -_**Authors:**_\ -Janet Ngugi, Vivek Rana, Chinenye Ifebirinachi, Ananya Jha, Umang Gupta, and Leonora Smart-Abbey, and Jeremi Joslin +> **Alpha specification.** Its requirements are classified as DRAFT and do not establish a GovStack certification claim. Implementers should use the latest approved Digital Registries specification for procurement or certification. -_**Editors:**_\ -Ali González-García and David Higgins +The Digital Registries Building Block defines interoperable behaviour for software that maintains authoritative records about persons, organisations, places, assets, or events. It specifies a minimum Base Registry Profile and a catalogue of additional capabilities that an implementation may support. -*** +The Base Registry Profile consists of Registry Core behaviour and the ability for an authorised API consumer to retrieve the current permitted representation of a record by its stable identifier. The specification does not prescribe a database product, administrative user interface, storage model, deployment topology, or domain data model. -_**First version by:**_ \ -Frank Grozel (UNCTAD), Ingmar Vali (ITU), Tambet Artma (ITU), Saurav Bhattarai (GIZ), Dr. P. S. Ramkumar (ITU), Rauno Kulla (UNCTAD), and Sebastian Leidig +## How to use this specification +- **Government architects** should begin with [Description and Scope](2-description-and-scope.md) and [Conformance](4-conformance.md) to determine where a Registry fits within a digital government architecture. +- **Procurement teams** can use the alpha to understand the intended profile structure, but should cite an approved specification version in a tender or acceptance contract. +- **Implementers** can use the DRAFT requirements, data structures, and workflow for prototyping. This alpha does not publish an implementation contract. +- **Conformance testers** can use [Testing](11-testing.md) to assess verification intent. This alpha does not publish a conformance suite or permit capability claims. +## Status and authorship -
+This alpha is structured around a domain-neutral Registry Core, mandatory Consultation Retrieve, and optional capability families. Earlier contributions, authors, coordinators, editors, and reviewers remain recorded in the [Version History](1-version-history/README.md) and [Release Notes](1-version-history/release-notes.md). + +_**Coordinating authors of the 3.0.0-alpha.1 work:**_ Dr. Bimal Kumar, Xilene Siquero, and Sebastian Leidig + +_**Authors:**_ Janet Ngugi, Vivek Rana, Chinenye Ifebirinachi, Ananya Jha, Umang Gupta, Leonora Smart-Abbey, and Jeremi Joslin + +_**Editors:**_ Ali González-García and David Higgins + +_**First version by:**_ Frank Grozel, Ingmar Vali, Tambet Artma, Saurav Bhattarai, Dr. P. S. Ramkumar, Rauno Kulla, and Sebastian Leidig + +
Digital Registries Building Block capability families
The target Base Registry Profile combines Registry Core with Consultation Retrieve.
diff --git a/spec/SUMMARY.md b/spec/SUMMARY.md index 91bd78a..0fa65d1 100644 --- a/spec/SUMMARY.md +++ b/spec/SUMMARY.md @@ -3,13 +3,24 @@ * [Digital Registries Building Block Specification](README.md) * [1 Version History](1-version-history/README.md) * [Release Notes](1-version-history/release-notes.md) -* [2 Description](2-description.md) +* [2 Description and Scope](2-description-and-scope.md) * [3 Terminology](3-terminology.md) -* [4 Key Digital Functionalities](4-key-digital-functionalities.md) -* [5 Cross Functional Requirements](5-cross-cutting-requirements.md) +* [4 Conformance](4-conformance.md) +* [5 Key Functionalities: API Families](5-key-functionalities.md) + * [Consultation](5-api-families/consultation.md) + * [Provisioning](5-api-families/provisioning.md) + * [Evidence](5-api-families/evidence.md) + * [Write](5-api-families/write.md) + * [Notification](5-api-families/notification.md) + * [Aggregate Data](5-api-families/aggregate-data.md) + * [Access Transparency](5-api-families/access-transparency.md) + * [Identity Federation](5-api-families/identity-federation.md) * [6 Functional Requirements](6-functional-requirements.md) -* [7 Data Structures](7-data-structures.md) -* [8 Service APIs](8-service-apis.md) -* [9 Internal Workflows](9-workflows.md) -* [10 Other Resources](10-other-resources/README.md) - * [10.5 Cross Functional Security and Interoperability Standards](10-other-resources/10.5-cross-functional-security-and-interoperability-standards.md) +* [7 Cross-Functional Requirements](7-cross-functional-requirements.md) +* [8 Data Structures](8-data-structures.md) +* [9 Service Interfaces](9-service-interfaces.md) +* [10 Workflows](10-workflows.md) +* [11 Testing](11-testing.md) +* [12 Other Resources](12-other-resources/README.md) + * [Migration from 3.0.0-alpha.1](12-other-resources/migration-from-3.0.md) + * [References](12-other-resources/references.md) diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..aa3a86b --- /dev/null +++ b/test/README.md @@ -0,0 +1,5 @@ +# Test artifacts + +The `openAPI/` directory contains the conformance harness for the generated CRUD interface used by earlier Digital Registries releases. It is retained as migration evidence and is not the 3.0.0-alpha.2 conformance suite. + +Draft verification intent and requirement traceability are documented in [the Testing chapter](../spec/11-testing.md). No executable conformance tests for the 3.0.0-alpha.2 specification are published. From e841a1088c9425e24444139182c8deb7c33eb4ab Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Mon, 10 Aug 2026 15:37:40 +0700 Subject: [PATCH 02/10] Preserve legacy API and example context Signed-off-by: Jeremi Joslin --- api/README.md | 2 ++ api/legacy/generated-crud/README.md | 24 ++++++++++++++++++++++++ examples/README.md | 12 ++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 api/legacy/generated-crud/README.md diff --git a/api/README.md b/api/README.md index a30c674..d89c834 100644 --- a/api/README.md +++ b/api/README.md @@ -2,6 +2,8 @@ The JSON and YAML files under `legacy/generated-crud/` describe the generated CRUD interface from earlier Digital Registries releases. They are retained for migration analysis and are not service contracts for the 3.0.0-alpha.2 specification. +Their original release status, contributor acknowledgements, and publication context are preserved in the [legacy API README](legacy/generated-crud/README.md). + The `gitbook-copies/` subdirectory contains additional copies previously embedded as publication assets. They remain separated from current API artifacts because their content is not identical in every case. In particular, the legacy interface does not provide the `consultation.retrieve` operation, which retrieves a Record directly by its stable Record Identifier. Its `POST /read` operation performs search-by-example instead. diff --git a/api/legacy/generated-crud/README.md b/api/legacy/generated-crud/README.md new file mode 100644 index 0000000..8bf36f4 --- /dev/null +++ b/api/legacy/generated-crud/README.md @@ -0,0 +1,24 @@ +# Generated CRUD API contracts + +> **Legacy artifacts.** These contracts describe the generated CRUD interface from earlier Digital Registries releases. They are not service contracts for the 3.0.0-alpha.2 specification. + +The JSON and YAML contracts in this directory were moved here without content changes. The `gitbook-copies/` subdirectory preserves additional versions that had been embedded in the published specification and that differ from the top-level copies in some details. + +## Original publication context + +The original API README identified these definitions as OpenAPI 3.0 artifacts with release status **RC.1.3**. + +It acknowledged the following contributors: + +- Frank Grozel, UNCTAD +- Ingmar Vali, UNCTAD +- Tambet Artma, Centre of Registers and Information Systems +- Saurav Bhattarai, GIZ +- Dr. P. S. Ramkumar, ITU +- Rauno Kulla, UNCTAD + +The original references named UNCTAD eRegistrations, UNCTAD, and the DIAL Digital Registries use-case catalogue. These references describe the context in which the generated CRUD interface was developed, not the status of the current specification. + +## Current use + +The artifacts remain useful for migration analysis and for understanding existing implementations. Known inconsistencies and the disposition of the previous requirements are documented in [Migration from the 3.0.0-alpha.1 Draft](../../../spec/12-other-resources/migration-from-3.0.md). diff --git a/examples/README.md b/examples/README.md index 11273dd..641e946 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,4 +4,16 @@ The examples in this directory demonstrate products and test environments develo They are retained for migration and implementation research. They do not demonstrate conformance with the 3.0.0-alpha.2 Base Registry Profile. +## Preserved implementation context + +### UNCTAD Generic Database Builder (eRegistrations) + +Earlier Digital Registries releases identified the UNCTAD Generic Database Builder, also known as eRegistrations, as an implementation of the generated CRUD and no-code Registry model. The original repository description characterised it as proprietary software available with a one-time UNCTAD support fee. + +The files under [eRegistrations](eRegistrations/README.md) preserve example requests and documentation from that integration. Previously listed GovStack sandbox and authorisation endpoints are no longer presented as active services. + +### Mockoon API mock + +The [Mockoon example](mockoon/README.md) preserves a local mock of the previous OpenAPI surface for development and migration analysis. + Any future example intended as conformance evidence needs to identify the specification and capability profile it implements and be verified by the corresponding conformance tests. From 3a0f70e6db5e760dc6a61663d0044d2aacb41f49 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 2 Sep 2026 16:08:15 +0700 Subject: [PATCH 03/10] Refine Registry Core structure and discovery metadata Address PR feedback on documentation layout, authorship, identity boundaries, and obsolete historical pages. Colocate shared requirements and data concepts with Registry Core and Consultation. Add DCAT metadata, API-family discovery, the formal vocabulary and JSON-LD context, and redirects for renamed GitBook pages. Signed-off-by: Jeremi Joslin --- .gitbook.yaml | 28 +- README.md | 12 +- spec/.gitbook/assets/api-families.svg | 6 +- .../README.md => 01-version-history.md} | 2 +- .../release-notes.md | 0 ...d-scope.md => 02-description-and-scope.md} | 6 +- spec/{3-terminology.md => 03-terminology.md} | 1 + spec/{4-conformance.md => 04-conformance.md} | 26 +- .../access-transparency.md | 8 +- .../aggregate-data.md | 8 +- spec/05-api-families/consultation.md | 112 ++++++ .../evidence.md | 6 +- spec/05-api-families/identity-federation.md | 35 ++ .../notification.md | 10 +- .../provisioning.md | 12 +- .../registry-core-context.jsonld | 76 ++++ .../registry-core-vocabulary.ttl | 157 ++++++++ spec/05-api-families/registry-core.md | 370 ++++++++++++++++++ .../write.md | 6 +- spec/05-key-functionalities.md | 50 +++ ...interfaces.md => 09-service-interfaces.md} | 24 +- spec/10-workflows.md | 10 +- spec/11-testing.md | 22 +- .../README.md => 12-other-resources.md} | 16 +- .../historical/future-considerations.md | 51 --- .../historical/key-decision-log.md | 48 --- spec/12-other-resources/migration-from-3.0.md | 10 +- spec/12-other-resources/references.md | 23 +- spec/5-api-families/consultation.md | 39 -- spec/5-api-families/identity-federation.md | 29 -- spec/5-key-functionalities.md | 36 -- spec/6-functional-requirements.md | 155 -------- spec/7-cross-functional-requirements.md | 20 - spec/8-data-structures.md | 90 ----- spec/README.md | 14 +- spec/SUMMARY.md | 36 +- 36 files changed, 964 insertions(+), 590 deletions(-) rename spec/{1-version-history/README.md => 01-version-history.md} (95%) rename spec/{1-version-history => 01-version-history}/release-notes.md (100%) rename spec/{2-description-and-scope.md => 02-description-and-scope.md} (88%) rename spec/{3-terminology.md => 03-terminology.md} (94%) rename spec/{4-conformance.md => 04-conformance.md} (51%) rename spec/{5-api-families => 05-api-families}/access-transparency.md (76%) rename spec/{5-api-families => 05-api-families}/aggregate-data.md (67%) create mode 100644 spec/05-api-families/consultation.md rename spec/{5-api-families => 05-api-families}/evidence.md (71%) create mode 100644 spec/05-api-families/identity-federation.md rename spec/{5-api-families => 05-api-families}/notification.md (63%) rename spec/{5-api-families => 05-api-families}/provisioning.md (70%) create mode 100644 spec/05-api-families/registry-core-context.jsonld create mode 100644 spec/05-api-families/registry-core-vocabulary.ttl create mode 100644 spec/05-api-families/registry-core.md rename spec/{5-api-families => 05-api-families}/write.md (71%) create mode 100644 spec/05-key-functionalities.md rename spec/{9-service-interfaces.md => 09-service-interfaces.md} (53%) rename spec/{12-other-resources/README.md => 12-other-resources.md} (67%) delete mode 100644 spec/12-other-resources/historical/future-considerations.md delete mode 100644 spec/12-other-resources/historical/key-decision-log.md delete mode 100644 spec/5-api-families/consultation.md delete mode 100644 spec/5-api-families/identity-federation.md delete mode 100644 spec/5-key-functionalities.md delete mode 100644 spec/6-functional-requirements.md delete mode 100644 spec/7-cross-functional-requirements.md delete mode 100644 spec/8-data-structures.md diff --git a/.gitbook.yaml b/.gitbook.yaml index a458190..2d7b0e9 100644 --- a/.gitbook.yaml +++ b/.gitbook.yaml @@ -1,5 +1,27 @@ root: ./spec/ -​structure: - readme: README.md - summary: SUMMARY.md​ +structure: + readme: README.md + summary: SUMMARY.md + +redirects: + 1-version-history: 01-version-history.md + 1-version-history/release-notes: 01-version-history/release-notes.md + 2-description-and-scope: 02-description-and-scope.md + 3-terminology: 03-terminology.md + 4-conformance: 04-conformance.md + 5-key-functionalities: 05-key-functionalities.md + 5-api-families/access-transparency: 05-api-families/access-transparency.md + 5-api-families/aggregate-data: 05-api-families/aggregate-data.md + 5-api-families/consultation: 05-api-families/consultation.md + 5-api-families/evidence: 05-api-families/evidence.md + 5-api-families/identity-federation: 05-api-families/identity-federation.md + 5-api-families/notification: 05-api-families/notification.md + 5-api-families/provisioning: 05-api-families/provisioning.md + 5-api-families/write: 05-api-families/write.md + 6-functional-requirements: 05-key-functionalities.md + 7-cross-functional-requirements: 04-conformance.md + 8-data-structures: 05-api-families/registry-core.md + 9-service-interfaces: 09-service-interfaces.md + 12-other-resources/historical/future-considerations: 12-other-resources.md + 12-other-resources/historical/key-decision-log: 12-other-resources/migration-from-3.0.md diff --git a/README.md b/README.md index 82a05bb..e94f879 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ The `3.0.0-alpha.2` specification defines a domain-neutral Registry Core with ma Start with the [Digital Registries Building Block Specification](spec/README.md). +### Alpha coverage + +The alpha publishes the proposed scope, terminology, Base Registry Profile, DRAFT Core and Retrieve requirements, conceptual Record model, workflow, verification intent, and migration from the previous `DRS-1` through `DRS-37` requirements. + +It does not publish a canonical OpenAPI contract or executable conformance suite. No implementation can claim conformance with this alpha. + ## Repository structure | Path | Contents | Current status | @@ -17,12 +23,6 @@ Start with the [Digital Registries Building Block Specification](spec/README.md) | `test/` | Conformance and contract tests | Previous generated CRUD tests retained as legacy; draft scenarios are documented in `spec/11-testing.md` | | `examples/` | Product and integration examples | Historical examples; not evidence of 3.0.0-alpha.2 conformance | -## Alpha coverage - -The alpha publishes the proposed scope, terminology, Base Registry Profile, DRAFT Core and Retrieve requirements, conceptual Record model, workflow, verification intent, and migration from the previous `DRS-1` through `DRS-37` requirements. - -It does not publish a canonical OpenAPI contract or executable conformance suite. No implementation can claim conformance with this alpha. - ## Publication GitBook publishes content from the `spec/` directory according to `.gitbook.yaml`. The navigation source is [spec/SUMMARY.md](spec/SUMMARY.md). diff --git a/spec/.gitbook/assets/api-families.svg b/spec/.gitbook/assets/api-families.svg index cb5d616..be41449 100644 --- a/spec/.gitbook/assets/api-families.svg +++ b/spec/.gitbook/assets/api-families.svg @@ -23,7 +23,7 @@ - Eight capability families with candidate interface bindings + Eight capability families with illustrative protocol options @@ -242,8 +242,8 @@ OpenID Connect + font-size="9.5" font-weight="500" + font-family="'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace">OWNERSHIP TBD diff --git a/spec/1-version-history/README.md b/spec/01-version-history.md similarity index 95% rename from spec/1-version-history/README.md rename to spec/01-version-history.md index 964c815..cf1b8ce 100644 --- a/spec/1-version-history/README.md +++ b/spec/01-version-history.md @@ -42,4 +42,4 @@ Authors: Janet Ngugi, Vivek Rana, Chinenye Ifebirinachi, Ananya Jha, Umang Gupta Editors: Ali González-García and David Higgins. -The detailed change record is preserved in the [Release Notes](release-notes.md). +The detailed change record is preserved in the [Release Notes](01-version-history/release-notes.md). diff --git a/spec/1-version-history/release-notes.md b/spec/01-version-history/release-notes.md similarity index 100% rename from spec/1-version-history/release-notes.md rename to spec/01-version-history/release-notes.md diff --git a/spec/2-description-and-scope.md b/spec/02-description-and-scope.md similarity index 88% rename from spec/2-description-and-scope.md rename to spec/02-description-and-scope.md index cf0a676..bec97b0 100644 --- a/spec/2-description-and-scope.md +++ b/spec/02-description-and-scope.md @@ -19,7 +19,7 @@ This specification covers: - identification and description of a registry; - stable identification and lifecycle representation of registry records; - retrieval of the current permitted representation of a record; -- declaration of schemas, semantic models, supported capabilities, and protocol bindings; +- declaration of representation formats, schemas, semantic models, supported capabilities, and protocol bindings; - registry-specific revision and provenance information; and - optional capabilities for provisioning, additional consultation patterns, evidence, writing, notifications, aggregate data, access transparency, and identity federation. @@ -30,7 +30,7 @@ The same specification can be applied to registries containing records about per The specification separates four concerns: 1. **Operations** describe what an API consumer can ask the registry to do. -2. **Common metadata** identifies the registry, record, revision, lifecycle state, schema, and provenance relevant to an operation. +2. **Common metadata** identifies the registry, record, revision, lifecycle state, representation format, schema, and provenance relevant to an operation. 3. **Semantic models** define the meaning of domain data. 4. **Bindings** map operations to HTTP, event-driven messaging, or an established industry protocol. @@ -54,7 +54,7 @@ A Registry can integrate with neighbouring Building Blocks without transferring | Consent | Consent can provide evidence or policy signals used in a disclosure decision. The Registry enforces the decision applicable to each request and supports other lawful bases where relevant. | | E-Signature | E-Signature can perform signing operations. The Registry remains responsible for the meaning, issuance, status, and lifecycle of Registry Evidence. | | Wallet | A Wallet can hold and present credentials issued through Evidence. The Registry remains the source of the asserted facts and is not required to operate a Wallet. | -| Identity | Identity can authenticate users or provide foundational identity services. A sectoral Registry remains responsible for its functional identifiers. Identity Federation does not replace API access control. | +| Identity | The [Identity Building Block](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) currently defines foundational identity services and discusses integration with functional identities. A sectoral Registry remains responsible for its functional identifiers. Ownership of an outward-facing functional Identity Federation profile remains an open cross-Building-Block decision, and Identity Federation does not replace API access control. | | GIS | GIS can provide geospatial processing and visualisation. A spatial Registry remains responsible for its records and can expose an OGC-aligned GIS Query capability. | These integrations are optional unless a selected capability profile states otherwise. diff --git a/spec/3-terminology.md b/spec/03-terminology.md similarity index 94% rename from spec/3-terminology.md rename to spec/03-terminology.md index eabcaab..5b30cc4 100644 --- a/spec/3-terminology.md +++ b/spec/03-terminology.md @@ -21,6 +21,7 @@ This specification uses the [GovStack Common Terminology](https://specs.govstack | Record Identifier | A stable identifier assigned to a record within a Registry. | | Record Principal | A person or organisation with a recognised relationship to a record, such as its subject, owner, title holder, director, or credential holder. | | Record Revision | A representation of a record at a defined point in its change history. | +| Representation Format | The serialisation or media type used to encode a returned representation, identified through the applicable binding. | | Registry Authority | The institution accountable for the Registry and its declared authoritative scope. | | Registry Core | Behaviour and metadata required of every conformant Registry implementation. | | Registry Identifier | A globally unique and stable identifier for a Registry. | diff --git a/spec/4-conformance.md b/spec/04-conformance.md similarity index 51% rename from spec/4-conformance.md rename to spec/04-conformance.md index 53ae15b..ddc2bae 100644 --- a/spec/4-conformance.md +++ b/spec/04-conformance.md @@ -1,5 +1,5 @@ --- -description: Draft minimum conformance and future capability model for Digital Registries. +description: Draft minimum conformance and capability model for Digital Registries. --- # 4 Conformance @@ -8,26 +8,34 @@ description: Draft minimum conformance and future capability model for Digital R All requirements in the 3.0.0-alpha.2 specification are classified as DRAFT. They do not create a certification obligation. -## 4.2 Target Base Registry Profile +Each requirement follows the GovStack Requirements Model. Requirement identifiers are permanently reserved even while the requirement is DRAFT. Cross-family requirements are defined under [Registry Core](05-api-families/registry-core.md#registry-core-functional-requirements), while family-specific requirements are defined on the applicable API-family page. + +## 4.2 Inherited cross-functional requirements + +This specification extends `govstack-cfr-2.1.0`. Every parent requirement applies with its original classifier and applicability conditions unless a Digital Registries requirement explicitly identifies a permitted extension or replacement under the GovStack Requirements Model. + +This release defines no Registry-specific cross-functional extension or replacement. It does not impose a jurisdiction-specific security framework, a universal legal basis for data processing, or one deletion policy on every type of Registry. + +## 4.3 Target Base Registry Profile The provisional name for the target minimum conformance claim is the **Base Registry Profile**. Its formal treatment as a profile, and the conditional applicability of additional capabilities, depend on equivalent support in the GovStack Common Requirements Framework. It is not claimable in this alpha because its requirements are DRAFT and no canonical contract or executable test suite is published. Once approved, an implementation claiming this profile: -1. satisfies the Registry Core requirements; -2. implements the Consultation Retrieve sub-pattern; +1. satisfies the [Registry Core requirements](05-api-families/registry-core.md#registry-core-functional-requirements); +2. implements the [Consultation Retrieve](05-api-families/consultation.md#retrieve-functional-requirements) sub-pattern; 3. identifies the Digital Registries specification version it implements; -4. returns records under an identified schema and published semantic model; and -5. satisfies the applicable GovStack Cross-Functional Requirements. +4. returns records in an identified representation format under an identified schema and published semantic model; and +5. satisfies the applicable `govstack-cfr-2.1.0` requirements. -Retrieve does not imply public access or disclosure of the complete stored record. It means that an authorised API consumer can request a record by its stable identifier and receive the current permitted representation or a policy-appropriate error response. +Retrieve does not imply public access or disclosure of the complete stored record. It means that an authorised API consumer can request a record by its stable identifier and receive the current permitted representation or a policy-appropriate unsuccessful outcome. -## 4.3 Future additional capability claims +## 4.4 Additional capability claims After the Common Requirements Framework supports conditional capability applicability, an approved Digital Registries release may allow an implementation to claim additional families and Consultation sub-patterns. Once claimed, every applicable REQUIRED requirement, operation, contract, and test for that capability becomes part of its conformance claim. Capabilities described only for architectural context, without approved requirements, contracts, and tests, are not claimable in this release. -## 4.4 Adaptors +## 4.5 Adaptors An existing registry does not need to replace its internal software to conform. An adaptor may translate an existing interface into the operations, metadata, outcomes, and bindings required by a claimed profile. Conformance applies to the resulting external behaviour. diff --git a/spec/5-api-families/access-transparency.md b/spec/05-api-families/access-transparency.md similarity index 76% rename from spec/5-api-families/access-transparency.md rename to spec/05-api-families/access-transparency.md index f290001..29229d4 100644 --- a/spec/5-api-families/access-transparency.md +++ b/spec/05-api-families/access-transparency.md @@ -12,7 +12,7 @@ Access Transparency enables an entitled Record Principal to obtain a permitted v A Record Principal can be a subject, owner, title holder, director, beneficiary, or credential holder. The relationship alone does not create a universal entitlement. The adopting jurisdiction defines the applicable right, delegation rules, and period for which the relationship is relevant. -## Candidate capability areas +## Capability areas | Area | Outcome | |---|---| @@ -24,11 +24,11 @@ A Record Principal can be a subject, owner, title holder, director, beneficiary, Internal security and audit logging is a cross-functional concern. Access Transparency is the outward-facing service derived from permitted audit information. Its representation can omit actor identities or operational details where disclosure would create a privacy, security, or investigation risk. -A complete profile needs to define entitlement, relationship verification, delegation, outward event vocabulary, retention, correction handling, and disclosure restrictions. +An adopting authority that includes Access Transparency in its deployment needs to define entitlement, relationship verification, delegation, outward event vocabulary, retention, correction handling, and disclosure restrictions. -## Candidate binding +## Binding status -Synchronous HTTP described by OpenAPI is the candidate general binding. No outward event schema or API contract is selected in this release. +This release does not specify an Access Transparency binding, outward event schema, or API contract. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI, but that choice does not create a GovStack capability claim. ## Example diff --git a/spec/5-api-families/aggregate-data.md b/spec/05-api-families/aggregate-data.md similarity index 67% rename from spec/5-api-families/aggregate-data.md rename to spec/05-api-families/aggregate-data.md index 155f12c..a813078 100644 --- a/spec/5-api-families/aggregate-data.md +++ b/spec/05-api-families/aggregate-data.md @@ -10,7 +10,7 @@ description: Approved statistics derived from Registry Records. Aggregate Data provides approved statistics derived from Registry Records, such as counts, distributions, or time series. It applies when the Registry itself publishes statistical outputs. In other deployments, a national statistics service or open-data platform can own that responsibility instead. -## Candidate capability areas +## Capability areas | Area | Outcome | |---|---| @@ -20,11 +20,11 @@ Aggregate Data provides approved statistics derived from Registry Records, such ## Capability boundary -Aggregate Data is not Record-level [Consultation](consultation.md), a mandatory analytics engine, or a dashboard. It is not automatically public. Aggregation is not itself anonymisation, and a complete profile needs to address disclosure thresholds, suppression, legal controls, revisions, and indicators of applied protection. +Aggregate Data is not Record-level [Consultation](consultation.md), a mandatory analytics engine, or a dashboard. It is not automatically public. Aggregation is not itself anonymisation. An adopting authority that includes Aggregate Data in its deployment needs to define disclosure thresholds, suppression, legal controls, revisions, and indicators of applied protection. -## Candidate bindings +## Binding status -Synchronous HTTP described by OpenAPI is a candidate general binding. SDMX is a candidate semantic and interchange standard where outputs need to participate in national or international statistical ecosystems. This release selects neither binding. +This release does not specify an Aggregate Data binding. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI or SDMX where outputs need to participate in national or international statistical ecosystems. These choices do not create a GovStack capability claim. ## Example diff --git a/spec/05-api-families/consultation.md b/spec/05-api-families/consultation.md new file mode 100644 index 0000000..aabf12f --- /dev/null +++ b/spec/05-api-families/consultation.md @@ -0,0 +1,112 @@ +--- +description: Read capabilities for permitted Registry information. +--- + +# Consultation + +> **Status:** Retrieve is DRAFT and part of the target Base Registry Profile. Existence Check, List, Search, Revision History, Record Match, and GIS Query are informative and not claimable in this release. + +## Purpose and applicability + +Consultation enables an API Consumer operating under an applicable access and disclosure policy to obtain a permitted representation of Registry information. It applies when a consumer needs current information from the authoritative source rather than a portable signed assertion or a derived statistic. + +Retrieve is the minimum read capability. It lets a consumer that already knows a Record Identifier obtain the current permitted representation without requiring the Registry to expose enumeration or discovery by personal or domain attributes. + +Consultation inherits the shared [Registry Core model and requirements](registry-core.md). In this family, the current revision means the latest accepted revision of the Record. It is not necessarily an active Record; the declared lifecycle state and applicable disclosure policy determine whether and how it is returned. + +Consultation provides a common capability framework for domain-specific registries. The applicable registry or sector profile defines the Record schema, semantic model, lifecycle vocabulary, permitted representations, and any domain-specific query or matching semantics. This specification does not require a generic query layer over arbitrary stored fields. + +## Capability patterns + +| Pattern | Outcome | +|---|---| +| `consultation.retrieve` | Returns the current permitted representation of one Record identified by its stable Record Identifier. | +| Existence Check | Indicates whether a Record exists only when the consumer is permitted to learn that fact. | +| List | Returns a bounded, paginated collection under an applicable domain profile, optionally filtered by declared attributes. | +| Search | Finds Records using predicates declared by the applicable registry or sector profile. | +| Revision History | Returns permitted revision metadata or a permitted historical representation of one Record. | +| Record Match | Returns possible matching Records with confidence information under a domain-specific matching profile. It does not make an authoritative identity or acceptance decision. | +| GIS Query | Applies domain-defined spatial predicates to geometric attributes maintained by the Registry. | + +## Capability boundary + +Consultation returns live Registry information. [Evidence](evidence.md) produces a signed assertion with its own validity and status. [Aggregate Data](aggregate-data.md) returns derived statistics rather than Record representations. + +Consultation is read-only. It does not create a Record, accept a new revision, change lifecycle state, or perform an approval decision. The Retrieve requirements define permitted representations and protected-existence handling. An adopter selecting Existence Check, List, Search, Revision History, Match, or GIS Query needs an applicable profile that defines disclosure, bounded results, query limits, and result interpretation for that capability. + +## Retrieve representation + +A successful Retrieve returns the [common Record context](registry-core.md#common-record-context) together with the domain data that the API Consumer is permitted to receive. The representation can omit or redact domain data and additional protected provenance, but the resulting projection remains unambiguous and valid against its declared representation schema. + +The Base Registry Profile retrieves the current revision. Revision History is a separate informative Consultation capability and is not claimable in this release. + +## Retrieve functional requirements + +The following DRAFT requirements define the Consultation capability in the target Base Registry Profile. They do not establish a certification claim in this release. + +### #1 Retrieve the current Record by identifier (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-consultation#req-1` + +`KF: Consultation` + +Given an unambiguous Registry context, a valid Record Identifier, and a request permitted by applicable policy, an implementation returns the current permitted representation of that Record without modifying the Record. + +**Purpose:** An API Consumer that already knows a Record Identifier can obtain authoritative Registry information without using search or enumeration. + +**Prerequisite:** A permitted consumer context and an accessible Record fixture exist. + +**Verification:** Retrieve a known Record by identifier, verify the Registry and Record identifiers, current revision, lifecycle state, representation format, schema, semantic model, minimum provenance, and permitted domain data, and confirm that a subsequent Retrieve returns the same revision when no intervening change occurred. + +### #2 Apply disclosure rules to the returned representation (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-consultation#req-2` + +`KF: Consultation` + +An implementation returns only the Record fields and metadata permitted for the API Consumer and request context. The resulting projection remains valid against its declared representation schema. + +**Purpose:** Retrieve does not become an entitlement to the complete stored Record. The same Registry can expose different valid representations under different disclosure policies, including a public representation where applicable. + +**Prerequisite:** At least two test consumer contexts have different disclosure entitlements for the same Record. + +**Verification:** Retrieve the same Record using both consumer contexts and verify that each receives only its permitted projection, each projection validates against its declared schema, and omitted values are not exposed through errors or metadata returned to the consumer. + +### #3 Hide protected Record existence (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-consultation#req-3` + +`KF: Consultation` + +For an API Consumer that is not authorised to learn whether a protected Record exists, an implementation returns an outcome that is indistinguishable under the published Retrieve contract from the outcome for an unknown Record Identifier. This includes the same status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values. Per-request trace or correlation values may differ when they are generated independently of Record existence. The response contains no Record-specific data. + +**Purpose:** An unauthorised consumer cannot enumerate protected Record Identifiers through the Retrieve contract. + +**Prerequisite:** An unknown Record Identifier and a protected Record Identifier are available as test fixtures for the same consumer context. + +**Verification:** Retrieve both identifiers using that consumer context and compare the status or protocol outcome, security-relevant response metadata, error type, response structure, non-Record-specific values, and data fields. Verify that any differing trace or correlation values are independent of Record existence and that neither response exposes Record-specific data. + +## Selecting additional Consultation capabilities + +An adopter may need Consultation capabilities beyond Retrieve. These capabilities are not part of the Base Registry Profile and are not claimable in this release. An adopter should select them only when they serve a defined consumer need and an applicable registry or sector profile supplies the required domain semantics. + +| Capability | Select when | The applicable profile needs to define | +|---|---|---| +| Existence Check | A consumer needs to determine whether a Record exists without receiving its representation. | When existence may be disclosed and how protected and unknown Records are treated consistently. | +| List | A consumer is permitted to browse a defined collection of Records. | Collection membership, filters, ordering, bounded pagination, collection metadata, and disclosure rules. | +| Search | A consumer needs to find Records without already knowing their Record Identifiers. | Searchable domain concepts, predicates, result limits, and zero-match, multiple-match, and truncated-result outcomes. | +| Revision History | A consumer needs permitted information about earlier revisions of a known Record. | Whether revision enumeration or historical representations are available, stable revision identifiers, ordering, retention, lifecycle interpretation, and disclosure or erasure rules for historical data. | +| Record Match | A consumer supplies incomplete or variable domain information that may correspond to more than one Record. | Permitted inputs, matching rules, confidence interpretation, disclosure of possible matches, and ambiguous or no-match outcomes. A match is not an authoritative identity, eligibility, or acceptance decision. | +| GIS Query | A spatial Registry exposes Records through geographic relationships. | Supported spatial predicates, coordinate and geometry semantics, spatial and result bounds, and disclosure of protected Records or locations. | + +Every selected capability applies disclosure to both Record content and result metadata. Counts, ordering, page boundaries, confidence values, suggestions, and geometries must not reveal information that the consumer is not permitted to learn. + +## Binding status + +This release defines the abstract Retrieve operation but does not specify an HTTP binding or publish a canonical OpenAPI contract. An adopter prototyping Retrieve can use synchronous HTTP described by OpenAPI. A spatial Registry evaluating GIS Query can consider OGC API Features. These implementation choices do not create a GovStack capability claim. + +See [Service Interfaces](../09-service-interfaces.md), [Workflows](../10-workflows.md), and [Testing](../11-testing.md). + +## Example + +A licensing service retrieves the current permitted representation of a business registration by its Record Identifier. The Registry returns only the fields and metadata that service is authorised to receive. diff --git a/spec/5-api-families/evidence.md b/spec/05-api-families/evidence.md similarity index 71% rename from spec/5-api-families/evidence.md rename to spec/05-api-families/evidence.md index 1a5686a..ffd1bc9 100644 --- a/spec/5-api-families/evidence.md +++ b/spec/05-api-families/evidence.md @@ -18,15 +18,15 @@ Evidence enables a Registry Authority to issue a signed assertion derived from a | Wallet-mediated credential | The issuer delivers a credential to a holder-controlled wallet for later presentation to a verifier. | | Status and trust metadata | A verifier obtains the information needed to evaluate issuer trust, proof validity, schema, and current Evidence status. | -Evidence can express a narrowly scoped fact, including a yes-or-no assertion, or a defined set of claims. A complete profile needs to define claim minimisation, subject binding, validity, status, revocation or supersession, and verifier trust discovery. +Evidence can express a narrowly scoped fact, including a yes-or-no assertion, or a defined set of claims. An adopting authority that includes Evidence in its deployment needs to define claim minimisation, subject binding, validity, status, revocation or supersession, and verifier trust discovery. ## Capability boundary [Consultation](consultation.md) returns current Registry information. Evidence produces a signed assertion whose validity and status are interpreted under an Evidence profile. A Wallet can hold and present a credential but is not the authoritative source. An E-Signature service can perform cryptographic operations, while the Registry Authority remains responsible for the meaning of the assertion. -## Candidate bindings +## Binding status -OpenID for Verifiable Credential Issuance and Presentation and the W3C Verifiable Credentials model are candidates for wallet-mediated Evidence. An OpenAPI operation returning a signed attestation is a candidate for direct delivery. This release does not select a credential format or status mechanism. +This release does not specify an Evidence binding, credential format, or status mechanism. An adopter evaluating wallet-mediated Evidence can consider OpenID for Verifiable Credential Issuance and Presentation with the W3C Verifiable Credentials model. Direct delivery can be described through an OpenAPI operation returning a signed attestation. These choices do not create a GovStack capability claim. ## Example diff --git a/spec/05-api-families/identity-federation.md b/spec/05-api-families/identity-federation.md new file mode 100644 index 0000000..e973f06 --- /dev/null +++ b/spec/05-api-families/identity-federation.md @@ -0,0 +1,35 @@ +--- +description: Sectoral subject authentication and authorised claim release. +--- + +# Identity Federation + +> **Status:** Informative and not claimable in this release. Cross-Building-Block ownership is unresolved. No Identity Federation requirements, claim profile, protocol profile, or tests are published. + +## Purpose and applicability + +Identity Federation enables a sectoral Registry containing Records about people, or a service acting for its authority, to authenticate the person represented by a Registry Record to a Relying Service and release authorised claims. It applies to sector populations such as farmers, students, health-service users, or licensed professionals. + +## Cross-Building-Block ownership + +GovStack has not decided whether an Identity Federation profile for a functional sector identity is defined by Digital Registries, by the Identity Building Block, or jointly. The current [Identity Building Block description](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) scopes that Building Block to foundational identity while also discussing integration with functional identities. That provides context for the discussion but does not settle profile ownership. + +Until the Digital Registries and Identity teams agree the boundary, this page records only the candidate capability outcome. It does not assign specification ownership or establish a protocol binding. + +## Profile considerations + +Any eventual profile needs to define the relationship between the authenticated subject and the Registry Record, the lifecycle of the functional identifier, authorised claim release, subject-identifier policy, suspension or termination of the sector relationship, assurance expectations, and issuer topology. + +The functional identifier remains issued and lifecycle-managed by the responsible Registry Authority. The eventual profile also needs to define the use of issuer-scoped and pairwise subject identifiers where required to limit correlation. + +## Capability boundary + +Identity Federation is an outward-facing service to a Relying Service. It is separate from authentication and authorisation used to protect Registry APIs. It does not issue or replace foundational identity. An Identity service can provide upstream authentication or identity proofing without taking ownership of the sectoral identifier. + +## Binding status + +This release does not select a protocol binding for Identity Federation. OpenID Connect can be evaluated during the cross-Building-Block discussion, but this specification does not adopt it for this family or create a GovStack capability claim. + +## Example + +A professional Registry authenticates a licensed practitioner to a continuing-education service and releases an authorised claim that identifies the relevant professional sector. diff --git a/spec/5-api-families/notification.md b/spec/05-api-families/notification.md similarity index 63% rename from spec/5-api-families/notification.md rename to spec/05-api-families/notification.md index eb8b1be..fe8abfc 100644 --- a/spec/5-api-families/notification.md +++ b/spec/05-api-families/notification.md @@ -10,7 +10,7 @@ description: Authorised delivery of Registry change events. Notification informs authorised subscribers that Registry state changed. It applies when downstream systems need timely cache invalidation, propagation, or processing and cannot rely on polling Consultation. -## Candidate capability areas +## Capability areas | Area | Outcome | |---|---| @@ -21,13 +21,13 @@ Notification informs authorised subscribers that Registry state changed. It appl A change event is not necessarily the authoritative Record. A consumer that needs the current permitted representation uses [Consultation](consultation.md). Notification is also distinct from internal security and audit logging. -## Data and policy considerations +## Adoption considerations -A complete profile needs to define event identifiers, Registry and Record context, revision references, event types, occurrence and publication time, subscription authorisation, minimisation, ordering, duplicate handling, delivery guarantees, and replay. +An adopting authority that includes Notification in its deployment needs to define event identifiers, Registry and Record context, revision references, event types, occurrence and publication time, subscription authorisation, minimisation, ordering, duplicate handling, delivery guarantees, and replay. -## Candidate bindings +## Binding status -OpenAPI webhooks are candidates for HTTP push. AsyncAPI is a candidate description format for event-driven transports such as AMQP, MQTT, Kafka, or WebSockets. A Messaging or Information Mediator component can carry events without owning their Registry meaning. +This release does not specify a Notification binding. An adopter evaluating HTTP push can consider OpenAPI webhooks, while event-driven transports such as AMQP, MQTT, Kafka, or WebSockets can be described with AsyncAPI. A Messaging or Information Mediator component can carry events without owning their Registry meaning. These choices do not create a GovStack capability claim. ## Example diff --git a/spec/5-api-families/provisioning.md b/spec/05-api-families/provisioning.md similarity index 70% rename from spec/5-api-families/provisioning.md rename to spec/05-api-families/provisioning.md index 545bcfe..38f4fca 100644 --- a/spec/5-api-families/provisioning.md +++ b/spec/05-api-families/provisioning.md @@ -12,24 +12,24 @@ Provisioning configures a Registry service and publishes its externally visible Many authoritative registries do not need this family. Their authority and schema may be established by law, governance, or an operational process outside an API. -## Candidate capability areas +## Capability areas | Area | Outcome | |---|---| -| Metadata administration | Creates or revises the Registry's machine-readable identity and capability declarations through an administrative interface. Registry Core separately requires publication of the current service metadata. | +| Metadata administration | Creates or revises the Registry's machine-readable identity and capability declarations through an administrative interface. Registry Core separately requires publication of the current Registry metadata. | | Schema lifecycle | Publishes, revises, or retires a representation schema under defined compatibility rules. | | Interface publication | Declares supported families, sub-patterns, bindings, and access conditions. | | Bulk transfer | Initiates a controlled import or export of data and metadata. | These areas do not require dynamic database creation, a no-code builder, an administrative user interface, or a particular storage engine. Provisioning manages metadata programmatically; it does not make the Core publication requirement optional. It also does not perform the legal or governance act that establishes a Registry Authority. -## Data and policy considerations +## Adoption considerations -A complete profile needs to address administrative authorisation, schema compatibility, publication lifecycle, bulk-operation validation, provenance, and failure recovery. Those decisions are not defined in this release. +An adopting authority that includes Provisioning in its deployment needs to define administrative authorisation, schema compatibility, publication lifecycle, bulk-operation validation, provenance, and failure recovery. This release does not supply those deployment rules. -## Candidate binding +## Binding status -Synchronous HTTP described by OpenAPI is a candidate for administrative operations. Long-running bulk work may require an asynchronous job or messaging pattern. No binding is selected in this release. +This release does not specify a Provisioning binding. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI for administrative operations and an asynchronous job or messaging pattern for long-running bulk work, but those choices do not create a GovStack capability claim. ## Example diff --git a/spec/05-api-families/registry-core-context.jsonld b/spec/05-api-families/registry-core-context.jsonld new file mode 100644 index 0000000..a37ab51 --- /dev/null +++ b/spec/05-api-families/registry-core-context.jsonld @@ -0,0 +1,76 @@ +{ + "@context": { + "@version": 1.1, + "@protected": true, + "dcat": "http://www.w3.org/ns/dcat#", + "dct": "http://purl.org/dc/terms/", + "apif": "https://vocab.govstack.global/digital-registries/api-families#", + "govreg": "https://vocab.govstack.global/digital-registries#", + "prov": "http://www.w3.org/ns/prov#", + "skos": "http://www.w3.org/2004/02/skos/core#", + "title": { + "@id": "dct:title", + "@container": "@language" + }, + "description": { + "@id": "dct:description", + "@container": "@language" + }, + "publisher": { + "@id": "dct:publisher", + "@type": "@id" + }, + "catalogResource": { + "@id": "dcat:resource", + "@type": "@id" + }, + "catalogDataset": { + "@id": "dcat:dataset", + "@type": "@id" + }, + "catalogService": { + "@id": "dcat:service", + "@type": "@id" + }, + "conformsTo": { + "@id": "dct:conformsTo", + "@type": "@id" + }, + "authority": { + "@id": "govreg:authority", + "@type": "@id" + }, + "governedDataset": { + "@id": "govreg:dataset", + "@type": "@id" + }, + "dataService": { + "@id": "govreg:dataService", + "@type": "@id" + }, + "prefLabel": { + "@id": "skos:prefLabel", + "@container": "@language" + }, + "inScheme": { + "@id": "skos:inScheme", + "@type": "@id" + }, + "serviceType": { + "@id": "dct:type", + "@type": "@id" + }, + "servesDataset": { + "@id": "dcat:servesDataset", + "@type": "@id" + }, + "endpointURL": { + "@id": "dcat:endpointURL", + "@type": "@id" + }, + "endpointDescription": { + "@id": "dcat:endpointDescription", + "@type": "@id" + } + } +} diff --git a/spec/05-api-families/registry-core-vocabulary.ttl b/spec/05-api-families/registry-core-vocabulary.ttl new file mode 100644 index 0000000..db73967 --- /dev/null +++ b/spec/05-api-families/registry-core-vocabulary.ttl @@ -0,0 +1,157 @@ +@prefix apif: . +@prefix dcat: . +@prefix dct: . +@prefix govreg: . +@prefix owl: . +@prefix prov: . +@prefix rdfs: . +@prefix skos: . + + + a owl:Ontology ; + dct:title "Digital Registries Registry Core Vocabulary"@en ; + dct:description + "Defines the Registry class, its authority, dataset, and data-service relationships, and the controlled API-family concepts used in Digital Registries metadata."@en ; + dct:hasPart + . + +govreg:Registry + a owl:Class ; + rdfs:label "Registry"@en ; + rdfs:comment + "An institutionally governed system that maintains authoritative Records within a declared scope."@en ; + rdfs:isDefinedBy ; + rdfs:subClassOf dcat:Resource . + +govreg:authority + a owl:ObjectProperty ; + rdfs:label "registry authority"@en ; + rdfs:comment + "Relates a Registry to the institution accountable for it and its authoritative scope."@en ; + rdfs:domain govreg:Registry ; + rdfs:isDefinedBy ; + rdfs:range prov:Agent . + +govreg:dataset + a owl:ObjectProperty ; + rdfs:label "governed dataset"@en ; + rdfs:comment + "Relates a Registry to a governed collection described as a DCAT Dataset."@en ; + rdfs:domain govreg:Registry ; + rdfs:isDefinedBy ; + rdfs:range dcat:Dataset . + +govreg:dataService + a owl:ObjectProperty ; + rdfs:label "data service"@en ; + rdfs:comment + "Relates a Registry to a technical interface described as a DCAT Data Service."@en ; + rdfs:domain govreg:Registry ; + rdfs:isDefinedBy ; + rdfs:range dcat:DataService . + + + a skos:ConceptScheme ; + dct:title "Digital Registries API Families"@en ; + dct:description + "Controlled concepts used to identify the API families supported by a Digital Registries Data Service."@en ; + dct:isPartOf ; + skos:scopeNote + "When used as a dct:type value on a dcat:DataService, an API-family concept asserts that the service exposes at least one operation assigned to that family. It does not assert support for every capability pattern in the family or conformance to a GovStack profile."@en ; + skos:hasTopConcept + apif:access-transparency, + apif:aggregate-data, + apif:consultation, + apif:evidence, + apif:identity-federation, + apif:notification, + apif:provisioning, + apif:write . + +apif:consultation + a skos:Concept ; + skos:prefLabel "Consultation"@en ; + skos:notation "consultation" ; + skos:definition + "Capabilities through which a consumer obtains a permitted representation of Registry information."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:provisioning + a skos:Concept ; + skos:prefLabel "Provisioning"@en ; + skos:notation "provisioning" ; + skos:definition + "Capabilities for configuring a Registry service and publishing its externally visible contracts."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:evidence + a skos:Concept ; + skos:prefLabel "Evidence"@en ; + skos:notation "evidence" ; + skos:definition + "Capabilities through which a consumer obtains a signed assertion derived from authoritative Registry information."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:write + a skos:Concept ; + skos:prefLabel "Write"@en ; + skos:notation "write" ; + skos:definition + "Capabilities for creating a Record or accepting a new authoritative revision."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:notification + a skos:Concept ; + skos:prefLabel "Notification"@en ; + skos:notation "notification" ; + skos:definition + "Capabilities for informing authorised subscribers that Registry state changed."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:aggregate-data + a skos:Concept ; + skos:prefLabel "Aggregate Data"@en ; + skos:notation "aggregate-data" ; + skos:definition + "Capabilities through which a consumer obtains approved statistics derived from Registry Records."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:access-transparency + a skos:Concept ; + skos:prefLabel "Access Transparency"@en ; + skos:notation "access-transparency" ; + skos:definition + "Capabilities through which a consumer obtains a permitted view of access to a related Record."@en ; + skos:inScheme + ; + skos:topConceptOf + . + +apif:identity-federation + a skos:Concept ; + skos:prefLabel "Identity Federation"@en ; + skos:notation "identity-federation" ; + skos:definition + "Capabilities for authenticating a person represented by a sectoral Registry Record and releasing authorised claims to a Relying Service."@en ; + skos:inScheme + ; + skos:topConceptOf + . diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md new file mode 100644 index 0000000..6145482 --- /dev/null +++ b/spec/05-api-families/registry-core.md @@ -0,0 +1,370 @@ +--- +description: Shared identity, metadata, semantics, lifecycle, and provenance for every Registry capability. +--- + +# Registry Core + +> **Status:** The Registry Core requirements are DRAFT and form part of the target Base Registry Profile. They do not establish a certification claim in this release. + +## Purpose and applicability + +Registry Core is the shared foundation for every Digital Registries capability. It is not an API family. It defines how an implementation identifies the Registry and its authority and how returned Records identify their schema, semantic model, revision, lifecycle state, and minimum provenance. + +Every Registry implementation publishes its current metadata. [Provisioning](provisioning.md) can optionally provide an administrative interface for creating or revising that metadata, but Provisioning is not required for publication and does not establish the Registry Authority. + +## Conceptual model + +```mermaid +flowchart LR + REGISTRY[Registry] -->|has authority| AUTHORITY[Registry Authority] + REGISTRY -->|maintains| RECORD[Record] + REGISTRY -.->|governs| DATASET[DCAT Dataset] + REGISTRY -.->|offers| SERVICE[DCAT Data Service] + RECORD -->|has| REVISION[Record Revision] + REVISION -->|is returned as| REPRESENTATION[Permitted Representation] + MODEL[Schema and Semantic Model] -->|governs| REPRESENTATION +``` + +The model describes externally observable concepts rather than database tables, internal modules, or a deployment topology. An implementation can operate one Registry or many Registries and can expose one or more technical services without changing the meaning of the Registry itself. + +## Registry metadata + +The Registry metadata description identifies the institutionally governed Registry. It keeps the Registry distinct from its governed datasets, technical interfaces, and any catalogue in which it is listed. + +### Minimal metadata + +| Concept | Status | RDF alignment | Meaning | +|---|---|---|---| +| Registry Identifier | Required | Registry resource IRI | Globally unique and stable identifier for the Registry. | +| Registry Name | Required | [`dct:title`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#title) | Human-readable name used by adopters and consumers. | +| Registry Authority | Required | `govreg:authority` with a [`prov:Agent`](https://www.w3.org/TR/prov-o/#Agent) value | Institution accountable for the Registry and its declared authoritative scope. | +| Digital Registries specification version | Required | [`dct:conformsTo`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#conformsTo) | Versioned Digital Registries specification implemented by the service. | +| CFR version | Required | [`dct:conformsTo`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#conformsTo) | Versioned GovStack Common Requirements Framework implemented by the service. | +| Description | Optional | [`dct:description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description) | Human-readable description of the Registry and its scope. | +| Governed dataset | Optional and repeatable | `govreg:dataset` with a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset) value | A governed collection of Registry Records described for discovery or exchange. | +| Data service | Optional and repeatable | `govreg:dataService` with a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service) value | A technical interface that provides access to Registry data or operations. | + +The proposed GovStack vocabulary is intentionally small: + +| Term | Meaning | +|---|---| +| `govreg:Registry` | A specialisation of `dcat:Resource` for an institutionally governed system that maintains authoritative Records within a declared scope. | +| `govreg:authority` | Relates a Registry to the institution accountable for it and its authoritative scope. | +| `govreg:dataset` | Relates a Registry to a governed collection described as a DCAT Dataset. | +| `govreg:dataService` | Relates a Registry to a technical interface described as a DCAT Data Service. | + +The companion [Turtle vocabulary](registry-core-vocabulary.ttl) provides machine-readable definitions of these terms and the API-family concept scheme. It keeps the vocabulary separate from the instance data in the example below. + +The selected publication namespace is the dedicated `vocab.govstack.global` host. The Registry Core namespace document is `https://vocab.govstack.global/digital-registries`, and the API-family concept-scheme document is `https://vocab.govstack.global/digital-registries/api-families`. Terms use fragment IRIs so each small vocabulary can be retrieved as one document. These version-independent IRIs remain stable when the vocabulary evolves. + +The host must be provisioned so both namespace documents dereference before the vocabulary is published. Content negotiation can add HTML and JSON-LD representations without changing the term IRIs. The companion file does not make Turtle a required Registry metadata publication format or establish RDF conformance, and this release does not define a SHACL shape. + +The versioned [JSON-LD context](registry-core-context.jsonld) is assigned the publication URI `https://vocab.govstack.global/digital-registries/context/v1`. When the vocabulary host is provisioned, this URI serves the context with the `application/ld+json` media type. Context versions are immutable because changing a context can change how existing JSON is interpreted. Versioning the context does not version or otherwise change the vocabulary term IRIs. + +### DCAT composition + +The [Data Catalog Vocabulary 3](https://www.w3.org/TR/vocab-dcat-3/) describes the resources around a Registry rather than replacing the Registry concept: + +- the institutionally governed Registry is a `govreg:Registry`; +- each governed collection can be a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset); +- each technical API or query interface can be a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service); and +- a directory that lists Registries can be a [`dcat:Catalog`](https://www.w3.org/TR/vocab-dcat-3/#Class:Catalog). + +The base model does not require a Registry to operate its own catalogue. A national or sector directory can catalogue Registry descriptions, datasets, or services maintained by multiple authorities. + +### API family discovery + +A `dcat:DataService` can identify the Digital Registries API families that it supports using [`dct:type`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#type). Each value is a concept from the **Digital Registries API Families** concept scheme. The `apif:` prefix abbreviates the concept namespace. + +| Concept | API family | +|---|---| +| `apif:consultation` | Consultation | +| `apif:provisioning` | Provisioning | +| `apif:evidence` | Evidence | +| `apif:write` | Write | +| `apif:notification` | Notification | +| `apif:aggregate-data` | Aggregate Data | +| `apif:access-transparency` | Access Transparency | +| `apif:identity-federation` | Identity Federation | + +An API-family type means that the Data Service exposes at least one operation assigned to that family. It does not imply support for every capability pattern in the family and does not establish a GovStack conformance claim. The service's `dcat:endpointDescription` identifies the operational contract and exact operations. A separate `dct:conformsTo` statement identifies a formal profile that the service claims to satisfy. + +### Discovery publication + +Registry metadata and API discovery serve related but distinct purposes. A Registry description identifies the governed Registry and its authority. An API catalogue provides an entry point for finding the technical interfaces published on an HTTPS origin. + +An implementation can publish its canonical DCAT catalogue at a stable HTTPS URI. The recommended default is the root-relative `/catalog` URI on the public API origin, with DCAT representations available through HTTP content negotiation. The catalogue can describe one or more Registries, their governed datasets, and their data services. The catalogue URI is not itself a Registry Identifier, and deployments can select a different stable path. + +For standardised API discovery, an implementation can use [RFC 9727, *api-catalog: A Well-Known URI and Link Relation to Help Discovery of APIs*](https://www.rfc-editor.org/rfc/rfc9727.html). RFC 9727 defines `/.well-known/api-catalog` and the `api-catalog` link relation. It provides indirection from the well-known URI to the deployment's canonical catalogue, whether that catalogue is published at `/catalog` or another path. A deployment using RFC 9727 follows its GET, HEAD, HTTPS, and [`application/linkset+json`](https://www.rfc-editor.org/rfc/rfc9264.html) requirements. + +The current alpha treats this publication layout as discovery guidance rather than an additional Registry Core conformance requirement. A future HTTP and metadata binding can define required representations, content negotiation, caching, access policy, and validation. + +### Informative JSON-LD example + +The following JSON-LD document describes one business Registry, accountable authority, governed dataset, and Retrieve service. It references the versioned GovStack context, which maps readable JSON property names to the RDF vocabulary and identifies properties whose values are IRIs. Readers familiar with [W3C Verifiable Credentials Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) will recognise the `@context`, `@id`, and `@type` pattern, but this catalogue metadata is not a Verifiable Credential. The versioned GovStack specification IRIs are illustrative because this alpha does not publish canonical IRIs for them. + +```json +{ + "@context": "https://vocab.govstack.global/digital-registries/context/v1", + "@graph": [ + { + "@id": "https://registry.example/catalog", + "@type": "dcat:Catalog", + "title": { + "en": "Business Registry catalogue" + }, + "description": { + "en": "Discovery metadata for the Business Registry, its dataset, and its Retrieve API." + }, + "publisher": "https://registry.example/organisations/business-authority", + "catalogResource": "https://registry.example/registries/business", + "catalogDataset": "https://registry.example/datasets/business-records", + "catalogService": "https://registry.example/services/business-retrieve" + }, + { + "@id": "https://registry.example/registries/business", + "@type": [ + "govreg:Registry", + "dcat:Resource" + ], + "title": { + "en": "Business Registry" + }, + "description": { + "en": "Registry maintained for authoritative business registration records." + }, + "conformsTo": [ + "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "https://specs.govstack.example/cfr/2.1.0" + ], + "authority": "https://registry.example/organisations/business-authority", + "governedDataset": "https://registry.example/datasets/business-records", + "dataService": "https://registry.example/services/business-retrieve" + }, + { + "@id": "https://registry.example/organisations/business-authority", + "@type": "prov:Organization", + "title": { + "en": "Business Registration Authority" + } + }, + { + "@id": "https://registry.example/datasets/business-records", + "@type": "dcat:Dataset", + "title": { + "en": "Business registration records dataset" + }, + "description": { + "en": "Governed collection of business registration Records." + }, + "publisher": "https://registry.example/organisations/business-authority" + }, + { + "@id": "https://vocab.govstack.global/digital-registries/api-families", + "@type": "skos:ConceptScheme", + "title": { + "en": "Digital Registries API Families" + } + }, + { + "@id": "apif:consultation", + "@type": "skos:Concept", + "prefLabel": { + "en": "Consultation" + }, + "inScheme": "https://vocab.govstack.global/digital-registries/api-families" + }, + { + "@id": "https://registry.example/services/business-retrieve", + "@type": "dcat:DataService", + "title": { + "en": "Business Registry Retrieve API" + }, + "description": { + "en": "Retrieves the current permitted representation of a business Record." + }, + "conformsTo": [ + "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "https://specs.govstack.example/cfr/2.1.0" + ], + "serviceType": "apif:consultation", + "servesDataset": "https://registry.example/datasets/business-records", + "endpointURL": "https://registry.example/api/business", + "endpointDescription": "https://registry.example/contracts/business-retrieve.openapi.json" + } + ] +} +``` + +The Registry is also typed as [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) so that the catalogue can list it with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource). This does not make the Registry a dataset or a data service. The vocabulary expresses `govreg:Registry` as a subclass of `dcat:Resource`, while explicit dual typing keeps an instance understandable without ontology inference. + +The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in this catalogue. `govreg:dataset` and `govreg:dataService` state which dataset and service belong to this Registry. `dcat:servesDataset` states which dataset the technical service exposes. + +The `dct:type apif:consultation` statement lets a client discover the supported API family from the catalogue. The client follows `dcat:endpointDescription` to determine which Consultation operations are available and how to invoke them. + +The same graph pattern covers common deployment arrangements: + +- a single-Registry deployment publishes one Registry, its datasets, and its services in the catalogue; +- a multi-Registry implementation adds more Registry resources and their related datasets and services to the same catalogue; and +- an aggregating national catalogue can list resources from multiple Registry Authorities or use [`dcat:catalog`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_catalog) to include catalogues published by those authorities. + +The catalogue contains descriptive metadata only. It does not publish the protected Records contained in a governed dataset. + +### Client discovery workflow + +A client can discover supported API families without knowing an implementation's API paths in advance: + +1. Locate the canonical catalogue from a configured URI, the optional RFC 9727 well-known resource, or the recommended `/catalog` convention. +2. Retrieve a supported RDF representation of the catalogue, such as JSON-LD. +3. Select the required `govreg:Registry` by its stable Registry Identifier. +4. Follow `govreg:dataService` to each associated `dcat:DataService`. +5. Read each service's `dct:type` values from the Digital Registries API Families scheme, then follow `dcat:endpointDescription` for the exact operations and invocation contract. + +The following language-neutral pseudocode illustrates the process for a JSON-LD client: + +```text +catalogUri = configuredCatalogUri + +if catalogUri is absent: + catalogUri = discoverCatalogUsingRfc9727(apiOrigin) + +if catalogUri is absent: + catalogUri = resolve(apiOrigin, "/catalog") + +catalog = loadJsonLd(catalogUri) +registry = catalog.resourceWithId(requiredRegistryId) +supportedCapabilities = [] + +for each serviceReference in asList(registry.dataService): + service = catalog.resourceWithId(serviceReference) + + for each family in asList(service.serviceType): + if DigitalRegistriesApiFamilies contains family: + supportedCapabilities.append({ + family: family, + service: resourceIdentifier(service), + endpoint: service.endpointURL, + description: service.endpointDescription + }) + +return supportedCapabilities +``` + +Here, `loadJsonLd` applies the versioned context and normalises properties that can contain one or several values. `DigitalRegistriesApiFamilies` is populated from the published [API-family vocabulary](registry-core-vocabulary.ttl), not inferred from an IRI prefix. With the preceding example, the result identifies the Retrieve Data Service as supporting the Consultation family. If a Data Service omits `serviceType`, a client cannot infer API-family support from the catalogue alone, even when its endpoint description happens to contain related operations. + +### External alignments + +External vocabularies and application profiles can add jurisdictional or discovery semantics without becoming dependencies of Registry Core. + +| Alignment | Intended use | +|---|---| +| Schema.org [`Service`](https://schema.org/Service) or [`GovernmentService`](https://schema.org/GovernmentService) | Web discovery when the Registry or its service facet meets the selected Schema.org type. | +| [Core Public Service Vocabulary Application Profile](https://github.com/SEMICeu/CPSV-AP) | Public-service description in implementations using CPSV or CPSV-AP. | +| [BRegDCAT-AP](https://github.com/SEMICeu/BRegDCAT-AP) | European base-registry catalogue interoperability. | +| National or sector profiles | Additional legal, organisational, service, or dataset metadata required by an adopter. | + +An adopting profile can add types and properties when their semantics apply. Registry Core does not assert that `govreg:Registry` is universally equivalent to an external service or base-registry class. + +## Common Record context + +Every returned Record representation carries a common context in addition to its permitted domain data. + +| Concept | Purpose | +|---|---| +| Registry Identifier | Identifies the Registry that returned the representation. | +| Record Identifier | Stable reference to the Record within the Registry. | +| Revision Identifier | Identifies the current revision represented by the response. | +| Lifecycle State | State permitted by the declared representation schema. | +| Representation Format | Identifies the serialisation or media type through the applicable binding. | +| Schema Reference | Resolves to the machine-readable structure used to validate the domain data. | +| Semantic Model Reference | Identifies the vocabulary or domain model used to interpret the domain data. | +| Registry Authority | Identifies the institution responsible for the authoritative source. | +| Recorded At | Identifies when the current revision was recorded. | + +The applicable capability determines whether a representation contains domain data and which projection the consumer is permitted to receive. Protected metadata can be omitted or redacted only where the applicable representation schema and capability requirements keep the result unambiguous and valid. + +## Revisions and lifecycle + +The Record Identifier remains stable when a new revision is accepted. Revision identifiers distinguish successive representations of the same Record. + +The declared representation schema defines the supported lifecycle-state vocabulary. Terms such as active, inactive, superseded, archived, and deleted are examples, not a mandatory enumeration in this release. + +## Domain semantics and extensions + +The Digital Registries Building Block does not define a universal person, business, parcel, vehicle, health, or programme schema. Each returned representation identifies its machine-readable schema and published semantic model. An adopter can use an appropriate sector model and map national extensions explicitly. + +Extensions do not change the meaning of required Registry or Record metadata. Rules for unknown fields, compatibility, and schema evolution are not defined in this release. + +## Registry Core functional requirements + +### #1 Publish Registry metadata (DRAFT EXTENSIBLE AUDITABLE) + +`govstack-bb-digital-registries-fr-core#req-1` + +An implementation publishes machine-readable Registry metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, the Digital Registries specification version, and the GovStack CFR version it implements. + +**Purpose:** An adopter can determine which Registry and authority stand behind a service and which complete set of requirements applies. + +**Prerequisite:** The Registry Authority and authoritative scope have been established by the adopting organisation. + +**Verification:** Inspect the published Registry metadata, validate that all required values are present, and review evidence that the Registry Identifier is not shared with another Registry or changed between service revisions. + +### #2 Identify each returned Record (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-core#req-2` + +Every returned Record representation includes the Registry Identifier and a Record Identifier that is unique within that Registry. Together, the two identifiers uniquely identify the Record. + +**Purpose:** Consumers can distinguish Records from different Registries and refer to one Record without depending on mutable domain attributes. + +**Prerequisite:** A Record has been accepted into the Registry. + +**Verification:** Retrieve two distinct Record fixtures and verify that each response carries the expected Registry Identifier and a different Record Identifier. + +### #3 Preserve Record Identifiers (DRAFT EXTENSIBLE AUDITABLE) + +`govstack-bb-digital-registries-fr-core#req-3` + +An implementation keeps a Record Identifier unchanged throughout that Record's lifecycle and revisions and never reassigns the identifier to a different Record. + +**Purpose:** A Record reference remains unambiguous after changes, retirement, archival, or deletion. + +**Prerequisite:** The implementation has a documented Record Identifier lifecycle policy. + +**Verification:** Review the identifier policy and evidence showing that successive revisions retain the same identifier, distinct Records do not share an identifier, and retired identifiers are not returned to the allocation pool. + +### #4 Identify the Record schema, semantic model, and representation format (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-core#req-4` + +Every returned Record representation identifies a resolvable machine-readable schema and the published semantic model that govern its domain data. It also identifies its representation format through the applicable binding. + +**Purpose:** Consumers can decode and validate a representation and interpret its domain meaning without knowledge of the implementation's internal storage. + +**Prerequisite:** The Registry Authority has selected the applicable representation format, schema, and semantic model. + +**Verification:** Retrieve a Record, verify that the representation format conveyed by the binding matches the returned representation, resolve the declared schema, validate the representation, and resolve the semantic-model identifier to its published definition. + +### #5 Identify the current revision and lifecycle state (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-core#req-5` + +Every returned Record representation identifies its current revision and a lifecycle state permitted by the representation's declared schema. + +**Purpose:** Consumers can distinguish the current representation from earlier revisions and interpret its declared state. + +**Prerequisite:** The selected representation schema defines the supported lifecycle-state vocabulary. + +**Verification:** Retrieve fixtures in each lifecycle state exposed through Consultation, validate each state against the declared schema, and verify that each response identifies a current revision. + +### #6 Provide minimum Record provenance (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-core#req-6` + +Every returned Record representation identifies the Registry Authority as the responsible source and provides the time at which the current revision was recorded. + +**Purpose:** A consumer can assess the institutional source and currency of the authoritative information. + +**Prerequisite:** The Registry captures provenance for each accepted revision. + +**Verification:** Retrieve a Record and verify that the representation contains the Registry Authority identifier and recording time. Additional protected provenance details are outside this minimum requirement. diff --git a/spec/5-api-families/write.md b/spec/05-api-families/write.md similarity index 71% rename from spec/5-api-families/write.md rename to spec/05-api-families/write.md index 69cbbe7..db41869 100644 --- a/spec/5-api-families/write.md +++ b/spec/05-api-families/write.md @@ -18,15 +18,15 @@ Write creates a Record or accepts a new authoritative revision. It applies when | Governed write | A proposed change becomes authoritative only after the required review or approval process. | | Correction | A subject or authorised actor requests correction through the governed path defined for that Registry. | -A complete Write profile needs to define accepted transitions, validation, transition-specific authorisation, idempotency, concurrency, provenance, correction, retirement, and any legally defined deletion behaviour. +An adopting authority that includes Write in its deployment needs to define accepted transitions, validation, transition-specific authorisation, idempotency, concurrency, provenance, correction, retirement, and any legally defined deletion behaviour. ## Capability boundary The Registry Authority remains responsible for accepted transitions and the resulting authoritative state. A Registration, Workflow, or sector-specific service can own intake and approval and then submit an approved result. Write does not require the Registry to implement a general workflow engine. -## Candidate binding +## Binding status -Synchronous HTTP described by OpenAPI is the candidate general binding. Governed or long-running changes may also require an asynchronous status pattern. No binding or job model is selected in this release. +This release does not specify a Write binding or job model. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI for immediate changes and an asynchronous status pattern for governed or long-running changes, but those choices do not create a GovStack capability claim. ## Example diff --git a/spec/05-key-functionalities.md b/spec/05-key-functionalities.md new file mode 100644 index 0000000..98c3857 --- /dev/null +++ b/spec/05-key-functionalities.md @@ -0,0 +1,50 @@ +--- +description: Capability families provided by the Digital Registries Building Block. +--- + +# 5 Key Functionalities: API Families + +The Digital Registries Building Block groups its externally visible capabilities into eight families. A family describes an adopter outcome and a coherent trust boundary. It does not prescribe an internal module, product architecture, or transport. + +Only **Consultation Retrieve** is part of the target Base Registry Profile. The other Consultation sub-patterns and seven other families are informative in this release. They are not claimable because they do not yet have approved requirements, contracts, and tests. + +
Digital Registries Building Block capability families
Registry Core provides the shared foundation. The target Base Registry Profile adds Consultation Retrieve.
+ +## 5.1 Reading capability requirements + +Requirements are placed with the capability to which they apply. Shared requirements are defined under [Registry Core](05-api-families/registry-core.md), while family-specific requirements are defined on the applicable family page. + +Each requirement follows the GovStack Requirements Model. `DRAFT` means that the requirement is available for review but is not included in certification. Requirement identifiers are permanently reserved even while the requirement is DRAFT. + +This organisation and the capability-specific requirement namespaces are provisional pending resolution of [GovStack CFR issue #7](https://github.com/GovStackWorkingGroup/cfr-architecture/issues/7) on optional capabilities and conformance profiles. + +This release contains only requirements that support the target Base Registry Profile. Informative capability descriptions do not create requirements or have conformance effect. + +## 5.2 Registry Core + +Registry Core provides the identity, metadata, Record reference, semantic, lifecycle, and provenance foundation shared by every API family. It is not itself an API family. Every family-specific profile inherits the [Registry Core model and requirements](05-api-families/registry-core.md) rather than restating them. + +## 5.3 Family catalogue + +| Family | Adopter outcome | Capability patterns | Status in this release | +|---|---|---|---| +| [Consultation](05-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, Existence Check, List, Search, Revision History, Record Match, GIS Query | Retrieve is in the target Base Registry Profile; other patterns are informative. | +| [Provisioning](05-api-families/provisioning.md) | Configure a Registry service and publish its externally visible contracts. | Metadata administration, schemas, capability publication, bulk transfer | Informative | +| [Evidence](05-api-families/evidence.md) | Obtain a signed assertion derived from authoritative Registry information. | Direct attestation, wallet-mediated credential, status | Informative | +| [Write](05-api-families/write.md) | Create a Record or accept a new authoritative revision. | Direct write, governed write, correction | Informative | +| [Notification](05-api-families/notification.md) | Inform authorised subscribers that Registry state changed. | Subscribe, filter, deliver, retry, replay | Informative | +| [Aggregate Data](05-api-families/aggregate-data.md) | Obtain approved statistics derived from Registry Records. | Aggregate query, dataset metadata, published release | Informative | +| [Access Transparency](05-api-families/access-transparency.md) | Obtain a permitted view of access to a related Record. | Access-history consultation | Informative | +| [Identity Federation](05-api-families/identity-federation.md) | Authenticate a person represented by a sectoral Registry Record to a Relying Service and release authorised claims. | Profile ownership and binding to be decided with the Identity team | Informative; cross-BB ownership unresolved | + +## 5.4 Selecting families + +An adopter selects capabilities from the Registry's institutional responsibilities, domain model, and consumer needs, not from the feature list of a particular product. Useful questions include: + +- Does the Registry expose only current Records, or also search, historical revisions, mutation, events, evidence, statistics, or subject authentication? +- Which actors can invoke each capability, and what may each actor learn? +- Does the Registry own an approval process, or accept an approved result from another service? +- Does the consumer need live Registry information, a portable proof, or notification that state changed? +- Which sector semantic model and protocol binding fit the participating systems? + +Each family page states its boundary and maturity. A registry or sector profile supplies the domain-specific schemas, lifecycle vocabulary, query semantics, and other constraints needed by its selected capabilities. A capability without published requirements, a binding, and tests cannot be included in a GovStack conformance claim for this release. diff --git a/spec/9-service-interfaces.md b/spec/09-service-interfaces.md similarity index 53% rename from spec/9-service-interfaces.md rename to spec/09-service-interfaces.md index a3e0221..4fe4aa9 100644 --- a/spec/9-service-interfaces.md +++ b/spec/09-service-interfaces.md @@ -1,5 +1,5 @@ --- -description: Abstract operation and proposed HTTP binding for Consultation Retrieve. +description: Abstract operation and binding status for Consultation Retrieve. --- # 9 Service Interfaces @@ -18,15 +18,15 @@ The previous generated CRUD OpenAPI files are legacy artifacts. They are not con | Purpose | Obtain the current permitted representation of one Record. | | Required input | Record Identifier. | | Request context | Authentication and authorisation information required by the deployment and inherited CFR requirements. | -| Success output | Current permitted Record representation described in [Data Structures](8-data-structures.md). | -| Unsuccessful output | Problem response without protected Record data and with the protected-existence handling required by `fr-consultation#req-3`. | -| Excluded behaviour | List, Search, Record Match, GIS Query, historical-revision retrieval, and individual stored-field retrieval. | +| Success output | Current permitted Record representation described under [Consultation](05-api-families/consultation.md#retrieve-representation), including the [common Record context](05-api-families/registry-core.md#common-record-context). | +| Unsuccessful outcome | Outcome without protected Record data and with the protected-existence handling required by `fr-consultation#req-3`. | +| Excluded behaviour | Existence Check, List, Search, Revision History, Record Match, GIS Query, and individual stored-field retrieval. | -## 9.3 Proposed HTTP binding +## 9.3 Binding status -The initial binding is synchronous HTTP over HTTPS and will be described by an OpenAPI contract. The contract will use the shared GovStack API components for problem details and other cross-BB structures once those components and their consumption rules are ratified. +No canonical OpenAPI contract is published in this release, so an implementation-specific HTTP interface cannot be used to establish a GovStack capability claim. An adopter prototyping Retrieve can use synchronous HTTP over HTTPS and describe that interface with OpenAPI. -No canonical OpenAPI file is published in this release. A future contract needs to define: +An HTTP contract used by an adopter needs to define: - resource path and API versioning; - exact Registry and Record metadata property names; @@ -35,14 +35,14 @@ No canonical OpenAPI file is published in this release. A future contract needs - policy-compliant mapping of unknown, unauthorised, inactive, and superseded outcomes; and - contract examples that do not assume a person registry. -## 9.4 Candidate bindings for later capabilities +## 9.4 Protocol options for additional capabilities -The following standards are informative candidates for capabilities that are not claimable in this release. This table does not establish a required version or profile. +The following standards can help an adopter evaluate implementation options for capabilities that are not claimable in this release. The table does not establish a required specification, version, or profile. -| Capability | Candidate specification | +| Capability | Protocol options | |---|---| | Provisioning and general HTTP operations | OpenAPI | -| Consultation Retrieve, List, Search, and Record Match | OpenAPI | +| Consultation Retrieve, Existence Check, List, Search, Revision History, and Record Match | OpenAPI | | GIS Query | OGC API Features | | Wallet-mediated Evidence | OpenID for Verifiable Credential Issuance and Presentation; W3C Verifiable Credentials | | Direct Evidence | OpenAPI with a signed credential or attestation format | @@ -50,4 +50,4 @@ The following standards are informative candidates for capabilities that are not | Notification | OpenAPI webhooks for HTTP push; AsyncAPI for event-driven bindings | | Aggregate Data | OpenAPI; SDMX for statistical exchange | | Access Transparency | OpenAPI | -| Identity Federation | OpenID Connect Core and Discovery | +| Identity Federation | No protocol option selected; profile ownership and binding remain subject to cross-BB agreement with the Identity team | diff --git a/spec/10-workflows.md b/spec/10-workflows.md index 85fdd00..bc7b073 100644 --- a/spec/10-workflows.md +++ b/spec/10-workflows.md @@ -18,7 +18,7 @@ This workflow describes externally observable behaviour. It does not prescribe i 1. The Registry publishes the identity metadata required by Registry Core. 2. The API Consumer has the credentials and request context required by the deployment. -3. The current Record representation identifies its schema, semantic model, revision, lifecycle state, and minimum provenance. +3. The current Record representation identifies its representation format, schema, semantic model, revision, lifecycle state, and minimum provenance. 4. The implementation can determine the permitted representation for the API Consumer and request context. ### Interaction @@ -27,7 +27,7 @@ This workflow describes externally observable behaviour. It does not prescribe i 2. The Registry authenticates the caller and evaluates access and disclosure policy. 3. If the policy permits access, the Registry resolves the current revision and lifecycle state. 4. The Registry constructs the permitted representation, including the Record context required by Registry Core. -5. The Registry returns the permitted representation or the applicable problem response. +5. The Registry returns the permitted representation or the applicable unsuccessful outcome. ### Outcomes @@ -35,11 +35,11 @@ This workflow describes externally observable behaviour. It does not prescribe i |---|---| | Current Record is accessible | Current permitted representation is returned. | | Consumer has narrower disclosure rights | A valid filtered or redacted representation is returned. | -| Identifier is unknown | The implementation returns its unknown-identifier problem response. | -| Consumer may not learn whether a protected Record exists | The response is indistinguishable under the published contract from the unknown-identifier response, including security-relevant headers and non-Record-specific problem values. Independently generated correlation values may differ, and no Record-specific data is returned. | +| Identifier is unknown | The implementation returns its unknown-identifier outcome. | +| Consumer may not learn whether a protected Record exists | The outcome is indistinguishable under the published contract from the unknown-identifier outcome, including the same status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values. Independently generated trace or correlation values may differ, and no Record-specific data is returned. | ### Postconditions - The Record is not modified by the operation. - The returned representation identifies the same Record Identifier requested by the consumer. -- A successful response identifies the Registry, current revision, lifecycle state, schema, semantic model, Registry Authority, and recording time. +- A successful response identifies the Registry, current revision, lifecycle state, representation format, schema, semantic model, Registry Authority, and recording time. diff --git a/spec/11-testing.md b/spec/11-testing.md index 110e4cf..ad5d635 100644 --- a/spec/11-testing.md +++ b/spec/11-testing.md @@ -1,5 +1,5 @@ --- -description: Proposed verification for the Base Registry Profile. +description: Verification approach for the Base Registry Profile. --- # 11 Testing @@ -12,9 +12,9 @@ Legacy Cucumber tests under `test/openAPI` exercise the previous generated CRUD ## 11.2 Required fixtures -A candidate implementation provides non-production fixtures for: +An implementation being evaluated provides non-production fixtures for: -- machine-readable service metadata; +- machine-readable Registry metadata; - two distinct current Records in the same Registry; - a current Record accessible to two consumers with different disclosure rights; - evidence of the identifier lifecycle across successive revisions and retired Records; @@ -28,17 +28,17 @@ Testers use synthetic fixtures rather than real personal or confidential data. | Requirement | Verification item | Expected result | |---|---|---| -| `fr-core#req-1` | Inspect machine-readable service metadata and identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, Digital Registries specification version, and CFR version are present. | +| `fr-core#req-1` | Inspect machine-readable Registry metadata and identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, Digital Registries specification version, and CFR version are present. | | `fr-core#req-2` | Retrieve two distinct Records | Each response includes the Registry Identifier and a different Record Identifier; each identifier pair is unique. | | `fr-core#req-3` | Inspect the identifier policy and lifecycle evidence | A Record Identifier remains unchanged across revisions and lifecycle states, is not shared, and is not reassigned after retirement. | -| `fr-core#req-4` | Validate a retrieved representation | Schema and semantic-model references resolve, and schema validation succeeds. | +| `fr-core#req-4` | Validate a retrieved representation | The representation format conveyed by the binding matches the representation, schema and semantic-model references resolve, and schema validation succeeds. | | `fr-core#req-5` | Retrieve fixtures across exposed lifecycle states | Each response identifies the current revision and a lifecycle state permitted by its declared schema. | | `fr-core#req-6` | Retrieve a known accessible Record | Registry Authority identifier and recording time are present. | | `fr-consultation#req-1` | Retrieve a known accessible Record | Current permitted representation is returned with required Record context. | | `fr-consultation#req-2` | Retrieve the same Record as two consumers | Each response contains only the projection permitted to that consumer. | -| `fr-consultation#req-3` | Retrieve unknown and protected identifiers as the same consumer | Status or error category, security-relevant headers, stable problem type or code, response schema, and non-Record-specific problem values match; any differing correlation values are independent of Record existence; neither response contains Record-specific data. | +| `fr-consultation#req-3` | Retrieve unknown and protected identifiers as the same consumer | Status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values match; any differing trace or correlation values are independent of Record existence; neither response contains Record-specific data. | -The abbreviated references in this table use the full `govstack-bb-digital-registries` namespaces defined in [Functional Requirements](6-functional-requirements.md). +The abbreviated references in this table use the full `govstack-bb-digital-registries` namespaces defined under [Registry Core](05-api-families/registry-core.md#registry-core-functional-requirements) and [Consultation](05-api-families/consultation.md#retrieve-functional-requirements). ## 11.4 Behaviour scenarios @@ -50,7 +50,7 @@ Feature: Retrieve the current permitted Registry Record And an API Consumer authorised to receive its standard representation When the consumer retrieves the Record by that identifier Then the Registry returns the current permitted representation - And the representation identifies its Registry, revision, lifecycle state, schema, semantic model, Registry Authority, and recording time + And the representation identifies its Registry, revision, lifecycle state, representation format, schema, semantic model, Registry Authority, and recording time And the retrieval does not modify the Record Scenario: Consumers receive different permitted representations @@ -62,9 +62,9 @@ Feature: Retrieve the current permitted Registry Record Given a consumer that is not authorised to know whether a protected Record exists And an unknown Record Identifier When the consumer requests the protected and unknown Record Identifiers - Then both responses use the same status or error category - And both responses use the same security-relevant headers, stable problem type or code, response schema, and non-Record-specific problem values - And any differing correlation values are generated independently of Record existence + Then both responses use the same status or protocol outcome + And both responses use the same security-relevant response metadata, stable error type, response structure, and non-Record-specific values + And any differing trace or correlation values are generated independently of Record existence And neither response contains Record-specific data ``` diff --git a/spec/12-other-resources/README.md b/spec/12-other-resources.md similarity index 67% rename from spec/12-other-resources/README.md rename to spec/12-other-resources.md index 68baf34..66bcf89 100644 --- a/spec/12-other-resources/README.md +++ b/spec/12-other-resources.md @@ -12,7 +12,7 @@ The 3.0.0-alpha.2 specification provides a minimum Registry model and DRAFT requ |---|---| | Registry scope and exclusions | Final capability-discovery format | | Base Registry Profile | Canonical HTTP path and JSON schema | -| Registry Core DRAFT requirements | Retrieval of historical revisions | +| Registry Core DRAFT requirements | Revision History contract and tests | | Consultation Retrieve DRAFT requirements | Optional-family requirements and tests | | Conceptual external data model | Named multi-family conformance profiles | | Retrieve workflow and verification intent | Domain-specific semantic models | @@ -21,19 +21,19 @@ The 3.0.0-alpha.2 specification provides a minimum Registry model and DRAFT requ ## 12.2 Specification decisions - The specification defines the external service behaviour of a Digital Registries implementation for records under a Registry Authority's declared scope. It does not prescribe a database platform. -- The proposed Base Registry Profile consists of Registry Core plus Consultation Retrieve. +- The target Base Registry Profile consists of Registry Core plus Consultation Retrieve. - Retrieve returns a permitted representation and does not imply public or complete-record access. -- List, Search, Record Match, and GIS Query are distinct optional Consultation sub-patterns. +- Existence Check, List, Search, Revision History, Record Match, and GIS Query are distinct optional Consultation sub-patterns. - Additional API families remain informative until each has requirements, a contract, and tests. +- DCAT 3 is the primary candidate for a future Registry and service discovery profile. Specialised DCAT profiles may inform individual mappings but are not conformance dependencies for this alpha. - Internal storage, administrative UI, deployment topology, multi-tenancy, and automatic API generation are implementation choices. - Domain data models are selected and declared by the Registry Authority rather than standardised by the Building Block. -- Authentication protecting Registry APIs is distinct from the optional Identity Federation family. +- Authentication protecting Registry APIs is distinct from the candidate Identity Federation family. Ownership of that family remains subject to agreement with the Identity team. ## 12.3 Migration and history -- [Migration from the 3.0.0-alpha.1 Draft](migration-from-3.0.md) records the disposition of every previous DRS requirement. -- [Release Notes](../1-version-history/release-notes.md) preserve detailed historical contributors and changes. -- [Historical Key Decision Log](historical/key-decision-log.md) and [Historical Future Considerations](historical/future-considerations.md) are retained as working-group history. They are not part of conformance for this release. +- [Migration from the 3.0.0-alpha.1 Draft](12-other-resources/migration-from-3.0.md) records the disposition of every previous DRS requirement. +- [Release Notes](01-version-history/release-notes.md) preserve detailed historical contributors and changes. The OpenAPI files under `api/legacy/generated-crud/` and Cucumber scenarios under `test/openAPI/` describe the previous generated CRUD interface. They are legacy artifacts and are not service contracts or conformance tests for this release. @@ -41,4 +41,4 @@ The OpenAPI files under `api/legacy/generated-crud/` and Cucumber scenarios unde Actors, organisational responsibilities, domain governance, semantic choices, and multi-Building-Block deployment patterns belong in a Registry Reference Architecture or implementation guide. They are useful to adopters but do not alter the technical conformance contract in this specification. -See [References](references.md) for standards and related GovStack material. +See [References](12-other-resources/references.md) for standards and related GovStack material. diff --git a/spec/12-other-resources/historical/future-considerations.md b/spec/12-other-resources/historical/future-considerations.md deleted file mode 100644 index be479a2..0000000 --- a/spec/12-other-resources/historical/future-considerations.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -description: Archived future-consideration backlog from earlier Digital Registries versions. ---- - -# Historical Future Considerations - -> **Archived and non-normative.** This page preserves an earlier working-group backlog. Statements and proposed requirements on this page are not part of the current specification. - -12.1 Integration with a blockchain solution to guarantee the integrity of the data and logs. The function would notice unauthorized changes in data. This option may be available with a fee therefore should be optional. - -12.2 Implementation improvements- system installation could be done with more simplifications so it would be a full SAAS cloud solution. - -12.3 Data validation and evaluation tools could be developed into the core Registries BB logic so it would generate warnings if data quality issues appear. - -12.4 Event based automated data export from Registries BB to legacy databases. Connection with messaging and workflow BB is required. - -12.5 Plug-in no-code connector to existing registry databases. It's currently a challenge to connect to existing registry databases. As a solution, the Digital Registries BB could offer a plug-in tool to connect existing databases to Information Mediator without the need to develop custom connectors. - -12.6 Open data component. It should be possible to mark down the data that must be visible as open data (API, bulk download). - -12.7 Personal data usage in Digital Registries in synchronization with Consent Management BB capabilities. - -12.8 Enable to connect Digital Registries BB to Verifiable Credential networks (W3C VC). - -12.9 Analyze a way to enable analyst to decide which data must be encrypted while in rest. The goal is to secure data while in rest. - -12.10 Data MUST be protected by proper anonymisation with analytics and related reporting functions. Proper analysis and user requirements mapping must be done based on a real use case. - -12.11 Maintenance functionalities and roles to help everyday operations of registries. - -12.12 Review results to be added to the next versions of the specifications. See decisions in the following table. - - - -| Comments/Feedback | Suggested Action/Reason | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|

DRS-3 Add fields to DB schema.

Does that means that collection types are not supported? For example, I want Applicant to submit her employments records history and I will define fields for one employment and then I want to define a history object, which is collection of employment records sorted by time. Then I want to add some validation rules not to a field but to a collection. Can I do that? How can I do that?

|

In most cases, the validation is done upon capturing data (Registration BB).


In Digital Registries basic validation rules for single record are in place (required, unique).


When the use case requires to add more validation functionality (e.g. to collection types), it will be added in the next iteration.


| -|

Associated meta data against (for) these actions (Enrol, Authenticate, Consent, Attest, Claim, Discover and Update actions ) MUST be part of the registry to bring in the authenticity and non-repudiability of registry data.




|

The UI and API has all necessary functions. If new functions are needed then these will be added during develop time.


11.1 Integration with a blockchain solution to guarantee the integrity of the data and logs. The function would notice unauthorized changes in data. This option may be available with a fee therefore should be optional.

| -|

Registries MUST support verifiable credentials (W3C VC) services using the trusted registry data as an integrated service with in this BB. This VC SHALL work both in Online and Offline modes.


| 11.8 Enable to connect Digital Registries BB to Verifiable Credential networks (W3C VC). | -|

Data MUST be secured during capture, transmission and rest with right encryption along with integrity protection.



|

Data is secured when in transit by Information Mediator (BB). The communication uses encryption in all endpoints.


Data in rest will be taken as a next challenge in V2.


Integrity protection is planned in V2 as well.


11.9 Analyse a way to enable analyst to decide which data must be encrypted while in rest. The goal is to secure data while in rest.

| -|

Data MUST be protected for privacy with appropriate roles and access permission for downstream consumption. This SHALL be using other BBs.



|

Yes, in Key Digital Functionalities chapter we describe it like this:


12. Manage access to registry data. Authorize users to see and edit registry records or data field (ABAC based access management).


DRS-6- Authorization to create and manage databases, API usage and access to DATA.


Additional requirements will be added based on real Use Cases.

| -|

Data MUST be protected by proper anonymisation with analytics and related reporting functions.


| 11.10 Data MUST be protected by proper anonymisation with analytics and related reporting functions. Proper analysis and user requirements mapping must be done based on a real use case. | -|

The scope is limited to simple registries. In real life, we are likely to have registries that require a multi level structure. In RDBMS terms, the data for a registry may need to be stored in multiple tables. It is not easy to handle such entities by defining foreign keys among tables. There should be a clear mechanism identified to handle digital registries that have a multi-level structure.


While it may appear easy to create a new API end point for every version, this places undue burden on the calling systems. Whenever a new API version is launched, the calling system will have to be modified to refer to the new API end point.


It is also quite difficult to invoke different API end points from the same front-end. Instead of this, the API end point should remain the same and the payload should indicate the version.

|

The requirements are based on a USE CASE with minimal viable product methodology. Therefore the complex database structure was not needed, thus the requirements focused on simple case. However the requirements to build more complex data storing structures can be added when use cases require it.

Digital Registries enables to create multi level registries.


For example if we rename a database to a table, and tables can be linked with foreign keys, then we have a multi level registry. In Digital Registries description we decided to name the tables as databases because this improves the user experience. See example illustration below:



The issue with API endpoint versions may need some clarification in the specification.

Currently we have written (DRS-4):

“Publish uses versioning. Every publish creates a new version of the database schema;

Old database schemas must be available to the users;

Data stored in the old database versions must be usable in old versions and in new versions; “

This description should be clear enough to explain that the users can still work with old API versions and do not have to switch to new API versions right away. However there is a risk that large schema changes may influence the old APi versions and therefore the system has a limit. We will analyze the risks and schema version options in the V2.


| -|

2.2 Event based notifications.

I see that as an issue. Subject of the Registry record may have specific life-cycle and on event of life-cycle there is a need to do some things, which is the reason why Registry even exists. For example, when driver license is expiring and state cannot notify person about that - I would say it is dysfunctional registry of driver licenses.

|

Yes, this function will be added in the iteration 2. Use cases did not require such functionality right away.


11.4 Event based automated data export from Registries BB to legacy databases. Connection with messaging and workflow BB is required.

| -|

DRS-3

you should add also time range

| Modifications acceptable but to be taken up in future version | -|

DRS-3

what kind of language should analyst to learn in order to express all that? One may provide, for example, embedded JavaScript editor. Will it be OK for being compliant with the spec?

|

We have no-code policy. Therefore, all functions must be available via user interface (and API). Advanced regex, JavaScript options could be added, but this is the decision in the implementation phase by the implementers.


Modifications acceptable but to be taken up in future version


| -|

DRS-4

before publishing I would recommend to have option for testing

| Noted. Will be added to the future functionality. | -| 3. Registries MUST support Enrol, Authenticate, Consent, Attest, Claim, Discover and Update actions using Registry and/or other BBs. Discover and update SHALL naturally fit into Registry BB. |

Enroll, Authenticate is solved by Information mediator and Security BB. Additional IAM system will be available for authorization.

Consent is in the scope of Consent management BB. Integration will be added in V2.

| -|

4.4

there are couple of important technical requirements missing with regard to API. For example, see Payments BB section 6.1.1 API management Gateway. I suggest to have generic API requirements description and here just refer to that.

|

To be analyzed in V2.

API Management Gateway

Handles all the API messaging calls and API access control verification from other BBs to the Payment BB and vice versa as well as within the Payment BB. All requests from other BBs first go through the API gateway. The gateway then routes requests to the appropriate application/service. The API Management gateway will:

  • Use Identity and access management for authentication

  • Perform input validation checks to prevent oversized message attacks, SQL injection attacks as well as JSON and XML threats,

  • Require authentication for all API users;

  • Manage access quotas and throttling;

  • Logging of all API calls made

  • Allow API providers to limit the rate of consumption for all API users.

  • Transform backend error messages into standardized messages so that all error messages look similar; this also eliminates exposing the backend code structure.
| -| The authors try to treat analyst and administrator as one user category and applicant as another user category. It could be a better idea to have three distinct roles viz., analyst, administrator and applicant. The analyst should be responsible for preparing the design and he/she should control the database design. The analyst should have no role to play in data administration. That responsibility should be with the administrator. Otherwise, we may be combining the responsibilities of architects and operators. |

Use cases currently do not require administrators. These role descriptions can be added later during implementation phase.

11.11 Maintenance functionalities and roles to help everyday operations of registries.

| -|

6.3
Conflicting - Earlier in the doc, it mentions views for personal data, but no information on how personal data should be accessed

Generic Comment - No ability to get user consent while accessing personal data.

|

According to our vision, personal data is like any other data that can be accessed by API or via user interface. Respective authorization must be granted in order to CRUD Personal data.


The principles of user consent is governed by Consent Management BB.


Modifications acceptable but to be taken up in future version.


Decisions: I added a line in the Future scope for the Consent Management.

11.7 Personal data usage in Digital Registries in synchronization with Consent Management BB capabilities.


| diff --git a/spec/12-other-resources/historical/key-decision-log.md b/spec/12-other-resources/historical/key-decision-log.md deleted file mode 100644 index d5115f8..0000000 --- a/spec/12-other-resources/historical/key-decision-log.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -description: Archived decision discussions from earlier Digital Registries versions. ---- - -# Historical Key Decision Log - -> **Archived and non-normative.** This page preserves decision discussions from earlier Digital Registries versions. It does not define requirements, scope, or conformance for the current specification. - -* The UNCTAD’s Generic Database Builder (eRegistrations) system will be used as a reference system in describing the functional requirements. -* 23.09.2021 - WG meeting, based on review recommendations made by Architecture WG, we decided to add API services or IT-specialists to create/modify/delete registry database schema. -* 22.11.2021 - Coverage map chapter will be added to the document. -* 28.02.2022 - Review comments incorporated to the main document (v1.1.0) 24.02.2022 (see below). Future consideration chapter updated based on reviewers comments. Recommendations not to be considered in this building block documented (see below) - - - -| Comments/Feedback | Suggested Action/Reason | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1. Incorporated in V1 | | -|

2. Key Digital Functionalities.

I would add here capability to manage access to the Registry data

|

Yes, see requirement DRS-6

Modifications to be absorbed in this version


Sharing data with others is a function that was added to the requirements. See DRS-33

| -|

2. Key Digital Functionalities.

currently, my impression is that the Registration BB is optimised for entering and processing data and not for retrieval and usage. I see it as a missing capability requirement.

|

Registration BB functionality is described in another document. Pull (read) data functionality in Registration BB improved.


Modifications to be absorbed in this version:

1. add arrows to the drawing to reflect the two-way communication.

See data retrieval API Open API services descriptions for more information.



| -|

DRS-2. Foreign keys.

I am not sure, I can understand the way how FK-s suppose to work (see comment below in Appendix 2)

|

Databases in this concept are stored as tables, thus the foreign key works the same as in a structured database. In the Digital Registries user interface it must be possible to open another database by clicking on the ID of one database and all corresponding records from the other database will open. In API, the developers can decide how to use the Foreign key to improve the UX.


Modifications to be absorbed in this version:

We improved the functionality description.

| -|

DRS-3

1. does it includes Dropbox option to select from List of Values (LOV)? How can I define List values and how can I attach it to field in a form?

2. Does it includes option for hierarchy of List of Values, where selected value in one LOV defines subset of allowable options in another LOV?

|

1. yes, catalog/select values are used, however this is managed by client UI (Registration BB). Digital registries is storing data/ key of the list element. Catalogs are managed in Registration BB/ other BB.

2. Sub-catalogues function and the control could be added to Registration BB when required by the Use Case. Digital Registries BB contains Enum list validation option.

Modifications acceptable but to be taken up in future version

| -|

6.

I was talking about the REST endpoint URL. The URL has a placeholder for version (marked as {version}). I believe it to be the version of the API being called, but the document throughout talks about DB schema version, and no mention of this version being the version of the API. That could create confusions on what the parameter "version" is.

|


Thank you for the clarification. Will be implemented in this version.

The system generates default API method endpoints automatically after each publish of the database schema. A new API service version is generated after each schema publish. Database schema version and API versions are in sync. I hope this clarifies the confusion.

| - - - -| 3. Not to be considered | | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -|

General recommendation.

Harmonize all URLs across all building blocks. The slide deck and the specs documents don't correspond very well and at times contradict. For example, the Purpose of the Registries BB isn't articulated in the Specs doc but appears only in the slide deck.

|

Not implemented.

Purpose is described in the specification and in the powerpoint. It is unclear what was expected.


| -| 2. Registries MUST adhere to core principles of data being Live, Reusable and Trustworthy. |

Registry management principles would be another document - user manual, or best practices to build digital registries.

Some examples:

UNCITRAL Legislative Guide on Key Principles of a Business Registry | United Nations iLibrary


| -|

Registry SHALL support use of multiple data stores like RDBMs, NoSQL and Graph to represent the data representation across domains.



| We are not restricting the support of any mentioned database types. | -|

Registry MAY optionally support to do payload level encryption (especially for highly sensitive data) over transport layer to ensure backend services (beyond TLS termination) handle data securely.



|

This is solved by Information Mediator BB.


| -|

Section 7 states, this BB doesn't have internal workflows. But this BB MUST support meta data about workflows on who has attested the data.


| Yes, metadata is like any data that can be added to the Digital Registries Database. Analyst can decide how to store the processing information. | -| Since APIs are available to access the digital registries, there is no need to have a separate data access mechanism for the administrators. It is important to use the same APIs in the user interface proposed for the administrators. | UI is needed for analysts to improve the UX. Same API will be used to create databases. | -|
  1. Description.

I understood, that authors divided overall registration domain into two parts: Registration BB covers process of submitting applications and processing the data to make decision and here suppose to be a Registry usage part. However, I do not see here specifics about usage of registries. For example, usage of Registry may have complex access rules, requirements of fast access to large data sets etc. I do not see any discussion here on those matters

|

This BB is about creating and managing data. IAM BB for user rights and roles management is a separate BB. However the system has its own internal authorization system.


Internal ABAC has been specified in DRS-6.

Open API for data exchange has been described below.


According to Use Case, no large datasets available for storing.

Modifications not feasible.

| -|
  1. Description.

Should there not be an intro what “registry” is and why in some cultures there are different concepts for registries and databases?


I would also think that it would be appropriate to guide a potential reader to right choice of register, i.e more policy choice questions for the intro part


|

Registry is defined in the Glossary. Domain specific rules of registration are different, so there is no common principles how to build or manage a generic registry. This could be generated in the future.

Registry owner- Analyst has all the rights to decide the data set to be stored. Basic registry functionality has been added to the technology and described as requirements. The analyst has the opportunity to decide by him/herself what data to store in the Digital Registries BB.

The principles of traditional Registries management is not in the scope of this document.


See example domain specific principles here: UNCITRAL Legislative Guide on Key Principles of a Business Registry | United Nations iLibrary


| -|
  1. Description -Digital Registries is simple to use.


This is true only if specific functional domain is properly embedded into the no-code platform as kinda of DSL. However, in case if I need to design complex models by myself, then usage of no-code platforms may be additional burden and bring too cumbersome development experience, which ultimately will decrease sustainability of the solution and increase TCO and even making kinda vendor-lock-in to the platform

|

With current task in hand, the use case is simple enough to be nicely fit into No-Code digital registry. In the future when we will find a domain and data set that needs something more complex, then we can analyze how to solve it.

It is always possible to use traditional methods to build registry databases if Digital registries is not suitable.

The training how to build a domain specific registry is the future challenge of next organizations.

A marketplace would help to solve these challenges. This spec enables to build any domain registry.



| -|
  1. Key Digital Functionalities

this capability should include also metadata aka configuration schema of a Registry in order to configure schema in dev environment, test it in next environment and then deploy it to production. This capability should be shown here explicitly. Also automation is needed for that.

|

Yes , this is point nr 1 and 2. See more requirement DRS-10 for schema import and export.


Modifications not feasible.


| -|
  1. (7) Import/export data from/to external files;

This capability should include also metadata aka configuration schema of a Registry in order to configure schema in dev environment, test it in next environment and then deploy it to production. This capability should be shown here explicitly. Also automation is needed for that.


|

Yes , this is point nr 1 and 2. See more requirement DRS-10 for schema import and export.


Modifications not feasible.


| -|

DRS-3

Does it includes option of pre-filling of forms based on Applicant context in the current registry as well as in other 3rd partied sources?

|

Pre-filling of forms is Registration BB functionality. User Interface is managed in Registration BB.

Digital registries has Triggers to prefill data fields in the database (ID, prefix etc. )

Modifications not feasible

| -| in case of notaries there is a need for more complex schema of user rights as far as Notar is independent private sector entity |

In this case Notary/ health worker is using Registries BB via Information Mediator. System must have basic User right management. Additional Roles may be added after IAM system is in place.


| -| in complex organisations with implies requirement to have an organisational data here and to able to create permissions for positions in organisational units. Also, there is aspect of substitution in case of illness, vacations etc. | Yes, we must link the system with IAM BB where we will get those roles. | -|

DRS-13

I would suggest to have similar abstraction for legal entity as well. Also, for relations between persons, legal entities, addresses etc. Otherwise it will be too complicated for analysts to model domains.

|

What would be the use case? the Digital registries allows to store any data.

Modifications not feasible

| -| to create meaningful UI to use complex data, for example, from licensing domain using such generic schema will be just too complicated and cumbersome task. It will not fly globally. |

Digital registries has capabilities to facilitate registry from any domain. If there is such a data schema that Digital Registres BB id not capable to facilitate, then traditional structured databases can be used instead.


Digital Registries functions well with the Mother and Child Program. It will take 15 minutes to create and publish a database for the program without writing any line of code.

| -|

9.

General comment. I do not think, such generic level as it is now the specification will be helpful for practitioners let's say in Rwanda, Botswana, Ukraine, Moldova etc. It does not bring simplification. It is more like you have to learn some proprietary cumbersome language to make simple things in a very complicated manner.

|

Digital Registries capabilities are following no-code principles, thus no need to learn cumbersome languages.

However any IT system (including MS SQL and Oracle, My SQL) requires admin/analyst user who must learn the principles of maintaining and configuring the system. In this case we have envisioned this role to be Analyst. Additional specifications to this BB can be added in the next iteration. Currently it is MVP and focused on one domain. Next , when new domains will be added, then we can add additional flesh on the bones. The system has capabilities for admins and analyst to build databases, sometimes even temporary registries and this is the best tool for it.

| -|

9.5

Should maybe integrity of registration process itself merit special concern depending on the registry in question and the obligation of owner to guarantee the correctness of data, e.g. think of property database and potential abuse?

| This question requires additional debate. According to the methodology the focus is in the Use Case of Mother and Child Program and related processes. Let’s not focus on all things at once. Next iteration we can add processes and use cases. So far the Digital Registries BB fulfilled the needs of the Domain process. | -| normally, database may contain several containers/tables, which may have also its own key. Like in case of RDBMS foreign key would have reference to database, table and record. Here is only 2 key. Would it be sufficient? | Noted. Currently it is sufficient. | -|

DRS-15

Does not clarify how transit is secured. (Encryption of a payload can be added as a "May")

| Information transit between building blocks is governed by Information Mediator BB. All information transit is encrypted between the BB-s. See more in Information Mediator. Decision: Added a comment on transit to this requireme | diff --git a/spec/12-other-resources/migration-from-3.0.md b/spec/12-other-resources/migration-from-3.0.md index 0523f24..bed4541 100644 --- a/spec/12-other-resources/migration-from-3.0.md +++ b/spec/12-other-resources/migration-from-3.0.md @@ -29,7 +29,7 @@ The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data | DRS-11 Import Schema | Moves to optional Provisioning. File formats will be defined by an applicable binding or guide. | | DRS-12 Service Usage Statistics | Generic monitoring inherits from CFR. Administrative analytics are implementation guidance. Logging every search term is not a default requirement. | | DRS-13 Personal Data Field | Sensitivity and classification metadata remain relevant through CFR and declared schemas. UI-specific field marking is retired. | -| DRS-14 Personal Data Identifier | Stable identifier concepts are retained, while Record, foundational, functional, and domain identifiers are distinguished. Federation behaviour moves to Identity Federation. | +| DRS-14 Personal Data Identifier | Stable identifier concepts are retained, while Record, foundational, functional, and domain identifiers are distinguished. Federation behaviour is tracked under the candidate Identity Federation family pending a cross-BB ownership decision. | | DRS-15 Secret Field | Classification, encryption, and transport security inherit from CFR. Policy-driven redaction is retained in Consultation. The credit-card and mandatory Information Mediator examples are removed. | | DRS-16 Read Schema in UI | Machine-readable schema declaration is retained. Administrative UI presentation is implementation guidance. | | DRS-17 Field Properties and Triggers | Validation constraints inform schemas and optional Provisioning. UI widgets, database relationships, and embedded trigger scripting are implementation choices. | @@ -47,7 +47,7 @@ The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data | DRS-29 Multiple Registries by API | Duplicate of DRS-2. Mandatory multi-tenancy is retired. | | DRS-30 Publish Registry by API | Duplicate of DRS-4. Moves to optional Provisioning. | | DRS-31 Modify APIs | Duplicate of DRS-5. Only abstract capability declaration is retained; generated-API product behaviour is retired. | -| DRS-32 Schema and API Discovery | Machine-readable contract and capability discovery are retained as design goals. Full schema administration is optional Provisioning. The discovery format is not specified in this release. | +| DRS-32 Schema and API Discovery | Machine-readable contract and capability discovery are retained as design goals. Full schema administration is optional Provisioning. The [Registry Core metadata model](../05-api-families/registry-core.md#registry-metadata) establishes a minimal conceptual DCAT composition, while its serialisation and validation remain unspecified in this release. | | DRS-33 Applicant CRUD | Split across mandatory Consultation Retrieve, optional Consultation sub-patterns, and optional Write. The Applicant CRUD framing is retired. | | DRS-34 Swagger Service List | Machine-readable service contracts are retained. Swagger UI and live production examples are not conformance requirements. Protocol-native bindings depend on the GovStack framework update. | | DRS-35 Personal Data Usage API | Duplicate of DRS-8. Moves to Access Transparency and is generalised from a person-specific identifier to a Record Principal. | @@ -60,17 +60,17 @@ The following DRAFT requirements carry forward the interoperability intent that | Current target | Principal predecessors | |---|---| -| `fr-core#req-1` Registry service metadata | DRS-1, DRS-32, DRS-34 | +| `fr-core#req-1` Registry metadata | DRS-1, DRS-32, DRS-34 | | `fr-core#req-2` Record identification | DRS-14, DRS-33 | | `fr-core#req-3` Record Identifier preservation | DRS-14, DRS-33 | -| `fr-core#req-4` Schema and semantic-model identification | DRS-3, DRS-4, DRS-16, DRS-17, DRS-32, DRS-34 | +| `fr-core#req-4` Schema, semantic-model, and representation-format identification | DRS-3, DRS-4, DRS-16, DRS-17, DRS-32, DRS-34 | | `fr-core#req-5` Revision and lifecycle-state identification | DRS-4, DRS-7, DRS-14 | | `fr-core#req-6` Minimum provenance | DRS-7, DRS-21, DRS-33 | | `fr-consultation#req-1` Retrieve by identifier | DRS-5, DRS-21, DRS-33 | | `fr-consultation#req-2` Permitted representation | DRS-6, DRS-15, DRS-21, DRS-27, DRS-33 | | `fr-consultation#req-3` Protected-existence handling | DRS-6, DRS-15, DRS-33 | -Concepts moved to capability families without requirements in this release retain no normative force. Provisioning carries DRS-1, DRS-3, DRS-4, DRS-10, DRS-11, DRS-17, DRS-24, DRS-28, and DRS-30. Consultation List or Search carries DRS-9 and DRS-23. Write carries DRS-22 and relevant parts of DRS-24. Notification carries DRS-19. Aggregate Data carries DRS-26 and DRS-36. Access Transparency carries DRS-8, DRS-35, and DRS-37. Evidence and Identity Federation carry the relevant disclosure and identifier-federation aspects of DRS-14 and DRS-27. +Concepts moved to capability families without requirements in this release retain no normative force. Provisioning carries DRS-1, DRS-3, DRS-4, DRS-10, DRS-11, DRS-17, DRS-24, DRS-28, and DRS-30. Consultation List or Search carries DRS-9 and DRS-23. Write carries DRS-22 and relevant parts of DRS-24. Notification carries DRS-19. Aggregate Data carries DRS-26 and DRS-36. Access Transparency carries DRS-8, DRS-35, and DRS-37. Evidence carries the relevant disclosure aspects of DRS-27. The candidate Identity Federation family tracks relevant identifier-federation aspects of DRS-14 and DRS-27 pending agreement with the Identity team on profile ownership. All remaining retired or guidance-only clauses have the exact disposition recorded in the table above. diff --git a/spec/12-other-resources/references.md b/spec/12-other-resources/references.md index 0f3cca7..abf6004 100644 --- a/spec/12-other-resources/references.md +++ b/spec/12-other-resources/references.md @@ -8,21 +8,40 @@ description: Standards and related material relevant to Digital Registries. - [GovStack Architecture and Cross-Functional Requirements](https://specs.govstack.global/architecture) - [GovStack Specification Framework](https://specs.govstack.global/architecture/5-specification-framework) +- [GovStack Identity Building Block description](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) ## Interface and domain standards These references inform the capability direction. Only the requirements and canonical service contracts published by this specification determine conformance. - [OpenAPI Specification](https://spec.openapis.org/oas/) +- [RFC 9727: api-catalog Well-Known URI and Link Relation](https://www.rfc-editor.org/rfc/rfc9727.html) +- [RFC 9264: Linkset Media Types and Link Relation](https://www.rfc-editor.org/rfc/rfc9264.html) +- [W3C Data Catalog Vocabulary (DCAT) 3](https://www.w3.org/TR/vocab-dcat-3/) - [AsyncAPI Specification 3.0.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0) - [OGC API Features](https://ogcapi.ogc.org/features/) - [SDMX Technical Specifications](https://sdmx.org/sdmx_tech_standards/sdmx-technical-specification/) -- [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) +- [W3C Verifiable Credentials Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) - [OpenID Foundation specifications](https://openid.net/developers/specs/) - [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) - [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) - [MOSIP Custom Handle Implementation Guide](https://docs.mosip.io/1.2.0/id-lifecycle-management/identity-issuance/id-repository/custom-handle) +## Metadata vocabularies and profiles + +These vocabularies and profiles inform the Registry Core metadata model. External alignments do not become conformance dependencies unless an adopting profile explicitly selects them. + +- [DCMI Metadata Terms](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/) +- [W3C PROV-O](https://www.w3.org/TR/prov-o/) +- [W3C Organization Ontology](https://www.w3.org/TR/vocab-org/) +- [W3C SKOS Simple Knowledge Organization System](https://www.w3.org/TR/skos-reference/) +- [W3C JSON-LD 1.1](https://www.w3.org/TR/json-ld11/) +- [W3C Cool URIs for the Semantic Web](https://www.w3.org/TR/cooluris/) +- [W3C Best Practice Recipes for Publishing RDF Vocabularies](https://www.w3.org/TR/swbp-vocab-pub/) +- [Schema.org GovernmentService](https://schema.org/GovernmentService) +- [Core Public Service Vocabulary Application Profile](https://github.com/SEMICeu/CPSV-AP) +- [BRegDCAT-AP](https://github.com/SEMICeu/BRegDCAT-AP) + ## Historical material -The detailed 3.0.0-alpha.1 [Release Notes](../1-version-history/release-notes.md), [Key Decision Log](historical/key-decision-log.md), and [Future Considerations](historical/future-considerations.md) are preserved for traceability. They do not add requirements to this release. +The detailed 3.0.0-alpha.1 [Release Notes](../01-version-history/release-notes.md) preserve the prior change record. The [migration ledger](migration-from-3.0.md) records the disposition of every previous DRS requirement. Neither adds requirements to this release. diff --git a/spec/5-api-families/consultation.md b/spec/5-api-families/consultation.md deleted file mode 100644 index 6b6faed..0000000 --- a/spec/5-api-families/consultation.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -description: Read capabilities for permitted Registry information. ---- - -# Consultation - -> **Status:** Retrieve is part of the target Base Registry Profile. List, Search, Record Match, and GIS Query are informative and not claimable in this release. - -## Purpose and applicability - -Consultation enables an authorised API Consumer to obtain a permitted representation of Registry information. It applies when a consumer needs current information from the authoritative source rather than a portable signed assertion or a derived statistic. - -Retrieve is the minimum read capability. It lets a consumer that already knows a Record Identifier obtain the current permitted representation without requiring the Registry to expose enumeration or discovery by personal or domain attributes. - -## Capability patterns - -| Pattern | Outcome | -|---|---| -| `consultation.retrieve` | Returns the current permitted representation of one Record identified by its stable Record Identifier. | -| List | Returns a bounded, paginated collection, optionally filtered by declared attributes. | -| Search | Finds Records using declared attribute predicates. | -| Record Match | Returns possible matching Records with confidence information under a declared matching profile. It does not make an authoritative identity or acceptance decision. | -| GIS Query | Applies spatial predicates to geometric attributes maintained by the Registry. | - -## Capability boundary - -Consultation returns live Registry information. [Evidence](evidence.md) produces a signed assertion with its own validity and status. [Aggregate Data](aggregate-data.md) returns derived statistics rather than Record representations. - -The Retrieve requirements define permitted representations and protected-existence handling. Later List, Search, Match, and GIS Query profiles will need their own disclosure, pagination, query-limit, and result-interpretation rules. - -## Bindings and current coverage - -Synchronous HTTP described by OpenAPI is the candidate general binding. OGC API Features is a candidate additional binding for GIS Query. This release defines only the abstract Retrieve operation and does not publish a canonical HTTP contract. - -See [Functional Requirements](../6-functional-requirements.md#63-consultation-retrieve), [Service Interfaces](../9-service-interfaces.md), [Workflows](../10-workflows.md), and [Testing](../11-testing.md). - -## Example - -A licensing service retrieves the current permitted representation of a business registration by its Record Identifier. The Registry returns only the fields and metadata that service is authorised to receive. diff --git a/spec/5-api-families/identity-federation.md b/spec/5-api-families/identity-federation.md deleted file mode 100644 index 6d5be2b..0000000 --- a/spec/5-api-families/identity-federation.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -description: Sectoral subject authentication and authorised claim release. ---- - -# Identity Federation - -> **Status:** Informative and not claimable in this release. No Identity Federation requirements, claim profile, protocol profile, or tests are published. - -## Purpose and applicability - -Identity Federation enables a sectoral Registry containing Records about people, or a service acting for its authority, to authenticate the person represented by a Registry Record to a Relying Service and release authorised claims. It applies to sector populations such as farmers, students, health-service users, or licensed professionals. - -## Registry-specific concerns - -A profile needs to define the relationship between the authenticated subject and the Registry Record, the lifecycle of the functional identifier, authorised claim release, subject-identifier policy, suspension or termination of the sector relationship, assurance expectations, and issuer topology. - -The functional identifier remains issued and lifecycle-managed by the responsible Registry Authority. OpenID Connect transports authentication and claims; it does not create or govern that identifier. An applicable OpenID Connect binding also follows its rules for issuer-scoped subject identifiers. A later profile can define when pairwise subject identifiers are used to limit correlation. - -## Capability boundary - -Identity Federation is an outward-facing service to a Relying Service. It is separate from authentication and authorisation used to protect Registry APIs. It does not issue or replace foundational identity. An Identity service can provide upstream authentication or identity proofing without taking ownership of the sectoral identifier. - -## Candidate binding - -OpenID Connect Core and Discovery are the candidate protocol specifications. The protocol's existing operations remain authoritative; a Registry profile would add only Registry-specific claims, assurance, subject-binding, and lifecycle rules. - -## Example - -A professional Registry authenticates a licensed practitioner to a continuing-education service and releases an authorised claim that identifies the relevant professional sector. diff --git a/spec/5-key-functionalities.md b/spec/5-key-functionalities.md deleted file mode 100644 index 8c4d5ae..0000000 --- a/spec/5-key-functionalities.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -description: Capability families provided by the Digital Registries Building Block. ---- - -# 5 Key Functionalities: API Families - -The Digital Registries Building Block groups its externally visible capabilities into eight families. A family describes an adopter outcome and a coherent trust boundary. It does not prescribe an internal module, product architecture, or transport. - -Only **Consultation Retrieve** is part of the target Base Registry Profile. The other Consultation sub-patterns and seven other families are informative in this release. They are not claimable because they do not yet have approved requirements, contracts, and tests. - -
Digital Registries Building Block capability families
Registry Core provides the shared foundation. The target Base Registry Profile adds Consultation Retrieve.
- -## 5.1 Family catalogue - -| Family | Adopter outcome | Capability patterns | Status in this release | -|---|---|---|---| -| [Consultation](5-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, List, Search, Record Match, GIS Query | Retrieve is in the target Base Registry Profile; other patterns are informative. | -| [Provisioning](5-api-families/provisioning.md) | Configure a Registry service and publish its externally visible contracts. | Service metadata, schemas, capability publication, bulk transfer | Informative | -| [Evidence](5-api-families/evidence.md) | Obtain a signed assertion derived from authoritative Registry information. | Direct attestation, wallet-mediated credential, status | Informative | -| [Write](5-api-families/write.md) | Create a Record or accept a new authoritative revision. | Direct write, governed write, correction | Informative | -| [Notification](5-api-families/notification.md) | Inform authorised subscribers that Registry state changed. | Subscribe, filter, deliver, retry, replay | Informative | -| [Aggregate Data](5-api-families/aggregate-data.md) | Obtain approved statistics derived from Registry Records. | Aggregate query, dataset metadata, published release | Informative | -| [Access Transparency](5-api-families/access-transparency.md) | Obtain a permitted view of access to a related Record. | Access-history consultation | Informative | -| [Identity Federation](5-api-families/identity-federation.md) | Authenticate a person represented by a sectoral Registry Record to a Relying Service and release authorised claims. | OpenID Provider and claim release | Informative | - -## 5.2 Selecting families - -An adopter selects capabilities from the Registry's institutional responsibilities and consumer needs, not from the feature list of a particular product. Useful questions include: - -- Does the Registry expose only current Records, or also search, mutation, events, evidence, statistics, or subject authentication? -- Which actors can invoke each capability, and what may each actor learn? -- Does the Registry own an approval process, or accept an approved result from another service? -- Does the consumer need live Registry information, a portable proof, or notification that state changed? -- Which sector semantic model and protocol binding fit the participating systems? - -Each family page states its boundary and maturity. Candidate operations and bindings on informative pages are design inputs, not implementation obligations. diff --git a/spec/6-functional-requirements.md b/spec/6-functional-requirements.md deleted file mode 100644 index 853b75e..0000000 --- a/spec/6-functional-requirements.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -description: Draft Registry Core and Consultation Retrieve requirements. ---- - -# 6 Functional Requirements - -## 6.1 Reading the requirements - -This release contains only requirements that support the target Base Registry Profile. Additional families are described in [Key Functionalities](5-key-functionalities.md) but have no requirements or conformance effect in this release. - -Each requirement follows the GovStack Requirements Model. `DRAFT` means that the requirement is available for review but is not included in certification. Requirement identifiers are permanently reserved even while the requirement is DRAFT. - -## 6.2 Registry Core - -Registry Core requirements apply globally rather than to one Key Functionality. - -### #1 Publish Registry service metadata - -`govstack-bb-digital-registries-fr-core#req-1` - -`DRAFT EXTENSIBLE AUDITABLE` - -An implementation publishes machine-readable service metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, the Digital Registries specification version, and the GovStack CFR version it implements. - -**Purpose:** An adopter can determine which Registry and authority stand behind a service and which complete set of requirements applies. - -**Prerequisite:** The Registry Authority and authoritative scope have been established by the adopting organisation. - -**Verification:** Inspect the published service metadata, validate that all required values are present, and review evidence that the Registry Identifier is not shared with another Registry or changed between service revisions. - -### #2 Identify each returned Record - -`govstack-bb-digital-registries-fr-core#req-2` - -`DRAFT EXTENSIBLE OBSERVABLE` - -Every returned Record representation includes the Registry Identifier and a Record Identifier that is unique within that Registry. Together, the two identifiers uniquely identify the Record. - -**Purpose:** Consumers can distinguish Records from different Registries and refer to one Record without depending on mutable domain attributes. - -**Prerequisite:** A Record has been accepted into the Registry. - -**Verification:** Retrieve two distinct Record fixtures and verify that each response carries the expected Registry Identifier and a different Record Identifier. - -### #3 Preserve Record Identifiers - -`govstack-bb-digital-registries-fr-core#req-3` - -`DRAFT EXTENSIBLE AUDITABLE` - -An implementation keeps a Record Identifier unchanged throughout that Record's lifecycle and revisions and never reassigns the identifier to a different Record. - -**Purpose:** A Record reference remains unambiguous after changes, retirement, archival, or deletion. - -**Prerequisite:** The implementation has a documented Record Identifier lifecycle policy. - -**Verification:** Review the identifier policy and evidence showing that successive revisions retain the same identifier, distinct Records do not share an identifier, and retired identifiers are not returned to the allocation pool. - -### #4 Identify the Record schema and semantic model - -`govstack-bb-digital-registries-fr-core#req-4` - -`DRAFT EXTENSIBLE OBSERVABLE` - -Every returned Record representation identifies a resolvable machine-readable schema and the published semantic model that govern its domain data. - -**Purpose:** Consumers can validate the structure of a representation and interpret its domain meaning without knowledge of the implementation's internal storage. - -**Prerequisite:** The Registry Authority has selected the applicable schema and semantic model. - -**Verification:** Retrieve a Record, resolve the declared schema, validate the representation, and resolve the semantic-model identifier to its published definition. - -### #5 Identify the current revision and lifecycle state - -`govstack-bb-digital-registries-fr-core#req-5` - -`DRAFT EXTENSIBLE OBSERVABLE` - -Every returned Record representation identifies its current revision and a lifecycle state permitted by the representation's declared schema. - -**Purpose:** Consumers can distinguish the current representation from earlier revisions and interpret its declared state. - -**Prerequisite:** The selected representation schema defines the supported lifecycle-state vocabulary. - -**Verification:** Retrieve fixtures in each lifecycle state exposed through Consultation, validate each state against the declared schema, and verify that each response identifies a current revision. - -### #6 Provide minimum Record provenance - -`govstack-bb-digital-registries-fr-core#req-6` - -`DRAFT EXTENSIBLE OBSERVABLE` - -Every returned Record representation identifies the Registry Authority as the responsible source and provides the time at which the current revision was recorded. - -**Purpose:** A consumer can assess the institutional source and currency of the authoritative information. - -**Prerequisite:** The Registry captures provenance for each accepted revision. - -**Verification:** Retrieve a Record and verify that the representation contains the Registry Authority identifier and recording time. Additional protected provenance details are outside this minimum requirement. - -## 6.3 Consultation Retrieve - -The following requirements link to the Consultation Key Functionality intended for the Base Registry Profile. - -### #1 Retrieve the current Record by identifier - -`govstack-bb-digital-registries-fr-consultation#req-1` - -`DRAFT EXTENSIBLE OBSERVABLE` - -`KF: Consultation` - -Given a valid Record Identifier and an authorised request, an implementation returns the current permitted representation of that Record without modifying the Record. - -**Purpose:** An API consumer that already knows a Record Identifier can obtain authoritative Registry information without using search or enumeration. - -**Prerequisite:** An authorised API consumer and an accessible Record fixture exist. - -**Verification:** Retrieve a known Record by identifier, verify the Registry and Record identifiers, current revision, lifecycle state, schema, semantic model, minimum provenance, and permitted domain data, and confirm that a subsequent Retrieve returns the same revision when no intervening change occurred. - -### #2 Apply disclosure rules to the returned representation - -`govstack-bb-digital-registries-fr-consultation#req-2` - -`DRAFT EXTENSIBLE OBSERVABLE` - -`KF: Consultation` - -An implementation returns only the Record fields and metadata permitted for the authenticated API consumer and request context. - -**Purpose:** Retrieve does not become an entitlement to the complete stored Record. - -**Prerequisite:** At least two test consumers have different disclosure entitlements for the same Record. - -**Verification:** Retrieve the same Record using both consumers and verify that each receives only its permitted projection and that omitted values are not exposed through errors or metadata returned to the consumer. - -### #3 Hide protected Record existence - -`govstack-bb-digital-registries-fr-consultation#req-3` - -`DRAFT EXTENSIBLE OBSERVABLE` - -`KF: Consultation` - -For an API consumer that is not authorised to learn whether a protected Record exists, an implementation returns an error response that is indistinguishable under the published Retrieve contract from the response for an unknown Record Identifier. This includes the same status or error category, security-relevant headers, stable problem type or code, response schema, and non-Record-specific problem values. Per-request correlation values may differ when they are generated independently of Record existence. The response contains no Record-specific data. - -**Purpose:** An unauthorised consumer cannot enumerate protected Record Identifiers through the Retrieve error contract. - -**Prerequisite:** An unknown Record Identifier and a protected Record Identifier are available as test fixtures for the same consumer. - -**Verification:** Retrieve both identifiers as that consumer and compare the status or error category, security-relevant headers, problem type or code, response schema, non-Record-specific problem values, and data fields. Verify that any differing correlation values are independent of Record existence and that neither response exposes Record-specific data. - -## 6.4 Deferred capabilities - -No requirement identifier is assigned to Provisioning, additional Consultation sub-patterns, Evidence, Write, Notification, Aggregate Data, Access Transparency, or Identity Federation in this release. diff --git a/spec/7-cross-functional-requirements.md b/spec/7-cross-functional-requirements.md deleted file mode 100644 index 3a8e5c7..0000000 --- a/spec/7-cross-functional-requirements.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -description: Cross-functional requirements inherited by Digital Registries. ---- - -# 7 Cross-Functional Requirements - -`govstack-bb-digital-registries-3.0.0-alpha.2 extends govstack-cfr-2.1.0` - -Every requirement from `govstack-cfr-2.1.0` applies according to its classifier and any applicability condition stated in that requirement, without being repeated in this specification. - -The inherited requirements cover, among other concerns: - -- authentication, authorisation, transport security, encryption, secrets, and security logging; -- API documentation, observability, availability, deployment, and maintainability; -- Unicode, timestamps, data formats, validation, portability, provenance, retention, and sensitivity classification; and -- use and publication of appropriate domain schemas and standards. - -This release defines no additional Registry-specific cross-functional requirement. In particular, it does not impose a jurisdiction-specific security framework, a universal legal basis for data processing, or one deletion policy on every type of Registry. - -Registry-specific behaviour that produces direct business value, such as the permitted representation returned by Consultation, remains in [Functional Requirements](6-functional-requirements.md) rather than being hidden in this chapter. diff --git a/spec/8-data-structures.md b/spec/8-data-structures.md deleted file mode 100644 index 7387ce8..0000000 --- a/spec/8-data-structures.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -description: Conceptual external data model for the Base Registry Profile. ---- - -# 8 Data Structures - -## 8.1 Scope - -This chapter describes the information that crosses the Base Registry Profile boundary. It does not prescribe database tables, field storage, entity-attribute-value structures, or an internal audit-log implementation. - -The names below are conceptual. This release does not define exact JSON property names or a canonical schema. - -## 8.2 Conceptual model - -```mermaid -erDiagram - REGISTRY ||--o{ RECORD : maintains - SCHEMA ||--o{ RECORD_REPRESENTATION : governs - RECORD ||--|{ RECORD_REVISION : has - RECORD_REVISION ||--o{ RECORD_REPRESENTATION : permits - - REGISTRY { - string registryIdentifier - string name - string authority - string specificationVersion - string cfrVersion - } - RECORD { - string recordIdentifier - } - RECORD_REVISION { - string revisionIdentifier - string lifecycleState - datetime recordedAt - string authorityIdentifier - } - RECORD_REPRESENTATION { - string registryIdentifier - string recordIdentifier - string revisionIdentifier - string lifecycleState - string schemaReference - string semanticModelReference - string authorityIdentifier - datetime recordedAt - object domainData - } -``` - -## 8.3 Registry metadata - -| Concept | Purpose | -|---|---| -| Registry Identifier | Globally unique and stable identifier for the Registry. | -| Registry Name | Human-readable name used by adopters and consumers. | -| Registry Authority | Institution accountable for the declared authoritative scope. | -| Specification Version | Digital Registries specification implemented by the service. | -| CFR Version | GovStack Common Requirements Framework version implemented by the service. | - -The capability-discovery format is not specified in this release. - -## 8.4 Record representation - -| Concept | Purpose | -|---|---| -| Registry Identifier | Identifies the Registry that returned the representation. | -| Record Identifier | Stable reference to the Record within the Registry. | -| Revision Identifier | Identifies the current revision represented by the response. | -| Lifecycle State | State permitted by the declared representation schema. | -| Schema Reference | Resolves to the machine-readable structure used to validate domain data. | -| Semantic Model Reference | Identifies the vocabulary or domain model used to interpret the data. | -| Minimum Provenance | Identifies the Registry Authority as the responsible source and the time at which the current revision was recorded. | -| Domain Data | The authorised projection of domain-specific Record content. | - -The permitted representation may omit or redact domain data and additional protected provenance. The Registry Core requirements identify which metadata is present in every returned representation. The applicable representation schema accounts for permitted omissions so that the response remains unambiguous and valid. - -## 8.5 Revisions and lifecycle - -The Base Registry Profile retrieves the current revision. It does not include an operation for retrieving historical revisions. - -The declared representation schema defines the supported lifecycle-state vocabulary. Terms such as active, inactive, superseded, archived, and deleted are examples, not a mandatory enumeration in this release. - -The Record Identifier remains stable when a new revision is accepted. Revision identifiers distinguish successive representations of the same Record. - -## 8.6 Domain semantics and extensions - -The Digital Registries Building Block does not define a universal person, business, parcel, vehicle, health, or programme schema. Each returned representation identifies its machine-readable schema and published semantic model. An adopter can use an appropriate sector model and map national extensions explicitly. - -Extensions do not change the meaning of required Registry metadata. Rules for unknown fields, compatibility, and schema evolution are not defined in this release. diff --git a/spec/README.md b/spec/README.md index a072f74..210662d 100644 --- a/spec/README.md +++ b/spec/README.md @@ -14,21 +14,15 @@ The Base Registry Profile consists of Registry Core behaviour and the ability fo ## How to use this specification -- **Government architects** should begin with [Description and Scope](2-description-and-scope.md) and [Conformance](4-conformance.md) to determine where a Registry fits within a digital government architecture. +- **Government architects** should begin with [Description and Scope](02-description-and-scope.md) and [Conformance](04-conformance.md) to determine where a Registry fits within a digital government architecture. - **Procurement teams** can use the alpha to understand the intended profile structure, but should cite an approved specification version in a tender or acceptance contract. -- **Implementers** can use the DRAFT requirements, data structures, and workflow for prototyping. This alpha does not publish an implementation contract. +- **Implementers** can use the DRAFT requirements, Registry Core model, capability descriptions, and workflow for prototyping. This alpha does not publish an implementation contract. - **Conformance testers** can use [Testing](11-testing.md) to assess verification intent. This alpha does not publish a conformance suite or permit capability claims. ## Status and authorship -This alpha is structured around a domain-neutral Registry Core, mandatory Consultation Retrieve, and optional capability families. Earlier contributions, authors, coordinators, editors, and reviewers remain recorded in the [Version History](1-version-history/README.md) and [Release Notes](1-version-history/release-notes.md). +This alpha is structured around a domain-neutral Registry Core, mandatory Consultation Retrieve, and optional capability families. Earlier contributions, authors, coordinators, editors, and reviewers remain recorded in the [Version History](01-version-history.md) and [Release Notes](01-version-history/release-notes.md). -_**Coordinating authors of the 3.0.0-alpha.1 work:**_ Dr. Bimal Kumar, Xilene Siquero, and Sebastian Leidig - -_**Authors:**_ Janet Ngugi, Vivek Rana, Chinenye Ifebirinachi, Ananya Jha, Umang Gupta, Leonora Smart-Abbey, and Jeremi Joslin - -_**Editors:**_ Ali González-García and David Higgins - -_**First version by:**_ Frank Grozel, Ingmar Vali, Tambet Artma, Saurav Bhattarai, Dr. P. S. Ramkumar, Rauno Kulla, and Sebastian Leidig +_**Coordinating authors of the 3.0.0-alpha.2 work:**_ Sebastian Leidig, Jeremi Joslin, and David Higgins
Digital Registries Building Block capability families
The target Base Registry Profile combines Registry Core with Consultation Retrieve.
diff --git a/spec/SUMMARY.md b/spec/SUMMARY.md index 0fa65d1..3829506 100644 --- a/spec/SUMMARY.md +++ b/spec/SUMMARY.md @@ -1,26 +1,24 @@ # Table of contents * [Digital Registries Building Block Specification](README.md) -* [1 Version History](1-version-history/README.md) - * [Release Notes](1-version-history/release-notes.md) -* [2 Description and Scope](2-description-and-scope.md) -* [3 Terminology](3-terminology.md) -* [4 Conformance](4-conformance.md) -* [5 Key Functionalities: API Families](5-key-functionalities.md) - * [Consultation](5-api-families/consultation.md) - * [Provisioning](5-api-families/provisioning.md) - * [Evidence](5-api-families/evidence.md) - * [Write](5-api-families/write.md) - * [Notification](5-api-families/notification.md) - * [Aggregate Data](5-api-families/aggregate-data.md) - * [Access Transparency](5-api-families/access-transparency.md) - * [Identity Federation](5-api-families/identity-federation.md) -* [6 Functional Requirements](6-functional-requirements.md) -* [7 Cross-Functional Requirements](7-cross-functional-requirements.md) -* [8 Data Structures](8-data-structures.md) -* [9 Service Interfaces](9-service-interfaces.md) +* [1 Version History](01-version-history.md) + * [Release Notes](01-version-history/release-notes.md) +* [2 Description and Scope](02-description-and-scope.md) +* [3 Terminology](03-terminology.md) +* [4 Conformance](04-conformance.md) +* [5 Key Functionalities: API Families](05-key-functionalities.md) + * [Registry Core](05-api-families/registry-core.md) + * [Consultation](05-api-families/consultation.md) + * [Provisioning](05-api-families/provisioning.md) + * [Evidence](05-api-families/evidence.md) + * [Write](05-api-families/write.md) + * [Notification](05-api-families/notification.md) + * [Aggregate Data](05-api-families/aggregate-data.md) + * [Access Transparency](05-api-families/access-transparency.md) + * [Identity Federation](05-api-families/identity-federation.md) +* [9 Service Interfaces](09-service-interfaces.md) * [10 Workflows](10-workflows.md) * [11 Testing](11-testing.md) -* [12 Other Resources](12-other-resources/README.md) +* [12 Other Resources](12-other-resources.md) * [Migration from 3.0.0-alpha.1](12-other-resources/migration-from-3.0.md) * [References](12-other-resources/references.md) From 8db7145cb9bac20edf83185d69fd2cb48a24a038 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 2 Sep 2026 16:23:22 +0700 Subject: [PATCH 04/10] Simplify Registry conformance metadata Signed-off-by: Jeremi Joslin --- spec/04-conformance.md | 2 +- spec/05-api-families/consultation.md | 2 +- spec/05-api-families/registry-core.md | 65 +++++++++------------------ spec/11-testing.md | 4 +- 4 files changed, 24 insertions(+), 49 deletions(-) diff --git a/spec/04-conformance.md b/spec/04-conformance.md index ddc2bae..568e459 100644 --- a/spec/04-conformance.md +++ b/spec/04-conformance.md @@ -8,7 +8,7 @@ description: Draft minimum conformance and capability model for Digital Registri All requirements in the 3.0.0-alpha.2 specification are classified as DRAFT. They do not create a certification obligation. -Each requirement follows the GovStack Requirements Model. Requirement identifiers are permanently reserved even while the requirement is DRAFT. Cross-family requirements are defined under [Registry Core](05-api-families/registry-core.md#registry-core-functional-requirements), while family-specific requirements are defined on the applicable API-family page. +Each requirement follows the [GovStack Requirements Model](https://specs.govstack.global/architecture/development/5-specification-framework/5.3-requirements-model). Requirement levels and other classifiers are interpreted according to that model. Lowercase modal verbs have their ordinary English meaning; this specification does not use BCP 14 keywords to assign requirement levels. Requirement identifiers are permanently reserved even while the requirement is DRAFT. Cross-family requirements are defined under [Registry Core](05-api-families/registry-core.md#registry-core-functional-requirements), while family-specific requirements are defined on the applicable API-family page. ## 4.2 Inherited cross-functional requirements diff --git a/spec/05-api-families/consultation.md b/spec/05-api-families/consultation.md index aabf12f..7cf0792 100644 --- a/spec/05-api-families/consultation.md +++ b/spec/05-api-families/consultation.md @@ -99,7 +99,7 @@ An adopter may need Consultation capabilities beyond Retrieve. These capabilitie | Record Match | A consumer supplies incomplete or variable domain information that may correspond to more than one Record. | Permitted inputs, matching rules, confidence interpretation, disclosure of possible matches, and ambiguous or no-match outcomes. A match is not an authoritative identity, eligibility, or acceptance decision. | | GIS Query | A spatial Registry exposes Records through geographic relationships. | Supported spatial predicates, coordinate and geometry semantics, spatial and result bounds, and disclosure of protected Records or locations. | -Every selected capability applies disclosure to both Record content and result metadata. Counts, ordering, page boundaries, confidence values, suggestions, and geometries must not reveal information that the consumer is not permitted to learn. +For every selected capability, disclosure applies to both Record content and result metadata. The applicable profile needs to ensure that counts, ordering, page boundaries, confidence values, suggestions, and geometries do not reveal information that the consumer is not permitted to learn. ## Binding status diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index 6145482..ee460b8 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -39,7 +39,6 @@ The Registry metadata description identifies the institutionally governed Regist | Registry Name | Required | [`dct:title`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#title) | Human-readable name used by adopters and consumers. | | Registry Authority | Required | `govreg:authority` with a [`prov:Agent`](https://www.w3.org/TR/prov-o/#Agent) value | Institution accountable for the Registry and its declared authoritative scope. | | Digital Registries specification version | Required | [`dct:conformsTo`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#conformsTo) | Versioned Digital Registries specification implemented by the service. | -| CFR version | Required | [`dct:conformsTo`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#conformsTo) | Versioned GovStack Common Requirements Framework implemented by the service. | | Description | Optional | [`dct:description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description) | Human-readable description of the Registry and its scope. | | Governed dataset | Optional and repeatable | `govreg:dataset` with a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset) value | A governed collection of Registry Records described for discovery or exchange. | | Data service | Optional and repeatable | `govreg:dataService` with a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service) value | A technical interface that provides access to Registry data or operations. | @@ -57,7 +56,9 @@ The companion [Turtle vocabulary](registry-core-vocabulary.ttl) provides machine The selected publication namespace is the dedicated `vocab.govstack.global` host. The Registry Core namespace document is `https://vocab.govstack.global/digital-registries`, and the API-family concept-scheme document is `https://vocab.govstack.global/digital-registries/api-families`. Terms use fragment IRIs so each small vocabulary can be retrieved as one document. These version-independent IRIs remain stable when the vocabulary evolves. -The host must be provisioned so both namespace documents dereference before the vocabulary is published. Content negotiation can add HTML and JSON-LD representations without changing the term IRIs. The companion file does not make Turtle a required Registry metadata publication format or establish RDF conformance, and this release does not define a SHACL shape. +> **Editorial note:** Before release, GovStack needs to provision the namespace host so that both namespace documents dereference. This note can be removed once the host is operational. + +The namespace can provide HTML, Turtle, and JSON-LD representations through HTTP content negotiation without changing the term IRIs. The companion Turtle file does not require Registry implementations to publish Turtle or claim RDF conformance. This release does not define a SHACL shape. The versioned [JSON-LD context](registry-core-context.jsonld) is assigned the publication URI `https://vocab.govstack.global/digital-registries/context/v1`. When the vocabulary host is provisioned, this URI serves the context with the `application/ld+json` media type. Context versions are immutable because changing a context can change how existing JSON is interpreted. Versioning the context does not version or otherwise change the vocabulary term IRIs. @@ -110,12 +111,8 @@ The following JSON-LD document describes one business Registry, accountable auth { "@id": "https://registry.example/catalog", "@type": "dcat:Catalog", - "title": { - "en": "Business Registry catalogue" - }, - "description": { - "en": "Discovery metadata for the Business Registry, its dataset, and its Retrieve API." - }, + "title": "Business Registry catalogue", + "description": "Discovery metadata for the Business Registry, its dataset, and its Retrieve API.", "publisher": "https://registry.example/organisations/business-authority", "catalogResource": "https://registry.example/registries/business", "catalogDataset": "https://registry.example/datasets/business-records", @@ -127,16 +124,9 @@ The following JSON-LD document describes one business Registry, accountable auth "govreg:Registry", "dcat:Resource" ], - "title": { - "en": "Business Registry" - }, - "description": { - "en": "Registry maintained for authoritative business registration records." - }, - "conformsTo": [ - "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", - "https://specs.govstack.example/cfr/2.1.0" - ], + "title": "Business Registry", + "description": "Registry maintained for authoritative business registration records.", + "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", "authority": "https://registry.example/organisations/business-authority", "governedDataset": "https://registry.example/datasets/business-records", "dataService": "https://registry.example/services/business-retrieve" @@ -144,49 +134,32 @@ The following JSON-LD document describes one business Registry, accountable auth { "@id": "https://registry.example/organisations/business-authority", "@type": "prov:Organization", - "title": { - "en": "Business Registration Authority" - } + "title": "Business Registration Authority" }, { "@id": "https://registry.example/datasets/business-records", "@type": "dcat:Dataset", - "title": { - "en": "Business registration records dataset" - }, - "description": { - "en": "Governed collection of business registration Records." - }, + "title": "Business registration records dataset", + "description": "Governed collection of business registration Records.", "publisher": "https://registry.example/organisations/business-authority" }, { "@id": "https://vocab.govstack.global/digital-registries/api-families", "@type": "skos:ConceptScheme", - "title": { - "en": "Digital Registries API Families" - } + "title": "Digital Registries API Families" }, { "@id": "apif:consultation", "@type": "skos:Concept", - "prefLabel": { - "en": "Consultation" - }, + "prefLabel": "Consultation", "inScheme": "https://vocab.govstack.global/digital-registries/api-families" }, { "@id": "https://registry.example/services/business-retrieve", "@type": "dcat:DataService", - "title": { - "en": "Business Registry Retrieve API" - }, - "description": { - "en": "Retrieves the current permitted representation of a business Record." - }, - "conformsTo": [ - "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", - "https://specs.govstack.example/cfr/2.1.0" - ], + "title": "Business Registry Retrieve API", + "description": "Retrieves the current permitted representation of a business Record.", + "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", "serviceType": "apif:consultation", "servesDataset": "https://registry.example/datasets/business-records", "endpointURL": "https://registry.example/api/business", @@ -196,6 +169,8 @@ The following JSON-LD document describes one business Registry, accountable auth } ``` +The example uses untagged strings for readability. Deployments can use JSON-LD language maps, such as `"title": {"en": "Business Registry"}`, when publishing multilingual labels. + The Registry is also typed as [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) so that the catalogue can list it with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource). This does not make the Registry a dataset or a data service. The vocabulary expresses `govreg:Registry` as a subclass of `dcat:Resource`, while explicit dual typing keeps an instance understandable without ontology inference. The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in this catalogue. `govreg:dataset` and `govreg:dataService` state which dataset and service belong to this Registry. `dcat:servesDataset` states which dataset the technical service exposes. @@ -301,9 +276,9 @@ Extensions do not change the meaning of required Registry or Record metadata. Ru `govstack-bb-digital-registries-fr-core#req-1` -An implementation publishes machine-readable Registry metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, the Digital Registries specification version, and the GovStack CFR version it implements. +An implementation publishes machine-readable Registry metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, and the Digital Registries specification version it implements. -**Purpose:** An adopter can determine which Registry and authority stand behind a service and which complete set of requirements applies. +**Purpose:** An adopter can determine which Registry and authority stand behind a service and which versioned requirement set, including its inherited requirements, applies. **Prerequisite:** The Registry Authority and authoritative scope have been established by the adopting organisation. diff --git a/spec/11-testing.md b/spec/11-testing.md index ad5d635..83def13 100644 --- a/spec/11-testing.md +++ b/spec/11-testing.md @@ -28,7 +28,7 @@ Testers use synthetic fixtures rather than real personal or confidential data. | Requirement | Verification item | Expected result | |---|---|---| -| `fr-core#req-1` | Inspect machine-readable Registry metadata and identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, Digital Registries specification version, and CFR version are present. | +| `fr-core#req-1` | Inspect machine-readable Registry metadata and identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, and Digital Registries specification version are present. | | `fr-core#req-2` | Retrieve two distinct Records | Each response includes the Registry Identifier and a different Record Identifier; each identifier pair is unique. | | `fr-core#req-3` | Inspect the identifier policy and lifecycle evidence | A Record Identifier remains unchanged across revisions and lifecycle states, is not shared, and is not reassigned after retirement. | | `fr-core#req-4` | Validate a retrieved representation | The representation format conveyed by the binding matches the representation, schema and semantic-model references resolve, and schema validation succeeds. | @@ -70,6 +70,6 @@ Feature: Retrieve the current permitted Registry Record ## 11.5 Evidence retained for audit -Verification evidence identifies the Digital Registries specification version and the `govstack-cfr-2.1.0` baseline tested. It also includes fixture definitions, requests, responses, schema-validation results, identifier-lifecycle evidence, and a traceability report mapping every evaluated requirement to a pass or fail result. +Verification evidence identifies the Digital Registries specification version tested. It also includes fixture definitions, requests, responses, schema-validation results, identifier-lifecycle evidence, and a traceability report mapping every evaluated requirement to a pass or fail result. No fixed response-time threshold, container technology, administrative user interface, Information Mediator header, or test tool is part of the target Base Registry Profile. From 66d50af212b43a60b240f1bc806dfd5f5b13066e Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 2 Sep 2026 16:32:10 +0700 Subject: [PATCH 05/10] Expand Registry service discovery example Signed-off-by: Jeremi Joslin --- .../registry-core-context.jsonld | 9 ---- spec/05-api-families/registry-core.md | 53 ++++++++++++------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/spec/05-api-families/registry-core-context.jsonld b/spec/05-api-families/registry-core-context.jsonld index a37ab51..44ed3bb 100644 --- a/spec/05-api-families/registry-core-context.jsonld +++ b/spec/05-api-families/registry-core-context.jsonld @@ -7,7 +7,6 @@ "apif": "https://vocab.govstack.global/digital-registries/api-families#", "govreg": "https://vocab.govstack.global/digital-registries#", "prov": "http://www.w3.org/ns/prov#", - "skos": "http://www.w3.org/2004/02/skos/core#", "title": { "@id": "dct:title", "@container": "@language" @@ -48,14 +47,6 @@ "@id": "govreg:dataService", "@type": "@id" }, - "prefLabel": { - "@id": "skos:prefLabel", - "@container": "@language" - }, - "inScheme": { - "@id": "skos:inScheme", - "@type": "@id" - }, "serviceType": { "@id": "dct:type", "@type": "@id" diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index ee460b8..f939f0e 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -102,7 +102,7 @@ The current alpha treats this publication layout as discovery guidance rather th ### Informative JSON-LD example -The following JSON-LD document describes one business Registry, accountable authority, governed dataset, and Retrieve service. It references the versioned GovStack context, which maps readable JSON property names to the RDF vocabulary and identifies properties whose values are IRIs. Readers familiar with [W3C Verifiable Credentials Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) will recognise the `@context`, `@id`, and `@type` pattern, but this catalogue metadata is not a Verifiable Credential. The versioned GovStack specification IRIs are illustrative because this alpha does not publish canonical IRIs for them. +The following JSON-LD document describes one business Registry, accountable authority, governed dataset, and three services supporting the Consultation, Write, and Evidence API families. It references the versioned GovStack context, which maps readable JSON property names to the RDF vocabulary and identifies properties whose values are IRIs. Readers familiar with [W3C Verifiable Credentials Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) will recognise the `@context`, `@id`, and `@type` pattern, but this catalogue metadata is not a Verifiable Credential. The versioned GovStack specification IRIs are illustrative because this alpha does not publish canonical IRIs for them. ```json { @@ -112,11 +112,15 @@ The following JSON-LD document describes one business Registry, accountable auth "@id": "https://registry.example/catalog", "@type": "dcat:Catalog", "title": "Business Registry catalogue", - "description": "Discovery metadata for the Business Registry, its dataset, and its Retrieve API.", + "description": "Discovery metadata for the Business Registry, its dataset, and its APIs.", "publisher": "https://registry.example/organisations/business-authority", "catalogResource": "https://registry.example/registries/business", "catalogDataset": "https://registry.example/datasets/business-records", - "catalogService": "https://registry.example/services/business-retrieve" + "catalogService": [ + "https://registry.example/services/business-retrieve", + "https://registry.example/services/business-write", + "https://registry.example/services/business-evidence" + ] }, { "@id": "https://registry.example/registries/business", @@ -129,7 +133,11 @@ The following JSON-LD document describes one business Registry, accountable auth "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", "authority": "https://registry.example/organisations/business-authority", "governedDataset": "https://registry.example/datasets/business-records", - "dataService": "https://registry.example/services/business-retrieve" + "dataService": [ + "https://registry.example/services/business-retrieve", + "https://registry.example/services/business-write", + "https://registry.example/services/business-evidence" + ] }, { "@id": "https://registry.example/organisations/business-authority", @@ -143,17 +151,6 @@ The following JSON-LD document describes one business Registry, accountable auth "description": "Governed collection of business registration Records.", "publisher": "https://registry.example/organisations/business-authority" }, - { - "@id": "https://vocab.govstack.global/digital-registries/api-families", - "@type": "skos:ConceptScheme", - "title": "Digital Registries API Families" - }, - { - "@id": "apif:consultation", - "@type": "skos:Concept", - "prefLabel": "Consultation", - "inScheme": "https://vocab.govstack.global/digital-registries/api-families" - }, { "@id": "https://registry.example/services/business-retrieve", "@type": "dcat:DataService", @@ -164,6 +161,26 @@ The following JSON-LD document describes one business Registry, accountable auth "servesDataset": "https://registry.example/datasets/business-records", "endpointURL": "https://registry.example/api/business", "endpointDescription": "https://registry.example/contracts/business-retrieve.openapi.json" + }, + { + "@id": "https://registry.example/services/business-write", + "@type": "dcat:DataService", + "title": "Business Registry Write API", + "description": "Accepts governed requests to create or revise business Records.", + "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "serviceType": "apif:write", + "endpointURL": "https://registry.example/api/business/write", + "endpointDescription": "https://registry.example/contracts/business-write.openapi.json" + }, + { + "@id": "https://registry.example/services/business-evidence", + "@type": "dcat:DataService", + "title": "Business Registry Evidence API", + "description": "Produces signed assertions derived from permitted business registration information.", + "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "serviceType": "apif:evidence", + "endpointURL": "https://registry.example/api/business/evidence", + "endpointDescription": "https://registry.example/contracts/business-evidence.openapi.json" } ] } @@ -173,9 +190,9 @@ The example uses untagged strings for readability. Deployments can use JSON-LD l The Registry is also typed as [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) so that the catalogue can list it with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource). This does not make the Registry a dataset or a data service. The vocabulary expresses `govreg:Registry` as a subclass of `dcat:Resource`, while explicit dual typing keeps an instance understandable without ontology inference. -The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in this catalogue. `govreg:dataset` and `govreg:dataService` state which dataset and service belong to this Registry. `dcat:servesDataset` states which dataset the technical service exposes. +The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in this catalogue. `govreg:dataset` and `govreg:dataService` state which datasets and services belong to this Registry. `dcat:servesDataset` states which dataset a technical service exposes, when applicable. -The `dct:type apif:consultation` statement lets a client discover the supported API family from the catalogue. The client follows `dcat:endpointDescription` to determine which Consultation operations are available and how to invoke them. +The `dct:type` statements let a client discover that the catalogue exposes Consultation, Write, and Evidence services. The client follows each service's `dcat:endpointDescription` to determine which operations are available and how to invoke them. The same graph pattern covers common deployment arrangements: @@ -225,7 +242,7 @@ for each serviceReference in asList(registry.dataService): return supportedCapabilities ``` -Here, `loadJsonLd` applies the versioned context and normalises properties that can contain one or several values. `DigitalRegistriesApiFamilies` is populated from the published [API-family vocabulary](registry-core-vocabulary.ttl), not inferred from an IRI prefix. With the preceding example, the result identifies the Retrieve Data Service as supporting the Consultation family. If a Data Service omits `serviceType`, a client cannot infer API-family support from the catalogue alone, even when its endpoint description happens to contain related operations. +Here, `loadJsonLd` applies the versioned context and normalises properties that can contain one or several values. `DigitalRegistriesApiFamilies` is populated from the published [API-family vocabulary](registry-core-vocabulary.ttl), not inferred from an IRI prefix. With the preceding example, the result identifies three Data Services supporting the Consultation, Write, and Evidence families. If a Data Service omits `serviceType`, a client cannot infer API-family support from the catalogue alone, even when its endpoint description happens to contain related operations. ### External alignments From 07a04f0afc2889b599274cc514393e97fe938452 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 2 Sep 2026 19:29:07 +0700 Subject: [PATCH 06/10] Remove unrelated credential comparison Signed-off-by: Jeremi Joslin --- spec/05-api-families/registry-core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index f939f0e..b68a383 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -102,7 +102,7 @@ The current alpha treats this publication layout as discovery guidance rather th ### Informative JSON-LD example -The following JSON-LD document describes one business Registry, accountable authority, governed dataset, and three services supporting the Consultation, Write, and Evidence API families. It references the versioned GovStack context, which maps readable JSON property names to the RDF vocabulary and identifies properties whose values are IRIs. Readers familiar with [W3C Verifiable Credentials Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) will recognise the `@context`, `@id`, and `@type` pattern, but this catalogue metadata is not a Verifiable Credential. The versioned GovStack specification IRIs are illustrative because this alpha does not publish canonical IRIs for them. +The following JSON-LD document describes one business Registry, accountable authority, governed dataset, and three services supporting the Consultation, Write, and Evidence API families. It references the versioned GovStack context, which maps readable JSON property names to the RDF vocabulary and identifies properties whose values are IRIs. The versioned GovStack specification IRIs are illustrative because this alpha does not publish canonical IRIs for them. ```json { From cacce0889818e93faaeda196621e8c3e436ebfb8 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 9 Sep 2026 15:18:37 +0700 Subject: [PATCH 07/10] feat: draft Registry Core, Consultation, and canonical read contract Checkpoint of the 3.0.0-alpha.2 rewrite: Registry Core metadata and requirements, Consultation read requirements with HTTP binding, canonical OpenAPI with example contracts, and the validation tooling. Signed-off-by: Jeremi Joslin --- README.md | 17 +- api/README.md | 78 +- api/common/README.md | 16 + api/common/govstack-openapi-common.yaml | 105 +++ api/coverage.yaml | 46 + api/examples/README.md | 44 + api/examples/birth-registration.openapi.yaml | 104 +++ api/examples/business-registry.openapi.yaml | 291 +++++++ api/examples/business-registry.schema.json | 167 ++++ api/examples/consultation-exchanges.json | 52 ++ api/examples/household-registry.openapi.yaml | 109 +++ .../relationship-examples.schema.json | 187 ++++ api/examples/relationship-exchanges.json | 45 + api/openapi.yaml | 817 ++++++++++++++++++ spec/.gitbook/assets/api-families.svg | 4 +- spec/01-version-history.md | 10 + spec/02-description-and-scope.md | 28 +- spec/03-terminology.md | 15 +- spec/04-conformance.md | 30 +- spec/05-api-families/access-transparency.md | 8 +- spec/05-api-families/aggregate-data.md | 8 +- spec/05-api-families/consultation.md | 243 ++++-- spec/05-api-families/evidence.md | 8 +- spec/05-api-families/identity-federation.md | 18 +- spec/05-api-families/notification.md | 8 +- spec/05-api-families/provisioning.md | 12 +- .../registry-core-context.jsonld | 4 + spec/05-api-families/registry-core.md | 258 ++++-- spec/05-api-families/write.md | 8 +- spec/05-key-functionalities.md | 21 +- spec/09-service-interfaces.md | 88 +- spec/10-workflows.md | 136 ++- spec/11-testing.md | 162 ++-- spec/12-other-resources.md | 58 +- spec/12-other-resources/migration-from-3.0.md | 45 +- .../read-api-design-decisions.md | 91 ++ spec/12-other-resources/references.md | 10 +- spec/README.md | 22 +- spec/SUMMARY.md | 1 + test/README.md | 6 +- tools/.gitignore | 1 + tools/requirements-api.txt | 7 + tools/validate_consultation.py | 369 ++++++++ 43 files changed, 3371 insertions(+), 386 deletions(-) create mode 100644 api/common/README.md create mode 100644 api/common/govstack-openapi-common.yaml create mode 100644 api/coverage.yaml create mode 100644 api/examples/README.md create mode 100644 api/examples/birth-registration.openapi.yaml create mode 100644 api/examples/business-registry.openapi.yaml create mode 100644 api/examples/business-registry.schema.json create mode 100644 api/examples/consultation-exchanges.json create mode 100644 api/examples/household-registry.openapi.yaml create mode 100644 api/examples/relationship-examples.schema.json create mode 100644 api/examples/relationship-exchanges.json create mode 100644 api/openapi.yaml create mode 100644 spec/12-other-resources/read-api-design-decisions.md create mode 100644 tools/.gitignore create mode 100644 tools/requirements-api.txt create mode 100644 tools/validate_consultation.py diff --git a/README.md b/README.md index e94f879..73835be 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,25 @@ # GovStack Digital Registries Building Block -This repository contains the Digital Registries Building Block specification, interface contracts, conformance tests, and implementation examples. +This repository contains the Digital Registries Building Block specification and supporting API, test, and implementation material. ## Specification status -The `3.0.0-alpha.2` specification defines a domain-neutral Registry Core with mandatory Consultation Retrieve and additional optional capability families. Its requirements are classified as DRAFT and do not establish a GovStack certification claim. +The `3.0.0-alpha.2` specification defines a mandatory, domain-neutral Registry Core with machine-readable metadata and discovery, plus at least one declared capability. All capability families are optional. -Start with the [Digital Registries Building Block Specification](spec/README.md). +The current draft defines four independently optional Consultation capabilities: Retrieve, Lookup, List, and Search. A [canonical OpenAPI contract](api/openapi.yaml) describes their HTTP binding. This draft does not establish an implementation conformance claim. -### Alpha coverage +The [illustrative business Registry contract](api/examples/business-registry.openapi.yaml), [business schema](api/examples/business-registry.schema.json), and [request/response fixtures](api/examples/consultation-exchanges.json) show a concrete adopter mapping. -The alpha publishes the proposed scope, terminology, Base Registry Profile, DRAFT Core and Retrieve requirements, conceptual Record model, workflow, verification intent, and migration from the previous `DRS-1` through `DRS-37` requirements. - -It does not publish a canonical OpenAPI contract or executable conformance suite. No implementation can claim conformance with this alpha. +Start with the [Digital Registries Building Block Specification](spec/README.md). See [Requirement Maturity](spec/04-conformance.md#41-requirement-maturity) for conformance status and [Coverage and Limitations](spec/12-other-resources.md#121-coverage-and-limitations) for published material and open work. ## Repository structure | Path | Contents | Current status | |---|---|---| | `spec/` | Human-readable specification published through GitBook | 3.0.0-alpha.2 draft | -| `api/` | Machine-readable service contracts | Previous generated CRUD contracts retained as legacy; no 3.0.0-alpha.2 contract published | -| `test/` | Conformance and contract tests | Previous generated CRUD tests retained as legacy; draft scenarios are documented in `spec/11-testing.md` | +| `api/` | Machine-readable service contracts | DRAFT Consultation OpenAPI contract and concrete adopter example; previous generated CRUD contracts retained as legacy | +| `tools/` | Draft artifact validation | Contract and example checks; does not exercise a Registry implementation | +| `test/` | Legacy interface tests | Previous generated CRUD tests retained as legacy; draft implementation scenarios are documented in `spec/11-testing.md` | | `examples/` | Product and integration examples | Historical examples; not evidence of 3.0.0-alpha.2 conformance | ## Publication diff --git a/api/README.md b/api/README.md index d89c834..a3425ba 100644 --- a/api/README.md +++ b/api/README.md @@ -1,11 +1,79 @@ # API artifacts -The JSON and YAML files under `legacy/generated-crud/` describe the generated CRUD interface from earlier Digital Registries releases. They are retained for migration analysis and are not service contracts for the 3.0.0-alpha.2 specification. +[openapi.yaml](openapi.yaml) defines the DRAFT Consultation HTTP contract: +OpenAPI **3.1.2**, API version **1.0.0-draft**, targeting API Design Guide and +ruleset **0.2.0-draft**. The `/v1` path identifies the HTTP compatibility line; +the Building Block specification has its own version. -Their original release status, contributor acknowledgements, and publication context are preserved in the [legacy API README](legacy/generated-crud/README.md). +| Capability | HTTP path | Success | +| --- | --- | --- | +| Retrieve | `GET /v1/records/{recordId}` | Record | +| List | `GET /v1/records` | RecordPage | +| Exact Lookup | `POST /v1/records:lookup` | Record | +| Named Search | `POST /v1/records:search` | RecordPage | -The `gitbook-copies/` subdirectory contains additional copies previously embedded as publication assets. They remain separated from current API artifacts because their content is not identical in every case. +`records` is the reference collection name. Deployments publish concrete names, +such as `/v1/businesses` or `/v1/households`, and select capabilities for each +collection. One API can expose several collections, each with a declared Registry, +membership scope, and operation schemas. Success responses share +`Record {recordId, data}` and `RecordPage {items, pageInfo}`. +Lookup and Search are synchronous reads. `/health` provides operational liveness. -In particular, the legacy interface does not provide the `consultation.retrieve` operation, which retrieves a Record directly by its stable Record Identifier. Its `POST /read` operation performs search-by-example instead. +The server URL identifies the deployment root, optionally with a stable prefix +such as `/registry`. The major version precedes the collection in each operation +path. API-family labels describe capabilities; families can share resource paths +with distinct HTTP methods, schemas, and access requirements. -No canonical OpenAPI contract for the 3.0.0-alpha.2 specification is published. An implementation therefore cannot claim API-contract conformance with this alpha. +The shared Record schemas apply the [Registry Core](../spec/05-api-families/registry-core.md) +representation rules. Core metadata is published separately as a static document or +catalogue entry. It identifies the Registry and its authority and links each service +to its deployed OpenAPI contract. Together, the metadata and selected Consultation +operations provide the Core + Consultation contract. + +A deployment publishes its selected operations with concrete schemas for +`data`, selector values, search criteria, and supported sorting. Its contract +declares collection scope, source currency, security, limits, and continuation rules. +The [OpenAPI examples](examples/README.md) show business reads, household +memberships, and birth-registration parent details. + +[coverage.yaml](coverage.yaml) maps DRAFT requirements to operations or review +evidence. [Common component provenance](common/README.md) pins the vendored +schemas for local reference resolution. + +## Validation + +From the repository root, validate the four OpenAPI documents, domain schemas, +inline examples, and positive and negative fixtures: + +```sh +uv run --with-requirements tools/requirements-api.txt python tools/validate_consultation.py +``` + +With the sibling `bb-template` checkout at guide/ruleset `0.2.0-draft` and its +documented linter dependencies installed, run the canonical artifact gate: + +```sh +uv run --with-requirements tools/requirements-api.txt node ../bb-template/api-design-guide/linter/cli.mjs --repo-root . +``` + +The checks validate current artifacts and local dependencies. The guide gate +checks canonical discovery, requirement coverage, OpenAPI, and Spectral rules. +[Implementation tests](../spec/11-testing.md) cover runtime authorization, +source behavior, and cursor guarantees. + +The canonical contract has these reviewed advisory findings: + +- **8.7:** The contract assigns quotas to the gateway and declares `Retry-After`. + The linter's proxy recommends BB-owned `RateLimit` headers on the Record, + RecordPage, and TooManyRequests responses. +- **7.16:** List uses `Cache-Control: no-store` with live pagination. + The linter recommends ETag and `304` support. Conditional Retrieve is optional. + +These findings are advisory; no rule exceptions are declared. + +## Historical artifacts + +`legacy/generated-crud/` preserves APIs from earlier releases for migration +analysis. Release context and contributor credits are in the +[legacy API README](legacy/generated-crud/README.md). Current Consultation +validation uses the artifacts listed above. diff --git a/api/common/README.md b/api/common/README.md new file mode 100644 index 0000000..e135eec --- /dev/null +++ b/api/common/README.md @@ -0,0 +1,16 @@ +# Shared HTTP schemas + +[govstack-openapi-common.yaml](govstack-openapi-common.yaml) is vendored unchanged +from `bb-template/api/common/govstack-openapi-common.yaml`, component version +**0.1.0-draft**. This component version is independent of the guide and ruleset +version **0.2.0-draft** used by the Consultation contracts. + +SHA-256: `05d1bfc89c86a8d64005e343268326b3fb43cd044fe30f662fec0f9f573b0c73`. + +The library contains no operations and is not a second API surface. Consultation +references its Problem, ValidationProblem and PageInfo schemas; local schemas +narrow pagination metadata to this binding's cursor constraints. Parameters, +headers, responses, error examples and security schemes remain local. + +To update it, review the published version and changes, replace the file as a +unit, update this provenance record, and rerun [API validation](../README.md#validation). diff --git a/api/common/govstack-openapi-common.yaml b/api/common/govstack-openapi-common.yaml new file mode 100644 index 0000000..f89b516 --- /dev/null +++ b/api/common/govstack-openapi-common.yaml @@ -0,0 +1,105 @@ +openapi: 3.1.0 +info: + title: GovStack OpenAPI Common Schemas + version: 0.1.0-draft + description: >- + Minimal cross-BB schemas for HTTP problem details, field validation, and + cursor pagination. Each BB owns its operations, security, parameters, + headers, responses, and examples. + contact: + name: GovStack API Working Group + url: https://www.govstack.global/ +paths: {} +x-govstack-components-version: 0.1.0-draft +components: + schemas: + Problem: + type: object + description: >- + RFC 9457 problem details with one stable machine identifier in type and + a trace identifier for correlation. Error text contains no personal + data or system-internal detail. + required: + - type + - title + - status + - traceId + properties: + type: + type: string + format: uri + pattern: '^https://govstack\.global/problems/[a-z][a-z0-9-]{1,30}/[a-z][a-z0-9]*(?:-[a-z0-9]+)*$' + description: >- + Stable GovStack problem-type URI and machine identifier in the form + https://govstack.global/problems/{bb-code}/{problem-slug}, where the + problem slug uses kebab-case. + title: + type: string + minLength: 1 + description: Short human-readable summary of the problem type. + status: + type: integer + minimum: 400 + maximum: 599 + description: HTTP status code for this occurrence. + detail: + type: string + description: Human-readable explanation specific to this occurrence. + instance: + type: string + format: uri-reference + description: URI reference identifying this problem occurrence. + traceId: + type: string + pattern: '^(?!0{32}$)[\da-f]{32}$' + description: The 32-hex-digit trace-id component of the effective request traceparent. + ValidationProblem: + description: Problem details for a request containing one or more invalid fields. + allOf: + - $ref: '#/components/schemas/Problem' + - type: object + description: Field-level validation details. + required: + - errors + properties: + errors: + type: array + minItems: 1 + description: One entry for each request field that failed validation. + items: + $ref: '#/components/schemas/FieldError' + FieldError: + type: object + description: Human-readable failure associated with one request field. + required: + - pointer + - message + properties: + pointer: + type: string + format: json-pointer + description: JSON Pointer identifying the invalid request field. + message: + type: string + minLength: 1 + description: Human-readable explanation of the field failure. + PageInfo: + type: object + description: Cursor metadata for a bounded collection response. + required: + - nextCursor + properties: + nextCursor: + type: + - string + - 'null' + minLength: 1 + description: Opaque non-empty cursor for the next page, or null on the final page. + total: + type: integer + minimum: 0 + description: >- + Optional total number of matching resources when inexpensive to + compute. Each BB use must document whether the value is exact or + estimated and whether it describes the current collection or the + snapshot used to produce the first page. diff --git a/api/coverage.yaml b/api/coverage.yaml new file mode 100644 index 0000000..6f83d39 --- /dev/null +++ b/api/coverage.yaml @@ -0,0 +1,46 @@ +version: 1 +# Review-only draft mappings do not establish certification or promote maturity. +requirements: [] +draftRequirements: + - id: govstack-bb-digital-registries-fr-core#req-1 + disposition: non-api + rationale: Review the published registry profile and metadata, outside individual read response bodies. + - id: govstack-bb-digital-registries-fr-core#req-2 + disposition: operation + operations: [retrieveRecord, lookupRecord, listRecords, searchRecords] + - id: govstack-bb-digital-registries-fr-core#req-3 + disposition: non-api + rationale: Audit source identifier stability, reuse and migration policy across time and services. + - id: govstack-bb-digital-registries-fr-core#req-4 + disposition: operation + operations: [retrieveRecord, lookupRecord, listRecords, searchRecords] + - id: govstack-bb-digital-registries-fr-core#req-5 + disposition: non-api + rationale: Review any claimed revision and lifecycle metadata against the source; the minimal read binding claims none. + - id: govstack-bb-digital-registries-fr-core#req-6 + disposition: non-api + rationale: Review any provided provenance against source evidence and declared semantics; the minimal read binding requires no provenance enrichment. + - id: govstack-bb-digital-registries-fr-core#req-7 + disposition: non-api + rationale: Verify that published service discovery metadata identifies the scoped registry, selected capabilities and operational contract. + - id: govstack-bb-digital-registries-fr-consultation#req-1 + disposition: operation + operations: [retrieveRecord] + - id: govstack-bb-digital-registries-fr-consultation#req-2 + disposition: operation + operations: [retrieveRecord, lookupRecord, listRecords, searchRecords] + - id: govstack-bb-digital-registries-fr-consultation#req-3 + disposition: operation + operations: [retrieveRecord, lookupRecord] + - id: govstack-bb-digital-registries-fr-consultation#req-4 + disposition: operation + operations: [lookupRecord] + - id: govstack-bb-digital-registries-fr-consultation#req-5 + disposition: operation + operations: [listRecords] + - id: govstack-bb-digital-registries-fr-consultation#req-6 + disposition: operation + operations: [searchRecords] + - id: govstack-bb-digital-registries-fr-consultation#req-7 + disposition: operation + operations: [listRecords, searchRecords] diff --git a/api/examples/README.md b/api/examples/README.md new file mode 100644 index 0000000..8fa54ff --- /dev/null +++ b/api/examples/README.md @@ -0,0 +1,44 @@ +# OpenAPI examples + +These illustrative deployments specialize the [Consultation contract](../openapi.yaml). + +| OpenAPI | Collection | Capabilities | Record view | +| --- | --- | --- | --- | +| [Business registry](business-registry.openapi.yaml) | `/v1/businesses` | Retrieve, Lookup, List, Search | Legal name and registration status | +| [Household registry](household-registry.openapi.yaml) | `/v1/households` | Retrieve | Address, memberships, and individual references | +| [Birth registration](birth-registration.openapi.yaml) | `/v1/birth-registrations` | Retrieve | Birth details and recorded parent information | + +Each contract publishes its Registry context, schemas, source currency, access +policy, limits, and response examples. The business contract also defines exact +and composite selectors, a typed status search, and live cursor pagination. + +The examples use `https://registry.example` as their API root. A deployment can +combine several collections under that root and associate each with its Registry. +Business Lookup and Search use `/v1/businesses:lookup` and +`/v1/businesses:search`; item identifiers remain in `/v1/businesses/{recordId}`. + +Household memberships are embedded components with household-scoped identifiers. +Their individual references inherit the target Registry from the field schema. +Birth-registration parent details carry their recorded meaning and can include +an individual reference. The concrete schemas declare each view's array bounds +and completeness. + +`IndividualReference` illustrates a binding to a target Individual service and +maps the referenced identifier to its Retrieve operation. That target contract is +not included in these artifacts; validation covers the reference shape and the +containing Record views. + +## Schemas and fixtures + +| Schema | Fixtures | +| --- | --- | +| [Business Record and request schemas](business-registry.schema.json) | [Consultation exchanges](consultation-exchanges.json) | +| [Household, birth-registration, and reference schemas](relationship-examples.schema.json) | [Relationship exchanges](relationship-exchanges.json) | + +Named exchanges represent independent fixture states, except +`emptySearchContinuation` and `finalSearchPage`, which form one traversal. +Example cursors are illustrative values. + +The [artifact validator](../../tools/validate_consultation.py) checks operation +schemas, examples, and valid and invalid inputs. Run it using the +[validation commands](../README.md#validation). diff --git a/api/examples/birth-registration.openapi.yaml b/api/examples/birth-registration.openapi.yaml new file mode 100644 index 0000000..b061242 --- /dev/null +++ b/api/examples/birth-registration.openapi.yaml @@ -0,0 +1,104 @@ +openapi: 3.1.2 +info: + title: 'Birth-registration registry Consultation: recorded-parent view' + version: 1.0.0-draft + description: >- + Illustrative birth-registrations collection for Registry + https://registry.example/registries/birth-registrations. Its membership is all birth + registration Records in that Registry. Retrieve selects the + birth-registration-with-recorded-parents view. BirthRegistrationRecord is defined in + relationship-examples.schema.json, published with dependencies at + https://registry.example/contracts/1.0.0-draft/examples/relationship-examples.schema.json. + Reads synchronously query the authoritative registration source and authorize all released + fields and components. + This profile returns the complete permitted parent view in source order, bounded to four + components. Overflow uses generic 500, subject to protected-existence policy. Optional + individualRef targets the Individuals Registry; IndividualReference declares its target + collection, Retrieve binding and identifier mapping. + Access tokens use issuer https://identity.example, the stable logical service audience + https://registry.example/birth-registrations and the declared read scope. Example + endpoints are non-production. TLS is 1.3 or later; the gateway allows 60 requests per + authenticated client per minute. Responses use no-store. Unsupported query parameters use + 400. + contact: + name: GovStack Digital Registries Working Group + url: https://github.com/GovStackWorkingGroup/bb-digital-registries + x-govstack-api-guide: + version: 0.2.0-draft + rulesetVersion: 0.2.0-draft +servers: + - url: https://{gatewayHost} + description: Non-production deployment root. The birth-registrations collection declares + its Registry, membership and representation. + variables: + gatewayHost: + default: registry.example + description: Reserved non-production documentation-domain default. +security: + - citizenOAuth: [bb:digital-registries:record:read] + - serviceOAuth: [bb:digital-registries:record:read] +tags: + - name: Consultation + description: Retrieve a permitted birth-registration view with recorded parent components. +paths: + /health: + $ref: '../openapi.yaml#/paths/~1health' + /v1/birth-registrations/{recordId}: + get: + operationId: retrieveBirthRegistration + summary: Retrieve a birth registration with its recorded parent data + description: >- + Retrieve a Record in the birth-registrations collection with its permitted view. + Parent components preserve nameAtRegistration as recorded; individualRef supplies + optional related Record identity. Absent Records, Records outside this collection + and protected existence share 404 record-not-available. + tags: [Consultation] + parameters: + - $ref: '../openapi.yaml#/components/parameters/RecordId' + - $ref: '../openapi.yaml#/components/parameters/Traceparent' + responses: + '200': + description: Complete permitted birth-registration view within its published profile bound. + headers: + Cache-Control: + $ref: '../openapi.yaml#/components/headers/CacheControl' + content: + application/json: + schema: + $ref: './relationship-examples.schema.json#/$defs/BirthRegistrationRecord' + example: + recordId: birth_19 + data: + dateOfBirth: '2020-06-12' + placeOfBirth: Example Town + parents: + - nameAtRegistration: Alex Example + - nameAtRegistration: Robin Example + individualRef: + recordId: person_57 + '400': + $ref: '../openapi.yaml#/components/responses/BadRequest' + '401': + $ref: '../openapi.yaml#/components/responses/Unauthorized' + '403': + $ref: '../openapi.yaml#/components/responses/Forbidden' + '404': + $ref: '../openapi.yaml#/components/responses/RecordNotAvailable' + '406': + $ref: '../openapi.yaml#/components/responses/NotAcceptable' + '429': + $ref: '../openapi.yaml#/components/responses/TooManyRequests' + '500': + $ref: '../openapi.yaml#/components/responses/InternalError' + '502': + $ref: '../openapi.yaml#/components/responses/BadGateway' + '503': + $ref: '../openapi.yaml#/components/responses/ServiceUnavailable' + '504': + $ref: '../openapi.yaml#/components/responses/GatewayTimeout' +components: + securitySchemes: + citizenOAuth: + $ref: '../openapi.yaml#/components/securitySchemes/citizenOAuth' + serviceOAuth: + $ref: '../openapi.yaml#/components/securitySchemes/serviceOAuth' diff --git a/api/examples/business-registry.openapi.yaml b/api/examples/business-registry.openapi.yaml new file mode 100644 index 0000000..32331e1 --- /dev/null +++ b/api/examples/business-registry.openapi.yaml @@ -0,0 +1,291 @@ +# Illustrative deployment binding; api/openapi.yaml remains the normative transport entrypoint. +openapi: 3.1.2 +info: + title: 'Business registry Consultation: concrete illustrative binding' + version: 1.0.0-draft + description: >- + Illustrative businesses collection for Registry https://registry.example/registries/business. + Its membership is all business registration Records in that Registry, including dissolved + registrations. Operations select the business-public view. Record.data follows + business-registry.schema.json, published with dependencies at + https://registry.example/contracts/1.0.0-draft/examples/business-registry.schema.json. + All four capabilities are selected. Reads synchronously query the authoritative source and + apply the caller’s permitted view. + Access tokens use issuer https://identity.example, the stable logical service audience + https://registry.example/business and the declared read scope. TLS is 1.3 or later. + Example endpoints are non-production. The gateway allows 60 requests per authenticated + client per minute and an 8 KiB request body. + Pages use live ascending ASCII recordId order. The initial pageSize defaults to 20, + maximum 100; continuations retain that effective value. Cursors expire 15 minutes after + traversal creation. Each page scans at most 1000 candidates or two seconds of source work; + its cursor advances beyond the last scanned candidate. Disclosure policy permits these + progress patterns. total is exact for permitted matches at page evaluation and is omitted + when unavailable within budget. Typed request schemas declare accepted inputs. Malformed + or structurally invalid input, unsupported query parameters and invalid pagination + controls use 400. Structurally valid bodies with unknown selector or search names or + invalid domain values use 422. + contact: + name: GovStack Digital Registries Working Group + url: https://github.com/GovStackWorkingGroup/bb-digital-registries + x-govstack-api-guide: + version: 0.2.0-draft + rulesetVersion: 0.2.0-draft +servers: +- url: https://{gatewayHost} + description: Non-production deployment root. The businesses collection declares its Registry + association, membership and representation independently of this root. + variables: + gatewayHost: + default: registry.example + description: Non-production reserved documentation-domain default. +security: +- citizenOAuth: + - bb:digital-registries:record:read +- serviceOAuth: + - bb:digital-registries:record:read +tags: +- name: Consultation + description: Read authorized Records from the businesses collection. +- name: Health + description: Bounded operational liveness without registry information. +paths: + /health: + $ref: ../openapi.yaml#/paths/~1health + /v1/businesses/{recordId}: + get: + operationId: retrieveBusiness + summary: Retrieve one record by its stable identifier + description: >- + Retrieve the permitted business-public view by source recordId within the businesses + collection. Absent Records, Records outside this collection and protected existence + share 404 record-not-available. The response uses no-store. + tags: + - Consultation + parameters: + - $ref: ../openapi.yaml#/components/parameters/RecordId + - $ref: ../openapi.yaml#/components/parameters/Traceparent + responses: + '200': + description: One authorized business-public record. + headers: + Cache-Control: + $ref: ../openapi.yaml#/components/headers/CacheControl + content: + application/json: + schema: + $ref: '#/components/schemas/BusinessRecord' + '400': + $ref: ../openapi.yaml#/components/responses/BadRequest + '401': + $ref: ../openapi.yaml#/components/responses/Unauthorized + '403': + $ref: ../openapi.yaml#/components/responses/Forbidden + '404': + $ref: ../openapi.yaml#/components/responses/RecordNotAvailable + '406': + $ref: ../openapi.yaml#/components/responses/NotAcceptable + '429': + $ref: ../openapi.yaml#/components/responses/TooManyRequests + '500': + $ref: ../openapi.yaml#/components/responses/InternalError + '502': + $ref: ../openapi.yaml#/components/responses/BadGateway + '503': + $ref: ../openapi.yaml#/components/responses/ServiceUnavailable + '504': + $ref: ../openapi.yaml#/components/responses/GatewayTimeout + /v1/businesses: + get: + operationId: listBusinesses + summary: List an authorized page of records + description: >- + Return permitted Records from the businesses collection in ascending ASCII recordId + order using the declared live pagination policy. Continue with cursor and the retained + effective pageSize. Only nextCursor null ends traversal. + tags: + - Consultation + parameters: + - $ref: ../openapi.yaml#/components/parameters/Traceparent + - $ref: ../openapi.yaml#/components/parameters/PageSize + - $ref: ../openapi.yaml#/components/parameters/Cursor + responses: + '200': + description: A bounded page of business-public records in ascending ASCII recordId + order. + headers: + Cache-Control: + $ref: ../openapi.yaml#/components/headers/CacheControl + content: + application/json: + schema: + $ref: '#/components/schemas/BusinessPage' + '400': + $ref: ../openapi.yaml#/components/responses/BadRequest + '401': + $ref: ../openapi.yaml#/components/responses/Unauthorized + '403': + $ref: ../openapi.yaml#/components/responses/Forbidden + '406': + $ref: ../openapi.yaml#/components/responses/NotAcceptable + '429': + $ref: ../openapi.yaml#/components/responses/TooManyRequests + '500': + $ref: ../openapi.yaml#/components/responses/InternalError + '502': + $ref: ../openapi.yaml#/components/responses/BadGateway + '503': + $ref: ../openapi.yaml#/components/responses/ServiceUnavailable + '504': + $ref: ../openapi.yaml#/components/responses/GatewayTimeout + /v1/businesses:lookup: + post: + operationId: lookupBusiness + summary: Look up one record using a declared exact selector + description: >- + Resolve byRegistrationNumber or the composite byJurisdictionNumber key within the + businesses collection using byte-for-byte string matching. BusinessLookupRequest + defines their fields and uniqueness scopes. Return the permitted Record, 404 for an + unavailable match, or generic 500 for a uniqueness violation. Malformed or structurally invalid input uses + 400; structurally valid input with an unknown selector or invalid domain values uses + 422. Protected-existence policy applies before Record-specific diagnostics. + tags: + - Consultation + parameters: + - $ref: ../openapi.yaml#/components/parameters/Traceparent + requestBody: + required: true + description: One published exact selector and all its typed key values. + content: + application/json: + schema: + $ref: '#/components/schemas/BusinessLookupRequest' + examples: + byRegistrationNumber: + summary: Illustrative declared selector from the business binding + value: + selector: byRegistrationNumber + values: + registrationNumber: BR-000042 + composite: + summary: Exact composite key + value: + selector: byJurisdictionNumber + values: + jurisdictionCode: AA + localNumber: '00000042' + responses: + '200': + description: One authorized business-public record. + headers: + Cache-Control: + $ref: ../openapi.yaml#/components/headers/CacheControl + content: + application/json: + schema: + $ref: '#/components/schemas/BusinessRecord' + '400': + $ref: ../openapi.yaml#/components/responses/BadRequest + '401': + $ref: ../openapi.yaml#/components/responses/Unauthorized + '403': + $ref: ../openapi.yaml#/components/responses/Forbidden + '404': + $ref: ../openapi.yaml#/components/responses/RecordNotAvailable + '406': + $ref: ../openapi.yaml#/components/responses/NotAcceptable + '413': + $ref: ../openapi.yaml#/components/responses/ContentTooLarge + '415': + $ref: ../openapi.yaml#/components/responses/UnsupportedMediaType + '422': + $ref: ../openapi.yaml#/components/responses/InvalidField + '429': + $ref: ../openapi.yaml#/components/responses/TooManyRequests + '500': + $ref: ../openapi.yaml#/components/responses/InternalError + '502': + $ref: ../openapi.yaml#/components/responses/BadGateway + '503': + $ref: ../openapi.yaml#/components/responses/ServiceUnavailable + '504': + $ref: ../openapi.yaml#/components/responses/GatewayTimeout + /v1/businesses:search: + post: + operationId: searchBusinesses + summary: Execute one declared search and return a page + description: >- + Search the businesses collection byRegistrationStatus using exact equality. Repeat + search and criteria with cursor on continuation; pageSize may be omitted to retain its + bound value. Apply the declared live pagination policy. Malformed or structurally invalid input and invalid + pagination controls use 400. Structurally valid input with an unknown search or invalid + domain values uses 422; malformed, expired or mismatched continuations use 400 + invalid-cursor. + tags: + - Consultation + parameters: + - $ref: ../openapi.yaml#/components/parameters/Traceparent + requestBody: + required: true + description: One declared search with criteria and body-carried pagination controls. + content: + application/json: + schema: + $ref: '#/components/schemas/BusinessSearchRequest' + examples: + byRegistrationStatus: + summary: First page using the business binding's status search + value: + search: byRegistrationStatus + criteria: + registrationStatus: DISSOLVED + pageSize: 20 + responses: + '200': + description: A bounded page of business-public records in ascending ASCII recordId + order. + headers: + Cache-Control: + $ref: ../openapi.yaml#/components/headers/CacheControl + content: + application/json: + schema: + $ref: '#/components/schemas/BusinessPage' + '400': + $ref: ../openapi.yaml#/components/responses/BadRequest + '401': + $ref: ../openapi.yaml#/components/responses/Unauthorized + '403': + $ref: ../openapi.yaml#/components/responses/Forbidden + '406': + $ref: ../openapi.yaml#/components/responses/NotAcceptable + '413': + $ref: ../openapi.yaml#/components/responses/ContentTooLarge + '415': + $ref: ../openapi.yaml#/components/responses/UnsupportedMediaType + '422': + $ref: ../openapi.yaml#/components/responses/InvalidField + '429': + $ref: ../openapi.yaml#/components/responses/TooManyRequests + '500': + $ref: ../openapi.yaml#/components/responses/InternalError + '502': + $ref: ../openapi.yaml#/components/responses/BadGateway + '503': + $ref: ../openapi.yaml#/components/responses/ServiceUnavailable + '504': + $ref: ../openapi.yaml#/components/responses/GatewayTimeout +components: + securitySchemes: + citizenOAuth: + $ref: ../openapi.yaml#/components/securitySchemes/citizenOAuth + serviceOAuth: + $ref: ../openapi.yaml#/components/securitySchemes/serviceOAuth + schemas: + BusinessRecord: + $ref: ./business-registry.schema.json#/$defs/BusinessRecord + BusinessPage: + $ref: ./business-registry.schema.json#/$defs/BusinessPage + BusinessLookupRequest: + $ref: ./business-registry.schema.json#/$defs/BusinessLookupRequest + BusinessSearchRequest: + $ref: ./business-registry.schema.json#/$defs/BusinessSearchRequest diff --git a/api/examples/business-registry.schema.json b/api/examples/business-registry.schema.json new file mode 100644 index 0000000..73eed0e --- /dev/null +++ b/api/examples/business-registry.schema.json @@ -0,0 +1,167 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Illustrative business registry Consultation binding", + "description": "Typed business-public data and Consultation inputs. The root validates Record.data; named definitions bind Record, RecordPage, Lookup and Search.", + "$ref": "#/$defs/BusinessData", + "$defs": { + "BusinessData": { + "type": "object", + "additionalProperties": false, + "description": "Fixed business-public view containing the registered legal name and domain registration status.", + "required": ["legalName", "registrationStatus"], + "properties": { + "legalName": { + "type": "string", + "minLength": 1, + "maxLength": 300, + "description": "Current legal name recorded by the business registry; no assertion about a person's identity is made." + }, + "registrationStatus": { + "$ref": "#/$defs/RegistrationStatus" + } + }, + "examples": [{"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}] + }, + "RegistrationStatus": { + "type": "string", + "enum": ["ACTIVE", "DISSOLVED"], + "description": "ACTIVE means registered and not dissolved; DISSOLVED means registration has ended. This profile uses a closed domain vocabulary.", + "examples": ["DISSOLVED"] + }, + "BusinessRecord": { + "description": "The shared record envelope bound to the business-public view; additive envelope metadata remains permitted.", + "allOf": [ + {"$ref": "../openapi.yaml#/components/schemas/Record"}, + { + "type": "object", + "description": "Concrete identity and view constraints for this example.", + "properties": { + "recordId": { + "type": "string", + "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{0,63}(?![\\s\\S])", + "description": "Existing non-personal source identifier. Records are ordered by ascending ASCII bytes of this value, which is also the unique tie-breaker." + }, + "data": {"$ref": "#/$defs/BusinessData"} + } + } + ], + "examples": [{"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}}] + }, + "BusinessPage": { + "description": "A typed business record page; optional total is exact for authorized matching records at evaluation of this page.", + "allOf": [ + {"$ref": "../openapi.yaml#/components/schemas/RecordPage"}, + { + "type": "object", + "description": "Every item uses the same declared business-public view.", + "properties": { + "items": { + "type": "array", + "maxItems": 100, + "description": "At most the effective pageSize business records, in ascending ASCII recordId order.", + "items": {"$ref": "#/$defs/BusinessRecord"} + } + } + } + ], + "examples": [{"items": [], "pageInfo": {"nextCursor": null, "total": 0}}] + }, + "RegistrationNumberValues": { + "type": "object", + "additionalProperties": false, + "description": "Complete exact key, unique throughout this Registry, matched byte for byte.", + "required": ["registrationNumber"], + "properties": { + "registrationNumber": { + "type": "string", + "pattern": "^BR-[0-9]{6}(?![\\s\\S])", + "description": "Registry-assigned registration number, including the uppercase prefix and all six digits." + } + }, + "examples": [{"registrationNumber": "BR-000042"}] + }, + "JurisdictionNumberValues": { + "type": "object", + "additionalProperties": false, + "description": "Composite exact key whose pair is unique in this Registry. Both fields are matched byte for byte.", + "required": ["jurisdictionCode", "localNumber"], + "properties": { + "jurisdictionCode": { + "type": "string", + "pattern": "^[A-Z]{2}(?![\\s\\S])", + "description": "Two-letter registry-owned jurisdiction code, not asserted to be an ISO country code." + }, + "localNumber": { + "type": "string", + "pattern": "^[0-9]{8}(?![\\s\\S])", + "description": "Eight-digit identifier within the jurisdiction; leading zeroes are significant." + } + }, + "examples": [{"jurisdictionCode": "AA", "localNumber": "00000042"}] + }, + "BusinessLookupRequest": { + "type": "object", + "additionalProperties": false, + "description": "One of two typed exact-key selectors. Selector names determine their complete accepted key fields.", + "required": ["selector", "values"], + "properties": { + "selector": { + "type": "string", + "description": "Published exact selector name, constrained together with its values by oneOf." + }, + "values": { + "type": "object", + "description": "The complete typed key associated with the chosen selector." + } + }, + "oneOf": [ + { + "description": "Registry-wide registration-number lookup.", + "properties": { + "selector": {"const": "byRegistrationNumber"}, + "values": {"$ref": "#/$defs/RegistrationNumberValues"} + } + }, + { + "description": "Jurisdiction and local-number composite lookup.", + "properties": { + "selector": {"const": "byJurisdictionNumber"}, + "values": {"$ref": "#/$defs/JurisdictionNumberValues"} + } + } + ], + "examples": [ + {"selector": "byRegistrationNumber", "values": {"registrationNumber": "BR-000042"}}, + {"selector": "byJurisdictionNumber", "values": {"jurisdictionCode": "AA", "localNumber": "00000042"}} + ] + }, + "RegistrationStatusCriteria": { + "type": "object", + "additionalProperties": false, + "description": "One equality predicate over the declared business registration status, with no implicit case conversion.", + "required": ["registrationStatus"], + "properties": {"registrationStatus": {"$ref": "#/$defs/RegistrationStatus"}}, + "examples": [{"registrationStatus": "DISSOLVED"}] + }, + "BusinessSearchRequest": { + "type": "object", + "additionalProperties": false, + "description": "Status-equality search with typed criteria and continuation controls. Repeat search and criteria on continuation.", + "required": ["search", "criteria"], + "properties": { + "search": { + "type": "string", + "const": "byRegistrationStatus", + "description": "The published status-equality search name." + }, + "criteria": {"$ref": "#/$defs/RegistrationStatusCriteria"}, + "pageSize": {"$ref": "../openapi.yaml#/components/schemas/PageSize"}, + "cursor": {"$ref": "../openapi.yaml#/components/schemas/Cursor"} + }, + "examples": [ + {"search": "byRegistrationStatus", "criteria": {"registrationStatus": "DISSOLVED"}, "pageSize": 20}, + {"search": "byRegistrationStatus", "criteria": {"registrationStatus": "DISSOLVED"}, "cursor": "pgn_7JpQ9m2W4xK8fR3cT6vN1"} + ] + } + } +} diff --git a/api/examples/consultation-exchanges.json b/api/examples/consultation-exchanges.json new file mode 100644 index 0000000..fdd2567 --- /dev/null +++ b/api/examples/consultation-exchanges.json @@ -0,0 +1,52 @@ +{ + "description": "Illustrative exchanges for the concrete business binding. Tokens are opaque example strings, not usable live continuations.", + "exchanges": [ + { + "name": "retrieve", + "operationId": "retrieveBusiness", + "status": 200, + "response": {"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}} + }, + { + "name": "lookup", + "operationId": "lookupBusiness", + "request": {"selector": "byRegistrationNumber", "values": {"registrationNumber": "BR-000042"}}, + "status": 200, + "response": {"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}} + }, + { + "name": "compositeLookup", + "operationId": "lookupBusiness", + "request": {"selector": "byJurisdictionNumber", "values": {"jurisdictionCode": "AA", "localNumber": "00000042"}}, + "status": 200, + "response": {"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}} + }, + { + "name": "emptySearchContinuation", + "operationId": "searchBusinesses", + "request": {"search": "byRegistrationStatus", "criteria": {"registrationStatus": "DISSOLVED"}, "pageSize": 20}, + "status": 200, + "response": {"items": [], "pageInfo": {"nextCursor": "pgn_7JpQ9m2W4xK8fR3cT6vN1"}} + }, + { + "name": "finalSearchPage", + "operationId": "searchBusinesses", + "request": {"search": "byRegistrationStatus", "criteria": {"registrationStatus": "DISSOLVED"}, "cursor": "pgn_7JpQ9m2W4xK8fR3cT6vN1"}, + "status": 200, + "response": {"items": [{"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}}], "pageInfo": {"nextCursor": null}} + }, + { + "name": "emptyList", + "operationId": "listBusinesses", + "status": 200, + "response": {"items": [], "pageInfo": {"nextCursor": null, "total": 0}} + }, + { + "name": "recordNotAvailable", + "operationId": "lookupBusiness", + "request": {"selector": "byRegistrationNumber", "values": {"registrationNumber": "BR-999999"}}, + "status": 404, + "response": {"type": "https://govstack.global/problems/digital-registries/record-not-available", "title": "Record not available", "status": 404, "traceId": "6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f"} + } + ] +} diff --git a/api/examples/household-registry.openapi.yaml b/api/examples/household-registry.openapi.yaml new file mode 100644 index 0000000..4b88303 --- /dev/null +++ b/api/examples/household-registry.openapi.yaml @@ -0,0 +1,109 @@ +openapi: 3.1.2 +info: + title: 'Household registry Consultation: nested fixed-view example' + version: 1.0.0-draft + description: >- + Illustrative households collection for Registry https://registry.example/registries/households. + Its membership is all household Records in that Registry. Retrieve selects the + household-with-memberships view. HouseholdRecord is defined in + relationship-examples.schema.json, published with dependencies at + https://registry.example/contracts/1.0.0-draft/examples/relationship-examples.schema.json. + Reads synchronously query the authoritative household source and authorize all released + fields and components. + This profile returns complete permitted arrays within bounds of 20 memberships and three + address lines. Overflow uses generic 500, subject to protected-existence policy. + individualRef targets the Individuals Registry; IndividualReference declares its target + collection, Retrieve binding and identifier mapping. + Access tokens use issuer https://identity.example, the stable logical service audience + https://registry.example/households and the declared read scope. Example endpoints are + non-production. TLS is 1.3 or later; the gateway allows 60 requests per authenticated + client per minute. Responses use no-store. Unsupported query parameters use 400. + contact: + name: GovStack Digital Registries Working Group + url: https://github.com/GovStackWorkingGroup/bb-digital-registries + x-govstack-api-guide: + version: 0.2.0-draft + rulesetVersion: 0.2.0-draft +servers: + - url: https://{gatewayHost} + description: Non-production deployment root. The households collection declares its Registry, + membership and representation. + variables: + gatewayHost: + default: registry.example + description: Reserved non-production documentation-domain default. +security: + - citizenOAuth: [bb:digital-registries:record:read] + - serviceOAuth: [bb:digital-registries:record:read] +tags: + - name: Consultation + description: Retrieve a permitted household view with embedded components. +paths: + /health: + $ref: '../openapi.yaml#/paths/~1health' + /v1/households/{recordId}: + get: + operationId: retrieveHousehold + summary: Retrieve a household with its declared embedded components + description: >- + Retrieve a Record in the households collection with its permitted embedded address + and membership components. individualRef identifies the related Individual Record. + Absent Records, Records outside this collection and protected existence share + 404 record-not-available. + tags: [Consultation] + parameters: + - $ref: '../openapi.yaml#/components/parameters/RecordId' + - $ref: '../openapi.yaml#/components/parameters/Traceparent' + responses: + '200': + description: Complete permitted household view within its published profile bounds. + headers: + Cache-Control: + $ref: '../openapi.yaml#/components/headers/CacheControl' + content: + application/json: + schema: + $ref: './relationship-examples.schema.json#/$defs/HouseholdRecord' + example: + recordId: household_8 + data: + address: + addressLines: [12 Example Street] + locality: Example Town + postalCode: '00120' + memberships: + - membershipId: membership_1 + role: REFERENCE_PERSON + individualRef: + recordId: person_42 + - membershipId: membership_2 + role: MEMBER + individualRef: + recordId: person_57 + registryId: https://registry.example/registries/individuals + '400': + $ref: '../openapi.yaml#/components/responses/BadRequest' + '401': + $ref: '../openapi.yaml#/components/responses/Unauthorized' + '403': + $ref: '../openapi.yaml#/components/responses/Forbidden' + '404': + $ref: '../openapi.yaml#/components/responses/RecordNotAvailable' + '406': + $ref: '../openapi.yaml#/components/responses/NotAcceptable' + '429': + $ref: '../openapi.yaml#/components/responses/TooManyRequests' + '500': + $ref: '../openapi.yaml#/components/responses/InternalError' + '502': + $ref: '../openapi.yaml#/components/responses/BadGateway' + '503': + $ref: '../openapi.yaml#/components/responses/ServiceUnavailable' + '504': + $ref: '../openapi.yaml#/components/responses/GatewayTimeout' +components: + securitySchemes: + citizenOAuth: + $ref: '../openapi.yaml#/components/securitySchemes/citizenOAuth' + serviceOAuth: + $ref: '../openapi.yaml#/components/securitySchemes/serviceOAuth' diff --git a/api/examples/relationship-examples.schema.json b/api/examples/relationship-examples.schema.json new file mode 100644 index 0000000..65252b7 --- /dev/null +++ b/api/examples/relationship-examples.schema.json @@ -0,0 +1,187 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Illustrative household and birth-registration relationship views", + "description": "Typed Household and Birth Registration Record views with embedded components, related Record references and recorded snapshots. Array bounds belong to these example profiles. Each response contains the complete permitted view within its declared bounds.", + "oneOf": [ + {"$ref": "#/$defs/HouseholdRecord"}, + {"$ref": "#/$defs/BirthRegistrationRecord"} + ], + "$defs": { + "IndividualReference": { + "type": "object", + "additionalProperties": false, + "description": "Related Record in the fixed target Registry https://registry.example/registries/individuals. registryId may be omitted; an explicit value must match that target. This illustrative field binding resolves through the individuals collection: operation retrieveIndividual in https://registry.example/contracts/1.0.0-draft/examples/individual-registry.openapi.yaml, GET https://registry.example/v1/individuals/{recordId}. Supply the referenced recordId as the path parameter, encoded as one segment. The illustrative target contract is not included in these artifacts; target access is evaluated separately.", + "allOf": [{"$ref": "../openapi.yaml#/components/schemas/RecordReference"}], + "properties": { + "recordId": {"$ref": "../openapi.yaml#/components/schemas/RecordId"}, + "registryId": { + "type": "string", + "const": "https://registry.example/registries/individuals", + "description": "The same target Registry already fixed by this field's schema." + } + }, + "examples": [ + {"recordId": "person_42"}, + {"recordId": "person_42", "registryId": "https://registry.example/registries/individuals"} + ] + }, + "UnscopedRecordReference": { + "type": "object", + "additionalProperties": false, + "description": "Reference field with an explicit target Registry. Both registryId and recordId are required because the field context leaves the target open.", + "allOf": [{"$ref": "../openapi.yaml#/components/schemas/RecordReference"}], + "required": ["registryId"], + "properties": { + "recordId": {"$ref": "../openapi.yaml#/components/schemas/RecordId"}, + "registryId": { + "type": "string", + "format": "iri", + "description": "Explicit absolute IRI of the target Registry; it need not be a retrieval endpoint." + } + }, + "examples": [ + {"recordId": "person_42", "registryId": "https://registry.example/registries/individuals"}, + {"recordId": "r_7", "registryId": "urn:example:registry:external"} + ] + }, + "Address": { + "type": "object", + "additionalProperties": false, + "description": "Current address embedded in and owned by the household Record.", + "required": ["addressLines", "locality"], + "properties": { + "addressLines": { + "type": "array", + "minItems": 1, + "maxItems": 3, + "description": "Complete ordered address lines, bounded to three in this profile.", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "One non-empty address line." + } + }, + "locality": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "Locality label recorded for this household address." + }, + "postalCode": { + "type": "string", + "minLength": 1, + "maxLength": 32, + "description": "Postal code as a string; leading zeroes are retained. Omitted when not recorded for this view." + } + }, + "examples": [{"addressLines": ["12 Example Street"], "locality": "Example Town", "postalCode": "00120"}] + }, + "HouseholdMembership": { + "type": "object", + "additionalProperties": false, + "description": "Household-owned membership component. membershipId identifies it within the household; role describes the relationship to the referenced individual.", + "required": ["membershipId", "role", "individualRef"], + "properties": { + "membershipId": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "description": "Stable component identifier unique within its household." + }, + "role": { + "type": "string", + "enum": ["REFERENCE_PERSON", "MEMBER"], + "description": "REFERENCE_PERSON identifies the administrative reference person; MEMBER identifies another recorded member. This profile uses a closed vocabulary." + }, + "individualRef": {"$ref": "#/$defs/IndividualReference"} + }, + "examples": [{"membershipId": "membership_1", "role": "REFERENCE_PERSON", "individualRef": {"recordId": "person_42"}}] + }, + "HouseholdData": { + "type": "object", + "additionalProperties": false, + "description": "Current household view with an embedded address and complete permitted membership components. Individual identities are carried as references.", + "required": ["address", "memberships"], + "properties": { + "address": {"$ref": "#/$defs/Address"}, + "memberships": { + "type": "array", + "maxItems": 20, + "description": "Complete permitted memberships ordered by membershipId in Unicode scalar order. This profile accepts up to 20 components; overflow fails the read.", + "items": {"$ref": "#/$defs/HouseholdMembership"} + } + }, + "examples": [{"address": {"addressLines": ["12 Example Street"], "locality": "Example Town"}, "memberships": [{"membershipId": "membership_1", "role": "REFERENCE_PERSON", "individualRef": {"recordId": "person_42"}}]}] + }, + "HouseholdRecord": { + "description": "Record in https://registry.example/registries/households with the typed household view and an extensible envelope.", + "allOf": [ + {"$ref": "../openapi.yaml#/components/schemas/Record"}, + { + "type": "object", + "description": "Concrete household data binding.", + "properties": {"data": {"$ref": "#/$defs/HouseholdData"}} + } + ], + "examples": [{"recordId": "household_8", "data": {"address": {"addressLines": ["12 Example Street"], "locality": "Example Town"}, "memberships": [{"membershipId": "membership_1", "role": "REFERENCE_PERSON", "individualRef": {"recordId": "person_42"}}]}}] + }, + "ParentAtRegistration": { + "type": "object", + "additionalProperties": false, + "description": "Parent details captured by the birth registration. nameAtRegistration retains its recorded meaning. individualRef is optional and supplies related Record identity when available.", + "required": ["nameAtRegistration"], + "properties": { + "nameAtRegistration": { + "type": "string", + "minLength": 1, + "maxLength": 300, + "description": "Parent name captured at registration, preserved as a historical fact." + }, + "individualRef": {"$ref": "#/$defs/IndividualReference"} + }, + "examples": [ + {"nameAtRegistration": "Alex Example"}, + {"nameAtRegistration": "Robin Example", "individualRef": {"recordId": "person_57"}} + ] + }, + "BirthRegistrationData": { + "type": "object", + "additionalProperties": false, + "description": "Recorded birth event and parent details in the fixed registration view.", + "required": ["dateOfBirth", "placeOfBirth", "parents"], + "properties": { + "dateOfBirth": { + "type": "string", + "format": "date", + "description": "Calendar date of birth as recorded by this registration." + }, + "placeOfBirth": { + "type": "string", + "minLength": 1, + "maxLength": 300, + "description": "Place of birth label captured by the registration." + }, + "parents": { + "type": "array", + "maxItems": 4, + "description": "Complete permitted parent components in source registration order. This profile accepts up to four components; overflow fails the read.", + "items": {"$ref": "#/$defs/ParentAtRegistration"} + } + }, + "examples": [{"dateOfBirth": "2020-06-12", "placeOfBirth": "Example Town", "parents": [{"nameAtRegistration": "Alex Example"}, {"nameAtRegistration": "Robin Example", "individualRef": {"recordId": "person_57"}}]}] + }, + "BirthRegistrationRecord": { + "description": "Record in https://registry.example/registries/birth-registrations with recorded parent data and optional related Record references.", + "allOf": [ + {"$ref": "../openapi.yaml#/components/schemas/Record"}, + { + "type": "object", + "description": "Concrete birth-registration data binding.", + "properties": {"data": {"$ref": "#/$defs/BirthRegistrationData"}} + } + ], + "examples": [{"recordId": "birth_19", "data": {"dateOfBirth": "2020-06-12", "placeOfBirth": "Example Town", "parents": [{"nameAtRegistration": "Alex Example"}, {"nameAtRegistration": "Robin Example", "individualRef": {"recordId": "person_57"}}]}}] + } + } +} diff --git a/api/examples/relationship-exchanges.json b/api/examples/relationship-exchanges.json new file mode 100644 index 0000000..e467ba2 --- /dev/null +++ b/api/examples/relationship-exchanges.json @@ -0,0 +1,45 @@ +{ + "description": "Household and Birth Registration Retrieve responses, each linked to its operation contract, plus a reference with an explicit target Registry.", + "examples": [ + { + "name": "householdWithEmbeddedMemberships", + "contract": "household-registry.openapi.yaml", + "operationId": "retrieveHousehold", + "status": 200, + "schema": "HouseholdRecord", + "value": { + "recordId": "household_8", + "data": { + "address": {"addressLines": ["12 Example Street"], "locality": "Example Town", "postalCode": "00120"}, + "memberships": [ + {"membershipId": "membership_1", "role": "REFERENCE_PERSON", "individualRef": {"recordId": "person_42"}}, + {"membershipId": "membership_2", "role": "MEMBER", "individualRef": {"recordId": "person_57", "registryId": "https://registry.example/registries/individuals"}} + ] + } + } + }, + { + "name": "birthRegistrationWithParentSnapshots", + "contract": "birth-registration.openapi.yaml", + "operationId": "retrieveBirthRegistration", + "status": 200, + "schema": "BirthRegistrationRecord", + "value": { + "recordId": "birth_19", + "data": { + "dateOfBirth": "2020-06-12", + "placeOfBirth": "Example Town", + "parents": [ + {"nameAtRegistration": "Alex Example"}, + {"nameAtRegistration": "Robin Example", "individualRef": {"recordId": "person_57"}} + ] + } + } + }, + { + "name": "referenceWithoutFixedTargetContext", + "schema": "UnscopedRecordReference", + "value": {"recordId": "r_7", "registryId": "urn:example:registry:external"} + } + ] +} diff --git a/api/openapi.yaml b/api/openapi.yaml new file mode 100644 index 0000000..469fe3a --- /dev/null +++ b/api/openapi.yaml @@ -0,0 +1,817 @@ +openapi: 3.1.2 +info: + title: GovStack Digital Registries Consultation API + version: 1.0.0-draft + description: >- + Read Records through declared collections. Each collection binds a Registry, its member + Records, supported operations and declared representation schemas or views. An API can expose + several collections. Deployments select at least one capability: Retrieve, Lookup, List or + Search. Their contracts declare typed data and input schemas, field meanings, source + currency, authorization and pagination policy. The records collection is the generic + reference binding; deployed contracts publish concrete collection paths and schemas. + Registry Core metadata identifies the Registry, its name, authority, authoritative scope and + specification version, and associates the service with its Registry, supported API + families, endpoint and deployed OpenAPI contract. Metadata can be published as a static + document or through an external catalogue. Each read applies the caller’s permitted + view. Public operations declare security: []. Transport uses TLS + 1.3 or later. The /v1 paths identify this API compatibility line; info.version versions + the draft HTTP contract. + contact: + name: GovStack Digital Registries Working Group + url: https://github.com/GovStackWorkingGroup/bb-digital-registries + x-govstack-api-guide: + version: 0.2.0-draft + rulesetVersion: 0.2.0-draft +servers: + - url: https://{gatewayHost} + description: >- + Deployment root; registry.example is non-production. A deployment may add a stable + routing prefix, such as /registry, before the versioned resource paths. Each collection's + contract supplies its Registry association and selected view; callers do not repeat + registryId on each request. API-family labels classify operations independently of paths. + variables: + gatewayHost: + default: registry.example + description: Deployment gateway hostname; registry.example is non-production. +security: + - citizenOAuth: [bb:digital-registries:record:read] + - serviceOAuth: [bb:digital-registries:record:read] +tags: + - name: Consultation + description: Read authorized Records from declared collections and their associated Registries. + - name: Health + description: Bounded operational liveness without registry information. +paths: + /health: + get: + operationId: getHealth + summary: Check service liveness + description: >- + Return HTTP 200 when the service can accept work and 503 otherwise. This bounded, + unauthenticated check exposes only a public service label. Dependency checks are + limited to those that determine service availability. + tags: [Health] + security: [] + parameters: + - $ref: '#/components/parameters/Traceparent' + responses: + '200': + description: The service is healthy and able to accept work. + content: + application/json: + schema: + $ref: '#/components/schemas/Health' + '500': + $ref: '#/components/responses/InternalError' + '503': + $ref: '#/components/responses/ServiceUnavailable' + /v1/records/{recordId}: + get: + operationId: retrieveRecord + summary: Retrieve one record by its stable identifier + description: >- + Return the permitted Record view for a stable identifier within this collection's + declared membership. Encode recordId as one path segment. Absent Records, Records + outside the collection and protected existence share the 404 response. Conditional + retrieval uses the representation’s ETag after authorization. + tags: [Consultation] + parameters: + - $ref: '#/components/parameters/RecordId' + - $ref: '#/components/parameters/Traceparent' + - $ref: '#/components/parameters/IfNoneMatch' + responses: + '200': + $ref: '#/components/responses/Record' + '304': + $ref: '#/components/responses/NotModified' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/RecordNotAvailable' + '406': + $ref: '#/components/responses/NotAcceptable' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + '502': + $ref: '#/components/responses/BadGateway' + '503': + $ref: '#/components/responses/ServiceUnavailable' + '504': + $ref: '#/components/responses/GatewayTimeout' + /v1/records: + get: + operationId: listRecords + summary: List an authorized page of records + description: >- + Return permitted Records from this collection in the deployment’s deterministic + default order with a unique tie-breaker. Deployments offering sort declare its allowed fields and directions. Each + request is authorized; unsupported query parameters return 400. Continuations follow + the Cursor and PageSize rules. + tags: [Consultation] + parameters: + - $ref: '#/components/parameters/Traceparent' + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/Sort' + responses: + '200': + $ref: '#/components/responses/RecordPage' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '406': + $ref: '#/components/responses/NotAcceptable' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + '502': + $ref: '#/components/responses/BadGateway' + '503': + $ref: '#/components/responses/ServiceUnavailable' + '504': + $ref: '#/components/responses/GatewayTimeout' + /v1/records:lookup: + post: + operationId: lookupRecord + summary: Look up one record using a declared exact selector + description: >- + Resolve one declared exact selector to a permitted Record in this collection. Each + selector specifies typed key fields, normalization, uniqueness scope and permitted + callers. Matching respects the declared collection membership and uniqueness scope. + Keys may be composite or derived from declared verified caller context. A missing + releasable match uses 404; a uniqueness violation uses generic 500, subject to + protected-existence policy. Malformed or structurally invalid input uses 400. + Structurally valid input with an unknown selector or invalid domain values uses 422. + This synchronous read is + retryable without an Idempotency-Key. Selector values remain confined to the request + body. + tags: [Consultation] + parameters: + - $ref: '#/components/parameters/Traceparent' + requestBody: + required: true + description: One published exact selector and all its typed key values. + content: + application/json: + schema: + $ref: '#/components/schemas/LookupRequest' + examples: + byRegistrationNumber: + summary: Illustrative declared selector from the business binding + value: + selector: byRegistrationNumber + values: + registrationNumber: BR-000042 + responses: + '200': + $ref: '#/components/responses/Record' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/RecordNotAvailable' + '406': + $ref: '#/components/responses/NotAcceptable' + '413': + $ref: '#/components/responses/ContentTooLarge' + '415': + $ref: '#/components/responses/UnsupportedMediaType' + '422': + $ref: '#/components/responses/InvalidField' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + '502': + $ref: '#/components/responses/BadGateway' + '503': + $ref: '#/components/responses/ServiceUnavailable' + '504': + $ref: '#/components/responses/GatewayTimeout' + /v1/records:search: + post: + operationId: searchRecords + summary: Execute one declared search and return a page + description: >- + Run one declared typed search within this collection and return a RecordPage. Continue + by POSTing the same search, criteria and any sort values with the returned cursor. + Criteria equality follows declared type semantics, independent of JSON property order. Malformed or + structurally invalid input and invalid pagination controls use 400. Structurally valid + input with an unknown search or invalid domain values uses 422. Invalid continuations + use 400 invalid-cursor. This synchronous read is retryable without an Idempotency-Key. + Search values remain confined to the request body. + tags: [Consultation] + parameters: + - $ref: '#/components/parameters/Traceparent' + requestBody: + required: true + description: One declared search with criteria and body-carried pagination controls. + content: + application/json: + schema: + $ref: '#/components/schemas/SearchRequest' + examples: + byRegistrationStatus: + summary: First page using the business binding's status search + value: + search: byRegistrationStatus + criteria: + registrationStatus: DISSOLVED + pageSize: 20 + responses: + '200': + $ref: '#/components/responses/RecordPage' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '406': + $ref: '#/components/responses/NotAcceptable' + '413': + $ref: '#/components/responses/ContentTooLarge' + '415': + $ref: '#/components/responses/UnsupportedMediaType' + '422': + $ref: '#/components/responses/InvalidField' + '429': + $ref: '#/components/responses/TooManyRequests' + '500': + $ref: '#/components/responses/InternalError' + '502': + $ref: '#/components/responses/BadGateway' + '503': + $ref: '#/components/responses/ServiceUnavailable' + '504': + $ref: '#/components/responses/GatewayTimeout' +components: + securitySchemes: + citizenOAuth: + type: oauth2 + description: >- + Citizen access-token authorization backed by OpenID Connect. Authorization-code + clients use PKCE S256. Deployments publish their issuer and audience, replacing these + non-production endpoints. ID Tokens are rejected. The read scope is evaluated with + Record and field disclosure rules. + flows: + authorizationCode: + authorizationUrl: https://identity.example/authorize + tokenUrl: https://identity.example/token + scopes: + bb:digital-registries:record:read: Attempt authorized Consultation reads. + serviceOAuth: + type: oauth2 + description: >- + Inter-BB client-credentials authorization with confidential-client authentication. + Access tokens are restricted to the service audience and operation scope; + sender-constrained tokens are recommended. Deployments replace the non-production + endpoint and authorize each page’s released data. + flows: + clientCredentials: + tokenUrl: https://identity.example/token + scopes: + bb:digital-registries:record:read: Attempt authorized Consultation reads. + parameters: + RecordId: + name: recordId + in: path + required: true + description: Stable opaque identifier within the selected registry, encoded as one path segment. + schema: + $ref: '#/components/schemas/RecordId' + Traceparent: + name: traceparent + in: header + required: false + description: >- + W3C Trace Context. Propagate valid context; create context when absent or invalid. + Problem traceId is the effective trace-id. Trace metadata excludes personal data. + schema: + type: string + IfNoneMatch: + name: If-None-Match + in: header + required: false + description: >- + Optional conditional Retrieve against the selected representation. Authorization + precedes evaluation of the validator. + schema: + type: string + PageSize: + name: pageSize + in: query + required: false + description: >- + Maximum items in this page, default 20 on the first request. With a + cursor, omission reuses its bound size; a supplied value must equal it. + schema: + $ref: '#/components/schemas/PageSize' + Cursor: + name: cursor + in: query + required: false + description: Omit for the first page; otherwise return the previous page's opaque nextCursor unchanged. + schema: + $ref: '#/components/schemas/Cursor' + Sort: + name: sort + in: query + required: false + description: >- + Declare this parameter when caller-selected sorting is supported. Publish allowed + fields, directions and a unique tie-breaker. Omission uses the default order; + continuation preserves the original sort input. + schema: + $ref: '#/components/schemas/Sort' + headers: + CacheControl: + description: >- + Protected reads and errors use no-store. Deployments may publish another caching + policy for public or properly isolated representations while preserving authorization. + schema: + type: string + const: no-store + ETag: + description: Optional HTTP validator for the caller-selected representation; not a source revision identifier. + schema: + type: string + example: 'W/"representation-7fa9"' + RetryAfter: + description: Delay in seconds or HTTP-date before retrying; authoritative over any advisory quota fields. + schema: + type: string + example: '30' + WwwAuthenticate: + description: Bearer authentication challenge, with no record-specific facts. + schema: + type: string + example: Bearer + schemas: + RecordId: + type: string + minLength: 1 + description: >- + Stable opaque identifier unique across all collections in the selected Registry, + unchanged throughout the Record's lifecycle and never reassigned to a different Record. + The same Record retains its identifier across collections and views. Suitable source + identifiers are retained. Exposed identifiers are non-personal and safe for URL + references. + examples: [r_42] + Record: + type: object + description: >- + Record identity and its typed, permitted domain view. Registry identity, data schema + and field meanings are supplied by the collection and operation binding. data may include + nested objects, embedded relationship components, references and predefined + related-data views with declared ownership and temporal semantics. Optional revision, + lifecycle and provenance fields are source-backed. Readers accept additive envelope + fields. + required: [recordId, data] + properties: + recordId: + $ref: '#/components/schemas/RecordId' + data: + type: object + description: >- + Fixed caller-authorized domain view. Deployments should reuse suitable established + domain schemas and vocabularies, including national or sector schemas. The contract + identifies adopted models and versions and binds their concepts to a concrete JSON + Schema, documenting mappings, local constraints and extensions. The view may contain + typed nested structures and relationships. + examples: + - recordId: r_42 + data: + legalName: Example Ltd + registrationStatus: DISSOLVED + RecordReference: + type: object + description: >- + Identity of a related Record. The field or deployment schema fixes the target + Registry; otherwise registryId is required. An explicit registryId must agree with the + fixed target. Concrete fields encode these constraints. When a target read is + offered, the field binding identifies the target collection, contract and operation, + and maps the referenced identifier to its input. Target reads follow the target + Registry's published capabilities and access policy. Profiles declare any + referential-integrity guarantees. Adopted domain reference forms may be used with + declared target semantics. + required: [recordId] + properties: + recordId: + $ref: '#/components/schemas/RecordId' + registryId: + type: string + format: iri + minLength: 1 + pattern: '^[A-Za-z][A-Za-z0-9+.-]*:' + description: >- + Stable absolute IRI of the target Registry; service endpoints are discovered + separately. + examples: + - recordId: person_42 + registryId: https://registry.example/registries/individuals + RecordPage: + type: object + description: >- + Bounded live page in the declared deterministic order. Concurrent changes can cause + omissions or repeats. A completed traversal over unchanged data and access conditions + contains each permitted matching Record once. Work per page is bounded and + continuations advance. Page boundaries and progress patterns follow disclosure policy. + A short or empty page may continue; nextCursor null ends traversal. total, when present, is exact for the + full permitted query at this page's evaluation, before applying the continuation boundary. + required: [items, pageInfo] + properties: + items: + type: array + maxItems: 100 + description: Authorized records in the deployment's declared deterministic order. + items: + $ref: '#/components/schemas/Record' + pageInfo: + $ref: '#/components/schemas/PageInfo' + examples: + - items: [] + pageInfo: + nextCursor: null + PageSize: + type: integer + minimum: 1 + maximum: 100 + default: 20 + description: >- + Maximum returned items. The first request defaults to 20. Values outside the declared + bounds return 400 bad-request. A continuation may omit pageSize to retain its bound + effective value or repeat that value; a change returns 400 invalid-cursor. + examples: [20] + PageInfo: + description: >- + Continuation metadata. Returned cursors satisfy the Cursor input constraints. Optional + total is exact for the full permitted query at the current page's evaluation, + before applying the continuation boundary. + allOf: + - $ref: './common/govstack-openapi-common.yaml#/components/schemas/PageInfo' + - type: object + description: The continuation obeys the same length and alphabet constraints as the request cursor. + properties: + nextCursor: + description: Opaque continuation accepted by the next request, or null on the final page. + anyOf: + - $ref: '#/components/schemas/Cursor' + - type: 'null' + description: No continuation remains for this traversal. + examples: + - nextCursor: null + - nextCursor: pgn_7JpQ9m2W4xK8fR3cT6vN1 + Cursor: + type: string + minLength: 1 + maxLength: 4096 + pattern: '^[A-Za-z0-9_-]+(?![\s\S])' + description: >- + URL-safe, opaque, integrity-protected continuation, excluding personal data. Bind it + to the service, Registry, collection, selected view, applicable access context, operation, + search name, criteria, ordering and effective pageSize. Return it unchanged and + authorize every request. Deployments publish expiry. Malformed, expired or + mismatched continuations return 400 invalid-cursor. + examples: [pgn_7JpQ9m2W4xK8fR3cT6vN1] + Sort: + type: string + minLength: 1 + pattern: '^-?[A-Za-z][A-Za-z0-9]*(,-?[A-Za-z][A-Za-z0-9]*)*(?![\s\S])' + description: >- + Optional declared field names separated by commas; a minus prefix means + descending. A deployment narrows this schema to its supported fields + and directions, or omits this input when it only provides default ordering. + examples: [recordId] + LookupRequest: + type: object + additionalProperties: false + description: >- + One declared exact selector with its typed key values. Deployments bind each selector + name to a closed values schema, such as oneOf branches with const names. Context-only + selectors use an empty values object; other selectors require their declared + client-supplied fields. + required: [selector, values] + properties: + selector: + type: string + minLength: 1 + description: Name of a deployment-declared exact key selector. + values: + type: object + description: All declared client-supplied key fields, or an empty object for a context-only selector. + examples: + - selector: byRegistrationNumber + values: + registrationNumber: BR-000042 + SearchRequest: + type: object + additionalProperties: false + description: >- + One declared search with typed criteria and continuation controls. Deployments bind + each name to a closed criteria schema and declare sort when supported. + required: [search, criteria] + properties: + search: + type: string + minLength: 1 + description: Name of a deployment-declared search. + criteria: + type: object + description: The closed typed criteria for this search, repeated on continuation. + pageSize: + $ref: '#/components/schemas/PageSize' + cursor: + $ref: '#/components/schemas/Cursor' + sort: + $ref: '#/components/schemas/Sort' + examples: + - search: byRegistrationStatus + criteria: + registrationStatus: DISSOLVED + pageSize: 20 + Problem: + $ref: './common/govstack-openapi-common.yaml#/components/schemas/Problem' + ValidationProblem: + $ref: './common/govstack-openapi-common.yaml#/components/schemas/ValidationProblem' + Health: + type: object + description: Optional informational body; only the HTTP status determines liveness. + properties: + description: + type: string + description: Public human-readable service label with no internal details. + examples: + - description: Digital Registries Consultation + responses: + Record: + description: >- + One permitted Record in the published fixed view. Retrieve and Lookup share this + envelope. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + ETag: + $ref: '#/components/headers/ETag' + content: + application/json: + schema: + $ref: '#/components/schemas/Record' + RecordPage: + description: One bounded page, which may be empty and still have a continuation cursor. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/json: + schema: + $ref: '#/components/schemas/RecordPage' + NotModified: + description: >- + Conditional Retrieve validator matches after authorization; the response is bodyless. + headers: + ETag: + $ref: '#/components/headers/ETag' + Cache-Control: + $ref: '#/components/headers/CacheControl' + BadRequest: + description: >- + bad-request identifies malformed or structurally invalid input, including malformed + JSON, missing or undeclared body members and incorrect JSON types. It also identifies + invalid/unsupported query parameters or invalid pagination controls, such as an + out-of-range pageSize. + invalid-cursor identifies a malformed, expired or mismatched continuation, including + changed effective pageSize. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + examples: + malformed: + value: + type: https://govstack.global/problems/digital-registries/bad-request + title: Invalid request + status: 400 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + structure: + summary: A required request member is missing + value: + type: https://govstack.global/problems/digital-registries/bad-request + title: Invalid request + status: 400 + detail: The request is missing a required member. + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + cursor: + value: + type: https://govstack.global/problems/digital-registries/invalid-cursor + title: Invalid continuation + status: 400 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + Unauthorized: + description: Missing or invalid access token; the problem reveals no record existence. + headers: + WWW-Authenticate: + $ref: '#/components/headers/WwwAuthenticate' + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/unauthorized + title: Authentication required + status: 401 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + Forbidden: + description: >- + Access to the operation or view is denied. Protected Record existence uses the 404 + response. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/forbidden + title: Operation not permitted + status: 403 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + RecordNotAvailable: + description: >- + Absent Records, Records outside the declared collection and protected existence return + the same status, problem type and public detail. Record-specific counts and hints are + withheld. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/record-not-available + title: Record not available + status: 404 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + NotAcceptable: + description: The requested response media type is not supported. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/not-acceptable + title: Response media type not supported + status: 406 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + ContentTooLarge: + description: The request exceeds the deployment's published body-size limit. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/content-too-large + title: Request body too large + status: 413 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + UnsupportedMediaType: + description: This read operation accepts application/json request bodies only. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/unsupported-media-type + title: Request media type not supported + status: 415 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + InvalidField: + description: >- + A structurally valid Lookup or Search body names an unknown selector or search, or + supplies domain values that violate declared format, enumeration or semantic + constraints. Structural input and pagination-control errors use 400. Field errors use + JSON Pointers and messages that exclude submitted values and internal details. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ValidationProblem' + example: + type: https://govstack.global/problems/digital-registries/invalid-field + title: Request validation failed + status: 422 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + errors: + - pointer: /values/registrationNumber + message: The registration number does not match the declared format. + TooManyRequests: + description: >- + The gateway enforces its published quota scope and supplies Retry-After. Advisory + RateLimit headers are gateway-owned. + headers: + Retry-After: + $ref: '#/components/headers/RetryAfter' + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/too-many-requests + title: Request rate exceeded + status: 429 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + InternalError: + description: >- + Request failure, including a source contract violation. Protected-existence policy + precedes Record-specific diagnostics. Problem text excludes personal data, source + counts and internal details; type is the sole machine identifier, with code and + timestamp omitted. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/internal-error + title: Request could not be completed + status: 500 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + BadGateway: + description: The registry adapter received an unusable upstream response; no upstream details are exposed. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/bad-gateway + title: Upstream request failed + status: 502 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + ServiceUnavailable: + description: The service temporarily cannot accept work; no dependency topology is exposed. + headers: + Retry-After: + $ref: '#/components/headers/RetryAfter' + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/service-unavailable + title: Service temporarily unavailable + status: 503 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f + GatewayTimeout: + description: The upstream read exceeded its time budget; no partial or fabricated record is returned. + headers: + Cache-Control: + $ref: '#/components/headers/CacheControl' + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + example: + type: https://govstack.global/problems/digital-registries/gateway-timeout + title: Upstream request timed out + status: 504 + traceId: 6f1c3f0e2a9b4c8d7e6f5a4b3c2d1e0f diff --git a/spec/.gitbook/assets/api-families.svg b/spec/.gitbook/assets/api-families.svg index be41449..6c6405f 100644 --- a/spec/.gitbook/assets/api-families.svg +++ b/spec/.gitbook/assets/api-families.svg @@ -23,7 +23,7 @@ - Eight capability families with illustrative protocol options + Eight optional capability families with illustrative protocol options @@ -250,7 +250,7 @@ - The target Base Registry Profile combines Registry Core with Consultation Retrieve. + Conformance combines Registry Core with at least one selected capability. diff --git a/spec/01-version-history.md b/spec/01-version-history.md index cf1b8ce..07b3bde 100644 --- a/spec/01-version-history.md +++ b/spec/01-version-history.md @@ -12,6 +12,16 @@ description: Major changes to the Digital Registries Building Block specificatio | 3.0.0-alpha.1, June 2026 | Coordinators, authors, and editors listed below | Expanded scope and alignment work for GovStack Architecture 2.x. Public alpha release. | | 3.0.0-alpha.2, August 2026 | Digital Registries Working Group | Reframed the alpha as a domain-neutral Registry Core with mandatory Consultation Retrieve and additional capability families. Breaking prerelease change. | +## Current alpha draft revision + +The 6 September 2026 revision of the `3.0.0-alpha.2` draft replaces universal Consultation Retrieve with a target conformance model of mandatory Registry Core plus at least one declared Registry capability. It strengthens Core metadata publication and service discovery, while leaving all API families optional. This is a revision of the same alpha draft, not a new release; no conformance claim is available. + +The revision adds DRAFT requirements and a [canonical HTTP contract](../api/openapi.yaml) for four independently optional Consultation capabilities: Retrieve, Lookup, List, and Search. GET serves Retrieve and List; POST carries exact Lookup and Search criteria. All four share a Record representation. List and Search use live cursor pagination with repeated criteria and a fixed effective page size. + +The Record model accepts stable source identifiers within a Registry and permits Registry and schema context through the endpoint, versioned contract, or response. Source revision, lifecycle, and recording time are optional unless a selected capability or profile requires them. Field meanings remain documented. + +The [household](../api/examples/household-registry.openapi.yaml) and [birth-registration](../api/examples/birth-registration.openapi.yaml) contracts illustrate nested components, Record references, recorded related details, and bounded arrays with declared completeness. API Design Guide `0.2.0-draft` accompanies these choices. Contract and example validation is published separately from implementation conformance testing. + ## Contributors by release ### Versions 0.7 and 0.8 diff --git a/spec/02-description-and-scope.md b/spec/02-description-and-scope.md index bec97b0..29ed1c2 100644 --- a/spec/02-description-and-scope.md +++ b/spec/02-description-and-scope.md @@ -6,32 +6,34 @@ description: Purpose, scope, architecture, and exclusions of the Digital Registr ## 2.1 Purpose -The GovStack Common Terminology defines the general concept of a Registry. A Digital Registries implementation exposes records for which a named authority accepts responsibility within a defined scope. Examples include business registrations, land titles, vehicle registrations, professional licences, programme enrolments, and civil events. +The GovStack Common Terminology defines the general concept of a Registry. A Digital Registries implementation exposes services over records for which a named authority accepts responsibility within a defined scope. Examples include business registrations, land titles, vehicle registrations, professional licences, programme enrolments, and civil events. A service can provide a permitted Record representation, signed evidence, approved statistics, or another declared Registry capability. -The Digital Registries Building Block defines the external behaviour that allows applications and other Building Blocks to use those records consistently. It separates that interoperability contract from the implementation's database technology, internal modules, administrative tools, and deployment model. +The Digital Registries Building Block defines the external behaviour that allows applications and other Building Blocks to use those records consistently. Its interoperability contract is independent of database technology, internal modules, administrative tools, and deployment model. -In this context, authoritative does not mean that a Record is necessarily complete or error-free. It means that a named Registry Authority is institutionally responsible for maintaining it within the declared scope. +Authoritative means that a named Registry Authority is institutionally responsible for maintaining a Record within the declared scope. Completeness and accuracy are separate data-quality properties. ## 2.2 Scope This specification covers: -- identification and description of a registry; -- stable identification and lifecycle representation of registry records; -- retrieval of the current permitted representation of a record; -- declaration of representation formats, schemas, semantic models, supported capabilities, and protocol bindings; -- registry-specific revision and provenance information; and -- optional capabilities for provisioning, additional consultation patterns, evidence, writing, notifications, aggregate data, access transparency, and identity federation. +- identification and description of a registry, its authority and scope, and its available services; +- stable identification of Registry Records within a declared scope; +- independently optional Retrieve, exact Lookup, List, and Search of permitted Record representations; +- declaration of representation formats, schemas, documented field meanings, supported capabilities, and protocol bindings; +- interpretation of source revision, lifecycle, and provenance information when supplied; and +- optional capabilities for provisioning, consultation, evidence, writing, notifications, aggregate data, access transparency, and identity federation. -The same specification can be applied to registries containing records about persons, organisations, places, assets, or events. Domain-specific meaning remains in a declared semantic model rather than being fixed by this Building Block. +The specification applies to registries containing records about persons, organisations, places, assets, or events. Their contracts document the domain-specific field meanings and can reference a formal semantic model. A selected profile or capability can require additional source metadata or a specific semantic model. + +The [conformance model](04-conformance.md) combines Registry Core with at least one selected capability. Every implementation publishes discovery metadata for its exposed Registry services. Each capability defines its result, which can be a Record representation or another form of Registry information. ## 2.3 Architectural approach The specification separates four concerns: 1. **Operations** describe what an API consumer can ask the registry to do. -2. **Common metadata** identifies the registry, record, revision, lifecycle state, representation format, schema, and provenance relevant to an operation. -3. **Semantic models** define the meaning of domain data. +2. **Common context** identifies the Registry, scoped Record reference, representation format, and schema through the endpoint, versioned contract, or response as the binding specifies. Supplied source revision, lifecycle, and provenance metadata have documented meanings. +3. **Domain semantics** document field meanings and can use a published semantic model. 4. **Bindings** map operations to HTTP, event-driven messaging, or an established industry protocol. This separation lets an existing national registry, a commercial product, an open-source platform, or an adaptor conform to the same external contract without sharing an internal architecture. @@ -54,7 +56,7 @@ A Registry can integrate with neighbouring Building Blocks without transferring | Consent | Consent can provide evidence or policy signals used in a disclosure decision. The Registry enforces the decision applicable to each request and supports other lawful bases where relevant. | | E-Signature | E-Signature can perform signing operations. The Registry remains responsible for the meaning, issuance, status, and lifecycle of Registry Evidence. | | Wallet | A Wallet can hold and present credentials issued through Evidence. The Registry remains the source of the asserted facts and is not required to operate a Wallet. | -| Identity | The [Identity Building Block](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) currently defines foundational identity services and discusses integration with functional identities. A sectoral Registry remains responsible for its functional identifiers. Ownership of an outward-facing functional Identity Federation profile remains an open cross-Building-Block decision, and Identity Federation does not replace API access control. | +| Identity | The [Identity Building Block](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) defines foundational identity services and describes integration with functional identities. A sectoral Registry owns its functional identifiers. [Identity Federation](05-api-families/identity-federation.md) addresses authentication to Relying Services; Registry API access control is a separate responsibility. | | GIS | GIS can provide geospatial processing and visualisation. A spatial Registry remains responsible for its records and can expose an OGC-aligned GIS Query capability. | These integrations are optional unless a selected capability profile states otherwise. diff --git a/spec/03-terminology.md b/spec/03-terminology.md index 5b30cc4..02d5f04 100644 --- a/spec/03-terminology.md +++ b/spec/03-terminology.md @@ -9,24 +9,29 @@ This specification uses the [GovStack Common Terminology](https://specs.govstack | Term | Definition | |---|---| | API Consumer | A system authorised to invoke a Registry service interface. | -| API Family | A coherent group of operations that provides one Registry capability. | +| API Family | A coherent group of related Registry capabilities and operations. | | Authoritative Source | A source for which a named authority accepts responsibility within a declared domain and scope. Authoritative does not imply error-free. | | Binding | A mapping of abstract operations to a transport or established protocol. | +| Capability Declaration | Discovery metadata identifying a supported API family and its service contract. | | Capability Claim | A declaration that an implementation supports a specified API family, sub-pattern, and binding and meets the requirements attached to that claim. | | Conformance Profile | A defined combination of core requirements and capability claims. | | Functional Identifier | An identifier issued and lifecycle-managed for a sector-specific purpose, such as a farmer, student, health, or professional identifier. | -| Lifecycle State | The current state of a Record under the vocabulary defined by its declared representation schema. | +| Lifecycle State | When supplied, the state of a Record under a documented vocabulary. A current Record is not necessarily active. | +| Lookup | Resolution of a Record using a declared exact selector, such as a registration number or a defined combination of fields. It does not imply general search or approximate matching. | | Permitted Representation | The record data and metadata an API consumer is authorised to receive. It may be filtered or redacted and need not contain the complete stored record. | | Record | The Registry's representation of an entity, place, asset, or event within its declared scope. | -| Record Identifier | A stable identifier assigned to a record within a Registry. | +| Record Identifier | A stable identifier unique within its Registry. It may reuse a suitable source identifier; the Registry context and identifier together identify the Record. | | Record Principal | A person or organisation with a recognised relationship to a record, such as its subject, owner, title holder, director, or credential holder. | +| Record Reference | A value identifying another Record and its target Registry through explicit or schema-defined context. It does not guarantee that the Record can be retrieved or disclosed. | | Record Revision | A representation of a record at a defined point in its change history. | | Representation Format | The serialisation or media type used to encode a returned representation, identified through the applicable binding. | | Registry Authority | The institution accountable for the Registry and its declared authoritative scope. | -| Registry Core | Behaviour and metadata required of every conformant Registry implementation. | +| Registry Core | The common behaviour and metadata required of Registry implementations, with Record-related requirements applied according to their applicability. | | Registry Identifier | A globally unique and stable identifier for a Registry. | | Registry Operator | The organisation that operates an implementation on behalf of, or as, the Registry Authority. | | Relying Service | A service that relies on authentication or claims provided through the Identity Federation family. | | Schema | A machine-readable definition of the structure and validation constraints of records or messages. | -| Semantic Model | The vocabulary and domain meaning of data carried in a Registry record. | +| Search | Retrieval of a bounded collection using criteria declared by the service contract or applicable domain profile. It does not imply a generic query engine. | +| Semantic Model | A published vocabulary or domain model for interpreting Registry data. A formal semantic-model reference is optional unless the selected profile requires it; field meanings remain documented. | +| Source Recorded At | When supplied, the time at which the source recorded the represented information or revision, with the precise meaning declared by the contract. It is not the time at which an adapter retrieved the information. | | Sub-pattern | An independently claimable capability within an API family. | diff --git a/spec/04-conformance.md b/spec/04-conformance.md index 568e459..bcbde29 100644 --- a/spec/04-conformance.md +++ b/spec/04-conformance.md @@ -10,32 +10,38 @@ All requirements in the 3.0.0-alpha.2 specification are classified as DRAFT. The Each requirement follows the [GovStack Requirements Model](https://specs.govstack.global/architecture/development/5-specification-framework/5.3-requirements-model). Requirement levels and other classifiers are interpreted according to that model. Lowercase modal verbs have their ordinary English meaning; this specification does not use BCP 14 keywords to assign requirement levels. Requirement identifiers are permanently reserved even while the requirement is DRAFT. Cross-family requirements are defined under [Registry Core](05-api-families/registry-core.md#registry-core-functional-requirements), while family-specific requirements are defined on the applicable API-family page. +The conformance model and capability-specific requirement namespaces remain provisional pending support for conditional capability applicability in the GovStack Common Requirements Framework. [GovStack CFR issue #7](https://github.com/GovStackWorkingGroup/cfr-architecture/issues/7) tracks that dependency. + +No implementation or capability can claim conformance with this alpha. Its requirements and Consultation HTTP binding are DRAFT, and no executable implementation conformance suite is published. The canonical Consultation contract and example-validation checks support prototyping and review. Procurement and certification should reference an approved specification version. See [Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) for the maturity of individual capabilities and publication gaps. + ## 4.2 Inherited cross-functional requirements This specification extends `govstack-cfr-2.1.0`. Every parent requirement applies with its original classifier and applicability conditions unless a Digital Registries requirement explicitly identifies a permitted extension or replacement under the GovStack Requirements Model. This release defines no Registry-specific cross-functional extension or replacement. It does not impose a jurisdiction-specific security framework, a universal legal basis for data processing, or one deletion policy on every type of Registry. -## 4.3 Target Base Registry Profile +## 4.3 Conformance model -The provisional name for the target minimum conformance claim is the **Base Registry Profile**. Its formal treatment as a profile, and the conditional applicability of additional capabilities, depend on equivalent support in the GovStack Common Requirements Framework. It is not claimable in this alpha because its requirements are DRAFT and no canonical contract or executable test suite is published. +Minimum conformance consists of **Registry Core plus at least one declared Registry capability**. All API families and operations, including Consultation Retrieve, are optional. -Once approved, an implementation claiming this profile: +An implementation claiming conformance: -1. satisfies the [Registry Core requirements](05-api-families/registry-core.md#registry-core-functional-requirements); -2. implements the [Consultation Retrieve](05-api-families/consultation.md#retrieve-functional-requirements) sub-pattern; -3. identifies the Digital Registries specification version it implements; -4. returns records in an identified representation format under an identified schema and published semantic model; and +1. satisfies the applicable [Registry Core requirements](05-api-families/registry-core.md#registry-core-functional-requirements), including publication of machine-readable Registry and service metadata; +2. implements at least one declared Registry capability with approved requirements, contracts, and tests; +3. identifies the Digital Registries specification version and capabilities covered by its claim; +4. publishes the API-family classifications, endpoints, and linked machine-readable operational contracts for the services it exposes through the Registry BB interface; and 5. satisfies the applicable `govstack-cfr-2.1.0` requirements. -Retrieve does not imply public access or disclosure of the complete stored record. It means that an authorised API consumer can request a record by its stable identifier and receive the current permitted representation or a policy-appropriate unsuccessful outcome. +Core requirements concerning returned Records apply when a selected capability returns Records. The Consultation Retrieve, Lookup, List, and Search requirements and shared HTTP binding apply only to the selected capabilities. Retrieve resolves a stable Record Identifier; Lookup resolves a declared exact selector; List and Search return bounded Pages. An authorised API consumer receives the current permitted representation or a policy-appropriate unsuccessful outcome. The permitted representation is governed by access policy. + +Registry metadata can describe a Registry for directory participation without establishing functional Registry BB conformance. A specification reference or family classification in metadata is not, by itself, a conformance claim. -## 4.4 Additional capability claims +## 4.4 Capability claims -After the Common Requirements Framework supports conditional capability applicability, an approved Digital Registries release may allow an implementation to claim additional families and Consultation sub-patterns. Once claimed, every applicable REQUIRED requirement, operation, contract, and test for that capability becomes part of its conformance claim. +A capability claim identifies the selected families and capability patterns. Every applicable REQUIRED requirement, operation, contract, and test for a claimed capability forms part of the claim. Consumers determine whether an implementation meets their needs from its declared capabilities and linked operational contracts. -Capabilities described only for architectural context, without approved requirements, contracts, and tests, are not claimable in this release. +Publication of a family label and an operational contract describes the service. A conformance claim additionally requires approved capability requirements, contracts, and tests, subject to [Requirement Maturity](#41-requirement-maturity). ## 4.5 Adaptors -An existing registry does not need to replace its internal software to conform. An adaptor may translate an existing interface into the operations, metadata, outcomes, and bindings required by a claimed profile. Conformance applies to the resulting external behaviour. +An existing registry does not need to replace its internal software to conform. An adaptor may translate an existing interface into the operations, metadata, outcomes, and bindings required by its conformance claim. Conformance applies to the resulting external behaviour. The adapter documents source currency, identifier mapping where needed, supported selectors and searches, and representation mappings. It does not fabricate source revisions, recording times, or lifecycle facts to fill an envelope. A service offering current reads does not need to implement Revision History or a general query engine. diff --git a/spec/05-api-families/access-transparency.md b/spec/05-api-families/access-transparency.md index 29229d4..07c9724 100644 --- a/spec/05-api-families/access-transparency.md +++ b/spec/05-api-families/access-transparency.md @@ -4,7 +4,7 @@ description: Permitted outward views of access to Registry Records. # Access Transparency -> **Status:** Informative and not claimable in this release. No Access Transparency requirements, entitlement model, event schema, contract, or tests are published. +> **Status:** Informative. See [Conformance](../04-conformance.md#44-capability-claims). ## Purpose and applicability @@ -24,11 +24,11 @@ A Record Principal can be a subject, owner, title holder, director, beneficiary, Internal security and audit logging is a cross-functional concern. Access Transparency is the outward-facing service derived from permitted audit information. Its representation can omit actor identities or operational details where disclosure would create a privacy, security, or investigation risk. -An adopting authority that includes Access Transparency in its deployment needs to define entitlement, relationship verification, delegation, outward event vocabulary, retention, correction handling, and disclosure restrictions. +Deployment rules cover entitlement, relationship verification, delegation, outward event vocabulary, retention, correction handling, and disclosure restrictions. -## Binding status +## Implementation options -This release does not specify an Access Transparency binding, outward event schema, or API contract. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI, but that choice does not create a GovStack capability claim. +Synchronous HTTP described by OpenAPI is an illustrative, non-normative implementation option. ## Example diff --git a/spec/05-api-families/aggregate-data.md b/spec/05-api-families/aggregate-data.md index a813078..d33a58f 100644 --- a/spec/05-api-families/aggregate-data.md +++ b/spec/05-api-families/aggregate-data.md @@ -4,7 +4,7 @@ description: Approved statistics derived from Registry Records. # Aggregate Data -> **Status:** Informative and not claimable in this release. No Aggregate Data requirements, statistical model, contract, or tests are published. +> **Status:** Informative. See [Conformance](../04-conformance.md#44-capability-claims). ## Purpose and applicability @@ -20,11 +20,11 @@ Aggregate Data provides approved statistics derived from Registry Records, such ## Capability boundary -Aggregate Data is not Record-level [Consultation](consultation.md), a mandatory analytics engine, or a dashboard. It is not automatically public. Aggregation is not itself anonymisation. An adopting authority that includes Aggregate Data in its deployment needs to define disclosure thresholds, suppression, legal controls, revisions, and indicators of applied protection. +Aggregate Data returns statistical outputs rather than the individual Records provided by [Consultation](consultation.md). Analytics engines and dashboards are deployment choices. Access depends on the release policy, and aggregation alone does not ensure anonymity. Deployment rules cover disclosure thresholds, suppression, legal controls, revisions, and indicators of applied protection. -## Binding status +## Implementation options -This release does not specify an Aggregate Data binding. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI or SDMX where outputs need to participate in national or international statistical ecosystems. These choices do not create a GovStack capability claim. +Illustrative, non-normative options include synchronous HTTP described by OpenAPI, or SDMX for outputs that participate in national or international statistical ecosystems. ## Example diff --git a/spec/05-api-families/consultation.md b/spec/05-api-families/consultation.md index 7cf0792..b7a5faa 100644 --- a/spec/05-api-families/consultation.md +++ b/spec/05-api-families/consultation.md @@ -1,48 +1,74 @@ --- -description: Read capabilities for permitted Registry information. +description: Interoperable read access to Registry Records. --- # Consultation -> **Status:** Retrieve is DRAFT and part of the target Base Registry Profile. Existence Check, List, Search, Revision History, Record Match, and GIS Query are informative and not claimable in this release. +> **Status:** DRAFT requirements and HTTP binding, for review and implementation trials. -## Purpose and applicability +## Purpose and capability model -Consultation enables an API Consumer operating under an applicable access and disclosure policy to obtain a permitted representation of Registry information. It applies when a consumer needs current information from the authoritative source rather than a portable signed assertion or a derived statistic. +Consultation defines read access to Registry Records for independently implemented services and API Consumers. A service selects one or more capabilities and publishes its operational contract through [Registry Core metadata](registry-core.md#api-family-discovery). Consumers use that contract to determine available operations and their inputs. -Retrieve is the minimum read capability. It lets a consumer that already knows a Record Identifier obtain the current permitted representation without requiring the Registry to expose enumeration or discovery by personal or domain attributes. +| Capability | Input | Successful result | +|---|---|---| +| `consultation.retrieve` | Record Identifier | One Record | +| `consultation.lookup` | Declared exact selector and its complete key | One Record | +| `consultation.list` | Declared collection and supported public filters | Page of Records | +| `consultation.search` | Declared search and typed criteria | Page of Records | -Consultation inherits the shared [Registry Core model and requirements](registry-core.md). In this family, the current revision means the latest accepted revision of the Record. It is not necessarily an active Record; the declared lifecycle state and applicable disclosure policy determine whether and how it is returned. +Shared requirements apply to every selected capability; operation requirements apply when that capability is selected. Each operation applies to a declared collection with an unambiguous Registry context, representation schema, and access policy. -Consultation provides a common capability framework for domain-specific registries. The applicable registry or sector profile defines the Record schema, semantic model, lifecycle vocabulary, permitted representations, and any domain-specific query or matching semantics. This specification does not require a generic query layer over arbitrary stored fields. +## Common read contract -## Capability patterns +A read preserves the source Records. Current information is the information accepted by the authoritative source and available under the service's declared currency contract, including replication or cache delay. Domain schemas define the meaning of status and validity fields. -| Pattern | Outcome | -|---|---| -| `consultation.retrieve` | Returns the current permitted representation of one Record identified by its stable Record Identifier. | -| Existence Check | Indicates whether a Record exists only when the consumer is permitted to learn that fact. | -| List | Returns a bounded, paginated collection under an applicable domain profile, optionally filtered by declared attributes. | -| Search | Finds Records using predicates declared by the applicable registry or sector profile. | -| Revision History | Returns permitted revision metadata or a permitted historical representation of one Record. | -| Record Match | Returns possible matching Records with confidence information under a domain-specific matching profile. It does not make an authoritative identity or acceptance decision. | -| GIS Query | Applies domain-defined spatial predicates to geometric attributes maintained by the Registry. | + + +**Record representation.** A Record contains `recordId` and `data`. The identifier is stable, unique within its Registry, and never reassigned. Registry context and the selected representation schema are unambiguous from the published contract, request context, or response. Retrieve and Lookup return one Record; List and Search use the same Record shape for each item in a Page. + +The `data` schema defines domain fields, structured values, references, and their meanings. A declared view selects the information represented by that schema. Revision, lifecycle, and provenance metadata are optional in the baseline; profiles can require source-backed metadata with defined semantics. + +**Example: Record representation.** Examples on this page use the [illustrative business Registry binding](../../api/examples/business-registry.openapi.yaml), which defines the domain fields, status values, and query names. Its published contract selects the Registry and the `business-public` view. A Record response contains: -## Capability boundary +```json +{ + "recordId": "r_42", + "data": { + "legalName": "Example Ltd", + "registrationStatus": "DISSOLVED" + } +} +``` -Consultation returns live Registry information. [Evidence](evidence.md) produces a signed assertion with its own validity and status. [Aggregate Data](aggregate-data.md) returns derived statistics rather than Record representations. +**Consumer behavior.** Consumers retain Registry context when storing or forwarding Record references, treat Record Identifiers as opaque, and interpret `data` using the declared schema. They accept additional response-envelope members and use only the inputs supported by the published contract. -Consultation is read-only. It does not create a Record, accept a new revision, change lifecycle state, or perform an approval decision. The Retrieve requirements define permitted representations and protected-existence handling. An adopter selecting Existence Check, List, Search, Revision History, Match, or GIS Query needs an applicable profile that defines disclosure, bounded results, query limits, and result interpretation for that capability. +## Domain models and service declarations + +Implementations should reuse suitable schemas and vocabularies, including [Schema.org](https://schema.org/), [EU SEMIC Core Vocabularies](https://interoperable-europe.ec.europa.eu/collection/semic-support-centre/solution/core-vocabularies), [PublicSchema](https://publicschema.org/), and models defined or adopted by national or sector authorities. + +A domain profile records reusable agreements about schemas, terminology, and query semantics. A service contract applies those agreements to the operations it exposes. An implementation can adopt an existing profile or publish a concrete domain binding directly. Both preserve the shared Consultation behavior. + +The published service contract supplies the following information for its selected capabilities and applicable representation features, directly or through versioned references: + +| Topic | Declared information | +|---|---| +| Registry and capabilities | Registry association and implemented operations for each collection, linked from Core metadata. | +| Representation | JSON Schemas for the Record view and responses; adopted models and versions; mappings, local constraints, and extensions. | +| Field meanings | Meaning, units, code lists, and omitted, null, or empty values, preserving the semantics of adopted models. | +| Lookup and Search | Names, typed inputs, required components, comparison and normalization rules, uniqueness scope, and matching semantics. | +| Collections | Names, membership, operation paths, supported filters and sorting, deterministic order, page-size limits, and cursor expiry. | +| Access and currency | Authentication requirements, permitted views, and source currency, including material replication or cache delay. | -## Retrieve representation +An API can expose several collections, such as individuals, households, and land parcels. Each collection selects Records within a declared Registry; different collections can belong to the same Registry or to different Registries. The contract associates each operation with its collection and response schema. Record identity remains the pair of Registry Identifier and Record Identifier across collections and views. -A successful Retrieve returns the [common Record context](registry-core.md#common-record-context) together with the domain data that the API Consumer is permitted to receive. The representation can omit or redact domain data and additional protected provenance, but the resulting projection remains unambiguous and valid against its declared representation schema. +Domain references identify their target Record and Registry. When a target read is offered, the field binding identifies its collection, operational contract, operation, and mapping from the reference to the required inputs. Consumers use that binding to resolve the reference. Embedded data declares its ownership and currency; embedded collections declare bounds, completeness, and overflow outcomes. The [Core representation conventions](registry-core.md#structured-values-and-references) provide the shared model, and OpenAPI supplies reusable reference schemas. -The Base Registry Profile retrieves the current revision. Revision History is a separate informative Consultation capability and is not claimable in this release. +Published schema versions remain resolvable while their contracts are supported. The service identifies changes to schemas, queries, and views through its contract version, following the API design guide's compatibility rules. -## Retrieve functional requirements +## Read requirements -The following DRAFT requirements define the Consultation capability in the target Base Registry Profile. They do not establish a certification claim in this release. + ### #1 Retrieve the current Record by identifier (DRAFT EXTENSIBLE OBSERVABLE) @@ -50,13 +76,9 @@ The following DRAFT requirements define the Consultation capability in the targe `KF: Consultation` -Given an unambiguous Registry context, a valid Record Identifier, and a request permitted by applicable policy, an implementation returns the current permitted representation of that Record without modifying the Record. +Given a valid Record Identifier for a Record in the selected collection and a permitted request, Retrieve returns the current representation of that Record. An unknown identifier or a Record outside that collection receives the binding's unavailable-Record outcome, subject to protected-existence handling. -**Purpose:** An API Consumer that already knows a Record Identifier can obtain authoritative Registry information without using search or enumeration. - -**Prerequisite:** A permitted consumer context and an accessible Record fixture exist. - -**Verification:** Retrieve a known Record by identifier, verify the Registry and Record identifiers, current revision, lifecycle state, representation format, schema, semantic model, minimum provenance, and permitted domain data, and confirm that a subsequent Retrieve returns the same revision when no intervening change occurred. +**Verification:** Retrieve a known source fixture and check its identity, schema, currency, and declared metadata. Confirm that the source Record is unchanged; exercise an unknown identifier and, where applicable, an identifier belonging to another collection. ### #2 Apply disclosure rules to the returned representation (DRAFT EXTENSIBLE OBSERVABLE) @@ -64,13 +86,9 @@ Given an unambiguous Registry context, a valid Record Identifier, and a request `KF: Consultation` -An implementation returns only the Record fields and metadata permitted for the API Consumer and request context. The resulting projection remains valid against its declared representation schema. - -**Purpose:** Retrieve does not become an entitlement to the complete stored Record. The same Registry can expose different valid representations under different disclosure policies, including a public representation where applicable. +For every selected read, the service returns a schema-valid representation containing only the Records, fields, metadata, and result information permitted for the consumer and request context. Disclosure applies to references, embedded data, counts, errors, and continuation information. -**Prerequisite:** At least two test consumer contexts have different disclosure entitlements for the same Record. - -**Verification:** Retrieve the same Record using both consumer contexts and verify that each receives only its permitted projection, each projection validates against its declared schema, and omitted values are not exposed through errors or metadata returned to the consumer. +**Verification:** Exercise each selected read with fixtures for the service's applicable access policies. Check representation validity and permitted information, including different entitlements where offered. ### #3 Hide protected Record existence (DRAFT EXTENSIBLE OBSERVABLE) @@ -78,35 +96,146 @@ An implementation returns only the Record fields and metadata permitted for the `KF: Consultation` -For an API Consumer that is not authorised to learn whether a protected Record exists, an implementation returns an outcome that is indistinguishable under the published Retrieve contract from the outcome for an unknown Record Identifier. This includes the same status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values. Per-request trace or correlation values may differ when they are generated independently of Record existence. The response contains no Record-specific data. +When policy protects Record existence, Retrieve and Lookup return the same unresolved outcome for unknown and protected Records. Equivalence covers protocol status, security-relevant metadata, error type, response structure, and non-Record-specific values. Trace and correlation values are generated independently of Record existence; the outcome contains no Record-specific data. + +**Verification:** Compare protected and unknown fixtures under the same consumer context for each selected operation. Check equivalent outcomes and independent trace values. -**Purpose:** An unauthorised consumer cannot enumerate protected Record Identifiers through the Retrieve contract. +### #4 Resolve a Record by a declared exact selector (DRAFT EXTENSIBLE OBSERVABLE) -**Prerequisite:** An unknown Record Identifier and a protected Record Identifier are available as test fixtures for the same consumer context. +`govstack-bb-digital-registries-fr-consultation#req-4` -**Verification:** Retrieve both identifiers using that consumer context and compare the status or protocol outcome, security-relevant response metadata, error type, response structure, non-Record-specific values, and data fields. Verify that any differing trace or correlation values are independent of Record existence and that neither response exposes Record-specific data. +`KF: Consultation` -## Selecting additional Consultation capabilities +Lookup accepts a published selector and all required key components. The key can be composite. Its declared comparison and normalization rules resolve at most one Record within the uniqueness scope. A permitted unique match in the selected collection returns that Record; zero matches in the collection produce the unresolved outcome. A source uniqueness violation produces a failure governed by disclosure policy. -An adopter may need Consultation capabilities beyond Retrieve. These capabilities are not part of the Base Registry Profile and are not claimable in this release. An adopter should select them only when they serve a defined consumer need and an applicable registry or sector profile supplies the required domain semantics. +Invalid, incomplete, or unsupported inputs are rejected. A selector can derive key components from verified consumer context when its contract defines that mode; a fully context-derived selector accepts an empty caller-supplied `values` object. -| Capability | Select when | The applicable profile needs to define | -|---|---|---| -| Existence Check | A consumer needs to determine whether a Record exists without receiving its representation. | When existence may be disclosed and how protected and unknown Records are treated consistently. | -| List | A consumer is permitted to browse a defined collection of Records. | Collection membership, filters, ordering, bounded pagination, collection metadata, and disclosure rules. | -| Search | A consumer needs to find Records without already knowing their Record Identifiers. | Searchable domain concepts, predicates, result limits, and zero-match, multiple-match, and truncated-result outcomes. | -| Revision History | A consumer needs permitted information about earlier revisions of a known Record. | Whether revision enumeration or historical representations are available, stable revision identifiers, ordering, retention, lifecycle interpretation, and disclosure or erasure rules for historical data. | -| Record Match | A consumer supplies incomplete or variable domain information that may correspond to more than one Record. | Permitted inputs, matching rules, confidence interpretation, disclosure of possible matches, and ambiguous or no-match outcomes. A match is not an authoritative identity, eligibility, or acceptance decision. | -| GIS Query | A spatial Registry exposes Records through geographic relationships. | Supported spatial predicates, coordinate and geometry semantics, spatial and result bounds, and disclosure of protected Records or locations. | +**Verification:** Exercise known, unknown, incomplete, incorrectly typed, and unsupported inputs, plus a source uniqueness violation. Verify comparison rules, composite keys where supported, and protected-existence handling. + +### #5 List a bounded Record collection (DRAFT EXTENSIBLE OBSERVABLE) -For every selected capability, disclosure applies to both Record content and result metadata. The applicable profile needs to ensure that counts, ordering, page boundaries, confidence values, suggestions, and geometries do not reveal information that the consumer is not permitted to learn. +`govstack-bb-digital-registries-fr-consultation#req-5` + +`KF: Consultation` -## Binding status +List returns a bounded Page of permitted Records from its declared collection, applying supported filters and ordering. Zero and single-result collections retain the Page shape. Unsupported filters or sorting produce a validation error. -This release defines the abstract Retrieve operation but does not specify an HTTP binding or publish a canonical OpenAPI contract. An adopter prototyping Retrieve can use synchronous HTTP described by OpenAPI. A spatial Registry evaluating GIS Query can consider OGC API Features. These implementation choices do not create a GovStack capability claim. +**Verification:** Use fixtures with zero, one, and multiple results, including tied sort values where applicable. Check membership, schemas, order, size bounds, and rejection of unsupported inputs. -See [Service Interfaces](../09-service-interfaces.md), [Workflows](../10-workflows.md), and [Testing](../11-testing.md). +### #6 Search using declared criteria (DRAFT EXTENSIBLE OBSERVABLE) -## Example +`govstack-bb-digital-registries-fr-consultation#req-6` + +`KF: Consultation` + +Search accepts a published search name and its typed criteria. It applies the declared matching rules to the selected collection and returns a bounded Page of permitted matching Records, retaining the Page shape for zero or one result. Unsupported searches, unknown criteria, and invalid inputs produce a validation error. + +**Verification:** Execute declared searches with valid and invalid inputs. Check matching results, empty Pages, applicable disclosure contexts, and use of the binding's protected request locations for personal criteria. + + + +### #7 Continue bounded result pages (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-consultation#req-7` + +`KF: Consultation` + +List and Search use a declared deterministic order with a unique tie-breaker. Each request performs bounded source work, returns a bounded Page, and applies current authorization. Continuation preserves the collection, query, and view and advances traversal to explicit completion. Invalid continuation produces an error. + +A completed traversal over unchanged data and access conditions contains each permitted matching Record once. + +Pagination observes live data: source changes can move, add, or remove Records and cause repeated results. A profile can define stronger snapshot guarantees. Disclosure policy governs counts, page sizes, and continuation patterns, including short or empty advancing Pages. + +Consumers treat cursors as opaque and return them unchanged with the original query inputs. They follow the completion signal, including when an intermediate Page is empty. The [HTTP binding](#http-binding) defines the continuation fields and fixed page-size policy. + +**Verification:** Traverse unchanged multi-page fixtures to completion, checking complete membership without duplicates, identity, order, size bounds, progress, and termination. Exercise malformed, expired, and mismatched cursors, source changes, and applicable access changes. Check permitted page patterns and any total against the full permitted query. + +## HTTP binding + +The [canonical OpenAPI](../../api/openapi.yaml) defines the HTTPS/JSON contract, version `1.0.0-draft`, using API design guide and ruleset `0.2.0-draft`. It uses `records` as the reference collection name. Deployments publish concrete collection names, selected operations, Registry associations, and schemas in OpenAPI. + +| Capability | Request | Successful body | +|---|---|---| +| Retrieve | `GET /v1/records/{recordId}` | `{recordId, data}` | +| Lookup | `POST /v1/records:lookup` with `{selector, values}` | `{recordId, data}` | +| List | `GET /v1/records` with pagination and supported public query parameters | `{items, pageInfo}` | +| Search | `POST /v1/records:search` with `{search, criteria}` and pagination controls | `{items, pageInfo}` | + +The major API version precedes collection paths. An OpenAPI server URL identifies the deployment root, optionally including a stable routing prefix, such as `https://example.org/registry`. API-family classifications are declared in Core metadata and operation tags. A shared API can therefore expose: + +```http +GET /v1/individuals/{recordId} +GET /v1/households/{recordId} +GET /v1/land-parcels/{recordId} +POST /v1/households:lookup +POST /v1/households:search +``` + +These are illustrative collection names; the published contract defines the supported paths. The `:lookup` and `:search` suffixes distinguish collection methods from item identifiers, including valid IDs such as `lookup` and `search`. + +Lookup and Search are synchronous reads returning `200`; selector and search values remain in the request body. The binding also defines the operational `/health` endpoint. [API composition](registry-core.md#api-composition) describes how collections and families share an API. + +**Example: exact Lookup.** The business binding names its collection `businesses`. To resolve a business by its declared registration-number key, send this body to `POST /v1/businesses:lookup`: + +```json +{ + "selector": "byRegistrationNumber", + "values": { + "registrationNumber": "BR-000042" + } +} +``` + +For the permitted match, the `200` response is the Record shown above. + +**Example: Search and collection result.** To find businesses with a declared registration status, send this body to `POST /v1/businesses:search`: + +```json +{ + "search": "byRegistrationStatus", + "criteria": { + "registrationStatus": "DISSOLVED" + }, + "pageSize": 20 +} +``` + +With one permitted match and traversal complete, the `200` response is: + +```json +{ + "items": [ + { + "recordId": "r_42", + "data": { + "legalName": "Example Ltd", + "registrationStatus": "DISSOLVED" + } + } + ], + "pageInfo": { + "nextCursor": null + } +} +``` + +List uses the same Page shape for its declared collection. + +**Continuation.** The first request selects `pageSize`, defaulting to 20 and bounded to 100 in the canonical contract. A continuation repeats the original criteria, search name where applicable, sorting, and view with the cursor. It can omit `pageSize` to retain the bound value or supply that same value. Cursors bind the operation, Registry, collection, query, view, effective size, and applicable access context. The service rejects continuations whose declared semantics it can no longer preserve. + +A non-null `pageInfo.nextCursor` enables continuation; `null` marks completion. Optional `pageInfo.total` is the exact count of the full permitted query at the documented page evaluation time, before applying the continuation boundary. Services omit an unavailable total. + +**Outcomes.** OpenAPI defines the status codes and Problem Details for each operation. Retrieve and Lookup share `404 record-not-available` for unknown Records, Records outside the selected collection, and Records whose existence is protected. Structural input errors, invalid query parameters, and invalid pagination controls use `400`. Structurally valid Lookup and Search bodies with unknown selector or search names or invalid domain values use `422`. Malformed, expired, or mismatched cursors use `400 invalid-cursor`. Authentication, authorization, source failures, caching, and optional conditional Retrieve follow the declared OpenAPI responses and the API design guide. + +## Conformance + +Evaluation identifies the service, specification and contract versions, selected capabilities, and any adopted domain profile. The service satisfies the common read contract, declaration rules, HTTP binding, and the requirements applicable to each selected capability. + +| Selected capability | Applicable Consultation requirements | +|---|---| +| Retrieve | #1, #2; also #3 when existence is protected | +| Lookup | #2, #4; also #3 when existence is protected | +| List | #2, #5, #7 | +| Search | #2, #6, #7 | -A licensing service retrieves the current permitted representation of a business registration by its Record Identifier. The Registry returns only the fields and metadata that service is authorised to receive. +Consumers follow the shared representation rules and the input, outcome, and continuation contracts for the capabilities they use. Verification checks published contracts and observable exchanges under the stated fixture conditions. The [OpenAPI examples](../../api/examples/README.md) and [artifact validation](../../api/README.md#validation) support review; deployed behavior is evaluated separately. diff --git a/spec/05-api-families/evidence.md b/spec/05-api-families/evidence.md index ffd1bc9..249bbe6 100644 --- a/spec/05-api-families/evidence.md +++ b/spec/05-api-families/evidence.md @@ -4,7 +4,7 @@ description: Signed assertions derived from authoritative Registry information. # Evidence -> **Status:** Informative and not claimable in this release. No Evidence requirements, credential profile, contract, or tests are published. +> **Status:** Informative. See [Conformance](../04-conformance.md#44-capability-claims). ## Purpose and applicability @@ -18,15 +18,15 @@ Evidence enables a Registry Authority to issue a signed assertion derived from a | Wallet-mediated credential | The issuer delivers a credential to a holder-controlled wallet for later presentation to a verifier. | | Status and trust metadata | A verifier obtains the information needed to evaluate issuer trust, proof validity, schema, and current Evidence status. | -Evidence can express a narrowly scoped fact, including a yes-or-no assertion, or a defined set of claims. An adopting authority that includes Evidence in its deployment needs to define claim minimisation, subject binding, validity, status, revocation or supersession, and verifier trust discovery. +Evidence can express a narrowly scoped fact, including a yes-or-no assertion, or a defined set of claims. Deployment rules cover claim minimisation, subject binding, validity, status, revocation or supersession, and verifier trust discovery. ## Capability boundary [Consultation](consultation.md) returns current Registry information. Evidence produces a signed assertion whose validity and status are interpreted under an Evidence profile. A Wallet can hold and present a credential but is not the authoritative source. An E-Signature service can perform cryptographic operations, while the Registry Authority remains responsible for the meaning of the assertion. -## Binding status +## Implementation options -This release does not specify an Evidence binding, credential format, or status mechanism. An adopter evaluating wallet-mediated Evidence can consider OpenID for Verifiable Credential Issuance and Presentation with the W3C Verifiable Credentials model. Direct delivery can be described through an OpenAPI operation returning a signed attestation. These choices do not create a GovStack capability claim. +Illustrative, non-normative options for wallet-mediated Evidence include OpenID for Verifiable Credential Issuance and Presentation with the W3C Verifiable Credentials model. Direct delivery can use an OpenAPI operation returning a signed attestation. ## Example diff --git a/spec/05-api-families/identity-federation.md b/spec/05-api-families/identity-federation.md index e973f06..26c8e3b 100644 --- a/spec/05-api-families/identity-federation.md +++ b/spec/05-api-families/identity-federation.md @@ -4,31 +4,29 @@ description: Sectoral subject authentication and authorised claim release. # Identity Federation -> **Status:** Informative and not claimable in this release. Cross-Building-Block ownership is unresolved. No Identity Federation requirements, claim profile, protocol profile, or tests are published. +> **Status:** Informative. Cross-Building-Block profile ownership is unresolved. See [Conformance](../04-conformance.md#44-capability-claims) and [Coverage and limitations](../12-other-resources.md#121-coverage-and-limitations). ## Purpose and applicability Identity Federation enables a sectoral Registry containing Records about people, or a service acting for its authority, to authenticate the person represented by a Registry Record to a Relying Service and release authorised claims. It applies to sector populations such as farmers, students, health-service users, or licensed professionals. -## Cross-Building-Block ownership +## Relationship to the Identity Building Block -GovStack has not decided whether an Identity Federation profile for a functional sector identity is defined by Digital Registries, by the Identity Building Block, or jointly. The current [Identity Building Block description](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) scopes that Building Block to foundational identity while also discussing integration with functional identities. That provides context for the discussion but does not settle profile ownership. +The [Identity Building Block description](https://github.com/GovStackWorkingGroup/bb-identity/blob/main/spec/2-description.md) scopes that Building Block to foundational identity and includes integration with functional identities. Identity Federation concerns authentication and claim release for a functional sector identity. -Until the Digital Registries and Identity teams agree the boundary, this page records only the candidate capability outcome. It does not assign specification ownership or establish a protocol binding. +## Profile scope -## Profile considerations +A sector identity profile covers the relationship between the authenticated subject and the Registry Record, the lifecycle of the functional identifier, authorised claim release, subject-identifier policy, suspension or termination of the sector relationship, assurance expectations, and issuer topology. -Any eventual profile needs to define the relationship between the authenticated subject and the Registry Record, the lifecycle of the functional identifier, authorised claim release, subject-identifier policy, suspension or termination of the sector relationship, assurance expectations, and issuer topology. - -The functional identifier remains issued and lifecycle-managed by the responsible Registry Authority. The eventual profile also needs to define the use of issuer-scoped and pairwise subject identifiers where required to limit correlation. +The responsible Registry Authority issues and manages the lifecycle of the functional identifier. Subject-identifier policy addresses issuer-scoped and pairwise identifiers where needed to limit correlation. ## Capability boundary Identity Federation is an outward-facing service to a Relying Service. It is separate from authentication and authorisation used to protect Registry APIs. It does not issue or replace foundational identity. An Identity service can provide upstream authentication or identity proofing without taking ownership of the sectoral identifier. -## Binding status +## Implementation options -This release does not select a protocol binding for Identity Federation. OpenID Connect can be evaluated during the cross-Building-Block discussion, but this specification does not adopt it for this family or create a GovStack capability claim. +OpenID Connect is an illustrative, non-normative implementation option. No protocol binding is selected for this family. ## Example diff --git a/spec/05-api-families/notification.md b/spec/05-api-families/notification.md index fe8abfc..0261bba 100644 --- a/spec/05-api-families/notification.md +++ b/spec/05-api-families/notification.md @@ -4,7 +4,7 @@ description: Authorised delivery of Registry change events. # Notification -> **Status:** Informative and not claimable in this release. No Notification requirements, event schema, delivery profile, or tests are published. +> **Status:** Informative. See [Conformance](../04-conformance.md#44-capability-claims). ## Purpose and applicability @@ -23,11 +23,11 @@ A change event is not necessarily the authoritative Record. A consumer that need ## Adoption considerations -An adopting authority that includes Notification in its deployment needs to define event identifiers, Registry and Record context, revision references, event types, occurrence and publication time, subscription authorisation, minimisation, ordering, duplicate handling, delivery guarantees, and replay. +Deployment rules cover event identifiers, Registry and Record context, revision references, event types, occurrence and publication time, subscription authorisation, minimisation, ordering, duplicate handling, delivery guarantees, and replay. -## Binding status +## Implementation options -This release does not specify a Notification binding. An adopter evaluating HTTP push can consider OpenAPI webhooks, while event-driven transports such as AMQP, MQTT, Kafka, or WebSockets can be described with AsyncAPI. A Messaging or Information Mediator component can carry events without owning their Registry meaning. These choices do not create a GovStack capability claim. +Illustrative, non-normative options include OpenAPI webhooks for HTTP push and AsyncAPI descriptions for event-driven transports such as AMQP, MQTT, Kafka, or WebSockets. A Messaging or Information Mediator component can carry events without owning their Registry meaning. ## Example diff --git a/spec/05-api-families/provisioning.md b/spec/05-api-families/provisioning.md index 38f4fca..81bb62d 100644 --- a/spec/05-api-families/provisioning.md +++ b/spec/05-api-families/provisioning.md @@ -4,13 +4,13 @@ description: Programmatic configuration and publication of a Registry service. # Provisioning -> **Status:** Informative and not claimable in this release. No Provisioning requirements, contract, or tests are published. +> **Status:** Informative. See [Conformance](../04-conformance.md#44-capability-claims). ## Purpose and applicability Provisioning configures a Registry service and publishes its externally visible contracts. It is useful where schemas, capabilities, bindings, or controlled bulk data flows are administered programmatically. -Many authoritative registries do not need this family. Their authority and schema may be established by law, governance, or an operational process outside an API. +A Registry can publish its metadata without a Provisioning API. Its authority and schema may be established by law, governance, or an operational process outside an API. ## Capability areas @@ -21,15 +21,15 @@ Many authoritative registries do not need this family. Their authority and schem | Interface publication | Declares supported families, sub-patterns, bindings, and access conditions. | | Bulk transfer | Initiates a controlled import or export of data and metadata. | -These areas do not require dynamic database creation, a no-code builder, an administrative user interface, or a particular storage engine. Provisioning manages metadata programmatically; it does not make the Core publication requirement optional. It also does not perform the legal or governance act that establishes a Registry Authority. +Provisioning administers service metadata and contracts independently of the storage engine and administrative tooling. Registry Core requires metadata publication whether or not Provisioning is supported. Establishing a Registry Authority remains a legal or governance act outside this API family. ## Adoption considerations -An adopting authority that includes Provisioning in its deployment needs to define administrative authorisation, schema compatibility, publication lifecycle, bulk-operation validation, provenance, and failure recovery. This release does not supply those deployment rules. +Deployment rules cover administrative authorisation, schema compatibility, publication lifecycle, bulk-operation validation, provenance, and failure recovery. -## Binding status +## Implementation options -This release does not specify a Provisioning binding. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI for administrative operations and an asynchronous job or messaging pattern for long-running bulk work, but those choices do not create a GovStack capability claim. +Illustrative, non-normative options include synchronous HTTP described by OpenAPI for administrative operations and an asynchronous job or messaging pattern for long-running bulk work. ## Example diff --git a/spec/05-api-families/registry-core-context.jsonld b/spec/05-api-families/registry-core-context.jsonld index 44ed3bb..add167f 100644 --- a/spec/05-api-families/registry-core-context.jsonld +++ b/spec/05-api-families/registry-core-context.jsonld @@ -31,6 +31,10 @@ "@id": "dcat:service", "@type": "@id" }, + "specification": { + "@id": "dct:references", + "@type": "@id" + }, "conformsTo": { "@id": "dct:conformsTo", "@type": "@id" diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index b68a383..54e57b8 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -4,13 +4,19 @@ description: Shared identity, metadata, semantics, lifecycle, and provenance for # Registry Core -> **Status:** The Registry Core requirements are DRAFT and form part of the target Base Registry Profile. They do not establish a certification claim in this release. +> **Status:** DRAFT. See [requirement maturity](../04-conformance.md#41-requirement-maturity). ## Purpose and applicability -Registry Core is the shared foundation for every Digital Registries capability. It is not an API family. It defines how an implementation identifies the Registry and its authority and how returned Records identify their schema, semantic model, revision, lifecycle state, and minimum provenance. +Registry Core defines the common behaviour and metadata shared by the API families. It identifies the Registry, its authority and scope, and its available services. Returned Records have stable identity within an unambiguous Registry context and a documented representation schema. A capability or domain profile can additionally require revision, lifecycle, provenance, or formal semantic-model information. -Every Registry implementation publishes its current metadata. [Provisioning](provisioning.md) can optionally provide an administrative interface for creating or revising that metadata, but Provisioning is not required for publication and does not establish the Registry Authority. +The [conformance model](../04-conformance.md) combines Core with at least one selected capability. Core requirements apply as follows: + +- Registry metadata and service discovery apply to every implementation. +- Record representation requirements apply to implemented capabilities that return Records. +- Identifier preservation applies where the implementation assigns or maintains Record Identifiers. + +[Provisioning](provisioning.md) provides optional administrative operations for creating or revising metadata. Publication can also use a static document or an external catalogue. ## Conceptual model @@ -25,11 +31,11 @@ flowchart LR MODEL[Schema and Semantic Model] -->|governs| REPRESENTATION ``` -The model describes externally observable concepts rather than database tables, internal modules, or a deployment topology. An implementation can operate one Registry or many Registries and can expose one or more technical services without changing the meaning of the Registry itself. +The model describes externally observable concepts. An implementation can operate one or more Registries, each with one or more technical services. ## Registry metadata -The Registry metadata description identifies the institutionally governed Registry. It keeps the Registry distinct from its governed datasets, technical interfaces, and any catalogue in which it is listed. +Registry metadata describes the institutionally governed Registry and its relationships to datasets, technical services, and catalogues. ### Minimal metadata @@ -38,12 +44,16 @@ The Registry metadata description identifies the institutionally governed Regist | Registry Identifier | Required | Registry resource IRI | Globally unique and stable identifier for the Registry. | | Registry Name | Required | [`dct:title`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#title) | Human-readable name used by adopters and consumers. | | Registry Authority | Required | `govreg:authority` with a [`prov:Agent`](https://www.w3.org/TR/prov-o/#Agent) value | Institution accountable for the Registry and its declared authoritative scope. | -| Digital Registries specification version | Required | [`dct:conformsTo`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#conformsTo) | Versioned Digital Registries specification implemented by the service. | -| Description | Optional | [`dct:description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description) | Human-readable description of the Registry and its scope. | +| Digital Registries specification reference | Required | [`dct:references`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#references) | Identifies the versioned Digital Registries specification used to describe the implementation. | +| Description and authoritative scope | Required | [`dct:description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description) | Describes the information for which the named authority accepts responsibility, including relevant domain or jurisdictional boundaries. | | Governed dataset | Optional and repeatable | `govreg:dataset` with a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset) value | A governed collection of Registry Records described for discovery or exchange. | -| Data service | Optional and repeatable | `govreg:dataService` with a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service) value | A technical interface that provides access to Registry data or operations. | +| Data service | Required for each exposed Registry service; repeatable | `govreg:dataService` with a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service) value | Associates the Registry with each interface exposed through the Digital Registries capability model. | + +The scope description states the information for which the Registry Authority accepts responsibility and can reference a fuller scope or mandate document. The Registry Authority, Registry Operator, and catalogue publisher are distinct roles that can be held by the same or different organisations. The adopting ecosystem determines how it accepts or verifies authority declarations. Publication alone does not establish institutional responsibility. -The proposed GovStack vocabulary is intentionally small: +In the JSON-LD context, `specification` maps to `dct:references` and identifies the specification version. A formal claim against an applicable approved specification or profile uses `conformsTo`, mapped to `dct:conformsTo`. [Conformance](../04-conformance.md) defines the conditions for such claims. + +The GovStack vocabulary defines these Registry terms: | Term | Meaning | |---|---| @@ -52,30 +62,26 @@ The proposed GovStack vocabulary is intentionally small: | `govreg:dataset` | Relates a Registry to a governed collection described as a DCAT Dataset. | | `govreg:dataService` | Relates a Registry to a technical interface described as a DCAT Data Service. | -The companion [Turtle vocabulary](registry-core-vocabulary.ttl) provides machine-readable definitions of these terms and the API-family concept scheme. It keeps the vocabulary separate from the instance data in the example below. - -The selected publication namespace is the dedicated `vocab.govstack.global` host. The Registry Core namespace document is `https://vocab.govstack.global/digital-registries`, and the API-family concept-scheme document is `https://vocab.govstack.global/digital-registries/api-families`. Terms use fragment IRIs so each small vocabulary can be retrieved as one document. These version-independent IRIs remain stable when the vocabulary evolves. - -> **Editorial note:** Before release, GovStack needs to provision the namespace host so that both namespace documents dereference. This note can be removed once the host is operational. +The [Turtle vocabulary](registry-core-vocabulary.ttl) provides machine-readable definitions of these terms and the API-family concept scheme. -The namespace can provide HTML, Turtle, and JSON-LD representations through HTTP content negotiation without changing the term IRIs. The companion Turtle file does not require Registry implementations to publish Turtle or claim RDF conformance. This release does not define a SHACL shape. +The vocabulary uses two namespace documents: `https://vocab.govstack.global/digital-registries` for Registry Core and `https://vocab.govstack.global/digital-registries/api-families` for the API-family concept scheme. Terms use stable, version-independent fragment IRIs. Namespace documents can provide HTML, Turtle, and JSON-LD representations through HTTP content negotiation. These vocabulary representations do not prescribe the format of an implementation's metadata. -The versioned [JSON-LD context](registry-core-context.jsonld) is assigned the publication URI `https://vocab.govstack.global/digital-registries/context/v1`. When the vocabulary host is provisioned, this URI serves the context with the `application/ld+json` media type. Context versions are immutable because changing a context can change how existing JSON is interpreted. Versioning the context does not version or otherwise change the vocabulary term IRIs. +The [JSON-LD context](registry-core-context.jsonld) has the assigned publication URI `https://vocab.govstack.global/digital-registries/context/v1` and media type `application/ld+json`. Context versions are immutable and versioned independently of vocabulary terms, preserving the interpretation of existing JSON. See [publication coverage and limitations](../12-other-resources.md#121-coverage-and-limitations) for namespace availability and validation status. ### DCAT composition -The [Data Catalog Vocabulary 3](https://www.w3.org/TR/vocab-dcat-3/) describes the resources around a Registry rather than replacing the Registry concept: +The model composes Registry metadata with [Data Catalog Vocabulary 3](https://www.w3.org/TR/vocab-dcat-3/) resources: - the institutionally governed Registry is a `govreg:Registry`; - each governed collection can be a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset); - each technical API or query interface can be a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service); and - a directory that lists Registries can be a [`dcat:Catalog`](https://www.w3.org/TR/vocab-dcat-3/#Class:Catalog). -The base model does not require a Registry to operate its own catalogue. A national or sector directory can catalogue Registry descriptions, datasets, or services maintained by multiple authorities. +Catalogues can be operated by a Registry or by a national or sector directory serving multiple authorities. ### API family discovery -A `dcat:DataService` can identify the Digital Registries API families that it supports using [`dct:type`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#type). Each value is a concept from the **Digital Registries API Families** concept scheme. The `apif:` prefix abbreviates the concept namespace. +Each service exposed through the Digital Registries capability model identifies its supported API families using [`dct:type`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#type) on its `dcat:DataService` description. Each family value is a concept from the **Digital Registries API Families** scheme, abbreviated by the `apif:` prefix. Declarations cover Registry services available to the metadata's intended audience. | Concept | API family | |---|---| @@ -88,21 +94,37 @@ A `dcat:DataService` can identify the Digital Registries API families that it su | `apif:access-transparency` | Access Transparency | | `apif:identity-federation` | Identity Federation | -An API-family type means that the Data Service exposes at least one operation assigned to that family. It does not imply support for every capability pattern in the family and does not establish a GovStack conformance claim. The service's `dcat:endpointDescription` identifies the operational contract and exact operations. A separate `dct:conformsTo` statement identifies a formal profile that the service claims to satisfy. +An API-family type means that the Data Service exposes at least one operation assigned to that family. Supported operations are defined in the contract linked by `dcat:endpointDescription`. Family classification alone establishes neither support for every operation in the family nor conformance to a profile. + +Service metadata includes the service identifier, family classifications, `dcat:endpointURL`, and `dcat:endpointDescription`. The linked contract is machine-readable. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. Parameters, request and response schemas, outcomes, and access requirements are defined in that contract. The catalogue supports service discovery; automatic selection and invocation of equivalent operations across implementations is outside this discovery model. + +A service description declares only the families available for its associated Registry. Where a shared API offers different families for different Registries, each Registry uses a separate logical Data Service description. Those descriptions can share an endpoint or contract URI. + +### API composition + +One API can expose several Record collections and operations from several families. Its contract declares each collection's Registry association and membership, and each operation's family, inputs, representation, and access requirements. API-family classifications describe capabilities independently of URL structure. + +Operations from different families can share a resource URI through distinct HTTP methods. For example, Consultation can retrieve a Record at a URI where Write accepts an update. Each operation defines its own request and response schemas and permissions. The API contract coordinates collection, action, and supporting-resource paths, including any schema, subscription, or asynchronous-operation resources. + +The major version applies to the API contract exposed at that root. Separately exposed APIs can evolve under their own versions. Protocol-specific bindings follow their protocol's endpoint and versioning conventions. ### Discovery publication -Registry metadata and API discovery serve related but distinct purposes. A Registry description identifies the governed Registry and its authority. An API catalogue provides an entry point for finding the technical interfaces published on an HTTPS origin. +An implementation publishes the required metadata at a stable URI made available to its intended API consumers. Publication can use a statically hosted document or an entry in an external catalogue. Implementations document the publication URI, supported representations, and access conditions. -An implementation can publish its canonical DCAT catalogue at a stable HTTPS URI. The recommended default is the root-relative `/catalog` URI on the public API origin, with DCAT representations available through HTTP content negotiation. The catalogue can describe one or more Registries, their governed datasets, and their data services. The catalogue URI is not itself a Registry Identifier, and deployments can select a different stable path. +For a DCAT catalogue on an HTTPS origin, the recommended default is the root-relative `/catalog` URI, with DCAT representations available through HTTP content negotiation. Deployments can select another stable path. The catalogue describes one or more Registries, their governed datasets, and their services. The catalogue URI identifies the catalogue; each Registry has its own Registry Identifier. -For standardised API discovery, an implementation can use [RFC 9727, *api-catalog: A Well-Known URI and Link Relation to Help Discovery of APIs*](https://www.rfc-editor.org/rfc/rfc9727.html). RFC 9727 defines `/.well-known/api-catalog` and the `api-catalog` link relation. It provides indirection from the well-known URI to the deployment's canonical catalogue, whether that catalogue is published at `/catalog` or another path. A deployment using RFC 9727 follows its GET, HEAD, HTTPS, and [`application/linkset+json`](https://www.rfc-editor.org/rfc/rfc9264.html) requirements. +The optional [RFC 9727 API discovery mechanism](https://www.rfc-editor.org/rfc/rfc9727.html) defines `/.well-known/api-catalog` and the `api-catalog` link relation for locating the canonical API catalogue. Deployments using it follow its GET, HEAD, HTTPS, and [`application/linkset+json`](https://www.rfc-editor.org/rfc/rfc9264.html) requirements. -The current alpha treats this publication layout as discovery guidance rather than an additional Registry Core conformance requirement. A future HTTP and metadata binding can define required representations, content negotiation, caching, access policy, and validation. +A deployment supporting the JSON-LD workflow below provides `application/ld+json` at the configured or discovered catalogue URI. When using RFC 9727, it also provides the required Linkset representation. Clients request JSON-LD explicitly and check the response media type before parsing; RFC 9727 alone guarantees only Linkset support. + +Declarations are scoped to the intended metadata audience. Missing declarations establish neither the absence of an undisclosed service nor a consumer's entitlement to use it. ### Informative JSON-LD example -The following JSON-LD document describes one business Registry, accountable authority, governed dataset, and three services supporting the Consultation, Write, and Evidence API families. It references the versioned GovStack context, which maps readable JSON property names to the RDF vocabulary and identifies properties whose values are IRIs. The versioned GovStack specification IRIs are illustrative because this alpha does not publish canonical IRIs for them. +This JSON-LD document describes a business Registry, its authority and governed dataset, and three logical services supporting Consultation, Write, and Evidence at a shared API endpoint. The GovStack context maps JSON properties to the RDF vocabulary and identifies IRI-valued properties. The specification IRI is illustrative; publication status is listed under [coverage and limitations](../12-other-resources.md#121-coverage-and-limitations). + +The Consultation entry illustrates publication of the [business Registry OpenAPI](../../api/examples/business-registry.openapi.yaml) with its local dependencies at the example contract URL. It supports Retrieve, Lookup, List, and Search. ```json { @@ -117,7 +139,7 @@ The following JSON-LD document describes one business Registry, accountable auth "catalogResource": "https://registry.example/registries/business", "catalogDataset": "https://registry.example/datasets/business-records", "catalogService": [ - "https://registry.example/services/business-retrieve", + "https://registry.example/services/business-consultation", "https://registry.example/services/business-write", "https://registry.example/services/business-evidence" ] @@ -129,12 +151,12 @@ The following JSON-LD document describes one business Registry, accountable auth "dcat:Resource" ], "title": "Business Registry", - "description": "Registry maintained for authoritative business registration records.", - "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "description": "Authoritative business registrations in Example Jurisdiction, including registered names and registration status. Tax status is outside this Registry's scope.", + "specification": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", "authority": "https://registry.example/organisations/business-authority", "governedDataset": "https://registry.example/datasets/business-records", "dataService": [ - "https://registry.example/services/business-retrieve", + "https://registry.example/services/business-consultation", "https://registry.example/services/business-write", "https://registry.example/services/business-evidence" ] @@ -152,24 +174,22 @@ The following JSON-LD document describes one business Registry, accountable auth "publisher": "https://registry.example/organisations/business-authority" }, { - "@id": "https://registry.example/services/business-retrieve", + "@id": "https://registry.example/services/business-consultation", "@type": "dcat:DataService", - "title": "Business Registry Retrieve API", - "description": "Retrieves the current permitted representation of a business Record.", - "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "title": "Business Registry Consultation API", + "description": "Retrieves, looks up, lists, and searches permitted business Records.", "serviceType": "apif:consultation", "servesDataset": "https://registry.example/datasets/business-records", - "endpointURL": "https://registry.example/api/business", - "endpointDescription": "https://registry.example/contracts/business-retrieve.openapi.json" + "endpointURL": "https://registry.example", + "endpointDescription": "https://registry.example/contracts/1.0.0-draft/examples/business-registry.openapi.yaml" }, { "@id": "https://registry.example/services/business-write", "@type": "dcat:DataService", "title": "Business Registry Write API", "description": "Accepts governed requests to create or revise business Records.", - "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", "serviceType": "apif:write", - "endpointURL": "https://registry.example/api/business/write", + "endpointURL": "https://registry.example", "endpointDescription": "https://registry.example/contracts/business-write.openapi.json" }, { @@ -177,9 +197,8 @@ The following JSON-LD document describes one business Registry, accountable auth "@type": "dcat:DataService", "title": "Business Registry Evidence API", "description": "Produces signed assertions derived from permitted business registration information.", - "conformsTo": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", "serviceType": "apif:evidence", - "endpointURL": "https://registry.example/api/business/evidence", + "endpointURL": "https://registry.example", "endpointDescription": "https://registry.example/contracts/business-evidence.openapi.json" } ] @@ -188,11 +207,11 @@ The following JSON-LD document describes one business Registry, accountable auth The example uses untagged strings for readability. Deployments can use JSON-LD language maps, such as `"title": {"en": "Business Registry"}`, when publishing multilingual labels. -The Registry is also typed as [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) so that the catalogue can list it with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource). This does not make the Registry a dataset or a data service. The vocabulary expresses `govreg:Registry` as a subclass of `dcat:Resource`, while explicit dual typing keeps an instance understandable without ontology inference. +The Registry has both `govreg:Registry` and [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) types. This explicitly expresses the vocabulary's subclass relationship and lets the catalogue list the Registry with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource), without relying on ontology inference. The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in this catalogue. `govreg:dataset` and `govreg:dataService` state which datasets and services belong to this Registry. `dcat:servesDataset` states which dataset a technical service exposes, when applicable. -The `dct:type` statements let a client discover that the catalogue exposes Consultation, Write, and Evidence services. The client follows each service's `dcat:endpointDescription` to determine which operations are available and how to invoke them. +An implementation exposing only Evidence uses the same pattern with just the Evidence service in the Registry's `dataService` list and the catalogue's `catalogService` list. The same graph pattern covers common deployment arrangements: @@ -200,14 +219,14 @@ The same graph pattern covers common deployment arrangements: - a multi-Registry implementation adds more Registry resources and their related datasets and services to the same catalogue; and - an aggregating national catalogue can list resources from multiple Registry Authorities or use [`dcat:catalog`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_catalog) to include catalogues published by those authorities. -The catalogue contains descriptive metadata only. It does not publish the protected Records contained in a governed dataset. +Catalogue entries contain descriptive metadata only. Services govern disclosure of Record information through their access policies. ### Client discovery workflow -A client can discover supported API families without knowing an implementation's API paths in advance: +A client using the illustrated DCAT publication arrangement can discover declared API families without knowing an implementation's API paths in advance: 1. Locate the canonical catalogue from a configured URI, the optional RFC 9727 well-known resource, or the recommended `/catalog` convention. -2. Retrieve a supported RDF representation of the catalogue, such as JSON-LD. +2. Request a documented RDF representation of the catalogue, such as JSON-LD, and check that the response uses that media type. 3. Select the required `govreg:Registry` by its stable Registry Identifier. 4. Follow `govreg:dataService` to each associated `dcat:DataService`. 5. Read each service's `dct:type` values from the Digital Registries API Families scheme, then follow `dcat:endpointDescription` for the exact operations and invocation contract. @@ -223,30 +242,34 @@ if catalogUri is absent: if catalogUri is absent: catalogUri = resolve(apiOrigin, "/catalog") -catalog = loadJsonLd(catalogUri) +response = get(catalogUri, accept = "application/ld+json") +requireMediaType(response, "application/ld+json") +catalog = loadJsonLd(response.body) registry = catalog.resourceWithId(requiredRegistryId) -supportedCapabilities = [] +discoveredServices = [] for each serviceReference in asList(registry.dataService): service = catalog.resourceWithId(serviceReference) for each family in asList(service.serviceType): if DigitalRegistriesApiFamilies contains family: - supportedCapabilities.append({ + discoveredServices.append({ family: family, service: resourceIdentifier(service), endpoint: service.endpointURL, description: service.endpointDescription }) -return supportedCapabilities +return discoveredServices ``` -Here, `loadJsonLd` applies the versioned context and normalises properties that can contain one or several values. `DigitalRegistriesApiFamilies` is populated from the published [API-family vocabulary](registry-core-vocabulary.ttl), not inferred from an IRI prefix. With the preceding example, the result identifies three Data Services supporting the Consultation, Write, and Evidence families. If a Data Service omits `serviceType`, a client cannot infer API-family support from the catalogue alone, even when its endpoint description happens to contain related operations. +`loadJsonLd` applies the versioned context and normalises properties that can contain one or several values. `DigitalRegistriesApiFamilies` contains the concepts defined in the [API-family vocabulary](registry-core-vocabulary.ttl); membership is determined by those definitions, not by an IRI prefix. The example returns three Data Services supporting Consultation, Write, and Evidence. + +The example assumes the selected Registry and its service descriptions are present in the returned graph. Deployments using external descriptions document their retrieval. A service description missing a required family classification or contract reference is incomplete under Core. Operation names alone establish neither a family classification nor a conformance claim. ### External alignments -External vocabularies and application profiles can add jurisdictional or discovery semantics without becoming dependencies of Registry Core. +Adopting profiles can use external vocabularies to add jurisdictional or discovery semantics. These alignments are optional. | Alignment | Intended use | |---|---| @@ -255,37 +278,84 @@ External vocabularies and application profiles can add jurisdictional or discove | [BRegDCAT-AP](https://github.com/SEMICeu/BRegDCAT-AP) | European base-registry catalogue interoperability. | | National or sector profiles | Additional legal, organisational, service, or dataset metadata required by an adopter. | -An adopting profile can add types and properties when their semantics apply. Registry Core does not assert that `govreg:Registry` is universally equivalent to an external service or base-registry class. +An adopting profile adds types and properties where their semantics apply. Any equivalence between `govreg:Registry` and an external class is specific to that profile. ## Common Record context -Every returned Record representation carries a common context in addition to its permitted domain data. +Every returned Record representation has the following context. The binding defines where it is conveyed: in the representation, response metadata, or the versioned operational contract and its association with the Registry. A consumer can determine that context without knowing the source's internal storage. Registry-wide information need not be repeated in every Record or collection item. -| Concept | Purpose | +| Concept | Baseline contract | |---|---| -| Registry Identifier | Identifies the Registry that returned the representation. | -| Record Identifier | Stable reference to the Record within the Registry. | -| Revision Identifier | Identifies the current revision represented by the response. | -| Lifecycle State | State permitted by the declared representation schema. | -| Representation Format | Identifies the serialisation or media type through the applicable binding. | -| Schema Reference | Resolves to the machine-readable structure used to validate the domain data. | -| Semantic Model Reference | Identifies the vocabulary or domain model used to interpret the domain data. | -| Registry Authority | Identifies the institution responsible for the authoritative source. | -| Recorded At | Identifies when the current revision was recorded. | - -The applicable capability determines whether a representation contains domain data and which projection the consumer is permitted to receive. Protected metadata can be omitted or redacted only where the applicable representation schema and capability requirements keep the result unambiguous and valid. +| Registry Identifier | The request and published service metadata establish one Registry context, or the returned Record explicitly identifies its Registry. | +| Record Identifier | A stable reference unique within that Registry, included in each returned Record. | +| Representation Format | The binding identifies the serialisation or media type. | +| Representation Schema | A resolvable, versioned machine-readable schema identifies the permitted representation; schema selection is unambiguous. | +| Field meanings | Schema descriptions or linked domain documentation explain field meanings, units, code lists, and relevant absence or null semantics. | +| Registry Authority | The Registry context resolves to the authority and authoritative scope published in Registry metadata. | + +The applicable capability determines which domain data and metadata the consumer may receive. A fixed public view is sufficient where it meets the applicable policy. Different consumer views are optional; each exposed view has a valid, documented schema. The HTTP binding uses the same Record object for single results and collection members within a declared view. + +Collections organise access to Records within the Registry's identity scope. The same Record retains its identifier across collections and views. Distinct Records have distinct identifiers within that Registry, including when their source collections use overlapping keys. An adapter can qualify such keys with a stable namespace; consumers continue to treat the resulting identifiers as opaque. + +A service returning Records from different Registries or schemas makes the distinction explicit for each affected Record. A shared service URL alone does not establish a unique Registry context. An export or portable representation declares any additional context needed when it leaves its original request context. + +Record schemas define [structured values and references](#structured-values-and-references), including the identity, ownership, and meaning of embedded data. + +**Example: resolving Record context.** In the illustrative business binding, `GET https://registry.example/v1/businesses/r_42` returns: + +```json +{ + "recordId": "r_42", + "data": { + "legalName": "Example Ltd", + "registrationStatus": "DISSOLVED" + } +} +``` + +The metadata above associates that service with Registry `https://registry.example/registries/business` and the Business Registration Authority. The linked OpenAPI associates the `businesses` collection with that Registry and selects the `business-public` view and its `BusinessData` schema. A consumer retaining this Record's identity stores the Registry Identifier together with `r_42`. ## Revisions and lifecycle -The Record Identifier remains stable when a new revision is accepted. Revision identifiers distinguish successive representations of the same Record. +The Record Identifier remains stable when the Record changes. Existing source identifiers may be reused when they satisfy the identity and stability requirements. Core does not require an adapter to introduce revision storage, maintain a journal, or mint aliases for already suitable source identifiers. + +Revision identifiers, revision recording times, and lifecycle fields are optional in the baseline. When supplied or required by a selected capability or profile, their schema defines their meaning and availability. A source revision identifies a revision accepted by the source; a response hash or HTTP validator does not by itself establish such an identifier. A response timestamp is not the time a source revision was recorded. + +Current information is the current accepted information available through the source interface under its documented currency contract. It need not describe an active entity. Domain status fields retain their documented meaning; omitting a generic lifecycle field does not imply an active state. Capabilities such as Revision History need a stronger revision contract than current Consultation reads. + +**Example: stable identity through a status change.** Two current reads of the same business, before and after its dissolution is accepted by the source, return: + +| Read | `recordId` | `data.registrationStatus` | +|---|---|---| +| Before dissolution | `r_42` | `ACTIVE` | +| After dissolution | `r_42` | `DISSOLVED` | -The declared representation schema defines the supported lifecycle-state vocabulary. Terms such as active, inactive, superseded, archived, and deleted are examples, not a mandatory enumeration in this release. +The identifier continues to refer to the same Record; its current domain status changes. ## Domain semantics and extensions -The Digital Registries Building Block does not define a universal person, business, parcel, vehicle, health, or programme schema. Each returned representation identifies its machine-readable schema and published semantic model. An adopter can use an appropriate sector model and map national extensions explicitly. +Adopters should reuse established domain schemas and vocabularies where suitable, including [Schema.org](https://schema.org/), [EU SEMIC Core Vocabularies](https://interoperable-europe.ec.europa.eu/collection/semic-support-centre/solution/core-vocabularies), [PublicSchema](https://publicschema.org/), and schemas defined or adopted by national and sector authorities. The contract identifies adopted models and versions, preserves their concepts' meanings, and documents field meanings, source mappings, local constraints, and extensions. A separately published formal semantic model is optional unless a selected capability or profile requires it. Representations follow the applicable inherited cross-functional requirements. -Extensions do not change the meaning of required Registry or Record metadata. Rules for unknown fields, compatibility, and schema evolution are not defined in this release. +Extensions preserve the meaning of required Registry and Record metadata. Compatible schema evolution keeps existing fields and context interpretable; an incompatible representation is identified through a new version or an explicitly selected view. The status of broader compatibility rules is documented under [coverage and limitations](../12-other-resources.md#121-coverage-and-limitations). + +### Structured values and references + +Domain schemas distinguish values owned by the containing Record, references to other Records, and embedded representations of related Records. Component identifiers have schema-defined scope. Embedded related representations preserve the target Record's identity and Registry context and declare their source currency. Recorded values retain the meaning assigned by their owning source, including its correction rules. + +A Record reference identifies its target Record and Registry unambiguously through the field schema or explicit reference context. Adopted domain reference forms can be used with documented identity, target scope, and resolution semantics. When a target read is offered, the field binding identifies the target collection, operational contract and operation, and how the reference supplies the required inputs. A binding with several possible targets defines how to select the applicable read. Target reads follow the Registry's published capabilities and access policy. Profiles declare any referential-integrity guarantees. + +Embedded collection schemas declare bounds. Their contracts define complete permitted views, selected subsets, or pages with continuation; omitted, null, and empty values; and overflow outcomes. A collection declared complete contains every component permitted by that view. Each paginated collection has its own continuation context. Disclosure policy applies to references, embedded data, and completeness information. + +**Example: related Record identity.** A field using the illustrative `UnscopedRecordReference` [schema](../../api/examples/relationship-examples.schema.json) carries the target Registry explicitly: + +```json +{ + "recordId": "person_42", + "registryId": "https://registry.example/registries/individuals" +} +``` + +The same schema document defines `IndividualReference`, whose target Registry is fixed to that IRI. A field using it can carry `{"recordId": "person_42"}`. Its illustrative field binding maps `recordId` to the path parameter of the target service's `GET /v1/individuals/{recordId}` operation. Reading that reference therefore uses `GET https://registry.example/v1/individuals/person_42`, subject to the target service's published contract and access conditions. The binding supplies the route; the identifier remains opaque. ## Registry Core functional requirements @@ -293,25 +363,25 @@ Extensions do not change the meaning of required Registry or Record metadata. Ru `govstack-bb-digital-registries-fr-core#req-1` -An implementation publishes machine-readable Registry metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, and the Digital Registries specification version it implements. +An implementation publishes machine-readable Registry metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, a description of its authoritative scope, and a reference identifying the Digital Registries specification version used to describe the implementation. The publication URI and access conditions are made available to the intended API consumers. -**Purpose:** An adopter can determine which Registry and authority stand behind a service and which versioned requirement set, including its inherited requirements, applies. +**Purpose:** An adopter can determine which Registry and authority stand behind a service, what information that authority accepts responsibility for, and which specification version the description references. **Prerequisite:** The Registry Authority and authoritative scope have been established by the adopting organisation. -**Verification:** Inspect the published Registry metadata, validate that all required values are present, and review evidence that the Registry Identifier is not shared with another Registry or changed between service revisions. +**Verification:** Access the metadata as an intended consumer, validate that all required values are present, check that the description states the authoritative scope, and review evidence that the Registry Identifier is not shared with another Registry or changed between service revisions. ### #2 Identify each returned Record (DRAFT EXTENSIBLE OBSERVABLE) `govstack-bb-digital-registries-fr-core#req-2` -Every returned Record representation includes the Registry Identifier and a Record Identifier that is unique within that Registry. Together, the two identifiers uniquely identify the Record. +Every returned Record representation includes a Record Identifier that is unique within an unambiguous Registry context. The applicable binding defines how the consumer determines the Registry Identifier from the request, published contract and service metadata, or the representation itself. Together, the two identifiers uniquely identify the Record. **Purpose:** Consumers can distinguish Records from different Registries and refer to one Record without depending on mutable domain attributes. **Prerequisite:** A Record has been accepted into the Registry. -**Verification:** Retrieve two distinct Record fixtures and verify that each response carries the expected Registry Identifier and a different Record Identifier. +**Verification:** Obtain two distinct Record fixtures through an implemented capability that returns Records and verify their different Record Identifiers and the Registry context established by the binding. If a service spans multiple Registries, verify that identical local identifiers in those Registries remain distinguishable. ### #3 Preserve Record Identifiers (DRAFT EXTENSIBLE AUDITABLE) @@ -325,38 +395,50 @@ An implementation keeps a Record Identifier unchanged throughout that Record's l **Verification:** Review the identifier policy and evidence showing that successive revisions retain the same identifier, distinct Records do not share an identifier, and retired identifiers are not returned to the allocation pool. -### #4 Identify the Record schema, semantic model, and representation format (DRAFT EXTENSIBLE OBSERVABLE) +### #4 Identify the representation schema and field meanings (DRAFT EXTENSIBLE OBSERVABLE) `govstack-bb-digital-registries-fr-core#req-4` -Every returned Record representation identifies a resolvable machine-readable schema and the published semantic model that govern its domain data. It also identifies its representation format through the applicable binding. +Every returned Record representation has an unambiguously identified, resolvable machine-readable schema and documented field meanings. The applicable binding identifies its representation format and how the consumer selects the schema. A formal semantic-model reference is provided when required by the selected capability or profile. -**Purpose:** Consumers can decode and validate a representation and interpret its domain meaning without knowledge of the implementation's internal storage. +**Purpose:** Consumers can decode, validate, and interpret a representation without knowledge of internal storage. -**Prerequisite:** The Registry Authority has selected the applicable representation format, schema, and semantic model. +**Prerequisite:** The implementation has published the applicable representation format, schema, and domain documentation. -**Verification:** Retrieve a Record, verify that the representation format conveyed by the binding matches the returned representation, resolve the declared schema, validate the representation, and resolve the semantic-model identifier to its published definition. +**Verification:** Obtain a Record representation through an implemented capability, identify its format and schema using only the published contract and response context, and validate it. Check adopted model versions, mappings, and extensions where used. Check the documentation for field meanings, units, code lists, and absence semantics, including whether nested objects are components, Record references, or embedded representations. For references, verify the target Registry context and any declared read binding. For embedded collections, verify the declared bounds and completeness semantics. Resolve a formal semantic-model reference when the selected contract requires one. -### #5 Identify the current revision and lifecycle state (DRAFT EXTENSIBLE OBSERVABLE) +### #5 Describe provided revision and lifecycle metadata (DRAFT EXTENSIBLE OBSERVABLE) `govstack-bb-digital-registries-fr-core#req-5` -Every returned Record representation identifies its current revision and a lifecycle state permitted by the representation's declared schema. +When an implemented capability exposes revision or lifecycle metadata, it defines those fields in the representation schema and returns values with the declared source semantics. A capability or profile requiring those fields supplies its additional guarantees; baseline Record reads do not require them. -**Purpose:** Consumers can distinguish the current representation from earlier revisions and interpret its declared state. +**Purpose:** Consumers can interpret available revision and lifecycle information without inferring guarantees that the source does not provide. -**Prerequisite:** The selected representation schema defines the supported lifecycle-state vocabulary. +**Prerequisite:** The selected contract exposes revision or lifecycle metadata. Otherwise, this requirement's metadata scenarios are not applicable. -**Verification:** Retrieve fixtures in each lifecycle state exposed through Consultation, validate each state against the declared schema, and verify that each response identifies a current revision. +**Verification:** Compare the provided metadata with source fixtures and the declared schema. Verify the meaning of revisions and exposed lifecycle states. Check that a representation validator is not presented as a source revision unless the source contract establishes that equivalence. -### #6 Provide minimum Record provenance (DRAFT EXTENSIBLE OBSERVABLE) +### #6 Describe provided Record provenance (DRAFT EXTENSIBLE OBSERVABLE) `govstack-bb-digital-registries-fr-core#req-6` -Every returned Record representation identifies the Registry Authority as the responsible source and provides the time at which the current revision was recorded. +The Registry context identifies the responsible Registry Authority through published metadata. When additional Record provenance is exposed, the contract defines its meaning and the implementation returns values supported by the source. A revision recording time is required only when the selected capability or profile requires it; retrieval time is not substituted for recording time. + +**Purpose:** A consumer can identify the institutional source and interpret available provenance without fabricated source facts. + +**Prerequisite:** Registry metadata identifies the authority. Additional provenance fixtures are required only for fields exposed by the selected contract. + +**Verification:** Resolve the Record's Registry context to its published authority. For every additional provenance field exposed by the contract, compare its value and meaning with source evidence. Verify that unavailable optional provenance is omitted rather than inferred from the adapter's response time. + +### #7 Publish service discovery metadata (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-core#req-7` + +For each service exposed through the Digital Registries capability model, an implementation publishes a machine-readable service description associated with the Registry. The description identifies the service, its supported API families from the Digital Registries API Families concept scheme, its endpoint, and a link to its machine-readable operational contract. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. Declarations reflect the families and endpoints available for that Registry to the metadata's intended audience and are kept current when those services change. -**Purpose:** A consumer can assess the institutional source and currency of the authoritative information. +**Purpose:** An API Consumer can discover relevant Registry services and follow their contracts to determine the supported operations and invocation details. -**Prerequisite:** The Registry captures provenance for each accepted revision. +**Prerequisite:** The Registry publishes at least one service under the capability model and makes the metadata and contract access conditions available to intended consumers. -**Verification:** Retrieve a Record and verify that the representation contains the Registry Authority identifier and recording time. Additional protected provenance details are outside this minimum requirement. +**Verification:** Obtain the metadata as an intended consumer. For every service exposed to that audience, verify its Registry association, service identifier, valid family classifications, endpoint, and resolvable machine-readable contract. Check that the contract describes the advertised endpoint and contains operations belonging to each declared family. Check declarations against the implementation's published service inventory, including different Registry contexts when an endpoint is shared. A missing required service description or contract fails this check; unrelated internal services are outside its scope. diff --git a/spec/05-api-families/write.md b/spec/05-api-families/write.md index db41869..7927387 100644 --- a/spec/05-api-families/write.md +++ b/spec/05-api-families/write.md @@ -4,7 +4,7 @@ description: Authorised creation and revision of Registry Records. # Write -> **Status:** Informative and not claimable in this release. No Write requirements, transition model, contract, or tests are published. +> **Status:** Informative. See [Conformance](../04-conformance.md#44-capability-claims). ## Purpose and applicability @@ -18,15 +18,15 @@ Write creates a Record or accepts a new authoritative revision. It applies when | Governed write | A proposed change becomes authoritative only after the required review or approval process. | | Correction | A subject or authorised actor requests correction through the governed path defined for that Registry. | -An adopting authority that includes Write in its deployment needs to define accepted transitions, validation, transition-specific authorisation, idempotency, concurrency, provenance, correction, retirement, and any legally defined deletion behaviour. +Deployment rules cover accepted transitions, validation, transition-specific authorisation, idempotency, concurrency, provenance, correction, retirement, and any legally defined deletion behaviour. ## Capability boundary The Registry Authority remains responsible for accepted transitions and the resulting authoritative state. A Registration, Workflow, or sector-specific service can own intake and approval and then submit an approved result. Write does not require the Registry to implement a general workflow engine. -## Binding status +## Implementation options -This release does not specify a Write binding or job model. An adopter evaluating implementation options can use synchronous HTTP described by OpenAPI for immediate changes and an asynchronous status pattern for governed or long-running changes, but those choices do not create a GovStack capability claim. +Illustrative, non-normative options include synchronous HTTP described by OpenAPI for immediate changes and an asynchronous status pattern for governed or long-running changes. ## Example diff --git a/spec/05-key-functionalities.md b/spec/05-key-functionalities.md index 98c3857..518efcd 100644 --- a/spec/05-key-functionalities.md +++ b/spec/05-key-functionalities.md @@ -6,29 +6,27 @@ description: Capability families provided by the Digital Registries Building Blo The Digital Registries Building Block groups its externally visible capabilities into eight families. A family describes an adopter outcome and a coherent trust boundary. It does not prescribe an internal module, product architecture, or transport. -Only **Consultation Retrieve** is part of the target Base Registry Profile. The other Consultation sub-patterns and seven other families are informative in this release. They are not claimable because they do not yet have approved requirements, contracts, and tests. +The [conformance model](04-conformance.md#43-conformance-model) requires Registry Core and at least one declared Registry capability. All API families and operations, including Consultation Retrieve, are optional. -
Digital Registries Building Block capability families
Registry Core provides the shared foundation. The target Base Registry Profile adds Consultation Retrieve.
+
Digital Registries Building Block capability families
Registry Core provides the mandatory shared foundation. Implementations select capabilities from optional families.
## 5.1 Reading capability requirements Requirements are placed with the capability to which they apply. Shared requirements are defined under [Registry Core](05-api-families/registry-core.md), while family-specific requirements are defined on the applicable family page. -Each requirement follows the GovStack Requirements Model. `DRAFT` means that the requirement is available for review but is not included in certification. Requirement identifiers are permanently reserved even while the requirement is DRAFT. - -This organisation and the capability-specific requirement namespaces are provisional pending resolution of [GovStack CFR issue #7](https://github.com/GovStackWorkingGroup/cfr-architecture/issues/7) on optional capabilities and conformance profiles. - -This release contains only requirements that support the target Base Registry Profile. Informative capability descriptions do not create requirements or have conformance effect. +[Requirement Maturity](04-conformance.md#41-requirement-maturity) defines requirement classification, governance dependencies, and conformance status. Informative capability descriptions do not create requirements. ## 5.2 Registry Core -Registry Core provides the identity, metadata, Record reference, semantic, lifecycle, and provenance foundation shared by every API family. It is not itself an API family. Every family-specific profile inherits the [Registry Core model and requirements](05-api-families/registry-core.md) rather than restating them. +Registry Core provides the identity, metadata, discovery, stable Record references, schema context, and field meanings shared by every API family. It also defines how supplied revision, lifecycle, and provenance metadata are described. It is not itself an API family. Each selected capability inherits the applicable [Registry Core model and requirements](05-api-families/registry-core.md). Requirements for returned Records apply when a capability returns Records. + +Registry Core requires publication of machine-readable Registry and service metadata. Service descriptions identify exposed API families, endpoints, and operational contracts. This publication can use static metadata and does not require a Provisioning API. Paths, methods, parameters, schemas, and security details belong in the linked operational contract, such as OpenAPI. ## 5.3 Family catalogue | Family | Adopter outcome | Capability patterns | Status in this release | |---|---|---|---| -| [Consultation](05-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, Existence Check, List, Search, Revision History, Record Match, GIS Query | Retrieve is in the target Base Registry Profile; other patterns are informative. | +| [Consultation](05-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, Lookup, List, Search, Existence Check, Revision History, Record Match, GIS Query | Retrieve, Lookup, List, and Search have DRAFT requirements and a draft HTTP contract; other patterns are informative. | | [Provisioning](05-api-families/provisioning.md) | Configure a Registry service and publish its externally visible contracts. | Metadata administration, schemas, capability publication, bulk transfer | Informative | | [Evidence](05-api-families/evidence.md) | Obtain a signed assertion derived from authoritative Registry information. | Direct attestation, wallet-mediated credential, status | Informative | | [Write](05-api-families/write.md) | Create a Record or accept a new authoritative revision. | Direct write, governed write, correction | Informative | @@ -41,10 +39,11 @@ Registry Core provides the identity, metadata, Record reference, semantic, lifec An adopter selects capabilities from the Registry's institutional responsibilities, domain model, and consumer needs, not from the feature list of a particular product. Useful questions include: -- Does the Registry expose only current Records, or also search, historical revisions, mutation, events, evidence, statistics, or subject authentication? +- Do consumers know Record Identifiers, need exact lookup by a domain identifier, or need collection browsing or search? +- Does the Registry expose historical revisions, mutation, events, evidence, statistics, or subject authentication? - Which actors can invoke each capability, and what may each actor learn? - Does the Registry own an approval process, or accept an approved result from another service? - Does the consumer need live Registry information, a portable proof, or notification that state changed? - Which sector semantic model and protocol binding fit the participating systems? -Each family page states its boundary and maturity. A registry or sector profile supplies the domain-specific schemas, lifecycle vocabulary, query semantics, and other constraints needed by its selected capabilities. A capability without published requirements, a binding, and tests cannot be included in a GovStack conformance claim for this release. +Each family page states its boundary and maturity. A registry or sector profile supplies domain-specific schemas, field meanings, declared selectors and search criteria, and other constraints needed by its selected capabilities. It defines lifecycle and revision semantics when those are provided or required. [Capability Claims](04-conformance.md#44-capability-claims) defines the requirements for claiming a selected capability. diff --git a/spec/09-service-interfaces.md b/spec/09-service-interfaces.md index 4fe4aa9..9a3ca51 100644 --- a/spec/09-service-interfaces.md +++ b/spec/09-service-interfaces.md @@ -1,48 +1,86 @@ --- -description: Abstract operation and binding status for Consultation Retrieve. +description: Operational contracts and the draft Consultation HTTP binding. --- # 9 Service Interfaces -## 9.1 Current coverage +## 9.1 Operational contracts -This release defines the semantics of one operation, `consultation.retrieve`. It does not define an HTTP path or exact JSON property names. +[Registry Core](05-api-families/registry-core.md#api-family-discovery) requires each exposed Registry service to publish its family classifications, endpoint, and a link to its machine-readable operational contract. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. -The previous generated CRUD OpenAPI files are legacy artifacts. They are not contracts for this release and do not contain a Retrieve-by-Identifier operation. +Family classifications identify a service's broad capabilities. The linked contract defines exact operations, parameters, schemas, outcomes, and access requirements. Catalogue descriptions link to these details without reproducing them. A static published description and contract are sufficient; discovery does not require a new runtime service. -## 9.2 Abstract Retrieve operation +[Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) records binding availability. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines conformance status. -| Element | Definition | -|---|---| -| Operation identifier | `consultation.retrieve` | -| Purpose | Obtain the current permitted representation of one Record. | -| Required input | Record Identifier. | -| Request context | Authentication and authorisation information required by the deployment and inherited CFR requirements. | -| Success output | Current permitted Record representation described under [Consultation](05-api-families/consultation.md#retrieve-representation), including the [common Record context](05-api-families/registry-core.md#common-record-context). | -| Unsuccessful outcome | Outcome without protected Record data and with the protected-existence handling required by `fr-consultation#req-3`. | -| Excluded behaviour | Existence Check, List, Search, Revision History, Record Match, GIS Query, and individual stored-field retrieval. | +## 9.2 Abstract Consultation operations + +[Consultation](05-api-families/consultation.md) defines the independently selectable Retrieve, Lookup, List, and Search capabilities and their [shared Record representation](05-api-families/consultation.md#retrieve-representation). + +## 9.3 Consultation HTTP binding + +The [canonical OpenAPI](../api/openapi.yaml) defines the synchronous HTTPS/JSON binding, including inputs, schemas, status codes, Problem Details, headers, and security. Its version is `1.0.0-draft`, with `/v1` as the HTTP compatibility line. It uses API Design Guide and ruleset `0.2.0-draft`; the BB requirements remain DRAFT. + +### Scope and deployment contract + +The server URL identifies the deployment root, optionally including a stable prefix such as `/registry`. The major version precedes each collection: `/v1/households` or, with that prefix, `/registry/v1/households`. + +One API can expose multiple collections. Its contract associates each collection with a Registry, membership scope, selected capabilities, and operation schemas. Registry metadata supplies authority and service context. A Record retains its `(registryId, recordId)` identity across collections and views within that Registry. + +A deployment publishes a concrete OpenAPI contract containing its selected operations, service and authentication endpoints, versioned JSON Schemas for `data` and the complete response, selectors, searches, supported filters and ordering, source currency, access policy, and continuation policy. Family classifications describe operations; Consultation and Write may share a resource URI with separate methods, request and response schemas, and permissions. The [OpenAPI examples](../api/examples/README.md) illustrate concrete collections, domain schemas, and response payloads. + +### Operations and inputs + +| HTTP operation, relative to the deployment root | Successful body | Input contract | +|---|---|---| +| `GET /v1/records/{recordId}` | Record | Record Identifier encoded as one path segment. | +| `POST /v1/records:lookup` | Record | JSON object with `selector` and `values`. | +| `GET /v1/records` | Page | Optional `pageSize`, `cursor`, and declared public filter or sort parameters. | +| `POST /v1/records:search` | Page | JSON object with `search`, `criteria`, and optional `pageSize`, `cursor`, and declared `sort`. | + +`records` is the canonical reference name. Deployments publish concrete collection paths, such as `/v1/businesses`; the suffixes `:lookup` and `:search` address operations on that collection. IDs such as `lookup` and `search` remain valid in the item path. + +The binding also exposes the guide's unversioned `/health` operation. Lookup and Search are synchronous reads returning `200`. Their criteria remain in the request body. Lookup uses a declared unique key within its documented scope; Search uses declared typed criteria. The concrete contract defines comparison and normalization rules and rejects unsupported inputs. + +### Representation and schema context + +Retrieve and Lookup return `{recordId, data}`. List and Search return `{items, pageInfo}`, with each item using the same Record schema for the declared view. Empty and single-result collections retain the Page shape. + +The endpoint and published contract provide Registry and schema context. Additional source metadata follows [Registry Core](05-api-families/registry-core.md#common-record-context). A schema linked with `rel="describedby"` describes the complete response, including its envelope. A separate summary view has its own declared schema and field meanings. + +### Outcomes, errors, and caching + +The OpenAPI defines HTTP outcomes and RFC 9457 Problem Details. Retrieve and Lookup use `404 record-not-available` for unknown Records and Records outside the collection. Protected Records use the same outcome where [protected-existence handling](05-api-families/consultation.md#retrieve-functional-requirements) applies. Invalid continuations fail explicitly. + +Protected reads and errors use `Cache-Control: no-store`. Deployments may declare caching for public or isolated representations. Optional conditional Retrieve evaluates authorization before returning `304`; its ETag validates the selected HTTP representation. + +### Pagination + +List and Search use forward opaque cursors under [Consultation requirement #7](05-api-families/consultation.md#pagination-contract). The first request selects an effective `pageSize`, defaulting to 20 and bounded to 100 in the canonical contract. A continuation repeats the original criteria, search name where applicable, sorting, and view with the cursor. Omitting `pageSize` retains the bound value; supplying a different value produces `400 invalid-cursor`. + +Cursors bind the operation, Registry, collection, query, view, effective page size, and applicable access context. The deployment declares expiry and rejects malformed, expired, or mismatched cursors, including continuations whose query or view semantics it can no longer preserve. A short or empty Page can carry a non-null `nextCursor` when source processing advances. Traversal completes at `nextCursor: null`. + +Optional `pageInfo.total` is the exact count of the full permitted query at the documented page evaluation time, before applying the continuation boundary. Services omit it when unavailable. OpenAPI defines the cursor format, limits, and error responses. + +### Record references + +The [Core representation rules](05-api-families/registry-core.md#structured-values-and-references) govern nested data and related Records. The reusable `RecordReference` schema carries `recordId` and, where the field schema leaves the target Registry open, required `registryId`. A field with a fixed target Registry permits omission of `registryId` and accepts an explicit value only when it matches that target. -## 9.3 Binding status +When a related read is offered, the field binding identifies its target collection, read operation, and operational contract, including how the reference supplies the operation's inputs. Consumers follow that binding and the target's access requirements. Record Identifiers remain opaque; reference identity is independent of the target's current availability. -No canonical OpenAPI contract is published in this release, so an implementation-specific HTTP interface cannot be used to establish a GovStack capability claim. An adopter prototyping Retrieve can use synchronous HTTP over HTTPS and describe that interface with OpenAPI. +Optional client-selected expansion declares its supported paths, bounds, source currency, and disclosure behavior in the deployment contract. The [OpenAPI examples](../api/examples/README.md) demonstrate concrete nested schemas and references. -An HTTP contract used by an adopter needs to define: +### Design choices and guide alignment -- resource path and API versioning; -- exact Registry and Record metadata property names; -- schema resolution and content negotiation; -- conditional retrieval and revision identifiers; -- policy-compliant mapping of unknown, unauthorised, inactive, and superseded outcomes; and -- contract examples that do not assume a person registry. +The [read API design decisions](12-other-resources/read-api-design-decisions.md) record the binding choices and the shared guide refinements. ## 9.4 Protocol options for additional capabilities -The following standards can help an adopter evaluate implementation options for capabilities that are not claimable in this release. The table does not establish a required specification, version, or profile. +The following standards provide implementation options. The table does not establish a required specification, version, or profile. | Capability | Protocol options | |---|---| | Provisioning and general HTTP operations | OpenAPI | -| Consultation Retrieve, Existence Check, List, Search, Revision History, and Record Match | OpenAPI | +| Additional Consultation Existence Check, Revision History, and Record Match | OpenAPI | | GIS Query | OGC API Features | | Wallet-mediated Evidence | OpenID for Verifiable Credential Issuance and Presentation; W3C Verifiable Credentials | | Direct Evidence | OpenAPI with a signed credential or attestation format | diff --git a/spec/10-workflows.md b/spec/10-workflows.md index bc7b073..add162a 100644 --- a/spec/10-workflows.md +++ b/spec/10-workflows.md @@ -1,45 +1,137 @@ --- -description: Base Registry Profile interaction and outcomes. +description: Registry service discovery, current Record reads, exact lookup, and bounded collection pagination. --- # 10 Workflows -## 10.1 Retrieve the current permitted Record representation +## 10.1 Discover Registry services and their contracts -This workflow describes externally observable behaviour. It does not prescribe internal services, databases, policy engines, gateways, or deployment topology. +This workflow applies to every Registry BB implementation. A publisher can provide the metadata as static documents at a stable URI or through a metadata service. ### Actors -- **API Consumer:** requests a Record it is authorised to use. -- **Registry implementation:** resolves the current Record revision and returns the permitted representation. -- **Access decision service:** optional component used by the implementation to evaluate access and disclosure policy. +- **API Consumer:** discovers a Registry and determines which operations it exposes. +- **Registry metadata publisher:** publishes the Registry description and service descriptions. ### Preconditions -1. The Registry publishes the identity metadata required by Registry Core. -2. The API Consumer has the credentials and request context required by the deployment. -3. The current Record representation identifies its representation format, schema, semantic model, revision, lifecycle state, and minimum provenance. -4. The implementation can determine the permitted representation for the API Consumer and request context. +1. The consumer has a metadata entry point, such as a configured URI or a directory entry. +2. The consumer has any access needed to read the metadata and linked contracts. +3. The publisher provides the Registry metadata and service discovery required by Registry Core. ### Interaction -1. The API Consumer requests the current representation using a Record Identifier. -2. The Registry authenticates the caller and evaluates access and disclosure policy. -3. If the policy permits access, the Registry resolves the current revision and lifecycle state. -4. The Registry constructs the permitted representation, including the Record context required by Registry Core. -5. The Registry returns the permitted representation or the applicable unsuccessful outcome. +1. The consumer reads the machine-readable Registry description and selects the Registry by its stable identifier. +2. The consumer inspects its authority, authoritative scope statement, and referenced Digital Registries specification version. +3. The consumer follows the Registry's service associations and reads each service's identifier, API-family labels, endpoint URL, and operational-contract reference for the services available to that consumer's audience. +4. The consumer follows the operational contract to determine the collections, their Registry associations, exact operations, inputs, outputs, and access requirements. For HTTP APIs, this is an OpenAPI description unless the applicable binding defines an established protocol-native description. +5. The consumer selects a suitable operation, or determines that the required operation is unavailable. ### Outcomes | Condition | Observable outcome | |---|---| -| Current Record is accessible | Current permitted representation is returned. | -| Consumer has narrower disclosure rights | A valid filtered or redacted representation is returned. | -| Identifier is unknown | The implementation returns its unknown-identifier outcome. | -| Consumer may not learn whether a protected Record exists | The outcome is indistinguishable under the published contract from the unknown-identifier outcome, including the same status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values. Independently generated trace or correlation values may differ, and no Record-specific data is returned. | +| Required operation appears in a service's linked contract | The consumer can inspect how to invoke that operation. | +| A service declares a family but its contract does not offer the required operation | The consumer does not infer that operation from the family label. | +| A Registry BB service exposed to the metadata's intended audience is missing from the Registry description, or lacks its identifier, valid family labels, endpoint, or machine-readable contract | The service discovery requirement is not satisfied. | ### Postconditions -- The Record is not modified by the operation. -- The returned representation identifies the same Record Identifier requested by the consumer. -- A successful response identifies the Registry, current revision, lifecycle state, representation format, schema, semantic model, Registry Authority, and recording time. +- The consumer can distinguish the governed Registry, its authority, and its technical services. +- The consumer knows which operations are available from each service's operational contract. +- Family labels classify the service's operations. Capability claims follow the [conformance model](04-conformance.md#44-capability-claims). + +## 10.2 Retrieve the current permitted Record representation + +This workflow applies to implementations selecting Retrieve. The [HTTP binding](../api/openapi.yaml) defines request and response details. + +### Actors + +- **API Consumer:** requests a Record. +- **Registry implementation:** resolves the Record and applies access and disclosure policy. + +### Preconditions + +1. The published service contract exposes Retrieve and identifies its Registry, collection membership, and representation schema. +2. The consumer has the credentials and request context required by the deployment. + +### Interaction + +1. The consumer sends a request to the declared item path, such as `GET /v1/businesses/{recordId}`, with a Record Identifier within the Registry. +2. The Registry evaluates authentication, access, and disclosure policy. +3. The Registry resolves the current Record within the collection and constructs its permitted `{recordId, data}` representation. Current Records may include inactive Records. +4. The Registry returns that representation or the declared unsuccessful outcome. + +### Outcomes + +| Condition | Observable outcome | +|---|---| +| Current Record is accessible | The permitted representation is returned. | +| Consumer has narrower disclosure rights | The returned representation satisfies both disclosure policy and its schema. | +| Identifier is unknown, belongs to a Record outside the collection, or has protected existence | The same `record-not-available` outcome is returned. | + +### Postconditions + +- The source Record is unchanged. +- The returned identifier matches the requested identifier. +- Registry, schema, and authority context are unambiguous; any additional source metadata follows the published contract. + +## 10.3 Look up a Record using an exact selector + +This workflow applies to implementations selecting Lookup. + +### Preconditions + +1. The contract exposes a Lookup operation, such as `POST /v1/businesses:lookup`, and declares the collection and selector's typed components, comparison rules, and uniqueness scope. +2. The consumer has the required credentials and request context. + +### Interaction + +1. The consumer sends `{selector, values}` using the declared schema. A composite selector supplies every key component. +2. The Registry validates the input and evaluates access and disclosure policy. +3. The Registry resolves the selector within its declared scope, checks uniqueness, and applies collection membership. +4. One permitted match returns the common Record representation. Other outcomes follow the contract, including protected-existence handling and source uniqueness failures. + +### Postconditions + +- The source Record is unchanged. +- A successful Lookup returns the same Record schema and field meanings as other reads of that view. +- Multiple source matches fail without selecting an arbitrary Record. + +## 10.4 Page through a declared collection or search result + +This workflow applies independently to List and Search. For the business example, List uses `GET /v1/businesses`; Search uses `POST /v1/businesses:search`. + +### Preconditions + +1. The contract declares the collection or search, accepted inputs, deterministic ordering with a unique tie breaker, page limits, and cursor lifetime. +2. The consumer has the required credentials and request context. + +### Interaction + +1. The consumer sends the first request without a cursor, supplying the declared criteria and any supported ordering and page size. +2. The Registry validates the request, evaluates current access and disclosure policy, and returns `{items, pageInfo}`. Items use the Record schema for the selected view. +3. For a non-null `nextCursor`, the consumer repeats the criteria and ordering with that cursor. It may omit `pageSize` or repeat the effective size established by the first request. +4. The Registry reauthorizes the continuation and verifies its cursor binding, including the collection. An invalid, expired, or mismatched cursor produces the declared failure. +5. The consumer continues until `nextCursor` is `null`, including after short or empty Pages with a continuing cursor. + +### Outcomes and limits + +- Every Page respects the effective size bound; every continuation advances source processing. +- Live-data changes follow the published pagination and source-currency policy. +- An optional `pageInfo.total` is the exact count of the full permitted query at that Page's evaluation time. +- Revoked access applies to subsequent requests. A failed continuation allows the consumer to start a fresh request when permitted. + +## 10.5 Read a household and interpret its relationships + +This workflow uses the [household OpenAPI](../api/examples/household-registry.openapi.yaml). + +1. The consumer sends `GET /v1/households/{recordId}` and receives a household containing its declared address and membership components. +2. The consumer interprets membership attributes as relationship facts. A `membershipId` identifies a component within that household. +3. The `individualRef` field schema fixes the target Individuals Registry, allowing the reference to omit `registryId`. +4. Where an individual read is offered, the consumer follows the field's declared target collection and operation binding through the target Registry's published service contract. The binding explains how to use the reference as input; the consumer follows the operation's access requirements. +5. The related read follows the target's authorization and source-currency contract. An unavailable target leaves the household's membership facts unchanged. + +A predefined household view may instead include permitted individual summaries, with declared fields, bounds, and source currency. + +The [birth-registration OpenAPI](../api/examples/birth-registration.openapi.yaml) illustrates recorded parent details. `nameAtRegistration` belongs to the birth-registration Record, with an optional reference to the individual. Changes to the individual's current Record leave this recorded value unchanged; accepted corrections to the birth-registration source may update it. diff --git a/spec/11-testing.md b/spec/11-testing.md index 83def13..5ae6c8f 100644 --- a/spec/11-testing.md +++ b/spec/11-testing.md @@ -1,75 +1,139 @@ --- -description: Verification approach for the Base Registry Profile. +description: Draft verification of mandatory Registry discovery and selected capabilities. --- # 11 Testing ## 11.1 Test maturity -The requirements and tests in this release are DRAFT. The scenarios below define deterministic verification intent. No executable conformance suite is published for this release. +The scenarios below define verification intent for the [draft requirements](04-conformance.md#41-requirement-maturity). The [Consultation artifact checks](../api/README.md#validation) validate OpenAPI documents and schema fixtures. Implementation conformance requires separate evaluation of a deployed Registry; an executable suite is pending. Legacy Cucumber tests under `test/openAPI` remain migration evidence for the previous generated CRUD interface. -Legacy Cucumber tests under `test/openAPI` exercise the previous generated CRUD interface. They are retained as migration evidence and are not a conformance suite for this release. +## 11.2 Applicability and required fixtures -## 11.2 Required fixtures +Verification starts with an inventory of the Registry BB capabilities and services the implementation exposes to each intended metadata audience. Every evaluation covers Registry identity, authoritative scope, specification-version metadata, and service discovery. Capability-specific verification follows the implementation's selected capabilities and the [conformance model](04-conformance.md#43-conformance-model). -An implementation being evaluated provides non-production fixtures for: +Common Record representation requirements are evaluated through each implemented operation that returns Records, using that operation to obtain the fixtures. Identifier lifecycle evidence applies wherever the implementation assigns or maintains Record Identifiers. -- machine-readable Registry metadata; -- two distinct current Records in the same Registry; -- a current Record accessible to two consumers with different disclosure rights; -- evidence of the identifier lifecycle across successive revisions and retired Records; -- an unknown Record Identifier; -- a protected Record whose existence must not be disclosed; and -- each lifecycle state the Registry exposes through Retrieve. +An implementation being evaluated provides non-production fixtures according to the following applicability rules: -Testers use synthetic fixtures rather than real personal or confidential data. +| Fixture or evidence | Required when | +|---|---| +| Machine-readable Registry metadata, the inventory of exposed Registry BB services, and their linked machine-readable operational contracts | Every evaluation. | +| Two distinct current Records in the same Registry, with expected scoped identity, declared schema, and field meanings | An implemented operation returns Record representations. | +| Record fixtures covering each exposed lifecycle state | An implemented operation returns Record representations in those states. | +| Identifier policy and stability/non-reassignment evidence across source changes and retirement where supported | The implementation assigns or maintains Record Identifiers. | +| Source revision, lifecycle, and provenance evidence for metadata actually exposed | The operation or selected profile exposes or requires this metadata. | +| Consumer contexts and expected permitted representations | An implemented operation returns Record representations. | +| The same Record accessible to consumers with different disclosure rights | The applicable policy provides different disclosure entitlements. | +| An unknown Record Identifier and a known Record outside the selected collection where applicable | Retrieve is selected. | +| Distinct Records in different collections | A Registry exposes multiple collections. | +| One Record available through multiple collections or views | Collections overlap or expose distinct views of one Record. | +| Known, unknown, invalid, and composite selector inputs where supported; a simulated source uniqueness failure | Lookup is selected. | +| A protected and an unknown identifier or selector for the same consumer context | Retrieve or Lookup is selected and the applicable policy protects Record existence. | +| Zero-, one-, and multi-result collections; typed search criteria and invalid inputs; duplicate sort values where applicable | List or Search is selected, using fixtures relevant to each selected operation. | +| Continuations covering completion, mismatch, expiry, and access changes; a short or empty advancing page where supported | List or Search is selected. | +| Nested components, same-target and mixed-target references, and collection-boundary fixtures | A selected view exposes subobjects, references, or embedded collections. | +| Recorded related details and a separately changed current target Record; a parent without an individual reference where supported | A selected view exposes recorded related details or optional references. | + +Use synthetic fixtures and record the applicability rationale for each omitted conditional fixture. ## 11.3 Requirement traceability -| Requirement | Verification item | Expected result | -|---|---|---| -| `fr-core#req-1` | Inspect machine-readable Registry metadata and identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, and Digital Registries specification version are present. | -| `fr-core#req-2` | Retrieve two distinct Records | Each response includes the Registry Identifier and a different Record Identifier; each identifier pair is unique. | -| `fr-core#req-3` | Inspect the identifier policy and lifecycle evidence | A Record Identifier remains unchanged across revisions and lifecycle states, is not shared, and is not reassigned after retirement. | -| `fr-core#req-4` | Validate a retrieved representation | The representation format conveyed by the binding matches the representation, schema and semantic-model references resolve, and schema validation succeeds. | -| `fr-core#req-5` | Retrieve fixtures across exposed lifecycle states | Each response identifies the current revision and a lifecycle state permitted by its declared schema. | -| `fr-core#req-6` | Retrieve a known accessible Record | Registry Authority identifier and recording time are present. | -| `fr-consultation#req-1` | Retrieve a known accessible Record | Current permitted representation is returned with required Record context. | -| `fr-consultation#req-2` | Retrieve the same Record as two consumers | Each response contains only the projection permitted to that consumer. | -| `fr-consultation#req-3` | Retrieve unknown and protected identifiers as the same consumer | Status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values match; any differing trace or correlation values are independent of Record existence; neither response contains Record-specific data. | +| Requirement | Applicability | Verification item | Expected result | +|---|---|---|---| +| `fr-core#req-1` | Every implementation | Access machine-readable Registry metadata as an intended consumer and inspect identifier evidence | Globally unique and stable Registry Identifier, Registry name, Registry Authority, authoritative scope statement, and Digital Registries specification-version reference are present; the publication URI and access conditions are available to intended consumers. | +| `fr-core#req-2` | Each implemented operation returning Records | Obtain two distinct Record representations through that operation; compare collections where supported | Each representation includes a different Record Identifier and has unambiguous Registry context; each identifier pair is unique across the Registry, including its collections, without requiring repeated Registry fields. | +| `fr-core#req-3` | Implementations assigning or maintaining Record Identifiers | Inspect the identifier policy and lifecycle evidence | A Record Identifier remains unchanged across revisions and lifecycle states, is not shared, and is not reassigned after retirement. | +| `fr-core#req-4` | Each implemented operation returning Records | Validate a returned representation | The binding identifies the format and versioned resolvable schema, field meanings are documented, and validation succeeds. A separate formal semantic model is checked only when declared. Nested component and reference meanings, target Registry scope, related-read bindings where offered, and collection completeness are unambiguous. | +| `fr-core#req-5` | Source revision or lifecycle metadata is exposed or required by the selected profile | Obtain relevant Record fixtures and source evidence | Provided metadata has documented meaning, matches the source, and is not fabricated from an ETag or adapter fetch. Absence is valid for a profile that does not require it. | +| `fr-core#req-6` | Each implemented operation returning Records, with conditional checks for extra provenance | Obtain a known accessible Record and resolve its Registry context | Registry Authority resolves through metadata. Any additional provenance has documented semantics and matches source evidence; a recording timestamp is not fabricated from fetch time. | +| `fr-core#req-7` | Every implementation | Compare services exposed to each intended metadata audience with their published discovery metadata and linked operational contracts | Every exposed Registry BB service is identified, associated with its Registry, and declares valid API-family concepts, an endpoint URL, and a resolvable machine-readable operational contract. The contract describes the advertised endpoint and operations from each declared family; declarations reflect currently available services. | +| `fr-consultation#req-1` | Retrieve selected | Retrieve a known accessible Record and a Record outside the collection where applicable | A current permitted collection member returns its required Record context; a Record outside the collection returns `record-not-available`. | +| `fr-consultation#req-2` | Every selected Consultation read | Invoke fixtures under applicable consumer contexts; compare responses where entitlements differ | Each response contains only the projection permitted to that consumer, validates against its schema, and does not expose omitted values through related references, embedded fields, errors, or collection metadata. | +| `fr-consultation#req-3` | Retrieve or Lookup selected and policy protects Record existence | Resolve unknown and protected fixtures as the same consumer through each selected operation | Status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values match; any differing trace or correlation values are independent of Record existence; neither response contains Record-specific data. | +| `fr-consultation#req-4` | Lookup selected | Exercise each declared exact selector with known, unknown, invalid, and ambiguous source fixtures | One collection member resolves uniquely within the selector's declared scope; missing components and unknown inputs fail; no permitted collection match gives the declared unresolved outcome; multiple matches never return an arbitrary Record. | +| `fr-consultation#req-5` | List selected | List declared collections, including zero and one result and unsupported inputs | Results retain the Page shape, satisfy membership and disclosure, respect the page bound and declared order, and reject unsupported filters or sort. | +| `fr-consultation#req-6` | Search selected | Execute each declared search with valid, empty-result, and invalid criteria | Matching permitted Records use the same declared view; empty results retain the Page shape; unsupported searches and fields fail. | +| `fr-consultation#req-7` | List or Search selected | Traverse unchanged fixtures; test changed collection or criteria, expiry, page-size mismatch, and authorization changes | Traversal advances to a null cursor, preserves collection, query, and view, respects the fixed effective size, reauthorizes, and never silently restarts. Optional totals match the full permitted query at evaluation. | The abbreviated references in this table use the full `govstack-bb-digital-registries` namespaces defined under [Registry Core](05-api-families/registry-core.md#registry-core-functional-requirements) and [Consultation](05-api-families/consultation.md#retrieve-functional-requirements). ## 11.4 Behaviour scenarios +The discovery scenarios apply to every implementation. Read scenarios apply to their selected capabilities. Disclosure differences, protected existence, exposed metadata, and bounded-scan behavior additionally require the corresponding conditions in section 11.2. + ```gherkin -Feature: Retrieve the current permitted Registry Record - - Scenario: Authorised consumer retrieves a current Record - Given a current Record with a stable Record Identifier - And an API Consumer authorised to receive its standard representation - When the consumer retrieves the Record by that identifier - Then the Registry returns the current permitted representation - And the representation identifies its Registry, revision, lifecycle state, representation format, schema, semantic model, Registry Authority, and recording time - And the retrieval does not modify the Record - - Scenario: Consumers receive different permitted representations - Given two API Consumers with different disclosure entitlements - When each consumer retrieves the same Record - Then each response contains only the fields and metadata permitted for that consumer - - Scenario: A protected Record cannot be enumerated through errors - Given a consumer that is not authorised to know whether a protected Record exists - And an unknown Record Identifier - When the consumer requests the protected and unknown Record Identifiers - Then both responses use the same status or protocol outcome - And both responses use the same security-relevant response metadata, stable error type, response structure, and non-Record-specific values - And any differing trace or correlation values are generated independently of Record existence - And neither response contains Record-specific data +Feature: Discover Registry services and their operational contracts + + Scenario: Every exposed service can be discovered + Given an inventory of the Registry BB services exposed to an intended metadata audience + When a consumer reads the published Registry metadata + Then the metadata identifies the Registry, its authority, authoritative scope, and specification version + And every exposed service is associated with that Registry + And each service has an identifier and declares valid API-family concepts, an endpoint URL, and a machine-readable operational contract + And each linked contract describes the advertised endpoint and operations belonging to each declared family + And the declarations reflect the services currently available to that audience + + Scenario: Discover the operations offered by an Evidence service + Given a Registry description linked to an Evidence service + And the service contract exposes Evidence operations without Retrieve + When a consumer inspects the service metadata and contract + Then the consumer identifies the Evidence operations offered by that service + And no Retrieve operation is identified in that service's contract + And the Evidence family label is treated as a service classification rather than a capability conformance claim + + Scenario: The operational contract determines operation availability + Given a service labelled with the Consultation API family + And its operational contract does not include Retrieve + When a consumer checks whether Retrieve is available + Then the consumer finds no Retrieve operation in that service's contract + + Scenario: A missing operational contract fails service discovery verification + Given an exposed Registry BB service associated with its Registry + And the service declares an API-family concept and endpoint URL + But it does not provide a machine-readable operational contract + When its metadata is evaluated against the service discovery requirement + Then that requirement is not satisfied ``` +The following cases apply to the selected read capabilities. Run them against each operation and view to which their fixtures apply. + +| Case | Exercise | Expected evidence | +|---|---|---| +| Current Retrieve | Read a known accessible Record, including an exposed inactive state. | Stable identifier, valid permitted representation, declared source currency, and an unchanged source Record. | +| Collection scope | Retrieve a known Record through a collection that excludes it. | The same `record-not-available` outcome as an unknown identifier. | +| Identity across collections | Read one Record through multiple collections or views, and compare distinct Records across collections in the same Registry. | The same Record retains its identifier; distinct Records have different identifiers within the Registry. | +| Collection methods | Retrieve Records whose identifiers are `lookup`, `lookups`, or `search`, where the identifier syntax permits them, and invoke the collection's `:lookup` or `:search` operation. | Item retrieval and collection methods route independently. | +| Disclosure | Read the same Record under different disclosure entitlements. | Each response matches the permitted fields and metadata for its consumer. | +| Protected existence | Retrieve and Look up unknown and protected fixtures as the same consumer. | Both produce the same contract-defined unresolved outcome and security-relevant content; independently generated trace values may differ. | +| Exact Lookup | Submit known, unknown, incomplete, incorrectly typed, and unsupported selector inputs, including composite keys where declared. | One permitted Record for a valid unique match; declared unresolved or validation errors otherwise. | +| Selector uniqueness failure | Supply source data with multiple matches for a unique selector. | The declared failure, with protected-existence policy applied and no arbitrary Record selected. | +| Empty and single-result collections | List and Search fixtures containing zero and one permitted match. | The Page shape is retained; completed results have `nextCursor: null`. | +| Complete traversal | Traverse an unchanged collection with duplicate primary sort values. | Every matching permitted Record appears once in the declared order; every Page respects the size bound and the last cursor is null. | +| Bounded source scan | Process a bounded source region with no permitted matches and unprocessed source state remaining. | A short or empty Page may carry a cursor that advances source processing. | +| Cursor binding | Change collection, criteria, search, ordering, view, or effective page size while reusing a cursor. | The invalid-cursor outcome, with no silent restart. | +| Continuation size | Omit `pageSize`, then repeat the original effective size on another continuation. | Both retain the bound size. | +| Cursor validity | Submit malformed, tampered, and expired cursors. | The invalid-cursor outcome. | +| Authorization change | Revoke access between Pages. | Subsequent requests enforce current authorization before releasing results. | +| Total | Compare any reported `total` on a later Page with the full permitted query. | An exact count at that Page's evaluation time, including matches before the cursor. | +| Live source changes | Insert, update, and remove source Records between Pages. | Observed results match the published currency and pagination policy. | +| Query disclosure | Compare unknown and protected-only query fixtures where match existence is protected. | Items, counts, and continuation patterns preserve the disclosure policy. | +| Unsupported input | Submit undeclared Search names, criteria, List parameters, and sort choices. | The declared validation error. | + +Relationship cases apply to views exposing the corresponding shapes. The [household](../api/examples/household-registry.openapi.yaml) and [birth-registration](../api/examples/birth-registration.openapi.yaml) contracts provide concrete examples; their [fixtures](../api/examples/relationship-exchanges.json) cover schema validation. + +| Case | Exercise | Expected evidence | +|---|---|---| +| Nested components | Read a household with an address and memberships. | Components validate with their declared field meanings and local identifier scope. | +| Fixed-target reference | Validate an individual reference with omitted, matching, and conflicting `registryId`. | Omitted or matching values resolve to the schema-declared Registry; a conflicting value fails validation. | +| Mixed-target reference | Validate a reference whose field allows multiple Registries. | The reference identifies its target Registry; omission fails validation. | +| Related read binding | Follow a reference for which the contract offers a related read. | The declared target collection, operation contract, and input mapping determine the request without parsing the opaque Record Identifier. | +| Recorded parent details | Change the individual's current name while leaving the birth registration unchanged. | The birth registration retains `nameAtRegistration`; a permitted parent component may omit its individual reference. | +| Complete array boundary | Exceed the response bound of a view declaring a complete memberships array. | The declared failure, with no truncated array presented as complete. | +| Related disclosure | Read a household with restricted individual or relationship fields. | References, embedded values, omissions, arrays, and completeness metadata satisfy the consumer's disclosure policy. | + ## 11.5 Evidence retained for audit -Verification evidence identifies the Digital Registries specification version tested. It also includes fixture definitions, requests, responses, schema-validation results, identifier-lifecycle evidence, and a traceability report mapping every evaluated requirement to a pass or fail result. +Retain the specification version, selected capabilities, exposed services, published metadata and contracts, and a requirement traceability report with pass, fail, or not-applicable results and applicability rationales. Applicable evidence includes fixtures, requests and responses, schema-validation results, source mapping and currency, pagination and disclosure outcomes, and identifier lifecycle evidence. -No fixed response-time threshold, container technology, administrative user interface, Information Mediator header, or test tool is part of the target Base Registry Profile. +Record artifact validation separately from deployed implementation results. diff --git a/spec/12-other-resources.md b/spec/12-other-resources.md index 66bcf89..fe4c188 100644 --- a/spec/12-other-resources.md +++ b/spec/12-other-resources.md @@ -1,41 +1,53 @@ --- -description: Coverage, decisions, migration material, and references. +description: Coverage, reader guidance, migration material, and references. --- # 12 Other Resources ## 12.1 Coverage and limitations -The 3.0.0-alpha.2 specification provides a minimum Registry model and DRAFT requirements. It does not provide a certification-ready API contract. +The 3.0.0-alpha.2 specification provides the Registry model, DRAFT Core requirements, and DRAFT requirements and an HTTP contract for Consultation Retrieve, Lookup, List, and Search. Additional capabilities remain informative. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines its conformance status and dependency on the GovStack Common Requirements Framework. -| Included in this release | Not specified in this release | +| Area | Published material | Not specified or published | +|---|---|---| +| Conformance | DRAFT model of Registry Core plus at least one declared capability, with capability-specific applicability | Approved conformance claims and named multi-family conformance profiles | +| Registry Core | DRAFT requirements for metadata, scoped Record identity, schema context, documented field meanings, and the interpretation of optional source metadata | Complete schema lifecycle and domain-specific compatibility policies | +| Metadata and discovery | DCAT-based model, vocabulary, JSON-LD context, and examples | Vocabulary and context publication at the assigned `vocab.govstack.global` IRIs; canonical specification-version IRIs; metadata HTTP binding and executable validation shape | +| Authority | Registry Authority identity and declared authoritative scope | Delegation, shared responsibility, and a machine-readable mandate model | +| Capabilities | DRAFT Consultation Retrieve, Lookup, List, and Search requirements; informative descriptions of other capabilities | Requirements, contracts, and tests for other capabilities, including Revision History | +| Service interfaces | [Canonical draft Consultation OpenAPI](../api/openapi.yaml), shared schemas, and [concrete example contracts](../api/examples/README.md) | Canonical contracts for other API families | +| Verification | Discovery, Retrieve, Lookup, and pagination workflows; verification scenarios; contract and example checks | End-to-end implementation conformance suite | +| Migration | Disposition of every previous DRS requirement | None | + +Domain-specific semantic models and jurisdiction-specific governance or legal compliance are outside the Building Block's standardisation scope. Registry Authorities and adopting ecosystems supply these as appropriate to their services. Field meanings must be documented even when no formal semantic model is selected. Source revision, lifecycle state, and source recording time remain optional unless a selected profile or capability requires them. + +Identity Federation profile ownership and binding remain subject to agreement with the Identity team. + +## 12.2 Reading guide + +| Topic | Reference | |---|---| -| Registry scope and exclusions | Final capability-discovery format | -| Base Registry Profile | Canonical HTTP path and JSON schema | -| Registry Core DRAFT requirements | Revision History contract and tests | -| Consultation Retrieve DRAFT requirements | Optional-family requirements and tests | -| Conceptual external data model | Named multi-family conformance profiles | -| Retrieve workflow and verification intent | Domain-specific semantic models | -| Complete disposition of previous DRS requirements | Jurisdiction-specific governance or legal compliance | - -## 12.2 Specification decisions - -- The specification defines the external service behaviour of a Digital Registries implementation for records under a Registry Authority's declared scope. It does not prescribe a database platform. -- The target Base Registry Profile consists of Registry Core plus Consultation Retrieve. -- Retrieve returns a permitted representation and does not imply public or complete-record access. -- Existence Check, List, Search, Revision History, Record Match, and GIS Query are distinct optional Consultation sub-patterns. -- Additional API families remain informative until each has requirements, a contract, and tests. -- DCAT 3 is the primary candidate for a future Registry and service discovery profile. Specialised DCAT profiles may inform individual mappings but are not conformance dependencies for this alpha. -- Internal storage, administrative UI, deployment topology, multi-tenancy, and automatic API generation are implementation choices. -- Domain data models are selected and declared by the Registry Authority rather than standardised by the Building Block. -- Authentication protecting Registry APIs is distinct from the candidate Identity Federation family. Ownership of that family remains subject to agreement with the Identity team. +| Service boundary, implementation choices, and neighbouring Building Blocks | [Description and Scope](02-description-and-scope.md) | +| Minimum conformance and capability claims | [Conformance](04-conformance.md) | +| Registry identity, authoritative scope, datasets, and DCAT composition | [Registry Core metadata](05-api-families/registry-core.md#registry-metadata) | +| Service discovery and linked operational contracts | [API family discovery](05-api-families/registry-core.md#api-family-discovery) and [Service Interfaces](09-service-interfaces.md) | +| Shared Record context and domain semantics | [Registry Core](05-api-families/registry-core.md#common-record-context) | +| Capability boundaries and selection | [API Families](05-key-functionalities.md) | +| Retrieve, exact Lookup, List, Search, and additional read patterns | [Consultation](05-api-families/consultation.md) | +| HTTP contract and shared representation/pagination rules | [Service Interfaces](09-service-interfaces.md) and [canonical OpenAPI](../api/openapi.yaml) | +| Structured values and references | [Core representation rules](05-api-families/registry-core.md#structured-values-and-references) and [OpenAPI examples](../api/examples/README.md) | +| Concrete adopter schema and fixtures | [Business Registry schema](../api/examples/business-registry.schema.json) and [request/response fixtures](../api/examples/consultation-exchanges.json) | +| Sectoral authentication and cross-Building-Block ownership | [Identity Federation](05-api-families/identity-federation.md) | +| Verification scenarios | [Testing](11-testing.md) | ## 12.3 Migration and history - [Migration from the 3.0.0-alpha.1 Draft](12-other-resources/migration-from-3.0.md) records the disposition of every previous DRS requirement. - [Release Notes](01-version-history/release-notes.md) preserve detailed historical contributors and changes. -The OpenAPI files under `api/legacy/generated-crud/` and Cucumber scenarios under `test/openAPI/` describe the previous generated CRUD interface. They are legacy artifacts and are not service contracts or conformance tests for this release. +The OpenAPI files under `api/legacy/generated-crud/` and Cucumber scenarios under `test/openAPI/` describe the previous generated CRUD interface. They are legacy artifacts and are not service contracts or conformance tests for this release. The legacy OpenAPI files do not contain a Retrieve-by-Identifier operation. + +The [Testing chapter](11-testing.md) distinguishes artifact validation from deployed implementation evidence. ## 12.4 Reference architecture and implementation guidance diff --git a/spec/12-other-resources/migration-from-3.0.md b/spec/12-other-resources/migration-from-3.0.md index bed4541..21b2408 100644 --- a/spec/12-other-resources/migration-from-3.0.md +++ b/spec/12-other-resources/migration-from-3.0.md @@ -18,18 +18,18 @@ The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data |---|---| | DRS-1 Create Registries | Registry identity, authority, classification, and lifecycle metadata inform Registry Core. Registry creation and schema configuration move to optional Provisioning. Storage-profile choices are retired. | | DRS-2 Multiple Databases | Mandatory multi-database, foreign-key, graph, and UI-navigation behaviour is retired. Relationships belong to the selected semantic model or implementation guidance. | -| DRS-3 Database Schema | Schema declaration and validation are retained conceptually. Schema authoring and field configuration move to optional Provisioning. The fixed field-type and UI-widget catalogue is retired. | +| DRS-3 Database Schema | Machine-readable representation schemas and documented field meanings are retained. Registry and schema context may be conveyed through the endpoint, versioned contract, or response as the binding specifies. Schema authoring and field configuration move to optional Provisioning. The fixed field-type and UI-widget catalogue is retired. | | DRS-4 Publishing and Versioning | Schema lifecycle and compatibility remain relevant to future Provisioning. Schema publication is decoupled from automatic endpoint-version generation. Deletion of old schemas is not carried forward. | | DRS-5 APIs | Split across Consultation, Write, Notification, and Provisioning. Automatic creation, copying, hiding, and deletion of CRUD endpoints is retired. | | DRS-6 Authorisation and Access Control | General authentication and access control inherit from GovStack CFR. Policy-based permitted representations are retained in Consultation. RBAC, ABAC, PBAC, consent, and anonymous-role internals are not prescribed. | -| DRS-7 Logging and Auditing | Record revision and provenance inform Registry Core. Principal-facing access history moves to Access Transparency. Generic security logging inherits from CFR. Blockchain is not a conformance mechanism. | +| DRS-7 Logging and Auditing | Registry Core defines the meaning of supplied source revision and provenance metadata; it does not require an adapter to invent missing values. Principal-facing access history moves to Access Transparency. Generic security logging inherits from CFR. Blockchain is not a conformance mechanism. | | DRS-8 Personal Data Usage | Access-event concepts move to Access Transparency. The fixed `PersonalDataID` log structure and optional device fingerprint are not retained. | -| DRS-9 Database Views | Saved views may inform optional List or Search. Open-data publication requires an explicit disclosure policy and is not equated with anonymous access. | +| DRS-9 Database Views | Defined views inform the independently optional List and Search capabilities, which now have DRAFT requirements and a shared pagination contract. Open-data publication requires an explicit disclosure policy and is not equated with anonymous access. | | DRS-10 Export Schema | Moves to optional Provisioning. File formats will be defined by an applicable binding or guide. | | DRS-11 Import Schema | Moves to optional Provisioning. File formats will be defined by an applicable binding or guide. | | DRS-12 Service Usage Statistics | Generic monitoring inherits from CFR. Administrative analytics are implementation guidance. Logging every search term is not a default requirement. | | DRS-13 Personal Data Field | Sensitivity and classification metadata remain relevant through CFR and declared schemas. UI-specific field marking is retired. | -| DRS-14 Personal Data Identifier | Stable identifier concepts are retained, while Record, foundational, functional, and domain identifiers are distinguished. Federation behaviour is tracked under the candidate Identity Federation family pending a cross-BB ownership decision. | +| DRS-14 Personal Data Identifier | Stable identifier concepts are retained, including suitable source identifiers unique within an unambiguous Registry context. Record, foundational, functional, and domain identifiers remain distinct. Federation behaviour is tracked under the candidate Identity Federation family pending a cross-BB ownership decision. | | DRS-15 Secret Field | Classification, encryption, and transport security inherit from CFR. Policy-driven redaction is retained in Consultation. The credit-card and mandatory Information Mediator examples are removed. | | DRS-16 Read Schema in UI | Machine-readable schema declaration is retained. Administrative UI presentation is implementation guidance. | | DRS-17 Field Properties and Triggers | Validation constraints inform schemas and optional Provisioning. UI widgets, database relationships, and embedded trigger scripting are implementation choices. | @@ -38,7 +38,7 @@ The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data | DRS-20 Schema Templates | Registry templates and marketplaces are implementation guidance, not interoperability requirements. | | DRS-21 View Data | Record access moves to Consultation and audit visibility to Access Transparency. Grid, detail, and document views are implementation choices. | | DRS-22 Edit Data | Record mutation moves to Write. Deletion inherits CFR lifecycle rules where applicable. Editing UI behaviour is implementation guidance. | -| DRS-23 Search Helpers | Filtering, full-text search, and ordering move to optional List and Search sub-patterns. UI behaviour is not retained. | +| DRS-23 Search Helpers | Declared filters, search criteria, and ordering move to independently optional List and Search capabilities with DRAFT requirements. Exact domain-identifier resolution is Lookup. Full-text or approximate matching and a general query language are not mandatory. UI behaviour is not retained. | | DRS-24 Import Data | Bulk import moves to optional Provisioning or an applicable Write profile. CSV and spreadsheet UI behaviour is guidance. | | DRS-25 Export Data | Bulk export moves to optional Provisioning or Consultation profiles. General portability inherits from CFR. | | DRS-26 Statistical Queries | Moves to optional Aggregate Data. Dashboards and report designers are implementation guidance. | @@ -46,34 +46,47 @@ The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data | DRS-28 Create Registry by API | Duplicate of the provisioning aspect of DRS-1. Moves to optional Provisioning. | | DRS-29 Multiple Registries by API | Duplicate of DRS-2. Mandatory multi-tenancy is retired. | | DRS-30 Publish Registry by API | Duplicate of DRS-4. Moves to optional Provisioning. | -| DRS-31 Modify APIs | Duplicate of DRS-5. Only abstract capability declaration is retained; generated-API product behaviour is retired. | -| DRS-32 Schema and API Discovery | Machine-readable contract and capability discovery are retained as design goals. Full schema administration is optional Provisioning. The [Registry Core metadata model](../05-api-families/registry-core.md#registry-metadata) establishes a minimal conceptual DCAT composition, while its serialisation and validation remain unspecified in this release. | -| DRS-33 Applicant CRUD | Split across mandatory Consultation Retrieve, optional Consultation sub-patterns, and optional Write. The Applicant CRUD framing is retired. | -| DRS-34 Swagger Service List | Machine-readable service contracts are retained. Swagger UI and live production examples are not conformance requirements. Protocol-native bindings depend on the GovStack framework update. | +| DRS-31 Modify APIs | Duplicate of DRS-5. Capability declaration and linked operational contracts are retained in Core; generated-API product behaviour is retired. | +| DRS-32 Schema and API Discovery | Machine-readable Registry and service metadata publication is required by the DRAFT Core requirements, including API-family classifications, endpoints, and linked operational contracts. Full schema administration is optional Provisioning. The [Registry Core metadata model](../05-api-families/registry-core.md#registry-metadata) defines the DCAT composition; executable conformance validation is not published in this release. | +| DRS-33 Applicant CRUD | Split across independently optional Consultation Retrieve, Lookup, List, and Search, and optional Write. The Applicant CRUD framing is retired. | +| DRS-34 Swagger Service List | Machine-readable service contracts are retained, including a canonical draft Consultation OpenAPI contract. Swagger UI and live production examples are not conformance requirements. Other protocol-native bindings depend on the applicable GovStack framework rules. | | DRS-35 Personal Data Usage API | Duplicate of DRS-8. Moves to Access Transparency and is generalised from a person-specific identifier to a Record Principal. | | DRS-36 Statistical Queries API | Moves to optional Aggregate Data. | | DRS-37 Data Owner Access Log | Duplicate of DRS-8 and DRS-35. Moves to Access Transparency and is generalised to a Record Principal. | ## Replacement index -The following DRAFT requirements carry forward the interoperability intent that remains in the Base Registry Profile. A previous requirement can map to more than one replacement because the earlier product-oriented clauses combined several concerns. +The following DRAFT requirements carry forward the interoperability intent in Registry Core and independently optional Consultation Retrieve, Lookup, List, and Search. Core requirements for returned Records apply when a selected capability returns Records. A previous requirement can map to more than one replacement because the earlier product-oriented clauses combined several concerns. | Current target | Principal predecessors | |---|---| | `fr-core#req-1` Registry metadata | DRS-1, DRS-32, DRS-34 | -| `fr-core#req-2` Record identification | DRS-14, DRS-33 | -| `fr-core#req-3` Record Identifier preservation | DRS-14, DRS-33 | -| `fr-core#req-4` Schema, semantic-model, and representation-format identification | DRS-3, DRS-4, DRS-16, DRS-17, DRS-32, DRS-34 | -| `fr-core#req-5` Revision and lifecycle-state identification | DRS-4, DRS-7, DRS-14 | -| `fr-core#req-6` Minimum provenance | DRS-7, DRS-21, DRS-33 | +| `fr-core#req-2` Record identification within Registry context | DRS-14, DRS-33 | +| `fr-core#req-3` Record Identifier stability | DRS-14, DRS-33 | +| `fr-core#req-4` Representation schema and field meanings | DRS-3, DRS-4, DRS-16, DRS-17, DRS-32, DRS-34 | +| `fr-core#req-5` Meaning of supplied revision and lifecycle metadata | DRS-4, DRS-7, DRS-14 | +| `fr-core#req-6` Meaning of supplied Record provenance | DRS-7, DRS-21, DRS-33 | +| `fr-core#req-7` Service discovery | DRS-5, DRS-31, DRS-32, DRS-34 | | `fr-consultation#req-1` Retrieve by identifier | DRS-5, DRS-21, DRS-33 | | `fr-consultation#req-2` Permitted representation | DRS-6, DRS-15, DRS-21, DRS-27, DRS-33 | | `fr-consultation#req-3` Protected-existence handling | DRS-6, DRS-15, DRS-33 | +| `fr-consultation#req-4` Exact selector Lookup | DRS-5, DRS-14, DRS-23, DRS-33 | +| `fr-consultation#req-5` Bounded List | DRS-9, DRS-21, DRS-23, DRS-33 | +| `fr-consultation#req-6` Search using declared criteria | DRS-9, DRS-23, DRS-33 | +| `fr-consultation#req-7` Bounded result continuation | DRS-9, DRS-23, DRS-25, DRS-33 | -Concepts moved to capability families without requirements in this release retain no normative force. Provisioning carries DRS-1, DRS-3, DRS-4, DRS-10, DRS-11, DRS-17, DRS-24, DRS-28, and DRS-30. Consultation List or Search carries DRS-9 and DRS-23. Write carries DRS-22 and relevant parts of DRS-24. Notification carries DRS-19. Aggregate Data carries DRS-26 and DRS-36. Access Transparency carries DRS-8, DRS-35, and DRS-37. Evidence carries the relevant disclosure aspects of DRS-27. The candidate Identity Federation family tracks relevant identifier-federation aspects of DRS-14 and DRS-27 pending agreement with the Identity team on profile ownership. +Concepts moved to capability families without requirements in this release retain no normative force. Provisioning carries DRS-1, DRS-3, DRS-4, DRS-10, DRS-11, DRS-17, DRS-24, DRS-28, and DRS-30. Write carries DRS-22 and relevant parts of DRS-24. Notification carries DRS-19. Aggregate Data carries DRS-26 and DRS-36. Access Transparency carries DRS-8, DRS-35, and DRS-37. Evidence carries the relevant disclosure aspects of DRS-27. The candidate Identity Federation family tracks relevant identifier-federation aspects of DRS-14 and DRS-27 pending agreement with the Identity team on profile ownership. All remaining retired or guidance-only clauses have the exact disposition recorded in the table above. +## Current draft read contract + +The [canonical Consultation OpenAPI contract](../../api/openapi.yaml) replaces the legacy generated CRUD interface for the current draft. Retrieve and List use GET; exact Lookup and Search use POST request bodies. The four capabilities are independently optional. No QUERY method, CQL2 implementation, or general query engine is required. + +The common Record shape is `{recordId, data}`. A Page contains `{items, pageInfo: {nextCursor, total?}}` and reuses that Record shape for the same response view. Continuation repeats the criteria and ordering with a fixed effective page size. Live pagination does not promise a source snapshot; totals are optional and, when supplied, exact for the current authorized result at the declared evaluation point. + +These choices accompany the API Design Guide `0.2.0-draft` work and remain part of `3.0.0-alpha.2`. No release or conformance certification is implied. Draft contract and example checks validate artifacts; an end-to-end implementation conformance suite is not yet published. + ## Legacy service contracts and tests The previous artifacts are not suitable as contracts for this release: diff --git a/spec/12-other-resources/read-api-design-decisions.md b/spec/12-other-resources/read-api-design-decisions.md new file mode 100644 index 0000000..55e8173 --- /dev/null +++ b/spec/12-other-resources/read-api-design-decisions.md @@ -0,0 +1,91 @@ +--- +description: Choices and guide refinements behind the first Consultation HTTP binding. +--- + +# Read API design decisions + +Status: accepted direction for the September 2026 draft. The requirements and [HTTP contract](../../api/openapi.yaml) remain DRAFT. + +## A practical shared read contract + +The binding defines four independently selectable read capabilities. A concrete Registry or sector contract supplies domain fields, views, selectors, and searches that map to its source operations. + +| Choice | Rationale | +|---|---| +| Record containing `recordId` and `data` | A common identity and data boundary, with Registry and schema context supplied by the endpoint and published contract. | +| Conditional source metadata | Adapters expose available source revisions, lifecycle states, and provenance with documented meanings. | +| Exact Lookup | A declared unique selector supports alternate-key access to one Record. | +| Named, typed Search | Published criteria describe the searches supported by the source. | +| Schema-defined subobjects and relationships | Domain components, references, and related-data views retain their domain meanings. | +| Shared Record and Page shapes | Consumers use the same Record view across selected operations. | +| GET Retrieve/List and POST Lookup/Search | Established HTTP tooling, with selectors and search criteria carried in request bodies. | +| Versioned, typed collections | One API can expose several domain collections with explicit Registry and schema bindings. | +| Collection methods `:lookup` and `:search` | Read actions have distinct routes while all valid Record Identifiers remain addressable. | +| Live cursor pagination | Bounded traversal in a deterministic order, adaptable to source continuation mechanisms. | +| Fixed effective page size | Stable page sizing supports adapters over source page or offset mechanisms. | +| Continuing short or empty Pages | Bounded source processing can advance independently of the number of permitted results. | + +## Standards reused and alternatives considered + +The contract uses [OpenAPI 3.1.2](https://spec.openapis.org/oas/v3.1.2.html), JSON Schema, [HTTP semantics](https://www.rfc-editor.org/rfc/rfc9110.html), and [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457.html) with GovStack extensions. A `rel="describedby"` link follows the [JSON Schema rule](https://json-schema.org/draft/2020-12/json-schema-core#section-9.5.1.1) by identifying a schema for the complete retrieved representation. + +| Alternative | Decision | +|---|---| +| [JSON:API 1.1](https://jsonapi.org/format/1.1/) | Select a small Record envelope and the guide's Page convention. Lookup and Search still need domain-specific input contracts. | +| [HTTP QUERY, RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html) | Use GET and read-only POST for current tooling compatibility; reconsider QUERY with deployment evidence. | +| Common expression language | Select named, typed searches for the baseline. Domain capabilities may adopt an expression language. | + +## Resource paths, identity, and API composition + +The API major version precedes resource collections, following established conventions illustrated by [Google AIP-185](https://google.aip.dev/185). An OpenAPI server URL supplies the deployment root and any stable routing prefix. For example, server `https://example.org/registry` and path `/v1/households/{recordId}` produce `https://example.org/registry/v1/households/{recordId}`. + +The reference binding uses the collection name `records`; concrete contracts publish domain names such as `businesses`, `individuals`, `households`, and `land-parcels`. Each collection declares its Registry association, membership, capabilities, and representation schemas. API-family classifications describe operations in metadata and contracts; they impose no URL prefix. + +Lookup and Search use the collection custom-method notation from [Google AIP-136](https://google.aip.dev/136): + +```http +GET /v1/households/{recordId} +GET /v1/households +POST /v1/households:lookup +POST /v1/households:search +``` + +This keeps collection methods distinct from item paths: a Record whose identifier is `search` remains available at `/v1/households/search`. OpenAPI gives [concrete paths precedence over templated paths](https://spec.openapis.org/oas/v3.1.2.html#paths-object), making a concrete `/households/search` route problematic for such identifiers. The broader guide permits both custom methods and action sub-resources; Consultation selects custom methods for Lookup and Search. + +Collection membership scopes every read. Retrieve and Lookup use the unavailable-Record outcome for Records outside that collection, and continuation binds the collection as well as the query. Identity remains `(registryId, recordId)` across collections and views. Source adapters disambiguate overlapping keys for distinct Records in the same Registry with stable identifiers. Field bindings identify target read operations and input mappings for resolvable references. + +The resource structure supports later family bindings as follows. These are composition principles; each family's contract defines its operations. + +| Area | Composition principle | +|---|---| +| Write | Retrieve and update can share a Record URI through different HTTP methods. Write defines its own input schemas and permissions; a permitted read view does not establish an update payload. Governed requests and asynchronous operations can have their own resources. | +| Provisioning and Notification | The API contract coordinates Record collection names with schema, subscription, and other supporting-resource paths. | +| Evidence and events | Record references retain Registry and Record identity. Evidence and event formats use the representations defined by their bindings. | +| Versioning | The major version applies to one API surface. Independently exposed APIs can version separately while retaining stable Registry and Record identity. | +| Protocol-specific families | Bindings such as credential issuance or identity federation follow their protocols' endpoint and versioning conventions. | + +## Relationship identity, snapshots, and completeness + +The [Core representation rules](../05-api-families/registry-core.md#structured-values-and-references) distinguish owned components, Record references, and related-data views across API families. The [household contract](../../api/examples/household-registry.openapi.yaml) embeds membership attributes and references individual Records. The [birth-registration contract](../../api/examples/birth-registration.openapi.yaml) owns recorded parent details, with optional individual references. + +Each view declares array bounds and completeness for the permitted representation. A complete array exceeding its bound follows the declared failure contract. A separately paginated relationship collection has its own published operation. + +## Explicit cross-BB guide refinements + +These general refinements belong to guide and ruleset `0.2.0-draft`; the guide's `draft-changes.md` records their details. Shared schema artifacts remain independently versioned at `0.1.0-draft`. + +| Guide area | General refinement | Registry binding choice | +|---|---|---| +| §10.1, identifiers | Stable source-owned keys with documented uniqueness scope. | Non-personal `recordId` unique within its Registry. | +| §9.8, extensibility | Extensible response resources, strict operation arguments, and schema-defined nesting. | Closed Lookup/Search inputs and additive response fields. | +| §2.6 and §5.1, deployment roots and versions | Major version in resource paths; shared API surfaces can expose multiple collections and families. | Deployment root plus `/v1/businesses`, `/v1/households`, or another declared collection. | +| §5.3 and §5.8, custom methods | Colon custom methods alongside action sub-resources, with distinct resource and method naming conventions. | `/v1/records:lookup` and `/v1/records:search` in the reference binding. | +| §6.6, body-based reads | Exact single-result POST Lookup alongside collection Search. | Typed request bodies and synchronous `200` results. | +| §12, pagination | Declared page-size policy, advancing short or empty Pages, and explicit embedded-array completeness. | Fixed size within a live traversal; optional exact totals. | +| §10, domain schemas | Explicit ownership of adopted domain schemas and applicable inherited requirements. | A data schema and documented field meanings for each view. | +| §2.3 and §3.3, historical artifacts | Explicit separation of legacy contracts from current surfaces. | Previous generated CRUD contracts retained as migration evidence. | +| §4.6 and §20, draft validation | Draft requirement mappings and artifact checks distinguished from active conformance coverage. | DRAFT read coverage and contract/example checks. | + +## Verification and follow-up boundary + +[Testing](../11-testing.md) separates artifact validation from deployed implementation evidence. The [concrete OpenAPI examples](../../api/examples/README.md) support contract review. Implementing selected operations over breg and a registry with a different source model will provide evidence about mapping effort, schema publication, and bounded continuation. diff --git a/spec/12-other-resources/references.md b/spec/12-other-resources/references.md index abf6004..3ed254d 100644 --- a/spec/12-other-resources/references.md +++ b/spec/12-other-resources/references.md @@ -14,7 +14,15 @@ description: Standards and related material relevant to Digital Registries. These references inform the capability direction. Only the requirements and canonical service contracts published by this specification determine conformance. -- [OpenAPI Specification](https://spec.openapis.org/oas/) +- [OpenAPI Specification 3.1.2](https://spec.openapis.org/oas/v3.1.2.html) +- [JSON Schema Draft 2020-12](https://json-schema.org/draft/2020-12) +- [Schema.org data model](https://schema.org/docs/datamodel.html) +- [EU SEMIC Core Vocabularies](https://interoperable-europe.ec.europa.eu/collection/semic-support-centre/solution/core-vocabularies) +- [PublicSchema](https://publicschema.org/about/) and its [published schema formats](https://publicschema.org/docs/jsonld-vc-guide/) +- [RFC 9110: HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html) +- [RFC 9457: Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457.html) +- [RFC 10008: The HTTP QUERY Method](https://www.rfc-editor.org/rfc/rfc10008.html), considered for a future binding +- [JSON:API 1.1](https://jsonapi.org/format/1.1/), considered as an alternative representation convention - [RFC 9727: api-catalog Well-Known URI and Link Relation](https://www.rfc-editor.org/rfc/rfc9727.html) - [RFC 9264: Linkset Media Types and Link Relation](https://www.rfc-editor.org/rfc/rfc9264.html) - [W3C Data Catalog Vocabulary (DCAT) 3](https://www.w3.org/TR/vocab-dcat-3/) diff --git a/spec/README.md b/spec/README.md index 210662d..479753f 100644 --- a/spec/README.md +++ b/spec/README.md @@ -6,23 +6,25 @@ description: Version 3.0.0-alpha.2 `govstack-bb-digital-registries-3.0.0-alpha.2 extends govstack-cfr-2.1.0` -> **Alpha specification.** Its requirements are classified as DRAFT and do not establish a GovStack certification claim. Implementers should use the latest approved Digital Registries specification for procurement or certification. +The Digital Registries Building Block defines interoperable behaviour for software that maintains authoritative records about persons, organisations, places, assets, or events. It specifies a mandatory Registry Core and a catalogue of optional capabilities that an implementation may support. -The Digital Registries Building Block defines interoperable behaviour for software that maintains authoritative records about persons, organisations, places, assets, or events. It specifies a minimum Base Registry Profile and a catalogue of additional capabilities that an implementation may support. +The conformance model combines Registry Core, including machine-readable Registry and service metadata, with at least one declared Registry capability. API families and operations are optional. The specification does not prescribe a database product, administrative user interface, storage model, deployment topology, or domain data model. -The Base Registry Profile consists of Registry Core behaviour and the ability for an authorised API consumer to retrieve the current permitted representation of a record by its stable identifier. The specification does not prescribe a database product, administrative user interface, storage model, deployment topology, or domain data model. +The current draft defines Consultation Retrieve, Lookup, List, and Search as independently optional capabilities, with a common Record representation and bounded collection pagination. [Service Interfaces](09-service-interfaces.md) introduces the canonical draft HTTP contract. Registry and schema context can be supplied through the response, endpoint, or versioned contract as the binding specifies. Source revision, lifecycle, and recording-time metadata are optional unless a selected profile or capability requires them. + +For this alpha's maturity and conformance status, see [Requirement Maturity](04-conformance.md#41-requirement-maturity). [Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) describes the available specifications and artifacts. ## How to use this specification - **Government architects** should begin with [Description and Scope](02-description-and-scope.md) and [Conformance](04-conformance.md) to determine where a Registry fits within a digital government architecture. -- **Procurement teams** can use the alpha to understand the intended profile structure, but should cite an approved specification version in a tender or acceptance contract. -- **Implementers** can use the DRAFT requirements, Registry Core model, capability descriptions, and workflow for prototyping. This alpha does not publish an implementation contract. -- **Conformance testers** can use [Testing](11-testing.md) to assess verification intent. This alpha does not publish a conformance suite or permit capability claims. +- **Procurement teams** should use [Conformance](04-conformance.md) to understand capability claims and cite an approved specification version in a tender or acceptance contract. +- **Implementers** should begin with [Registry Core](05-api-families/registry-core.md), then consult the selected [API families](05-key-functionalities.md) and [Service Interfaces](09-service-interfaces.md). The [illustrative business Registry contract](../api/examples/business-registry.openapi.yaml) shows a concrete mapping. +- **Conformance testers** should use [Testing](11-testing.md) for verification scenarios and their applicability. -## Status and authorship +## Authorship -This alpha is structured around a domain-neutral Registry Core, mandatory Consultation Retrieve, and optional capability families. Earlier contributions, authors, coordinators, editors, and reviewers remain recorded in the [Version History](01-version-history.md) and [Release Notes](01-version-history/release-notes.md). +Contributions, authors, coordinators, editors, and reviewers are recorded in the [Version History](01-version-history.md) and [Release Notes](01-version-history/release-notes.md). -_**Coordinating authors of the 3.0.0-alpha.2 work:**_ Sebastian Leidig, Jeremi Joslin, and David Higgins +_**Coordinating authors (3.0.0-alpha.2):**_ Sebastian Leidig, Jeremi Joslin, and David Higgins -
Digital Registries Building Block capability families
The target Base Registry Profile combines Registry Core with Consultation Retrieve.
+
Digital Registries Building Block capability families
The conformance model combines mandatory Registry Core with at least one selected capability.
diff --git a/spec/SUMMARY.md b/spec/SUMMARY.md index 3829506..ba16bfd 100644 --- a/spec/SUMMARY.md +++ b/spec/SUMMARY.md @@ -21,4 +21,5 @@ * [11 Testing](11-testing.md) * [12 Other Resources](12-other-resources.md) * [Migration from 3.0.0-alpha.1](12-other-resources/migration-from-3.0.md) + * [Read API design decisions](12-other-resources/read-api-design-decisions.md) * [References](12-other-resources/references.md) diff --git a/test/README.md b/test/README.md index aa3a86b..c721768 100644 --- a/test/README.md +++ b/test/README.md @@ -1,5 +1,7 @@ # Test artifacts -The `openAPI/` directory contains the conformance harness for the generated CRUD interface used by earlier Digital Registries releases. It is retained as migration evidence and is not the 3.0.0-alpha.2 conformance suite. +The [Consultation validator](../tools/validate_consultation.py) checks the canonical transport and the Business, Household and Birth Registration contracts. It also checks domain schemas, inline examples and exchange fixtures, including rejection cases for invalid inputs and references. -Draft verification intent and requirement traceability are documented in [the Testing chapter](../spec/11-testing.md). No executable conformance tests for the 3.0.0-alpha.2 specification are published. +Run the [documented validation commands](../api/README.md#validation). Deployment behavior and audit evidence are covered by [the Testing chapter](../spec/11-testing.md). + +The `openAPI/` directory retains the earlier generated CRUD harness as migration evidence. diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/tools/requirements-api.txt b/tools/requirements-api.txt new file mode 100644 index 0000000..df82ea5 --- /dev/null +++ b/tools/requirements-api.txt @@ -0,0 +1,7 @@ +# Exact tool versions used to validate the draft Consultation artifacts. +openapi-spec-validator==0.9.0 +jsonschema==4.26.0 +PyYAML==6.0.3 +referencing==0.37.0 +# Enables JSON Schema's IRI format assertion instead of silently skipping it. +rfc3987-syntax==1.1.0 diff --git a/tools/validate_consultation.py b/tools/validate_consultation.py new file mode 100644 index 0000000..28335d6 --- /dev/null +++ b/tools/validate_consultation.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python3 +"""Validate the current Consultation contracts and their concrete examples. + +Run from the repository root: + uv run --with-requirements tools/requirements-api.txt python tools/validate_consultation.py + +This checks artifacts and schema acceptance/rejection, not deployed authorization, +source matching, cursor integrity/expiry, bounded work, or disclosure behavior. +It reads only explicitly named current artifacts and their local dependencies. +""" + +from __future__ import annotations + +from copy import deepcopy +import json +from pathlib import Path +import re +import unittest +from urllib.parse import unquote, urldefrag, urljoin, urlparse + +from jsonschema import Draft202012Validator, FormatChecker +from openapi_spec_validator import validate +from referencing import Registry, Resource +from referencing.jsonschema import DRAFT202012 +import yaml + + +API = Path(__file__).resolve().parents[1] / "api" +CANONICAL = API / "openapi.yaml" +BUSINESS = API / "examples/business-registry.openapi.yaml" +BINDING = API / "examples/business-registry.schema.json" +HOUSEHOLD = API / "examples/household-registry.openapi.yaml" +BIRTH = API / "examples/birth-registration.openapi.yaml" +RELATIONSHIPS = API / "examples/relationship-examples.schema.json" +OPENAPI_DOCUMENTS = (CANONICAL, BUSINESS, HOUSEHOLD, BIRTH) +SCHEMA_DOCUMENTS = (BINDING, RELATIONSHIPS) +DOCUMENTS: dict[str, dict] = {} + + +def load_local(uri: str) -> Resource: + """Resolve shipped references without network access or legacy inspection.""" + parsed = urlparse(uri) + if parsed.scheme != "file" or parsed.netloc: + raise ValueError(f"Only local contract references are permitted: {uri}") + source = Path(unquote(parsed.path)).resolve() + if not source.is_relative_to(API) or source.is_relative_to(API / "legacy"): + raise ValueError("Contract reference leaves current API artifacts") + if uri not in DOCUMENTS: + DOCUMENTS[uri] = yaml.safe_load(source.read_text()) + return Resource.from_contents(DOCUMENTS[uri], default_specification=DRAFT202012) + + +REGISTRY = Registry(retrieve=load_local) + + +def document(path: Path) -> dict: + return load_local(path.as_uri()).contents + + +def validator(path: Path, pointer: str) -> Draft202012Validator: + return Draft202012Validator( + {"$ref": path.as_uri() + "#" + pointer}, + registry=REGISTRY, + format_checker=FormatChecker(), + ) + + +def pointer_key(key: str) -> str: + return str(key).replace("~", "~0").replace("/", "~1") + + +def nodes(value, pointer=""): + if isinstance(value, dict): + yield pointer, value + for key, child in value.items(): + yield from nodes(child, pointer + "/" + pointer_key(key)) + elif isinstance(value, list): + for index, child in enumerate(value): + yield from nodes(child, pointer + "/" + str(index)) + + +def resolve_object(path: Path, value: dict) -> tuple[Path, dict]: + """Resolve OpenAPI Reference Objects while preserving the correct file base.""" + while "$ref" in value: + reference, fragment = urldefrag(value["$ref"]) + path = (path.parent / reference).resolve() if reference else path + value = document(path) + for token in fragment.lstrip("/").split("/") if fragment else []: + value = value[token.replace("~1", "/").replace("~0", "~")] + return path, value + + +class ConsultationContractTests(unittest.TestCase): + def test_required_format_checkers_are_available(self): + self.assertIn("iri", FormatChecker().checkers, + "Install tools/requirements-api.txt so Registry IRI formats are asserted") + + def test_openapi_and_local_schema_documents(self): + for path in OPENAPI_DOCUMENTS: + with self.subTest(path=path.name): + validate(document(path), base_uri=path.as_uri()) + for path in SCHEMA_DOCUMENTS: + Draft202012Validator.check_schema(document(path)) + for schema in document(CANONICAL)["components"]["schemas"].values(): + Draft202012Validator.check_schema(schema) + + def test_all_inline_schema_and_media_examples(self): + count = 0 + for path in (*OPENAPI_DOCUMENTS, *SCHEMA_DOCUMENTS): + for pointer, node in nodes(document(path)): + if isinstance(node.get("examples"), list): + for example in node["examples"]: + with self.subTest(file=path.name, pointer=pointer): + validator(path, pointer).validate(example) + count += 1 + if "schema" in node: + examples = [] + if "example" in node: + examples.append(node["example"]) + if isinstance(node.get("examples"), dict): + examples.extend(e["value"] for e in node["examples"].values() if "value" in e) + for example in examples: + with self.subTest(file=path.name, pointer=pointer): + validator(path, pointer + "/schema").validate(example) + count += 1 + self.assertGreater(count, 30, "The current request, response and domain examples must be exercised") + + def test_published_exchanges_use_actual_operation_schemas(self): + spec = document(BUSINESS) + operations = { + operation["operationId"]: (path, method, operation) + for path, item in spec["paths"].items() + for method, operation in item.items() + if method in ("get", "post") + } + exchanges = json.loads((API / "examples/consultation-exchanges.json").read_text())["exchanges"] + for exchange in exchanges: + path, method, operation = operations[exchange["operationId"]] + base = "/paths/" + pointer_key(path) + "/" + method + with self.subTest(exchange=exchange["name"]): + if "request" in exchange: + validator(BUSINESS, base + "/requestBody/content/application~1json/schema").validate(exchange["request"]) + response_path, response = resolve_object(BUSINESS, operation["responses"][str(exchange["status"])]) + media = "application/json" if exchange["status"] < 400 else "application/problem+json" + schema = response["content"][media]["schema"] + Draft202012Validator( + {**schema, "$ref": urljoin(response_path.as_uri(), schema["$ref"])}, + registry=REGISTRY, + format_checker=FormatChecker(), + ).validate(exchange["response"]) + if exchange["status"] >= 400: + self.assertEqual(exchange["response"]["status"], exchange["status"]) + + def test_exact_selectors_reject_incomplete_or_undeclared_keys(self): + check = validator(BINDING, "/$defs/BusinessLookupRequest") + valid = {"selector": "byJurisdictionNumber", "values": {"jurisdictionCode": "AA", "localNumber": "00000042"}} + check.validate(valid) + invalid = [ + {"selector": "byJurisdictionNumber", "values": {"localNumber": "00000042"}}, + {"selector": "byJurisdictionNumber", "values": {"jurisdictionCode": "AA", "localNumber": 42}}, + {"selector": "byRegistrationNumber", "values": {"registrationNumber": "br-000042"}}, + {"selector": "byRegistrationNumber", "values": {"registrationNumber": "BR-000042\n"}}, + {"selector": "byJurisdictionNumber", "values": {"jurisdictionCode": "AA\n", "localNumber": "00000042"}}, + {"selector": "byJurisdictionNumber", "values": {"jurisdictionCode": "AA", "localNumber": "00000042\n"}}, + {"selector": "byRegistrationNumber", "values": valid["values"]}, + {"selector": "byRegistrationNumber", "values": {"registrationNumber": "BR-000042", "legalName": "Example Ltd"}}, + {"selector": "byUnknownKey", "values": {"key": "42"}}, + {"selector": "byRegistrationNumber", "values": {}}, + {**valid, "pageSize": 1}, + ] + for value in invalid: + with self.subTest(value=value): + self.assertFalse(check.is_valid(value)) + # A different deployment can bind a context-only selector with values:{}. + validator(CANONICAL, "/components/schemas/LookupRequest").validate({"selector": "byVerifiedCaller", "values": {}}) + + def test_declared_search_rejects_unbounded_and_undeclared_inputs(self): + check = validator(BINDING, "/$defs/BusinessSearchRequest") + valid = {"search": "byRegistrationStatus", "criteria": {"registrationStatus": "DISSOLVED"}} + check.validate(valid) + invalid = [ + {**valid, "filter": "registrationStatus eq 'DISSOLVED'"}, + {**valid, "sort": "recordId"}, + {**valid, "search": "anyExpression"}, + {**valid, "criteria": {"registrationStatus": "DISSOLVED", "legalName": "Example Ltd"}}, + {**valid, "criteria": {"registrationStatus": None}}, + {**valid, "pageSize": 0}, + {**valid, "pageSize": 101}, + {**valid, "cursor": ""}, + {**valid, "cursor": "opaqueCursor\n"}, + {**valid, "cursor": None}, + ] + for value in invalid: + with self.subTest(value=value): + self.assertFalse(check.is_valid(value)) + + self.assertFalse(validator(CANONICAL, "/components/schemas/Sort").is_valid("recordId\n")) + + def test_fixed_view_and_additive_envelope(self): + check = validator(BINDING, "/$defs/BusinessRecord") + record = {"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}} + check.validate(record) + check.validate({**record, "additionalEnvelopeMetadata": "future declared field"}) + self.assertFalse(check.is_valid({**record, "recordId": "r_42\n"})) + for data in ({"registrationStatus": "DISSOLVED"}, {**record["data"], "undeclaredPrivateField": "value"}, {**record["data"], "legalName": 42}): + self.assertFalse(check.is_valid({**record, "data": data})) + + def test_custom_methods_preserve_opaque_identifier_routes(self): + bindings = ((CANONICAL, "records"), (BUSINESS, "businesses"), + (HOUSEHOLD, "households"), (BIRTH, "birth-registrations")) + for contract, collection in bindings: + spec = document(contract) + collection_path = "/v1/" + collection + retrieve_path = collection_path + "/{recordId}" + self.assertEqual(spec["servers"][0]["url"], "https://{gatewayHost}") + self.assertIn("get", spec["paths"][retrieve_path]) + for source_id in ("lookup", "lookups", "search"): + with self.subTest(contract=contract.name, recordId=source_id): + validator(CANONICAL, "/components/schemas/RecordId").validate(source_id) + requested_path = collection_path + "/" + source_id + # Compare path templates before method dispatch: literal paths can + # shadow a Retrieve template even when they only declare POST. + matches = [] + for path in spec["paths"]: + pattern = "".join("[^/]+" if part.startswith("{") else re.escape(part) + for part in re.split(r"(\{[^{}]+\})", path)) + if re.fullmatch(pattern, requested_path): + matches.append(path) + self.assertEqual(matches, [retrieve_path]) + if contract in (CANONICAL, BUSINESS): + for suffix in ("lookup", "search"): + self.assertIn("post", spec["paths"][collection_path + ":" + suffix]) + concrete_operations = [operation["operationId"] + for contract in (BUSINESS, HOUSEHOLD, BIRTH) + for path, item in document(contract)["paths"].items() + if path.startswith("/v1/") + for method, operation in item.items() + if method in ("get", "post")] + self.assertEqual(len(concrete_operations), len(set(concrete_operations)), + "Collection operations must remain unique when composing these examples into one API") + + def test_page_completion_and_bounds(self): + check = validator(BINDING, "/$defs/BusinessPage") + check.validate({"items": [], "pageInfo": {"nextCursor": "opaqueContinuation"}}) + check.validate({"items": [], "pageInfo": {"nextCursor": None, "total": 0}}) + for page_info in ({}, {"nextCursor": ""}, {"nextCursor": "invalid+cursor"}, + {"nextCursor": "opaqueCursor\n"}, + {"nextCursor": "a" * 4097}, {"hasMore": False}, + {"nextCursor": None, "total": 1.5}): + self.assertFalse(check.is_valid({"items": [], "pageInfo": page_info})) + item = {"recordId": "r_42", "data": {"legalName": "Example Ltd", "registrationStatus": "DISSOLVED"}} + self.assertFalse(check.is_valid({"items": [item] * 101, "pageInfo": {"nextCursor": None}})) + exchanges = json.loads((API / "examples/consultation-exchanges.json").read_text())["exchanges"] + search_id = document(BUSINESS)["paths"]["/v1/businesses:search"]["post"]["operationId"] + pages = [e for e in exchanges if e["operationId"] == search_id] + first, final = pages + self.assertEqual(first["response"]["items"], []) + self.assertEqual(first["response"]["pageInfo"]["nextCursor"], final["request"]["cursor"]) + self.assertEqual(first["request"]["search"], final["request"]["search"]) + self.assertEqual(first["request"]["criteria"], final["request"]["criteria"]) + self.assertNotIn("pageSize", final["request"], "Example must exercise omission reusing the bound size") + self.assertLessEqual(len(final["response"]["items"]), first["request"]["pageSize"]) + self.assertIsNone(final["response"]["pageInfo"]["nextCursor"]) + + def test_error_examples_match_http_status_and_namespace(self): + for name, response in document(CANONICAL)["components"]["responses"].items(): + media = response.get("content", {}).get("application/problem+json") + if not media: + continue + examples = [media["example"]] if "example" in media else [e["value"] for e in media["examples"].values()] + for example in examples: + with self.subTest(response=name): + self.assertTrue(example["type"].startswith("https://govstack.global/problems/digital-registries/")) + self.assertNotIn("code", example) + self.assertNotIn("timestamp", example) + for item in document(CANONICAL)["paths"].values(): + for method, operation in item.items(): + if method not in ("get", "post"): + continue + for status, declared in operation["responses"].items(): + if declared.get("$ref") == "#/components/responses/" + name: + self.assertEqual(example["status"], int(status)) + + def test_relationship_fixtures_use_concrete_schemas(self): + fixtures = json.loads((API / "examples/relationship-exchanges.json").read_text())["examples"] + for fixture in fixtures: + with self.subTest(fixture=fixture["name"]): + validator(RELATIONSHIPS, "/$defs/" + fixture["schema"]).validate(fixture["value"]) + if "contract" in fixture: + contract = API / "examples" / fixture["contract"] + self.assertIn(contract, OPENAPI_DOCUMENTS) + matches = [(path, method, operation) + for path, item in document(contract)["paths"].items() + for method, operation in item.items() + if method in ("get", "post") and operation["operationId"] == fixture["operationId"]] + self.assertEqual(len(matches), 1) + path, method, operation = matches[0] + status = str(fixture["status"]) + media = operation["responses"][status]["content"]["application/json"] + pointer = "/paths/" + pointer_key(path) + "/" + method + "/responses/" + status + "/content/application~1json/schema" + validator(contract, pointer).validate(fixture["value"]) + self.assertEqual(media["example"], fixture["value"], "Operation example and response fixture must agree") + for contract, collection in ((HOUSEHOLD, "households"), (BIRTH, "birth-registrations")): + operation = document(contract)["paths"]["/v1/" + collection + "/{recordId}"]["get"] + parameters = [resolve_object(contract, p)[1] for p in operation["parameters"]] + self.assertFalse(any(p["in"] == "query" for p in parameters), "These Retrieve contracts serve their declared fixed views") + + def test_reference_context_rejects_ambiguous_or_conflicting_targets(self): + fixed = validator(RELATIONSHIPS, "/$defs/IndividualReference") + explicit = validator(RELATIONSHIPS, "/$defs/UnscopedRecordReference") + target = "https://registry.example/registries/individuals" + fixed.validate({"recordId": "person_42"}) + fixed.validate({"recordId": "person_42", "registryId": target}) + explicit.validate({"recordId": "person_42", "registryId": target}) + explicit.validate({"recordId": "r_7", "registryId": "urn:example:registry:external"}) + explicit.validate({"recordId": "r_7", "registryId": "urn:example:registre:état-civil"}) + for value in ({"recordId": "person_42", "registryId": "https://registry.example/registries/other"}, + {"registryId": target}, {"recordId": ""}, + {"recordId": "person_42", "href": "https://registry.example/person_42"}): + with self.subTest(fixed_target=value): + self.assertFalse(fixed.is_valid(value)) + for value in ({"recordId": "person_42"}, {"registryId": target}, + {"recordId": "person_42", "registryId": "/registries/individuals"}, + {"recordId": "person_42", "registryId": "urn:example:invalid registry"}, + {"recordId": "person_42", "registryId": "https://registry.example/%invalid"}, + {"recordId": "person_42", "registryId": 42}): + with self.subTest(unscoped_target=value): + self.assertFalse(explicit.is_valid(value)) + + def test_household_nested_types_and_profile_bounds(self): + check = validator(RELATIONSHIPS, "/$defs/HouseholdRecord") + record = deepcopy(document(RELATIONSHIPS)["$defs"]["HouseholdRecord"]["examples"][0]) + check.validate(record) + check.validate({**record, "additionalEnvelopeMetadata": "future declared field"}) + invalid_data = [ + {**record["data"], "address": "12 Example Street"}, + {**record["data"], "address": {"addressLines": [12], "locality": "Example Town"}}, + {**record["data"], "address": {"addressLines": ["Line"] * 4, "locality": "Example Town"}}, + {**record["data"], "address": {"addressLines": ["Line"], "locality": "Example Town", "postalCode": 120}}, + {**record["data"], "memberships": {}}, + {**record["data"], "memberships": [{"membershipId": "m_1", "role": "MEMBER", "individualRef": "person_42"}]}, + {**record["data"], "memberships": [{"role": "MEMBER", "individualRef": {"recordId": "person_42"}}]}, + {**record["data"], "memberships": [{"membershipId": "m_1", "role": 1, "individualRef": {"recordId": "person_42"}}]}, + {**record["data"], "memberships": [{"membershipId": "m_" + str(i), "role": "MEMBER", "individualRef": {"recordId": "person_" + str(i)}} for i in range(21)]}, + {**record["data"], "include": "individuals"}, + ] + for data in invalid_data: + with self.subTest(data=data): + self.assertFalse(check.is_valid({**record, "data": data})) + + def test_registration_snapshots_do_not_require_parent_references(self): + parent_check = validator(RELATIONSHIPS, "/$defs/ParentAtRegistration") + parent_check.validate({"nameAtRegistration": "Alex Example"}) + parent_check.validate({"nameAtRegistration": "Robin Example", "individualRef": {"recordId": "person_57"}}) + for value in ({"individualRef": {"recordId": "person_57"}}, + {"nameAtRegistration": "Robin Example", "individualRef": None}, + {"nameAtRegistration": "Robin Example", "individualRef": {"recordId": "person_57", "registryId": "urn:example:wrong-registry"}}, + {"nameAtRegistration": 57}): + self.assertFalse(parent_check.is_valid(value)) + record_check = validator(RELATIONSHIPS, "/$defs/BirthRegistrationRecord") + record = deepcopy(document(RELATIONSHIPS)["$defs"]["BirthRegistrationRecord"]["examples"][0]) + record_check.validate(record) + self.assertEqual(set(record), {"recordId", "data"}, "The example must not require source metadata enrichment") + self.assertFalse(record_check.is_valid({**record, "data": {**record["data"], "parents": [{"nameAtRegistration": "Example"}] * 5}})) + self.assertFalse(record_check.is_valid({**record, "data": {**record["data"], "dateOfBirth": "2020-02-30"}})) + + +if __name__ == "__main__": + unittest.main(verbosity=2) From 035a15ab0b30afe5bfbca0dc3345b203677cecc0 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 9 Sep 2026 16:06:18 +0700 Subject: [PATCH 08/10] feat: bind operations to Registry context and adopt RFC 9727 discovery Every Record-returning operation declares registry, collection, capability and view with x-govstack-digital-registries so a validator can link a read to the authority in the published metadata. Discovery moves to the /.well-known/api-catalog linkset, which the API design guide already permits, replacing the root /catalog recommendation. Consultation owns its HTTP binding; chapter 9 keeps operational contracts and protocol options. Signed-off-by: Jeremi Joslin --- api/README.md | 17 +- api/coverage.yaml | 5 +- api/examples/README.md | 15 +- api/examples/api-catalog.linkset.json | 31 ++++ api/examples/birth-registration.openapi.yaml | 5 + api/examples/business-registry.openapi.yaml | 20 ++ api/examples/household-registry.openapi.yaml | 5 + api/examples/registry-metadata.jsonld | 76 ++++++++ api/extensions/registry-metadata.schema.json | 122 +++++++++++++ .../x-govstack-digital-registries.schema.json | 30 +++ api/openapi.yaml | 20 ++ spec/03-terminology.md | 5 +- spec/04-conformance.md | 2 +- spec/05-api-families/consultation.md | 126 ++++++++----- spec/05-api-families/provisioning.md | 2 +- spec/05-api-families/registry-core.md | 131 +++++++++++--- spec/09-service-interfaces.md | 69 +------ spec/10-workflows.md | 9 +- spec/11-testing.md | 3 +- spec/12-other-resources.md | 4 +- spec/12-other-resources/references.md | 1 + spec/README.md | 2 +- tools/requirements-api.txt | 1 + tools/validate_consultation.py | 171 +++++++++++++++++- 24 files changed, 717 insertions(+), 155 deletions(-) create mode 100644 api/examples/api-catalog.linkset.json create mode 100644 api/examples/registry-metadata.jsonld create mode 100644 api/extensions/registry-metadata.schema.json create mode 100644 api/extensions/x-govstack-digital-registries.schema.json diff --git a/api/README.md b/api/README.md index a3425ba..ded2219 100644 --- a/api/README.md +++ b/api/README.md @@ -25,10 +25,15 @@ path. API-family labels describe capabilities; families can share resource paths with distinct HTTP methods, schemas, and access requirements. The shared Record schemas apply the [Registry Core](../spec/05-api-families/registry-core.md) -representation rules. Core metadata is published separately as a static document or -catalogue entry. It identifies the Registry and its authority and links each service -to its deployed OpenAPI contract. Together, the metadata and selected Consultation -operations provide the Core + Consultation contract. +representation rules. Core metadata is published as a JSON-LD document that the +RFC 9727 `/.well-known/api-catalog` linkset locates. It identifies the Registry and +its authority and links each service to its deployed OpenAPI contract. Every +Record-returning operation declares its Registry, collection, capability, and view +with the `x-govstack-digital-registries` extension. Together, the metadata and +selected Consultation operations provide the Core + Consultation contract. + +[extensions/](extensions/) holds the JSON Schemas for the extension and for the +compacted metadata document. A deployment publishes its selected operations with concrete schemas for `data`, selector values, search criteria, and supported sorting. Its contract @@ -43,7 +48,9 @@ schemas for local reference resolution. ## Validation From the repository root, validate the four OpenAPI documents, domain schemas, -inline examples, and positive and negative fixtures: +inline examples, positive and negative fixtures, the Registry context extension +of every operation, and the discovery examples against their schemas and the +Registry Core page: ```sh uv run --with-requirements tools/requirements-api.txt python tools/validate_consultation.py diff --git a/api/coverage.yaml b/api/coverage.yaml index 6f83d39..ac937f7 100644 --- a/api/coverage.yaml +++ b/api/coverage.yaml @@ -22,7 +22,10 @@ draftRequirements: rationale: Review any provided provenance against source evidence and declared semantics; the minimal read binding requires no provenance enrichment. - id: govstack-bb-digital-registries-fr-core#req-7 disposition: non-api - rationale: Verify that published service discovery metadata identifies the scoped registry, selected capabilities and operational contract. + rationale: Verify that published service discovery metadata identifies the scoped registry, selected capabilities and operational contract, and that /.well-known/api-catalog links the metadata document and the contract. + - id: govstack-bb-digital-registries-fr-core#req-8 + disposition: operation + operations: [retrieveRecord, lookupRecord, listRecords, searchRecords] - id: govstack-bb-digital-registries-fr-consultation#req-1 disposition: operation operations: [retrieveRecord] diff --git a/api/examples/README.md b/api/examples/README.md index 8fa54ff..653c20c 100644 --- a/api/examples/README.md +++ b/api/examples/README.md @@ -8,8 +8,9 @@ These illustrative deployments specialize the [Consultation contract](../openapi | [Household registry](household-registry.openapi.yaml) | `/v1/households` | Retrieve | Address, memberships, and individual references | | [Birth registration](birth-registration.openapi.yaml) | `/v1/birth-registrations` | Retrieve | Birth details and recorded parent information | -Each contract publishes its Registry context, schemas, source currency, access -policy, limits, and response examples. The business contract also defines exact +Each contract declares its Registry, collection, capability, and view on every +operation with `x-govstack-digital-registries`, and publishes schemas, source +currency, access policy, limits, and response examples. The business contract also defines exact and composite selectors, a typed status search, and live cursor pagination. The examples use `https://registry.example` as their API root. A deployment can @@ -35,6 +36,16 @@ containing Record views. | [Business Record and request schemas](business-registry.schema.json) | [Consultation exchanges](consultation-exchanges.json) | | [Household, birth-registration, and reference schemas](relationship-examples.schema.json) | [Relationship exchanges](relationship-exchanges.json) | +## Discovery + +| Artifact | Purpose | +| --- | --- | +| [Registry metadata](registry-metadata.jsonld) | Compacted JSON-LD document for the business Registry, validated against the [metadata document schema](../extensions/registry-metadata.schema.json) | +| [API catalog linkset](api-catalog.linkset.json) | RFC 9727 `/.well-known/api-catalog` response linking the three contracts and the metadata document | + +The Registry Core page embeds both documents; the validator checks that the +embedded copies and these files are identical. + Named exchanges represent independent fixture states, except `emptySearchContinuation` and `finalSearchPage`, which form one traversal. Example cursors are illustrative values. diff --git a/api/examples/api-catalog.linkset.json b/api/examples/api-catalog.linkset.json new file mode 100644 index 0000000..f4cdad9 --- /dev/null +++ b/api/examples/api-catalog.linkset.json @@ -0,0 +1,31 @@ +{ + "linkset": [ + { + "anchor": "https://registry.example/", + "service-desc": [ + { + "href": "https://registry.example/contracts/1.0.0-draft/examples/business-registry.openapi.yaml", + "type": "application/vnd.oai.openapi", + "title": "Business Registry Consultation API" + }, + { + "href": "https://registry.example/contracts/business-write.openapi.json", + "type": "application/vnd.oai.openapi+json", + "title": "Business Registry Write API" + }, + { + "href": "https://registry.example/contracts/business-evidence.openapi.json", + "type": "application/vnd.oai.openapi+json", + "title": "Business Registry Evidence API" + } + ], + "service-meta": [ + { + "href": "https://registry.example/catalog", + "type": "application/ld+json", + "title": "Registry metadata for the Business Registry" + } + ] + } + ] +} diff --git a/api/examples/birth-registration.openapi.yaml b/api/examples/birth-registration.openapi.yaml index b061242..5ec9ea8 100644 --- a/api/examples/birth-registration.openapi.yaml +++ b/api/examples/birth-registration.openapi.yaml @@ -53,6 +53,11 @@ paths: optional related Record identity. Absent Records, Records outside this collection and protected existence share 404 record-not-available. tags: [Consultation] + x-govstack-digital-registries: + registry: https://registry.example/registries/birth-registrations + collection: birth-registrations + capability: retrieve + view: birth-registration-with-recorded-parents parameters: - $ref: '../openapi.yaml#/components/parameters/RecordId' - $ref: '../openapi.yaml#/components/parameters/Traceparent' diff --git a/api/examples/business-registry.openapi.yaml b/api/examples/business-registry.openapi.yaml index 32331e1..763f6ba 100644 --- a/api/examples/business-registry.openapi.yaml +++ b/api/examples/business-registry.openapi.yaml @@ -61,6 +61,11 @@ paths: share 404 record-not-available. The response uses no-store. tags: - Consultation + x-govstack-digital-registries: + registry: https://registry.example/registries/business + collection: businesses + capability: retrieve + view: business-public parameters: - $ref: ../openapi.yaml#/components/parameters/RecordId - $ref: ../openapi.yaml#/components/parameters/Traceparent @@ -104,6 +109,11 @@ paths: effective pageSize. Only nextCursor null ends traversal. tags: - Consultation + x-govstack-digital-registries: + registry: https://registry.example/registries/business + collection: businesses + capability: list + view: business-public parameters: - $ref: ../openapi.yaml#/components/parameters/Traceparent - $ref: ../openapi.yaml#/components/parameters/PageSize @@ -150,6 +160,11 @@ paths: 422. Protected-existence policy applies before Record-specific diagnostics. tags: - Consultation + x-govstack-digital-registries: + registry: https://registry.example/registries/business + collection: businesses + capability: lookup + view: business-public parameters: - $ref: ../openapi.yaml#/components/parameters/Traceparent requestBody: @@ -222,6 +237,11 @@ paths: invalid-cursor. tags: - Consultation + x-govstack-digital-registries: + registry: https://registry.example/registries/business + collection: businesses + capability: search + view: business-public parameters: - $ref: ../openapi.yaml#/components/parameters/Traceparent requestBody: diff --git a/api/examples/household-registry.openapi.yaml b/api/examples/household-registry.openapi.yaml index 4b88303..a0d2f73 100644 --- a/api/examples/household-registry.openapi.yaml +++ b/api/examples/household-registry.openapi.yaml @@ -51,6 +51,11 @@ paths: Absent Records, Records outside this collection and protected existence share 404 record-not-available. tags: [Consultation] + x-govstack-digital-registries: + registry: https://registry.example/registries/households + collection: households + capability: retrieve + view: household-with-memberships parameters: - $ref: '../openapi.yaml#/components/parameters/RecordId' - $ref: '../openapi.yaml#/components/parameters/Traceparent' diff --git a/api/examples/registry-metadata.jsonld b/api/examples/registry-metadata.jsonld new file mode 100644 index 0000000..58d3885 --- /dev/null +++ b/api/examples/registry-metadata.jsonld @@ -0,0 +1,76 @@ +{ + "@context": "https://vocab.govstack.global/digital-registries/context/v1", + "@graph": [ + { + "@id": "https://registry.example/catalog", + "@type": "dcat:Catalog", + "title": "Business Registry catalogue", + "description": "Discovery metadata for the Business Registry, its dataset, and its APIs.", + "publisher": "https://registry.example/organisations/business-authority", + "catalogResource": "https://registry.example/registries/business", + "catalogDataset": "https://registry.example/datasets/business-records", + "catalogService": [ + "https://registry.example/services/business-consultation", + "https://registry.example/services/business-write", + "https://registry.example/services/business-evidence" + ] + }, + { + "@id": "https://registry.example/registries/business", + "@type": [ + "govreg:Registry", + "dcat:Resource" + ], + "title": "Business Registry", + "description": "Authoritative business registrations in Example Jurisdiction, including registered names and registration status. Tax status is outside this Registry's scope.", + "specification": "https://specs.govstack.example/digital-registries/3.0.0-alpha.2", + "authority": "https://registry.example/organisations/business-authority", + "governedDataset": "https://registry.example/datasets/business-records", + "dataService": [ + "https://registry.example/services/business-consultation", + "https://registry.example/services/business-write", + "https://registry.example/services/business-evidence" + ] + }, + { + "@id": "https://registry.example/organisations/business-authority", + "@type": "prov:Organization", + "title": "Business Registration Authority" + }, + { + "@id": "https://registry.example/datasets/business-records", + "@type": "dcat:Dataset", + "title": "Business registration records dataset", + "description": "Governed collection of business registration Records.", + "publisher": "https://registry.example/organisations/business-authority" + }, + { + "@id": "https://registry.example/services/business-consultation", + "@type": "dcat:DataService", + "title": "Business Registry Consultation API", + "description": "Retrieves, looks up, lists, and searches permitted business Records.", + "serviceType": "apif:consultation", + "servesDataset": "https://registry.example/datasets/business-records", + "endpointURL": "https://registry.example", + "endpointDescription": "https://registry.example/contracts/1.0.0-draft/examples/business-registry.openapi.yaml" + }, + { + "@id": "https://registry.example/services/business-write", + "@type": "dcat:DataService", + "title": "Business Registry Write API", + "description": "Accepts governed requests to create or revise business Records.", + "serviceType": "apif:write", + "endpointURL": "https://registry.example", + "endpointDescription": "https://registry.example/contracts/business-write.openapi.json" + }, + { + "@id": "https://registry.example/services/business-evidence", + "@type": "dcat:DataService", + "title": "Business Registry Evidence API", + "description": "Produces signed assertions derived from permitted business registration information.", + "serviceType": "apif:evidence", + "endpointURL": "https://registry.example", + "endpointDescription": "https://registry.example/contracts/business-evidence.openapi.json" + } + ] +} diff --git a/api/extensions/registry-metadata.schema.json b/api/extensions/registry-metadata.schema.json new file mode 100644 index 0000000..6f6d07c --- /dev/null +++ b/api/extensions/registry-metadata.schema.json @@ -0,0 +1,122 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Registry metadata document", + "description": "Shape of a Registry metadata document compacted with the Digital Registries JSON-LD context version 1. The document is a named graph of catalogue, Registry, agent, dataset and Data Service nodes. Every govreg:Registry node carries the minimal metadata required by Registry Core and every dcat:DataService node carries the service discovery metadata.", + "type": "object", + "required": ["@context", "@graph"], + "properties": { + "@context": { + "const": "https://vocab.govstack.global/digital-registries/context/v1" + }, + "@graph": { + "type": "array", + "minItems": 1, + "items": {"$ref": "#/$defs/node"}, + "contains": {"$ref": "#/$defs/registry"} + } + }, + "$defs": { + "iri": {"type": "string", "format": "iri"}, + "iris": { + "anyOf": [ + {"$ref": "#/$defs/iri"}, + {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/iri"}} + ] + }, + "text": { + "description": "A plain string or a JSON-LD language map keyed by BCP 47 language tag.", + "anyOf": [ + {"type": "string", "minLength": 1}, + { + "type": "object", + "minProperties": 1, + "additionalProperties": {"type": "string", "minLength": 1} + } + ] + }, + "types": { + "anyOf": [ + {"type": "string"}, + {"type": "array", "minItems": 1, "items": {"type": "string"}} + ] + }, + "node": { + "type": "object", + "required": ["@id", "@type"], + "properties": { + "@id": {"$ref": "#/$defs/iri"}, + "@type": {"$ref": "#/$defs/types"} + }, + "allOf": [ + { + "if": {"properties": {"@type": {"$ref": "#/$defs/hasRegistryType"}}}, + "then": {"$ref": "#/$defs/registry"} + }, + { + "if": {"properties": {"@type": {"$ref": "#/$defs/hasDataServiceType"}}}, + "then": {"$ref": "#/$defs/dataService"} + } + ] + }, + "hasRegistryType": { + "anyOf": [ + {"const": "govreg:Registry"}, + {"type": "array", "contains": {"const": "govreg:Registry"}} + ] + }, + "hasDataServiceType": { + "anyOf": [ + {"const": "dcat:DataService"}, + {"type": "array", "contains": {"const": "dcat:DataService"}} + ] + }, + "registry": { + "description": "Minimal Registry metadata: identifier, name, authority, specification reference, scope description and one Data Service per exposed service.", + "type": "object", + "required": ["@id", "@type", "title", "description", "authority", "specification", "dataService"], + "properties": { + "@type": {"$ref": "#/$defs/hasRegistryType"}, + "title": {"$ref": "#/$defs/text"}, + "description": {"$ref": "#/$defs/text"}, + "authority": {"$ref": "#/$defs/iris"}, + "specification": {"$ref": "#/$defs/iri"}, + "conformsTo": {"$ref": "#/$defs/iris"}, + "governedDataset": {"$ref": "#/$defs/iris"}, + "dataService": {"$ref": "#/$defs/iris"} + } + }, + "dataService": { + "description": "Service discovery metadata: identifier, API families, endpoint and machine-readable contract.", + "type": "object", + "required": ["@id", "@type", "title", "serviceType", "endpointURL", "endpointDescription"], + "properties": { + "@type": {"$ref": "#/$defs/hasDataServiceType"}, + "title": {"$ref": "#/$defs/text"}, + "description": {"$ref": "#/$defs/text"}, + "serviceType": { + "anyOf": [ + {"$ref": "#/$defs/apiFamily"}, + {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/apiFamily"}} + ] + }, + "servesDataset": {"$ref": "#/$defs/iris"}, + "endpointURL": {"$ref": "#/$defs/iri"}, + "endpointDescription": {"$ref": "#/$defs/iri"} + } + }, + "apiFamily": { + "description": "A concept of the Digital Registries API Families scheme, compacted with the apif prefix.", + "type": "string", + "enum": [ + "apif:consultation", + "apif:provisioning", + "apif:evidence", + "apif:write", + "apif:notification", + "apif:aggregate-data", + "apif:access-transparency", + "apif:identity-federation" + ] + } + } +} diff --git a/api/extensions/x-govstack-digital-registries.schema.json b/api/extensions/x-govstack-digital-registries.schema.json new file mode 100644 index 0000000..706bdf4 --- /dev/null +++ b/api/extensions/x-govstack-digital-registries.schema.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "x-govstack-digital-registries", + "description": "Registry context declared on every Digital Registries operation of an OpenAPI Operation Object. The values bind the operation to the Registry Identifier published in Registry metadata, to the collection it serves, to its capability and to the single Record view it returns.", + "type": "object", + "required": ["registry", "collection", "capability", "view"], + "additionalProperties": false, + "properties": { + "registry": { + "description": "Registry Identifier of the Registry whose Records the operation returns. It equals the @id of a govreg:Registry in the published Registry metadata.", + "type": "string", + "format": "iri" + }, + "collection": { + "description": "Collection name. It equals the collection segment of the operation path.", + "type": "string", + "pattern": "^[a-z][a-z0-9-]*$" + }, + "capability": { + "description": "Capability implemented by the operation.", + "type": "string", + "enum": ["retrieve", "lookup", "list", "search"] + }, + "view": { + "description": "Name of the Record view the operation returns. Operations of one collection that share a view name return the same Record schema.", + "type": "string", + "pattern": "^[a-z][a-z0-9-]*$" + } + } +} diff --git a/api/openapi.yaml b/api/openapi.yaml index 469fe3a..ffe9eb8 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -75,6 +75,11 @@ paths: outside the collection and protected existence share the 404 response. Conditional retrieval uses the representation’s ETag after authorization. tags: [Consultation] + x-govstack-digital-registries: + registry: https://registry.example/registries/records + collection: records + capability: retrieve + view: record-public parameters: - $ref: '#/components/parameters/RecordId' - $ref: '#/components/parameters/Traceparent' @@ -114,6 +119,11 @@ paths: request is authorized; unsupported query parameters return 400. Continuations follow the Cursor and PageSize rules. tags: [Consultation] + x-govstack-digital-registries: + registry: https://registry.example/registries/records + collection: records + capability: list + view: record-public parameters: - $ref: '#/components/parameters/Traceparent' - $ref: '#/components/parameters/PageSize' @@ -156,6 +166,11 @@ paths: retryable without an Idempotency-Key. Selector values remain confined to the request body. tags: [Consultation] + x-govstack-digital-registries: + registry: https://registry.example/registries/records + collection: records + capability: lookup + view: record-public parameters: - $ref: '#/components/parameters/Traceparent' requestBody: @@ -214,6 +229,11 @@ paths: use 400 invalid-cursor. This synchronous read is retryable without an Idempotency-Key. Search values remain confined to the request body. tags: [Consultation] + x-govstack-digital-registries: + registry: https://registry.example/registries/records + collection: records + capability: search + view: record-public parameters: - $ref: '#/components/parameters/Traceparent' requestBody: diff --git a/spec/03-terminology.md b/spec/03-terminology.md index 02d5f04..be1d324 100644 --- a/spec/03-terminology.md +++ b/spec/03-terminology.md @@ -12,8 +12,9 @@ This specification uses the [GovStack Common Terminology](https://specs.govstack | API Family | A coherent group of related Registry capabilities and operations. | | Authoritative Source | A source for which a named authority accepts responsibility within a declared domain and scope. Authoritative does not imply error-free. | | Binding | A mapping of abstract operations to a transport or established protocol. | +| Capability | An independently selectable operation pattern within an API family, such as Retrieve or Search. | | Capability Declaration | Discovery metadata identifying a supported API family and its service contract. | -| Capability Claim | A declaration that an implementation supports a specified API family, sub-pattern, and binding and meets the requirements attached to that claim. | +| Capability Claim | A declaration that an implementation supports a specified API family, capability, and binding and meets the requirements attached to that claim. | | Conformance Profile | A defined combination of core requirements and capability claims. | | Functional Identifier | An identifier issued and lifecycle-managed for a sector-specific purpose, such as a farmer, student, health, or professional identifier. | | Lifecycle State | When supplied, the state of a Record under a documented vocabulary. A current Record is not necessarily active. | @@ -34,4 +35,4 @@ This specification uses the [GovStack Common Terminology](https://specs.govstack | Search | Retrieval of a bounded collection using criteria declared by the service contract or applicable domain profile. It does not imply a generic query engine. | | Semantic Model | A published vocabulary or domain model for interpreting Registry data. A formal semantic-model reference is optional unless the selected profile requires it; field meanings remain documented. | | Source Recorded At | When supplied, the time at which the source recorded the represented information or revision, with the precise meaning declared by the contract. It is not the time at which an adapter retrieved the information. | -| Sub-pattern | An independently claimable capability within an API family. | +| Sub-pattern | See Capability. | diff --git a/spec/04-conformance.md b/spec/04-conformance.md index bcbde29..c703575 100644 --- a/spec/04-conformance.md +++ b/spec/04-conformance.md @@ -32,7 +32,7 @@ An implementation claiming conformance: 4. publishes the API-family classifications, endpoints, and linked machine-readable operational contracts for the services it exposes through the Registry BB interface; and 5. satisfies the applicable `govstack-cfr-2.1.0` requirements. -Core requirements concerning returned Records apply when a selected capability returns Records. The Consultation Retrieve, Lookup, List, and Search requirements and shared HTTP binding apply only to the selected capabilities. Retrieve resolves a stable Record Identifier; Lookup resolves a declared exact selector; List and Search return bounded Pages. An authorised API consumer receives the current permitted representation or a policy-appropriate unsuccessful outcome. The permitted representation is governed by access policy. +Core requirements concerning returned Records apply when a selected capability returns Records. The Consultation Retrieve, Lookup, List, and Search requirements and shared HTTP binding apply only to the selected capabilities. Retrieve resolves a stable Record Identifier; Lookup resolves a declared exact selector; List and Search return bounded Pages. An authorised API consumer receives the current permitted representation or a policy-appropriate unsuccessful outcome. The permitted representation is governed by access policy. Consumer guidance in the capability pages is informative; conformance applies to implementations only. Registry metadata can describe a Registry for directory participation without establishing functional Registry BB conformance. A specification reference or family classification in metadata is not, by itself, a conformance claim. diff --git a/spec/05-api-families/consultation.md b/spec/05-api-families/consultation.md index b7a5faa..79d77b9 100644 --- a/spec/05-api-families/consultation.md +++ b/spec/05-api-families/consultation.md @@ -12,24 +12,26 @@ Consultation defines read access to Registry Records for independently implement | Capability | Input | Successful result | |---|---|---| -| `consultation.retrieve` | Record Identifier | One Record | -| `consultation.lookup` | Declared exact selector and its complete key | One Record | -| `consultation.list` | Declared collection and supported public filters | Page of Records | -| `consultation.search` | Declared search and typed criteria | Page of Records | +| Retrieve | Record Identifier | One Record | +| Lookup | Declared exact selector and its complete key | One Record | +| List | Declared collection and its supported equality filters | Page of Records | +| Search | Declared search and typed criteria | Page of Records | Shared requirements apply to every selected capability; operation requirements apply when that capability is selected. Each operation applies to a declared collection with an unambiguous Registry context, representation schema, and access policy. +Consultation interoperates at the level Core defines: operation shapes, the Record envelope, error outcomes, pagination, and discovery are the same for every Registry, while domain fields, selectors, searches, and filters are declared per contract. A consumer reads any conforming Registry with the same client code once it has loaded that Registry's contract. See the [interoperability boundary](registry-core.md#purpose-and-applicability) in Core. + ## Common read contract -A read preserves the source Records. Current information is the information accepted by the authoritative source and available under the service's declared currency contract, including replication or cache delay. Domain schemas define the meaning of status and validity fields. +A read preserves the source Records. Current information is the information accepted by the authoritative source and available under the service's declared currency contract, including replication or cache delay. The contract documents currency; verification reviews that documentation and the source arrangement rather than measuring delay. Domain schemas define the meaning of status and validity fields. -**Record representation.** A Record contains `recordId` and `data`. The identifier is stable, unique within its Registry, and never reassigned. Registry context and the selected representation schema are unambiguous from the published contract, request context, or response. Retrieve and Lookup return one Record; List and Search use the same Record shape for each item in a Page. +**Record representation.** A Record contains `recordId` and `data`. The identifier is stable, unique within its Registry, and never reassigned. The [Common Record context](registry-core.md#common-record-context) defines how the contract establishes the Registry and the representation schema: each operation declares its Registry, collection, capability, and view with the `x-govstack-digital-registries` extension, and its response schema defines the view. Retrieve and Lookup return one Record; List and Search use the same Record shape for each item in a Page. -The `data` schema defines domain fields, structured values, references, and their meanings. A declared view selects the information represented by that schema. Revision, lifecycle, and provenance metadata are optional in the baseline; profiles can require source-backed metadata with defined semantics. +The `data` schema defines domain fields, structured values, references, and their meanings. Revision, lifecycle, and provenance metadata are optional in the baseline; profiles can require source-backed metadata with defined semantics. -**Example: Record representation.** Examples on this page use the [illustrative business Registry binding](../../api/examples/business-registry.openapi.yaml), which defines the domain fields, status values, and query names. Its published contract selects the Registry and the `business-public` view. A Record response contains: +**Example: Record representation.** Examples on this page use the [illustrative business Registry binding](../../api/examples/business-registry.openapi.yaml), which defines the domain fields, status values, and query names. Its operations declare Registry `https://registry.example/registries/business`, collection `businesses`, and view `business-public`. A Record response contains: ```json { @@ -41,30 +43,24 @@ The `data` schema defines domain fields, structured values, references, and thei } ``` -**Consumer behavior.** Consumers retain Registry context when storing or forwarding Record references, treat Record Identifiers as opaque, and interpret `data` using the declared schema. They accept additional response-envelope members and use only the inputs supported by the published contract. - -## Domain models and service declarations +**Consumer guidance (informative).** Consumers retain Registry context when storing or forwarding Record references, treat Record Identifiers as opaque, and interpret `data` using the declared schema. They accept additional response-envelope members and use only the inputs supported by the published contract. This specification places no conformance requirements on consumers. -Implementations should reuse suitable schemas and vocabularies, including [Schema.org](https://schema.org/), [EU SEMIC Core Vocabularies](https://interoperable-europe.ec.europa.eu/collection/semic-support-centre/solution/core-vocabularies), [PublicSchema](https://publicschema.org/), and models defined or adopted by national or sector authorities. +## Service declarations -A domain profile records reusable agreements about schemas, terminology, and query semantics. A service contract applies those agreements to the operations it exposes. An implementation can adopt an existing profile or publish a concrete domain binding directly. Both preserve the shared Consultation behavior. - -The published service contract supplies the following information for its selected capabilities and applicable representation features, directly or through versioned references: +The published service contract supplies the following information for its selected capabilities, directly or through versioned references: | Topic | Declared information | |---|---| -| Registry and capabilities | Registry association and implemented operations for each collection, linked from Core metadata. | +| Registry context | Registry Identifier, collection, capability, and view of each operation, through the Core [extension](registry-core.md#api-composition). | | Representation | JSON Schemas for the Record view and responses; adopted models and versions; mappings, local constraints, and extensions. | | Field meanings | Meaning, units, code lists, and omitted, null, or empty values, preserving the semantics of adopted models. | | Lookup and Search | Names, typed inputs, required components, comparison and normalization rules, uniqueness scope, and matching semantics. | -| Collections | Names, membership, operation paths, supported filters and sorting, deterministic order, page-size limits, and cursor expiry. | -| Access and currency | Authentication requirements, permitted views, and source currency, including material replication or cache delay. | - -An API can expose several collections, such as individuals, households, and land parcels. Each collection selects Records within a declared Registry; different collections can belong to the same Registry or to different Registries. The contract associates each operation with its collection and response schema. Record identity remains the pair of Registry Identifier and Record Identifier across collections and views. +| List | Supported equality filters and sorting, deterministic order, page-size limits, and cursor expiry. | +| Access and currency | Authentication requirements, access policy for the declared view, and source currency, including material replication or cache delay. | -Domain references identify their target Record and Registry. When a target read is offered, the field binding identifies its collection, operational contract, operation, and mapping from the reference to the required inputs. Consumers use that binding to resolve the reference. Embedded data declares its ownership and currency; embedded collections declare bounds, completeness, and overflow outcomes. The [Core representation conventions](registry-core.md#structured-values-and-references) provide the shared model, and OpenAPI supplies reusable reference schemas. +A domain profile records reusable agreements about schemas, terminology, and query semantics. A service contract applies those agreements to the operations it exposes. An implementation can adopt an existing profile or publish a concrete domain binding directly. Both preserve the shared Consultation behaviour. Reuse of domain models, the treatment of structured values, Record references, and embedded collections, and schema evolution follow [Registry Core](registry-core.md#domain-semantics-and-extensions). -Published schema versions remain resolvable while their contracts are supported. The service identifies changes to schemas, queries, and views through its contract version, following the API design guide's compatibility rules. +**List and Search.** List and Search both return Pages, and the split between them follows the API design guide. List carries equality filters on declared non-personal fields as query parameters, one parameter per field (guide §12.8). Personal criteria, composite keys, and non-equality matching belong to Search, whose request body keeps them out of URLs and logs (guide §8.6 and §12.9). A contract that needs neither can select List alone; a contract whose every useful criterion is personal selects Search alone. ## Read requirements @@ -78,7 +74,9 @@ Published schema versions remain resolvable while their contracts are supported. Given a valid Record Identifier for a Record in the selected collection and a permitted request, Retrieve returns the current representation of that Record. An unknown identifier or a Record outside that collection receives the binding's unavailable-Record outcome, subject to protected-existence handling. -**Verification:** Retrieve a known source fixture and check its identity, schema, currency, and declared metadata. Confirm that the source Record is unchanged; exercise an unknown identifier and, where applicable, an identifier belonging to another collection. +**Prerequisite:** Retrieve is selected and the collection declares its Registry context and view. + +**Verification:** Retrieve a known source fixture and check its identity, schema, currency documentation, and declared metadata. Confirm that the source Record is unchanged; exercise an unknown identifier and, where applicable, an identifier belonging to another collection. ### #2 Apply disclosure rules to the returned representation (DRAFT EXTENSIBLE OBSERVABLE) @@ -86,7 +84,9 @@ Given a valid Record Identifier for a Record in the selected collection and a pe `KF: Consultation` -For every selected read, the service returns a schema-valid representation containing only the Records, fields, metadata, and result information permitted for the consumer and request context. Disclosure applies to references, embedded data, counts, errors, and continuation information. +For every selected read, the service returns a representation valid against the declared view schema and containing only the Records, fields, metadata, and result information permitted for the consumer and request context. Disclosure applies to references, embedded data, counts, errors, and continuation information. Withholding applies to optional fields of the declared view; it does not substitute another schema. + +**Prerequisite:** The access policy for the declared view is documented. **Verification:** Exercise each selected read with fixtures for the service's applicable access policies. Check representation validity and permitted information, including different entitlements where offered. @@ -96,9 +96,11 @@ For every selected read, the service returns a schema-valid representation conta `KF: Consultation` -When policy protects Record existence, Retrieve and Lookup return the same unresolved outcome for unknown and protected Records. Equivalence covers protocol status, security-relevant metadata, error type, response structure, and non-Record-specific values. Trace and correlation values are generated independently of Record existence; the outcome contains no Record-specific data. +When policy protects Record existence, Retrieve and Lookup return the same unresolved outcome for unknown and protected Records. Equivalence covers protocol status, security-relevant metadata, error type, response structure, and non-Record-specific values. Trace and correlation values are generated independently of Record existence; the outcome contains no Record-specific data. A Lookup failure caused by a source uniqueness violation on a protected key is indistinguishable from the unresolved outcome. + +**Prerequisite:** The access policy declares which Records or keys have protected existence. -**Verification:** Compare protected and unknown fixtures under the same consumer context for each selected operation. Check equivalent outcomes and independent trace values. +**Verification:** Compare protected and unknown fixtures under the same consumer context for each selected operation, including a uniqueness violation on a protected key where Lookup is selected. Check equivalent outcomes and independent trace values. ### #4 Resolve a Record by a declared exact selector (DRAFT EXTENSIBLE OBSERVABLE) @@ -108,9 +110,11 @@ When policy protects Record existence, Retrieve and Lookup return the same unres Lookup accepts a published selector and all required key components. The key can be composite. Its declared comparison and normalization rules resolve at most one Record within the uniqueness scope. A permitted unique match in the selected collection returns that Record; zero matches in the collection produce the unresolved outcome. A source uniqueness violation produces a failure governed by disclosure policy. -Invalid, incomplete, or unsupported inputs are rejected. A selector can derive key components from verified consumer context when its contract defines that mode; a fully context-derived selector accepts an empty caller-supplied `values` object. +Invalid, incomplete, or unsupported inputs are rejected. A **context-derived Lookup** derives some or all key components from verified consumer context, such as the authenticated subject, when its selector contract defines that mode; a fully context-derived selector accepts an empty caller-supplied `values` object. -**Verification:** Exercise known, unknown, incomplete, incorrectly typed, and unsupported inputs, plus a source uniqueness violation. Verify comparison rules, composite keys where supported, and protected-existence handling. +**Prerequisite:** Lookup is selected and each selector declares its key components, comparison rules, uniqueness scope, and any context-derived components. + +**Verification:** Exercise known, unknown, incomplete, incorrectly typed, and unsupported inputs, plus a source uniqueness violation. Verify comparison rules, composite keys where supported, context-derived components where declared, and protected-existence handling. ### #5 List a bounded Record collection (DRAFT EXTENSIBLE OBSERVABLE) @@ -118,7 +122,9 @@ Invalid, incomplete, or unsupported inputs are rejected. A selector can derive k `KF: Consultation` -List returns a bounded Page of permitted Records from its declared collection, applying supported filters and ordering. Zero and single-result collections retain the Page shape. Unsupported filters or sorting produce a validation error. +List returns a bounded Page of permitted Records from its declared collection, applying its supported equality filters and ordering. Filters address declared non-personal fields only. Zero and single-result collections retain the Page shape. Unsupported filters or sorting produce a validation error. + +**Prerequisite:** List is selected and the collection declares its order, tie-breaker, filters, and sorting. **Verification:** Use fixtures with zero, one, and multiple results, including tied sort values where applicable. Check membership, schemas, order, size bounds, and rejection of unsupported inputs. @@ -130,6 +136,8 @@ List returns a bounded Page of permitted Records from its declared collection, a Search accepts a published search name and its typed criteria. It applies the declared matching rules to the selected collection and returns a bounded Page of permitted matching Records, retaining the Page shape for zero or one result. Unsupported searches, unknown criteria, and invalid inputs produce a validation error. +**Prerequisite:** Search is selected and each search declares its criteria schema and matching rules. + **Verification:** Execute declared searches with valid and invalid inputs. Check matching results, empty Pages, applicable disclosure contexts, and use of the binding's protected request locations for personal criteria. @@ -148,20 +156,21 @@ Pagination observes live data: source changes can move, add, or remove Records a Consumers treat cursors as opaque and return them unchanged with the original query inputs. They follow the completion signal, including when an intermediate Page is empty. The [HTTP binding](#http-binding) defines the continuation fields and fixed page-size policy. +**Prerequisite:** List or Search is selected and the collection declares its cursor expiry and page-size bounds. + **Verification:** Traverse unchanged multi-page fixtures to completion, checking complete membership without duplicates, identity, order, size bounds, progress, and termination. Exercise malformed, expired, and mismatched cursors, source changes, and applicable access changes. Check permitted page patterns and any total against the full permitted query. ## HTTP binding -The [canonical OpenAPI](../../api/openapi.yaml) defines the HTTPS/JSON contract, version `1.0.0-draft`, using API design guide and ruleset `0.2.0-draft`. It uses `records` as the reference collection name. Deployments publish concrete collection names, selected operations, Registry associations, and schemas in OpenAPI. +The [canonical OpenAPI](../../api/openapi.yaml) defines the synchronous HTTPS/JSON contract, version `1.0.0-draft`, using API design guide and ruleset `0.2.0-draft`. It uses `records` as the reference collection name and `/v1` as the HTTP compatibility line. The BB requirements remain DRAFT. The [read API design decisions](../12-other-resources/read-api-design-decisions.md) record the binding choices and the shared guide refinements. -| Capability | Request | Successful body | -|---|---|---| -| Retrieve | `GET /v1/records/{recordId}` | `{recordId, data}` | -| Lookup | `POST /v1/records:lookup` with `{selector, values}` | `{recordId, data}` | -| List | `GET /v1/records` with pagination and supported public query parameters | `{items, pageInfo}` | -| Search | `POST /v1/records:search` with `{search, criteria}` and pagination controls | `{items, pageInfo}` | +### Deployment contract + +The server URL identifies the deployment root, optionally including a stable routing prefix such as `/registry`. The major version precedes each collection: `/v1/households` or, with that prefix, `/registry/v1/households`. -The major API version precedes collection paths. An OpenAPI server URL identifies the deployment root, optionally including a stable routing prefix, such as `https://example.org/registry`. API-family classifications are declared in Core metadata and operation tags. A shared API can therefore expose: +A deployment publishes a concrete OpenAPI contract containing its selected operations, service and authentication endpoints, versioned JSON Schemas for `data` and the complete response, selectors, searches, supported filters and ordering, source currency, access policy, and continuation policy. Every Record-returning operation carries the `x-govstack-digital-registries` extension required by [Core requirement #8](registry-core.md#registry-core-functional-requirements); it names the Registry, collection, capability, and view, and the operation's response schema defines that view. The extension is the binding's answer to the Common Record context: the Registry Identifier is not repeated in requests or Records. + +One API can expose several collections. A shared API can therefore expose: ```http GET /v1/individuals/{recordId} @@ -171,9 +180,18 @@ POST /v1/households:lookup POST /v1/households:search ``` -These are illustrative collection names; the published contract defines the supported paths. The `:lookup` and `:search` suffixes distinguish collection methods from item identifiers, including valid IDs such as `lookup` and `search`. +These are illustrative collection names; the published contract defines the supported paths. Different collections can belong to the same Registry or to different Registries. A Record retains its `(registryId, recordId)` identity across collections and views within its Registry. [API composition](registry-core.md#api-composition) describes how collections and families share an API; Consultation and Write can share a resource URI with separate methods, schemas, and permissions. The [OpenAPI examples](../../api/examples/README.md) illustrate concrete collections, domain schemas, and response payloads. + +### Operations -Lookup and Search are synchronous reads returning `200`; selector and search values remain in the request body. The binding also defines the operational `/health` endpoint. [API composition](registry-core.md#api-composition) describes how collections and families share an API. +| Capability | HTTP operation, relative to the deployment root | Successful body | Input contract | +|---|---|---|---| +| Retrieve | `GET /v1/records/{recordId}` | `{recordId, data}` | Record Identifier encoded as one path segment. | +| Lookup | `POST /v1/records:lookup` | `{recordId, data}` | JSON object with `selector` and `values`. | +| List | `GET /v1/records` | `{items, pageInfo}` | Optional `pageSize`, `cursor`, declared equality filters as query parameters, and declared sort parameters. | +| Search | `POST /v1/records:search` | `{items, pageInfo}` | JSON object with `search`, `criteria`, and optional `pageSize`, `cursor`, and declared `sort`. | + +The `:lookup` and `:search` suffixes distinguish collection methods from item identifiers, including valid IDs such as `lookup` and `search`. Lookup and Search are synchronous reads returning `200`; selector and search values remain in the request body. Lookup uses a declared unique key within its documented scope; Search uses declared typed criteria. The concrete contract defines comparison and normalization rules and rejects unsupported inputs. The binding also exposes the guide's unversioned `/health` operation. **Example: exact Lookup.** The business binding names its collection `businesses`. To resolve a business by its declared registration-number key, send this body to `POST /v1/businesses:lookup`: @@ -221,15 +239,35 @@ With one permitted match and traversal complete, the `200` response is: List uses the same Page shape for its declared collection. -**Continuation.** The first request selects `pageSize`, defaulting to 20 and bounded to 100 in the canonical contract. A continuation repeats the original criteria, search name where applicable, sorting, and view with the cursor. It can omit `pageSize` to retain the bound value or supply that same value. Cursors bind the operation, Registry, collection, query, view, effective size, and applicable access context. The service rejects continuations whose declared semantics it can no longer preserve. +### Representation and schema context + +Retrieve and Lookup return `{recordId, data}`. List and Search return `{items, pageInfo}`, with each item using the same Record schema for the declared view. Empty and single-result collections retain the Page shape. + +The operation's Registry context declaration and response schema provide Registry and schema context. Additional source metadata follows [Registry Core](registry-core.md#common-record-context). A schema linked with `rel="describedby"` describes the complete response, including its envelope. An operation exposing a different view is a separate operation with its own declared schema and field meanings. + +### Continuation + +The first request selects `pageSize`, defaulting to 20 and bounded to 100 in the canonical contract. A continuation repeats the original criteria, search name where applicable, sorting, and view with the cursor. It can omit `pageSize` to retain the bound value or supply that same value; a different value produces `400 invalid-cursor`. Cursors bind the operation, Registry, collection, query, view, effective size, and applicable access context. The deployment declares expiry and rejects malformed, expired, or mismatched cursors, including continuations whose declared semantics it can no longer preserve. A short or empty Page can carry a non-null `nextCursor` when source processing advances. + +A non-null `pageInfo.nextCursor` enables continuation; `null` marks completion. Optional `pageInfo.total` is the exact count of the full permitted query at the documented page evaluation time, before applying the continuation boundary. Because the count is of permitted Records only, disclosure policy decides whether it is offered at all. Services omit an unavailable total. OpenAPI defines the cursor format, limits, and error responses. + +### Outcomes, errors, and caching + +OpenAPI defines the status codes and RFC 9457 Problem Details for each operation. Retrieve and Lookup share `404 record-not-available` for unknown Records, Records outside the selected collection, and Records whose existence is protected under [requirement #3](#retrieve-functional-requirements). Structural input errors, invalid query parameters, and invalid pagination controls use `400`. Structurally valid Lookup and Search bodies with unknown selector or search names or invalid domain values use `422`. Malformed, expired, or mismatched cursors use `400 invalid-cursor`. + +Protected reads and errors use `Cache-Control: no-store`. Deployments may declare caching for public or isolated representations. Optional conditional Retrieve evaluates authorization before returning `304`; its ETag validates the selected HTTP representation. Authentication, authorization, and source failures follow the declared OpenAPI responses and the API design guide. + +### Record references and expansion + +The [Core representation rules](registry-core.md#structured-values-and-references) govern nested data and related Records. The reusable `RecordReference` schema carries `recordId` and, where the field schema leaves the target Registry open, required `registryId`. A field with a fixed target Registry permits omission of `registryId` and accepts an explicit value only when it matches that target. -A non-null `pageInfo.nextCursor` enables continuation; `null` marks completion. Optional `pageInfo.total` is the exact count of the full permitted query at the documented page evaluation time, before applying the continuation boundary. Services omit an unavailable total. +When a related read is offered, the field binding identifies its target collection, read operation, and operational contract, including how the reference supplies the operation's inputs. Consumers follow that binding and the target's access requirements. Record Identifiers remain opaque; reference identity is independent of the target's current availability. -**Outcomes.** OpenAPI defines the status codes and Problem Details for each operation. Retrieve and Lookup share `404 record-not-available` for unknown Records, Records outside the selected collection, and Records whose existence is protected. Structural input errors, invalid query parameters, and invalid pagination controls use `400`. Structurally valid Lookup and Search bodies with unknown selector or search names or invalid domain values use `422`. Malformed, expired, or mismatched cursors use `400 invalid-cursor`. Authentication, authorization, source failures, caching, and optional conditional Retrieve follow the declared OpenAPI responses and the API design guide. +Optional client-selected expansion declares its supported paths, bounds, source currency, and disclosure behaviour in the deployment contract. Expansion embeds related representations inside the declared view; it does not select a different view. The [OpenAPI examples](../../api/examples/README.md) demonstrate concrete nested schemas and references. ## Conformance -Evaluation identifies the service, specification and contract versions, selected capabilities, and any adopted domain profile. The service satisfies the common read contract, declaration rules, HTTP binding, and the requirements applicable to each selected capability. +Evaluation identifies the service, specification and contract versions, selected capabilities, and any adopted domain profile. The service satisfies the common read contract, service declarations, HTTP binding, and the requirements applicable to each selected capability. | Selected capability | Applicable Consultation requirements | |---|---| @@ -238,4 +276,4 @@ Evaluation identifies the service, specification and contract versions, selected | List | #2, #5, #7 | | Search | #2, #6, #7 | -Consumers follow the shared representation rules and the input, outcome, and continuation contracts for the capabilities they use. Verification checks published contracts and observable exchanges under the stated fixture conditions. The [OpenAPI examples](../../api/examples/README.md) and [artifact validation](../../api/README.md#validation) support review; deployed behavior is evaluated separately. +Verification checks published contracts and observable exchanges under the stated fixture conditions. The [OpenAPI examples](../../api/examples/README.md) and [artifact validation](../../api/README.md#validation) support review; deployed behaviour is evaluated separately. diff --git a/spec/05-api-families/provisioning.md b/spec/05-api-families/provisioning.md index 81bb62d..ab95c75 100644 --- a/spec/05-api-families/provisioning.md +++ b/spec/05-api-families/provisioning.md @@ -18,7 +18,7 @@ A Registry can publish its metadata without a Provisioning API. Its authority an |---|---| | Metadata administration | Creates or revises the Registry's machine-readable identity and capability declarations through an administrative interface. Registry Core separately requires publication of the current Registry metadata. | | Schema lifecycle | Publishes, revises, or retires a representation schema under defined compatibility rules. | -| Interface publication | Declares supported families, sub-patterns, bindings, and access conditions. | +| Interface publication | Declares supported families, capabilities, bindings, and access conditions. | | Bulk transfer | Initiates a controlled import or export of data and metadata. | Provisioning administers service metadata and contracts independently of the storage engine and administrative tooling. Registry Core requires metadata publication whether or not Provisioning is supported. Establishing a Registry Authority remains a legal or governance act outside this API family. diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index 54e57b8..5230804 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -10,11 +10,14 @@ description: Shared identity, metadata, semantics, lifecycle, and provenance for Registry Core defines the common behaviour and metadata shared by the API families. It identifies the Registry, its authority and scope, and its available services. Returned Records have stable identity within an unambiguous Registry context and a documented representation schema. A capability or domain profile can additionally require revision, lifecycle, provenance, or formal semantic-model information. +Core is the interoperability boundary of this specification. Two implementations that conform to Core and the same capability expose the same operation shapes, error model, pagination, discovery mechanism and Record envelope. They do not expose the same domain fields: each deployment declares its own Record schemas in its published contract, and a domain profile can narrow them. A consumer that reads one Registry can read another after loading that Registry's contract, not before. + The [conformance model](../04-conformance.md) combines Core with at least one selected capability. Core requirements apply as follows: - Registry metadata and service discovery apply to every implementation. - Record representation requirements apply to implemented capabilities that return Records. - Identifier preservation applies where the implementation assigns or maintains Record Identifiers. +- Registry context declaration applies to every published OpenAPI contract. [Provisioning](provisioning.md) provides optional administrative operations for creating or revising metadata. Publication can also use a static document or an external catalogue. @@ -102,7 +105,20 @@ A service description declares only the families available for its associated Re ### API composition -One API can expose several Record collections and operations from several families. Its contract declares each collection's Registry association and membership, and each operation's family, inputs, representation, and access requirements. API-family classifications describe capabilities independently of URL structure. +One API can expose several Record collections and operations from several families. Its contract documents each collection's membership and each operation's inputs, representation, and access requirements. API-family classifications describe capabilities independently of URL structure. + +An OpenAPI contract declares the Registry context of each operation that returns Records with the `x-govstack-digital-registries` extension on the Operation Object. The extension carries four values: `registry`, the Registry Identifier, equal to the `@id` of a `govreg:Registry` in the published metadata; `collection`, equal to the collection segment of the operation path; `capability`, one of `retrieve`, `lookup`, `list` and `search`; and `view`, the name of the Record view the operation returns. The [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json) is its normative definition. Operations of one collection that declare the same view return the same Record schema. The extension is the machine-readable link between a Record read and the metadata that identifies its Registry and authority; the [Common Record context](#common-record-context) relies on it. + +```yaml + /v1/businesses/{recordId}: + get: + operationId: retrieveBusiness + x-govstack-digital-registries: + registry: https://registry.example/registries/business + collection: businesses + capability: retrieve + view: business-public +``` Operations from different families can share a resource URI through distinct HTTP methods. For example, Consultation can retrieve a Record at a URI where Write accepts an update. Each operation defines its own request and response schemas and permissions. The API contract coordinates collection, action, and supporting-resource paths, including any schema, subscription, or asynchronous-operation resources. @@ -110,21 +126,53 @@ The major version applies to the API contract exposed at that root. Separately e ### Discovery publication -An implementation publishes the required metadata at a stable URI made available to its intended API consumers. Publication can use a statically hosted document or an entry in an external catalogue. Implementations document the publication URI, supported representations, and access conditions. +An implementation publishes its Registry metadata as one document compacted with the version 1 JSON-LD context and served as `application/ld+json`. The [metadata document schema](../../api/extensions/registry-metadata.schema.json) defines the compacted shape; the JSON-LD context defines its RDF meaning. The document describes one or more Registries, their governed datasets, and their services. The document URI identifies the document; each Registry has its own Registry Identifier. The document URI is chosen by the deployment, is stable, and is not part of the versioned API surface. -For a DCAT catalogue on an HTTPS origin, the recommended default is the root-relative `/catalog` URI, with DCAT representations available through HTTP content negotiation. Deployments can select another stable path. The catalogue describes one or more Registries, their governed datasets, and their services. The catalogue URI identifies the catalogue; each Registry has its own Registry Identifier. +Consumers locate the document through the [RFC 9727](https://www.rfc-editor.org/rfc/rfc9727.html) API catalog. The origin that hosts a Digital Registries API serves `/.well-known/api-catalog` as an [RFC 9264 linkset](https://www.rfc-editor.org/rfc/rfc9264.html) in `application/linkset+json`, following the GET, HEAD, and HTTPS requirements of RFC 9727. For every Digital Registries API at that origin, the linkset carries a `service-desc` link to the OpenAPI contract and a `service-meta` link, typed `application/ld+json`, to the Registry metadata document. Both link relations are defined by [RFC 8631](https://www.rfc-editor.org/rfc/rfc8631.html). The well-known path is one of the unversioned paths the GovStack API Design Guide permits, so no other root path is needed for discovery. -The optional [RFC 9727 API discovery mechanism](https://www.rfc-editor.org/rfc/rfc9727.html) defines `/.well-known/api-catalog` and the `api-catalog` link relation for locating the canonical API catalogue. Deployments using it follow its GET, HEAD, HTTPS, and [`application/linkset+json`](https://www.rfc-editor.org/rfc/rfc9264.html) requirements. +The linkset below publishes the three contracts and the metadata document of the [informative example](#informative-json-ld-example). It is also available as a [file](../../api/examples/api-catalog.linkset.json). -A deployment supporting the JSON-LD workflow below provides `application/ld+json` at the configured or discovered catalogue URI. When using RFC 9727, it also provides the required Linkset representation. Clients request JSON-LD explicitly and check the response media type before parsing; RFC 9727 alone guarantees only Linkset support. +```json +{ + "linkset": [ + { + "anchor": "https://registry.example/", + "service-desc": [ + { + "href": "https://registry.example/contracts/1.0.0-draft/examples/business-registry.openapi.yaml", + "type": "application/vnd.oai.openapi", + "title": "Business Registry Consultation API" + }, + { + "href": "https://registry.example/contracts/business-write.openapi.json", + "type": "application/vnd.oai.openapi+json", + "title": "Business Registry Write API" + }, + { + "href": "https://registry.example/contracts/business-evidence.openapi.json", + "type": "application/vnd.oai.openapi+json", + "title": "Business Registry Evidence API" + } + ], + "service-meta": [ + { + "href": "https://registry.example/catalog", + "type": "application/ld+json", + "title": "Registry metadata for the Business Registry" + } + ] + } + ] +} +``` -Declarations are scoped to the intended metadata audience. Missing declarations establish neither the absence of an undisclosed service nor a consumer's entitlement to use it. +An entry in an external catalogue, such as a national data portal, can repeat the metadata but does not replace the well-known resource. Declarations are scoped to the intended metadata audience. Missing declarations establish neither the absence of an undisclosed service nor a consumer's entitlement to use it. ### Informative JSON-LD example This JSON-LD document describes a business Registry, its authority and governed dataset, and three logical services supporting Consultation, Write, and Evidence at a shared API endpoint. The GovStack context maps JSON properties to the RDF vocabulary and identifies IRI-valued properties. The specification IRI is illustrative; publication status is listed under [coverage and limitations](../12-other-resources.md#121-coverage-and-limitations). -The Consultation entry illustrates publication of the [business Registry OpenAPI](../../api/examples/business-registry.openapi.yaml) with its local dependencies at the example contract URL. It supports Retrieve, Lookup, List, and Search. +The Consultation entry illustrates publication of the [business Registry OpenAPI](../../api/examples/business-registry.openapi.yaml) with its local dependencies at the example contract URL. It supports Retrieve, Lookup, List, and Search. The document is also available as a [file](../../api/examples/registry-metadata.jsonld) and validates against the metadata document schema. Its own URI, `https://registry.example/catalog`, is the `service-meta` target of the linkset above. ```json { @@ -223,10 +271,10 @@ Catalogue entries contain descriptive metadata only. Services govern disclosure ### Client discovery workflow -A client using the illustrated DCAT publication arrangement can discover declared API families without knowing an implementation's API paths in advance: +A client can discover declared API families without knowing an implementation's API paths in advance: -1. Locate the canonical catalogue from a configured URI, the optional RFC 9727 well-known resource, or the recommended `/catalog` convention. -2. Request a documented RDF representation of the catalogue, such as JSON-LD, and check that the response uses that media type. +1. Request `/.well-known/api-catalog` at the API origin as `application/linkset+json`, or start from a configured metadata document URI. +2. Follow the `service-meta` link to the metadata document, request it as `application/ld+json`, and check that the response uses that media type. 3. Select the required `govreg:Registry` by its stable Registry Identifier. 4. Follow `govreg:dataService` to each associated `dcat:DataService`. 5. Read each service's `dct:type` values from the Digital Registries API Families scheme, then follow `dcat:endpointDescription` for the exact operations and invocation contract. @@ -234,22 +282,21 @@ A client using the illustrated DCAT publication arrangement can discover declare The following language-neutral pseudocode illustrates the process for a JSON-LD client: ```text -catalogUri = configuredCatalogUri - -if catalogUri is absent: - catalogUri = discoverCatalogUsingRfc9727(apiOrigin) +metadataUri = configuredMetadataUri -if catalogUri is absent: - catalogUri = resolve(apiOrigin, "/catalog") +if metadataUri is absent: + linkset = get(resolve(apiOrigin, "/.well-known/api-catalog"), accept = "application/linkset+json") + requireMediaType(linkset, "application/linkset+json") + metadataUri = firstLink(linkset, rel = "service-meta", type = "application/ld+json").href -response = get(catalogUri, accept = "application/ld+json") +response = get(metadataUri, accept = "application/ld+json") requireMediaType(response, "application/ld+json") -catalog = loadJsonLd(response.body) -registry = catalog.resourceWithId(requiredRegistryId) +metadata = loadJsonLd(response.body) +registry = metadata.resourceWithId(requiredRegistryId) discoveredServices = [] for each serviceReference in asList(registry.dataService): - service = catalog.resourceWithId(serviceReference) + service = metadata.resourceWithId(serviceReference) for each family in asList(service.serviceType): if DigitalRegistriesApiFamilies contains family: @@ -282,18 +329,18 @@ An adopting profile adds types and properties where their semantics apply. Any e ## Common Record context -Every returned Record representation has the following context. The binding defines where it is conveyed: in the representation, response metadata, or the versioned operational contract and its association with the Registry. A consumer can determine that context without knowing the source's internal storage. Registry-wide information need not be repeated in every Record or collection item. +Every returned Record representation has the following context. The binding defines where it is conveyed: in the representation, response metadata, or the versioned operational contract and its association with the Registry. The HTTP binding conveys it through the contract: the `x-govstack-digital-registries` extension on each operation names the Registry, collection, capability, and view, and the operation's response schema is the representation schema. A consumer can determine that context without knowing the source's internal storage. Registry-wide information need not be repeated in every Record or collection item. | Concept | Baseline contract | |---|---| -| Registry Identifier | The request and published service metadata establish one Registry context, or the returned Record explicitly identifies its Registry. | +| Registry Identifier | The operational contract binds the operation to one Registry, or the returned Record explicitly identifies its Registry. | | Record Identifier | A stable reference unique within that Registry, included in each returned Record. | | Representation Format | The binding identifies the serialisation or media type. | | Representation Schema | A resolvable, versioned machine-readable schema identifies the permitted representation; schema selection is unambiguous. | | Field meanings | Schema descriptions or linked domain documentation explain field meanings, units, code lists, and relevant absence or null semantics. | | Registry Authority | The Registry context resolves to the authority and authoritative scope published in Registry metadata. | -The applicable capability determines which domain data and metadata the consumer may receive. A fixed public view is sufficient where it meets the applicable policy. Different consumer views are optional; each exposed view has a valid, documented schema. The HTTP binding uses the same Record object for single results and collection members within a declared view. +The applicable capability determines which domain data and metadata the consumer may receive. Each operation returns exactly one declared view, named in its Registry context declaration and defined by its response schema. A deployment that needs a different view for another audience exposes it as a separate operation or a separate API; one operation does not select among views per request. Access policy can withhold optional fields of the declared view; it does not substitute another schema. A fixed public view is sufficient where it meets the applicable policy. The HTTP binding uses the same Record object for single results and collection members within a declared view. Collections organise access to Records within the Registry's identity scope. The same Record retains its identifier across collections and views. Distinct Records have distinct identifiers within that Registry, including when their source collections use overlapping keys. An adapter can qualify such keys with a stable namespace; consumers continue to treat the resulting identifiers as opaque. @@ -313,7 +360,7 @@ Record schemas define [structured values and references](#structured-values-and- } ``` -The metadata above associates that service with Registry `https://registry.example/registries/business` and the Business Registration Authority. The linked OpenAPI associates the `businesses` collection with that Registry and selects the `business-public` view and its `BusinessData` schema. A consumer retaining this Record's identity stores the Registry Identifier together with `r_42`. +The metadata above associates that service with Registry `https://registry.example/registries/business` and the Business Registration Authority. The Retrieve operation in the linked OpenAPI declares that Registry, the `businesses` collection, and the `business-public` view; its response schema is `BusinessRecord`, whose `data` follows `BusinessData`. A consumer retaining this Record's identity stores the Registry Identifier together with `r_42`. ## Revisions and lifecycle @@ -363,6 +410,8 @@ The same schema document defines `IndividualReference`, whose target Registry is `govstack-bb-digital-registries-fr-core#req-1` +`KF: Registry Core` + An implementation publishes machine-readable Registry metadata containing a globally unique and stable Registry Identifier, a human-readable Registry name, the identity of the Registry Authority, a description of its authoritative scope, and a reference identifying the Digital Registries specification version used to describe the implementation. The publication URI and access conditions are made available to the intended API consumers. **Purpose:** An adopter can determine which Registry and authority stand behind a service, what information that authority accepts responsibility for, and which specification version the description references. @@ -375,6 +424,8 @@ An implementation publishes machine-readable Registry metadata containing a glob `govstack-bb-digital-registries-fr-core#req-2` +`KF: Registry Core` + Every returned Record representation includes a Record Identifier that is unique within an unambiguous Registry context. The applicable binding defines how the consumer determines the Registry Identifier from the request, published contract and service metadata, or the representation itself. Together, the two identifiers uniquely identify the Record. **Purpose:** Consumers can distinguish Records from different Registries and refer to one Record without depending on mutable domain attributes. @@ -387,11 +438,13 @@ Every returned Record representation includes a Record Identifier that is unique `govstack-bb-digital-registries-fr-core#req-3` -An implementation keeps a Record Identifier unchanged throughout that Record's lifecycle and revisions and never reassigns the identifier to a different Record. +`KF: Registry Core` + +An implementation keeps a Record Identifier unchanged throughout that Record's lifecycle and revisions and never reassigns the identifier to a different Record. An adaptor over an existing source can satisfy this by declaring that it inherits the source's identifier policy, when that policy meets these conditions. **Purpose:** A Record reference remains unambiguous after changes, retirement, archival, or deletion. -**Prerequisite:** The implementation has a documented Record Identifier lifecycle policy. +**Prerequisite:** The implementation has a documented Record Identifier lifecycle policy, which can be the source system's policy adopted by an adaptor. **Verification:** Review the identifier policy and evidence showing that successive revisions retain the same identifier, distinct Records do not share an identifier, and retired identifiers are not returned to the allocation pool. @@ -399,6 +452,8 @@ An implementation keeps a Record Identifier unchanged throughout that Record's l `govstack-bb-digital-registries-fr-core#req-4` +`KF: Registry Core` + Every returned Record representation has an unambiguously identified, resolvable machine-readable schema and documented field meanings. The applicable binding identifies its representation format and how the consumer selects the schema. A formal semantic-model reference is provided when required by the selected capability or profile. **Purpose:** Consumers can decode, validate, and interpret a representation without knowledge of internal storage. @@ -411,6 +466,8 @@ Every returned Record representation has an unambiguously identified, resolvable `govstack-bb-digital-registries-fr-core#req-5` +`KF: Registry Core` + When an implemented capability exposes revision or lifecycle metadata, it defines those fields in the representation schema and returns values with the declared source semantics. A capability or profile requiring those fields supplies its additional guarantees; baseline Record reads do not require them. **Purpose:** Consumers can interpret available revision and lifecycle information without inferring guarantees that the source does not provide. @@ -423,6 +480,8 @@ When an implemented capability exposes revision or lifecycle metadata, it define `govstack-bb-digital-registries-fr-core#req-6` +`KF: Registry Core` + The Registry context identifies the responsible Registry Authority through published metadata. When additional Record provenance is exposed, the contract defines its meaning and the implementation returns values supported by the source. A revision recording time is required only when the selected capability or profile requires it; retrieval time is not substituted for recording time. **Purpose:** A consumer can identify the institutional source and interpret available provenance without fabricated source facts. @@ -435,10 +494,26 @@ The Registry context identifies the responsible Registry Authority through publi `govstack-bb-digital-registries-fr-core#req-7` -For each service exposed through the Digital Registries capability model, an implementation publishes a machine-readable service description associated with the Registry. The description identifies the service, its supported API families from the Digital Registries API Families concept scheme, its endpoint, and a link to its machine-readable operational contract. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. Declarations reflect the families and endpoints available for that Registry to the metadata's intended audience and are kept current when those services change. +`KF: Registry Core` + +For each service exposed through the Digital Registries capability model, an implementation publishes a machine-readable service description associated with the Registry. The description identifies the service, its supported API families from the Digital Registries API Families concept scheme, its endpoint, and a link to its machine-readable operational contract. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. The description is part of the Registry metadata document, and the origin hosting an HTTP service locates that document and each contract through `/.well-known/api-catalog` as defined under [discovery publication](#discovery-publication). Declarations reflect the families and endpoints available for that Registry to the metadata's intended audience and are kept current when those services change. **Purpose:** An API Consumer can discover relevant Registry services and follow their contracts to determine the supported operations and invocation details. **Prerequisite:** The Registry publishes at least one service under the capability model and makes the metadata and contract access conditions available to intended consumers. -**Verification:** Obtain the metadata as an intended consumer. For every service exposed to that audience, verify its Registry association, service identifier, valid family classifications, endpoint, and resolvable machine-readable contract. Check that the contract describes the advertised endpoint and contains operations belonging to each declared family. Check declarations against the implementation's published service inventory, including different Registry contexts when an endpoint is shared. A missing required service description or contract fails this check; unrelated internal services are outside its scope. +**Verification:** Request `/.well-known/api-catalog` at each HTTP service origin, check the `application/linkset+json` response, and follow its `service-meta` link to the metadata document as an intended consumer. For every service exposed to that audience, verify its Registry association, service identifier, valid family classifications, endpoint, and resolvable machine-readable contract, and check that the linkset carries a `service-desc` link to that contract. Check that the contract describes the advertised endpoint and contains operations belonging to each declared family. Check declarations against the implementation's published service inventory, including different Registry contexts when an endpoint is shared. A missing required service description or contract fails this check; unrelated internal services are outside its scope. + +### #8 Declare the Registry context of each operation (DRAFT EXTENSIBLE OBSERVABLE) + +`govstack-bb-digital-registries-fr-core#req-8` + +`KF: Registry Core` + +Every operation in a published OpenAPI contract that returns Records declares its Registry Identifier, collection, capability, and view with the `x-govstack-digital-registries` extension, valid against the [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json). The Registry Identifier equals the identifier of a Registry described in the published Registry metadata, and the collection equals the collection segment of the operation path. Operations of one collection that declare the same view use the same Record schema. + +**Purpose:** A consumer or validator can determine from the contract alone which Registry and authority a Record read belongs to and which representation it returns. + +**Prerequisite:** The Registry metadata and the OpenAPI contract are published. + +**Verification:** Validate the extension of every Record-returning operation against the schema. Check that its Registry Identifier resolves to a Registry in the published metadata and that its collection matches the path. Compare the response schemas of operations that share a collection and view and confirm they are identical. diff --git a/spec/09-service-interfaces.md b/spec/09-service-interfaces.md index 9a3ca51..f032006 100644 --- a/spec/09-service-interfaces.md +++ b/spec/09-service-interfaces.md @@ -1,79 +1,24 @@ --- -description: Operational contracts and the draft Consultation HTTP binding. +description: Operational contracts, the Consultation HTTP binding pointer, and protocol options. --- # 9 Service Interfaces ## 9.1 Operational contracts -[Registry Core](05-api-families/registry-core.md#api-family-discovery) requires each exposed Registry service to publish its family classifications, endpoint, and a link to its machine-readable operational contract. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. +[Registry Core](05-api-families/registry-core.md#api-family-discovery) requires each exposed Registry service to publish its family classifications, endpoint, and a link to its machine-readable operational contract. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. Consumers locate the contract and the Registry metadata through the [discovery publication](05-api-families/registry-core.md#discovery-publication) rules. Family classifications identify a service's broad capabilities. The linked contract defines exact operations, parameters, schemas, outcomes, and access requirements. Catalogue descriptions link to these details without reproducing them. A static published description and contract are sufficient; discovery does not require a new runtime service. -[Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) records binding availability. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines conformance status. - -## 9.2 Abstract Consultation operations - -[Consultation](05-api-families/consultation.md) defines the independently selectable Retrieve, Lookup, List, and Search capabilities and their [shared Record representation](05-api-families/consultation.md#retrieve-representation). - -## 9.3 Consultation HTTP binding - -The [canonical OpenAPI](../api/openapi.yaml) defines the synchronous HTTPS/JSON binding, including inputs, schemas, status codes, Problem Details, headers, and security. Its version is `1.0.0-draft`, with `/v1` as the HTTP compatibility line. It uses API Design Guide and ruleset `0.2.0-draft`; the BB requirements remain DRAFT. - -### Scope and deployment contract - -The server URL identifies the deployment root, optionally including a stable prefix such as `/registry`. The major version precedes each collection: `/v1/households` or, with that prefix, `/registry/v1/households`. - -One API can expose multiple collections. Its contract associates each collection with a Registry, membership scope, selected capabilities, and operation schemas. Registry metadata supplies authority and service context. A Record retains its `(registryId, recordId)` identity across collections and views within that Registry. - -A deployment publishes a concrete OpenAPI contract containing its selected operations, service and authentication endpoints, versioned JSON Schemas for `data` and the complete response, selectors, searches, supported filters and ordering, source currency, access policy, and continuation policy. Family classifications describe operations; Consultation and Write may share a resource URI with separate methods, request and response schemas, and permissions. The [OpenAPI examples](../api/examples/README.md) illustrate concrete collections, domain schemas, and response payloads. - -### Operations and inputs - -| HTTP operation, relative to the deployment root | Successful body | Input contract | -|---|---|---| -| `GET /v1/records/{recordId}` | Record | Record Identifier encoded as one path segment. | -| `POST /v1/records:lookup` | Record | JSON object with `selector` and `values`. | -| `GET /v1/records` | Page | Optional `pageSize`, `cursor`, and declared public filter or sort parameters. | -| `POST /v1/records:search` | Page | JSON object with `search`, `criteria`, and optional `pageSize`, `cursor`, and declared `sort`. | - -`records` is the canonical reference name. Deployments publish concrete collection paths, such as `/v1/businesses`; the suffixes `:lookup` and `:search` address operations on that collection. IDs such as `lookup` and `search` remain valid in the item path. - -The binding also exposes the guide's unversioned `/health` operation. Lookup and Search are synchronous reads returning `200`. Their criteria remain in the request body. Lookup uses a declared unique key within its documented scope; Search uses declared typed criteria. The concrete contract defines comparison and normalization rules and rejects unsupported inputs. - -### Representation and schema context +Every Record-returning operation of an OpenAPI contract declares its Registry context with the `x-govstack-digital-registries` extension defined under [API composition](05-api-families/registry-core.md#api-composition). Each API family owns the HTTP binding of its operations and documents it on its own page. -Retrieve and Lookup return `{recordId, data}`. List and Search return `{items, pageInfo}`, with each item using the same Record schema for the declared view. Empty and single-result collections retain the Page shape. - -The endpoint and published contract provide Registry and schema context. Additional source metadata follows [Registry Core](05-api-families/registry-core.md#common-record-context). A schema linked with `rel="describedby"` describes the complete response, including its envelope. A separate summary view has its own declared schema and field meanings. - -### Outcomes, errors, and caching - -The OpenAPI defines HTTP outcomes and RFC 9457 Problem Details. Retrieve and Lookup use `404 record-not-available` for unknown Records and Records outside the collection. Protected Records use the same outcome where [protected-existence handling](05-api-families/consultation.md#retrieve-functional-requirements) applies. Invalid continuations fail explicitly. - -Protected reads and errors use `Cache-Control: no-store`. Deployments may declare caching for public or isolated representations. Optional conditional Retrieve evaluates authorization before returning `304`; its ETag validates the selected HTTP representation. - -### Pagination - -List and Search use forward opaque cursors under [Consultation requirement #7](05-api-families/consultation.md#pagination-contract). The first request selects an effective `pageSize`, defaulting to 20 and bounded to 100 in the canonical contract. A continuation repeats the original criteria, search name where applicable, sorting, and view with the cursor. Omitting `pageSize` retains the bound value; supplying a different value produces `400 invalid-cursor`. - -Cursors bind the operation, Registry, collection, query, view, effective page size, and applicable access context. The deployment declares expiry and rejects malformed, expired, or mismatched cursors, including continuations whose query or view semantics it can no longer preserve. A short or empty Page can carry a non-null `nextCursor` when source processing advances. Traversal completes at `nextCursor: null`. - -Optional `pageInfo.total` is the exact count of the full permitted query at the documented page evaluation time, before applying the continuation boundary. Services omit it when unavailable. OpenAPI defines the cursor format, limits, and error responses. - -### Record references - -The [Core representation rules](05-api-families/registry-core.md#structured-values-and-references) govern nested data and related Records. The reusable `RecordReference` schema carries `recordId` and, where the field schema leaves the target Registry open, required `registryId`. A field with a fixed target Registry permits omission of `registryId` and accepts an explicit value only when it matches that target. - -When a related read is offered, the field binding identifies its target collection, read operation, and operational contract, including how the reference supplies the operation's inputs. Consumers follow that binding and the target's access requirements. Record Identifiers remain opaque; reference identity is independent of the target's current availability. - -Optional client-selected expansion declares its supported paths, bounds, source currency, and disclosure behavior in the deployment contract. The [OpenAPI examples](../api/examples/README.md) demonstrate concrete nested schemas and references. +[Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) records binding availability. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines conformance status. -### Design choices and guide alignment +## 9.2 Consultation -The [read API design decisions](12-other-resources/read-api-design-decisions.md) record the binding choices and the shared guide refinements. +[Consultation](05-api-families/consultation.md) defines the independently selectable Retrieve, Lookup, List, and Search capabilities, their [shared Record representation](05-api-families/consultation.md#retrieve-representation), their [pagination contract](05-api-families/consultation.md#pagination-contract), and the [HTTP binding](05-api-families/consultation.md#http-binding) realised by the [canonical OpenAPI](../api/openapi.yaml). The [read API design decisions](12-other-resources/read-api-design-decisions.md) record the binding choices and the shared guide refinements. -## 9.4 Protocol options for additional capabilities +## 9.3 Protocol options for additional capabilities The following standards provide implementation options. The table does not establish a required specification, version, or profile. diff --git a/spec/10-workflows.md b/spec/10-workflows.md index add162a..406df7a 100644 --- a/spec/10-workflows.md +++ b/spec/10-workflows.md @@ -6,7 +6,7 @@ description: Registry service discovery, current Record reads, exact lookup, and ## 10.1 Discover Registry services and their contracts -This workflow applies to every Registry BB implementation. A publisher can provide the metadata as static documents at a stable URI or through a metadata service. +This workflow applies to every Registry BB implementation. The publisher serves the Registry metadata document and locates it, with each contract, through the RFC 9727 `/.well-known/api-catalog` linkset at the API origin. ### Actors @@ -15,16 +15,16 @@ This workflow applies to every Registry BB implementation. A publisher can provi ### Preconditions -1. The consumer has a metadata entry point, such as a configured URI or a directory entry. +1. The consumer knows the API origin or has a configured metadata document URI. 2. The consumer has any access needed to read the metadata and linked contracts. 3. The publisher provides the Registry metadata and service discovery required by Registry Core. ### Interaction -1. The consumer reads the machine-readable Registry description and selects the Registry by its stable identifier. +1. The consumer requests `/.well-known/api-catalog` at the API origin, follows its `service-meta` link to the Registry metadata document, and selects the Registry by its stable identifier. 2. The consumer inspects its authority, authoritative scope statement, and referenced Digital Registries specification version. 3. The consumer follows the Registry's service associations and reads each service's identifier, API-family labels, endpoint URL, and operational-contract reference for the services available to that consumer's audience. -4. The consumer follows the operational contract to determine the collections, their Registry associations, exact operations, inputs, outputs, and access requirements. For HTTP APIs, this is an OpenAPI description unless the applicable binding defines an established protocol-native description. +4. The consumer follows the operational contract to determine the collections, the Registry context declared on each operation, exact operations, inputs, outputs, and access requirements. For HTTP APIs, this is an OpenAPI description unless the applicable binding defines an established protocol-native description. 5. The consumer selects a suitable operation, or determines that the required operation is unavailable. ### Outcomes @@ -34,6 +34,7 @@ This workflow applies to every Registry BB implementation. A publisher can provi | Required operation appears in a service's linked contract | The consumer can inspect how to invoke that operation. | | A service declares a family but its contract does not offer the required operation | The consumer does not infer that operation from the family label. | | A Registry BB service exposed to the metadata's intended audience is missing from the Registry description, or lacks its identifier, valid family labels, endpoint, or machine-readable contract | The service discovery requirement is not satisfied. | +| The API origin serves no `/.well-known/api-catalog` linkset, or the linkset lacks a `service-meta` link to the metadata document | The discovery publication rules are not satisfied. | ### Postconditions diff --git a/spec/11-testing.md b/spec/11-testing.md index 5ae6c8f..8882963 100644 --- a/spec/11-testing.md +++ b/spec/11-testing.md @@ -47,7 +47,8 @@ Use synthetic fixtures and record the applicability rationale for each omitted c | `fr-core#req-4` | Each implemented operation returning Records | Validate a returned representation | The binding identifies the format and versioned resolvable schema, field meanings are documented, and validation succeeds. A separate formal semantic model is checked only when declared. Nested component and reference meanings, target Registry scope, related-read bindings where offered, and collection completeness are unambiguous. | | `fr-core#req-5` | Source revision or lifecycle metadata is exposed or required by the selected profile | Obtain relevant Record fixtures and source evidence | Provided metadata has documented meaning, matches the source, and is not fabricated from an ETag or adapter fetch. Absence is valid for a profile that does not require it. | | `fr-core#req-6` | Each implemented operation returning Records, with conditional checks for extra provenance | Obtain a known accessible Record and resolve its Registry context | Registry Authority resolves through metadata. Any additional provenance has documented semantics and matches source evidence; a recording timestamp is not fabricated from fetch time. | -| `fr-core#req-7` | Every implementation | Compare services exposed to each intended metadata audience with their published discovery metadata and linked operational contracts | Every exposed Registry BB service is identified, associated with its Registry, and declares valid API-family concepts, an endpoint URL, and a resolvable machine-readable operational contract. The contract describes the advertised endpoint and operations from each declared family; declarations reflect currently available services. | +| `fr-core#req-7` | Every implementation | Request `/.well-known/api-catalog` at each HTTP service origin, follow its `service-meta` link to the metadata document, and compare services exposed to each intended metadata audience with their published discovery metadata and linked operational contracts | Every exposed Registry BB service is identified, associated with its Registry, and declares valid API-family concepts, an endpoint URL, and a resolvable machine-readable operational contract. The contract describes the advertised endpoint and operations from each declared family; declarations reflect currently available services. | +| `fr-core#req-8` | Every implementation publishing an OpenAPI contract | Validate the `x-govstack-digital-registries` extension of every Record-returning operation against its schema and compare it with the published metadata and the operation path | Every such operation declares a Registry Identifier present in the metadata, the collection segment of its path, its capability, and a view; operations sharing a collection and view use one Record schema. | | `fr-consultation#req-1` | Retrieve selected | Retrieve a known accessible Record and a Record outside the collection where applicable | A current permitted collection member returns its required Record context; a Record outside the collection returns `record-not-available`. | | `fr-consultation#req-2` | Every selected Consultation read | Invoke fixtures under applicable consumer contexts; compare responses where entitlements differ | Each response contains only the projection permitted to that consumer, validates against its schema, and does not expose omitted values through related references, embedded fields, errors, or collection metadata. | | `fr-consultation#req-3` | Retrieve or Lookup selected and policy protects Record existence | Resolve unknown and protected fixtures as the same consumer through each selected operation | Status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values match; any differing trace or correlation values are independent of Record existence; neither response contains Record-specific data. | diff --git a/spec/12-other-resources.md b/spec/12-other-resources.md index fe4c188..6f67559 100644 --- a/spec/12-other-resources.md +++ b/spec/12-other-resources.md @@ -12,7 +12,7 @@ The 3.0.0-alpha.2 specification provides the Registry model, DRAFT Core requirem |---|---|---| | Conformance | DRAFT model of Registry Core plus at least one declared capability, with capability-specific applicability | Approved conformance claims and named multi-family conformance profiles | | Registry Core | DRAFT requirements for metadata, scoped Record identity, schema context, documented field meanings, and the interpretation of optional source metadata | Complete schema lifecycle and domain-specific compatibility policies | -| Metadata and discovery | DCAT-based model, vocabulary, JSON-LD context, and examples | Vocabulary and context publication at the assigned `vocab.govstack.global` IRIs; canonical specification-version IRIs; metadata HTTP binding and executable validation shape | +| Metadata and discovery | DCAT-based model, vocabulary, JSON-LD context, metadata document schema, RFC 9727 discovery linkset, OpenAPI Registry context extension, and examples | Vocabulary, context, and schema publication at the assigned `vocab.govstack.global` IRIs; canonical specification-version IRIs | | Authority | Registry Authority identity and declared authoritative scope | Delegation, shared responsibility, and a machine-readable mandate model | | Capabilities | DRAFT Consultation Retrieve, Lookup, List, and Search requirements; informative descriptions of other capabilities | Requirements, contracts, and tests for other capabilities, including Revision History | | Service interfaces | [Canonical draft Consultation OpenAPI](../api/openapi.yaml), shared schemas, and [concrete example contracts](../api/examples/README.md) | Canonical contracts for other API families | @@ -34,7 +34,7 @@ Identity Federation profile ownership and binding remain subject to agreement wi | Shared Record context and domain semantics | [Registry Core](05-api-families/registry-core.md#common-record-context) | | Capability boundaries and selection | [API Families](05-key-functionalities.md) | | Retrieve, exact Lookup, List, Search, and additional read patterns | [Consultation](05-api-families/consultation.md) | -| HTTP contract and shared representation/pagination rules | [Service Interfaces](09-service-interfaces.md) and [canonical OpenAPI](../api/openapi.yaml) | +| HTTP contract and shared representation/pagination rules | [Consultation HTTP binding](05-api-families/consultation.md#http-binding) and [canonical OpenAPI](../api/openapi.yaml) | | Structured values and references | [Core representation rules](05-api-families/registry-core.md#structured-values-and-references) and [OpenAPI examples](../api/examples/README.md) | | Concrete adopter schema and fixtures | [Business Registry schema](../api/examples/business-registry.schema.json) and [request/response fixtures](../api/examples/consultation-exchanges.json) | | Sectoral authentication and cross-Building-Block ownership | [Identity Federation](05-api-families/identity-federation.md) | diff --git a/spec/12-other-resources/references.md b/spec/12-other-resources/references.md index 3ed254d..403f96f 100644 --- a/spec/12-other-resources/references.md +++ b/spec/12-other-resources/references.md @@ -25,6 +25,7 @@ These references inform the capability direction. Only the requirements and cano - [JSON:API 1.1](https://jsonapi.org/format/1.1/), considered as an alternative representation convention - [RFC 9727: api-catalog Well-Known URI and Link Relation](https://www.rfc-editor.org/rfc/rfc9727.html) - [RFC 9264: Linkset Media Types and Link Relation](https://www.rfc-editor.org/rfc/rfc9264.html) +- [RFC 8631: Link Relation Types for Web Services](https://www.rfc-editor.org/rfc/rfc8631.html) - [W3C Data Catalog Vocabulary (DCAT) 3](https://www.w3.org/TR/vocab-dcat-3/) - [AsyncAPI Specification 3.0.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0) - [OGC API Features](https://ogcapi.ogc.org/features/) diff --git a/spec/README.md b/spec/README.md index 479753f..c6eaa90 100644 --- a/spec/README.md +++ b/spec/README.md @@ -10,7 +10,7 @@ The Digital Registries Building Block defines interoperable behaviour for softwa The conformance model combines Registry Core, including machine-readable Registry and service metadata, with at least one declared Registry capability. API families and operations are optional. The specification does not prescribe a database product, administrative user interface, storage model, deployment topology, or domain data model. -The current draft defines Consultation Retrieve, Lookup, List, and Search as independently optional capabilities, with a common Record representation and bounded collection pagination. [Service Interfaces](09-service-interfaces.md) introduces the canonical draft HTTP contract. Registry and schema context can be supplied through the response, endpoint, or versioned contract as the binding specifies. Source revision, lifecycle, and recording-time metadata are optional unless a selected profile or capability requires them. +The current draft defines Consultation Retrieve, Lookup, List, and Search as independently optional capabilities, with a common Record representation and bounded collection pagination. [Service Interfaces](09-service-interfaces.md) introduces the canonical draft HTTP contract. The HTTP binding supplies Registry and schema context through a declaration on each operation of the versioned contract. Source revision, lifecycle, and recording-time metadata are optional unless a selected profile or capability requires them. For this alpha's maturity and conformance status, see [Requirement Maturity](04-conformance.md#41-requirement-maturity). [Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) describes the available specifications and artifacts. diff --git a/tools/requirements-api.txt b/tools/requirements-api.txt index df82ea5..809f3ed 100644 --- a/tools/requirements-api.txt +++ b/tools/requirements-api.txt @@ -5,3 +5,4 @@ PyYAML==6.0.3 referencing==0.37.0 # Enables JSON Schema's IRI format assertion instead of silently skipping it. rfc3987-syntax==1.1.0 +PyLD==2.0.4 diff --git a/tools/validate_consultation.py b/tools/validate_consultation.py index 28335d6..888f336 100644 --- a/tools/validate_consultation.py +++ b/tools/validate_consultation.py @@ -33,7 +33,22 @@ BIRTH = API / "examples/birth-registration.openapi.yaml" RELATIONSHIPS = API / "examples/relationship-examples.schema.json" OPENAPI_DOCUMENTS = (CANONICAL, BUSINESS, HOUSEHOLD, BIRTH) -SCHEMA_DOCUMENTS = (BINDING, RELATIONSHIPS) +EXTENSION = "x-govstack-digital-registries" +EXTENSION_SCHEMA = API / "extensions/x-govstack-digital-registries.schema.json" +METADATA_SCHEMA = API / "extensions/registry-metadata.schema.json" +METADATA_EXAMPLE = API / "examples/registry-metadata.jsonld" +LINKSET_EXAMPLE = API / "examples/api-catalog.linkset.json" +CONTEXT = Path(__file__).resolve().parents[1] / "spec/05-api-families/registry-core-context.jsonld" +CORE_PAGE = Path(__file__).resolve().parents[1] / "spec/05-api-families/registry-core.md" +CONTEXT_URI = "https://vocab.govstack.global/digital-registries/context/v1" +API_FAMILY_PREFIX = "apif:" +CAPABILITY_BY_ROUTE = { + ("get", "item"): "retrieve", + ("get", "collection"): "list", + ("post", "lookup"): "lookup", + ("post", "search"): "search", +} +SCHEMA_DOCUMENTS = (BINDING, RELATIONSHIPS, EXTENSION_SCHEMA, METADATA_SCHEMA) DOCUMENTS: dict[str, dict] = {} @@ -90,6 +105,58 @@ def resolve_object(path: Path, value: dict) -> tuple[Path, dict]: return path, value +def route_kind(path: str, method: str) -> tuple[str, str] | None: + """Classify a Consultation route by its shape: item, collection, :lookup or :search.""" + if not path.startswith("/v1/"): + return None + if path.endswith(":lookup"): + return method, "lookup" + if path.endswith(":search"): + return method, "search" + if path.endswith("/{recordId}"): + return method, "item" + return method, "collection" + + +def collection_segment(path: str) -> str: + return path.removeprefix("/v1/").split("/")[0].split(":")[0] + + +def success_record_schema(path: Path, operation: dict) -> dict: + """Return the resolved Record schema of a 200 response, unwrapping a Page's items.""" + response_path, response = resolve_object(path, operation["responses"]["200"]) + schema_path, schema = resolve_object(response_path, response["content"]["application/json"]["schema"]) + for member in [schema, *schema.get("allOf", [])]: + if "items" in member.get("properties", {}): + schema_path, items = resolve_object(schema_path, member["properties"]["items"]) + schema_path, schema = resolve_object(schema_path, items["items"]) + break + return schema + + +def as_list(value) -> list: + return value if isinstance(value, list) else [value] + + +def fenced_json_blocks(markdown: str, heading: str) -> list[dict]: + """Parse every ```json block between the named heading and the next heading of equal or higher level.""" + lines = markdown.splitlines() + level = heading.count("#", 0, heading.find(" ")) + start = lines.index(heading) + blocks, current = [], None + for line in lines[start + 1:]: + if line.startswith("#") and line.count("#", 0, line.find(" ")) <= level: + break + if line.strip() == "```json": + current = [] + elif line.strip() == "```" and current is not None: + blocks.append(json.loads("\n".join(current))) + current = None + elif current is not None: + current.append(line) + return blocks + + class ConsultationContractTests(unittest.TestCase): def test_required_format_checkers_are_available(self): self.assertIn("iri", FormatChecker().checkers, @@ -364,6 +431,108 @@ def test_registration_snapshots_do_not_require_parent_references(self): self.assertFalse(record_check.is_valid({**record, "data": {**record["data"], "parents": [{"nameAtRegistration": "Example"}] * 5}})) self.assertFalse(record_check.is_valid({**record, "data": {**record["data"], "dateOfBirth": "2020-02-30"}})) + def test_consultation_operations_declare_registry_context(self): + extension_check = validator(EXTENSION_SCHEMA, "") + for path in OPENAPI_DOCUMENTS: + spec = document(path) + views: dict[tuple[str, str, str], tuple[str, dict]] = {} + for route, item in spec["paths"].items(): + for method, operation in item.items(): + kind = route_kind(route, method) + if kind is None: + continue + with self.subTest(file=path.name, operation=operation.get("operationId")): + self.assertIn(EXTENSION, operation, "Every Consultation operation declares its Registry context") + declared = operation[EXTENSION] + extension_check.validate(declared) + self.assertEqual(declared["capability"], CAPABILITY_BY_ROUTE[kind]) + self.assertEqual(declared["collection"], collection_segment(route)) + key = (declared["registry"], declared["collection"], declared["view"]) + schema = success_record_schema(path, operation) + if key in views: + self.assertEqual(views[key][1], schema, + f"{operation['operationId']} and {views[key][0]} share a view but not a Record schema") + views[key] = (operation["operationId"], schema) + for path, invalid in ( + (EXTENSION_SCHEMA, {"registry": "https://registry.example/registries/business", "collection": "businesses", "capability": "retrieve"}), + (EXTENSION_SCHEMA, {"registry": "not an iri", "collection": "businesses", "capability": "retrieve", "view": "public"}), + (EXTENSION_SCHEMA, {"registry": "https://registry.example/registries/business", "collection": "Businesses", "capability": "retrieve", "view": "public"}), + (EXTENSION_SCHEMA, {"registry": "https://registry.example/registries/business", "collection": "businesses", "capability": "delete", "view": "public"}), + (EXTENSION_SCHEMA, {"registry": "https://registry.example/registries/business", "collection": "businesses", "capability": "retrieve", "view": "public", "family": "consultation"}), + ): + self.assertFalse(validator(path, "").is_valid(invalid), invalid) + + def test_registry_metadata_example_is_well_formed(self): + metadata = json.loads(METADATA_EXAMPLE.read_text()) + validator(METADATA_SCHEMA, "").validate(metadata) + self.assertEqual(metadata["@context"], CONTEXT_URI) + from pyld import jsonld + local_context = json.loads(CONTEXT.read_text()) + def loader(url, options=None): + self.assertEqual(url, CONTEXT_URI, "The example must only depend on the shipped context") + return {"contextUrl": None, "documentUrl": url, "document": local_context} + expanded = jsonld.expand(metadata, {"documentLoader": loader}) + by_id = {node["@id"]: node for node in expanded} + registries = [n for n in expanded if "https://vocab.govstack.global/digital-registries#Registry" in n.get("@type", [])] + self.assertTrue(registries, "The example describes at least one Registry") + for registry in registries: + for property_iri in ("http://purl.org/dc/terms/title", "http://purl.org/dc/terms/description", + "http://purl.org/dc/terms/references", + "https://vocab.govstack.global/digital-registries#authority", + "https://vocab.govstack.global/digital-registries#dataService"): + self.assertIn(property_iri, registry, f"{registry['@id']} lacks {property_iri}") + for service_ref in registry["https://vocab.govstack.global/digital-registries#dataService"]: + service = by_id[service_ref["@id"]] + self.assertIn("http://www.w3.org/ns/dcat#DataService", service["@type"]) + families = [t["@id"] for t in service["http://purl.org/dc/terms/type"]] + self.assertTrue(all(f.startswith("https://vocab.govstack.global/digital-registries/api-families#") for f in families)) + self.assertIn("http://www.w3.org/ns/dcat#endpointURL", service) + self.assertIn("http://www.w3.org/ns/dcat#endpointDescription", service) + metadata_check = validator(METADATA_SCHEMA, "") + registry_node = next(n for n in metadata["@graph"] if "govreg:Registry" in as_list(n["@type"])) + for missing in ("title", "authority", "specification", "description", "dataService"): + broken = deepcopy(metadata) + node = next(n for n in broken["@graph"] if n["@id"] == registry_node["@id"]) + del node[missing] + self.assertFalse(metadata_check.is_valid(broken), f"Registry without {missing} must be rejected") + broken = deepcopy(metadata) + broken["@context"] = "https://vocab.govstack.global/digital-registries/context/v2" + self.assertFalse(metadata_check.is_valid(broken), "Only the pinned context version is accepted") + + def test_api_catalog_links_contracts_and_metadata(self): + linkset = json.loads(LINKSET_EXAMPLE.read_text()) + metadata = json.loads(METADATA_EXAMPLE.read_text()) + self.assertEqual(list(linkset), ["linkset"]) + descriptions, metadata_links = set(), set() + for context in linkset["linkset"]: + self.assertTrue(context["anchor"].startswith("https://")) + for link in context.get("service-desc", []): + self.assertTrue(link["href"].startswith("https://")) + self.assertIn(link["type"], ("application/vnd.oai.openapi", "application/vnd.oai.openapi+json")) + descriptions.add(link["href"]) + for link in context.get("service-meta", []): + self.assertEqual(link["type"], "application/ld+json") + metadata_links.add(link["href"]) + services = [n for n in metadata["@graph"] if "dcat:DataService" in as_list(n["@type"])] + self.assertTrue(services) + self.assertEqual({s["endpointDescription"] for s in services}, descriptions, + "The linkset advertises exactly the contracts the metadata declares") + catalog = next(n for n in metadata["@graph"] if "dcat:Catalog" in as_list(n["@type"])) + self.assertEqual(metadata_links, {catalog["@id"]}, "service-meta points at the metadata document") + business = document(BUSINESS) + registry = next(n for n in metadata["@graph"] if "govreg:Registry" in as_list(n["@type"])) + for item in business["paths"].values(): + for method, operation in item.items(): + if route_kind(next(iter(business["paths"])), method) and EXTENSION in operation: + self.assertEqual(operation[EXTENSION]["registry"], registry["@id"]) + + def test_core_page_examples_match_discovery_artifacts(self): + page = CORE_PAGE.read_text() + metadata_blocks = fenced_json_blocks(page, "### Informative JSON-LD example") + self.assertEqual(metadata_blocks, [json.loads(METADATA_EXAMPLE.read_text())]) + linkset_blocks = fenced_json_blocks(page, "### Discovery publication") + self.assertEqual(linkset_blocks, [json.loads(LINKSET_EXAMPLE.read_text())]) + if __name__ == "__main__": unittest.main(verbosity=2) From 27148c5612684e4bae866b40d36f685b62bf48e0 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Wed, 9 Sep 2026 16:38:46 +0700 Subject: [PATCH 09/10] docs: add adopter kit and move RDF vocabulary to an appendix Implementers need four artifacts, not the RDF theory behind them. The new adopter kit lists the OpenAPI contract, metadata document, API catalog linkset, and health endpoint with the files to start from. The DCAT, SKOS, and PROV alignment moves to an informative appendix; Registry Core now speaks in JSON keys and points at the metadata schema. The discovery mechanism (RFC 9727 linkset and the metadata document with its schema) stays normative. Also trims duplicated conformance prose, workflow actor blocks, and the gherkin discovery scenario, and adds a validator test that the adopter kit names every published artifact and that its links resolve. Signed-off-by: Jeremi Joslin --- spec/03-terminology.md | 3 - spec/04-conformance.md | 4 +- spec/05-api-families/registry-core.md | 95 +++++-------------- spec/05-key-functionalities.md | 25 +++-- spec/09-service-interfaces.md | 2 +- spec/10-workflows.md | 17 +--- spec/11-testing.md | 36 +------ spec/12-other-resources.md | 6 +- spec/12-other-resources/adopter-kit.md | 31 ++++++ .../12-other-resources/metadata-vocabulary.md | 78 +++++++++++++++ spec/12-other-resources/migration-from-3.0.md | 2 +- spec/README.md | 2 +- spec/SUMMARY.md | 2 + tools/validate_consultation.py | 22 +++++ 14 files changed, 182 insertions(+), 143 deletions(-) create mode 100644 spec/12-other-resources/adopter-kit.md create mode 100644 spec/12-other-resources/metadata-vocabulary.md diff --git a/spec/03-terminology.md b/spec/03-terminology.md index be1d324..64ee0b1 100644 --- a/spec/03-terminology.md +++ b/spec/03-terminology.md @@ -13,9 +13,7 @@ This specification uses the [GovStack Common Terminology](https://specs.govstack | Authoritative Source | A source for which a named authority accepts responsibility within a declared domain and scope. Authoritative does not imply error-free. | | Binding | A mapping of abstract operations to a transport or established protocol. | | Capability | An independently selectable operation pattern within an API family, such as Retrieve or Search. | -| Capability Declaration | Discovery metadata identifying a supported API family and its service contract. | | Capability Claim | A declaration that an implementation supports a specified API family, capability, and binding and meets the requirements attached to that claim. | -| Conformance Profile | A defined combination of core requirements and capability claims. | | Functional Identifier | An identifier issued and lifecycle-managed for a sector-specific purpose, such as a farmer, student, health, or professional identifier. | | Lifecycle State | When supplied, the state of a Record under a documented vocabulary. A current Record is not necessarily active. | | Lookup | Resolution of a Record using a declared exact selector, such as a registration number or a defined combination of fields. It does not imply general search or approximate matching. | @@ -35,4 +33,3 @@ This specification uses the [GovStack Common Terminology](https://specs.govstack | Search | Retrieval of a bounded collection using criteria declared by the service contract or applicable domain profile. It does not imply a generic query engine. | | Semantic Model | A published vocabulary or domain model for interpreting Registry data. A formal semantic-model reference is optional unless the selected profile requires it; field meanings remain documented. | | Source Recorded At | When supplied, the time at which the source recorded the represented information or revision, with the precise meaning declared by the contract. It is not the time at which an adapter retrieved the information. | -| Sub-pattern | See Capability. | diff --git a/spec/04-conformance.md b/spec/04-conformance.md index c703575..daede94 100644 --- a/spec/04-conformance.md +++ b/spec/04-conformance.md @@ -38,9 +38,7 @@ Registry metadata can describe a Registry for directory participation without es ## 4.4 Capability claims -A capability claim identifies the selected families and capability patterns. Every applicable REQUIRED requirement, operation, contract, and test for a claimed capability forms part of the claim. Consumers determine whether an implementation meets their needs from its declared capabilities and linked operational contracts. - -Publication of a family label and an operational contract describes the service. A conformance claim additionally requires approved capability requirements, contracts, and tests, subject to [Requirement Maturity](#41-requirement-maturity). +A capability claim names the selected families and capabilities; every applicable REQUIRED requirement, operation, contract, and test for a claimed capability forms part of the claim. Publishing a family label and an operational contract describes a service. A conformance claim additionally requires approved capability requirements, contracts, and tests, subject to [Requirement Maturity](#41-requirement-maturity). ## 4.5 Adaptors diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index 5230804..0ed921a 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -38,55 +38,29 @@ The model describes externally observable concepts. An implementation can operat ## Registry metadata -Registry metadata describes the institutionally governed Registry and its relationships to datasets, technical services, and catalogues. +Registry metadata describes the institutionally governed Registry and its relationships to datasets, technical services, and catalogues. An implementation publishes it as one JSON document, as described under [Discovery publication](#discovery-publication). The keys below are defined by the [metadata document schema](../../api/extensions/registry-metadata.schema.json). The [metadata vocabulary appendix](../12-other-resources/metadata-vocabulary.md) explains their DCAT and RDF meaning for catalogue integrators; producing or consuming the document does not require RDF tooling. ### Minimal metadata -| Concept | Status | RDF alignment | Meaning | +| Concept | JSON key | Status | Meaning | |---|---|---|---| -| Registry Identifier | Required | Registry resource IRI | Globally unique and stable identifier for the Registry. | -| Registry Name | Required | [`dct:title`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#title) | Human-readable name used by adopters and consumers. | -| Registry Authority | Required | `govreg:authority` with a [`prov:Agent`](https://www.w3.org/TR/prov-o/#Agent) value | Institution accountable for the Registry and its declared authoritative scope. | -| Digital Registries specification reference | Required | [`dct:references`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#references) | Identifies the versioned Digital Registries specification used to describe the implementation. | -| Description and authoritative scope | Required | [`dct:description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description) | Describes the information for which the named authority accepts responsibility, including relevant domain or jurisdictional boundaries. | -| Governed dataset | Optional and repeatable | `govreg:dataset` with a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset) value | A governed collection of Registry Records described for discovery or exchange. | -| Data service | Required for each exposed Registry service; repeatable | `govreg:dataService` with a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service) value | Associates the Registry with each interface exposed through the Digital Registries capability model. | +| Registry Identifier | `@id` of the Registry | Required | Globally unique and stable identifier for the Registry. | +| Registry Name | `title` | Required | Human-readable name used by adopters and consumers. | +| Registry Authority | `authority` | Required | Institution accountable for the Registry and its declared authoritative scope. | +| Digital Registries specification reference | `specification` | Required | Identifies the versioned Digital Registries specification used to describe the implementation. | +| Description and authoritative scope | `description` | Required | Describes the information for which the named authority accepts responsibility, including relevant domain or jurisdictional boundaries. | +| Governed dataset | `governedDataset` | Optional and repeatable | A governed collection of Registry Records described for discovery or exchange. | +| Data service | `dataService` | Required for each exposed Registry service; repeatable | Associates the Registry with each interface exposed through the Digital Registries capability model. | The scope description states the information for which the Registry Authority accepts responsibility and can reference a fuller scope or mandate document. The Registry Authority, Registry Operator, and catalogue publisher are distinct roles that can be held by the same or different organisations. The adopting ecosystem determines how it accepts or verifies authority declarations. Publication alone does not establish institutional responsibility. -In the JSON-LD context, `specification` maps to `dct:references` and identifies the specification version. A formal claim against an applicable approved specification or profile uses `conformsTo`, mapped to `dct:conformsTo`. [Conformance](../04-conformance.md) defines the conditions for such claims. - -The GovStack vocabulary defines these Registry terms: - -| Term | Meaning | -|---|---| -| `govreg:Registry` | A specialisation of `dcat:Resource` for an institutionally governed system that maintains authoritative Records within a declared scope. | -| `govreg:authority` | Relates a Registry to the institution accountable for it and its authoritative scope. | -| `govreg:dataset` | Relates a Registry to a governed collection described as a DCAT Dataset. | -| `govreg:dataService` | Relates a Registry to a technical interface described as a DCAT Data Service. | - -The [Turtle vocabulary](registry-core-vocabulary.ttl) provides machine-readable definitions of these terms and the API-family concept scheme. - -The vocabulary uses two namespace documents: `https://vocab.govstack.global/digital-registries` for Registry Core and `https://vocab.govstack.global/digital-registries/api-families` for the API-family concept scheme. Terms use stable, version-independent fragment IRIs. Namespace documents can provide HTML, Turtle, and JSON-LD representations through HTTP content negotiation. These vocabulary representations do not prescribe the format of an implementation's metadata. - -The [JSON-LD context](registry-core-context.jsonld) has the assigned publication URI `https://vocab.govstack.global/digital-registries/context/v1` and media type `application/ld+json`. Context versions are immutable and versioned independently of vocabulary terms, preserving the interpretation of existing JSON. See [publication coverage and limitations](../12-other-resources.md#121-coverage-and-limitations) for namespace availability and validation status. - -### DCAT composition - -The model composes Registry metadata with [Data Catalog Vocabulary 3](https://www.w3.org/TR/vocab-dcat-3/) resources: - -- the institutionally governed Registry is a `govreg:Registry`; -- each governed collection can be a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset); -- each technical API or query interface can be a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service); and -- a directory that lists Registries can be a [`dcat:Catalog`](https://www.w3.org/TR/vocab-dcat-3/#Class:Catalog). - -Catalogues can be operated by a Registry or by a national or sector directory serving multiple authorities. +`specification` identifies the specification version used to describe the implementation. A formal claim against an applicable approved specification or profile uses `conformsTo`. [Conformance](../04-conformance.md) defines the conditions for such claims. ### API family discovery -Each service exposed through the Digital Registries capability model identifies its supported API families using [`dct:type`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#type) on its `dcat:DataService` description. Each family value is a concept from the **Digital Registries API Families** scheme, abbreviated by the `apif:` prefix. Declarations cover Registry services available to the metadata's intended audience. +Each service exposed through the Digital Registries capability model identifies its supported API families with `serviceType` values on its data service description. Each value is a concept from the **Digital Registries API Families** scheme, abbreviated by the `apif:` prefix. Declarations cover Registry services available to the metadata's intended audience. -| Concept | API family | +| `serviceType` value | API family | |---|---| | `apif:consultation` | Consultation | | `apif:provisioning` | Provisioning | @@ -97,17 +71,17 @@ Each service exposed through the Digital Registries capability model identifies | `apif:access-transparency` | Access Transparency | | `apif:identity-federation` | Identity Federation | -An API-family type means that the Data Service exposes at least one operation assigned to that family. Supported operations are defined in the contract linked by `dcat:endpointDescription`. Family classification alone establishes neither support for every operation in the family nor conformance to a profile. +An API-family value means that the data service exposes at least one operation assigned to that family. Supported operations are defined in the contract linked by `endpointDescription`. Family classification alone establishes neither support for every operation in the family nor a conformance claim. -Service metadata includes the service identifier, family classifications, `dcat:endpointURL`, and `dcat:endpointDescription`. The linked contract is machine-readable. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. Parameters, request and response schemas, outcomes, and access requirements are defined in that contract. The catalogue supports service discovery; automatic selection and invocation of equivalent operations across implementations is outside this discovery model. +Service metadata includes the service identifier, family classifications, `endpointURL`, and `endpointDescription`. The linked contract is machine-readable. HTTP operations use OpenAPI, or a protocol-native machine-readable description where the selected binding defines one. Parameters, request and response schemas, outcomes, and access requirements are defined in that contract. The metadata supports service discovery; automatic selection and invocation of equivalent operations across implementations is outside this discovery model. -A service description declares only the families available for its associated Registry. Where a shared API offers different families for different Registries, each Registry uses a separate logical Data Service description. Those descriptions can share an endpoint or contract URI. +A service description declares only the families available for its associated Registry. Where a shared API offers different families for different Registries, each Registry uses a separate logical data service description. Those descriptions can share an endpoint or contract URI. ### API composition One API can expose several Record collections and operations from several families. Its contract documents each collection's membership and each operation's inputs, representation, and access requirements. API-family classifications describe capabilities independently of URL structure. -An OpenAPI contract declares the Registry context of each operation that returns Records with the `x-govstack-digital-registries` extension on the Operation Object. The extension carries four values: `registry`, the Registry Identifier, equal to the `@id` of a `govreg:Registry` in the published metadata; `collection`, equal to the collection segment of the operation path; `capability`, one of `retrieve`, `lookup`, `list` and `search`; and `view`, the name of the Record view the operation returns. The [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json) is its normative definition. Operations of one collection that declare the same view return the same Record schema. The extension is the machine-readable link between a Record read and the metadata that identifies its Registry and authority; the [Common Record context](#common-record-context) relies on it. +An OpenAPI contract declares the Registry context of each operation that returns Records with the `x-govstack-digital-registries` extension on the Operation Object. The extension carries four values: `registry`, the Registry Identifier, equal to the `@id` of a Registry in the published metadata; `collection`, equal to the collection segment of the operation path; `capability`, one of `retrieve`, `lookup`, `list` and `search`; and `view`, the name of the Record view the operation returns. The [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json) is its normative definition. Operations of one collection that declare the same view return the same Record schema. The extension is the machine-readable link between a Record read and the metadata that identifies its Registry and authority; the [Common Record context](#common-record-context) relies on it. ```yaml /v1/businesses/{recordId}: @@ -126,7 +100,7 @@ The major version applies to the API contract exposed at that root. Separately e ### Discovery publication -An implementation publishes its Registry metadata as one document compacted with the version 1 JSON-LD context and served as `application/ld+json`. The [metadata document schema](../../api/extensions/registry-metadata.schema.json) defines the compacted shape; the JSON-LD context defines its RDF meaning. The document describes one or more Registries, their governed datasets, and their services. The document URI identifies the document; each Registry has its own Registry Identifier. The document URI is chosen by the deployment, is stable, and is not part of the versioned API surface. +An implementation publishes its Registry metadata as one document compacted with the version 1 JSON-LD context and served as `application/ld+json`. The [metadata document schema](../../api/extensions/registry-metadata.schema.json) defines the compacted shape; the JSON-LD context defines its RDF meaning for consumers that want it. The [adopter kit](../12-other-resources/adopter-kit.md) lists this document alongside the other published artifacts. The document describes one or more Registries, their governed datasets, and their services. The document URI identifies the document; each Registry has its own Registry Identifier. The document URI is chosen by the deployment, is stable, and is not part of the versioned API surface. Consumers locate the document through the [RFC 9727](https://www.rfc-editor.org/rfc/rfc9727.html) API catalog. The origin that hosts a Digital Registries API serves `/.well-known/api-catalog` as an [RFC 9264 linkset](https://www.rfc-editor.org/rfc/rfc9264.html) in `application/linkset+json`, following the GET, HEAD, and HTTPS requirements of RFC 9727. For every Digital Registries API at that origin, the linkset carries a `service-desc` link to the OpenAPI contract and a `service-meta` link, typed `application/ld+json`, to the Registry metadata document. Both link relations are defined by [RFC 8631](https://www.rfc-editor.org/rfc/rfc8631.html). The well-known path is one of the unversioned paths the GovStack API Design Guide permits, so no other root path is needed for discovery. @@ -255,17 +229,7 @@ The Consultation entry illustrates publication of the [business Registry OpenAPI The example uses untagged strings for readability. Deployments can use JSON-LD language maps, such as `"title": {"en": "Business Registry"}`, when publishing multilingual labels. -The Registry has both `govreg:Registry` and [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) types. This explicitly expresses the vocabulary's subclass relationship and lets the catalogue list the Registry with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource), without relying on ontology inference. - -The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in this catalogue. `govreg:dataset` and `govreg:dataService` state which datasets and services belong to this Registry. `dcat:servesDataset` states which dataset a technical service exposes, when applicable. - -An implementation exposing only Evidence uses the same pattern with just the Evidence service in the Registry's `dataService` list and the catalogue's `catalogService` list. - -The same graph pattern covers common deployment arrangements: - -- a single-Registry deployment publishes one Registry, its datasets, and its services in the catalogue; -- a multi-Registry implementation adds more Registry resources and their related datasets and services to the same catalogue; and -- an aggregating national catalogue can list resources from multiple Registry Authorities or use [`dcat:catalog`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_catalog) to include catalogues published by those authorities. +The [metadata vocabulary appendix](../12-other-resources/metadata-vocabulary.md) explains the RDF types and catalogue relationships used in the example and how the same pattern covers multi-Registry implementations and aggregating national catalogues. An implementation exposing only Evidence uses the same pattern with just the Evidence service in the Registry's `dataService` list and the catalogue's `catalogService` list. Catalogue entries contain descriptive metadata only. Services govern disclosure of Record information through their access policies. @@ -275,11 +239,11 @@ A client can discover declared API families without knowing an implementation's 1. Request `/.well-known/api-catalog` at the API origin as `application/linkset+json`, or start from a configured metadata document URI. 2. Follow the `service-meta` link to the metadata document, request it as `application/ld+json`, and check that the response uses that media type. -3. Select the required `govreg:Registry` by its stable Registry Identifier. -4. Follow `govreg:dataService` to each associated `dcat:DataService`. -5. Read each service's `dct:type` values from the Digital Registries API Families scheme, then follow `dcat:endpointDescription` for the exact operations and invocation contract. +3. Select the required Registry by its `@id`, the stable Registry Identifier. +4. Follow `dataService` to each associated data service. +5. Read each service's `serviceType` values, then follow `endpointDescription` for the exact operations and invocation contract. -The following language-neutral pseudocode illustrates the process for a JSON-LD client: +The following language-neutral pseudocode illustrates the process: ```text metadataUri = configuredMetadataUri @@ -310,23 +274,10 @@ for each serviceReference in asList(registry.dataService): return discoveredServices ``` -`loadJsonLd` applies the versioned context and normalises properties that can contain one or several values. `DigitalRegistriesApiFamilies` contains the concepts defined in the [API-family vocabulary](registry-core-vocabulary.ttl); membership is determined by those definitions, not by an IRI prefix. The example returns three Data Services supporting Consultation, Write, and Evidence. +`loadJsonLd` parses the document and normalises properties that can contain one or several values; because the document is compacted with the pinned context, a plain JSON parser is sufficient. `DigitalRegistriesApiFamilies` contains the eight `serviceType` values listed under [API family discovery](#api-family-discovery). The example returns three data services supporting Consultation, Write, and Evidence. The example assumes the selected Registry and its service descriptions are present in the returned graph. Deployments using external descriptions document their retrieval. A service description missing a required family classification or contract reference is incomplete under Core. Operation names alone establish neither a family classification nor a conformance claim. -### External alignments - -Adopting profiles can use external vocabularies to add jurisdictional or discovery semantics. These alignments are optional. - -| Alignment | Intended use | -|---|---| -| Schema.org [`Service`](https://schema.org/Service) or [`GovernmentService`](https://schema.org/GovernmentService) | Web discovery when the Registry or its service facet meets the selected Schema.org type. | -| [Core Public Service Vocabulary Application Profile](https://github.com/SEMICeu/CPSV-AP) | Public-service description in implementations using CPSV or CPSV-AP. | -| [BRegDCAT-AP](https://github.com/SEMICeu/BRegDCAT-AP) | European base-registry catalogue interoperability. | -| National or sector profiles | Additional legal, organisational, service, or dataset metadata required by an adopter. | - -An adopting profile adds types and properties where their semantics apply. Any equivalence between `govreg:Registry` and an external class is specific to that profile. - ## Common Record context Every returned Record representation has the following context. The binding defines where it is conveyed: in the representation, response metadata, or the versioned operational contract and its association with the Registry. The HTTP binding conveys it through the contract: the `x-govstack-digital-registries` extension on each operation names the Registry, collection, capability, and view, and the operation's response schema is the representation schema. A consumer can determine that context without knowing the source's internal storage. Registry-wide information need not be repeated in every Record or collection item. diff --git a/spec/05-key-functionalities.md b/spec/05-key-functionalities.md index 518efcd..b128ee0 100644 --- a/spec/05-key-functionalities.md +++ b/spec/05-key-functionalities.md @@ -24,16 +24,23 @@ Registry Core requires publication of machine-readable Registry and service meta ## 5.3 Family catalogue -| Family | Adopter outcome | Capability patterns | Status in this release | +Consultation is the only family with requirements and a contract in this release. + +| Family | Adopter outcome | Capabilities | Status in this release | |---|---|---|---| -| [Consultation](05-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, Lookup, List, Search, Existence Check, Revision History, Record Match, GIS Query | Retrieve, Lookup, List, and Search have DRAFT requirements and a draft HTTP contract; other patterns are informative. | -| [Provisioning](05-api-families/provisioning.md) | Configure a Registry service and publish its externally visible contracts. | Metadata administration, schemas, capability publication, bulk transfer | Informative | -| [Evidence](05-api-families/evidence.md) | Obtain a signed assertion derived from authoritative Registry information. | Direct attestation, wallet-mediated credential, status | Informative | -| [Write](05-api-families/write.md) | Create a Record or accept a new authoritative revision. | Direct write, governed write, correction | Informative | -| [Notification](05-api-families/notification.md) | Inform authorised subscribers that Registry state changed. | Subscribe, filter, deliver, retry, replay | Informative | -| [Aggregate Data](05-api-families/aggregate-data.md) | Obtain approved statistics derived from Registry Records. | Aggregate query, dataset metadata, published release | Informative | -| [Access Transparency](05-api-families/access-transparency.md) | Obtain a permitted view of access to a related Record. | Access-history consultation | Informative | -| [Identity Federation](05-api-families/identity-federation.md) | Authenticate a person represented by a sectoral Registry Record to a Relying Service and release authorised claims. | Profile ownership and binding to be decided with the Identity team | Informative; cross-BB ownership unresolved | +| [Consultation](05-api-families/consultation.md) | Obtain a permitted representation of Registry information. | Retrieve, Lookup, List, Search | DRAFT requirements and a draft HTTP contract. Existence Check, Revision History, Record Match, and GIS Query are described informatively. | + +The remaining families are informative roadmap descriptions. They have no requirements, contracts, or tests in this release. + +| Family | Adopter outcome | Capabilities | +|---|---|---| +| [Provisioning](05-api-families/provisioning.md) | Configure a Registry service and publish its externally visible contracts. | Metadata administration, schemas, capability publication, bulk transfer | +| [Evidence](05-api-families/evidence.md) | Obtain a signed assertion derived from authoritative Registry information. | Direct attestation, wallet-mediated credential, status | +| [Write](05-api-families/write.md) | Create a Record or accept a new authoritative revision. | Direct write, governed write, correction | +| [Notification](05-api-families/notification.md) | Inform authorised subscribers that Registry state changed. | Subscribe, filter, deliver, retry, replay | +| [Aggregate Data](05-api-families/aggregate-data.md) | Obtain approved statistics derived from Registry Records. | Aggregate query, dataset metadata, published release | +| [Access Transparency](05-api-families/access-transparency.md) | Obtain a permitted view of access to a related Record. | Access-history consultation | +| [Identity Federation](05-api-families/identity-federation.md) | Authenticate a person represented by a sectoral Registry Record to a Relying Service and release authorised claims. | Profile ownership and binding to be decided with the Identity team; cross-BB ownership unresolved | ## 5.4 Selecting families diff --git a/spec/09-service-interfaces.md b/spec/09-service-interfaces.md index f032006..bae4c4f 100644 --- a/spec/09-service-interfaces.md +++ b/spec/09-service-interfaces.md @@ -12,7 +12,7 @@ Family classifications identify a service's broad capabilities. The linked contr Every Record-returning operation of an OpenAPI contract declares its Registry context with the `x-govstack-digital-registries` extension defined under [API composition](05-api-families/registry-core.md#api-composition). Each API family owns the HTTP binding of its operations and documents it on its own page. -[Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) records binding availability. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines conformance status. +The [adopter kit](12-other-resources/adopter-kit.md) lists the artifacts an implementation publishes. [Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) records binding availability. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines conformance status. ## 9.2 Consultation diff --git a/spec/10-workflows.md b/spec/10-workflows.md index 406df7a..445f2d9 100644 --- a/spec/10-workflows.md +++ b/spec/10-workflows.md @@ -8,11 +8,6 @@ description: Registry service discovery, current Record reads, exact lookup, and This workflow applies to every Registry BB implementation. The publisher serves the Registry metadata document and locates it, with each contract, through the RFC 9727 `/.well-known/api-catalog` linkset at the API origin. -### Actors - -- **API Consumer:** discovers a Registry and determines which operations it exposes. -- **Registry metadata publisher:** publishes the Registry description and service descriptions. - ### Preconditions 1. The consumer knows the API origin or has a configured metadata document URI. @@ -29,12 +24,7 @@ This workflow applies to every Registry BB implementation. The publisher serves ### Outcomes -| Condition | Observable outcome | -|---|---| -| Required operation appears in a service's linked contract | The consumer can inspect how to invoke that operation. | -| A service declares a family but its contract does not offer the required operation | The consumer does not infer that operation from the family label. | -| A Registry BB service exposed to the metadata's intended audience is missing from the Registry description, or lacks its identifier, valid family labels, endpoint, or machine-readable contract | The service discovery requirement is not satisfied. | -| The API origin serves no `/.well-known/api-catalog` linkset, or the linkset lacks a `service-meta` link to the metadata document | The discovery publication rules are not satisfied. | +The linked contract, not the family label, tells the consumer which operations exist. Discovery is not satisfied when an exposed service is missing from the Registry description or lacks its identifier, valid family labels, endpoint, or machine-readable contract, or when the origin serves no `/.well-known/api-catalog` linkset with a `service-meta` link to the metadata document. ### Postconditions @@ -46,11 +36,6 @@ This workflow applies to every Registry BB implementation. The publisher serves This workflow applies to implementations selecting Retrieve. The [HTTP binding](../api/openapi.yaml) defines request and response details. -### Actors - -- **API Consumer:** requests a Record. -- **Registry implementation:** resolves the Record and applies access and disclosure policy. - ### Preconditions 1. The published service contract exposes Retrieve and identifies its Registry, collection membership, and representation schema. diff --git a/spec/11-testing.md b/spec/11-testing.md index 8882963..bd7f909 100644 --- a/spec/11-testing.md +++ b/spec/11-testing.md @@ -61,41 +61,7 @@ The abbreviated references in this table use the full `govstack-bb-digital-regis ## 11.4 Behaviour scenarios -The discovery scenarios apply to every implementation. Read scenarios apply to their selected capabilities. Disclosure differences, protected existence, exposed metadata, and bounded-scan behavior additionally require the corresponding conditions in section 11.2. - -```gherkin -Feature: Discover Registry services and their operational contracts - - Scenario: Every exposed service can be discovered - Given an inventory of the Registry BB services exposed to an intended metadata audience - When a consumer reads the published Registry metadata - Then the metadata identifies the Registry, its authority, authoritative scope, and specification version - And every exposed service is associated with that Registry - And each service has an identifier and declares valid API-family concepts, an endpoint URL, and a machine-readable operational contract - And each linked contract describes the advertised endpoint and operations belonging to each declared family - And the declarations reflect the services currently available to that audience - - Scenario: Discover the operations offered by an Evidence service - Given a Registry description linked to an Evidence service - And the service contract exposes Evidence operations without Retrieve - When a consumer inspects the service metadata and contract - Then the consumer identifies the Evidence operations offered by that service - And no Retrieve operation is identified in that service's contract - And the Evidence family label is treated as a service classification rather than a capability conformance claim - - Scenario: The operational contract determines operation availability - Given a service labelled with the Consultation API family - And its operational contract does not include Retrieve - When a consumer checks whether Retrieve is available - Then the consumer finds no Retrieve operation in that service's contract - - Scenario: A missing operational contract fails service discovery verification - Given an exposed Registry BB service associated with its Registry - And the service declares an API-family concept and endpoint URL - But it does not provide a machine-readable operational contract - When its metadata is evaluated against the service discovery requirement - Then that requirement is not satisfied -``` +Discovery is verified through `fr-core#req-7` in the traceability table: every exposed service is reachable through the linkset and the metadata document, a family label does not by itself establish that any particular operation exists, and a service without a machine-readable contract fails the requirement. Read scenarios apply to their selected capabilities. Disclosure differences, protected existence, exposed metadata, and bounded-scan behavior additionally require the corresponding conditions in section 11.2. The following cases apply to the selected read capabilities. Run them against each operation and view to which their fixtures apply. diff --git a/spec/12-other-resources.md b/spec/12-other-resources.md index 6f67559..0b9d890 100644 --- a/spec/12-other-resources.md +++ b/spec/12-other-resources.md @@ -12,7 +12,7 @@ The 3.0.0-alpha.2 specification provides the Registry model, DRAFT Core requirem |---|---|---| | Conformance | DRAFT model of Registry Core plus at least one declared capability, with capability-specific applicability | Approved conformance claims and named multi-family conformance profiles | | Registry Core | DRAFT requirements for metadata, scoped Record identity, schema context, documented field meanings, and the interpretation of optional source metadata | Complete schema lifecycle and domain-specific compatibility policies | -| Metadata and discovery | DCAT-based model, vocabulary, JSON-LD context, metadata document schema, RFC 9727 discovery linkset, OpenAPI Registry context extension, and examples | Vocabulary, context, and schema publication at the assigned `vocab.govstack.global` IRIs; canonical specification-version IRIs | +| Metadata and discovery | JSON metadata document with schema, RFC 9727 discovery linkset, OpenAPI Registry context extension, examples, and an informative DCAT vocabulary appendix | Vocabulary, context, and schema publication at the assigned `vocab.govstack.global` IRIs; canonical specification-version IRIs | | Authority | Registry Authority identity and declared authoritative scope | Delegation, shared responsibility, and a machine-readable mandate model | | Capabilities | DRAFT Consultation Retrieve, Lookup, List, and Search requirements; informative descriptions of other capabilities | Requirements, contracts, and tests for other capabilities, including Revision History | | Service interfaces | [Canonical draft Consultation OpenAPI](../api/openapi.yaml), shared schemas, and [concrete example contracts](../api/examples/README.md) | Canonical contracts for other API families | @@ -29,7 +29,9 @@ Identity Federation profile ownership and binding remain subject to agreement wi |---|---| | Service boundary, implementation choices, and neighbouring Building Blocks | [Description and Scope](02-description-and-scope.md) | | Minimum conformance and capability claims | [Conformance](04-conformance.md) | -| Registry identity, authoritative scope, datasets, and DCAT composition | [Registry Core metadata](05-api-families/registry-core.md#registry-metadata) | +| The artifacts an implementation publishes | [Adopter kit](12-other-resources/adopter-kit.md) | +| Registry identity, authoritative scope, and metadata keys | [Registry Core metadata](05-api-families/registry-core.md#registry-metadata) | +| DCAT, RDF vocabulary, and JSON-LD context | [Metadata vocabulary](12-other-resources/metadata-vocabulary.md) (informative) | | Service discovery and linked operational contracts | [API family discovery](05-api-families/registry-core.md#api-family-discovery) and [Service Interfaces](09-service-interfaces.md) | | Shared Record context and domain semantics | [Registry Core](05-api-families/registry-core.md#common-record-context) | | Capability boundaries and selection | [API Families](05-key-functionalities.md) | diff --git a/spec/12-other-resources/adopter-kit.md b/spec/12-other-resources/adopter-kit.md new file mode 100644 index 0000000..0ecd796 --- /dev/null +++ b/spec/12-other-resources/adopter-kit.md @@ -0,0 +1,31 @@ +--- +description: The four artifacts an implementation publishes, with the files to start from. +--- + +# Adopter kit + +An implementation of Registry Core with Consultation publishes four artifacts. The rest of this specification explains what they mean; this page lists them so that an implementer knows what to produce. + +| Artifact | Where it is served | Start from | Defined by | +|---|---|---|---| +| OpenAPI contract, one per API | A stable URL chosen by the deployment | [Business Registry example](../../api/examples/business-registry.openapi.yaml), which reuses the shared components of the [canonical Consultation OpenAPI](../../api/openapi.yaml) | [Consultation HTTP binding](../05-api-families/consultation.md#http-binding) and [API composition](../05-api-families/registry-core.md#api-composition) | +| Registry metadata document | A stable document URI, served as `application/ld+json` | [Registry metadata example](../../api/examples/registry-metadata.jsonld), validated by the [metadata document schema](../../api/extensions/registry-metadata.schema.json) | [Registry metadata](../05-api-families/registry-core.md#registry-metadata) | +| API catalog linkset | `/.well-known/api-catalog` at the API origin, served as `application/linkset+json` | [API catalog example](../../api/examples/api-catalog.linkset.json) | [Discovery publication](../05-api-families/registry-core.md#discovery-publication) | +| Health endpoint | `/health` at the API origin | The `/health` path of the [canonical Consultation OpenAPI](../../api/openapi.yaml) | GovStack API Design Guide, unversioned health endpoint | + +## Producing the artifacts + +1. **Contract.** Copy the business example, rename its collection and Record schema, and keep the `$ref` links into the canonical OpenAPI for shared parameters, headers, responses, and security schemes. Every Record-returning operation keeps its `x-govstack-digital-registries` declaration, with `registry` set to your Registry Identifier and `collection` equal to the path segment. +2. **Metadata document.** Describe one Registry (`@id`, `title`, `description`, `authority`, `specification`, `dataService`) and one data service per API (`serviceType`, `endpointURL`, `endpointDescription` pointing at the contract). Validate the document against the metadata document schema with any JSON Schema validator. The document is plain JSON; RDF tooling is not needed unless a catalogue integrator wants it, in which case the [metadata vocabulary appendix](metadata-vocabulary.md) explains the mapping. +3. **Linkset.** Serve the API catalog with one `service-desc` link per contract and one `service-meta` link to the metadata document. +4. **Health.** Expose `/health` as declared in the canonical OpenAPI. + +## Checking the artifacts + +The repository's [artifact validator](../../tools/validate_consultation.py) checks the example contracts, schemas, fixtures, metadata document, and linkset shipped with this specification; the [validation commands](../../api/README.md#validation) show how to run it and how to lint a contract with the GovStack API Design Guide linter. Adopters run the same linter against their own contract and validate their metadata document against the schema. [Testing](../11-testing.md) covers verification of a deployed implementation. + +## What is not needed + +- A catalogue API or Provisioning API: static documents satisfy discovery. +- Every API family: minimum conformance is Registry Core plus one declared capability, as defined in [Conformance](../04-conformance.md#43-conformance-model). +- Revision, lifecycle, or provenance metadata, unless a selected capability or profile requires it. diff --git a/spec/12-other-resources/metadata-vocabulary.md b/spec/12-other-resources/metadata-vocabulary.md new file mode 100644 index 0000000..3eaac44 --- /dev/null +++ b/spec/12-other-resources/metadata-vocabulary.md @@ -0,0 +1,78 @@ +--- +description: Informative background on the DCAT, RDF, and JSON-LD meaning of the Registry metadata document. +--- + +# Metadata vocabulary (informative) + +The [Registry metadata document](../05-api-families/registry-core.md#registry-metadata) is plain JSON whose keys are fixed by the [metadata document schema](../../api/extensions/registry-metadata.schema.json). Because it is compacted with a published JSON-LD context, the same document is also an RDF graph aligned with the Data Catalog Vocabulary. This appendix records that alignment for catalogue integrators and vocabulary maintainers. Nothing here adds an obligation for an implementation. + +## Key to term mapping + +| JSON key | RDF term | Notes | +|---|---|---| +| `@id` of the Registry | Registry resource IRI | The Registry Identifier. | +| `title` | [`dct:title`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#title) | Language map allowed. | +| `description` | [`dct:description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description) | Language map allowed. | +| `authority` | `govreg:authority` with a [`prov:Agent`](https://www.w3.org/TR/prov-o/#Agent) value | | +| `specification` | [`dct:references`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#references) | Identifies the specification version used to describe the implementation. | +| `conformsTo` | [`dct:conformsTo`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#conformsTo) | A formal claim against an approved specification or profile. | +| `governedDataset` | `govreg:dataset` with a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset) value | | +| `dataService` | `govreg:dataService` with a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service) value | | +| `serviceType` | [`dct:type`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#type) | Values are concepts of the API-family scheme, prefix `apif:`. | +| `servesDataset` | [`dcat:servesDataset`](https://www.w3.org/TR/vocab-dcat-3/#Property:data_service_serves_dataset) | | +| `endpointURL` | [`dcat:endpointURL`](https://www.w3.org/TR/vocab-dcat-3/#Property:data_service_endpoint_url) | | +| `endpointDescription` | [`dcat:endpointDescription`](https://www.w3.org/TR/vocab-dcat-3/#Property:data_service_endpoint_description) | | +| `publisher`, `catalogResource`, `catalogDataset`, `catalogService` | [`dct:publisher`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#publisher), [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource), [`dcat:dataset`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_dataset), [`dcat:service`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_service) | Catalogue membership. | + +## GovStack vocabulary terms + +| Term | Meaning | +|---|---| +| `govreg:Registry` | A specialisation of `dcat:Resource` for an institutionally governed system that maintains authoritative Records within a declared scope. | +| `govreg:authority` | Relates a Registry to the institution accountable for it and its authoritative scope. | +| `govreg:dataset` | Relates a Registry to a governed collection described as a DCAT Dataset. | +| `govreg:dataService` | Relates a Registry to a technical interface described as a DCAT Data Service. | + +The [Turtle vocabulary](../05-api-families/registry-core-vocabulary.ttl) provides machine-readable definitions of these terms and the API-family concept scheme. + +The vocabulary uses two namespace documents: `https://vocab.govstack.global/digital-registries` for Registry Core and `https://vocab.govstack.global/digital-registries/api-families` for the API-family concept scheme. Terms use stable, version-independent fragment IRIs. Namespace documents can provide HTML, Turtle, and JSON-LD representations through HTTP content negotiation. These vocabulary representations do not prescribe the format of an implementation's metadata. + +The [JSON-LD context](../05-api-families/registry-core-context.jsonld) has the assigned publication URI `https://vocab.govstack.global/digital-registries/context/v1` and media type `application/ld+json`. Context versions are immutable and versioned independently of vocabulary terms, preserving the interpretation of existing JSON. See [publication coverage and limitations](../12-other-resources.md#121-coverage-and-limitations) for namespace availability and validation status. + +## DCAT composition + +The model composes Registry metadata with [Data Catalog Vocabulary 3](https://www.w3.org/TR/vocab-dcat-3/) resources: + +- the institutionally governed Registry is a `govreg:Registry`; +- each governed collection can be a [`dcat:Dataset`](https://www.w3.org/TR/vocab-dcat-3/#Class:Dataset); +- each technical API or query interface can be a [`dcat:DataService`](https://www.w3.org/TR/vocab-dcat-3/#Class:Data_Service); and +- a directory that lists Registries can be a [`dcat:Catalog`](https://www.w3.org/TR/vocab-dcat-3/#Class:Catalog). + +Catalogues can be operated by a Registry or by a national or sector directory serving multiple authorities. + +In the [example document](../05-api-families/registry-core.md#informative-json-ld-example), the Registry has both `govreg:Registry` and [`dcat:Resource`](https://www.w3.org/TR/vocab-dcat-3/#Class:Resource) types. This explicitly expresses the vocabulary's subclass relationship and lets the catalogue list the Registry with [`dcat:resource`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_resource), without relying on ontology inference. + +The relationships have different scopes. `dcat:resource`, `dcat:dataset`, and `dcat:service` state what is listed in a catalogue. `govreg:dataset` and `govreg:dataService` state which datasets and services belong to a Registry. `dcat:servesDataset` states which dataset a technical service exposes, when applicable. + +The same graph pattern covers common deployment arrangements: + +- a single-Registry deployment publishes one Registry, its datasets, and its services in the catalogue; +- a multi-Registry implementation adds more Registry resources and their related datasets and services to the same catalogue; and +- an aggregating national catalogue can list resources from multiple Registry Authorities or use [`dcat:catalog`](https://www.w3.org/TR/vocab-dcat-3/#Property:catalog_catalog) to include catalogues published by those authorities. + +## Processing as RDF + +A consumer that needs RDF expands the document with the pinned context. `DigitalRegistriesApiFamilies` membership is then determined by the concept definitions in the Turtle vocabulary rather than by an IRI prefix. The `serviceType` values expand to concept IRIs under `https://vocab.govstack.global/digital-registries/api-families#`. + +### External alignments + +Adopting profiles can use external vocabularies to add jurisdictional or discovery semantics. These alignments are optional. + +| Alignment | Intended use | +|---|---| +| Schema.org [`Service`](https://schema.org/Service) or [`GovernmentService`](https://schema.org/GovernmentService) | Web discovery when the Registry or its service facet meets the selected Schema.org type. | +| [Core Public Service Vocabulary Application Profile](https://github.com/SEMICeu/CPSV-AP) | Public-service description in implementations using CPSV or CPSV-AP. | +| [BRegDCAT-AP](https://github.com/SEMICeu/BRegDCAT-AP) | European base-registry catalogue interoperability. | +| National or sector profiles | Additional legal, organisational, service, or dataset metadata required by an adopter. | + +An adopting profile adds types and properties where their semantics apply. Any equivalence between `govreg:Registry` and an external class is specific to that profile. diff --git a/spec/12-other-resources/migration-from-3.0.md b/spec/12-other-resources/migration-from-3.0.md index 21b2408..aa602d0 100644 --- a/spec/12-other-resources/migration-from-3.0.md +++ b/spec/12-other-resources/migration-from-3.0.md @@ -47,7 +47,7 @@ The earlier draft also elevated `govstack-cfr-data#req-4` and `govstack-cfr-data | DRS-29 Multiple Registries by API | Duplicate of DRS-2. Mandatory multi-tenancy is retired. | | DRS-30 Publish Registry by API | Duplicate of DRS-4. Moves to optional Provisioning. | | DRS-31 Modify APIs | Duplicate of DRS-5. Capability declaration and linked operational contracts are retained in Core; generated-API product behaviour is retired. | -| DRS-32 Schema and API Discovery | Machine-readable Registry and service metadata publication is required by the DRAFT Core requirements, including API-family classifications, endpoints, and linked operational contracts. Full schema administration is optional Provisioning. The [Registry Core metadata model](../05-api-families/registry-core.md#registry-metadata) defines the DCAT composition; executable conformance validation is not published in this release. | +| DRS-32 Schema and API Discovery | Machine-readable Registry and service metadata publication is required by the DRAFT Core requirements, including API-family classifications, endpoints, and linked operational contracts. Full schema administration is optional Provisioning. The [Registry Core metadata model](../05-api-families/registry-core.md#registry-metadata) defines the metadata document and the [metadata vocabulary appendix](metadata-vocabulary.md) records its DCAT composition; executable conformance validation is not published in this release. | | DRS-33 Applicant CRUD | Split across independently optional Consultation Retrieve, Lookup, List, and Search, and optional Write. The Applicant CRUD framing is retired. | | DRS-34 Swagger Service List | Machine-readable service contracts are retained, including a canonical draft Consultation OpenAPI contract. Swagger UI and live production examples are not conformance requirements. Other protocol-native bindings depend on the applicable GovStack framework rules. | | DRS-35 Personal Data Usage API | Duplicate of DRS-8. Moves to Access Transparency and is generalised from a person-specific identifier to a Record Principal. | diff --git a/spec/README.md b/spec/README.md index c6eaa90..7411938 100644 --- a/spec/README.md +++ b/spec/README.md @@ -18,7 +18,7 @@ For this alpha's maturity and conformance status, see [Requirement Maturity](04- - **Government architects** should begin with [Description and Scope](02-description-and-scope.md) and [Conformance](04-conformance.md) to determine where a Registry fits within a digital government architecture. - **Procurement teams** should use [Conformance](04-conformance.md) to understand capability claims and cite an approved specification version in a tender or acceptance contract. -- **Implementers** should begin with [Registry Core](05-api-families/registry-core.md), then consult the selected [API families](05-key-functionalities.md) and [Service Interfaces](09-service-interfaces.md). The [illustrative business Registry contract](../api/examples/business-registry.openapi.yaml) shows a concrete mapping. +- **Implementers** should begin with the [Adopter kit](12-other-resources/adopter-kit.md), which lists the four artifacts to publish, then read [Registry Core](05-api-families/registry-core.md), the selected [API families](05-key-functionalities.md), and [Service Interfaces](09-service-interfaces.md). The [illustrative business Registry contract](../api/examples/business-registry.openapi.yaml) shows a concrete mapping. - **Conformance testers** should use [Testing](11-testing.md) for verification scenarios and their applicability. ## Authorship diff --git a/spec/SUMMARY.md b/spec/SUMMARY.md index ba16bfd..a723747 100644 --- a/spec/SUMMARY.md +++ b/spec/SUMMARY.md @@ -20,6 +20,8 @@ * [10 Workflows](10-workflows.md) * [11 Testing](11-testing.md) * [12 Other Resources](12-other-resources.md) + * [Adopter kit](12-other-resources/adopter-kit.md) + * [Metadata vocabulary](12-other-resources/metadata-vocabulary.md) * [Migration from 3.0.0-alpha.1](12-other-resources/migration-from-3.0.md) * [Read API design decisions](12-other-resources/read-api-design-decisions.md) * [References](12-other-resources/references.md) diff --git a/tools/validate_consultation.py b/tools/validate_consultation.py index 888f336..c426c84 100644 --- a/tools/validate_consultation.py +++ b/tools/validate_consultation.py @@ -40,6 +40,9 @@ LINKSET_EXAMPLE = API / "examples/api-catalog.linkset.json" CONTEXT = Path(__file__).resolve().parents[1] / "spec/05-api-families/registry-core-context.jsonld" CORE_PAGE = Path(__file__).resolve().parents[1] / "spec/05-api-families/registry-core.md" +SPEC = Path(__file__).resolve().parents[1] / "spec" +ADOPTER_KIT = SPEC / "12-other-resources/adopter-kit.md" +VOCABULARY_APPENDIX = SPEC / "12-other-resources/metadata-vocabulary.md" CONTEXT_URI = "https://vocab.govstack.global/digital-registries/context/v1" API_FAMILY_PREFIX = "apif:" CAPABILITY_BY_ROUTE = { @@ -533,6 +536,25 @@ def test_core_page_examples_match_discovery_artifacts(self): linkset_blocks = fenced_json_blocks(page, "### Discovery publication") self.assertEqual(linkset_blocks, [json.loads(LINKSET_EXAMPLE.read_text())]) + def test_adopter_kit_names_the_published_artifacts_and_links_resolve(self): + page = ADOPTER_KIT.read_text() + for artifact in ("openapi.yaml", "registry-metadata.jsonld", "registry-metadata.schema.json", + "api-catalog.linkset.json", "/.well-known/api-catalog", "/health", "validate_consultation.py"): + self.assertIn(artifact, page) + for source in (ADOPTER_KIT, VOCABULARY_APPENDIX): + for target in re.findall(r"\]\(([^)#\s]+)(?:#[^)]*)?\)", source.read_text()): + if target.startswith("http"): + continue + self.assertTrue((source.parent / target).exists(), f"{source.name} links to missing {target}") + for navigation in (SPEC / "SUMMARY.md", SPEC / "README.md", SPEC / "12-other-resources.md", CORE_PAGE): + self.assertIn("adopter-kit.md", navigation.read_text(), navigation.name) + for navigation in (SPEC / "SUMMARY.md", SPEC / "12-other-resources.md", CORE_PAGE): + self.assertIn("metadata-vocabulary.md", navigation.read_text(), navigation.name) + core = CORE_PAGE.read_text() + self.assertIn("| Concept | JSON key | Status | Meaning |", core, "Core describes metadata by JSON key") + self.assertNotIn("### External alignments", core, "RDF alignments live in the appendix") + self.assertIn("### External alignments", VOCABULARY_APPENDIX.read_text()) + if __name__ == "__main__": unittest.main(verbosity=2) From ca03751e7ab71be55688226a6710a2c804f24160 Mon Sep 17 00:00:00 2001 From: Jeremi Joslin Date: Thu, 10 Sep 2026 13:36:33 +0700 Subject: [PATCH 10/10] Fix Registry consultation applicability and metadata validation Signed-off-by: Jeremi Joslin --- api/README.md | 2 +- .../x-govstack-digital-registries.schema.json | 2 +- spec/05-api-families/consultation.md | 4 ++-- spec/05-api-families/registry-core.md | 16 ++++++------- spec/09-service-interfaces.md | 2 +- spec/11-testing.md | 2 +- spec/12-other-resources/adopter-kit.md | 6 ++--- tools/validate_consultation.py | 24 +++++++++++++++---- 8 files changed, 37 insertions(+), 21 deletions(-) diff --git a/api/README.md b/api/README.md index ded2219..daf27b1 100644 --- a/api/README.md +++ b/api/README.md @@ -28,7 +28,7 @@ The shared Record schemas apply the [Registry Core](../spec/05-api-families/regi representation rules. Core metadata is published as a JSON-LD document that the RFC 9727 `/.well-known/api-catalog` linkset locates. It identifies the Registry and its authority and links each service to its deployed OpenAPI contract. Every -Record-returning operation declares its Registry, collection, capability, and view +Consultation operation declares its Registry, collection, capability, and view with the `x-govstack-digital-registries` extension. Together, the metadata and selected Consultation operations provide the Core + Consultation contract. diff --git a/api/extensions/x-govstack-digital-registries.schema.json b/api/extensions/x-govstack-digital-registries.schema.json index 706bdf4..6a7c1b2 100644 --- a/api/extensions/x-govstack-digital-registries.schema.json +++ b/api/extensions/x-govstack-digital-registries.schema.json @@ -1,7 +1,7 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "x-govstack-digital-registries", - "description": "Registry context declared on every Digital Registries operation of an OpenAPI Operation Object. The values bind the operation to the Registry Identifier published in Registry metadata, to the collection it serves, to its capability and to the single Record view it returns.", + "description": "Registry context declared on the OpenAPI Operation Object of every Consultation operation. The values bind the operation to the Registry Identifier published in Registry metadata, to the collection it serves, to its capability and to the single Record view it returns.", "type": "object", "required": ["registry", "collection", "capability", "view"], "additionalProperties": false, diff --git a/spec/05-api-families/consultation.md b/spec/05-api-families/consultation.md index 79d77b9..488e6e6 100644 --- a/spec/05-api-families/consultation.md +++ b/spec/05-api-families/consultation.md @@ -19,7 +19,7 @@ Consultation defines read access to Registry Records for independently implement Shared requirements apply to every selected capability; operation requirements apply when that capability is selected. Each operation applies to a declared collection with an unambiguous Registry context, representation schema, and access policy. -Consultation interoperates at the level Core defines: operation shapes, the Record envelope, error outcomes, pagination, and discovery are the same for every Registry, while domain fields, selectors, searches, and filters are declared per contract. A consumer reads any conforming Registry with the same client code once it has loaded that Registry's contract. See the [interoperability boundary](registry-core.md#purpose-and-applicability) in Core. +Consultation interoperates at the level Core defines: operation shapes, the Record envelope, error outcomes, pagination, and discovery are the same for every Registry, while domain fields, selectors, searches, and filters are declared per contract. Consumers can reuse protocol and envelope handling; domain-specific selectors, field meanings, and reference bindings still require integration against the published contract. See the [interoperability boundary](registry-core.md#purpose-and-applicability) in Core. ## Common read contract @@ -168,7 +168,7 @@ The [canonical OpenAPI](../../api/openapi.yaml) defines the synchronous HTTPS/JS The server URL identifies the deployment root, optionally including a stable routing prefix such as `/registry`. The major version precedes each collection: `/v1/households` or, with that prefix, `/registry/v1/households`. -A deployment publishes a concrete OpenAPI contract containing its selected operations, service and authentication endpoints, versioned JSON Schemas for `data` and the complete response, selectors, searches, supported filters and ordering, source currency, access policy, and continuation policy. Every Record-returning operation carries the `x-govstack-digital-registries` extension required by [Core requirement #8](registry-core.md#registry-core-functional-requirements); it names the Registry, collection, capability, and view, and the operation's response schema defines that view. The extension is the binding's answer to the Common Record context: the Registry Identifier is not repeated in requests or Records. +A deployment publishes a concrete OpenAPI contract containing its selected operations, service and authentication endpoints, versioned JSON Schemas for `data` and the complete response, selectors, searches, supported filters and ordering, source currency, access policy, and continuation policy. Every selected Consultation operation carries the `x-govstack-digital-registries` extension required by [Core requirement #8](registry-core.md#registry-core-functional-requirements); it names the Registry, collection, capability, and view, and the operation's response schema defines that view. The extension is the binding's answer to the Common Record context: the Registry Identifier is not repeated in requests or Records. One API can expose several collections. A shared API can therefore expose: diff --git a/spec/05-api-families/registry-core.md b/spec/05-api-families/registry-core.md index 0ed921a..4f6d501 100644 --- a/spec/05-api-families/registry-core.md +++ b/spec/05-api-families/registry-core.md @@ -10,14 +10,14 @@ description: Shared identity, metadata, semantics, lifecycle, and provenance for Registry Core defines the common behaviour and metadata shared by the API families. It identifies the Registry, its authority and scope, and its available services. Returned Records have stable identity within an unambiguous Registry context and a documented representation schema. A capability or domain profile can additionally require revision, lifecycle, provenance, or formal semantic-model information. -Core is the interoperability boundary of this specification. Two implementations that conform to Core and the same capability expose the same operation shapes, error model, pagination, discovery mechanism and Record envelope. They do not expose the same domain fields: each deployment declares its own Record schemas in its published contract, and a domain profile can narrow them. A consumer that reads one Registry can read another after loading that Registry's contract, not before. +Core is the interoperability boundary of this specification. Two implementations that conform to Core and the same capability expose the same operation shapes, error model, pagination, discovery mechanism and Record envelope. They do not expose the same domain fields: each deployment declares its own Record schemas in its published contract, and a domain profile can narrow them. Consumers can reuse protocol and envelope handling across Registries; domain-specific inputs and interpretation still require integration against each published contract. The [conformance model](../04-conformance.md) combines Core with at least one selected capability. Core requirements apply as follows: - Registry metadata and service discovery apply to every implementation. - Record representation requirements apply to implemented capabilities that return Records. - Identifier preservation applies where the implementation assigns or maintains Record Identifiers. -- Registry context declaration applies to every published OpenAPI contract. +- The OpenAPI Registry context extension applies to the selected Consultation operations. [Provisioning](provisioning.md) provides optional administrative operations for creating or revising metadata. Publication can also use a static document or an external catalogue. @@ -81,7 +81,7 @@ A service description declares only the families available for its associated Re One API can expose several Record collections and operations from several families. Its contract documents each collection's membership and each operation's inputs, representation, and access requirements. API-family classifications describe capabilities independently of URL structure. -An OpenAPI contract declares the Registry context of each operation that returns Records with the `x-govstack-digital-registries` extension on the Operation Object. The extension carries four values: `registry`, the Registry Identifier, equal to the `@id` of a Registry in the published metadata; `collection`, equal to the collection segment of the operation path; `capability`, one of `retrieve`, `lookup`, `list` and `search`; and `view`, the name of the Record view the operation returns. The [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json) is its normative definition. Operations of one collection that declare the same view return the same Record schema. The extension is the machine-readable link between a Record read and the metadata that identifies its Registry and authority; the [Common Record context](#common-record-context) relies on it. +An OpenAPI contract declares the Registry context of each Consultation operation with the `x-govstack-digital-registries` extension on the Operation Object. The extension carries four values: `registry`, the Registry Identifier, equal to the `@id` of a Registry in the published metadata; `collection`, equal to the collection segment of the operation path; `capability`, one of `retrieve`, `lookup`, `list` and `search`; and `view`, the name of the Record view the operation returns. The [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json) is its normative definition. Operations of one collection that declare the same view return the same Record schema. The extension is the machine-readable link between a Record read and the metadata that identifies its Registry and authority; the [Common Record context](#common-record-context) relies on it. ```yaml /v1/businesses/{recordId}: @@ -280,7 +280,7 @@ The example assumes the selected Registry and its service descriptions are prese ## Common Record context -Every returned Record representation has the following context. The binding defines where it is conveyed: in the representation, response metadata, or the versioned operational contract and its association with the Registry. The HTTP binding conveys it through the contract: the `x-govstack-digital-registries` extension on each operation names the Registry, collection, capability, and view, and the operation's response schema is the representation schema. A consumer can determine that context without knowing the source's internal storage. Registry-wide information need not be repeated in every Record or collection item. +Every returned Record representation has the following context. The binding defines where it is conveyed: in the representation, response metadata, or the versioned operational contract and its association with the Registry. The Consultation HTTP binding conveys it through the contract: the `x-govstack-digital-registries` extension on each operation names the Registry, collection, capability, and view, and the operation's response schema is the representation schema. A consumer can determine that context without knowing the source's internal storage. Registry-wide information need not be repeated in every Record or collection item. | Concept | Baseline contract | |---|---| @@ -291,7 +291,7 @@ Every returned Record representation has the following context. The binding defi | Field meanings | Schema descriptions or linked domain documentation explain field meanings, units, code lists, and relevant absence or null semantics. | | Registry Authority | The Registry context resolves to the authority and authoritative scope published in Registry metadata. | -The applicable capability determines which domain data and metadata the consumer may receive. Each operation returns exactly one declared view, named in its Registry context declaration and defined by its response schema. A deployment that needs a different view for another audience exposes it as a separate operation or a separate API; one operation does not select among views per request. Access policy can withhold optional fields of the declared view; it does not substitute another schema. A fixed public view is sufficient where it meets the applicable policy. The HTTP binding uses the same Record object for single results and collection members within a declared view. +The applicable capability determines which domain data and metadata the consumer may receive. Each operation returns exactly one declared view, defined by its response schema and, for Consultation, named in its Registry context declaration. A deployment that needs a different view for another audience exposes it as a separate operation or a separate API; one operation does not select among views per request. Access policy can withhold optional fields of the declared view; it does not substitute another schema. A fixed public view is sufficient where it meets the applicable policy. The HTTP binding uses the same Record object for single results and collection members within a declared view. Collections organise access to Records within the Registry's identity scope. The same Record retains its identifier across collections and views. Distinct Records have distinct identifiers within that Registry, including when their source collections use overlapping keys. An adapter can qualify such keys with a stable namespace; consumers continue to treat the resulting identifiers as opaque. @@ -461,10 +461,10 @@ For each service exposed through the Digital Registries capability model, an imp `KF: Registry Core` -Every operation in a published OpenAPI contract that returns Records declares its Registry Identifier, collection, capability, and view with the `x-govstack-digital-registries` extension, valid against the [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json). The Registry Identifier equals the identifier of a Registry described in the published Registry metadata, and the collection equals the collection segment of the operation path. Operations of one collection that declare the same view use the same Record schema. +Every Consultation operation in a published OpenAPI contract declares its Registry Identifier, collection, capability, and view with the `x-govstack-digital-registries` extension, valid against the [extension schema](../../api/extensions/x-govstack-digital-registries.schema.json). The Registry Identifier equals the identifier of a Registry described in the published Registry metadata, and the collection equals the collection segment of the operation path. Operations of one collection that declare the same view use the same Record schema. **Purpose:** A consumer or validator can determine from the contract alone which Registry and authority a Record read belongs to and which representation it returns. -**Prerequisite:** The Registry metadata and the OpenAPI contract are published. +**Prerequisite:** At least one Consultation capability is selected, and the Registry metadata and OpenAPI contract are published. -**Verification:** Validate the extension of every Record-returning operation against the schema. Check that its Registry Identifier resolves to a Registry in the published metadata and that its collection matches the path. Compare the response schemas of operations that share a collection and view and confirm they are identical. +**Verification:** Validate the extension of every Consultation operation against the schema. Check that its Registry Identifier resolves to a Registry in the published metadata and that its collection matches the path. Compare the response schemas of operations that share a collection and view and confirm they are identical. diff --git a/spec/09-service-interfaces.md b/spec/09-service-interfaces.md index bae4c4f..949658d 100644 --- a/spec/09-service-interfaces.md +++ b/spec/09-service-interfaces.md @@ -10,7 +10,7 @@ description: Operational contracts, the Consultation HTTP binding pointer, and p Family classifications identify a service's broad capabilities. The linked contract defines exact operations, parameters, schemas, outcomes, and access requirements. Catalogue descriptions link to these details without reproducing them. A static published description and contract are sufficient; discovery does not require a new runtime service. -Every Record-returning operation of an OpenAPI contract declares its Registry context with the `x-govstack-digital-registries` extension defined under [API composition](05-api-families/registry-core.md#api-composition). Each API family owns the HTTP binding of its operations and documents it on its own page. +Every Consultation operation of an OpenAPI contract declares its Registry context with the `x-govstack-digital-registries` extension defined under [API composition](05-api-families/registry-core.md#api-composition). Each API family owns the HTTP binding of its operations and documents it on its own page. The [adopter kit](12-other-resources/adopter-kit.md) lists the artifacts an implementation publishes. [Coverage and Limitations](12-other-resources.md#121-coverage-and-limitations) records binding availability. [Requirement Maturity](04-conformance.md#41-requirement-maturity) defines conformance status. diff --git a/spec/11-testing.md b/spec/11-testing.md index bd7f909..8e6a366 100644 --- a/spec/11-testing.md +++ b/spec/11-testing.md @@ -48,7 +48,7 @@ Use synthetic fixtures and record the applicability rationale for each omitted c | `fr-core#req-5` | Source revision or lifecycle metadata is exposed or required by the selected profile | Obtain relevant Record fixtures and source evidence | Provided metadata has documented meaning, matches the source, and is not fabricated from an ETag or adapter fetch. Absence is valid for a profile that does not require it. | | `fr-core#req-6` | Each implemented operation returning Records, with conditional checks for extra provenance | Obtain a known accessible Record and resolve its Registry context | Registry Authority resolves through metadata. Any additional provenance has documented semantics and matches source evidence; a recording timestamp is not fabricated from fetch time. | | `fr-core#req-7` | Every implementation | Request `/.well-known/api-catalog` at each HTTP service origin, follow its `service-meta` link to the metadata document, and compare services exposed to each intended metadata audience with their published discovery metadata and linked operational contracts | Every exposed Registry BB service is identified, associated with its Registry, and declares valid API-family concepts, an endpoint URL, and a resolvable machine-readable operational contract. The contract describes the advertised endpoint and operations from each declared family; declarations reflect currently available services. | -| `fr-core#req-8` | Every implementation publishing an OpenAPI contract | Validate the `x-govstack-digital-registries` extension of every Record-returning operation against its schema and compare it with the published metadata and the operation path | Every such operation declares a Registry Identifier present in the metadata, the collection segment of its path, its capability, and a view; operations sharing a collection and view use one Record schema. | +| `fr-core#req-8` | Implementations selecting Consultation capabilities | Validate the `x-govstack-digital-registries` extension of every selected Consultation operation against its schema and compare it with the published metadata and the operation path | Every such operation declares a Registry Identifier present in the metadata, the collection segment of its path, its capability, and a view; operations sharing a collection and view use one Record schema. | | `fr-consultation#req-1` | Retrieve selected | Retrieve a known accessible Record and a Record outside the collection where applicable | A current permitted collection member returns its required Record context; a Record outside the collection returns `record-not-available`. | | `fr-consultation#req-2` | Every selected Consultation read | Invoke fixtures under applicable consumer contexts; compare responses where entitlements differ | Each response contains only the projection permitted to that consumer, validates against its schema, and does not expose omitted values through related references, embedded fields, errors, or collection metadata. | | `fr-consultation#req-3` | Retrieve or Lookup selected and policy protects Record existence | Resolve unknown and protected fixtures as the same consumer through each selected operation | Status or protocol outcome, security-relevant response metadata, stable error type, response structure, and non-Record-specific values match; any differing trace or correlation values are independent of Record existence; neither response contains Record-specific data. | diff --git a/spec/12-other-resources/adopter-kit.md b/spec/12-other-resources/adopter-kit.md index 0ecd796..49dd2ab 100644 --- a/spec/12-other-resources/adopter-kit.md +++ b/spec/12-other-resources/adopter-kit.md @@ -11,14 +11,14 @@ An implementation of Registry Core with Consultation publishes four artifacts. T | OpenAPI contract, one per API | A stable URL chosen by the deployment | [Business Registry example](../../api/examples/business-registry.openapi.yaml), which reuses the shared components of the [canonical Consultation OpenAPI](../../api/openapi.yaml) | [Consultation HTTP binding](../05-api-families/consultation.md#http-binding) and [API composition](../05-api-families/registry-core.md#api-composition) | | Registry metadata document | A stable document URI, served as `application/ld+json` | [Registry metadata example](../../api/examples/registry-metadata.jsonld), validated by the [metadata document schema](../../api/extensions/registry-metadata.schema.json) | [Registry metadata](../05-api-families/registry-core.md#registry-metadata) | | API catalog linkset | `/.well-known/api-catalog` at the API origin, served as `application/linkset+json` | [API catalog example](../../api/examples/api-catalog.linkset.json) | [Discovery publication](../05-api-families/registry-core.md#discovery-publication) | -| Health endpoint | `/health` at the API origin | The `/health` path of the [canonical Consultation OpenAPI](../../api/openapi.yaml) | GovStack API Design Guide, unversioned health endpoint | +| Health endpoint | `/health` relative to the OpenAPI server URL, including any routing prefix | The `/health` path of the [canonical Consultation OpenAPI](../../api/openapi.yaml) | GovStack API Design Guide, unversioned health endpoint | ## Producing the artifacts -1. **Contract.** Copy the business example, rename its collection and Record schema, and keep the `$ref` links into the canonical OpenAPI for shared parameters, headers, responses, and security schemes. Every Record-returning operation keeps its `x-govstack-digital-registries` declaration, with `registry` set to your Registry Identifier and `collection` equal to the path segment. +1. **Contract.** Copy the business example, rename its collection and Record schema, and keep the `$ref` links into the canonical OpenAPI for shared parameters, headers, responses, and security schemes. Every selected Consultation operation keeps its `x-govstack-digital-registries` declaration, with `registry` set to your Registry Identifier and `collection` equal to the path segment. 2. **Metadata document.** Describe one Registry (`@id`, `title`, `description`, `authority`, `specification`, `dataService`) and one data service per API (`serviceType`, `endpointURL`, `endpointDescription` pointing at the contract). Validate the document against the metadata document schema with any JSON Schema validator. The document is plain JSON; RDF tooling is not needed unless a catalogue integrator wants it, in which case the [metadata vocabulary appendix](metadata-vocabulary.md) explains the mapping. 3. **Linkset.** Serve the API catalog with one `service-desc` link per contract and one `service-meta` link to the metadata document. -4. **Health.** Expose `/health` as declared in the canonical OpenAPI. +4. **Health.** Expose `/health` relative to the OpenAPI server URL, for example `/registry/health` when that URL includes `/registry`. ## Checking the artifacts diff --git a/tools/validate_consultation.py b/tools/validate_consultation.py index c426c84..4b72f87 100644 --- a/tools/validate_consultation.py +++ b/tools/validate_consultation.py @@ -522,12 +522,28 @@ def test_api_catalog_links_contracts_and_metadata(self): "The linkset advertises exactly the contracts the metadata declares") catalog = next(n for n in metadata["@graph"] if "dcat:Catalog" in as_list(n["@type"])) self.assertEqual(metadata_links, {catalog["@id"]}, "service-meta points at the metadata document") + self.assert_registry_associations(document(BUSINESS), metadata) + + def assert_registry_associations(self, contract, metadata): + registry_ids = {n["@id"] for n in metadata["@graph"] + if "govreg:Registry" in as_list(n["@type"])} + for route, item in contract["paths"].items(): + for method, operation in item.items(): + if route_kind(route, method) and EXTENSION in operation: + self.assertIn(operation[EXTENSION]["registry"], registry_ids) + + def test_registry_association_rejects_undeclared_registry(self): + metadata = json.loads(METADATA_EXAMPLE.read_text()) business = document(BUSINESS) - registry = next(n for n in metadata["@graph"] if "govreg:Registry" in as_list(n["@type"])) - for item in business["paths"].values(): + for route, item in business["paths"].items(): for method, operation in item.items(): - if route_kind(next(iter(business["paths"])), method) and EXTENSION in operation: - self.assertEqual(operation[EXTENSION]["registry"], registry["@id"]) + if EXTENSION not in operation: + continue + with self.subTest(operation=operation["operationId"]): + broken = deepcopy(business) + broken["paths"][route][method][EXTENSION]["registry"] = "https://registry.example/registries/absent" + with self.assertRaises(AssertionError): + self.assert_registry_associations(broken, metadata) def test_core_page_examples_match_discovery_artifacts(self): page = CORE_PAGE.read_text()