Skip to content

docs(roles): state the limits of the operations allowlist - #631

Draft
dawsontoth wants to merge 1 commit into
mainfrom
docs/operations-allowlist-semantics
Draft

docs(roles): state the limits of the operations allowlist#631
dawsontoth wants to merge 1 commit into
mainfrom
docs/operations-allowlist-semantics

Conversation

@dawsontoth

Copy link
Copy Markdown
Contributor

Companion to HarperFast/studio#1628, which surfaces permission.operations in the Studio roles UI. Building that UI meant establishing the field's real semantics against the Harper source, and several of them contradict a natural reading of this page — I got each one wrong first and had them caught in review.

What changes

The two-gate description reads as universal ("any unlisted operation is denied"), so the obvious next thought is a restricted super user. Three limits are now stated explicitly:

  • super_user/cluster_user + operations is a validation error. validateNoSUPerms rejects any multi-key permission setting either flag. Authorization also returns early for a super_user role before reaching the allowlist gate, so even a stored one would not narrow it.
  • structure_user bypasses the allowlist for DDL only — the four table/attribute operations, plus create/drop database for the boolean form; the array form scopes that to its listed databases. Everything else is still gated.
  • sql is authorized on its own path (checkASTPermissions/verifyPermsAST), which never consults the allowlist. Worth stating plainly because sql appears in both read_only and standard_user, so the groups imply the opposite.

Plus a pointer to HarperFast/harper#2194 for the non-array case, since a role carrying one can stop the instance loading its user cache.

Verification

Read against harper v5.2.2 (utility/operation_authorization.ts, validation/role_validation.ts, security/user.ts, server/serverHelpers/serverUtilities.ts); the sql and structure_user claims were also exercised against the compiled dist/. No behavior change here — this documents what 5.x already does.

Review coverage

Written by an LLM (Claude Fable 5). Prose-only change to one file; prettier --check clean. The underlying findings were reviewed by @cb1kenobi and @kriszyp on studio#1628.

🤖 Generated with Claude Code

The two-gate description reads as universal, which leads people to expect a
'restricted super user' — a combination add_role/alter_role actually reject,
and which authorization would ignore anyway. Documents that, the structure_user
DDL carve-out (scoped to the listed databases for the array form), and that sql
is authorized on its own path so listing it neither grants nor restricts SQL —
worth stating since both permission groups include the name.

Also notes that a non-array value can wedge the user-cache load (harper#2194).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the documentation in reference/users-and-roles/overview.md to clarify the scoping behavior and limitations of the operations field in permission objects. The review feedback suggests clarifying the explanation of how super_user roles interact with the allowlist to avoid misleading phrasing, and recommends using a VersionBadge component to properly document the behavior change introduced in version 5.0.0.


The field scopes an ordinary role; it is not a way to narrow an administrator. Three limits follow from that, and each one surprises people:

- **`super_user` and `cluster_user` roles cannot carry an allowlist at all.** `add_role` and `alter_role` reject any permission that sets either flag alongside other keys, so the combination is a validation error rather than a restricted admin. Authorization also clears a `super_user` role before the allowlist is consulted.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The phrase 'clears a super_user role' is misleading as it might imply that the role or its permissions are being deleted or emptied. Based on the actual authorization logic, it would be clearer to state that authorization bypasses the allowlist check or returns early for super_user roles.

Suggested change
- **`super_user` and `cluster_user` roles cannot carry an allowlist at all.** `add_role` and `alter_role` reject any permission that sets either flag alongside other keys, so the combination is a validation error rather than a restricted admin. Authorization also clears a `super_user` role before the allowlist is consulted.
- **<code>super_user</code> and <code>cluster_user</code> roles cannot carry an allowlist at all.** <code>add_role</code> and <code>alter_role</code> reject any permission that sets either flag alongside other keys, so the combination is a validation error rather than a restricted admin. Authorization also bypasses the allowlist check for a <code>super_user</code> role.

- **`structure_user` roles bypass the allowlist for DDL only.** `create_table`, `create_attribute`, `drop_table`, and `drop_attribute` are reachable regardless of the list — plus `create_database`/`drop_database` when `structure_user` is `true`. When it is an array of database names, that carve-out applies only to those databases. Every other operation is still gated normally.
- **`sql` is not gated by this field.** SQL statements are authorized against table CRUD permissions on their own path, so listing `sql` neither grants nor restricts them, and omitting it does not prevent a role from running SQL. This matters when reading the `read_only` and `standard_user` groups below, both of which include the name.

The value must be an array of strings. A non-array value is rejected on write, and a role that already holds one (for example a pre-5.0 role that granted a database named `operations`) can prevent the instance from loading its user cache — see [HarperFast/harper#2194](https://github.com/HarperFast/harper/issues/2194).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the repository's guidelines, when documenting behavior changes to an existing surface (such as the change in v5.0.0 where operations became a reserved array of strings instead of allowing a database named operations), we should use the <VersionBadge type="changed" version="vX.Y.0" /> format.

Suggested change
The value must be an array of strings. A non-array value is rejected on write, and a role that already holds one (for example a pre-5.0 role that granted a database named `operations`) can prevent the instance from loading its user cache — see [HarperFast/harper#2194](https://github.com/HarperFast/harper/issues/2194).
The value must be an array of strings. <VersionBadge type="changed" version="v5.0.0" /> A non-array value is rejected on write, and a role that already holds one (for example a pre-5.0 role that granted a database named <code>operations</code>) can prevent the instance from loading its user cache — see [HarperFast/harper#2194](https://github.com/HarperFast/harper/issues/2194).
References
  1. Use the <VersionBadge type="changed" version="vX.Y.0" /> format when documenting behavior changes to existing surface, as prescribed in the repository's guidelines.

@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-631

This preview will update automatically when you push new commits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant