Type to search pages and rules.

Browse pages

Access

Who may act in the product and how they reach it: actors, roles, permissions, entry points, and external systems. Product owners approve these records above the review line, and stacks enforce them in authorization code below it. The model page states the shared record rules, and the domain page states the use cases that need permissions.

Markdown15 provisions

Concepts#

The Permission Chain#

Access follows one chain from actor to use case: an actor holds a role at a scope, the role allows permissions, and the use case needs permissions. The chain answers every access question in one place: which actor held which role at which scope, which permission the role allowed, and which use case needed it. The domain page states how a use case names the permissions it needs.

The chain is role-based access control: permissions attach to roles, never to actors directly, and scopes bound each hold to one reach. The lineage page names the practice LiteSpec borrows.

Actors, Roles, and Scopes#

An actor is one party that acts in the product. Its kind is person for a human acting directly, organization for a company or group acting as one party, or system for software acting on its own.

A role is one named set of permissions granted together. Its scope is a kebab-case level naming the reach of the grant, such as platform, tenant, or self. An actor records each grant in holds as the role with the scope at which it holds it, so the same role grants different reach in different places.

Permissions#

A permission is one allowed action. The project keeps every permission in one shared list, and each permission states in meaning what it allows in one sentence. Roles allow permissions from that list, and use cases need them, so the list is the one vocabulary both sides share.

Entry Points#

An entry point is one way people or systems reach the product. Its kind is app for an interactive application, api for a public interface, cli for a command line, job for background work without a request, or reaction for behavior an event causes. Use cases name the entry points that reach them, so every operation shows how callers arrive.

External Systems#

An external system is one system outside the bounded context that the product exchanges messages with, such as a payment provider or a text gateway. It acts inside the product as one actor, named in actor, so everything it does stays attributable to a party the access records know. It names each message it sends in sends and each message it receives in receives, and it states in failure what the product does when the system fails, such as queueing notices until the gateway answers.

Homes and Summaries#

Each access record lives in one home, and the model page states the shared identifier and ownership rules.

TypeStored asHome
actorpagedocs/domain/actors/<name>.md
rolepagedocs/domain/roles/<name>.md
permissionentrydocs/domain/permissions.md
entry-pointentrydocs/domain/entry-points.md
external-systempagedocs/domain/systems/<name>.md

An actor, role, or external system page carries a Summary section stating what the record is for. The permission and entry point lists carry entries only, with no body section.

Standards#

Keep Access Records in Their Homes#

ruleguidance
litespec/core/access#keep-access-records-in-their-homes
Statement

An access record MUST live in the home its type names.

Why

One home per type tells a reader where to open a record and tells the book where to render it. A record kept anywhere else looks written while readers open the home and find nothing there.

Checka reviewer answers

Actor, role, and external system pages sit under docs/domain/actors/, docs/domain/roles/, and docs/domain/systems/; permission and entry point entries sit in docs/domain/permissions.md and docs/domain/entry-points.md.

Marked guidance: a reviewer answers this question.

Name Every Actor with Its Kind#

rulecheckable
litespec/core/access#name-every-actor-with-its-kind
Statement

An actor MUST name its kind in kind.

Why

The kind tells a reviewer whether a human, an organization, or software stands behind the actor, which decides who answers for what it does. Without the kind, a reviewer assigns responsibility without knowing whether a person or software stands behind the actor.

Example

An employee actor carries person, and a payout service carries system.

Checkchecked by a tool

litespec model check reports record-shape for an actor without kind and invalid-field for a kind outside person, organization, and system.

Marked checkable: the tool named here checks it.

Record Every Role Hold with Its Scope#

ruleguidance
litespec/core/access#record-every-role-hold-with-its-scope
Statement

An actor that acts through a role MUST record the hold in holds.

Why

The hold is the grant: without it, the actor and the role sit on separate pages with no stated connection, and no reviewer can tell what the actor is allowed to do. The scope bounds each grant, so one role grants platform reach to one actor and self reach to another.

Example

JSON
"holds": [{ "role": "role/employee", "scope": "self" }]
Checka reviewer answers

Each actor page under docs/domain/actors/ names in holds every role the actor acts through, with the scope of each grant.

Marked guidance: a reviewer answers this question.

Scope Every Role#

rulecheckable
litespec/core/access#scope-every-role
Statement

A role MUST name its scope in scope.

Why

The scope bounds what the role reaches: the same permission allows platform-wide action in one grant and own-record action in another. Without a named scope, every grant reads as product-wide, and the narrowest grant gets the widest reach.

Example

A scope of team bounds the role to one team, while platform bounds it to the whole product.

Checkchecked by a tool

litespec model check reports record-shape for a role without scope and invalid-field for a scope outside kebab-case form.

Marked checkable: the tool named here checks it.

Grant Permissions Through Roles#

rulecheckable
litespec/core/access#grant-permissions-through-roles
Statement

A role MUST name the permissions it allows in allows.

Why

The allows list is the middle of the chain: it joins the actors that hold the role to the use cases that need its permissions. A role that names no permission grants nothing, so every use case its holders run breaks the chain at the middle link.

Example

role/employee allows permission/submit-expense, which the submit use case needs.

Checkchecked by a tool

litespec model check reports record-shape for a role with no allows entry.

Marked checkable: the tool named here checks it.

State Every Permission with Its Meaning#

rulecheckable
litespec/core/access#state-every-permission-with-its-meaning
Statement

A permission MUST state what it allows in meaning.

Why

The meaning is the one sentence a reviewer reads to decide whether the grant fits the role: a name alone carries no boundary. Two permissions with the same name pattern and no meanings drift into overlapping grants that no audit can separate.

Example

permission/submit-expense carries "Submit an expense for approval."

Checkchecked by a tool

litespec model check reports record-shape for a permission without meaning in docs/domain/permissions.md.

Marked checkable: the tool named here checks it.

Name Every Entry Point with Its Kind#

rulecheckable
litespec/core/access#name-every-entry-point-with-its-kind
Statement

An entry point MUST name its kind in kind.

Why

The kind tells a reviewer how callers arrive: an app serves people, an api serves callers over a boundary, a cli serves operators, and a job or reaction runs without a request. Without the kind, interactive operations and background work look alike.

Example

The web shop carries app, and the nightly export carries job.

Checkchecked by a tool

litespec model check reports record-shape for an entry point without kind and invalid-field for a kind outside app, api, cli, job, and reaction.

Marked checkable: the tool named here checks it.

Name the Actor for Every External System#

rulecheckable
litespec/core/access#name-the-actor-for-every-external-system
Statement

An external system MUST name the actor it acts as in actor.

Why

The actor link attributes everything the system does to a party the access records know: journeys, holds, and permissions all start from actors. A system with no actor acts in the product as nobody, and its messages enter use cases with no stated party behind them.

Example

The text gateway names actor/reader as its actor.

Checkchecked by a tool

litespec model check reports record-shape for an external system without actor.

Marked checkable: the tool named here checks it.

Name What an External System Sends#

ruleguidance
litespec/core/access#name-what-an-external-system-sends
Statement

An external system MUST name every message it sends in sends.

Why

The sends list bounds what flows out of the product: each entry names one message the product hands to the outside system. Without the list, a new outbound message ships as an unreviewed dependency on behavior the product does not control.

Example

The text gateway names "Overdue notices" in sends.

Checka reviewer answers

Each page under docs/domain/systems/ names in sends every message the product hands to that system.

Marked guidance: a reviewer answers this question.

Name What an External System Receives#

ruleguidance
litespec/core/access#name-what-an-external-system-receives
Statement

An external system MUST name every message it receives in receives.

Why

The receives list bounds what flows into the product: each entry names one message the product accepts from the outside system. Without the list, a new inbound message arrives as unreviewed input to behavior the reviewers approved without it.

Example

The text gateway names "Delivery receipts" in receives.

Checka reviewer answers

Each page under docs/domain/systems/ names in receives every message the product accepts from that system.

Marked guidance: a reviewer answers this question.

State the Failure Behavior of Every External System#

ruleguidance
litespec/core/access#state-the-failure-behavior-of-every-external-system
Statement

An external system MUST state the product behavior when the system fails in failure.

Why

Outside systems fail on their own schedule: the record states what the product does until they answer, such as queueing work or refusing with a named result. Without the stated behavior, each caller invents its own fallback, and one outage produces as many behaviors as callers.

Example

The text gateway states "Notices queue until the gateway answers." in failure.

Checka reviewer answers

Each page under docs/domain/systems/ states in failure what the product does until the system answers.

Marked guidance: a reviewer answers this question.

Write a Summary on Every Actor and Role Page#

rulecheckable
litespec/core/access#write-a-summary-on-every-actor-and-role-page
Statement

An actor or role page MUST carry a Summary section.

Why

The Summary states in plain sentences who the party is and what the grant is for, which the fields alone do not say. A reviewer meets the story first and the fields after, so the grant reads as a decision rather than a row.

Checkchecked by a tool

litespec consumer fails an actor or role page without an H2 Summary.

Marked checkable: the tool named here checks it.

Write a Summary on Every External System Page#

rulecheckable
litespec/core/access#write-a-summary-on-every-external-system-page
Statement

An external system page MUST carry a Summary section.

Why

The Summary states in plain sentences what the outside system does for the product, which the message lists alone do not say. A reviewer meets the relationship first and the messages after, so the dependency reads as a decision rather than a row.

Checkchecked by a tool

litespec consumer fails an external system page without an H2 Summary.

Marked checkable: the tool named here checks it.

Keep Permission and Entry Point Lists to Entries#

ruleguidance
litespec/core/access#keep-permission-and-entry-point-lists-to-entries
Statement

A permission list or entry point list page MUST NOT carry a body section.

Why

The lists hold entries only: each permission and entry point is one row with its fields, and prose around them would restate the meanings the entries already carry. A list with no body section stays readable as a list even as entries grow.

Checka reviewer answers

docs/domain/permissions.md and docs/domain/entry-points.md hold entries with no H2 body section.

Marked guidance: a reviewer answers this question.

Conventions#

Use Three Conventional Scope Levels#

conventionguidance
litespec/core/access#use-three-conventional-scope-levels
Default

Use platform, tenant, and self as role scopes.

ReplacementA project names its own scope levels in its role records.

Why

Three levels cover the grants most products need: product-wide administration, tenant-wide operation, and action on one's own records. A project with different boundaries names its own levels, and every role still carries exactly one scope.

Checka reviewer answers

Role pages under docs/domain/roles/ carry platform, tenant, or self in scope, or the project names its own levels there.

Marked guidance: a reviewer answers this question.

Verification#

IDMarkEvidence
litespec/core/access#keep-access-records-in-their-homesguidanceActor, role, and external system pages sit under docs/domain/actors/, docs/domain/roles/, and docs/domain/systems/; permission and entry point entries sit in docs/domain/permissions.md and docs/domain/entry-points.md.
litespec/core/access#name-every-actor-with-its-kindcheckablelitespec model check reports record-shape for an actor without kind and invalid-field for a kind outside person, organization, and system.
litespec/core/access#record-every-role-hold-with-its-scopeguidanceEach actor page under docs/domain/actors/ names in holds every role the actor acts through, with the scope of each grant.
litespec/core/access#scope-every-rolecheckablelitespec model check reports record-shape for a role without scope and invalid-field for a scope outside kebab-case form.
litespec/core/access#grant-permissions-through-rolescheckablelitespec model check reports record-shape for a role with no allows entry.
litespec/core/access#state-every-permission-with-its-meaningcheckablelitespec model check reports record-shape for a permission without meaning in docs/domain/permissions.md.
litespec/core/access#name-every-entry-point-with-its-kindcheckablelitespec model check reports record-shape for an entry point without kind and invalid-field for a kind outside app, api, cli, job, and reaction.
litespec/core/access#name-the-actor-for-every-external-systemcheckablelitespec model check reports record-shape for an external system without actor.
litespec/core/access#name-what-an-external-system-sendsguidanceEach page under docs/domain/systems/ names in sends every message the product hands to that system.
litespec/core/access#name-what-an-external-system-receivesguidanceEach page under docs/domain/systems/ names in receives every message the product accepts from that system.
litespec/core/access#state-the-failure-behavior-of-every-external-systemguidanceEach page under docs/domain/systems/ states in failure what the product does until the system answers.
litespec/core/access#write-a-summary-on-every-actor-and-role-pagecheckablelitespec consumer fails an actor or role page without an H2 Summary.
litespec/core/access#write-a-summary-on-every-external-system-pagecheckablelitespec consumer fails an external system page without an H2 Summary.
litespec/core/access#keep-permission-and-entry-point-lists-to-entriesguidancedocs/domain/permissions.md and docs/domain/entry-points.md hold entries with no H2 body section.
litespec/core/access#use-three-conventional-scope-levelsguidanceRole pages under docs/domain/roles/ carry platform, tenant, or self in scope, or the project names its own levels there.