fix: merge RBAC verbs in createRBACMap instead of overwriting#2977
fix: merge RBAC verbs in createRBACMap instead of overwriting#2977joonas wants to merge 2 commits intodefenseunicorns:mainfrom
createRBACMap instead of overwriting#2977Conversation
`createRBACMap` in `src/lib/helpers.ts` had two problems that caused
RBAC verb loss when multiple bindings targeted the same resource
kind:
1. The `isFinalize` branch unconditionally replaced the entire RBAC
entry (`acc[key] = { verbs: ["patch"], ... }`), discarding any
`"watch"` verb that a prior `isWatch` binding had set.
2. The `isWatch` branch was guarded by `if (!acc[key] && ...)`, so
it only registered `"watch"` for the first binding per resource
key. If a finalize binding created the entry first, the
subsequent watch binding was silently skipped — again losing
the `"watch"` verb.
Both branches now check whether the key already exists and merge
the new verb into the existing `verbs` array (with an `includes`
guard to prevent duplicates) rather than overwriting the entry.
Four test changes cover the fix across two levels:
- **`helpers.test.ts`**: Two unit tests for `createRBACMap` —
watch-then-finalize and finalize-then-watch binding order — each
using sorted equality (`toSorted().toEqual(["patch", "watch"])`)
to assert exact verb content without duplicates.
- **`rbac.test.ts`**: One integration test for `clusterRole` in
scoped mode using a new `capabilityWithWatchAndFinalize` fixture
from `defaultTestObjects.ts`. Asserts a single configmaps rule
with exactly `["patch", "watch"]` after deduplication.
- **`rbac.test.ts`**: Updated the existing finalize-only test
expectation — the peprstores entry now correctly retains all four
verbs (`["patch", "create", "get", "watch"]`) from the merge of
custom RBAC and the hardcoded peprstore entry, rather than the
prior `["patch"]` which was an artifact of the overwrite bug.
Signed-off-by: Joonas Bergius <joonas@defenseunicorns.com>
Greptile SummaryThis PR fixes two verb-loss bugs in Confidence Score: 5/5Safe to merge — targeted bug fix with thorough test coverage across both binding orders and integration levels. All findings are P2 or lower. The logic change is minimal and correct, tests cover both failure modes explicitly, and the updated expectation on the existing test confirms the prior behaviour was an artifact of the bug rather than intentional. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[forEach binding] --> B{isWatch?}
B -- yes --> C{acc-key exists?}
C -- no --> D[create entry with watch]
C -- yes --> E{has watch verb?}
E -- no --> F[push watch]
E -- yes --> G[skip]
B -- no --> H{isFinalize?}
H -- yes --> I{acc-key exists?}
I -- no --> J[create entry with patch]
I -- yes --> K{has patch verb?}
K -- no --> L[push patch]
K -- yes --> M[skip]
H -- no --> N[no-op]
Reviews (1): Last reviewed commit: "Merge branch 'main' into fix/rbac-map-me..." | Re-trigger Greptile |
Description
createRBACMapinsrc/lib/helpers.tshad two problems that caused RBAC verb loss when multiple bindings targeted the same resource kind:The
isFinalizebranch unconditionally replaced the entire RBAC entry (acc[key] = { verbs: ["patch"], ... }), discarding any"watch"verb that a priorisWatchbinding had set.The
isWatchbranch was guarded byif (!acc[key] && ...), so it only registered"watch"for the first binding per resource key. If a finalize binding created the entry first, the subsequent watch binding was silently skipped — again losing the"watch"verb.Both branches now check whether the key already exists and merge the new verb into the existing
verbsarray (with anincludesguard to prevent duplicates) rather than overwriting the entry.Four test changes cover the fix across two levels:
helpers.test.ts: Two unit tests forcreateRBACMap— watch-then-finalize and finalize-then-watch binding order — each using sorted equality (toSorted().toEqual(["patch", "watch"])) to assert exact verb content without duplicates.rbac.test.ts: One integration test forclusterRolein scoped mode using a newcapabilityWithWatchAndFinalizefixture fromdefaultTestObjects.ts. Asserts a single configmaps rule with exactly["patch", "watch"]after deduplication.rbac.test.ts: Updated the existing finalize-only test expectation — the peprstores entry now correctly retains all four verbs (["patch", "create", "get", "watch"]) from the merge of custom RBAC and the hardcoded peprstore entry, rather than the prior["patch"]which was an artifact of the overwrite bug.End to End Test:
(See Pepr Excellent Examples)
Type of change
Checklist before merging