Example configurations
A configuration document tells Countersign which record types exist, which fields they have, how they nest, and what each role may write and approve. The reference is docs/configuration.md; this folder holds complete documents to start from.
| File | Domain | Hierarchy | Roles |
|---|---|---|---|
lab-equipment.json |
Laboratory equipment register | Site › Laboratory › Instrument, grouped by Instrument class; Service providers as a plain link | 8 |
Three more configurations are built in as presets with demo data (preset:fleet, preset:property,
preset:clinic, in lib/presets/). To get one as a JSON file, initialise a scratch store from it and run
config show.
lab-equipment.json
The register of laboratory instruments of a company with several sites. It is the document that the walkthrough "Design your own domain" in the configuration reference builds step by step.
| Record type | Id | Prefix | Notable fields |
|---|---|---|---|
| Site | site |
ST |
name, three-letter site code (unique, pattern), country, GMP site (boolean) |
| Laboratory | laboratory |
LB |
name, kind (select), building; parent: site |
| Instrument class | instrument-class |
IC |
name, category (select: Group A, B, C), description |
| Service provider | provider |
SP |
name, accredited (boolean), accreditation number, valid until (date) |
| Instrument | instrument |
EQ |
asset tag (unique, pattern BSL-00417), description, manufacturer, model, serial number, status (select), subject to calibration (boolean), last calibration and calibration due (dates), measuring range (numbers) and its unit, channels (integer 1 to 96), notes; group: instrument class; parent: laboratory; link: service provider |
An instrument inherits options in the order Instrument › Instrument class › Laboratory › Site › default, because its class field is declared before its laboratory field.
| Role | Id | Writes | Approves |
|---|---|---|---|
| Metrologist | metrologist |
instruments, values at instrument level | the same |
| Laboratory Manager | lab-manager |
laboratories, values at laboratory level | those, and instruments and their values |
| Instrument Class Owner | class-owner |
instrument classes, values at class level | the same |
| Site Quality Head | site-quality |
sites, service providers, values at site level | the same |
| Option Steward | steward |
option definitions | option definitions |
| Quality Assurance | qa |
nothing | everything |
| Auditor | auditor |
nothing | nothing (read only) |
| System Owner | system-owner |
import, configure |
nothing |
The role ids are what your identity provider must deliver (as Entra app role values, or mapped from groups with
COUNTERSIGN_ROLE_MAP); see docs/authentication.md.
Options are not part of a configuration: they are records that the Option Steward creates in the application. The document suggests four groups for them (Calibration, Maintenance, Qualification, Data integrity). Options that fit this domain, to give an idea:
| Option | Kind | Default | Typically set at |
|---|---|---|---|
| Calibration interval | number, months, 1 to 60 | 12 | class; shorter for single instruments |
| As-found reading required | yes / no | yes | site or class |
| Calibration performed | selection: In-house, External, Manufacturer | External | class or laboratory |
| Out-of-tolerance escalation | selection: Laboratory manager, Site quality | Laboratory manager | site |
| Requalification after repair | yes / no | yes | class |
| Audit trail review interval | number, months | 12 | class (computerised systems) |
Try it
Validation needs no store:
$ node scripts/countersign.ts config validate examples/config/lab-equipment.json
examples/config/lab-equipment.json is valid: 5 record types, 8 roles. SHA-256 deedf81469275b0b0924282f745841a969e9720a4d76547620b67870aa2d3760
Initialise a scratch SQLite store from it:
$ export COUNTERSIGN_STORAGE=sqlite COUNTERSIGN_DATA_FILE=./scratch/lab.sqlite
$ node scripts/countersign.ts init --config examples/config/lab-equipment.json
Initialised the sqlite store with 1 entry from examples/config/lab-equipment.json. Head #1 d6c42fbaa8ada24a95b5f5f67fdfa318f9f3b9e0c2c38482cc52794f4722945a
$ node scripts/countersign.ts status
store sqlite
entries 1
head hash d6c42fbaa8ada24a95b5f5f67fdfa318f9f3b9e0c2c38482cc52794f4722945a
configuration lab-equipment "Laboratory equipment register", revision 1, SHA-256 deedf81469275b0b0924282f745841a969e9720a4d76547620b67870aa2d3760
records 0 (0 including removed)
integrity ok
The head hash differs on every run, because the first entry carries the time it was written. The configuration's SHA-256 is always the one shown: it is the fingerprint of the document's content.
To work with it in the browser, start the server on that store with a sign-in method that delivers the role ids above. For a trial without an identity provider, use the demo sign-in and name the people to pick from:
export COUNTERSIGN_AUTH=demo COUNTERSIGN_SESSION_SECRET="$(openssl rand -base64 48)"
export COUNTERSIGN_DEMO_USERS='[{"id":"mia","name":"Mia Keller","roles":["metrologist"]},{"id":"noor","name":"Noor Haddad","roles":["lab-manager"]}]'
npm run dev
Evaluation only; see docs/developer-setup.md.
Writing your own
- Copy
lab-equipment.json, changeidandname, and replace the record types and roles. node scripts/countersign.ts config validate <file>until it is valid.- Initialise a scratch store and try it as each role.
- Keep the file under version control. Once a store has been initialised from it, later changes are applied with
config apply, with a reason and a reviewer; see docs/configuration.md.