fix(roles): support colons in smart-action names in the roles CSV - #813
Open
Gawtier wants to merge 1 commit into
Open
fix(roles): support colons in smart-action names in the roles CSV#813Gawtier wants to merge 1 commit into
Gawtier wants to merge 1 commit into
Conversation
`forest roles:export` emitted a column per smart action as
`collection:action:suffix`, and `roles:apply` read it back with a plain
`split(':')` that only accepted 2 or 3 segments. A smart action whose own
name contains a colon — e.g. "SAML SSO #2: Edit SSO config" — produced 4
segments, so applying a freshly exported CSV failed with
`Unrecognized CSV column`.
The export was silently wrong too: buildCellForColumn re-split the header
string it had just built, fell through the 2/3-segment cases and returned
'false' for every cell of such an action, regardless of the real
permissions. Applying that CSV would have revoked those grants.
Parse the header from its trailing suffix instead of splitting on every
colon (the CRUD and smart-action suffix sets are disjoint, so the last
segment identifies the column shape), and carry structured column
descriptors through the export path so a header is never re-parsed. As a
side effect, collection names containing a colon now work on CRUD columns.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Context
Reported by a customer (Spendesk) round-tripping the new roles commands:
forest roles:exportproduced a CSV, andforest roles:applyon that same untouched file failed withThe smart action exists and the export extracted it verbatim — the asymmetry was in the reader.
Root cause
The export emits one column per smart action as
collection:action:suffix.applyHeaderread it back with a plainsplit(':')and only accepted 2 or 3 segments. A smart action whose own name contains a colon — hereSAML SSO #2: Edit SSO config— yields 4 segments and falls through to theUnrecognized CSV columnthrow.The bug behind the bug
The export path was silently wrong too.
buildCellForColumnre-split the header string it had just built; with 4 segments it missed both the 2- and 3-segment cases and hit the trailingreturn 'false'. Every cell of such an action exported asfalse, regardless of the actual permissions.So had the parser not thrown,
roles:applywould have silently revokedtriggeron that action for every role. The error was acting as an accidental guard rail.Fix
parseHeader()keys off the trailing suffix instead of splitting on every colon. The CRUD (browse/read/add/edit/delete/export) and smart-action (trigger/approvalRequired/userApproval/selfApproval/hasConditions) suffix sets are disjoint, so the last segment is enough to tell the two column shapes apart; the action name is whatever sits between the collection and the suffix, colons included.collectColumnsnow returns structured descriptors ({header, collectionName, actionName, suffix}) instead of strings, so a header is never re-parsed to locate its value.Side effect, for free: collection names containing a colon (schema-prefixed tables) now work on CRUD columns.
Known limitation, documented in a comment: a header where both the collection and the action contain a colon stays ambiguous, and keeps the export's convention that the collection is the first segment. Resolving it properly would mean passing the known collection list into
parseWide(roles:applyhas it viafullRoles) — out of scope here.Tests
3 new cases in
roles-csv.unit.test.js: export cells for a colon-bearing action name, a verbatim round-trip of the Spendesk column, and a colon-bearing collection name on a CRUD column. Fullroles-csvunit suite plus the 4roles:*command suites pass (32 tests), lint clean.Also verified end-to-end that export → apply on the Spendesk shape now yields 0 ops, which was the customer's expectation.
Note for support
The CSV the customer already exported is unusable as-is — the cells for that action read
falsewhile the real grants are likelytrue. They need to re-export with this fix rather than re-apply the file they have.🤖 Generated with Claude Code
Note
Fix roles CSV parsing to support colons in smart-action names
header.split(':')logic incollectColumns,buildCellForColumn, andapplyHeaderwith structured column descriptors and aparseHeaderhelper that uses the last colon to locate the trailing suffix.collectionNamefrom the first segment andactionNamefrom the remainder, preserving internal colons.falsecell values and could be misclassified or rejected during import.Macroscope summarized d73adad.