@rebasepro/studio 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/{ApiExplorer-D-jLWAaY.js → ApiExplorer-CCtczj3F.js} +16 -32
  2. package/dist/ApiExplorer-CCtczj3F.js.map +1 -0
  3. package/dist/ApiKeysView-B66TdzhH.js +1738 -0
  4. package/dist/ApiKeysView-B66TdzhH.js.map +1 -0
  5. package/dist/BackupsView-DmSMzAbT.js +368 -0
  6. package/dist/BackupsView-DmSMzAbT.js.map +1 -0
  7. package/dist/{BranchesView-D6Sz1a5f.js → BranchesView-DP1a87E-.js} +12 -8
  8. package/dist/BranchesView-DP1a87E-.js.map +1 -0
  9. package/dist/{CronJobsView-JwRjQCde.js → CronJobsView-TDErHTuK.js} +143 -68
  10. package/dist/CronJobsView-TDErHTuK.js.map +1 -0
  11. package/dist/{JSEditor-qiuwmcvk.js → JSEditor-B59pwg4c.js} +120 -74
  12. package/dist/JSEditor-B59pwg4c.js.map +1 -0
  13. package/dist/{LogsExplorer-Xq8K4oo6.js → LogsExplorer-BKM4yfP8.js} +48 -22
  14. package/dist/LogsExplorer-BKM4yfP8.js.map +1 -0
  15. package/dist/{MonacoEditor-D0_QljcX.js → MonacoEditor-CUxy5_k5.js} +11 -9
  16. package/dist/MonacoEditor-CUxy5_k5.js.map +1 -0
  17. package/dist/{RLSEditor-B-qrgdHy.js → RLSEditor-BlLLV6xs.js} +350 -98
  18. package/dist/RLSEditor-BlLLV6xs.js.map +1 -0
  19. package/dist/{SQLEditor-sdtoZv5F.js → SQLEditor-1An7w0j6.js} +496 -224
  20. package/dist/SQLEditor-1An7w0j6.js.map +1 -0
  21. package/dist/{SchemaVisualizer-DtDzIUNy.js → SchemaVisualizer-DCLVfA5t.js} +20 -24
  22. package/dist/SchemaVisualizer-DCLVfA5t.js.map +1 -0
  23. package/dist/{StorageView-C52dSZNf.js → StorageView-CbsHuCBf.js} +382 -228
  24. package/dist/StorageView-CbsHuCBf.js.map +1 -0
  25. package/dist/components/ApiExplorer/TryItPanel.d.ts +6 -1
  26. package/dist/components/ApiKeys/CreateApiKeyDialog.d.ts +21 -2
  27. package/dist/components/ApiKeys/scope-words.d.ts +37 -0
  28. package/dist/components/ApiKeys/scopes.d.ts +113 -0
  29. package/dist/components/AuthSimulationSelector.d.ts +5 -1
  30. package/dist/components/LogsExplorer/useLogTail.d.ts +9 -0
  31. package/dist/components/RLSEditor/policyListing.d.ts +44 -0
  32. package/dist/components/RLSEditor/policyRules.d.ts +49 -0
  33. package/dist/components/SQLEditor/MonacoEditor.d.ts +13 -1
  34. package/dist/components/SchemaVisualizer/schema-visualizer.utils.d.ts +0 -1
  35. package/dist/components/SchemaVisualizer/useSchemaGraph.d.ts +6 -0
  36. package/dist/components/load-failure.d.ts +1 -1
  37. package/dist/components/useRunAsUsers.d.ts +25 -0
  38. package/dist/index.es.js +11 -11
  39. package/dist/{load-failure-C6OMJSGC.js → load-failure-Bd8lFIO7.js} +2 -2
  40. package/dist/load-failure-Bd8lFIO7.js.map +1 -0
  41. package/dist/useRunAsUsers-CLaAtXt6.js +122 -0
  42. package/dist/useRunAsUsers-CLaAtXt6.js.map +1 -0
  43. package/dist/utils/sql_utils.d.ts +126 -36
  44. package/package.json +9 -9
  45. package/dist/ApiExplorer-D-jLWAaY.js.map +0 -1
  46. package/dist/ApiKeysView-OfJLH2x7.js +0 -1239
  47. package/dist/ApiKeysView-OfJLH2x7.js.map +0 -1
  48. package/dist/AuthSimulationSelector-BewmhMBw.js +0 -56
  49. package/dist/AuthSimulationSelector-BewmhMBw.js.map +0 -1
  50. package/dist/BackupsView-DYTAD6aW.js +0 -253
  51. package/dist/BackupsView-DYTAD6aW.js.map +0 -1
  52. package/dist/BranchesView-D6Sz1a5f.js.map +0 -1
  53. package/dist/CronJobsView-JwRjQCde.js.map +0 -1
  54. package/dist/JSEditor-qiuwmcvk.js.map +0 -1
  55. package/dist/LogsExplorer-Xq8K4oo6.js.map +0 -1
  56. package/dist/MonacoEditor-D0_QljcX.js.map +0 -1
  57. package/dist/RLSEditor-B-qrgdHy.js.map +0 -1
  58. package/dist/SQLEditor-sdtoZv5F.js.map +0 -1
  59. package/dist/SchemaVisualizer-DtDzIUNy.js.map +0 -1
  60. package/dist/StorageView-C52dSZNf.js.map +0 -1
  61. package/dist/components/ApiKeys/permissions.d.ts +0 -66
  62. package/dist/load-failure-C6OMJSGC.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiKeysView-B66TdzhH.js","names":[],"sources":["../src/components/ApiKeys/scopes.ts","../src/components/ApiKeys/scope-words.ts","../src/components/ApiKeys/CreateApiKeyDialog.tsx","../src/components/ApiKeys/ApiKeysView.tsx"],"sourcesContent":["/**\n * The pure half of the API-key panel: reading a key's scopes back as groups a\n * person can scan, and turning the create dialog's picker into the scope list\n * the server mints.\n *\n * The vocabulary itself — what a scope is, which ones take a target, which\n * plane each belongs to — is `@rebasepro/types`' `scopes.ts`, the same module\n * the server enforces with. Nothing here re-derives it; this file only shapes\n * it for the screen, so it can be tested without rendering one.\n *\n * @module\n */\n\nimport {\n describeScope,\n isAdminScope,\n isDataPlaneScope,\n KEY_MANAGEMENT_SCOPES,\n parseScope,\n scopeGrantsAny,\n scopeTargets,\n summarizeScopes,\n type ScopeSummary\n} from \"@rebasepro/types\";\n\n/** Which plane a scope belongs to, as `GET /auth/scopes` names it. */\nexport type ScopePlane = ScopeSummary[\"plane\"];\n\n/** The planes in the order the panel shows them. */\nexport const SCOPE_PLANES: readonly ScopePlane[] = [\"data\", \"admin\", \"app\"];\n\n/* ═══════════════════════════════════════════════════════════════\n Reading a key's scopes\n ═══════════════════════════════════════════════════════════════ */\n\n/** One scope a key holds, with every target it holds it on. */\nexport interface HeldScope {\n /** `resource:action`, without a target. */\n scope: string;\n label: string;\n description: string;\n plane: ScopePlane;\n /** What a target names — `collection`, `bucket`, `function`, or an app's own word. */\n targetKind?: string;\n /** `\"all\"` for the unqualified grant, otherwise the targets it is narrowed to. */\n targets: \"all\" | string[];\n}\n\nexport interface ScopeGroup {\n plane: ScopePlane;\n scopes: HeldScope[];\n}\n\nfunction planeOf(scope: string): ScopePlane {\n if (isDataPlaneScope(scope)) return \"data\";\n if (isAdminScope(scope)) return \"admin\";\n return \"app\";\n}\n\n/**\n * A key's scopes, grouped by plane and folded per scope: `data:read:posts` and\n * `data:read:authors` read as one \"Read data\" row narrowed to two collections,\n * and `data:read` beside them as the same row on every collection.\n *\n * Ordered the way the catalogue lists scopes; a scope the catalogue does not\n * know (an app scope removed since the key was minted) keeps its raw name and\n * lands at the end of the plane it would belong to.\n */\nexport function groupKeyScopes(\n scopes: readonly string[],\n catalogue: readonly ScopeSummary[] = summarizeScopes()\n): ScopeGroup[] {\n const bases: string[] = [];\n for (const entry of scopes) {\n const base = parseScope(entry)?.scope ?? entry;\n if (!bases.includes(base)) bases.push(base);\n }\n\n const position = (base: string): number => {\n const index = catalogue.findIndex(summary => summary.scope === base);\n return index < 0 ? catalogue.length + bases.indexOf(base) : index;\n };\n bases.sort((a, b) => position(a) - position(b));\n\n const held: HeldScope[] = bases.map(base => {\n const summary = catalogue.find(entry => entry.scope === base);\n const parsed = parseScope(base);\n const fallback = describeScope(base);\n return {\n scope: base,\n label: summary?.label ?? fallback.label,\n description: summary?.description ?? fallback.description,\n plane: summary?.plane ?? planeOf(base),\n ...(summary?.target ? { targetKind: summary.target } : {}),\n targets: parsed ? scopeTargets(scopes, base) : \"all\"\n };\n });\n\n return SCOPE_PLANES\n .map(plane => ({ plane, scopes: held.filter(entry => entry.plane === plane) }))\n .filter(group => group.scopes.length > 0);\n}\n\n/* ═══════════════════════════════════════════════════════════════\n What the create dialog may offer\n ═══════════════════════════════════════════════════════════════ */\n\n/** Never offered: a key that manages keys could mint its own successor. */\nexport function isKeyManagementScope(scope: string): boolean {\n return (KEY_MANAGEMENT_SCOPES as readonly string[]).includes(scope);\n}\n\n/**\n * The catalogue entries a caller may put on a key: the ones they hold, on at\n * least one target, minus key management. The server refuses anything else\n * (`SCOPE_EXCEEDS_CREATOR`, `KEY_MANAGEMENT_SCOPE`), so offering it would only\n * be a way to fail.\n */\nexport function grantableScopes(catalogue: readonly ScopeSummary[], held: readonly string[]): ScopeSummary[] {\n return catalogue.filter(summary => !isKeyManagementScope(summary.scope) && scopeGrantsAny(held, summary.scope));\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Picker state\n ═══════════════════════════════════════════════════════════════ */\n\n/** For one chosen scope: every target, or only the listed ones. */\nexport type TargetChoice =\n | { mode: \"all\" }\n | { mode: \"some\"; targets: string[] };\n\n/** The chosen scopes, keyed by `resource:action`. A scope absent here is not chosen. */\nexport type ScopeSelection = Readonly<Record<string, TargetChoice>>;\n\n/** `data:read` on everything — the narrowest useful key, and what the dialog opens with. */\nexport function defaultSelection(grantable: readonly ScopeSummary[]): ScopeSelection {\n return grantable.some(summary => summary.scope === \"data:read\") ? { \"data:read\": { mode: \"all\" } } : {};\n}\n\nfunction cleanTargets(targets: readonly string[]): string[] {\n const out: string[] = [];\n for (const raw of targets) {\n const target = raw.trim();\n if (target && !/\\s/.test(target) && !out.includes(target)) out.push(target);\n }\n return out;\n}\n\n/**\n * The scope strings a selection mints, in catalogue order when one is given.\n *\n * A scope on every target is sent unqualified; one narrowed to targets is sent\n * once per target. A scope narrowed to no target at all grants nothing and is\n * left out — {@link incompleteScopes} is how the dialog says so.\n */\nexport function buildScopeList(selection: ScopeSelection, order: readonly string[] = []): string[] {\n const chosen = Object.keys(selection);\n const rank = (scope: string): number => {\n const index = order.indexOf(scope);\n return index < 0 ? order.length + chosen.indexOf(scope) : index;\n };\n const out: string[] = [];\n for (const scope of [...chosen].sort((a, b) => rank(a) - rank(b))) {\n const choice = selection[scope];\n if (choice.mode === \"all\") {\n out.push(scope);\n } else {\n for (const target of cleanTargets(choice.targets)) out.push(`${scope}:${target}`);\n }\n }\n return out;\n}\n\n/** Scopes switched to \"only some\" with nothing chosen yet. */\nexport function incompleteScopes(selection: ScopeSelection): string[] {\n return Object.entries(selection)\n .filter(([, choice]) => choice.mode === \"some\" && cleanTargets(choice.targets).length === 0)\n .map(([scope]) => scope);\n}\n\n/** Free text in a target field: commas or whitespace separate entries. */\nexport function splitList(text: string): string[] {\n return cleanTargets(text.split(/[\\s,]+/));\n}\n\n/* ═══════════════════════════════════════════════════════════════\n The roles a service key runs as\n ═══════════════════════════════════════════════════════════════ */\n\n/**\n * The roles a service key runs as beside `service`: the picked ones, then any\n * typed ones, deduplicated. `service` itself is every service key's identity\n * already, so listing it adds nothing and is dropped, as the server does.\n */\nexport function combineRoles(picked: readonly string[], typed: string): string[] {\n const out: string[] = [];\n for (const role of [...picked, ...splitList(typed)]) {\n const id = role.trim();\n if (id && id !== \"service\" && !out.includes(id)) out.push(id);\n }\n return out;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Limits\n ═══════════════════════════════════════════════════════════════ */\n\nexport const EXPIRY_CHOICES = [\"never\", \"7d\", \"30d\", \"90d\", \"1y\"] as const;\nexport type ExpiryChoice = (typeof EXPIRY_CHOICES)[number];\n\nconst EXPIRY_DAYS: Record<Exclude<ExpiryChoice, \"never\">, number> = { \"7d\": 7, \"30d\": 30, \"90d\": 90, \"1y\": 365 };\n\nexport function isExpiryChoice(value: string): value is ExpiryChoice {\n return (EXPIRY_CHOICES as readonly string[]).includes(value);\n}\n\n/** The `expires_at` an expiry choice sends: an ISO instant, or null for never. */\nexport function expiresAtFor(choice: ExpiryChoice, now: number = Date.now()): string | null {\n if (choice === \"never\") return null;\n return new Date(now + EXPIRY_DAYS[choice] * 86_400_000).toISOString();\n}\n\n/** The `rate_limit` a rate-limit field sends: a positive integer, or null for the server default. */\nexport function rateLimitFrom(text: string): number | null {\n const digits = text.replace(/\\D/g, \"\");\n if (!digits) return null;\n const value = parseInt(digits, 10);\n return value >= 1 ? value : null;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n What the server answers\n ═══════════════════════════════════════════════════════════════ */\n\n/** The minting refusals the dialog names, beside the server's own message. */\nexport const KEY_ERROR_CODES = [\n \"INVALID_SCOPES\",\n \"SCOPE_EXCEEDS_CREATOR\",\n \"ROLE_EXCEEDS_CREATOR\",\n \"UNKNOWN_SCOPE_TARGET\",\n \"KEY_MANAGEMENT_SCOPE\"\n] as const;\nexport type KeyErrorCode = (typeof KEY_ERROR_CODES)[number];\n\nexport interface KeyError {\n /** One of {@link KEY_ERROR_CODES}, or null for anything else. */\n code: KeyErrorCode | null;\n /** The server's message, never re-worded. */\n message: string;\n}\n\nfunction codeOf(error: unknown): string | null {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) return null;\n return typeof error.code === \"string\" ? error.code : null;\n}\n\nfunction isKeyErrorCode(code: string | null): code is KeyErrorCode {\n return code !== null && (KEY_ERROR_CODES as readonly string[]).includes(code);\n}\n\nexport function readKeyError(error: unknown): KeyError {\n const code = codeOf(error);\n return {\n code: isKeyErrorCode(code) ? code : null,\n message: error instanceof Error ? error.message : String(error)\n };\n}\n\n/** The backend answered `403 PERSONAL_KEYS_DISABLED`: the app has not switched them on. */\nexport function isPersonalKeysDisabled(error: unknown): boolean {\n return codeOf(error) === \"PERSONAL_KEYS_DISABLED\";\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(entry => typeof entry === \"string\");\n}\n\nfunction isPlane(value: unknown): value is ScopePlane {\n return value === \"data\" || value === \"admin\" || value === \"app\";\n}\n\nfunction readScopeSummary(value: unknown): ScopeSummary | null {\n if (typeof value !== \"object\" || value === null) return null;\n if (!(\"scope\" in value) || typeof value.scope !== \"string\") return null;\n if (!(\"plane\" in value) || !isPlane(value.plane)) return null;\n const label = \"label\" in value && typeof value.label === \"string\" ? value.label : value.scope;\n const description = \"description\" in value && typeof value.description === \"string\" ? value.description : \"\";\n const target = \"target\" in value && typeof value.target === \"string\" ? value.target : undefined;\n return { scope: value.scope, label, description, plane: value.plane, ...(target ? { target } : {}) };\n}\n\n/** What `GET /auth/scopes` answers. */\nexport interface ScopeListing {\n scopes: ScopeSummary[];\n held: string[];\n}\n\n\n/**\n * Read `GET /auth/scopes`. Null for anything that is not that shape — a backend\n * older than scopes answers this route with something else, and offering a\n * picker built from it would offer scopes the server does not know.\n */\nexport function readScopeListing(body: unknown): ScopeListing | null {\n if (typeof body !== \"object\" || body === null) return null;\n if (!(\"scopes\" in body) || !Array.isArray(body.scopes)) return null;\n if (!(\"held\" in body) || !isStringArray(body.held)) return null;\n const scopes: ScopeSummary[] = [];\n for (const entry of body.scopes) {\n const summary = readScopeSummary(entry);\n if (summary) scopes.push(summary);\n }\n return { scopes, held: body.held };\n}\n\n/** Function names out of `GET /functions` — `{ functions: [{ name }] }`. */\nexport function functionNamesFrom(body: unknown): string[] {\n if (typeof body !== \"object\" || body === null || !(\"functions\" in body) || !Array.isArray(body.functions)) return [];\n const names: string[] = [];\n for (const entry of body.functions) {\n if (typeof entry === \"object\" && entry !== null && \"name\" in entry && typeof entry.name === \"string\" && entry.name) {\n names.push(entry.name);\n }\n }\n return names;\n}\n","/**\n * How the key panel words scopes: plane headings, \"every collection\", the\n * title over a minting refusal. One place, so the detail panel, the create\n * dialog and the secret confirmation cannot drift apart.\n *\n * Every string is a translation key. A built-in scope's label and description\n * are keys too, derived from the scope (`data:read` →\n * `studio_scope_data_read_label`); an app's own scopes are worded as the app\n * declared them, in the server's catalogue (`GET /auth/scopes`).\n *\n * @module\n */\n\nimport { DEFAULT_STORAGE_SOURCE_KEY, isBuiltInScope, type ScopeSummary } from \"@rebasepro/types\";\n\nimport type { HeldScope, KeyErrorCode, ScopePlane } from \"./scopes\";\n\n/** The panel's `t`, from `useTranslation()`. */\nexport type Translate = (key: string, vars?: Record<string, string | number>) => string;\n\n/** `data:read` → `studio_scope_data_read_label`. */\nexport function scopeLabelKey(scope: string): string {\n return `studio_scope_${scope.replace(/[^a-z0-9]/g, \"_\")}_label`;\n}\n\n/** `data:read` → `studio_scope_data_read_description`. */\nexport function scopeDescriptionKey(scope: string): string {\n return `studio_scope_${scope.replace(/[^a-z0-9]/g, \"_\")}_description`;\n}\n\n/** The translation, or `fallback` when the catalogue has none — i18next answers a missing key with the key. */\nfunction translatedOr(t: Translate, key: string, fallback: string): string {\n const text = t(key);\n return text && text !== key ? text : fallback;\n}\n\n/**\n * The catalogue in the panel's language. Built-in scopes are translated; an\n * app scope keeps the label its app declared, and a built-in scope this panel\n * has no key for (one the server added since) keeps the server's wording\n * rather than rendering blank or as a key.\n */\nexport function localizeScopes(t: Translate, catalogue: readonly ScopeSummary[]): ScopeSummary[] {\n return catalogue.map(summary => isBuiltInScope(summary.scope)\n ? {\n ...summary,\n label: translatedOr(t, scopeLabelKey(summary.scope), summary.label),\n description: translatedOr(t, scopeDescriptionKey(summary.scope), summary.description)\n }\n : summary);\n}\n\nexport function planeLabel(t: Translate, plane: ScopePlane): string {\n switch (plane) {\n case \"data\": return t(\"studio_api_keys_plane_data\");\n case \"admin\": return t(\"studio_api_keys_plane_admin\");\n case \"app\": return t(\"studio_api_keys_plane_app\");\n }\n}\n\nexport function planeHint(t: Translate, plane: ScopePlane): string {\n switch (plane) {\n case \"data\": return t(\"studio_api_keys_plane_data_hint\");\n case \"admin\": return t(\"studio_api_keys_plane_admin_hint\");\n case \"app\": return t(\"studio_api_keys_plane_app_hint\");\n }\n}\n\n/** \"Every collection\", \"Every storage source\", \"Every function\", \"Any project\". */\nexport function everyTargetLabel(t: Translate, targetKind: string): string {\n switch (targetKind) {\n case \"collection\": return t(\"studio_api_keys_target_all_collection\");\n case \"bucket\": return t(\"studio_api_keys_target_all_bucket\");\n case \"function\": return t(\"studio_api_keys_target_all_function\");\n default: return t(\"studio_api_keys_target_all_other\", { kind: targetKind });\n }\n}\n\n/** One target as a person reads it: the default storage source is \"Default bucket\", not `(default)`. */\nexport function targetLabel(t: Translate, targetKind: string | undefined, target: string): string {\n if (targetKind === \"bucket\" && target === DEFAULT_STORAGE_SOURCE_KEY) return t(\"studio_api_keys_bucket_default\");\n return target;\n}\n\n/** A held scope as one line: \"Read data — posts, authors\", \"Read data — every collection\", \"Read server logs\". */\nexport function heldScopeLine(t: Translate, held: HeldScope): string {\n if (!held.targetKind && held.targets === \"all\") return held.label;\n const reach = held.targets === \"all\"\n ? everyTargetLabel(t, held.targetKind ?? \"\")\n : held.targets.map(target => targetLabel(t, held.targetKind, target)).join(\", \");\n return `${held.label} — ${reach}`;\n}\n\n/** The title over a refused create; the server's own message goes underneath. */\nexport function keyErrorTitle(t: Translate, code: KeyErrorCode | null): string {\n switch (code) {\n case \"INVALID_SCOPES\": return t(\"studio_api_keys_error_invalid_scopes\");\n case \"SCOPE_EXCEEDS_CREATOR\": return t(\"studio_api_keys_error_scope_exceeds_creator\");\n case \"ROLE_EXCEEDS_CREATOR\": return t(\"studio_api_keys_error_role_exceeds_creator\");\n case \"UNKNOWN_SCOPE_TARGET\": return t(\"studio_api_keys_error_unknown_scope_target\");\n case \"KEY_MANAGEMENT_SCOPE\": return t(\"studio_api_keys_error_key_management_scope\");\n case null: return t(\"studio_api_keys_error_generic\");\n }\n}\n","import React, { useEffect, useMemo, useState } from \"react\";\nimport {\n Alert,\n Button,\n Checkbox,\n CircularProgress,\n cls,\n DatabaseIcon,\n defaultBorderMixin,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n iconSize,\n Label,\n MultiSelect,\n MultiSelectItem,\n Select,\n SelectItem,\n ShieldIcon,\n TagIcon,\n TextField,\n Tooltip,\n Typography,\n WrenchIcon\n} from \"@rebasepro/ui\";\nimport {\n useApiBase,\n useApiConfig,\n useRebaseClient,\n useStorageSources,\n useStudioCollectionRegistry,\n useTranslation\n} from \"@rebasepro/app\";\nimport {\n DEFAULT_STORAGE_SOURCE_KEY,\n hasAdminRole,\n scopeTargets,\n type ApiKeyKind,\n type ApiKeyWithSecret,\n type RebaseClient,\n type RoleSummary,\n type ScopeSummary\n} from \"@rebasepro/types\";\n\nimport {\n buildScopeList,\n combineRoles,\n defaultSelection,\n EXPIRY_CHOICES,\n expiresAtFor,\n functionNamesFrom,\n grantableScopes,\n groupKeyScopes,\n incompleteScopes,\n isExpiryChoice,\n rateLimitFrom,\n readKeyError,\n SCOPE_PLANES,\n splitList,\n type ExpiryChoice,\n type KeyError,\n type ScopeListing,\n type ScopePlane,\n type ScopeSelection,\n type TargetChoice\n} from \"./scopes\";\nimport { everyTargetLabel, heldScopeLine, keyErrorTitle, localizeScopes, planeHint, planeLabel, type Translate } from \"./scope-words\";\n\n/** The scope catalogue as the panel holds it: still loading, read, or not readable. */\nexport type ScopeListingState =\n | { status: \"loading\" }\n | { status: \"ready\"; listing: ScopeListing }\n | { status: \"failed\"; message: string };\n\n/* ═══════════════════════════════════════════════════════════════\n Section heading\n ═══════════════════════════════════════════════════════════════ */\n\nfunction SectionLabel({ children, hint }: { children: React.ReactNode; hint?: React.ReactNode }) {\n return (\n <div className=\"flex items-baseline gap-2 mb-2\">\n <Typography\n variant=\"label\"\n className=\"text-2xs uppercase tracking-wider font-semibold text-surface-600 dark:text-surface-300\"\n gutterBottom={false}\n >\n {children}\n </Typography>\n {hint && (\n <Typography variant=\"caption\" color=\"secondary\" className=\"text-2xs\" gutterBottom={false}>\n {hint}\n </Typography>\n )}\n </div>\n );\n}\n\nexport function PlaneIcon({ plane, className }: { plane: ScopePlane; className?: string }) {\n const Component = plane === \"data\" ? DatabaseIcon : plane === \"admin\" ? WrenchIcon : TagIcon;\n return <Component size={iconSize.smallest} className={className}/>;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n One scope in the picker\n ═══════════════════════════════════════════════════════════════ */\n\ninterface ScopeRowProps {\n summary: ScopeSummary;\n choice: TargetChoice | undefined;\n /** What the caller holds this scope on: every target, or only these. */\n reach: \"all\" | string[];\n /** The targets the panel can list for this scope's kind, or null to type them. */\n options: { value: string; label: string }[] | null;\n draft: string | undefined;\n onToggle: (on: boolean) => void;\n onChoice: (choice: TargetChoice) => void;\n onDraft: (text: string) => void;\n first: boolean;\n t: Translate;\n}\n\nfunction ScopeRow({ summary, choice, reach, options, draft, onToggle, onChoice, onDraft, first, t }: ScopeRowProps) {\n const id = `api-key-scope-${summary.scope.replace(/[^a-z0-9-]/gi, \"-\")}`;\n const targetKind = summary.target;\n const pickable = reach === \"all\" ? options : reach.map(value => ({ value, label: value }));\n return (\n <div className={cls(\"flex flex-col gap-2 px-3 py-2.5\", !first && cls(\"border-t\", defaultBorderMixin))}>\n <div className=\"flex items-start gap-3\">\n {/* The kit's checkbox sits in a 32px hit area; pulled up and left so\n the box lines up with the label's first line and the row's edge. */}\n <div className=\"-my-1.5 -ml-2 shrink-0\">\n <Checkbox id={id} size=\"small\" checked={!!choice} onCheckedChange={onToggle}/>\n </div>\n <Label htmlFor={id} className=\"flex-1 min-w-0 cursor-pointer\">\n <Typography variant=\"body2\" component=\"span\" gutterBottom={false} className=\"block text-[13px] font-medium\">\n {summary.label}\n </Typography>\n {summary.description && (\n <Typography variant=\"caption\" component=\"span\" color=\"secondary\" gutterBottom={false} className=\"block text-2xs leading-snug font-normal\">\n {summary.description}\n </Typography>\n )}\n </Label>\n <Typography variant=\"caption\" color=\"disabled\" gutterBottom={false} className=\"font-mono text-2xs shrink-0 pt-0.5\">\n {summary.scope}\n </Typography>\n </div>\n\n {choice && targetKind && (\n <div className=\"flex flex-wrap items-center gap-2 pl-9\">\n {reach === \"all\" && (\n <div className=\"w-52 shrink-0\">\n <Select\n size=\"small\"\n fullWidth\n position=\"popper\"\n value={choice.mode}\n aria-label={t(\"studio_api_keys_target_mode\")}\n onValueChange={(mode) => onChoice(mode === \"all\"\n ? { mode: \"all\" }\n : { mode: \"some\", targets: choice.mode === \"some\" ? choice.targets : [] })}\n renderValue={(mode) => mode === \"all\"\n ? everyTargetLabel(t, targetKind)\n : t(\"studio_api_keys_target_some\")}\n >\n <SelectItem value=\"all\">{everyTargetLabel(t, targetKind)}</SelectItem>\n <SelectItem value=\"some\">{t(\"studio_api_keys_target_some\")}</SelectItem>\n </Select>\n </div>\n )}\n {choice.mode === \"some\" && (pickable && pickable.length > 0\n ? (\n <div className=\"flex-1 min-w-[12rem]\">\n <MultiSelect\n size=\"small\"\n className=\"w-full\"\n value={choice.targets}\n placeholder={t(\"studio_api_keys_target_pick\")}\n onValueChange={(targets) => onChoice({ mode: \"some\", targets })}\n >\n {pickable.map(option => (\n <MultiSelectItem key={option.value} value={option.value}>\n {option.label}\n </MultiSelectItem>\n ))}\n </MultiSelect>\n </div>\n )\n : (\n <TextField\n size=\"small\"\n className=\"flex-1 min-w-[12rem]\"\n aria-label={t(\"studio_api_keys_target_typed_placeholder\", { kind: targetKind })}\n placeholder={t(\"studio_api_keys_target_typed_placeholder\", { kind: targetKind })}\n value={draft ?? (choice.mode === \"some\" ? choice.targets.join(\", \") : \"\")}\n onChange={(e) => {\n onDraft(e.target.value);\n onChoice({ mode: \"some\", targets: splitList(e.target.value) });\n }}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Create API Key Dialog\n ═══════════════════════════════════════════════════════════════ */\n\nexport function CreateApiKeyDialog({\n kind,\n scopeListing,\n onRetryScopes,\n onClose,\n onCreated\n }: {\n /** A service key for the project, or a personal key for the signed-in account. */\n kind: ApiKeyKind;\n scopeListing: ScopeListingState;\n onRetryScopes: () => void;\n onClose: () => void;\n onCreated: (key: ApiKeyWithSecret) => void;\n}) {\n const client = useRebaseClient<RebaseClient>();\n const { t } = useTranslation();\n const collectionRegistry = useStudioCollectionRegistry();\n const storageSources = useStorageSources();\n const apiConfig = useApiConfig();\n const apiBase = useApiBase();\n\n const listing = scopeListing.status === \"ready\" ? scopeListing.listing : null;\n /** Built-in scopes in the panel's language; app scopes as the app declared them. */\n const catalogue = useMemo(() => listing ? localizeScopes(t, listing.scopes) : [], [listing, t]);\n const grantable = useMemo(() => listing ? grantableScopes(catalogue, listing.held) : [], [listing, catalogue]);\n const order = useMemo(() => catalogue.map(summary => summary.scope), [catalogue]);\n\n const [name, setName] = useState(\"\");\n /** Null until the person changes it: the default follows the catalogue once it arrives. */\n const [chosen, setChosen] = useState<ScopeSelection | null>(null);\n const [drafts, setDrafts] = useState<Record<string, string>>({});\n const [pickedRoles, setPickedRoles] = useState<string[]>([]);\n const [typedRoles, setTypedRoles] = useState(\"\");\n const [roleOptions, setRoleOptions] = useState<RoleSummary[]>([]);\n const [rolesUnavailable, setRolesUnavailable] = useState(false);\n const [rateLimit, setRateLimit] = useState(\"\");\n const [expiry, setExpiry] = useState<ExpiryChoice>(\"never\");\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<KeyError | null>(null);\n\n const selection = chosen ?? defaultSelection(grantable);\n\n /* ── What a target can name, for the scopes that take one ── */\n\n const collections = useMemo(\n () => (collectionRegistry?.collections ?? [])\n .map(col => col.slug)\n .filter((slug): slug is string => !!slug)\n .sort((a, b) => a.localeCompare(b)),\n [collectionRegistry?.collections]\n );\n\n const buckets = useMemo(() => {\n const keys = Object.keys(storageSources.sources);\n if (!keys.includes(DEFAULT_STORAGE_SOURCE_KEY)) keys.unshift(DEFAULT_STORAGE_SOURCE_KEY);\n return keys.map(key => ({\n value: key,\n label: storageSources.registry[key]?.label\n ?? (key === DEFAULT_STORAGE_SOURCE_KEY ? t(\"studio_api_keys_bucket_default\") : key)\n }));\n }, [storageSources.sources, storageSources.registry, t]);\n\n /**\n * Served functions, so a key can be narrowed to one by name. Best-effort:\n * a backend that serves none, or refuses the index, leaves the free-text\n * field — and the server refuses a name it does not serve.\n */\n const [functionNames, setFunctionNames] = useState<string[]>([]);\n useEffect(() => {\n if (!apiBase) return;\n let cancelled = false;\n (async () => {\n try {\n const token = await apiConfig?.getAuthToken?.();\n const res = await fetch(`${apiBase}/functions`, {\n headers: token ? { Authorization: `Bearer ${token}` } : undefined\n });\n if (!res.ok) return;\n const names = functionNamesFrom(await res.json());\n if (!cancelled) setFunctionNames(names);\n } catch {\n /* No listing available; the free-text field covers it. */\n }\n })();\n return () => { cancelled = true; };\n }, [apiBase, apiConfig]);\n\n const optionsFor = (summary: ScopeSummary): { value: string; label: string }[] | null => {\n switch (summary.target) {\n case \"collection\": return collections.map(slug => ({ value: slug, label: slug }));\n case \"bucket\": return buckets;\n case \"function\": return functionNames.map(fn => ({ value: fn, label: `${fn}()` }));\n default: return null;\n }\n };\n\n /* ── Roles a service key runs as ── */\n\n useEffect(() => {\n if (kind !== \"service\") return;\n const admin = client?.admin;\n if (!admin) {\n setRolesUnavailable(true);\n return;\n }\n let cancelled = false;\n admin.listRoles()\n .then(res => { if (!cancelled) setRoleOptions(res.roles); })\n .catch(() => { if (!cancelled) setRolesUnavailable(true); });\n return () => { cancelled = true; };\n }, [client, kind]);\n\n /* ── Picker edits ── */\n\n const toggle = (summary: ScopeSummary, on: boolean) => {\n setChosen(current => {\n const next: Record<string, TargetChoice> = { ...(current ?? defaultSelection(grantable)) };\n if (!on) {\n delete next[summary.scope];\n return next;\n }\n const reach = listing ? scopeTargets(listing.held, summary.scope) : \"all\";\n next[summary.scope] = reach === \"all\" ? { mode: \"all\" } : { mode: \"some\", targets: [] };\n return next;\n });\n };\n\n const setChoice = (scope: string, choice: TargetChoice) => {\n setChosen(current => ({ ...(current ?? defaultSelection(grantable)), [scope]: choice }));\n };\n\n /* ── What would be sent ── */\n\n const scopes = buildScopeList(selection, order);\n const incomplete = incompleteScopes(selection);\n const roles = kind === \"service\" ? combineRoles(pickedRoles, typedRoles) : [];\n const runsAsAdmin = hasAdminRole(roles);\n const granted = groupKeyScopes(scopes, catalogue);\n const labelOf = (scope: string) => catalogue.find(summary => summary.scope === scope)?.label ?? scope;\n\n const canSubmit = !!listing && !!name.trim() && scopes.length > 0 && incomplete.length === 0 && !creating;\n const submitBlockedReason = !name.trim()\n ? t(\"studio_api_keys_block_name\")\n : scopes.length === 0\n ? t(\"studio_api_keys_block_scopes\")\n : incomplete.length > 0\n ? t(\"studio_api_keys_block_targets\")\n : \"\";\n\n const handleCreate = async () => {\n if (!canSubmit || !client) return;\n setCreating(true);\n setError(null);\n try {\n const expires_at = expiresAtFor(expiry);\n const created = kind === \"service\"\n ? await client.apiKeys?.createKey({\n name: name.trim(),\n scopes,\n roles,\n rate_limit: rateLimitFrom(rateLimit),\n expires_at\n })\n : await client.personalKeys?.createKey({ name: name.trim(), scopes, expires_at });\n if (!created) {\n setError({ code: null, message: t(\"studio_api_keys_unsupported\") });\n return;\n }\n onCreated(created.key);\n } catch (e: unknown) {\n setError(readKeyError(e));\n } finally {\n setCreating(false);\n }\n };\n\n const planes = SCOPE_PLANES\n .map(plane => ({ plane, scopes: grantable.filter(summary => summary.plane === plane) }))\n .filter(group => group.scopes.length > 0);\n\n return (\n <Dialog open onOpenChange={(open) => { if (!open && !creating) onClose(); }} maxWidth=\"2xl\">\n\n <DialogTitle variant=\"subtitle1\" gutterBottom={false} className=\"font-semibold\">\n {kind === \"service\" ? t(\"studio_api_keys_create_title\") : t(\"studio_api_keys_create_personal_title\")}\n </DialogTitle>\n\n <DialogContent includeMargin={false} className=\"px-8 pt-2 pb-4 flex flex-col gap-6\">\n\n <Typography variant=\"body2\" color=\"secondary\" gutterBottom={false} className=\"text-[13px] max-w-[62ch]\">\n {kind === \"service\" ? t(\"studio_api_keys_create_intro\") : t(\"studio_api_keys_create_personal_intro\")}\n </Typography>\n\n <TextField\n label={t(\"studio_api_keys_field_name\")}\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={t(\"studio_api_keys_field_name_placeholder\")}\n size=\"small\"\n autoFocus\n />\n\n {/* ── Scopes ── */}\n <div>\n <SectionLabel hint={t(\"studio_api_keys_section_scopes_hint\")}>\n {t(\"studio_api_keys_scopes\")}\n </SectionLabel>\n\n {scopeListing.status === \"loading\" && (\n <div className=\"flex justify-center py-6\"><CircularProgress size=\"small\"/></div>\n )}\n\n {scopeListing.status === \"failed\" && (\n <Alert\n color=\"error\"\n size=\"small\"\n action={<Button size=\"small\" variant=\"text\" onClick={onRetryScopes}>{t(\"retry\")}</Button>}\n >\n <Typography variant=\"body2\" gutterBottom={false} className=\"font-medium\">\n {t(\"studio_api_keys_scopes_read_failed\")}\n </Typography>\n {scopeListing.message && (\n <Typography variant=\"caption\" gutterBottom={false} className=\"block font-mono break-all\">\n {scopeListing.message}\n </Typography>\n )}\n </Alert>\n )}\n\n {listing && (\n <div className=\"flex flex-col gap-4\">\n {planes.map(({ plane, scopes: offered }) => (\n <div key={plane}>\n <div className=\"flex items-center gap-2 mb-1.5\">\n <PlaneIcon plane={plane} className=\"text-surface-500 dark:text-surface-400\"/>\n <Typography variant=\"body2\" gutterBottom={false} className=\"text-[13px] font-medium\">\n {planeLabel(t, plane)}\n </Typography>\n <Typography variant=\"caption\" color=\"secondary\" gutterBottom={false} className=\"text-2xs truncate\">\n {planeHint(t, plane)}\n </Typography>\n </div>\n <div className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}>\n {offered.map((summary, index) => (\n <ScopeRow\n key={summary.scope}\n summary={summary}\n choice={selection[summary.scope]}\n reach={scopeTargets(listing.held, summary.scope)}\n options={optionsFor(summary)}\n draft={drafts[summary.scope]}\n onToggle={(on) => toggle(summary, on)}\n onChoice={(choice) => setChoice(summary.scope, choice)}\n onDraft={(text) => setDrafts(current => ({ ...current, [summary.scope]: text }))}\n first={index === 0}\n t={t}\n />\n ))}\n </div>\n </div>\n ))}\n <Typography variant=\"caption\" color=\"secondary\" gutterBottom={false} className=\"text-2xs leading-snug max-w-[70ch]\">\n {t(\"studio_api_keys_scopes_offered_note\")}\n </Typography>\n </div>\n )}\n </div>\n\n {/* ── RLS roles ── */}\n {kind === \"service\" && (\n <div>\n <SectionLabel hint={t(\"studio_api_keys_roles_rows_hint\")}>\n {t(\"studio_api_keys_roles\")}\n </SectionLabel>\n <Typography variant=\"caption\" color=\"secondary\" gutterBottom={false} className=\"block mb-3 text-2xs leading-snug max-w-[70ch]\">\n {t(\"studio_api_keys_roles_explainer\")}\n </Typography>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3 items-start\">\n {roleOptions.length > 0 && (\n <div>\n <MultiSelect\n size=\"small\"\n className=\"w-full\"\n label={t(\"roles\")}\n value={pickedRoles}\n onValueChange={setPickedRoles}\n >\n {roleOptions.map(role => (\n <MultiSelectItem key={role.id} value={role.id}>\n {role.name === role.id ? role.id : `${role.name} (${role.id})`}\n </MultiSelectItem>\n ))}\n </MultiSelect>\n </div>\n )}\n <TextField\n size=\"small\"\n label={t(\"studio_api_keys_roles_other\")}\n placeholder={t(\"studio_api_keys_roles_other_placeholder\")}\n value={typedRoles}\n onChange={(e) => setTypedRoles(e.target.value)}\n />\n </div>\n {rolesUnavailable && (\n <Typography variant=\"caption\" color=\"secondary\" gutterBottom={false} className=\"block mt-1.5 text-2xs\">\n {t(\"studio_api_keys_roles_unavailable\")}\n </Typography>\n )}\n {runsAsAdmin && (\n <Alert color=\"warning\" size=\"small\" outerClassName=\"mt-3\">\n {t(\"studio_api_keys_roles_admin_warning\")}\n </Alert>\n )}\n </div>\n )}\n\n {/* ── Limits ── */}\n <div>\n <SectionLabel>{t(\"studio_api_keys_section_limits\")}</SectionLabel>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3 items-end\">\n {/* Each control gets its own cell: `Select.Root` renders no DOM\n node, so an unwrapped Select puts its label and its control\n into two separate grid items. */}\n <div>\n <Select\n label={t(\"studio_api_keys_stat_expires\")}\n value={expiry}\n onValueChange={(value) => { if (isExpiryChoice(value)) setExpiry(value); }}\n size=\"small\"\n fullWidth\n position=\"popper\"\n renderValue={(value) => expiryLabel(t, isExpiryChoice(value) ? value : \"never\")}\n >\n {EXPIRY_CHOICES.map(choice => (\n <SelectItem key={choice} value={choice}>{expiryLabel(t, choice)}</SelectItem>\n ))}\n </Select>\n </div>\n {kind === \"service\" && (\n <div>\n {/* Labelled above rather than floating inside, so it lines\n up with the Select beside it. */}\n <Label\n htmlFor=\"api-key-rate-limit\"\n className=\"block ml-3.5 mb-1 text-text-secondary dark:text-text-secondary-dark\"\n >\n {t(\"studio_api_keys_stat_rate_limit\")}\n </Label>\n <TextField\n id=\"api-key-rate-limit\"\n value={rateLimit}\n onChange={(e) => setRateLimit(e.target.value.replace(/\\D/g, \"\"))}\n placeholder=\"1000\"\n size=\"small\"\n endAdornment={\n <Typography variant=\"caption\" color=\"secondary\" component=\"span\" gutterBottom={false} className=\"text-2xs whitespace-nowrap\">\n {t(\"studio_api_keys_rate_limit_unit\")}\n </Typography>\n }\n />\n </div>\n )}\n </div>\n {kind === \"service\" && (\n <Typography variant=\"caption\" color=\"secondary\" gutterBottom={false} className=\"block mt-1.5 text-2xs\">\n {t(\"studio_api_keys_rate_limit_hint\")} {t(\"studio_api_keys_rate_limit_scope\")}\n </Typography>\n )}\n </div>\n\n {/* ── Plain-language read-back of the key being built ── */}\n {listing && (\n <div className={cls(\"rounded-lg border px-3 py-2.5 bg-surface-field\", defaultBorderMixin)}>\n <Typography\n variant=\"label\"\n gutterBottom={false}\n className=\"text-2xs uppercase tracking-wider font-semibold text-surface-600 dark:text-surface-300\"\n >\n {t(\"studio_api_keys_summary_title\")}\n </Typography>\n {granted.length === 0\n ? (\n <Typography variant=\"body2\" color=\"secondary\" gutterBottom={false} className=\"mt-1.5 text-[13px]\">\n {t(\"studio_api_keys_summary_empty\")}\n </Typography>\n )\n : (\n <div className=\"mt-1.5 flex flex-col gap-1\">\n {granted.flatMap(group => group.scopes.map(held => (\n <div key={held.scope} className=\"flex items-start gap-2\">\n <PlaneIcon plane={group.plane} className=\"mt-[3px] shrink-0 text-surface-500 dark:text-surface-400\"/>\n <Typography variant=\"body2\" gutterBottom={false} className=\"text-[13px] leading-snug\">\n {heldScopeLine(t, held)}\n </Typography>\n </div>\n )))}\n {kind === \"service\" && roles.length > 0 && (\n <div className=\"flex items-start gap-2\">\n <ShieldIcon\n size={iconSize.smallest}\n className={cls(\"mt-[3px] shrink-0\", runsAsAdmin\n ? \"text-amber-600 dark:text-amber-400\"\n : \"text-surface-500 dark:text-surface-400\")}\n />\n <Typography variant=\"body2\" gutterBottom={false} className=\"text-[13px] leading-snug\">\n {t(\"studio_api_keys_summary_roles\", { roles: [\"service\", ...roles].join(\", \") })}\n </Typography>\n </div>\n )}\n </div>\n )}\n {incomplete.length > 0 && (\n <Typography variant=\"caption\" color=\"secondary\" gutterBottom={false} className=\"block mt-2 text-2xs\">\n {incomplete.map(scope => t(\"studio_api_keys_target_missing\", { scope: labelOf(scope) })).join(\" \")}\n </Typography>\n )}\n </div>\n )}\n\n {error && (\n <Alert color=\"error\" size=\"small\">\n <Typography variant=\"body2\" gutterBottom={false} className=\"font-medium\">\n {keyErrorTitle(t, error.code)}\n </Typography>\n <Typography variant=\"caption\" gutterBottom={false} className=\"block leading-snug\">\n {error.message}\n </Typography>\n </Alert>\n )}\n\n </DialogContent>\n\n <DialogActions>\n <Button variant=\"text\" onClick={onClose} disabled={creating}>{t(\"cancel\")}</Button>\n <Tooltip title={submitBlockedReason}>\n <span>\n <Button\n color=\"primary\"\n onClick={handleCreate}\n disabled={!canSubmit}\n startIcon={creating ? <CircularProgress size=\"smallest\"/> : undefined}\n >\n {creating ? t(\"studio_api_keys_creating\") : t(\"studio_api_keys_create\")}\n </Button>\n </span>\n </Tooltip>\n </DialogActions>\n </Dialog>\n );\n}\n\nfunction expiryLabel(t: Translate, choice: ExpiryChoice): string {\n switch (choice) {\n case \"never\": return t(\"studio_api_keys_never\");\n case \"7d\": return t(\"studio_api_keys_expiry_7d\");\n case \"30d\": return t(\"studio_api_keys_expiry_30d\");\n case \"90d\": return t(\"studio_api_keys_expiry_90d\");\n case \"1y\": return t(\"studio_api_keys_expiry_1y\");\n }\n}\n","\nimport React, { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport {\n Alert,\n Button,\n Chip,\n CircularProgress,\n cls,\n defaultBorderMixin,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n IconButton,\n iconSize,\n KeyRoundIcon,\n RefreshCwIcon,\n ShieldIcon,\n Tab,\n Tabs,\n Tooltip,\n Typography,\n CopyIcon,\n PlusIcon as AddIcon,\n Trash2Icon as DeleteIcon,\n AlertCircleIcon,\n CheckCircleIcon\n} from \"@rebasepro/ui\";\nimport { useRebaseClient, useSnackbarController, useTranslation } from \"@rebasepro/app\";\nimport {\n ADMIN_ROLE,\n hasAdminRole,\n summarizeScopes,\n type ApiKeyKind,\n type ApiKeyMasked,\n type ApiKeyWithSecret,\n type RebaseClient,\n type ScopeSummary\n} from \"@rebasepro/types\";\n\nimport { CreateApiKeyDialog, PlaneIcon, type ScopeListingState } from \"./CreateApiKeyDialog\";\nimport { groupKeyScopes, isPersonalKeysDisabled, readScopeListing, type ScopeGroup } from \"./scopes\";\nimport { everyTargetLabel, heldScopeLine, localizeScopes, planeHint, planeLabel, targetLabel, type Translate } from \"./scope-words\";\nimport { classifyLoadFailure, type LoadFailure } from \"../load-failure\";\nimport { LoadFailureView } from \"../load-failure-view\";\n\n/* ═══════════════════════════════════════════════════════════════\n Helpers\n ═══════════════════════════════════════════════════════════════ */\n\n/** Within a day, relative and in the panel's language; beyond it, the date. */\nfunction formatRelative(iso: string | null | undefined, language: string): string {\n if (!iso) return \"—\";\n const date = new Date(iso);\n const diff = date.getTime() - Date.now();\n const abs = Math.abs(diff);\n try {\n if (abs >= 86_400_000) return date.toLocaleDateString(language);\n const format = new Intl.RelativeTimeFormat(language, { numeric: \"auto\", style: \"short\" });\n if (abs < 3_600_000) return format.format(Math.round(diff / 60_000), \"minute\");\n return format.format(Math.round(diff / 3_600_000), \"hour\");\n } catch {\n return date.toLocaleDateString();\n }\n}\n\nfunction isExpired(key: ApiKeyMasked): boolean {\n return !!(key.expires_at && new Date(key.expires_at) < new Date());\n}\n\ntype KeyStatusKind = \"active\" | \"expired\" | \"revoked\";\n\nfunction keyStatus(key: ApiKeyMasked): { kind: KeyStatusKind; color: string } {\n if (key.revoked_at) return { kind: \"revoked\", color: \"text-red-500\" };\n if (isExpired(key)) return { kind: \"expired\", color: \"text-amber-500\" };\n return { kind: \"active\", color: \"text-emerald-500\" };\n}\n\nfunction statusLabel(t: Translate, kind: KeyStatusKind): string {\n switch (kind) {\n case \"active\": return t(\"studio_api_keys_status_active\");\n case \"expired\": return t(\"studio_api_keys_status_expired\");\n case \"revoked\": return t(\"studio_api_keys_status_revoked\");\n }\n}\n\n/**\n * A service key that runs as `admin`: row-level security does not limit its\n * reads, writes or deletes, and it passes `admin` checks in functions and\n * storage. A personal key has no roles of its own.\n */\nfunction runsAsAdmin(key: ApiKeyMasked): boolean {\n return key.kind === \"service\" && hasAdminRole(key.roles);\n}\n\n/** One short phrase for a list row: the one scope a key holds, or how many. */\nfunction scopeBrief(t: Translate, groups: ScopeGroup[]): string {\n const held = groups.flatMap(group => group.scopes);\n if (held.length === 0) return \"—\";\n if (held.length === 1) return held[0].label;\n return t(\"studio_api_keys_scopes_count\", { count: held.length });\n}\n\n/**\n * The scope catalogue — every scope this backend knows, worded, and what the\n * signed-in account holds. The create dialog offers from it; the detail panel\n * labels a key's scopes with it, and falls back to the built-in wording while\n * it is loading or when this backend does not serve it.\n */\nfunction useScopeListing(client: RebaseClient | undefined): [ScopeListingState, () => void] {\n const [state, setState] = useState<ScopeListingState>({ status: \"loading\" });\n const [attempt, setAttempt] = useState(0);\n\n useEffect(() => {\n const api = client?.personalKeys;\n if (!api) {\n setState({ status: \"failed\", message: \"\" });\n return;\n }\n let cancelled = false;\n setState({ status: \"loading\" });\n (async () => {\n try {\n const listing = readScopeListing(await api.listScopes());\n if (!cancelled) setState(listing ? { status: \"ready\", listing } : { status: \"failed\", message: \"\" });\n } catch (e: unknown) {\n if (!cancelled) setState({ status: \"failed\", message: e instanceof Error ? e.message : String(e) });\n }\n })();\n return () => { cancelled = true; };\n }, [client, attempt]);\n\n const retry = useCallback(() => setAttempt(n => n + 1), []);\n return [state, retry];\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Main Component\n ═══════════════════════════════════════════════════════════════ */\n\nexport function ApiKeysView() {\n const client = useRebaseClient<RebaseClient>();\n const { t } = useTranslation();\n const [kind, setKind] = useState<ApiKeyKind>(\"service\");\n const [scopeListing, retryScopes] = useScopeListing(client);\n\n const tabs = (\n <Tabs\n value={kind}\n onValueChange={(value) => setKind(value === \"personal\" ? \"personal\" : \"service\")}\n variant=\"boxy\"\n className=\"border-b border-hairline\"\n >\n <Tab value=\"service\">{t(\"studio_api_keys_tab_service\")}</Tab>\n <Tab value=\"personal\">{t(\"studio_api_keys_tab_personal\")}</Tab>\n </Tabs>\n );\n\n // Keyed by kind: each tab is its own list, selection and failure.\n return (\n <KeysPane\n key={kind}\n kind={kind}\n tabs={tabs}\n scopeListing={scopeListing}\n onRetryScopes={retryScopes}\n />\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n One tab: service keys, or the signed-in account's own\n ═══════════════════════════════════════════════════════════════ */\n\nfunction KeysPane({\n kind,\n tabs,\n scopeListing,\n onRetryScopes\n }: {\n kind: ApiKeyKind;\n tabs: React.ReactNode;\n scopeListing: ScopeListingState;\n onRetryScopes: () => void;\n}) {\n const client = useRebaseClient<RebaseClient>();\n const snackbar = useSnackbarController();\n const { t } = useTranslation();\n const [keys, setKeys] = useState<ApiKeyMasked[]>([]);\n const [loading, setLoading] = useState(true);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [showCreate, setShowCreate] = useState(false);\n const [showSecret, setShowSecret] = useState<ApiKeyWithSecret | null>(null);\n const [revoking, setRevoking] = useState<string | null>(null);\n const [confirmRevoke, setConfirmRevoke] = useState<ApiKeyMasked | null>(null);\n /** Why the key listing failed, classified — see `load-failure.ts`. */\n const [failure, setFailure] = useState<LoadFailure | null>(null);\n /** The backend answered PERSONAL_KEYS_DISABLED: a setting, not a failure. */\n const [personalOff, setPersonalOff] = useState(false);\n\n // Built-in scopes in the panel's language; app scopes as the app declared them.\n const catalogue: readonly ScopeSummary[] = useMemo(\n () => localizeScopes(t, scopeListing.status === \"ready\" ? scopeListing.listing.scopes : summarizeScopes()),\n [t, scopeListing]\n );\n\n const clientRef = useRef(client);\n clientRef.current = client;\n const snackbarRef = useRef(snackbar);\n snackbarRef.current = snackbar;\n\n const keysApi = useCallback(() => {\n const c = clientRef.current;\n return kind === \"service\" ? c?.apiKeys : c?.personalKeys;\n }, [kind]);\n\n const loadKeys = useCallback(async () => {\n const api = keysApi();\n if (!api) { setLoading(false); return; }\n try {\n const res = await api.listKeys();\n setKeys(res.keys);\n setFailure(null);\n setPersonalOff(false);\n } catch (e: unknown) {\n // \"No API keys yet\" is a claim about the project. A refused listing\n // is a claim about the caller, and only one of the two is an\n // invitation to create a key. Personal keys switched off is a third\n // thing: the app's own setting, explained rather than reported.\n if (kind === \"personal\" && isPersonalKeysDisabled(e)) {\n setPersonalOff(true);\n setFailure(null);\n } else {\n setFailure(classifyLoadFailure(e));\n }\n } finally {\n setLoading(false);\n }\n }, [keysApi, kind]);\n\n useEffect(() => { loadKeys(); }, [loadKeys]);\n\n const handleRevoke = async (id: string) => {\n const api = keysApi();\n if (!api) return;\n setRevoking(id);\n try {\n await api.revokeKey(id);\n snackbarRef.current.open({ type: \"success\", message: t(\"studio_api_keys_revoked\") });\n await loadKeys();\n if (selectedId === id) setSelectedId(null);\n } catch (e: unknown) {\n snackbarRef.current.open({ type: \"error\", message: e instanceof Error ? e.message : String(e) });\n } finally { setRevoking(null); }\n };\n\n const handleCreated = (keyWithSecret: ApiKeyWithSecret) => {\n setShowCreate(false);\n setShowSecret(keyWithSecret);\n loadKeys();\n };\n\n const selectedKey = keys.find(k => k.id === selectedId);\n const activeKeys = keys.filter(k => !k.revoked_at && !isExpired(k));\n const inactiveKeys = keys.filter(k => k.revoked_at || isExpired(k));\n\n return (\n <>\n <div className=\"flex h-full w-full overflow-hidden bg-surface-card\">\n {/* ── Key List ── */}\n <div className={cls(\"flex flex-col w-[340px] min-w-[280px] border-r h-full\", defaultBorderMixin)}>\n {tabs}\n <div className={cls(\"flex items-center justify-between px-4 py-2.5 border-b bg-surface-sheet min-h-[48px]\", defaultBorderMixin)}>\n <div className=\"flex items-center gap-2\">\n <KeyRoundIcon size={iconSize.smallest} className=\"text-primary\"/>\n <Typography variant=\"subtitle2\" className=\"font-semibold\">{t(\"studio_tool_api_keys\")}</Typography>\n <Chip size=\"smallest\" className=\"bg-surface-raised text-surface-600 dark:text-surface-300\">{activeKeys.length}</Chip>\n </div>\n <div className=\"flex items-center gap-1\">\n <IconButton size=\"small\" onClick={loadKeys} title={t(\"studio_api_keys_refresh\")}><RefreshCwIcon size={iconSize.smallest}/></IconButton>\n <Button\n size=\"small\"\n color=\"primary\"\n disabled={personalOff}\n onClick={() => setShowCreate(true)}\n startIcon={<AddIcon size={iconSize.smallest}/>}\n >\n {t(\"studio_api_keys_new\")}\n </Button>\n </div>\n </div>\n <div className=\"flex-1 overflow-y-auto p-2 space-y-1\">\n {loading && (\n <div className=\"flex items-center justify-center h-full\"><CircularProgress/></div>\n )}\n {!loading && failure && (\n <LoadFailureView\n failure={failure}\n title={kind === \"service\" ? t(\"studio_api_keys_read_failed\") : t(\"studio_api_keys_personal_read_failed\")}\n deniedTitle={kind === \"service\" ? t(\"studio_api_keys_denied_title\") : t(\"studio_api_keys_personal_denied_title\")}\n deniedHint={kind === \"service\" ? t(\"studio_api_keys_denied_hint\") : t(\"studio_api_keys_personal_denied_hint\")}\n onRetry={loadKeys}\n />\n )}\n {!loading && personalOff && <PersonalKeysOff/>}\n {!loading && !failure && !personalOff && activeKeys.length === 0 && inactiveKeys.length === 0 && (\n <div className=\"flex flex-col items-center justify-center h-full gap-3 text-center p-6\">\n <KeyRoundIcon size={iconSize.medium} className=\"text-surface-300 dark:text-surface-600\"/>\n <Typography variant=\"body2\" color=\"secondary\">\n {kind === \"service\" ? t(\"studio_api_keys_empty_title\") : t(\"studio_api_keys_personal_empty_title\")}\n </Typography>\n <Typography variant=\"caption\" color=\"disabled\">\n {kind === \"service\" ? t(\"studio_api_keys_empty_hint\") : t(\"studio_api_keys_personal_empty_hint\")}\n </Typography>\n </div>\n )}\n {!loading && activeKeys.map(key => (\n <KeyListItem key={key.id} apiKey={key} catalogue={catalogue} selected={selectedId === key.id} onClick={() => setSelectedId(key.id)}/>\n ))}\n {!loading && inactiveKeys.length > 0 && (\n <>\n <div className=\"px-2 pt-3 pb-1\">\n <Typography variant=\"caption\" color=\"disabled\" className=\"text-[10px] uppercase tracking-wider font-medium\">{t(\"studio_api_keys_inactive_heading\")}</Typography>\n </div>\n {inactiveKeys.map(key => (\n <KeyListItem key={key.id} apiKey={key} catalogue={catalogue} selected={selectedId === key.id} onClick={() => setSelectedId(key.id)}/>\n ))}\n </>\n )}\n </div>\n </div>\n\n {/* ── Detail Panel ── */}\n <div className=\"flex-1 flex flex-col min-w-0 h-full overflow-hidden\">\n {!selectedKey ? (\n <div className=\"flex items-center justify-center h-full\">\n {!personalOff && (\n <Typography variant=\"body2\" color=\"disabled\">{t(\"studio_api_keys_select_hint\")}</Typography>\n )}\n </div>\n ) : (\n <KeyDetail\n apiKey={selectedKey}\n catalogue={catalogue}\n revoking={revoking === selectedKey.id}\n onRevoke={() => setConfirmRevoke(selectedKey)}\n />\n )}\n </div>\n </div>\n\n {/* Revoke Confirmation Dialog */}\n <Dialog\n open={confirmRevoke !== null}\n onOpenChange={(open) => {\n if (!open && !revoking) setConfirmRevoke(null);\n }}\n >\n <DialogTitle hidden>{t(\"studio_api_keys_revoke_confirmation\")}</DialogTitle>\n <DialogContent>\n <Typography variant=\"subtitle1\" className=\"font-semibold mb-2\">\n {t(\"studio_api_keys_revoke_title\", { name: confirmRevoke?.name ?? \"\" })}\n </Typography>\n <Typography variant=\"body2\" color=\"secondary\">\n {t(\"studio_api_keys_revoke_body\")}\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button\n variant=\"text\"\n onClick={() => setConfirmRevoke(null)}\n disabled={revoking !== null}\n >\n {t(\"cancel\")}\n </Button>\n <Button\n color=\"error\"\n disabled={revoking !== null}\n startIcon={revoking !== null ? <CircularProgress size=\"smallest\"/> : <DeleteIcon size={iconSize.smallest}/>}\n onClick={async () => {\n if (!confirmRevoke) return;\n await handleRevoke(confirmRevoke.id);\n setConfirmRevoke(null);\n }}\n >\n {t(\"studio_api_keys_revoke\")}\n </Button>\n </DialogActions>\n </Dialog>\n\n {/* Create Dialog */}\n {showCreate && (\n <CreateApiKeyDialog\n kind={kind}\n scopeListing={scopeListing}\n onRetryScopes={onRetryScopes}\n onClose={() => setShowCreate(false)}\n onCreated={handleCreated}\n />\n )}\n\n {/* Secret Display Dialog */}\n {showSecret && (\n <SecretDisplayDialog\n keyWithSecret={showSecret}\n catalogue={catalogue}\n onClose={() => setShowSecret(null)}\n />\n )}\n </>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Personal keys switched off\n ═══════════════════════════════════════════════════════════════ */\n\n/**\n * Not an error and not a refusal of this person: the app has not enabled\n * personal keys. Says what they are and where the switch is.\n */\nfunction PersonalKeysOff() {\n const { t } = useTranslation();\n return (\n <div className=\"flex flex-col items-center justify-center h-full gap-3 text-center p-6\">\n <KeyRoundIcon size={iconSize.medium} className=\"text-surface-300 dark:text-surface-600\"/>\n <Typography variant=\"body2\" color=\"secondary\">{t(\"studio_api_keys_personal_off_title\")}</Typography>\n <Typography variant=\"caption\" color=\"disabled\" className=\"max-w-[34ch]\">\n {t(\"studio_api_keys_personal_off_body\")}\n </Typography>\n <Typography variant=\"mono\" component=\"div\" className=\"text-[11px] px-2 py-1 rounded-md bg-surface-field\">\n {\"auth: { personalKeys: true }\"}\n </Typography>\n </div>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n List item\n ═══════════════════════════════════════════════════════════════ */\n\n/**\n * Marks a service key that runs as the admin role.\n *\n * Not cosmetic: such a key reads, changes and deletes every row its scopes\n * reach through the admin policies, and without this it is indistinguishable\n * in the list from a narrow one.\n */\nfunction AdminChip() {\n const { t } = useTranslation();\n return (\n <Tooltip title={t(\"studio_api_keys_admin_chip_tooltip\")}>\n <Chip size=\"smallest\" colorScheme=\"yellow\" className=\"shrink-0\" icon={<ShieldIcon size={10}/>}>\n {ADMIN_ROLE}\n </Chip>\n </Tooltip>\n );\n}\n\nfunction KeyListItem({ apiKey, catalogue, selected, onClick }: {\n apiKey: ApiKeyMasked;\n catalogue: readonly ScopeSummary[];\n selected: boolean;\n onClick: () => void;\n}) {\n const { t } = useTranslation();\n const status = keyStatus(apiKey);\n return (\n <div\n onClick={onClick}\n className={cls(\n \"flex items-center gap-3 px-3 py-2.5 rounded-lg cursor-pointer transition-all\",\n selected\n ? \"bg-primary/10 dark:bg-primary/15 ring-1 ring-primary/30\"\n : \"hover:bg-surface-hover\"\n )}\n >\n <div className={cls(\"w-2 h-2 rounded-full shrink-0\",\n status.kind === \"active\" ? \"bg-emerald-400\" :\n status.kind === \"expired\" ? \"bg-amber-400\" : \"bg-red-400\"\n )}/>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\n <Typography variant=\"body2\" className=\"truncate font-medium text-[13px]\">{apiKey.name}</Typography>\n {runsAsAdmin(apiKey) && <AdminChip/>}\n </div>\n <Typography variant=\"caption\" color=\"secondary\" className=\"truncate text-[11px] font-mono\">{apiKey.key_prefix}•••</Typography>\n </div>\n <div className=\"shrink-0\">\n <Typography variant=\"caption\" color=\"disabled\" className=\"text-[10px]\">\n {scopeBrief(t, groupKeyScopes(apiKey.scopes, catalogue))}\n </Typography>\n </div>\n </div>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Detail\n ═══════════════════════════════════════════════════════════════ */\n\nfunction KeyDetail({ apiKey, catalogue, revoking, onRevoke }: {\n apiKey: ApiKeyMasked;\n catalogue: readonly ScopeSummary[];\n revoking: boolean;\n onRevoke: () => void;\n}) {\n const { t, i18n } = useTranslation();\n const language = i18n.language;\n const status = keyStatus(apiKey);\n const groups = groupKeyScopes(apiKey.scopes, catalogue);\n const service = apiKey.kind === \"service\";\n\n return (\n <>\n {/* Header */}\n <div className={cls(\"flex items-center justify-between px-5 py-3 border-b bg-surface-card min-h-[56px]\", defaultBorderMixin)}>\n <div className=\"flex items-center gap-3 min-w-0\">\n <KeyRoundIcon size={iconSize.small} className=\"text-primary shrink-0\"/>\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <Typography variant=\"subtitle1\" className=\"font-semibold truncate\">{apiKey.name}</Typography>\n {runsAsAdmin(apiKey) && <AdminChip/>}\n </div>\n <Typography variant=\"caption\" color=\"secondary\" className=\"font-mono text-[11px]\">{apiKey.key_prefix}•••</Typography>\n </div>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {!apiKey.revoked_at && (\n <Button\n size=\"small\"\n color=\"error\"\n variant=\"outlined\"\n onClick={onRevoke}\n disabled={revoking}\n startIcon={revoking ? <CircularProgress size=\"smallest\"/> : <DeleteIcon size={iconSize.smallest}/>}\n >\n {t(\"studio_api_keys_revoke\")}\n </Button>\n )}\n </div>\n </div>\n\n {/* Stats */}\n <div className=\"px-5 py-4 bg-surface-sheet\">\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3\">\n <StatCard label={t(\"studio_api_keys_stat_status\")} value={statusLabel(t, status.kind)} className={status.color}/>\n <StatCard label={t(\"created\")} value={formatRelative(apiKey.created_at, language)}/>\n <StatCard label={t(\"studio_api_keys_stat_last_used\")} value={formatRelative(apiKey.last_used_at, language)}/>\n <StatCard label={t(\"studio_api_keys_stat_expires\")} value={apiKey.expires_at ? formatRelative(apiKey.expires_at, language) : t(\"studio_api_keys_never\")}/>\n </div>\n <div className=\"grid grid-cols-2 md:grid-cols-3 gap-3 mt-3\">\n <StatCard\n label={t(\"studio_api_keys_stat_kind\")}\n value={service ? t(\"studio_api_keys_kind_service\") : t(\"studio_api_keys_kind_personal\")}\n />\n <StatCard\n label={t(\"studio_api_keys_stat_rate_limit\")}\n value={apiKey.rate_limit\n ? t(\"studio_api_keys_rate_limit_value\", { limit: apiKey.rate_limit })\n : t(\"studio_api_keys_rate_limit_default\")}\n />\n {service\n ? <StatCard label={t(\"studio_api_keys_stat_created_by\")} value={apiKey.created_by} mono/>\n : <StatCard label={t(\"studio_api_keys_stat_owner\")} value={apiKey.owner_uid ?? \"—\"} mono/>}\n </div>\n <Typography variant=\"caption\" color=\"secondary\" className=\"block mt-2 text-[11px] leading-snug\">\n {t(\"studio_api_keys_rate_limit_scope\")}\n </Typography>\n </div>\n\n {/* Scopes */}\n <div className={cls(\"flex items-center gap-2 px-5 py-2 border-y bg-surface-card\", defaultBorderMixin)}>\n <Typography variant=\"subtitle2\" className=\"font-semibold text-[13px]\">{t(\"studio_api_keys_scopes\")}</Typography>\n <Chip size=\"smallest\" className=\"bg-surface-raised text-surface-600 dark:text-surface-300\">\n {apiKey.scopes.length}\n </Chip>\n </div>\n <div className=\"flex-1 overflow-y-auto px-5 py-3 flex flex-col gap-5\">\n <RolesBlock apiKey={apiKey}/>\n {groups.length === 0\n ? <Typography variant=\"body2\" color=\"disabled\">{t(\"studio_api_keys_no_scopes\")}</Typography>\n : groups.map(group => (\n <div key={group.plane}>\n <BlockHeading\n icon={<PlaneIcon plane={group.plane} className=\"text-surface-500 dark:text-surface-400\"/>}\n label={planeLabel(t, group.plane)}\n hint={planeHint(t, group.plane)}\n />\n <div className=\"space-y-2\">\n {group.scopes.map(held => (\n <div key={held.scope} className={cls(\"flex items-center gap-3 px-3 py-2 rounded-lg border\", defaultBorderMixin)}>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-baseline gap-2 min-w-0\">\n <Typography variant=\"body2\" className=\"text-[13px] font-medium truncate\">\n {held.label}\n </Typography>\n <Typography variant=\"caption\" color=\"disabled\" className=\"font-mono text-[11px] shrink-0\">\n {held.scope}\n </Typography>\n </div>\n {held.description && (\n <Typography variant=\"caption\" color=\"secondary\" className=\"block text-[11px] leading-snug\">\n {held.description}\n </Typography>\n )}\n </div>\n {held.targetKind && (\n <div className=\"flex flex-wrap justify-end gap-1 shrink-0 max-w-[50%]\">\n {held.targets === \"all\"\n ? (\n <Chip size=\"smallest\" className=\"bg-surface-raised text-surface-600 dark:text-surface-300\">\n {everyTargetLabel(t, held.targetKind)}\n </Chip>\n )\n : held.targets.map(target => (\n <Chip key={target} size=\"smallest\" className=\"font-mono bg-surface-raised text-surface-700 dark:text-surface-200\">\n {targetLabel(t, held.targetKind, target)}\n </Chip>\n ))}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </>\n );\n}\n\nfunction BlockHeading({ icon, label, hint }: { icon: React.ReactNode; label: string; hint: string }) {\n return (\n <div className=\"flex items-center gap-2 mb-2 min-w-0\">\n {icon}\n <Typography variant=\"body2\" className=\"text-[13px] font-medium shrink-0\">{label}</Typography>\n <Typography variant=\"caption\" color=\"secondary\" className=\"text-[11px] truncate\">{hint}</Typography>\n </div>\n );\n}\n\n/**\n * Who the key runs as — which rows it reads. Scopes, below it, are which\n * endpoints it may call; the two are separate and both are shown.\n */\nfunction RolesBlock({ apiKey }: { apiKey: ApiKeyMasked }) {\n const { t } = useTranslation();\n const shield = <ShieldIcon size={iconSize.smallest} className=\"text-surface-500 dark:text-surface-400\"/>;\n\n if (apiKey.kind === \"personal\") {\n return (\n <div>\n <BlockHeading icon={shield} label={t(\"studio_api_keys_roles\")} hint={t(\"studio_api_keys_roles_rows_hint\")}/>\n <Typography variant=\"caption\" color=\"secondary\" className=\"block text-[12px] leading-snug\">\n {t(\"studio_api_keys_personal_roles\")}\n </Typography>\n </div>\n );\n }\n\n return (\n <div>\n <BlockHeading icon={shield} label={t(\"studio_api_keys_roles\")} hint={t(\"studio_api_keys_roles_rows_hint\")}/>\n <div className=\"flex flex-wrap gap-1.5\">\n <Chip size=\"small\" className=\"font-mono bg-surface-raised text-surface-600 dark:text-surface-300\">service</Chip>\n {apiKey.roles.map(role => (\n <Chip\n key={role}\n size=\"small\"\n colorScheme={role === ADMIN_ROLE ? \"yellow\" : undefined}\n className={cls(\"font-mono\", role !== ADMIN_ROLE && \"bg-surface-raised text-surface-700 dark:text-surface-200\")}\n >\n {role}\n </Chip>\n ))}\n </div>\n {runsAsAdmin(apiKey)\n ? (\n <Alert color=\"warning\" size=\"small\" outerClassName=\"mt-2\">\n {t(\"studio_api_keys_admin_bypasses_rls\")}\n </Alert>\n )\n : (\n <Typography variant=\"caption\" color=\"secondary\" className=\"block mt-1.5 text-[11px] leading-snug\">\n {apiKey.roles.length === 0 ? t(\"studio_api_keys_roles_service_only\") : t(\"studio_api_keys_roles_service_plus\")}\n </Typography>\n )}\n </div>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Stat card\n ═══════════════════════════════════════════════════════════════ */\n\nfunction StatCard({ label, value, mono, className }: { label: string; value: string; mono?: boolean; className?: string }) {\n return (\n <div className={cls(\"px-3 py-2 rounded-lg border bg-surface-card\", defaultBorderMixin)}>\n <Typography variant=\"caption\" color=\"secondary\" className=\"text-[10px] uppercase tracking-wider font-medium\">{label}</Typography>\n <Typography variant=\"body2\" className={cls(\n \"mt-0.5 font-semibold text-[13px] truncate\",\n mono && \"font-mono\",\n className\n )}>{value}</Typography>\n </div>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Secret Display Dialog — shown exactly once after creation\n ═══════════════════════════════════════════════════════════════ */\n\nfunction SecretDisplayDialog({ keyWithSecret, catalogue, onClose }: {\n keyWithSecret: ApiKeyWithSecret;\n catalogue: readonly ScopeSummary[];\n onClose: () => void;\n}) {\n const { t } = useTranslation();\n const snackbar = useSnackbarController();\n const [copied, setCopied] = useState(false);\n const granted = groupKeyScopes(keyWithSecret.scopes, catalogue).flatMap(group => group.scopes);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(keyWithSecret.key);\n setCopied(true);\n snackbar.open({ type: \"success\", message: t(\"studio_api_keys_copied\") });\n setTimeout(() => setCopied(false), 2000);\n } catch {\n snackbar.open({ type: \"error\", message: t(\"studio_api_keys_copy_failed\") });\n }\n };\n\n return (\n <Dialog open onOpenChange={(open) => { if (!open) onClose(); }} maxWidth=\"md\">\n <DialogTitle>\n <div className=\"flex items-center gap-2\">\n <CheckCircleIcon size={iconSize.small} className=\"text-emerald-500\"/>\n {t(\"studio_api_keys_created_title\")}\n </div>\n </DialogTitle>\n <DialogContent>\n <div className=\"p-3 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800/50 mb-4\">\n <div className=\"flex items-center gap-2 mb-1\">\n <AlertCircleIcon size={iconSize.smallest} className=\"text-amber-600 dark:text-amber-400\"/>\n <Typography variant=\"caption\" className=\"font-semibold text-amber-700 dark:text-amber-400\">\n {t(\"studio_api_keys_copy_now\")}\n </Typography>\n </div>\n <Typography variant=\"caption\" className=\"text-amber-600 dark:text-amber-300\">\n {t(\"studio_api_keys_copy_now_hint\")}\n </Typography>\n </div>\n\n <div className={cls(\"flex items-center gap-2 p-3 rounded-lg border bg-surface-sheet\", defaultBorderMixin)}>\n <code className=\"flex-1 text-[12px] font-mono break-all text-surface-700 dark:text-surface-300 select-all\">\n {keyWithSecret.key}\n </code>\n <Tooltip title={copied ? t(\"copied\") : t(\"copy\")}>\n <IconButton aria-label={copied ? t(\"copied\") : t(\"copy\")} size=\"small\" onClick={handleCopy}>\n {copied\n ? <CheckCircleIcon size={iconSize.smallest} className=\"text-emerald-500\"/>\n : <CopyIcon size={iconSize.smallest}/>\n }\n </IconButton>\n </Tooltip>\n </div>\n\n <div className=\"mt-4 space-y-1\">\n <Typography variant=\"caption\" color=\"secondary\" className=\"block\">\n <strong>{t(\"studio_api_keys_name_label\")}</strong> {keyWithSecret.name}\n </Typography>\n <Typography variant=\"caption\" color=\"secondary\" className=\"block\">\n <strong>{t(\"studio_api_keys_access_label\")}</strong>{\" \"}\n {granted.length > 0 ? granted.map(held => heldScopeLine(t, held)).join(\"; \") : \"—\"}\n </Typography>\n {runsAsAdmin(keyWithSecret) && (\n <Typography variant=\"caption\" className=\"flex items-center gap-1.5 text-amber-700 dark:text-amber-300\">\n <ShieldIcon size={iconSize.smallest} className=\"shrink-0\"/>\n <span><strong>{t(\"studio_api_keys_admin_granted\")}</strong> — {t(\"studio_api_keys_admin_granted_hint\")}</span>\n </Typography>\n )}\n </div>\n </DialogContent>\n <DialogActions>\n <Button color=\"primary\" onClick={onClose}>{t(\"studio_api_keys_done\")}</Button>\n </DialogActions>\n </Dialog>\n );\n}\n"],"mappings":"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"}