Repository navigation
fix(roles): the role editor says Harper 5.3 gates a structure user's DDL and SQL by the allowlist - #1896
Merged
dawsontoth merged 4 commits intoOct 12, 2026
Conversation
…the allowlist From Harper 5.3.0-alpha.1 (harper f8a5aa90a), verifyPerms runs a role's operations allowlist ahead of its super_user and structure_user returns, and chooseOperation runs it on `sql`. The editor and the assignment summary still said a structure user reaches DDL regardless of the list and that the list does not restrict SQL, and the effective count left `sql` out. GrantBand gains a `5.3-early` band (5.3.0-alpha.1 to beta.2) between `pre-5.3` and `5.3`, so the gate-order change and the beta.3 naming change are both resolved from one band. The structure-user, SQL and empty-list copy, the `sql` chip and the effective count follow it. The permission hooks keep their behavior; their comments and AGENTS.md now say why on each version, and #1894 tracks per-operation checks for 5.3. Closes #1885 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…change Nothing outside the catalog reads ALLOWLIST_GATE_RUNS_FIRST_FROM, and the GateChange doc still said "before 5.3" for a change that landed in 5.3.0-beta.3, which the new 5.3-early band makes ambiguous. Refs #1885 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates the operations allowlist editor, summary components, and tests to correctly handle Harper 5.3+ permission gating changes, specifically introducing the 5.3-early grant band for versions starting from 5.3.0-alpha.1 where the allowlist gates SQL and structure-user DDL paths. The review feedback points out an issue in RoleOperationsSummary.tsx where the database scope restriction is hidden for scoped structure users when gatesEveryPath is true, and suggests preserving this scope in the summary message.
dawsontoth
added this pull request to stack #1902
October 11, 2026 21:25
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
…ist gates its DDL On the 5.3 bands the role summary said only that the structure-user DDL needs listing, dropping the database scope the pre-5.3 copy and the editor's gated note both keep. verifyPerms still applies the structure_user array after gate 1 (harper utility/operation_authorization.ts:810-824), so a listed DDL operation reaches only those databases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wlist preparePermissionForSave's doc still described the pre-5.3 gate order as universal; from 5.3.0-alpha.1 Harper gates the structure-user DDL on the list too. Also drops a PR-number reference from a test comment in favour of the boundary it means. Comment-only; raised by the pre-push domain adjudication. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dawsontoth
marked this pull request as ready for review
October 12, 2026 17:36
dawsontoth
removed this pull request from stack #1902
October 12, 2026 17:36
dawsontoth
merged commit Oct 12, 2026
883ff75
into
claude/1788-operations-catalog-5-3
4 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The role editor and the role-assignment summary now say what Harper 5.3 actually does with a role's
operationsallowlist. From Harper 5.3.0-alpha.1 the list also gates a structure user's DDL and every SQL statement, and Studio still told authors the opposite.Closes #1885.
⊙ Problem
Harper commit
f8a5aa90a(harper#2176) is in every tag fromv5.3.0-alpha.1on and in no 5.2.x tag (git tag --contains; v5.2.15 is the newest 5.2 tag). It changed gate 1 of the allowlist in two ways:verifyPermschecks the allowlist before its super_user and structure_user returns (utility/operation_authorization.tsat v5.3.0: gate at line 773, super-user return at 799, structure-user returns at 805 and 810). Through v5.2.15 those returns come first (593, 599, 604) and the gate is at 629.chooseOperationruns the gate onsqlbeforecheckASTPermissions(server/serverHelpers/serverUtilities.tsat v5.3.0, line 373). Through v5.2.15 the SQL branch goes straight tocheckASTPermissions(line 239).On 5.3, the editor told a structure-user author that
create_table,drop_tableand the other DDL work "regardless of the list below", and Harper refuses them. It also said "this list does not restrict" SQL, and the effective count leftsqlout, soread_onlycounted 12 operations where Harper grants 13.💡 Solution
GrantBandgains a third band, so each instance version resolves to one band that covers both 5.3 changes:pre-5.35.3-early5.3allowlistGatesEveryPath(band)answers the first question, and #1884'sgateVerdictstill answers the second. On a gate-first instance:sql(or a group with it) listed.sql: it counts as a grant, soread_onlycounts 13. Its "changes nothing" chip title shows only before 5.3.Before 5.3 every sentence reads as it did. The
5.3-earlyband exists because 5.3.0-beta.2 already gates first whiledeploy_componentand the other 19 entries are still unnamed. I ran this against Harper's own build (Verification).⚖️ Alternatives
band === '5.3'→ new copy). Rejected: 5.3.0-alpha.1 through beta.2 gate first but read aspre-5.3there, so four tagged builds would keep the wrong copy.GateOrder) next toGrantBand. Rejected: the effective count needs both answers (names fordeploy_component, order forsql), soisInertGrant,expandEffectiveOperationsandAllowlistVersionwould each gain a parameter at every caller. With three bands, every fix(roles): the operations editor knows what Harper 5.3's allowlist grants #1884 signature stays the same.outOfGateas a set of bands. Not done: it names one band, matched by equality. That fitssql, the only entry that sets it. An operation outside the gate in two bands would need the type widened.structureUserDdlScopeversion-aware. Rejected: it reads the role's shape, and Edit roles in a visual editor, with JSON as the fallback #1893's structure-user radio uses it for that. Returningfalseon 5.3 would hide that the role is a structure user and lose the per-database scope, which still applies.The planning review (codex) returned
chosen-approach-sound. Its one blocker was that thesqlchip title had to follow the band too, and that is done.🔧 Changes
Catalog (
operationsCatalog.ts): the three-bandGrantBand, resolved byresolveGrantBandfrom a privateALLOWLIST_GATE_RUNS_FIRST_FROM = '5.3.0-alpha.1'beside fix(roles): the operations editor knows what Harper 5.3's allowlist grants #1884's beta.3 constant.allowlistGatesEveryPathis the gate-order question, andisOutOfGateis the single band-aware check thatisInertGrantand the chip title share.sqlis nowoutOfGate: 'pre-5.3', and the field takes a band. Its caveat names the version. The module header no longer states the 5.2 order as a fact, and theGateChangedoc dates the naming change to beta.3.Editor (
OperationsAllowlistEditor.tsx): it resolvesgatesEveryPathonce, then branches the headline, the structure-user note (the newGatedStructureUserNote, which lists the six DDL names for the boolean form), the empty-list line and the chip title on it.Summary (
RoleOperationsSummary.tsx):gatesEveryPathpicks the structure-user note, which still names a scoped structure user's databases ("its structure-user DDL on dev, qa needs listing too"), and the empty-list line.Role shape (
localRolePermission.ts):structureUserDdlScopeandSTRUCTURE_USER_DDL_OPERATIONSare documented as the flag's shape, not a bypass.STRUCTURE_USER_DATABASE_OPERATIONSnames the boolean form's create/drop database.Hooks (
usePermissions.ts,checkOperationPermission.ts): comments only. Super users still skip the list on 5.3, but now becausevalidateNoSUPermsrefuses to store one besidesuper_user(validation/role_validation.ts, line 280, on both versions):useInstanceManagePermissionand the module header.useInstanceBrowseManagePermissioncites Database and application chrome is offered to an allowlisted structure user on Harper 5.3, where the list gates its DDL #1894.checkTableOperationsAllowedno longer citesisElevatedRole, which feat(roles): surface operation-level grants (permission.operations) in the roles/users UI #1628 removed.AGENTS.md: the role section describes both versions: the intro names both cutovers, and the super-user, structure-user and
sqlbullets each say what holds on each side. The practical-consequence paragraph says the copy needs the band. "Which of those the UI gating turns on" explains the hooks on 5.3 and why onlysuper_usershort-circuits DML. It also records thedist-based way to check a verdict on several versions.Save path (
preparePermissionForSave.ts): the docblock no longer says the gate "still runs for everything but DDL". It now says Harper gates a structure user's DDL too from 5.3.0-alpha.1. Comment only.✅ Verification
Harper's own
verifyPerms, off-repo. I ran it from the installed 5.2.3 and 5.3.0-beta.2 packages and the checkout's 5.3.1dist, with no checkout edited:structure_user: true,[read_only]→create_tablestructure_user: true,[read_only]→create_databasestructure_user: true,[create_table]→create_tablestructure_user: ['dev'],[drop_table]→drop_tableonotherstructure_user: ['dev'],[]→drop_tableondevsuper_user: true,[]→create_tablesql,[read_only]/[insert]Reviewers can't re-run this from the repo. AGENTS.md says how to.
Unit tests:
operationsCatalog.test.ts: the band at alpha.1, beta.1, beta.2 (5.3-early), at 5.2.15, 5.2.99, 5.0.0-alpha.8 and 5.0.0 (pre-5.3), and the existing beta.3+ and unreadable cases.allowlistGatesEveryPathper band. The 20needs-5.3names and theneverset in5.3-early.sqlinert and out of the gate only inpre-5.3.read_onlycounts 12, then 13, and a directsqlgrant follows the band.OperationsAllowlistEditor.test.tsx: on alpha.1, beta.2 and 5.3.0, the structure-user note and the exact unlisted DDL; no missing-DDL sentence once all six are listed; thecreate_schemaalias doesn't count as listingcreate_database; the array form's scope; the empty-list line; the headline on beta.2 and on 5.2.15;sqlcounted with no "changes nothing" title on 5.3; deploy grants still inert on beta.2; the pre-5.3sqlchip. A 5.2 test comment now names its version, and the gate-first block's comment names the beta.3 boundary instead of a PR number.RoleOperationsSummary.test.tsx: the 5.2 structure-user cases are pinned topre-5.3; the gate-first wording in both later bands; the SQL wording per band;read_onlycounts 13, then 12; a scoped structure user's databases stay in the note on both gate-first bands (fails with the scope dropped).checkOperationPermission.test.ts(and) andcheckSchemaTablePermission.test.tschanged only in comments.Mutation checks. I reverted each guard in turn and ran the role-operations tests: dropping the
5.3-earlybranch failed 5 tests;allowlistGatesEveryPath→falsefailed 9; makingisOutOfGateignore the band failed 7; showing the caveat on every chip failed 1; dropping the missing-DDL sentence failed 2; reverting the editor note, empty line and headline failed 4, 1 and 1; reverting the summary note and empty line failed 1 and 2. Computing the missing DDL from the raw list instead of the effective set stayed green. That is an equivalent mutant: no group carries DDL and no DDL name is inert, so the two sets agree on DDL today.Gates. The pre-commit hook ran vitest (395 files, 3,696 passed, 11 skipped), oxlint, dprint and commitlint.
npx tsc -b,npx oxlint --format stylish .andnpx dprint checkall exited 0. I didn't verify in a browser, because port 5173 is shared with parallel sessions. The change is copy and counts, all covered by the component tests.Cross-model review. A codex planning round came first (
chosen-approach-sound), then one full implementation round with codex (graded) and gemini. Its verdict was COMMENTS, with no functional defect. I fixed both codex comments in the second commit: an export nothing imported, and a "before 5.3" doc comment that now means beta.3. I rejected gemini's "wasAReleasedBeforeBmay be strict": it returnsb >= a(src/lib/string/wasAReleasedBeforeB.ts), and the tests pin alpha.1 →5.3-earlyand beta.3 →5.3. Its comment nit cites test comments this PR doesn't touch. Coverage gap in that round: the Cursor leg failed on the 1Password SSH agent (no-receipt), and the Harper domain adjudicator failed auth (an expired Claude OAuth session), so no adjudication ran. After the gemini-code-assist fix, a second full round ran codex (graded), gemini and the Harper domain adjudicator at8a846dfa, with Cursor pruned on purpose. Its verdict was COMMENTS, and it found no functional defect. Its one surviving nit was the stale save-path docblock plus a reviewer-addressed test comment.7c010178fixes both, comments only.gemini-code-assist feedback. Its one thread said the summary dropped a scoped structure user's databases on the gate-first bands. It was right, because the editor's gated note keeps the scope and verifyPerms still applies the
structure_userarray after gate 1 (harperutility/operation_authorization.ts:810-824). Fixed in8a846dfa, with the test above. On the gate-first bands this note still says "needs listing too" even when every DDL operation is listed, which the domain review logged as a decision (summary-generic-ddl-note). It is coarser than the editor but never wrong about enforcement.🤖 Generated by Claude Code (Claude Opus); posted via @dawsontoth.
🤖 Generated with Claude Code
Related PRs: #1884 overlaps (the base of this stack)
Complexity: medium
Review-Coverage: authored=claude; ran=codex,gemini; adjudicated=domain; blocked=cursor-composer(no-receipt); declined=cursor-grok,cursor-kimi,cursor-muse; rounds=2; full=1 @ 7c01017
Review-Attention: read ~5m (decisions: browse-manage-stays-ungated, three-band-enum, outofgate-single-band, summary-generic-ddl-note, do-less-alternative) @ 7c01017