Unreleased documentation. These pages follow the main branch and can change before the next release. For supported guidance, use v0.26.1.
Derive a registry from PublicSchema
For the data publisher
If you are a data publisher who finished Create and query your first registry, you
already have bregctl installed. This tutorial derives a registry project from PublicSchema, an
external reference model embedded in the tooling, instead of writing the domain-neutral example
project. You pick a starter selection of concepts and properties, read what init wrote, check and
start the project, then edit the selection and derive it again.
Before you start
Section titled “Before you start”Open a terminal where you want to create the project, and confirm the binary is on your PATH:
bregctl --versionNothing here needs the tutorial-work directory from
Create and query your first registry; this tutorial
derives a project of its own. Docker is needed only later, to start the registry.
Derive a project from PublicSchema
Section titled “Derive a project from PublicSchema”bregctl init writes the domain-neutral example project by default. With --from publicschema, it
derives a project from the PublicSchema 0.3.0 snapshot embedded in the binary instead, guided by a
selection of concepts and properties. --starter household supplies a selection shipped with the
model: the concepts Person, Household, and GroupMembership, with a subset of their properties.
Derive a project from the household starter:
bregctl init household-registry --from publicschema --starter householdInitialized a registry project. 6 artifacts written. revision sha256:<digest>
README.md dev-clients.yaml model/selection.yaml registry.yaml runtime.example.yaml tests/journeys.yaml
finding access.profile.higher_classification 2 paths entities[id=person].accessProfiles[id=operator].readableFields[field=marital-status] finding access.profile.unrestricted_collection 6 paths entities[id=person].accessProfiles[id=operator].rowBoundaries
0 errors, 8 findings.
Next: 1. read household-registry/README.md, then run 'bregctl check household-registry' 2. leave the findings above as they are; the `operator` and `reader` profiles list whole collections on purpose, and the `operator` profile reads 2 fields the model marks sensitive, and household-registry/README.md says where to narrow them 3. run 'bregctl dev household-registry' to start the registry locally and replay household-registry/tests/journeys.yaml 4. replace canonicalBaseIri in household-registry/registry.yaml before you build a production package; the derived value is a reserved .invalid name that never resolves 5. keep household-registry/model/selection.yaml beside the project: edit it and pass it back with --selection to derive a fresh projectEach finding prints a sentence of its own and one path per place it fires; one path per finding is
kept, the rest omitted. init compiled the project before printing its revision, the digest of
the compiled model, and check and dev repeat that revision and every finding until you change
something. Unlike the domain-neutral example, a derived project has no modules/ directory: every
entity lives in registry.yaml. The rest of this tutorial follows the numbered steps in order.
Read what init wrote
Section titled “Read what init wrote”Open household-registry/README.md. It carries the attribution PublicSchema’s license requires:
“The concepts, properties, and code lists in this project are derived from PublicSchema 0.3.0 (https://github.com/PublicSchema/publicschema.org), licensed under CC-BY-4.0 (https://creativecommons.org/licenses/by/4.0/). The derivation selects, renames, and retypes definitions, so this project is a modified form of the model. Keep this notice with the project and with any package built from it.”
Carry the same notice into any package you build from this project; CC-BY-4.0 requires it.
The README lists one section per entity, each naming the PublicSchema concept it came from and a
field table. The person entity, from PublicSchema’s Person:
| Field | Property | Type | Classification |
|---|---|---|---|
person-code | identifier | string, 1 to 64 characters | internal |
given-name | given_name | string, up to 255 characters | internal |
family-name | family_name | string, up to 255 characters | internal |
date-of-birth | date_of_birth | date | internal |
sex | sex | vocabulary-code from sex | internal |
preferred-language | preferred_language | string, up to 64 characters | internal |
phone-number | phone_number | string, up to 255 characters | internal |
marital-status | marital_status | vocabulary-code from marital-status | restricted |
household and group-membership get the same shape lower in the file. The README’s “How the
project was derived” section states the rules that chose these fields and their types;
How a registry is derived from a model
explains them and names what the derivation refuses outright.
household-registry/model/selection.yaml is the input init derived the project from, written back
into the project. Keep it beside the project and edit it to derive again.
Check the project
Section titled “Check the project”Run bregctl check the way the first next step says:
bregctl check household-registryThe report repeats the same revision and the same eight findings, without the artifact list and the
next steps that only init writes. Both codes are expected: the household starter has no tenancy
field to bind a row restriction to, so every operator and reader profile can list a whole
collection, and the operator profile reads the two fields PublicSchema marks sensitive. The
README’s “Access profiles” section names those two fields and says how to narrow either finding
before you build a production package.
Start the registry
Section titled “Start the registry”Start the project as a registry the same way as Create and query your first registry:
bregctl dev household-registryThe first start downloads the pinned PostgreSQL image. Once the registry answers, the report shows
its address, a token endpoint, and one credential per client in dev-clients.yaml: an operator and
a reader, matching this project’s two access profiles.
Before that report, dev replayed household-registry/tests/journeys.yaml against a throwaway
database, then activated the package on an empty one, so the registry starts with no records. To
make the journey’s first record by hand, get a token the way
Create and query your first registry does, then send this body with
the create request:
{ "data": { "personCode": "person-1", "givenName": "example", "familyName": "example", "dateOfBirth": "2024-01-01", "sex": "not_known", "preferredLanguage": "example", "phoneNumber": "example", "maritalStatus": "never_married" }}The journey file writes those field identifiers in kebab case, person-code; the API takes them in
camel case. This project routes them under persons rather than the records route of the
domain-neutral example:
$registry_url/v1/records/persons?accessProfile=operatorThe other routes are households and group-memberships. Stop the registry with
bregctl dev stop household-registry.
bregctl dev stop household-registry --remove also removes the container and its data volume, so
every record you created is gone and the next start begins on an empty database.
Edit the selection and derive again
Section titled “Edit the selection and derive again”model/selection.yaml is ordinary input, not a generated file: edit it and derive again to get a
fresh project from the change. Open household-registry/model/selection.yaml and remove
marital_status from Person’s properties:
- concept: Person properties: - name: given_name - name: family_name - name: date_of_birth - name: sex - name: preferred_language - name: phone_numberDerive a second project from the edited file, into a new directory:
bregctl init household-registry-2 --from publicschema --selection household-registry/model/selection.yamlThe report has a new revision, the same six access.profile.unrestricted_collection findings, and
one access.profile.higher_classification finding left, for group-membership.person; removing
marital_status removed the other one. The person field table in household-registry-2/README.md
no longer lists marital-status, and that README’s “Access profiles” section now reads in the
singular. Any other edit, adding a property or removing one, follows the same cycle: change
model/selection.yaml, derive into a new directory, and read the new README.
Use the interactive wizard
Section titled “Use the interactive wizard”Without --starter or --selection, init --from publicschema asks its questions at a terminal
instead of reading a file:
bregctl init household-registry-3 --from publicschemaNine questions follow: what the registry is called, which concepts become entities, which unchosen concepts would connect them, which properties become fields, how the entities and routes are named, and which code lists the project writes out in full. The last one prints the selection your answers describe and asks whether to derive from it. Every prompt goes to standard error, so a script that captures standard output still gets a clean report. The PublicSchema wizard prompts records each question, what it lists, and what starts ticked.
Without a terminal at all, for example in a script or in CI, the wizard cannot run, and
init --from publicschema alone refuses immediately:
bregctl init refused.
error init.selection.missing arguments `init --from publicschema` asks its questions at a terminal; without one, pass `--selection <FILE>` or `--starter <NAME>` (one of `household`)
1 error, 0 findings.Pass --starter household or --selection <FILE> instead, the way the rest of this tutorial does.
What you built
Section titled “What you built”You derived a project from PublicSchema with a shipped selection, read the attribution and the
fields init chose, checked the project, started it and made its first record by hand, then edited
the selection and derived a second project with one fewer sensitive field.
Troubleshooting
Section titled “Troubleshooting”Create and query your first registry covers the problems common to
every project: a binary that is not on PATH, a port already taken, and a dev start that never
reaches ready because Docker is not running.
| Symptom | Next move |
|---|---|
bregctl dev refuses with dev.failed over a reported version | The installed breg or mint comes from another release than this bregctl. The refusal names the file that answered, the version it reported, and the version this bregctl reports. Install all three from the same release, or put the matching build first on PATH. |
init --from publicschema refuses with init.selection.missing | No terminal is attached, so the wizard cannot ask its questions. Pass --starter household or --selection <FILE> instead. |
init --from publicschema --selection <FILE> refuses over the file | <FILE> is a symbolic link, or larger than 256 KiB. Point --selection at an ordinary file under that size. |
bregctl init cannot parse the edited model/selection.yaml | Compare the indentation of the lines you changed with the rest of the file; a selection is a plain YAML list of entities, each with a properties list under it. |
- How a registry is derived from a model for the rules behind the fields, types, and classifications you read.
- The PublicSchema wizard prompts for the nine questions and their defaults.
- Author a registry project to add fields and entities beyond the selection.
- Query a registry from Python and Node to make the same requests from an application.