Loading

Permissions

The access model itself — grant-only, layered across datastore, field and row — and how a single access decision is reached.

The Permissions Model

This subcategory describes the access model. The screens that configure each part have their own subcategories — Field Security and Record Access Roles — and are referenced where relevant.

Where to find it

Architect Panel → Security:

  • Permissions — named permissions and the groups holding them
  • Record Access Roles — per-record grants

Architect Panel → Data:

  • Datastores — the Permissions row action, where datastore access is granted

Grant-only

Access is granted, never denied. A group holds a list of what it is permitted to do, and anything not on that list is refused.

There is no deny mechanism because there is nothing for it to do — absence is already refusal. That sounds like a limitation and is mostly a simplification: with deny rules, "why can this person see this?" requires evaluating every rule that might apply and their precedence. Without them, the answer is a short list of grants.

The cost is that you cannot express "everybody except" in one step. You grant to those who should have it, which is more typing and considerably easier to review.

Three layers

  1. Datastore — may this group work with this kind of record at all?
  2. Field — which parts of those records may they see and change?
  3. Row — which individual records may they reach?

The layers narrow; they never widen

This is the single most useful rule for reasoning about access. Each layer can only restrict what the layer above allowed.

A field grant does not give access to a datastore the group cannot reach. A record-level grant does not override a datastore permission. So when something is unexpectedly inaccessible, work downwards from the datastore — the fault is almost always at a higher layer than the one being investigated.

Permissions attach to groups

Never to individuals. A person's access is the union of what their groups grant, which is why adding somebody to a group can give more than intended, and why membership deserves as much review as the grants themselves.

Administrators are not a good test

Administrative accounts are generally exempt from these restrictions. Verifying a permission configuration while signed in as one proves nothing at all.

Keep a test account per major group and check through it. This is the most common reason a permission problem reaches production.

Diagnosing access

  1. Which groups is the person actually in?
  2. Does any of those groups have datastore access?
  3. Is the field restricted for those groups?
  4. Does the datastore use row-level access, and do they have a grant?
  5. Are you testing as an exempt account?

Worked example

A caseworker cannot see a case they were told to handle. Datastore access is present; the field matrix is not involved; the datastore uses record access roles and no grant exists for them. They are added as a co-worker on that case, with a reason and an expiry. Four questions, answered in order, and no guessing.

Recommendations

  • Work downwards through the layers when diagnosing.
  • Grant to groups only.
  • Keep test accounts and never verify as an administrator.
  • Prefer more grants to fewer, broader ones — they are easier to review.

Datastore Permissions

Datastore permissions decide whether a group may work with a kind of record at all. Everything else narrows within them.

Where to find it

Architect Panel → Data:

  • Datastores — the Permissions row action on each datastore

Architect Panel → Security:

  • Permissions — the named permissions a grant is composed of

Where it is configured

Architect Panel → DataDatastores, then the Permissions row action on the datastore you want. Not from a menu — this is one of many places the platform surfaces functionality as a row action.

What a grant contains

A grant ties a group to a datastore and lists the named permissions it holds there. Those permissions are the specific capabilities — reading, creating, editing, deleting and so on — rather than a single level.

Because it is a list, a group can hold some capabilities and not others. Read without delete is an ordinary configuration, and it is worth using: most people who need to see records do not need to remove them.

Get this layer right first

Field and row restrictions are refinements. If the datastore layer is wrong, nothing below it can rescue the situation — and a group granted access to a datastore it should not touch at all is a much larger problem than a misconfigured field.

Delete deserves its own decision

It is the capability people grant without thinking, because it arrives alongside edit in most mental models. Deletion is soft here — records go to Trash — which makes it recoverable, not harmless.

Grant it to the groups that genuinely need to remove records, which is usually fewer than have edit.

Start from nothing

A new group should begin with no datastore access and gain what it needs. Copying another group's grants carries across everything that group accumulated, including whatever nobody has reviewed.

Review by datastore, not by group

Both views are useful, but reviewing per datastore answers the question that matters: who can reach this? For a sensitive datastore, that list should be short and every entry should be explicable.

Reviewing per group tends to confirm what you expected; reviewing per datastore surfaces the group you had forgotten about.

Watch for grants to All Users

A datastore granted to the All Users group is granted to every account, including ones created in future, and it cannot be found by reviewing membership because that group has none. Check for it explicitly.

Worked example

A review of a supplier datastore lists five groups with access. Three are expected. One is a project group whose project ended. One is All Users, added years earlier so that staff could look up contact details — which now means every account can read supplier bank references. Both are corrected, and the review is scheduled annually.

Recommendations

  • Fix this layer before configuring anything below it.
  • Grant delete deliberately, to fewer groups than edit.
  • Review per datastore, not only per group.
  • Check for All Users grants explicitly.

Fields Within the Model

Field permissions narrow access within a record somebody can already reach. The configuration screen and its three levels are covered under Field Security; this article is about how the layer fits the model.

Where to find it

Architect Panel → Security:

  • Permissions — the per-field matrix and its levels

Architect Panel → Data:

  • Datastores — where field security is enabled per datastore

It only narrows

A field grant cannot give somebody access to a datastore they do not have. If a group has no datastore permission, configuring their field access changes nothing — and this is the most common misdiagnosis in this area.

Check the layer above before investigating a field problem.

Opt-in per datastore

A datastore with no field permissions configured behaves normally: every field follows the datastore grant. Field security switches on for a datastore the moment you configure something on it.

That has a practical consequence worth knowing: the first restriction you add to a datastore changes how the whole datastore is evaluated, so test the entire form at that point rather than only the field you restricted.

When to reach for it

When one record genuinely mixes sensitivities — an employee record with a name and a salary, a case with a status and a medical note.

The alternative is splitting the datastore in two, and that is almost always worse: two records to keep in step, a relationship to maintain, and reporting that has to rejoin them. Field security keeps one record and narrows the view.

What it cannot do

  • It cannot vary by record. Every record in the datastore is treated the same way — that is the row layer's job.
  • It cannot grant more than the datastore layer allows.
  • It cannot protect a value from somebody who legitimately has access to that field.

The first is the one people expect it to do. "This group can see the salary field, but only on their own team's records" is two layers, not one.

New fields need a decision

A field added to a datastore that uses field security has no explicit permission until you give it one. Set access when you add the field, particularly a sensitive one — the failure here is silent.

Combine with encryption for the sensitive ones

Field security controls who inside the system may see a value. Field encryption protects it if the database or a backup is obtained. They address different threats and the genuinely sensitive fields usually warrant both.

Worked example

An HR datastore restricts salary to read-only for line managers and hides bank details from them entirely. When a new "pension contribution" field is added six months later, it is given the same treatment as salary in the same change — because the team had made that part of their process for that datastore.

Recommendations

  • Check datastore access first on any field problem.
  • Use it instead of splitting a datastore.
  • Set access on new fields as you add them.
  • Pair field security with encryption on the sensitive ones.

Rows Within the Model

Row-level access decides which individual records somebody may reach. The roles and grants are covered under Record Access Roles; this article is about when the layer is needed and how it composes.

Where to find it

Architect Panel → Security:

  • Record Access Roles — the roles and per-record grants
  • Permissions — the datastore layer above it

Architect Panel → Data:

  • Datastores — datastore-level access

The question it answers

Datastore permissions say somebody may work with cases. Row-level access says which cases. Without it, anybody who can open one case can open all of them.

It narrows, like the others

A record-level grant does not give access to a datastore the person cannot otherwise reach. Both must permit it. When a grant appears to have done nothing, the datastore layer is the first thing to check.

When a datastore needs it

  • Records belong to teams, regions or services and should not be visible across them.
  • Records concern individuals, and staff should see only those they are working with.
  • External users see their own records through a portal.
  • Sensitivity varies between records of the same kind.

The alternative to avoid

The instinct is to solve this by splitting the datastore — cases per team, per region, per service. It works until it does not:

  • The same fields are defined many times and drift apart.
  • Reporting has to union everything back together.
  • A record cannot move between teams without being recreated, losing its history.
  • Every new team means a new datastore, forms, views and permissions.

One datastore with row-level access avoids all of it, and a record moving between teams is a change of grant rather than a migration.

Grant to groups and teams

A grant can name an individual, a security group or a team. Prefer the latter two: individual grants become stale the moment somebody changes role, and nobody goes back to tidy them.

Use reasons and expiries

Per-record grants accumulate faster than any other kind, because they are made in the flow of ordinary work rather than as an administrative decision. A reason makes them reviewable and an expiry makes them self-clearing — without both, a record ends up accessible to people nobody chose.

Combine the layers deliberately

The three layers compose into precise access: a caseworker may work with cases (datastore), may see their own team's (row), and may not see the financial assessment on them (field). Each layer answers a different question, and trying to make one of them do another's job is where configurations become unmanageable.

Worked example

An organisation with six service teams keeps one case datastore. Each team is granted access to its own cases through a team role; escalations add the safeguarding group as reviewer with a reason and an expiry. Reporting runs across every case in one query, and a case transferred between teams keeps its full history.

Recommendations

  • One datastore with row-level access, not one per team.
  • Grant to groups and teams rather than individuals.
  • Always record a reason and set an expiry.
  • Let each layer do its own job.

How Access Is Resolved

People belong to several groups and each may say something about the same thing. Understanding how that resolves is what makes access predictable.

Where to find it

Architect Panel → Security:

  • Permissions — the grants themselves
  • Record Access Roles — the row layer

Groups combine as a union

Somebody in several groups holds everything any of those groups grants. There is nothing to subtract, because there are no deny rules — so access only ever accumulates as memberships are added.

The practical consequence: adding somebody to a group to solve one problem can grant considerably more than intended. Look at what a group holds before adding people to it, not afterwards.

The layers evaluate in order

  1. Datastore — if no group grants access, the answer is no and evaluation stops.
  2. Row — where the datastore uses record-level access, is there a grant for this record?
  3. Field — which fields on that record are visible and writable?

Because each layer can only narrow, a "no" at any point is final and nothing below can reverse it.

Working out what somebody can reach

To answer it properly, in order:

  1. List the groups they are actually in — not the ones you expect.
  2. Take the union of datastore grants across those groups.
  3. For each datastore, check whether row-level access applies and what grants exist.
  4. For each, check the field matrix for those groups.

This is genuinely harder on paper than it looks, which is the argument for the next point.

Test rather than reason

Keep a test account per major group and sign in as it. Five minutes of looking beats an hour of working it out from configuration screens, and it catches the group membership nobody remembered.

Never verify as an administrator — administrative accounts are generally exempt, so they see everything regardless of what you configured.

Removing access means removing every grant

Because access is a union, taking somebody out of one group leaves whatever their other groups grant. And a group removal does not remove per-record grants made to them individually.

When somebody changes role, check group memberships and individual record grants. The second is the one that gets missed.

More groups is not more secure

A large set of narrow groups produces heavy overlap, and people end up in six of them for reasons nobody recorded. The union is then very hard to predict.

A smaller set of well-defined groups, each with a clear purpose, gives access that can actually be reasoned about — which is what makes a review meaningful rather than performative.

Worked example

An access review picks ten staff at random and signs in as each with a test account mirroring their group memberships. Two turn out to reach a finance datastore through a group added for a project two years earlier. Nothing in the configuration looked wrong — it only surfaced by looking through their eyes.

Recommendations

  • Check what a group holds before adding anybody to it.
  • Test as a real member rather than reasoning from screens.
  • On a role change, review memberships and record grants.
  • Keep the group set small enough to reason about.