Specify Who Can Read and Change a Record

Drafted and reviewed using AI assistance.

On this page

“Only let people edit their own records” leaves several decisions open. Can a reviewer read another person's record? Can a maintainer delete it? What happens when an old browser tab still shows an Edit button after membership is withdrawn?

Give the coding agent a table of decisions for named actions and records before asking it to choose an authorization library. The table should describe what the request handler may disclose or change, separately from which controls the interface displays.

Authentication establishes an identity. Authorization decides whether that identity may perform this action on this resource. OWASP recommends an explicit default refusal and permission checks for every request. Knowing an object identifier does not establish permission to access it. OWASP Authorization Cheat Sheet

Fill in a small world completely

Consider a fictional project notebook called Lumen. Every record belongs to one workspace and one owner. The following identities, data and policy are invented for this example; they are not CueSpec account roles.

Identity label Current membership in demo Owns
Mira Editor R41
Sol Editor R42
Tess Reviewer Neither record
Jae Maintainer Neither record
Record Workspace Owner Title Body
R41 demo Mira Outline parser Try a short example.
R42 demo Sol Review export Check the column order.

There are exactly three actions in scope: read, updateTitle and delete. A read returns the complete record. An updateTitle changes only title; it cannot change ownership, membership, workspace or body. A delete removes the record from this fictional notebook. Adding a new action requires a new policy decision.

The server resolves identity and current membership from its trusted application context. A caller-supplied role, owner or identity label is not a way to acquire that context. These labels make the example readable; they are not an authentication protocol.

Write every cell, including refusals

For an existing record in the member's workspace, use this chosen policy:

Current role Relationship to record read updateTitle delete
Editor Own record Allow Allow Deny
Editor Other owner's record Deny Deny Deny
Reviewer Own record Allow Deny Deny
Reviewer Other owner's record Allow Deny Deny
Maintainer Own record Allow Allow Allow
Maintainer Other owner's record Allow Allow Allow

“Own record” is a relationship, not a fourth role. It does not override the Reviewer restrictions. Tess and Jae do not currently own records, but their own-record rows define what should happen if ownership later changes.

Before applying that table, require a recognized current membership, a recognized action and a record belonging to the same workspace. If any of those conditions is absent, deny the action. A label such as Guest, an invented action such as transferOwnership, or a record from another workspace has no implied permission.

This exercise deliberately gives Maintainers broad rights. Whether a real application needs deletion, separate approval or a narrower role is a product decision. Do not silently extend this small table to billing, exports, attachments or administration.

Separate the screen from the request decision

Mira opens R41, types a new title and submits this illustrative application request:

{
  "action": "updateTitle",
  "recordId": "R41",
  "changes": {"title": "Outline parser examples"}
}

With Mira's current Editor membership, the handler allows it. R41.title becomes Outline parser examples; its owner, workspace and body stay as shown above. The client can display the confirmed title after receiving the successful result.

Now consider independent requests from the same starting data. Each row is a hand-worked expected outcome, not a request sent to a service.

Case Interface situation Request evaluated with current membership Required result
A A stale screen shows Tess an Edit button Tess changes R41.title Deny; title stays Outline parser; no record body returned
B Mira's screen hides Delete Mira sends delete R41 anyway Deny; R41 remains present; no record body returned
C Mira knows the identifier R42 Mira requests read R42 Deny; disclose none of its title, owner or body
D Tess opens R42 through an allowed link Tess requests read R42 Allow; return the record shown in the data table
E Tess then tries to revise that title Tess sends updateTitle R42 Deny; R42 stays unchanged; read permission has not become write permission
F A caller has an unrecognized Guest membership Caller requests read R41 Deny; no record fields returned
G Jae requests an action the table never defined Jae sends transferOwnership R41 Deny; no ownership change or record body returned
H Mira includes an extra ownership change updateTitle R41 includes owner: Mira Reject the entire change; neither title nor ownership changes

Case H defines a narrow payload rule: changes must contain exactly one field, title. For this exercise, its value has 1–80 printable ASCII characters, from U+0020 through U+007E, with at least one character other than a space. The examples do not trim or normalize it. This deliberately small title alphabet is an example policy, not a recommendation for international text. Do not apply the recognized part of a request and ignore an unauthorized extra change.

For the denied cases, this example chooses a generic application error:

{"code":"NOT_ALLOWED","message":"You cannot perform this action."}

The error carries no record fields. Choosing an HTTP status, deciding how missing records are concealed, and specifying audit retention belong in the service contract; the permission matrix does not settle them.

Describe what withdrawal changes

A screen can outlive the policy decision that made it appear. In this fictional sequence, actions are evaluated one at a time; no request is already running when membership changes.

Step Membership when the next request is evaluated Request Expected result
1 Mira is Editor Read R41 Allow
2 Mira is Editor Update the title of R41 Allow
3 Mira's membership is removed Read R41 from an old tab Deny; no new record data returned
4 Membership remains absent Submit an edit prepared earlier Deny; no saved change
5 Mira is explicitly re-added as Reviewer Read R41 Allow
6 Mira is Reviewer and still owns R41 Update its title Deny; ownership does not restore Editor rights

Previously displayed text is not erased from someone's memory by a refusal. The next server response and effect are the boundaries being specified here. For a real service, ask separately how membership caches, concurrent requests and revocation timing will meet the chosen policy; a table alone cannot answer those implementation questions.

Copy an authorization brief

Prepare an authorization design for the fictional Lumen notebook.
Do not connect to accounts, change real permissions or deploy anything.

Use the identities, two records, three actions and full six-row matrix
in this article. Resolve identity and current membership from trusted
application context; never grant a role from a request payload.

Before the matrix, require recognized membership, a recognized action
and a record in that membership's workspace. Default to denial otherwise.
updateTitle may change only title. Reject the whole request if changes
contains anything else. Use the stated 1-80 printable ASCII title rule.

Treat UI controls as presentation. Cases A-H must have their listed
outcomes even when a control is visible, hidden or stale. A denied read
returns no record fields; a denied mutation applies no record change.
Use the withdrawal sequence exactly, including the Reviewer re-entry.

Return the decision table, request-handler boundaries and expected
responses. Identify unresolved authentication, cache, concurrency,
missing-record disclosure and audit choices before choosing a framework.
Keep those choices separate from the supplied business policy.

Review the returned design by following a forbidden request all the way to its outcome. It should stop before disclosing the record or applying the change. That concrete behavior gives a developer much more to work with than “hide the button for unauthorized users.”