fix(FR-3017): version-branch myRoles entityType filter shape#7686
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has required the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Coverage Report for react-coverage (./react)
File Coverage
|
||||||||||||||||||||||||||||||||||||||
7c70016 to
1c1f9a1
Compare
1c1f9a1 to
0946581
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes a backwards-compatibility break in the myRoles GraphQL query filter shape across Backend.AI core versions by introducing a capability-gated runtime branch: older cores (<= 26.4.3 / 26.4.4rc1–3) receive a direct enum value, while newer cores (>= 26.4.4rc4) receive the newer { equals: ... } wrapper form.
Changes:
- Added a new
backend.ai-clientcapability flag (rbac-element-type-filter) gated at manager version26.4.4rc4. - Updated
useCurrentUserProjectRolesto pass thepermissionfilter via a Relay variable and construct the correct runtime shape based on capability detection. - Regenerated the Relay query artifact to reflect the new query variable.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| react/src/hooks/useCurrentUserProjectRoles.ts | Builds permission.entityType filter shape at runtime (wrapper vs bare enum) and sends it as a Relay variable to avoid query-validation failures on older cores. |
| react/src/generated/useCurrentUserProjectRolesQuery.graphql.ts | Regenerated Relay artifact for the new $permissionFilter variable and non-literal filter argument. |
| packages/backend.ai-client/src/client.ts | Adds rbac-element-type-filter feature flag gated at 26.4.4rc4 to correctly classify rc builds vs stable per PEP440 ordering. |
Files not reviewed (1)
- react/src/generated/useCurrentUserProjectRolesQuery.graphql.ts: Language not supported
Merge activity
|
Resolves #7665 (FR-3017) ## Problem `useCurrentUserProjectRoles` issued the `myRoles` query with `permission.entityType` always as the **`RBACElementTypeFilter` wrapper** (`{ equals: PROJECT_ADMIN_PAGE }`). Cores **<= 26.4.3** define this field as a **direct `RBACElementType` enum** and reject the wrapper at **query-validation** time: ``` Enum "RBACElementType" cannot represent non-enum value: {equals: PROJECT_ADMIN_PAGE} (GRAPHQL_VALIDATION_FAILED) ``` Because it is a query-validation error (not a field error), `@catch(to: RESULT)` cannot absorb it — the whole query is rejected and the app **fails to load** against those backends. ## Fix (option a — version branch) - **`backend.ai-client`**: add a `rbac-element-type-filter` capability flag, gated at **`26.4.4rc4`** — the exact tag where the backend switched `PermissionNestedFilter.{scope,entity}Type` to the `RBACElementTypeFilter` wrapper (backend.ai #11442). - **`useCurrentUserProjectRoles`**: pass the `permission` filter as a **Relay variable** so a single compiled query carries either shape, and build it at runtime: - `>= 26.4.4rc4` → wrapper `{ entityType: { equals: PROJECT_ADMIN_PAGE } }` - `<= 26.4.3` / `26.4.4rc1-3` → direct enum `{ entityType: PROJECT_ADMIN_PAGE }` The generated Relay type only models the latest (wrapper) shape, so the legacy branch is cast (`as unknown as ...`). ### Why gate on the exact rc `26.4.4rcN` builds already carry the wrapper, but PEP440 sorts `26.4.4rcN < 26.4.4`. Gating at the stable `26.4.4` would misclassify rc4–rc6 as older and send them the direct enum, re-triggering the bug. Gating at `26.4.4rc4` classifies every release correctly: | version | branch | |---|---| | <= 26.4.3 | direct enum | | 26.4.4rc1–3 (pre-wrapper) | direct enum | | 26.4.4rc4–rc6, 26.4.4, 26.5.x+ | wrapper | ## Verification Automated — `bash scripts/verify.sh`: **Lint / Format / TypeScript PASS**, Relay regenerated. (The harness's "Vite warmup paths" check also fails on a clean `main` — pre-existing, unrelated to this change.) ### TODO — manual checks (cannot be covered by verify.sh) `verify.sh` only compiles against the latest (wrapper) schema; it cannot exercise the `<= 26.4.3` path. Confirm both branches against live backends: **Wrapper path — backend `>= 26.4.4rc4`:** - [ ] Super-admin loads the app; no `GRAPHQL_VALIDATION_FAILED` in console/network - [ ] Regular (non-admin) user loads the app; `myRoles` resolves - [ ] Network tab: `myRoles` request sends `permission.entityType = { equals: PROJECT_ADMIN_PAGE }` **Direct-enum path — backend `<= 26.4.3`:** - [ ] Super-admin and regular user both load the app without `GRAPHQL_VALIDATION_FAILED` - [ ] Network tab: `myRoles` request sends `permission.entityType = PROJECT_ADMIN_PAGE` (bare enum) - [ ] Project-admin scope still resolves (admin UI gating unchanged) **Regression:** - [ ] No `data/schema.graphql` divergence required (acceptance criterion from FR-3017) > Note: after pulling this change onto a running dev session, do a **full browser refresh** — `_features` is cached on the global `backendaiclient`, so HMR alone may keep the stale capability map.
0946581 to
e708bc3
Compare

Resolves #7665 (FR-3017)
Problem
useCurrentUserProjectRolesissued themyRolesquery withpermission.entityTypealways as theRBACElementTypeFilterwrapper ({ equals: PROJECT_ADMIN_PAGE }). Cores <= 26.4.3 define this field as a directRBACElementTypeenum and reject the wrapper at query-validation time:Because it is a query-validation error (not a field error),
@catch(to: RESULT)cannot absorb it — the whole query is rejected and the app fails to load against those backends.Fix (option a — version branch)
backend.ai-client: add arbac-element-type-filtercapability flag, gated at26.4.4rc4— the exact tag where the backend switchedPermissionNestedFilter.{scope,entity}Typeto theRBACElementTypeFilterwrapper (backend.ai #11442).useCurrentUserProjectRoles: pass thepermissionfilter as a Relay variable so a single compiled query carries either shape, and build it at runtime:>= 26.4.4rc4→ wrapper{ entityType: { equals: PROJECT_ADMIN_PAGE } }<= 26.4.3/26.4.4rc1-3→ direct enum{ entityType: PROJECT_ADMIN_PAGE }The generated Relay type only models the latest (wrapper) shape, so the legacy branch is cast (
as unknown as ...).Why gate on the exact rc
26.4.4rcNbuilds already carry the wrapper, but PEP440 sorts26.4.4rcN < 26.4.4. Gating at the stable26.4.4would misclassify rc4–rc6 as older and send them the direct enum, re-triggering the bug. Gating at26.4.4rc4classifies every release correctly:Verification
Automated —
bash scripts/verify.sh: Lint / Format / TypeScript PASS, Relay regenerated.(The harness's "Vite warmup paths" check also fails on a clean
main— pre-existing, unrelated to this change.)TODO — manual checks (cannot be covered by verify.sh)
verify.shonly compiles against the latest (wrapper) schema; it cannot exercise the<= 26.4.3path. Confirm both branches against live backends:Wrapper path — backend
>= 26.4.4rc4:GRAPHQL_VALIDATION_FAILEDin console/networkmyRolesresolvesmyRolesrequest sendspermission.entityType = { equals: PROJECT_ADMIN_PAGE }Direct-enum path — backend
<= 26.4.3:GRAPHQL_VALIDATION_FAILEDmyRolesrequest sendspermission.entityType = PROJECT_ADMIN_PAGE(bare enum)Regression:
data/schema.graphqldivergence required (acceptance criterion from FR-3017)