Unreleased documentation. These pages follow the main branch and can change before the next release. For supported guidance, use v0.44.0.
Derive a registry from PublicSchema
For the data publisher
If you would rather start your registry from a published data model than type its fields yourself, derive one from PublicSchema with Base Registry Engine (BReg). In about 30 to 45 minutes you will have a registry of people, households, and household memberships running on your machine, with one person in it that your operator client can read in full and your reader client can read without the sensitive field. You will then edit the saved selection, compare the newly derived candidate with the running package, and carry a local field and its access policy into the intended successor.
Why start from a published model
Section titled “Why start from a published model”PublicSchema is a published vocabulary for social protection and public-service data: people, households, memberships, programmes, and the code lists that describe them. The BReg component carries a copy of PublicSchema 0.3.0, so deriving from it needs no network.
Starting from the model gives you field names, types, and code lists that other institutions
already use, so a ministry system or a partner’s data maps onto your registry without a round of
naming meetings. It also settles the mechanical choices the same way every time: each concept you
select becomes a Record type with an identifier the caller supplies, each property becomes a
bounded field, an enumeration short enough to read becomes a closed list of codes, and a property
the model marks sensitive becomes a restricted field.
The derivation is a starting point, not a governance decision. It cannot know who in your country may read a person’s marital status, or what a record means in law. Those stay with your institution: once derived, the project is ordinary source you edit like any other.
Derive a project
Section titled “Derive a project”The household starter selects three PublicSchema concepts, Person, Household, and
GroupMembership, with some of their properties:
rstack breg 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.yamlIt then reports two warnings. Each says a profile reads a field that is more sensitive than its Record type:
warning[breg.access.profile-higher-classification] recordTypes[id=group-membership].accessProfiles[id=operator].readableFields[field=person] this field is more sensitive than its record type's classification; verify the profile's scope and purpose before disclosing it next: Remove the field from readableFields, or confirm that the profile scopes and purposes admit only callers cleared for this classification.The other warning is for a person’s marital status. It is followed by the count and the next steps:
warning[breg.access.profile-higher-classification] recordTypes[id=person].accessProfiles[id=operator].readableFields[field=marital-status] this field is more sensitive than its record type's classification; verify the profile's scope and purpose before disclosing it next: Remove the field from readableFields, or confirm that the profile scopes and purposes admit only callers cleared for this classification.0 errors, 2 warnings
Next: 1. read household-registry/README.md, then run 'bregctl check household-registry' 2. review the generated access profiles; their required scopes and purposes bound whole-collection access, and household-registry/README.md says where to add row boundaries when callers need row-level separation 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 projecthousehold-registry is a registry project: the
files that define your registry. It declares three
Record types, person, household, and
group-membership, and two access profiles,
operator and reader, each naming what its callers may read and change.
The two warnings are about the operator profile reading fields PublicSchema marks sensitive.
The generated README explains why they exist and how to align the Record type classifications.
Before production, remove fields the operator must not read or confirm that admitted callers are
cleared for them.
Read what init wrote
Section titled “Read what init wrote”Open household-registry/README.md. It lists every Record type with the PublicSchema concept it
came from, its route, and a table of its fields. The person table ends with the field the model
marks sensitive:
| `phone-number` | `phone_number` | string, up to 255 characters | `internal` || `marital-status` | `marital_status` | vocabulary-code from `marital-status` | `restricted` |The README opens with the attribution notice PublicSchema’s license requires:
“The concepts, properties, and code lists in this project are derived from PublicSchema 0.3.0, revision e5cfbbc0161e4d2c802d1acd752ec193253f7820 (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.”
Keep it with the project and with any package you build from it.
model/selection.yaml is the input the project was derived from. You edit it later when you derive
a candidate.
Check the project:
rstack breg check household-registryAuthoring check passed; registry revision sha256:<digest>.The same two warnings follow, each pointing at the line of registry.yaml it is about.
Add an institution-specific field
Section titled “Add an institution-specific field”The selection records what came from PublicSchema, but the derived project is the source you own.
Add an optional note to the person Record type for a local registration reference:
- {id: phone-number, type: string, maximumLength: 255, classification: internal} - {id: marital-status, type: vocabulary-code, vocabulary: marital-status, classification: restricted} - {id: registration-note, type: string, maximumLength: 120, classification: internal}constraints:Give the operator permission to read and write the field. Do not add it to the reader profile, because this registry’s reporting client does not need the local reference:
readableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number, marital-status]writableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number, marital-status]readableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number, marital-status, registration-note]writableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number, marital-status, registration-note]filterableFields: [person-code, given-name, family-name, sex, preferred-language, phone-number, marital-status]Check after an ordinary source edit, before the local runtime packages it:
rstack breg check household-registryThe check still passes with the two classification warnings. A missing writable grant would instead report that the optional stored field has no writer; correct the field or its intended grant before you continue.
Start the registry
Section titled “Start the registry”rstack breg dev start household-registrybregctl dev succeeded. status readyThe first start downloads PostgreSQL and the local token issuer, so allow a few minutes. Before it
reports ready, dev replays the scenarios in tests/journeys.yaml against a throwaway database,
then starts your registry on an empty one. The report also prints the registry’s address, breg url, and one client for each access profile, operator and reader. If dev start stops
because a port is taken, Create your first registry shows how to pick
other ports.
Create a person
Section titled “Create a person”Save the person you will create. The API takes field names in camel case, personCode for the
person-code field:
{ "data": { "personCode": "P-0001", "givenName": "Ama", "familyName": "Mensah", "dateOfBirth": "1990-04-12", "maritalStatus": "married", "registrationNote": "local-ref-17" }}Create it as the local operator client. The API command finds the running project and obtains a
fresh credential. Every write carries an idempotency key, so a retry of the same request never
creates a second person:
rstack breg api /v1/records/persons \ --project household-registry \ --client operator \ --idempotency-key first-person \ --input person.json{ "domainData": { "dateOfBirth": "1990-04-12", "familyName": "Mensah", "givenName": "Ama", "maritalStatus": "married", "personCode": "P-0001", "phoneNumber": null, "preferredLanguage": null, "registrationNote": "local-ref-17", "sex": null }, "recordIdentifier": "<uuid>", "revisionIdentifier": "1"}The response carries the Record the registry now
holds: your fields under domainData, an identifier the registry assigned, and revision 1. Fields you
did not send are null, because the derivation makes no PublicSchema property required.
Read it as a reader
Section titled “Read it as a reader”List people under the reader access profile:
rstack breg api '/v1/records/persons?accessProfile=reader' \ --project household-registry \ --client reader{ "domainData": { "dateOfBirth": "1990-04-12", "familyName": "Mensah", "givenName": "Ama", "personCode": "P-0001", "phoneNumber": null, "preferredLanguage": null, "sex": null }, "recordIdentifier": "<uuid>", "revisionIdentifier": "1"}The same person comes back without maritalStatus or registrationNote. The derivation left the
sensitive PublicSchema field out of the reader grant, and your local policy did the same for the
institution-specific field.
Edit the saved selection and derive a candidate
Section titled “Edit the saved selection and derive a candidate”Open household-registry/model/selection.yaml and remove marital_status from Person:
- concept: Person properties: - name: given_name - name: family_name - name: date_of_birth - name: sex - name: preferred_language - name: phone_number - name: marital_status- concept: HouseholdDerive a candidate from the edited file into a fresh directory. Do not derive over the project you run: a fresh directory keeps the generated result separate from source you have governed locally.
rstack breg init household-registry-2 --from publicschema --selection household-registry/model/selection.yamlThe report has a new revision and one warning, for the membership’s link to a person:
warning[breg.access.profile-higher-classification] recordTypes[id=group-membership].accessProfiles[id=operator].readableFields[field=person] this field is more sensitive than its record type's classification; verify the profile's scope and purpose before disclosing it next: Remove the field from readableFields, or confirm that the profile scopes and purposes admit only callers cleared for this classification.Check the generated candidate, then compare its compiled result with the package the local runtime configuration binds:
rstack breg check household-registry-2rstack breg diff household-registry-2 \ --runtime-config "$(pwd)/household-registry/.breg/dev/runtime.yaml" baseline assurance runtime-bound changes.person.marital-status changes.person.registration-noteThe check passes with the one warning. The diff says baseline assurance runtime-bound and reports
both the intended PublicSchema removal and the unintended loss of registration-note and its
operator grants. Do not seek migration approval for this result: first compare the source and
restore the local decision.
To build a selection by answering questions instead, run rstack breg init <directory> --from publicschema at a terminal. The PublicSchema wizard
prompts describes each question.
Compare the source and reconcile the customization
Section titled “Compare the source and reconcile the customization”Compare the authored registry files before treating the generated directory as a successor:
diff -u household-registry/registry.yaml household-registry-2/registry.yamldiff exits 1 when it finds differences and 2 when the comparison itself fails. Read the
whole comparison. It includes the intended removal of marital-status, but it also shows that the
fresh derivation has no registration-note field or operator grants. The selection can reproduce
model-derived choices; it does not own local fields, classifications, grants, Actions, or other
policy that you added to the project.
Reconcile those decisions manually. Add the field to the candidate:
- {id: phone-number, type: string, maximumLength: 255, classification: internal} - {id: registration-note, type: string, maximumLength: 120, classification: internal}constraints:Restore only the operator grants, preserving the decision not to disclose the field to the reader:
readableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number]writableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number]readableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number, registration-note]writableFields: [person-code, given-name, family-name, date-of-birth, sex, preferred-language, phone-number, registration-note]filterableFields: [person-code, given-name, family-name, sex, preferred-language, phone-number]Do not use an automatic merge tool for this step. Generated source and governed local source have different owners, so review each difference and copy only the intended model and local decisions into the candidate.
Recheck the reconciled project:
rstack breg check household-registry-2The check passes with one warning, for the operator reading the membership’s link to a person. Inspect the compiled model and access policy as well as the YAML:
rstack breg explain model household-registry-2rstack breg explain access household-registry-2 registration-note: internal, optional readable fields ["date-of-birth","family-name","given-name","person-code","phone-number","preferred-language","registration-note","sex"] writable fields ["date-of-birth","family-name","given-name","person-code","phone-number","preferred-language","registration-note","sex"] readable fields ["date-of-birth","family-name","given-name","person-code","phone-number","preferred-language","sex"] writable fields noneConfirm that registration-note remains internal, the operator can read and write it, and the
reader cannot read it. If any of those checks disagree with the policy you intended, edit the
candidate and repeat check and both explanations before comparing packages.
Compare the reconciled candidate again
Section titled “Compare the reconciled candidate again”Repeat the package comparison. rstack breg diff compares the compiled candidate with a package, not
with another source directory. Use the absolute local runtime path so the report verifies the
runtime configuration and its exact package digest binding:
rstack breg diff household-registry-2 \ --runtime-config "$(pwd)/household-registry/.breg/dev/runtime.yaml" baseline assurance runtime-bound finding diff.history.removed-values-retained changes.person.marital-statusRead all changes and findings again. The report still says baseline assurance runtime-bound, but
the removal of registration-note and its operator grants is gone. This candidate removes
marital-status and its grants while retaining registration-note and its operator-only policy.
If you have the active package directory but no runtime file, use --package <absolute-directory>
instead. That path verifies the package’s checksums and re-derives its contents, but the report says
integrity-only because no runtime configuration binds that directory and digest.
The three comparisons answer different questions:
- The source comparison exposes generated and local edits that need manual reconciliation.
- The package diff classifies the effective candidate against the deployed or otherwise verified package.
- Migration approval is a later decision.
diffneither approves a destructive or access change nor authorizes activation.
When the package diff matches your intent, continue with Change an active
registry. That procedure explains which classifications need a
reviewed migration, how to test and package the successor with the active package as its baseline,
and how the migration credential holder reviews and activates it. If the diff contains an
unexpected removal, disclosure change, or unsupported change, keep the running project unchanged,
correct the candidate, then run check, the explanations, and diff again.
Stop the registry
Section titled “Stop the registry”--remove deletes the registry’s database with the person you created. Leave it off to keep the
records for a later dev start:
rstack breg dev stop household-registry --removebregctl dev succeeded. status stoppedThe next tutorial continues from the contact directory of Create your first registry, not from this household registry, so create that one first if you have not; it takes about fifteen minutes. You can declare the same kind of Actions on this project later, as Declare Actions and Proposals describes.
- Change a registry with an Action: change records through a named operation the project declares, instead of a raw write.
Cookies on Registry Stack
We use optional cookies to understand how you use the main Registry Stack website and this documentation. If you contact us, we may link this activity to your enquiry. You can change your choice at any time. Read the privacy policy.
Your browser asks sites not to track you, so optional tracking stays off.
We could not use or save that choice. Optional tracking remains off.