fix(permissions): resolve grant scope by catalog scopeField; numeric scope escape hatch - #54
Merged
Merged
Conversation
…scope escape hatch (#49) `ct adopt grants` assumed every scoped dataId was a group and pointed at `ct adopt group <id>`, but scoped rights whose catalog scopeField isn't "cdb_gruppe" (e.g. churchdb's security-level / comment-viewer rights) scope by a different dimension entirely — GET /groups/{id} 404s for them, so a partial adoption block would revoke live grants on apply. - src/permissions/scope.ts: resolveScope now accepts a raw numeric scope entry alongside logical group keys (the escape hatch), passed straight through with no state lookup and no re-resolution at apply time. - src/permissions/types.ts, src/config/context.ts: Grant.scope widened to (string | number)[], with DSL-level validation of each entry. - src/permissions/plan.ts: desiredTuples only retains scopeKey for logical-key resolutions, never for numeric ones. - src/permissions/adopt.ts: grant emission now branches on the right's actual scopeField — only "cdb_gruppe"-scoped rights are round-tripped as managed-group refs (unchanged behavior, including the `ct adopt group` hint for unmanaged dataIds); every other scope dimension emits the numeric form directly as an active, paste-ready grant. - docs/permissions.md, src/permissions/README.md, examples/permissions.config.ts: document the numeric scope escape hatch and the adopt behavior split. Closes #49
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.
Summary
ct adopt grants group_type_role 9against real prod data (issue #49) returned 27 live grants, 10 of which are scoped churchdb rights (churchdb:view comments,churchdb:security level view own data,churchdb:security level edit own data) scoped to dataIds 1, 2, 3, 5.src/permissions/adopt.tsassumed every scoped dataId is a group (findByTypeId(state, "group", id)) and told you toct adopt group <id>— butGET /groups/{1,2,3,5}404s, because those dataIds aren't groups: the rights' catalogscopeFieldiscc_securitylevel/cdb_comment_viewer, a different ChurchTools dimension. The resulting partial adoption block couldn't express those grants, so applying it would revoke live grants — blocking plan-to-no-op on a real instance. There was also no way to declare a known non-group dataId in the DSL at all (scopeonly accepted logical group keys).This PR implements all three requirements from the issue:
scopeField. Only rights whose scopeField is the group dimension ("cdb_gruppe") are resolved/round-tripped as logical group refs (src/permissions/adopt.ts). Every other scope dimension passes through numerically.src/permissions/scope.ts,src/permissions/types.ts,src/config/context.ts): ascopearray entry may now be a raw positive-integernumberalongside logical group keys — validated at eval time, resolved with no state lookup, and (correctly) never retains ascopeKeyfor re-resolution at apply time, since its dataId is already final.ct adopt grantsemits the numeric form and names the scope dimension for any scoped right whose scopeField isn't the group dimension — always as an active, paste-ready grant line, never act adopt group #Nhint for a dataId that was never a group. The existingct adopt group <id>hint is preserved unchanged for genuinely unmanaged group-scoped dataIds.Test plan
resolveScopenumeric entries (pass-through, sorting, validation of non-positive/non-integer values) —tests/permission-scope.test.tsdesiredTuplesnumeric scope entries (noscopeKeyretained, mixable with logical keys) —tests/permission-plan.test.ts(string | number)[]scope arrays and rejecting invalid entries —tests/context.test.tsemitAdoptedGrants: non-group scope dimensions emit the numeric form as an active grant (never a WARNING orct adopt grouphint), a regression test locking the unchanged group-dimension behavior, and a full round-trip repro of the issue's exact scenario (churchdb:security level view/edit own datascoped to dataIds 1,2,3,5) assertingdiffGrantsproduces zerotoPutand zerotoDelete—tests/permission-adopt.test.tsnpm test— 354 passed, 4 skipped (0 failures)npm run typecheck— cleannpm run lint— cleannpm run build— sanity build succeedsNever hits a live instance or requires credentials — all fixtures are inline
RawPermission[]rows.Closes #49