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.
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.
| Type | Stored as | Home |
|---|---|---|
actor | page | docs/domain/actors/<name>.md |
role | page | docs/domain/roles/<name>.md |
permission | entry | docs/domain/permissions.md |
entry-point | entry | docs/domain/entry-points.md |
external-system | page | docs/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#
ruleguidancelitespec/core/access#keep-access-records-in-their-homesAn 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#
rulecheckablelitespec/core/access#name-every-actor-with-its-kindAn 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#
ruleguidancelitespec/core/access#record-every-role-hold-with-its-scopeAn 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
"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#
rulecheckablelitespec/core/access#scope-every-roleA 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#
rulecheckablelitespec/core/access#grant-permissions-through-rolesA 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#
rulecheckablelitespec/core/access#state-every-permission-with-its-meaningA 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#
rulecheckablelitespec/core/access#name-every-entry-point-with-its-kindAn 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#
rulecheckablelitespec/core/access#name-the-actor-for-every-external-systemAn 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#
ruleguidancelitespec/core/access#name-what-an-external-system-sendsAn 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#
ruleguidancelitespec/core/access#name-what-an-external-system-receivesAn 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#
ruleguidancelitespec/core/access#state-the-failure-behavior-of-every-external-systemAn 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#
rulecheckablelitespec/core/access#write-a-summary-on-every-actor-and-role-pageAn 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#
rulecheckablelitespec/core/access#write-a-summary-on-every-external-system-pageAn 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#
ruleguidancelitespec/core/access#keep-permission-and-entry-point-lists-to-entriesA 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#
conventionguidancelitespec/core/access#use-three-conventional-scope-levelsUse 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#
| ID | Mark | Evidence |
|---|---|---|
| litespec/core/access#keep-access-records-in-their-homes | guidance | 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. |
| litespec/core/access#name-every-actor-with-its-kind | checkable | litespec 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-scope | guidance | Each 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-role | checkable | litespec 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-roles | checkable | litespec model check reports record-shape for a role with no allows entry. |
| litespec/core/access#state-every-permission-with-its-meaning | checkable | litespec model check reports record-shape for a permission without meaning in docs/domain/permissions.md. |
| litespec/core/access#name-every-entry-point-with-its-kind | checkable | 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. |
| litespec/core/access#name-the-actor-for-every-external-system | checkable | litespec model check reports record-shape for an external system without actor. |
| litespec/core/access#name-what-an-external-system-sends | guidance | Each page under docs/domain/systems/ names in sends every message the product hands to that system. |
| litespec/core/access#name-what-an-external-system-receives | guidance | Each 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-system | guidance | Each 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-page | checkable | litespec consumer fails an actor or role page without an H2 Summary. |
| litespec/core/access#write-a-summary-on-every-external-system-page | checkable | litespec consumer fails an external system page without an H2 Summary. |
| litespec/core/access#keep-permission-and-entry-point-lists-to-entries | guidance | docs/domain/permissions.md and docs/domain/entry-points.md hold entries with no H2 body section. |
| litespec/core/access#use-three-conventional-scope-levels | guidance | Role pages under docs/domain/roles/ carry platform, tenant, or self in scope, or the project names its own levels there. |