Groups and grants
What a person may do: a grant for each page, how much of a record they see, and the groups that give both.
Where people sign in, what a person may do is a set of grants and a detail level. A grant opens a page, and the detail level decides how much of a record they see there. Groups give both. The desk keeps the groups whether it keeps the people itself, in local mode, or an identity provider signs them in. Where nobody signs in, the local person holds every grant and sees everything.
Grants
A grant names a page and how far a person goes there: see, or work, which includes see. The assistant has a grant of its own, use, and the audit log is only seen. A grant is written as the page and the level, such as query:work or kvasir:see. Home is every signed-in person’s and needs none.
| Page | Grants | See | Work also |
|---|---|---|---|
| Assistant | assistant:use |
conversations of one’s own, sharing them, memory, plans waiting and one’s standing grants | |
| Query | query:see, query:work |
asking, running and charting questions, opening the cards people share, selections and exports | keeping cards and selections, saving, and queuing ask jobs |
| Data | data:see, data:work |
datasets with their steps and batches, Browse, cohorts, ID types, the held files as shapes and counts, and the clinical vocabulary | adding and changing datasets (with Places), reading, pseudonymising, filing a map, merging two subjects, making and changing cohorts and their members, promoting a card’s answer into a cohort, loading a clinical vocabulary and importing clinical rows, cancelling any of these |
| Review | review:see, review:work |
what waits for a person, why a stack was judged so, main scans, the rules, their proposals and quality, rounds | answering and deciding, picking, proposing rules and trying them, reading an open campaign’s results with its raters named; adopting a rule needs work on Data as well |
| Campaigns | campaigns:see, campaigns:work |
the campaigns one is named in, and the label sets | making a campaign, rating, adjudicating, closing, exporting, changing the raters of an open campaign (its maker’s, or work on Review’s), writing a label set of the decisions in force (with Review) |
| Release | release:see, release:work |
the releases made, and the session schemes | making a release, handing it over, withdrawing it, keeping a scheme |
| Handover passwords | handover-password:see, handover-password:work |
showing any handover’s password | typing one when handing over |
| Pipelines | pipelines:see, pipelines:work |
jobs, the catalog with its runtime and starters, runs and logs | starting and cancelling sorts (Sort again among them), picks, session and picture builds (Rebuild visits) and pipeline runs (a run also needs the identifying details level), running body part and post-contrast |
| Models | models:see, models:work |
the models of each task and their cards | registering, admitting, promoting and retiring a model, choosing the one that answers, recording a certificate |
| The install: Overview, Parts, Engine, Desk, Setup | install:see, install:work |
versions, health and the steps of setup | updating and restarting parts, installing dcm2niix, the machine’s folders, adding a pipeline, where pipelines run, the runtime and the starters, their secrets, the setup steps the supervisor makes, uninstalling |
| Language models | kvasir:see, kvasir:work |
where each station goes, the models, and a ChatGPT subscription of one’s own | models, downloads, keys and where stations go |
| The assistant’s settings | assistant-settings:see, assistant-settings:work |
the assistant’s part page | the install’s instructions, everyone’s standing grants, Teaching |
| Places | places:see, places:work |
where scans come from and where releases go | adding places and changing them |
| Backups | database:see, database:work |
the backups, their schedule and the registry’s calendar | changing the schedule and the calendar, backing up and checking |
| People | identity:see, identity:work |
who signs in, the groups, and what each may do | adding people, making groups and changing them, resetting a password, removing a person |
| Audit | audit:see |
the audit log and custody |
The grants keep the names of the pages they were made for: Backups is database, People is identity, and Language models is kvasir.
Three sections open on any of two grants. Review opens for review:see or campaigns:see, so a rater who holds only campaigns finds their campaigns and no queue, rules or subjects. Pipelines opens for pipelines:see or models:see, and each of its pages needs its own grant.
Some acts need two grants: adding a root folder or a dataset needs work on Data and on Places, and adopting a rule needs work on Review and on Data. A ChatGPT subscription of one’s own needs the assistant and see on Kvasir. Anyone who may make a campaign sees the names of the people who can rate it, and nothing more. In Teaching, making a set needs work on Review, and the model steps need work on Kvasir.
Handover passwords is a line of its own in the group editor, not a page. The person who made a release shows and types the passwords of its handovers without it. Admins hold it, and any group can be given it. An agent or a model is refused a password whatever it holds.
Making and removing a key needs work on Backups and on the install, and one subject’s IDs need work on Data and on the install, both at the everything detail level: in practice, an admin.
A sealed sample is hidden from every door. Reading what a system said of one needs sealed:see, which no group gives and the Admins group does not hold; only a token that names it has it.
What they see in records
Beside the grants, each person has one detail level for every page, the lowest first:
| On the desk | Detail | What they see |
|---|---|---|
| Without identifying details | plain |
records without dates, subject codes, sex or age, scanner names or series descriptions, and without sensitive events |
| With identifying details | quasi |
as well, the identifying details: dates, subject codes, sex and age, scanner station names, series and protocol descriptions, a stack’s free text, and the images of a stack |
| Everything | sensitive |
as well, sensitive events, raw identifiers and burned-in annotation |
A job keeps the detail of the person who queued it, so it never reads more than they could.
Summaries at plain
At plain the Query page shows an identifying detail, such as an age, only as its shape, 99 for 47. A question that groups people answers some summaries of it all the same:
| Of an identifying detail, over a group | At plain |
|---|---|
| The mean and the spread (standard deviation) | shown when the group holds 5 people or more with a value, held back below |
| The number of different values | the same |
| The youngest, the oldest, the median, a percentile | never shown as a value: each is one person’s own |
| How many people, how many visits | shown, but a count under 5 people that an identifying detail chose or grouped is held back, with the counts that would give it away by subtraction |
| A list of the people an identifying detail chose | held back whole where it holds 1 to 4 people, its length too |
People are counted, never rows: one person’s five visits are one person. An answer names the columns it held back and why (“a group under 5 subjects”), and a list held back reads as held back, never as empty.
Filters still narrow. At
plaina question may still filter, sort and count by an identifying detail, so asking again with a narrower filter, such as ages 40 to 50 and then 40 to 45, can narrow a value down. The rules hold each answer, not a series of questions. Giveplainonly to people who may see such counts and summaries.
Reading an identifier needs data:work and the sensitive detail together: applying the map, revealing a dataset’s held identifiers, merging two subjects, and pseudonymising a dataset, which reads the identifiers it replaces. What holds no identifier needs the grant alone: the map’s dry run and its report, the held files as shapes and counts, and the identifier types. Identifiers and the map lists them.
An ID type can say it leads to a person wherever it is met, such as a hospital’s record number. Looking a subject up by one needs work on Data and the sensitive detail; looking one up by a study’s own ID needs the quasi detail.
Groups
A group has a name, the grants it gives, a detail level and, where people sign in through an identity provider, the provider’s groups it follows: whoever is in one of those joins the group when they sign in.
A person gets everything all their groups give, with the highest of their detail levels, and on top of that whatever is given to that person alone. Nothing takes away what a group gives: to give someone less, take them out of the group, or make a group that gives less.
An admin holds everything. A person who may change people and groups (work on People) is resolved to every grant and every detail, campaigns and models included, whatever the group that made them an admin was made with. Their form shows every page at its top and every detail with nothing to choose. The assistant may do everything they may, so they have no standing grants to give. A sealed sample stays sealed.
Setting every page, or everything, at once from a person’s or a group’s form does not make an admin: work on People is chosen on its own line, and the form says it makes an admin. The desk refuses a change that would leave nobody with work on People, since nobody could then change people and groups.
Groups and people are changed on the People page, or on the command line below.
A person with no grant is a state, not a fault. Someone who signs in and holds nothing sees one page that says so: the account exists, holds no grant, and pages are given on the People page. Every part refuses them too.
The first four groups
A new desk starts with four groups, and a desk updated from a release before groups makes them the first time it starts. They are made from the steps access used to be, and each old name still works wherever it is met: in a named token, in --role, in an entitlement a provider sends, in --entitlement, in the desk’s export and an app’s entitlement, and in Kvasir’s auth.roles.
| Group | Old name | Gives | Detail |
|---|---|---|---|
| Readers | reader |
data:see, query:work |
plain |
| Reviewers | reviewer |
as Readers, and review:work, pipelines:see, models:see |
quasi |
| Operators | operator |
as Reviewers, and data:work, release:work, pipelines:work, models:work, places:work, install:see, kvasir:see, assistant-settings:see |
sensitive |
| Admins | admin |
every grant | sensitive |
assist |
assistant:use |
The Admins group gives the assistant too, but the name admin stands for every grant but assistant:use, so a provider that sends only admin gives no assistant without assist.
None of the first three groups gives the campaign grants. To let a person rate, make a group that gives campaigns:work (and campaigns:see, which it includes) and put the raters in it.
On an update, each person the desk keeps joins the group of their old step, and a person who could use the assistant keeps it as a grant of their own. Under a provider, the old entitlements it sends always count for their sets, beside what the groups give, so a registration made before groups keeps working. The four are groups like any other: change what they give, or remove the ones you do not want, and they are not made again.
On the command line
Each takes --config FILE, nils-desk.toml unless given.
nils-desk group list
nils-desk group add "Data team" --grant data:work --grant query:work --detail quasi
nils-desk group set "Data team" --grant data:work --grant query:work --grant review:see
nils-desk group set "Data team" --rename "Imaging data"
nils-desk user access bo --group Reviewers --group "Imaging data" --grant assistant:use
nils-desk user access bo --none
nils-desk user list
nils-desk group remove "Imaging data"
--grantnames a grant and--groupa group, and both repeat.--detailisplain,quasiorsensitive.--follows GROUPnames a provider’s group the group follows, and repeats.group setchanges only what it names:--grantreplaces the group’s grants,--detailits detail and--followsthe provider’s groups it follows.--no-grantsand--no-followsclear them, and--rename NEWrenames the group.user accesschanges only what it names too: the person’s groups with--group, the grants they hold alone with--grant, and their own detail with--detail.--nonetakes every group and own grant away, and with none of these it refuses to run.group removeleaves its people what else they hold.
In local mode nils-desk user add takes the same --group, --grant and --detail; see the desk keeps the people. Under a provider, user access changes people who have signed in. A password is changed on the profile page, or by an admin on the People page; nils-desk user password NAME does it from the command line.
Every part checks
The desk signs a short-lived token for each person with their grants and detail, and sends it to the engine, Kvasir and the assistant. Each part checks the token at its own doors, so a page the desk does not show is closed at the part as well, and a caller with no grant for a door is refused with 403. What each part reads is on its own page: the engine, Kvasir and the assistant.
Updated 17 October 2026