From 5e7d83e5dd944cd572d2d19e319e25197a1e5fdb Mon Sep 17 00:00:00 2001 From: gitlawr Date: Mon, 29 Jun 2026 19:13:14 +0800 Subject: [PATCH] fix(api-keys): let platform admin create a non-tenant-pinned API key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CreateOrgScopeField slot only renders a "Global" choice when the host form passes ``allowGlobal: true``. Without it, an admin in the "All Orgs" view sees only Personal + every org in the dropdown — and the form's submit injects an ``X-Organization-Id`` header for every choice, pinning the new key to a tenant. The matching backend change (api_keys.owner_principal_id nullable) only kicks in when no header is sent. Pass ``allowGlobal: true`` (default-selects Global for admin) plus ``globalLabelId: 'scope.global'`` so the dropdown option reads as plain "Global" — matching the existing tag / column labels for the same concept elsewhere in the UI, instead of the longer inference-backend "shared with all organizations" copy. Relax the ListItem type so ``owner_principal_id`` may be ``null`` — the OrganizationCell / OwnerScopeTag renderers already render the "Global" placeholder for null/undefined; the type was the only thing still claiming the column was always present. --- src/pages/api-keys/components/add-apikey-modal/form.tsx | 7 ++++++- src/pages/api-keys/config/types.ts | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pages/api-keys/components/add-apikey-modal/form.tsx b/src/pages/api-keys/components/add-apikey-modal/form.tsx index 911203a7..2ac99d30 100644 --- a/src/pages/api-keys/components/add-apikey-modal/form.tsx +++ b/src/pages/api-keys/components/add-apikey-modal/form.tsx @@ -47,7 +47,12 @@ const APIKeyForm: React.FC<{ diff --git a/src/pages/api-keys/config/types.ts b/src/pages/api-keys/config/types.ts index b0a8ecfe..f26e6155 100644 --- a/src/pages/api-keys/config/types.ts +++ b/src/pages/api-keys/config/types.ts @@ -6,10 +6,10 @@ export interface ListItem { masked_value?: string; user_id?: number; user_name?: string; - // The owning principal — an Org, or a USER principal when the key - // was created in someone's Personal Org. Read by the enterprise - // plugin's Organization column in the admin All-org view. - owner_principal_id?: number; + // The owning principal — an Org, or a USER principal for a + // personal-scope key, or NULL for an admin "All" mode key (no + // tenant pinning). + owner_principal_id?: number | null; created_at: string; updated_at: string; expires_at: string;