Skip to content

fix(api-manager): preserve allowedCombos entries the Combo picker cannot render - #12397

Merged
diegosouzapw merged 3 commits into
diegosouzapw:release/v3.8.51from
pacocartones:fix/12267-allowed-combos-preserve-unrenderable
Sep 2, 2026
Merged

diegosouzapw merged 3 commits into
diegosouzapw:release/v3.8.51from
pacocartones:fix/12267-allowed-combos-preserve-unrenderable

Conversation

@pacocartones

Copy link
Copy Markdown
Contributor

Summary

  • The API key permissions modal silently dropped allowedCombos entries its Combo picker cannot render (routing-rule names such as rt-*, which matchesComboAccessRule() already honours via rule === requestedModel). Stored entries rendered as zero selected, and clicking "All" then "Restrict" then Save persisted allowedCombos: [], which is deny-all for combo requests.
  • Those entries now survive the "All" toggle, are listed read-only under the combo list (so the header count and the list agree), and are saved back verbatim. The UI does not learn routing-rule semantics (option 1 from the issue, as confirmed by the maintainer). The behaviour change is limited to the "All" toggle keeping entries the list cannot render; a fully renderable selection is still cleared as before, and the save payload shape is unchanged.
  • The Allowed Combos section moves out of the frozen ApiManagerPageClient.tsx into components/AllowedCombosSection.tsx, following the UsageLimitSettings pattern; the split logic lives in apiManagerPageUtils.listUnrenderableComboAccessRules().
  • Two apiManager i18n keys added to en.json and propagated to the other 42 locales as __MISSING__ sentinels (the runtime falls back to English); happy to run the translation pass if preferred.

Related Issues

Validation

  • Change type: UI
  • Focused tests and category gates from the golden path: tests/unit/api-keys-allowed-combos-preserve-12267.test.ts (5/5), tests/unit/ui/combo-picker-unrenderable-12267.test.tsx (6/6, vitest), api-manager-*.test.ts + api-key-policy.test.ts (108/108), npm run typecheck:core 0, node scripts/check/check-complexity-ratchets.mjs --base-ref origin/release/v3.8.51 (no regression), npm run check:file-size OK, npm run check:mutation-test-coverage OK, npm run check:changelog-integrity OK
  • npm run lint — repository-wide eslint exit 0 (run with --pass-on-unpruned-suppressions; the literal command reports only pre-existing unused global suppressions on this base)
  • Reconciled with the current active release base release/v3.8.51; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR
  • SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.

Mutation: with "All" reverted to [] and the combo/* guard removed, one vitest case ("keeps the rule-layer entries when the All toggle…") and node rule R3 fail.

Tests Added Or Updated

  • tests/unit/api-keys-allowed-combos-preserve-12267.test.ts (node runner, rules R1–R6: order kept, entities excluded, combo/* never reported, rule-only keys kept, empty/fully-renderable selection, PATCH schema round-trip). On the base: 4 fail / 1 pass; with the fix: 5/5.
  • tests/unit/ui/combo-picker-unrenderable-12267.test.tsx (Vitest, 6 cases: read-only chips and count, "All" keeps unrenderable entries, "All" clears a fully renderable selection, "Restrict" does not touch the selection, row toggles delegate, nothing rendered without combos).

Coverage Notes

  • src/app/(dashboard)/dashboard/api-manager/apiManagerPageUtils.ts: the new helper is covered by the node-runner test above.
  • src/app/(dashboard)/dashboard/api-manager/components/AllowedCombosSection.tsx: covered by the Vitest test above; both new tests fail with the fix reverted.
  • src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx: only a JSX block replaced by the component (−76/+9); the existing api-manager tests still pass.

…not render

Root cause: matchesComboAccessRule() (src/shared/utils/apiKeyPolicy.ts)
accepts routing-rule names such as `rt-*` as valid allowedCombos entries
through its `rule === requestedModel` branch, but the Allowed Combos picker
in the API key permissions modal only renders GET /api/combos entities
(`cb-*`). Stored `rt-*` entries therefore matched no row and were invisible,
while the "All" toggle ran `setSelectedCombos([])` unconditionally
(ApiManagerPageClient.tsx, Allowed Combos section). Clicking "All", then
"Restrict", then Save persisted `allowedCombos: []`, which
isComboAllowedForKey treats as deny-all for combo requests — a working key
silently stopped reaching anything.

Boundary (maintainer's option 1 on diegosouzapw#12267): the UI does not learn
routing-rule semantics. Entries that name no loaded combo are kept in the
selection, survive the "All" toggle, are listed read-only under the combo
list so the header count and the list agree, and are saved back verbatim.

- apiManagerPageUtils.listUnrenderableComboAccessRules(): pure split of the
  selection into entries the picker cannot render (never reports `combo/*`).
- components/AllowedCombosSection.tsx: the Allowed Combos section, extracted
  out of the frozen ApiManagerPageClient.tsx following the UsageLimitSettings
  pattern; "All" now keeps the unrenderable entries and Restrict mode shows
  them as read-only chips.
- Two apiManager i18n keys in en.json, propagated to the other 42 locales as
  __MISSING__ sentinels (English fallback at runtime).

Verification: tests/unit/api-keys-allowed-combos-preserve-12267.test.ts
(node runner, 5 rules) and tests/unit/ui/combo-picker-unrenderable-12267.test.tsx
(vitest, 6 cases) fail on the base and with the fix reverted, pass with it;
api-manager and api-key-policy neighbours 108/108; typecheck:core, eslint
(repo suppressions), complexity ratchets, file-size, mutation test-coverage
drift and changelog-integrity gates green.

Closes diegosouzapw#12267

Co-authored-by: Leon Marcos <leonaniagomez@gmail.com>
pacocartones and others added 2 commits September 2, 2026 02:04
…anslate the vi keys

Two Unit Tests fast-path shards were red on diegosouzapw#12397.

1. `permissions modal serializes All and empty Restrict Combo access
   distinctly` (tests/unit/api-manager-page-static.test.ts) pins the
   modal's All/Restrict wiring by source text, including the literal
   `setAllowAllCombos(false)` behind the Restrict button. Extracting the
   picker into AllowedCombosSection moved that call into the component and
   left the page with `onAllowAllCombosChange={setAllowAllCombos}`, so the
   assertion no longer matched. The modal now owns both transitions again:
   the component exposes `onAllowAll(preservedRules)` and `onRestrict()`,
   and the page wires `setAllowAllCombos(true)` +
   `setSelectedCombos(preservedRules)` for All and
   `setAllowAllCombos(false)` for Restrict. `preservedRules` is only the
   entries the picker cannot render, so a fully renderable selection still
   collapses to `[]` under All and serialises exactly as before, while
   `rt-*` entries keep surviving the toggle and are saved back verbatim.
   The component test follows the renamed callbacks.

2. `Vietnamese locale has no internal missing markers or empty fallbacks`
   (tests/unit/i18n-vi-completeness.test.ts) rejects `__MISSING__:`
   sentinels, which the locale propagation had left on
   `apiManager.preservedComboRules` and `apiManager.preservedComboRuleHint`
   in vi.json. Both keys now carry Vietnamese copy that reuses the
   surrounding apiManager wording; the ICU plural keeps the `count`
   placeholder and the `one`/`other` categories of en.json.

Co-authored-by: Leon Marcos <leonaniagomez@gmail.com>
@diegosouzapw
diegosouzapw merged commit 26d20a0 into diegosouzapw:release/v3.8.51 Sep 2, 2026
16 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…not render (diegosouzapw#12397)

The API key permissions modal silently dropped allowedCombos entries its Combo picker cannot render — routing-rule names such as rt-*, which matchesComboAccessRule() already honours. Stored entries rendered as zero selected, and clicking All then Restrict then Save persisted allowedCombos: [], which is deny-all for combo requests.

Those entries now survive the All toggle, are listed read-only under the combo list so the header count and the list agree, and are saved back verbatim. The UI does not learn routing-rule semantics (option 1 from the issue). The Allowed Combos section moves out of the frozen ApiManagerPageClient.tsx into its own component following the UsageLimitSettings pattern.

Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.

Thanks @pacocartones.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(api-manager): API-key allowedCombos silently drops routing-rule entries the Combo picker cannot render

2 participants