@veltrixsecops/app-sdk 3.2.0 → 3.5.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 (77) hide show
  1. package/README.md +1 -1
  2. package/dist/byol/index.cjs +3802 -0
  3. package/dist/byol/index.cjs.map +1 -0
  4. package/dist/byol/index.d.cts +578 -0
  5. package/dist/byol/index.d.ts +578 -0
  6. package/dist/byol/index.js +2587 -0
  7. package/dist/byol/index.js.map +1 -0
  8. package/dist/chunk-3WK4EVQ3.js +842 -0
  9. package/dist/chunk-3WK4EVQ3.js.map +1 -0
  10. package/dist/{chunk-EOOEHZGC.js → chunk-HIL6RIDG.js} +107 -3
  11. package/dist/chunk-HIL6RIDG.js.map +1 -0
  12. package/dist/{chunk-VWFTOFTI.js → chunk-Y6XBNZGR.js} +8 -2
  13. package/dist/chunk-Y6XBNZGR.js.map +1 -0
  14. package/dist/client/index.cjs +112 -2
  15. package/dist/client/index.cjs.map +1 -1
  16. package/dist/client/index.d.cts +118 -6
  17. package/dist/client/index.d.ts +118 -6
  18. package/dist/client/index.js +13 -1
  19. package/dist/connections/index.cjs +1787 -0
  20. package/dist/connections/index.cjs.map +1 -0
  21. package/dist/connections/index.d.cts +78 -0
  22. package/dist/connections/index.d.ts +78 -0
  23. package/dist/connections/index.js +754 -0
  24. package/dist/connections/index.js.map +1 -0
  25. package/dist/hooks/index.cjs.map +1 -1
  26. package/dist/hooks/index.d.cts +2 -2
  27. package/dist/hooks/index.d.ts +2 -2
  28. package/dist/hooks/index.js +1 -1
  29. package/dist/index.cjs +7 -0
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +3 -3
  32. package/dist/index.d.ts +3 -3
  33. package/dist/index.js +3 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/opentofu/index.cjs +138 -0
  36. package/dist/opentofu/index.cjs.map +1 -0
  37. package/dist/opentofu/index.d.cts +131 -0
  38. package/dist/opentofu/index.d.ts +131 -0
  39. package/dist/opentofu/index.js +109 -0
  40. package/dist/opentofu/index.js.map +1 -0
  41. package/dist/pipeline/index.cjs +7 -0
  42. package/dist/pipeline/index.cjs.map +1 -1
  43. package/dist/pipeline/index.d.cts +9 -2
  44. package/dist/pipeline/index.d.ts +9 -2
  45. package/dist/pipeline/index.js +3 -1
  46. package/dist/pipeline-beeT8dje.d.cts +408 -0
  47. package/dist/pipeline-beeT8dje.d.ts +408 -0
  48. package/dist/ui/index.cjs +136 -0
  49. package/dist/ui/index.cjs.map +1 -1
  50. package/dist/ui/index.d.cts +109 -1
  51. package/dist/ui/index.d.ts +109 -1
  52. package/dist/ui/index.js +35 -677
  53. package/dist/ui/index.js.map +1 -1
  54. package/dist/{use-app-context-OQlcmq7t.d.cts → use-app-context-Byv_fam0.d.cts} +206 -4
  55. package/dist/{use-app-context-OQlcmq7t.d.ts → use-app-context-Byv_fam0.d.ts} +206 -4
  56. package/opentofu/README.md +114 -0
  57. package/opentofu/modules/aws/main.tf +1008 -0
  58. package/opentofu/modules/aws/outputs.tf +90 -0
  59. package/opentofu/modules/aws/variables.tf +437 -0
  60. package/opentofu/modules/aws/versions.tf +23 -0
  61. package/opentofu/modules/azure/main.tf +920 -0
  62. package/opentofu/modules/azure/outputs.tf +72 -0
  63. package/opentofu/modules/azure/variables.tf +498 -0
  64. package/opentofu/modules/azure/versions.tf +27 -0
  65. package/opentofu/modules/gcp/main.tf +645 -0
  66. package/opentofu/modules/gcp/outputs.tf +73 -0
  67. package/opentofu/modules/gcp/variables.tf +428 -0
  68. package/opentofu/modules/gcp/versions.tf +27 -0
  69. package/opentofu/modules/hetzner/main.tf +432 -0
  70. package/opentofu/modules/hetzner/outputs.tf +72 -0
  71. package/opentofu/modules/hetzner/variables.tf +423 -0
  72. package/opentofu/modules/hetzner/versions.tf +26 -0
  73. package/package.json +33 -1
  74. package/dist/chunk-EOOEHZGC.js.map +0 -1
  75. package/dist/chunk-VWFTOFTI.js.map +0 -1
  76. package/dist/pipeline-A-gSsPRR.d.cts +0 -189
  77. package/dist/pipeline-A-gSsPRR.d.ts +0 -189
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/inventory.ts","../../src/client/connectivity.ts","../../src/client/environments.ts","../../src/client/credentials.ts","../../src/client/onboarding.ts","../../src/client/index.ts","../../src/byol/index.tsx","../../src/byol/ByolInfrastructureManager.tsx","../../src/ui/index.tsx","../../src/byol/types.ts","../../src/byol/status.ts","../../src/byol/detail/shared.tsx","../../src/byol/api.ts","../../src/byol/ByolInfrastructureDetail.tsx","../../src/byol/placement.ts","../../src/byol/topology.ts","../../src/byol/detail/OverviewTab.tsx","../../src/byol/detail/ResourcesTab.tsx","../../src/byol/detail/ActivityTab.tsx","../../src/byol/detail/AccessTab.tsx","../../src/byol/detail/ConfigurationTab.tsx","../../src/byol/detail/SettingsTab.tsx","../../src/byol/detail/ByolPlanModal.tsx","../../src/byol/diffPlan.ts","../../src/byol/detail/planLines.tsx","../../src/byol/detail/DestroyPlanModal.tsx","../../src/byol/detail/icons.tsx","../../src/byol/ClusterPlacementField.tsx","../../src/byol/tags.ts"],"sourcesContent":["// ========================================================================\n// Inventory — the deployment targets an app can deploy configuration to.\n//\n// \"Inventory\" is the app-facing name for the platform's *components*: the\n// servers (hostname/port), domains, and IP/CIDR ranges a customer has\n// registered as deploy targets. These helpers are a typed, convenient\n// surface over the platform's components API (/api/components), enriched\n// with `domains` and `ipRanges`.\n//\n// Framework-free (no React) — safe to import from any client code. Every\n// call goes through the same `authFetch` the '/client' subpath exports, so\n// requests carry the platform's Authorization header. Non-2xx responses are\n// surfaced as thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type { InventoryItem, InventoryItemInput } from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's components (inventory) API. */\nconst INVENTORY_API = '/api/components'\n\n/**\n * Loosely-typed shape of a raw component as returned by the platform, before\n * it is normalized down to the {@link InventoryItem} surface.\n */\ninterface RawInventoryItem {\n id: string\n hostname?: string\n port?: string\n webPort?: string | null\n sshUser?: string | null\n splunkHome?: string | null\n type?: string[]\n domains?: string[]\n ipRanges?: string[]\n tags?: Array<{ id: string; name: string }>\n connectivityProviderId?: string | null\n credentialId?: string | null\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function inventoryError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform component into the typed InventoryItem surface. */\nfunction toInventoryItem(raw: RawInventoryItem): InventoryItem {\n return {\n id: String(raw.id),\n hostname: raw.hostname ?? '',\n port: raw.port ?? undefined,\n webPort: raw.webPort ?? null,\n sshUser: raw.sshUser ?? null,\n splunkHome: raw.splunkHome ?? null,\n type: Array.isArray(raw.type) ? raw.type : undefined,\n domains: Array.isArray(raw.domains) ? raw.domains : [],\n ipRanges: Array.isArray(raw.ipRanges) ? raw.ipRanges : [],\n tags: Array.isArray(raw.tags)\n ? raw.tags.map((tag) => ({ id: String(tag.id), name: String(tag.name) }))\n : [],\n connectivityProviderId: raw.connectivityProviderId ?? null,\n credentialId: raw.credentialId ?? null,\n }\n}\n\n/**\n * A platform Tool. Each installed app is upserted as a Tool keyed by its\n * manifest `name`, and inventory items (components) belong to a tool.\n */\nexport interface Tool {\n id: string\n name: string\n vendor?: string\n}\n\n/**\n * Resolve the platform Tool for an app by its manifest name (the platform\n * upserts `Tool.name === app name`). The tool id is required by the platform\n * when creating an inventory item, so call this once and pass the id as\n * `toolId` to {@link addInventoryItem}. Returns null when no tool matches.\n *\n * GET /api/tools (paginated — `{ data, pagination }` — or a bare array; both are\n * handled). We MUST filter server-side by name: the list is paginated (default 20,\n * ordered by createdAt) so once a tenant has enough apps installed, a bare\n * client-side find over just the first page silently misses a real tool whose row\n * fell to a later page — surfacing a false \"no <app> tool found, install the app\n * first\" error for an app that is in fact installed. `search` is a case-insensitive\n * contains match, so we still exact-match `tool.name === name` on the result.\n */\nexport async function resolveTool(name: string): Promise<Tool | null> {\n const res = await authFetch(`/api/tools?search=${encodeURIComponent(name)}&limit=100`)\n if (!res.ok) throw await inventoryError(res)\n const body = (await res.json()) as unknown\n const tools: Tool[] = Array.isArray(body)\n ? (body as Tool[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: Tool[] }).data)\n : []\n return tools.find((tool) => tool.name === name) ?? null\n}\n\n/** List the customer's inventory (deployment targets). GET /api/components */\nexport async function listInventory(): Promise<InventoryItem[]> {\n const res = await authFetch(INVENTORY_API)\n if (!res.ok) throw await inventoryError(res)\n const data = (await res.json()) as RawInventoryItem[]\n return Array.isArray(data) ? data.map(toInventoryItem) : []\n}\n\n/** Add a new inventory item (deployment target). POST /api/components */\nexport async function addInventoryItem(input: InventoryItemInput): Promise<InventoryItem> {\n const res = await authFetch(INVENTORY_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Update an existing inventory item. PUT /api/components/:id */\nexport async function updateInventoryItem(\n id: string,\n input: InventoryItemInput,\n): Promise<InventoryItem> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Remove an inventory item. DELETE /api/components/:id */\nexport async function removeInventoryItem(id: string): Promise<void> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await inventoryError(res)\n}\n","// ========================================================================\n// Connectivity providers — the customer's ZTNA providers (Tailscale,\n// WireGuard, ZeroTier, …), platform-managed under Settings → Connectivity.\n//\n// A thin reader over the platform's connectivity-providers API\n// (/api/connectivity-providers), used to populate the ZTNA link picker when\n// creating or editing an Access Server (a component). Framework-free — every\n// call goes through the same `authFetch` the '/client' subpath exports.\n// ========================================================================\n\nimport type { ConnectivityProviderRef } from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's connectivity-providers API. */\nconst CONNECTIVITY_PROVIDERS_API = '/api/connectivity-providers'\n\ninterface RawConnectivityProvider {\n id: string\n name?: string\n providerType?: string\n status?: string\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function providerError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/**\n * List the customer's ZTNA connectivity providers, used to populate the Access\n * Server link picker. GET /api/connectivity-providers (the endpoint may return\n * a bare array or a paginated `{ data, ... }` shape — both are handled).\n */\nexport async function listConnectivityProviders(): Promise<ConnectivityProviderRef[]> {\n const res = await authFetch(CONNECTIVITY_PROVIDERS_API)\n if (!res.ok) throw await providerError(res)\n const body = (await res.json()) as unknown\n const providers: RawConnectivityProvider[] = Array.isArray(body)\n ? (body as RawConnectivityProvider[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: RawConnectivityProvider[] }).data)\n : []\n return providers.map((provider) => ({\n id: String(provider.id),\n name: provider.name ?? '',\n providerType: provider.providerType ?? undefined,\n status: provider.status ?? undefined,\n }))\n}\n","// ========================================================================\n// Environments — the deployment scopes that determine where a configuration is\n// pushed. Environments are the customer's platform tags (dev/staging/prod, …);\n// a Connection (credential) or Access Server (component) is tied to one by\n// carrying the environment id in its `tagIds`.\n//\n// A thin reader over the platform's environments API (/api/environments), used\n// to populate the Environment picker on the Connections and Access Servers\n// pages. Framework-free — every call goes through the same `authFetch` the\n// '/client' subpath exports.\n// ========================================================================\n\nimport type { EnvironmentRef } from '../types/pipeline'\nimport { authFetch } from './index'\n\n/** Base route for the platform's environments API. */\nconst ENVIRONMENTS_API = '/api/environments'\n\ninterface RawEnvironment {\n id: string\n name?: string\n environmentTypes?: string[]\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function environmentError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/**\n * List the customer's environments (deployment scopes). GET /api/environments\n * (the endpoint may return a bare array or a paginated `{ data, ... }` shape —\n * both are handled). Use the returned id as a `tagIds` entry to tie a Connection\n * or Access Server to that environment.\n */\nexport async function listEnvironments(): Promise<EnvironmentRef[]> {\n const res = await authFetch(ENVIRONMENTS_API)\n if (!res.ok) throw await environmentError(res)\n const body = (await res.json()) as unknown\n const rows: RawEnvironment[] = Array.isArray(body)\n ? (body as RawEnvironment[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: RawEnvironment[] }).data)\n : []\n return rows.map((env) => ({\n id: String(env.id),\n name: env.name ?? '',\n environmentTypes: Array.isArray(env.environmentTypes) ? env.environmentTypes : [],\n }))\n}\n","// ========================================================================\n// Credentials — how an app authenticates to a server (\"connection\").\n//\n// A \"connection\" pairs a server (a platform *component* — see inventory.ts)\n// with a *credential*: the account and write-only secret used to reach that\n// server. These helpers are a typed surface over the platform's credentials\n// API (POST /api/credentials, GET /api/tools/:toolId/credentials, PUT/DELETE\n// /api/credentials/:id).\n//\n// Framework-free (no React). Every call goes through the same `authFetch` the\n// '/client' subpath exports, so requests carry the platform's Authorization\n// header. Non-2xx responses are surfaced as thrown Errors carrying the\n// platform's error text.\n//\n// SECURITY: `listCredentials` returns a REDACTED {@link CredentialSummary} —\n// secret material (password / apiToken / certificate) is dropped before it\n// reaches app code, so secrets are never held in memory or logged. Only whether\n// a secret exists is surfaced (`hasSecret`). Secrets are write-only: they can be\n// set via create/update, never read back.\n// ========================================================================\n\nimport type { CredentialInput, CredentialSummary } from '../types/platform'\nimport type { TestConnectionResult } from '../types/pipeline'\nimport { authFetch } from './index'\n\n/** Base route for the platform's credentials API. */\nconst CREDENTIALS_API = '/api/credentials'\n\n/**\n * Loosely-typed shape of a raw credential as returned by the platform, before\n * it is redacted down to the {@link CredentialSummary} surface. The secret\n * fields (`password` / `apiToken` / `certificate`) are read here only to derive\n * `hasSecret` — they are never carried into app-visible data.\n */\ninterface RawCredential {\n id: string\n name?: string\n username?: string\n type?: string | null\n endpoint?: string | null\n environmentType?: string | null\n toolId?: string\n // The platform redacts secrets from credential responses and surfaces only\n // whether each is set via these flags. Older platforms may still send the\n // secret fields instead — both shapes are handled below.\n hasPassword?: boolean\n hasApiToken?: boolean\n hasCertificate?: boolean\n password?: string | null\n apiToken?: string | null\n certificate?: string | null\n tags?: Array<{ id: string; name: string }>\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function credentialError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/**\n * Redact a raw platform credential down to the app-visible summary, dropping\n * every secret field and surfacing only whether a secret is stored.\n */\nfunction toCredentialSummary(raw: RawCredential): CredentialSummary {\n // Prefer the redacted has* flags; fall back to the presence of the secret\n // fields themselves for older platforms that still return them.\n const hasSecret = Boolean(\n raw.hasApiToken ||\n raw.hasPassword ||\n (raw.apiToken && raw.apiToken.length > 0) ||\n (raw.password && raw.password.length > 0),\n )\n return {\n id: String(raw.id),\n name: raw.name ?? '',\n username: raw.username ?? '',\n type: raw.type ?? null,\n endpoint: raw.endpoint ?? null,\n environmentType: raw.environmentType ?? null,\n toolId: raw.toolId ?? '',\n hasSecret,\n tags: Array.isArray(raw.tags)\n ? raw.tags.map((t) => ({ id: String(t.id), name: String(t.name) }))\n : [],\n }\n}\n\n/**\n * List the redacted credentials registered for a tool. GET\n * /api/tools/:toolId/credentials. Secrets are stripped before return — see the\n * module's SECURITY note. Returns an empty array when the tool has none.\n */\nexport async function listCredentials(toolId: string): Promise<CredentialSummary[]> {\n const res = await authFetch(`/api/tools/${encodeURIComponent(toolId)}/credentials`)\n if (!res.ok) throw await credentialError(res)\n const data = (await res.json()) as unknown\n const rows: RawCredential[] = Array.isArray(data)\n ? (data as RawCredential[])\n : Array.isArray((data as { data?: unknown })?.data)\n ? ((data as { data: RawCredential[] }).data)\n : []\n return rows.map(toCredentialSummary)\n}\n\n/**\n * Create a credential. POST /api/credentials. The platform requires `name`,\n * `username`, `password`, `toolId`, and `tagIds` — this helper defaults\n * `tagIds` to `[]` and `password` to `''` (valid for token-only auth, where the\n * secret travels in `apiToken`). Returns the new credential's id.\n */\nexport async function createCredential(input: CredentialInput): Promise<{ id: string }> {\n const res = await authFetch(CREDENTIALS_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n name: input.name,\n username: input.username,\n password: input.password ?? '',\n apiToken: input.apiToken,\n type: input.type,\n endpoint: input.endpoint,\n environmentType: input.environmentType ?? null,\n toolId: input.toolId,\n tagIds: input.tagIds ?? [],\n }),\n })\n if (!res.ok) throw await credentialError(res)\n const body = (await res.json()) as { id?: string }\n return { id: String(body.id) }\n}\n\n/**\n * Update a credential. PUT /api/credentials/:id. Only the fields you pass are\n * changed; omit `password`/`apiToken` to leave the stored secret untouched.\n */\nexport async function updateCredential(\n id: string,\n input: Partial<CredentialInput>,\n): Promise<{ id: string }> {\n const body: Record<string, unknown> = {}\n if (input.name !== undefined) body.name = input.name\n if (input.username !== undefined) body.username = input.username\n if (input.password !== undefined) body.password = input.password\n if (input.apiToken !== undefined) body.apiToken = input.apiToken\n if (input.type !== undefined) body.type = input.type\n if (input.endpoint !== undefined) body.endpoint = input.endpoint\n if (input.environmentType !== undefined) body.environmentType = input.environmentType\n if (input.tagIds !== undefined) body.tagIds = input.tagIds\n const res = await authFetch(`${CREDENTIALS_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!res.ok) throw await credentialError(res)\n const result = (await res.json().catch(() => ({}))) as { id?: string }\n return { id: result.id ? String(result.id) : id }\n}\n\n/** Remove a credential. DELETE /api/credentials/:id. */\nexport async function removeCredential(id: string): Promise<void> {\n const res = await authFetch(`${CREDENTIALS_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await credentialError(res)\n}\n\nexport type { TestConnectionResult }\n\n/**\n * Test a Connection's endpoint + credential. The platform decrypts the secret,\n * runs the owning app's connectivity-test handler in-process (the secret is\n * never returned), and reports whether the endpoint + credentials actually work.\n * A failed test resolves normally with `{ ok: false, message }` — it does not\n * throw. Only transport/auth errors (401/404) surface as `{ ok: false }` too.\n *\n * @param appId the app that owns the connection, e.g. `splunk-cloud`\n * @param credentialId the connection (credential) id\n * @param opts.endpoint optional endpoint to test against instead of the one stored\n * on the credential — e.g. an Access Server's reachable address\n * (`<host>:<port>`). The host is scoped to the caller's tenant.\n */\nexport async function testConnection(\n appId: string,\n credentialId: string,\n opts: { endpoint?: string } = {},\n): Promise<TestConnectionResult> {\n const endpoint = typeof opts.endpoint === 'string' ? opts.endpoint.trim() : ''\n const res = await authFetch(\n `/api/apps/${encodeURIComponent(appId)}/connections/${encodeURIComponent(credentialId)}/test`,\n endpoint\n ? { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ endpoint }) }\n : { method: 'POST' },\n )\n if (!res.ok) {\n const err = await credentialError(res)\n return { ok: false, message: err.message }\n }\n return (await res.json()) as TestConnectionResult\n}\n\n/** Result of running an app operation. Mirrors the server operation handler's return. */\nexport interface OperationResult {\n ok: boolean\n message: string\n details?: string[]\n /** Optional structured payload (e.g. an export download URL, a job id). */\n data?: Record<string, unknown>\n}\n\n/**\n * Run an app operation — a one-off action (restart, export, retry, …), NOT a\n * configuration deploy. The platform decrypts the chosen connection's secret and\n * runs the app's operation handler in-process (the secret is never returned). A\n * failed operation resolves normally with `{ ok: false, message }` rather than\n * throwing.\n *\n * @param appId the app that owns the operation, e.g. `splunk-cloud`\n * @param operationId the operation id declared in the app manifest\n * @param opts the connection (credentialId) to authenticate with, + params\n */\nexport async function runOperation(\n appId: string,\n operationId: string,\n opts: { credentialId?: string; params?: Record<string, unknown> } = {},\n): Promise<OperationResult> {\n const res = await authFetch(\n `/api/apps/${encodeURIComponent(appId)}/operations/${encodeURIComponent(operationId)}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentialId: opts.credentialId, params: opts.params ?? {} }),\n },\n )\n if (!res.ok) {\n const err = await credentialError(res)\n return { ok: false, message: err.message }\n }\n return (await res.json()) as OperationResult\n}\n","// ========================================================================\n// Connection onboarding — one-click \"Connect …\" flow (consent + broker).\n//\n// Typed surface over the platform's generic onboarding routes\n// (POST /api/apps/:appId/connections/onboard/start, …/onboard/status,\n// …/onboard/revoke). Framework-free; every call carries the platform's\n// Authorization header via the shared `authFetch`.\n//\n// The flow: call `startOnboarding` → open the returned `authorizeUrl` (the\n// admin consents on Microsoft's hosted page) → the platform's static callback\n// persists the connection and redirects back to the Connections page with an\n// `?onboarded=ok` flag. No secret is ever handled by app code.\n// ========================================================================\n\nimport { authFetch } from './index'\n\nasync function onboardingError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n /* not JSON */\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** The client-safe onboarding descriptor an app advertises in /apps/enabled. */\nexport interface AppOnboardingDescriptor {\n provider: string\n label: string\n brokered?: boolean\n requiredSettings?: string[]\n}\n\n/**\n * Fetch an app's connection-onboarding descriptor from GET /api/apps/enabled,\n * so the Connections UI can offer an \"Integrate via OAuth\" option without the\n * app page having to pass it in. Returns null when the app declares no\n * onboarding (its connections stay credential-only).\n */\nexport async function fetchAppOnboarding(appId: string): Promise<AppOnboardingDescriptor | null> {\n try {\n const res = await authFetch('/api/apps/enabled', { method: 'GET' })\n if (!res.ok) return null\n const data = (await res.json()) as unknown\n const list = Array.isArray(data) ? data : ((data as { data?: unknown[] })?.data ?? [])\n const app = (list as Array<{ appId?: string; id?: string; connection?: { onboarding?: AppOnboardingDescriptor } }>).find(\n (a) => a.appId === appId || a.id === appId,\n )\n return app?.connection?.onboarding ?? null\n } catch {\n return null\n }\n}\n\nexport interface StartOnboardingInput {\n /** The deployment scope (environment) the new connection belongs to. */\n environmentId: string\n /** Display name for the new connection. */\n connectionName: string\n /**\n * Settings the admin supplies BEFORE consent (e.g. Sentinel's\n * subscription_id / resource_group / workspace_name, or a cloud override).\n */\n settings?: Record<string, unknown>\n}\n\nexport interface StartOnboardingResult {\n /** Open this in the browser — the provider's hosted consent page. */\n authorizeUrl: string\n provider: string\n}\n\n/** Begin onboarding a connection. POST /api/apps/:appId/connections/onboard/start. */\nexport async function startOnboarding(\n appId: string,\n input: StartOnboardingInput,\n): Promise<StartOnboardingResult> {\n const res = await authFetch(\n `/api/apps/${encodeURIComponent(appId)}/connections/onboard/start`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n environmentId: input.environmentId,\n connectionName: input.connectionName,\n settings: input.settings ?? {},\n }),\n },\n )\n if (!res.ok) throw await onboardingError(res)\n return (await res.json()) as StartOnboardingResult\n}\n\nexport interface OnboardingStatus {\n provider: string\n brokered: boolean\n tenantId: string | null\n cloud: string\n manualSteps: Array<{\n type: string\n title: string\n description: string\n deepLink?: string\n cliCommand?: string\n verifiable: boolean\n }>\n verify?: { effective: boolean; message: string }\n}\n\n/**\n * Read onboarding status for a connection, optionally running the verify probe\n * for pending manual steps (e.g. the Sentinel role assignment).\n * GET /api/apps/:appId/connections/:credentialId/onboard/status.\n */\nexport async function getOnboardingStatus(\n appId: string,\n credentialId: string,\n opts: { verify?: boolean } = {},\n): Promise<OnboardingStatus> {\n const qs = opts.verify ? '?verify=1' : ''\n const res = await authFetch(\n `/api/apps/${encodeURIComponent(appId)}/connections/${encodeURIComponent(credentialId)}/onboard/status${qs}`,\n )\n if (!res.ok) throw await onboardingError(res)\n return (await res.json()) as OnboardingStatus\n}\n\n/**\n * Disconnect an onboarded connection (best-effort tenant-side teardown, then\n * delete). POST /api/apps/:appId/connections/:credentialId/onboard/revoke.\n */\nexport async function revokeOnboarding(\n appId: string,\n credentialId: string,\n): Promise<{ cleaned: boolean; message: string }> {\n const res = await authFetch(\n `/api/apps/${encodeURIComponent(appId)}/connections/${encodeURIComponent(credentialId)}/onboard/revoke`,\n { method: 'POST' },\n )\n if (!res.ok) throw await onboardingError(res)\n return (await res.json()) as { cleaned: boolean; message: string }\n}\n","// ========================================================================\n// Client runtime contract — how app client bundles talk to the host.\n//\n// App client code is packaged as a hermetic ESM bundle in which `react`,\n// `react-dom`, `react/jsx-runtime`, and every `@veltrixsecops/app-sdk`\n// subpath are compile-time shims that read the host-provided runtime from\n// `globalThis.__VELTRIX_APP_RUNTIME__`. The platform installs that global\n// (with ITS React instance, the shared AppContext, and an authenticated\n// fetch) before dynamically importing any app bundle, so app components\n// render inside the host React tree with working hooks and context.\n//\n// App authors: import from '@veltrixsecops/app-sdk/client' (and /hooks) —\n// never bundle your own copy of react. Use `authFetch` for calls to your\n// app's server routes (/api/apps/<app-id>/...): plain fetch() lacks the\n// platform's Authorization header and will receive 401s.\n// ========================================================================\n\nimport type { ComponentType, Context, LazyExoticComponent } from 'react'\nimport type { AppContextValue } from '../hooks/use-app-context'\nimport type { AppPermissionsApi } from '../types/platform'\n\nexport type { AppBrandingDeclaration } from '../types/manifest'\nexport type { AppPermissionsApi, PermissionEntry, PermissionCheckOptions } from '../types/platform'\n\n// Inventory — typed helpers over the platform's components API (deployment\n// targets: servers, domains, IP/CIDR ranges). Framework-free; they use the\n// `authFetch` exported below internally.\nexport {\n listInventory,\n addInventoryItem,\n updateInventoryItem,\n removeInventoryItem,\n resolveTool,\n} from './inventory'\nexport type { Tool } from './inventory'\nexport type { InventoryItem, InventoryItemInput } from '../types/platform'\n\n// Connectivity providers — reader over the customer's ZTNA providers, used to\n// populate the Access Server link picker. Framework-free; uses `authFetch`.\nexport { listConnectivityProviders } from './connectivity'\nexport type { ConnectivityProviderRef } from '../types/platform'\n\n// Environments — reader over the customer's deployment scopes, used to populate\n// the Environment picker on Connections + Access Servers. Framework-free.\nexport { listEnvironments } from './environments'\nexport type { EnvironmentRef } from '../types/pipeline'\n\n// Credentials — typed helpers over the platform's credentials API. Paired with\n// a server (component) these form a \"connection\". Secrets are write-only:\n// `listCredentials` returns redacted summaries only. Framework-free; they use\n// the `authFetch` exported below internally.\nexport {\n listCredentials,\n createCredential,\n updateCredential,\n removeCredential,\n testConnection,\n runOperation,\n} from './credentials'\nexport type { Credential, CredentialSummary, CredentialInput } from '../types/platform'\nexport type { TestConnectionResult } from '../types/pipeline'\nexport type { OperationResult } from './credentials'\n\n// Connection onboarding — the one-click \"Connect …\" flow (consent + broker).\n// Framework-free; uses `authFetch`.\nexport { startOnboarding, getOnboardingStatus, revokeOnboarding, fetchAppOnboarding } from './onboarding'\nexport type {\n StartOnboardingInput,\n StartOnboardingResult,\n OnboardingStatus,\n AppOnboardingDescriptor,\n} from './onboarding'\n\n/** Name of the global the platform installs before loading app bundles. */\nexport const HOST_RUNTIME_GLOBAL = '__VELTRIX_APP_RUNTIME__'\n\n/**\n * The runtime surface the platform exposes to app client bundles.\n * The react/reactDom/jsxRuntime members are the host's own module objects —\n * app bundles are compiled with shims that re-export them, guaranteeing a\n * single React instance per page.\n */\nexport interface VeltrixHostRuntime {\n /** The host's `react` module object. */\n react: unknown\n /** The host's `react-dom` module object. */\n reactDom: unknown\n /** The host's `react-dom/client` module object. */\n reactDomClient?: unknown\n /** The host's `react/jsx-runtime` module object. */\n jsxRuntime: unknown\n /** Shared app context — the host wraps app pages in its Provider. */\n AppContext: Context<AppContextValue | null>\n /** fetch() with the platform's Authorization header attached. */\n authFetch: (input: string, init?: RequestInit) => Promise<Response>\n /**\n * The SDK surface app bundles receive for `@veltrixsecops/app-sdk`,\n * `.../hooks`, and `.../client` imports (useAppContext, AppContext,\n * usePipelineStatus, authFetch, getHostRuntime, ...).\n */\n sdk: Record<string, unknown>\n /**\n * The platform's design-system components and hooks, host-owned so they\n * share the single host React instance. Keyed by the exact component/hook\n * names re-exported from `@veltrixsecops/app-sdk/ui` (Button, Input, Card,\n * DataTable, useToast, ...). Present only inside the platform.\n */\n ui?: Record<string, unknown>\n /**\n * Platform-scoped permission checks (RBAC/IdP hardening, Wave C4) —\n * `opts.appId` is NOT defaulted here (omit for a platform-scoped check).\n * App page code should prefer `usePermissions()`\n * (`@veltrixsecops/app-sdk/hooks`), which defaults `opts.appId` to the\n * app's own id. Optional for compatibility with a host that hasn't\n * deployed this surface yet.\n */\n permissions?: AppPermissionsApi\n}\n\n/** Read the host runtime, or null outside the platform (tests, storybook). */\nexport function getHostRuntime(): VeltrixHostRuntime | null {\n const runtime = (globalThis as Record<string, unknown>)[HOST_RUNTIME_GLOBAL]\n return (runtime as VeltrixHostRuntime) ?? null\n}\n\n/** Read the host runtime, throwing a diagnosable error when absent. */\nexport function requireHostRuntime(): VeltrixHostRuntime {\n const runtime = getHostRuntime()\n if (!runtime) {\n throw new Error(\n 'Veltrix host runtime not found — app client bundles only run inside the ' +\n `Veltrix platform (missing globalThis.${HOST_RUNTIME_GLOBAL})`,\n )\n }\n return runtime\n}\n\n/**\n * fetch() that carries the platform's Authorization header. Required for an\n * app page to call its own server routes (/api/apps/<app-id>/...), which are\n * bearer-token protected. Falls back to plain fetch outside the platform.\n */\nexport function authFetch(input: string, init?: RequestInit): Promise<Response> {\n const runtime = getHostRuntime()\n if (runtime) return runtime.authFetch(input, init)\n return fetch(input, init)\n}\n\n/** A sidebar entry contributed by the app's client entry module. */\nexport interface AppSidebarItem {\n path: string\n label: string\n icon?: string\n}\n\n/**\n * Shape of the default export of an app's `client/index.tsx`.\n * `pages` keys must match `manifest.client.pages[].component`.\n */\nexport interface AppClientModule {\n id: string\n pages: Record<string, ComponentType | LazyExoticComponent<ComponentType>>\n sidebarItems?: AppSidebarItem[]\n}\n","// =============================================================================\n// @veltrixsecops/app-sdk/byol — reusable BYOL infrastructure surface.\n//\n// A searchable/filterable list whose rows open a full deployment console (the\n// detail view): summary header, an expandable secondary sidebar, the end-to-end\n// resource plan grouped by tier, and a live deployment activity timeline. Any app\n// can mount <ByolInfrastructureManager apiBase=… /> pointed at its own app-owned\n// `/byol` routes; the app owns the data, this module owns the UI.\n// =============================================================================\n\nexport { ByolInfrastructureManager, default } from './ByolInfrastructureManager'\nexport { ByolInfrastructureDetail } from './ByolInfrastructureDetail'\nexport { ByolPlanModal } from './detail/ByolPlanModal'\nexport type { ByolPlanModalProps } from './detail/ByolPlanModal'\nexport { DestroyPlanModal } from './detail/DestroyPlanModal'\nexport type { DestroyPlanModalProps } from './detail/DestroyPlanModal'\n\n// Plan → Apply diff (pure, React-free — also usable on the server side)\nexport { diffPlan, buildByolPlan, planHasChanges } from './diffPlan'\nexport type {\n PlanAction,\n PlanDiff,\n PlanDiffCurrent,\n PlanDiffDesired,\n ByolPlan,\n ByolPlanSummary,\n ByolPlanItem,\n ByolPlanGroup,\n ByolPlanNetwork,\n} from './diffPlan'\n\n// Tenant / cost-allocation tag builder (pure, React-free — usable server-side)\nexport { buildByolTags, BYOL_TAG_KEYS, MANAGED_BY } from './tags'\nexport type { ByolTags, ByolTagInput } from './tags'\n\n// Cluster placement allocation (pure, React-free — usable server-side)\nexport { allocateNodesBySite, validatePlacement, effectivePlacement } from './placement'\nexport type { SiteAllocation } from './placement'\n\n// Types\nexport type {\n ByolInfrastructure,\n ByolInfrastructureManagerProps,\n ByolConfigLink,\n ByolResource,\n ByolDeployment,\n ByolDeploymentStep,\n ByolRegion,\n Tag,\n CloudProvider,\n CloudRegion,\n CloudAccount,\n FormState,\n ControlPlaneLayout,\n PlacementGranularity,\n PlacementSite,\n ClusterPlacement,\n} from './types'\nexport {\n SINGLE_SITE_PLACEMENT,\n MIN_HEAVY_FORWARDERS,\n CONTROL_PLANE_LAYOUT_OPTIONS,\n PLACEMENT_GRANULARITY_OPTIONS,\n} from './types'\n\n// Status helpers\nexport {\n statusVariant,\n statusLabel,\n isRunning,\n isNotStarted,\n resourceStatusVariant,\n resourceStatusLabel,\n stepStatusVariant,\n} from './status'\n\n// Topology (also exported from the React-free root entry for server use)\nexport { buildByolResourcePlan, TIER_LABELS, TIER_ORDER, DEPLOYMENT_STEPS } from './topology'\nexport type {\n ByolResourceTier,\n ByolResourceKind,\n ByolResourcePlanItem,\n ByolResourcePlanItemWithOrder,\n ByolTopologyInput,\n} from './topology'\n","import React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { authFetch } from '../client'\nimport {\n Card,\n CardHeader,\n CardBody,\n Button,\n Input,\n Select,\n Alert,\n FormDialog,\n DataTable,\n FilterBar,\n SortSelect,\n Pagination,\n type DataTableColumn,\n type FilterDefinition,\n type SortOption,\n} from '../ui'\nimport {\n type ByolInfrastructure,\n type ByolInfrastructureManagerProps,\n type Tag,\n type CloudProvider,\n type CloudRegion,\n type CloudAccount,\n type FormState,\n SELF_HOSTED,\n SELF_HOSTED_LABEL,\n DEFAULT_DEPLOYMENT_TYPES,\n NETWORK_MODE_OPTIONS,\n DNS_MODE_OPTIONS,\n BYOC_NETWORK_MODES,\n CONTROL_PLANE_LAYOUT_OPTIONS,\n INSTANCE_TYPE_EXAMPLES,\n BLANK_FORM,\n editFormState,\n} from './types'\nimport { StatusPill, tokens } from './detail/shared'\nimport { errorText, formatDate } from './api'\nimport { ByolInfrastructureDetail } from './ByolInfrastructureDetail'\nimport { ClusterPlacementField } from './ClusterPlacementField'\nimport { validatePlacement } from './placement'\n\n/**\n * Reusable BYOL infrastructure manager: a searchable/filterable list whose rows\n * open a full deployment console (the detail view), a Provider picker (platform\n * cloud providers plus Self-Hosted), an Environment picker fed by the customer's\n * tags, and a cloud region picker shown only for a distributed cloud deployment.\n * The app owns the data (its own DB table + routes); this component owns the UI.\n */\nexport const ByolInfrastructureManager: React.FC<ByolInfrastructureManagerProps> = ({\n apiBase,\n title = 'BYOL Infrastructure',\n deploymentTypes = DEFAULT_DEPLOYMENT_TYPES,\n configBase,\n configLinks,\n versionOptions = [],\n defaultVersionId,\n}) => {\n const [infrastructure, setInfrastructure] = useState<ByolInfrastructure[]>([])\n const [tags, setTags] = useState<Tag[]>([])\n const [cloudProviders, setCloudProviders] = useState<CloudProvider[]>([])\n const [regions, setRegions] = useState<CloudRegion[]>([])\n const [cloudAccounts, setCloudAccounts] = useState<CloudAccount[]>([])\n const [error, setError] = useState<string | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n\n // Master→detail: which infrastructure (if any) is open.\n const [selectedId, setSelectedId] = useState<string | null>(() => {\n if (typeof window === 'undefined') return null\n return new URLSearchParams(window.location.search).get('infra')\n })\n const [reloadSignal, setReloadSignal] = useState(0)\n\n const [search, setSearch] = useState('')\n const [environmentFilter, setEnvironmentFilter] = useState<string | null>(null)\n const [deploymentFilter, setDeploymentFilter] = useState<string | null>(null)\n const [statusFilter, setStatusFilter] = useState<string | null>(null)\n const [sortField, setSortField] = useState('name')\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc')\n const [page, setPage] = useState(1)\n const [pageSize, setPageSize] = useState(10)\n\n const [dialogOpen, setDialogOpen] = useState(false)\n const [editing, setEditing] = useState<ByolInfrastructure | null>(null)\n const [form, setForm] = useState<FormState>(BLANK_FORM)\n const [submitting, setSubmitting] = useState(false)\n const [formError, setFormError] = useState<string | null>(null)\n\n const load = useCallback(() => {\n setIsLoading(true)\n setError(null)\n return authFetch(apiBase)\n .then((res) => (res.ok ? res.json() : Promise.reject(new Error(`HTTP ${res.status}`))))\n .then((data: ByolInfrastructure[]) => setInfrastructure(Array.isArray(data) ? data : []))\n .catch((e: Error) => setError(e.message))\n .finally(() => setIsLoading(false))\n }, [apiBase])\n\n useEffect(() => {\n void load()\n }, [load])\n\n // Reference lists: environment tags + platform cloud providers + cloud account\n // connections (for BYOC deployment targets). Best-effort.\n useEffect(() => {\n authFetch('/api/tags')\n .then((res) => (res.ok ? res.json() : []))\n .then((data: Tag[]) => setTags(Array.isArray(data) ? data : []))\n .catch(() => setTags([]))\n authFetch('/api/cloud-providers')\n .then((res) => (res.ok ? res.json() : []))\n .then((data: CloudProvider[]) =>\n setCloudProviders(Array.isArray(data) ? data.filter((c) => c.isActive !== false) : []),\n )\n .catch(() => setCloudProviders([]))\n authFetch('/api/cloud-accounts')\n .then((res) => (res.ok ? res.json() : []))\n .then((data: CloudAccount[]) => setCloudAccounts(Array.isArray(data) ? data : []))\n .catch(() => setCloudAccounts([]))\n }, [])\n\n const isCloud = form.providerId !== '' && form.providerId !== SELF_HOSTED\n const showRegion = isCloud && form.deploymentType === 'distributed'\n // Every cloud deploy can pick a verified account — the tenant's own (customer)\n // for BYOC, or a Veltrix-managed (platform) account for a hosted deploy. BYOC\n // (dedicated/existing) REQUIRES one (whose VPC to use); hosted (shared) is\n // optional (falls back to the default provisioning identity).\n const isByoc = BYOC_NETWORK_MODES.has(form.networkMode)\n const showCloudAccount = isCloud\n // A BYOC (dedicated/existing) target needs a cloud account — but only for a CLOUD\n // deploy. Self-hosted ignores networkMode entirely, so it must never gate Save on\n // an account it doesn't even show a picker for.\n const cloudAccountRequired = isByoc && isCloud\n\n // Load the selected cloud provider's regions when needed for the region picker.\n useEffect(() => {\n if (!isCloud) {\n setRegions([])\n return\n }\n let cancelled = false\n authFetch(`/api/cloud-providers/${form.providerId}/regions`)\n .then((res) => (res.ok ? res.json() : []))\n .then((data: CloudRegion[]) => {\n if (!cancelled) setRegions(Array.isArray(data) ? data.filter((r) => r.isActive !== false) : [])\n })\n .catch(() => {\n if (!cancelled) setRegions([])\n })\n return () => {\n cancelled = true\n }\n }, [isCloud, form.providerId])\n\n const openCreate = () => {\n setEditing(null)\n // A fresh infrastructure defaults its version to the app-supplied \"latest\"\n // (defaultVersionId) when one is available; an existing row's Edit form\n // always reflects its own stored versionId instead (see editFormState).\n setForm({ ...BLANK_FORM, versionId: defaultVersionId ?? '' })\n setFormError(null)\n setDialogOpen(true)\n }\n\n const openEdit = (row: ByolInfrastructure) => {\n setEditing(row)\n setForm(editFormState(row))\n setFormError(null)\n setDialogOpen(true)\n }\n\n const closeDialog = useCallback(() => {\n if (submitting) return\n setDialogOpen(false)\n }, [submitting])\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }))\n\n // A cloud account is scoped to a provider — switching providers invalidates any\n // previously selected account (the Cloud account options are recomputed to match\n // the new provider, so keeping the stale id around would let it slip into submit).\n const handleProviderChange = (value: string) =>\n setForm((prev) => ({ ...prev, providerId: value, cloudAccountConnectionId: '' }))\n\n const handleSubmit = async () => {\n if (!form.name.trim()) {\n setFormError('Name is required')\n return\n }\n const indexerCount = Number(form.indexerCount)\n const searchHeadCount = Number(form.searchHeadCount)\n if (form.deploymentType === 'distributed') {\n if (indexerCount < 3) {\n setFormError('Distributed deployments require at least 3 indexers')\n return\n }\n if (searchHeadCount < 2) {\n setFormError('Distributed deployments require at least 2 search heads')\n return\n }\n if (showRegion) {\n const indexerErr = validatePlacement(form.indexerPlacement, indexerCount)\n if (indexerErr) {\n setFormError(`Indexer placement: ${indexerErr}`)\n return\n }\n const searchErr = validatePlacement(form.searchHeadPlacement, searchHeadCount)\n if (searchErr) {\n setFormError(`Search head placement: ${searchErr}`)\n return\n }\n }\n }\n if (cloudAccountRequired && !form.cloudAccountConnectionId) {\n setFormError('Select a verified cloud account for a BYOC deployment target')\n return\n }\n const selfHosted = form.providerId === SELF_HOSTED\n const selectedCloud = cloudProviders.find((c) => c.id === form.providerId)\n const distributed = form.deploymentType === 'distributed'\n // Placement only applies to a distributed cloud deployment (needs AZs/regions);\n // single-instance or self-hosted always collapses to a single site.\n const normalizePlacement = (p: FormState['indexerPlacement']) =>\n distributed && showRegion && p?.mode === 'multi-site' ? p : { mode: 'single' as const }\n setSubmitting(true)\n setFormError(null)\n const payload = {\n name: form.name.trim(),\n deploymentType: form.deploymentType,\n environmentType: form.environmentType,\n hosting_type: selfHosted ? SELF_HOSTED_LABEL : (selectedCloud?.name ?? ''),\n cloudProviderId: selfHosted ? undefined : form.providerId || undefined,\n region: showRegion ? form.region : '',\n indexerCount,\n searchHeadCount,\n networkMode: form.networkMode,\n dnsMode: form.dnsMode,\n cloudAccountConnectionId: showCloudAccount ? form.cloudAccountConnectionId : undefined,\n // Topology authoring — only meaningful for distributed deployments.\n controlPlaneLayout: distributed ? form.controlPlaneLayout : 'dedicated',\n heavyForwarderCount: distributed ? Math.max(1, Number(form.heavyForwarderCount) || 1) : 1,\n // Compute size override; empty → the cloud default (t2.medium-class). Only\n // meaningful for a cloud deployment.\n instanceType: !selfHosted ? form.instanceType.trim() || undefined : undefined,\n indexerPlacement: normalizePlacement(form.indexerPlacement),\n searchHeadPlacement: normalizePlacement(form.searchHeadPlacement),\n versionId: form.versionId || undefined,\n }\n try {\n const res = await authFetch(editing ? `${apiBase}/${editing.id}` : apiBase, {\n method: editing ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) throw new Error(await errorText(res))\n setDialogOpen(false)\n await load()\n // If we edited the open infrastructure, refresh the detail view too.\n if (editing) setReloadSignal((n) => n + 1)\n } catch (e) {\n setFormError((e as Error).message)\n } finally {\n setSubmitting(false)\n }\n }\n\n const openDetail = (id: string | null) => {\n setSelectedId(id)\n if (typeof window !== 'undefined' && id === null) {\n const params = new URLSearchParams(window.location.search)\n params.delete('infra')\n params.delete('section')\n const qs = params.toString()\n window.history.replaceState(null, '', qs ? `${window.location.pathname}?${qs}` : window.location.pathname)\n }\n }\n\n const columns: DataTableColumn<ByolInfrastructure>[] = [\n { key: 'name', header: 'Name', render: (row) => <strong>{row.name}</strong> },\n { key: 'deploymentType', header: 'Deployment', render: (row) => row.deploymentType ?? '—' },\n { key: 'environmentType', header: 'Environment', render: (row) => row.environmentType ?? '—' },\n { key: 'hosting_type', header: 'Provider', render: (row) => row.hosting_type ?? '—' },\n { key: 'region', header: 'Region', render: (row) => row.region || '—' },\n { key: 'indexerCount', header: 'Indexers', align: 'right', render: (row) => row.indexerCount ?? '—' },\n { key: 'searchHeadCount', header: 'Search heads', align: 'right', render: (row) => row.searchHeadCount ?? '—' },\n { key: 'status', header: 'Status', render: (row) => <StatusPill status={row.status} /> },\n { key: 'updatedAt', header: 'Updated', render: (row) => formatDate(row.updatedAt) },\n { key: 'chevron', header: '', align: 'right', width: '32px', render: () => <span aria-hidden style={{ color: tokens.faint }}>›</span> },\n ]\n\n const environmentOptions = useMemo(() => tags.map((t) => ({ value: t.name, label: t.name })), [tags])\n const providerOptions = useMemo(\n () => [\n { value: SELF_HOSTED, label: SELF_HOSTED_LABEL },\n ...cloudProviders.map((c) => ({ value: c.id, label: c.name })),\n ],\n [cloudProviders],\n )\n const regionOptions = useMemo(\n () => regions.map((r) => ({ value: r.code, label: `${r.name} (${r.code})` })),\n [regions],\n )\n const selectedProvider = useMemo(\n () => cloudProviders.find((c) => c.id === form.providerId),\n [cloudProviders, form.providerId],\n )\n // Only verified accounts, narrowed to the selected cloud provider (when one is picked).\n const verifiedCloudAccounts = useMemo(\n () =>\n cloudAccounts.filter(\n (a) => a.status === 'VERIFIED' && (!selectedProvider?.code || a.provider === selectedProvider.code),\n ),\n [cloudAccounts, selectedProvider],\n )\n const cloudAccountOptions = useMemo(\n () =>\n verifiedCloudAccounts.map((a) => ({\n value: a.id,\n label: `${a.name} (${a.provider}${a.scope === 'platform' ? ' · Veltrix-managed' : ''})`,\n })),\n [verifiedCloudAccounts],\n )\n\n const statusFilterOptions = useMemo(() => {\n const seen = new Set<string>()\n infrastructure.forEach((i) => seen.add(i.status ?? 'unknown'))\n return Array.from(seen, (value) => ({ value, label: value }))\n }, [infrastructure])\n\n const sortOptions: SortOption[] = [\n { value: 'name', label: 'Name' },\n { value: 'indexerCount', label: 'Indexers' },\n { value: 'searchHeadCount', label: 'Search heads' },\n { value: 'status', label: 'Status' },\n { value: 'updatedAt', label: 'Updated' },\n ]\n const filters: FilterDefinition[] = [\n { key: 'environment', label: 'Environment', options: environmentOptions, value: environmentFilter, onChange: setEnvironmentFilter, alwaysVisible: true },\n { key: 'deployment', label: 'Deployment', options: deploymentTypes, value: deploymentFilter, onChange: setDeploymentFilter },\n { key: 'status', label: 'Status', options: statusFilterOptions, value: statusFilter, onChange: setStatusFilter },\n ]\n\n const filteredSorted = useMemo(() => {\n const term = search.trim().toLowerCase()\n const rows = infrastructure.filter((row) => {\n if (term) {\n const haystack = `${row.name ?? ''} ${row.hosting_type ?? ''} ${row.region ?? ''}`.toLowerCase()\n if (!haystack.includes(term)) return false\n }\n if (environmentFilter && row.environmentType !== environmentFilter) return false\n if (deploymentFilter && row.deploymentType !== deploymentFilter) return false\n if (statusFilter && (row.status ?? 'unknown') !== statusFilter) return false\n return true\n })\n const dir = sortDir === 'asc' ? 1 : -1\n return [...rows].sort((a, b) => {\n switch (sortField) {\n case 'indexerCount':\n return ((a.indexerCount ?? 0) - (b.indexerCount ?? 0)) * dir\n case 'searchHeadCount':\n return ((a.searchHeadCount ?? 0) - (b.searchHeadCount ?? 0)) * dir\n case 'status':\n return (a.status ?? '').localeCompare(b.status ?? '') * dir\n case 'updatedAt':\n return (new Date(a.updatedAt ?? 0).getTime() - new Date(b.updatedAt ?? 0).getTime()) * dir\n case 'name':\n default:\n return (a.name ?? '').localeCompare(b.name ?? '') * dir\n }\n })\n }, [infrastructure, search, environmentFilter, deploymentFilter, statusFilter, sortField, sortDir])\n\n const pageRows = useMemo(\n () => filteredSorted.slice((page - 1) * pageSize, page * pageSize),\n [filteredSorted, page, pageSize],\n )\n\n useEffect(() => {\n setPage(1)\n }, [search, environmentFilter, deploymentFilter, statusFilter, sortField, sortDir])\n\n const selected = selectedId ? infrastructure.find((i) => i.id === selectedId) ?? null : null\n\n // --- Detail view (master→detail swap) ---\n if (selectedId && selected) {\n return (\n <>\n <ByolInfrastructureDetail\n apiBase={apiBase}\n initialInfra={selected}\n configBase={configBase}\n configLinks={configLinks}\n reloadSignal={reloadSignal}\n onBack={() => openDetail(null)}\n onEdit={openEdit}\n onDeleted={() => {\n openDetail(null)\n void load()\n }}\n onChanged={() => void load()}\n />\n <FormDialog\n isOpen={dialogOpen}\n onClose={closeDialog}\n title={editing ? `Edit \"${editing.name}\"` : 'New BYOL infrastructure'}\n description=\"Define the deployment topology for a Bring-Your-Own-License Splunk environment.\"\n onSubmit={handleSubmit}\n submitText={editing ? 'Save changes' : 'Create infrastructure'}\n isSubmitting={submitting}\n submitDisabled={!form.name.trim() || (cloudAccountRequired && !form.cloudAccountConnectionId)}\n error={formError}\n size=\"md\"\n >\n <FormBody\n form={form}\n setField={setField}\n onProviderChange={handleProviderChange}\n deploymentTypes={deploymentTypes}\n environmentOptions={environmentOptions}\n providerOptions={providerOptions}\n regionOptions={regionOptions}\n showRegion={showRegion}\n showCloudAccount={showCloudAccount}\n cloudAccountRequired={cloudAccountRequired}\n cloudAccountOptions={cloudAccountOptions}\n selectedProviderName={selectedProvider?.name}\n providerCode={selectedProvider?.code}\n versionOptions={versionOptions}\n />\n </FormDialog>\n </>\n )\n }\n\n // --- List view ---\n return (\n <Card variant=\"bordered\">\n <CardHeader\n actions={\n <div style={{ display: 'flex', gap: 8 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => void load()} isLoading={isLoading}>\n Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={openCreate}>\n New infrastructure\n </Button>\n </div>\n }\n >\n <h2 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{title}</h2>\n </CardHeader>\n <CardBody>\n {error ? (\n <p style={{ color: tokens.danger }}>Failed to load BYOL infrastructure: {error}</p>\n ) : null}\n\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>\n <FilterBar\n search={{ value: search, onChange: setSearch, placeholder: 'Search infrastructure…' }}\n filters={filters}\n />\n <SortSelect\n options={sortOptions}\n value={sortField}\n direction={sortDir}\n onChange={(field, dir) => {\n setSortField(field)\n setSortDir(dir)\n }}\n />\n </div>\n\n <DataTable\n columns={columns}\n data={pageRows}\n rowKey={(row) => row.id}\n isLoading={isLoading}\n onRowClick={(row) => openDetail(row.id)}\n emptyState={{\n title: 'No BYOL infrastructure yet',\n description: 'Create a BYOL deployment to manage its topology, resources and lifecycle here.',\n }}\n />\n <div style={{ marginTop: 12 }}>\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={filteredSorted.length}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n pageSizeOptions={[10, 25, 50]}\n />\n </div>\n </CardBody>\n\n <FormDialog\n isOpen={dialogOpen}\n onClose={closeDialog}\n title={editing ? `Edit \"${editing.name}\"` : 'New BYOL infrastructure'}\n description=\"Define the deployment topology for a Bring-Your-Own-License Splunk environment.\"\n onSubmit={handleSubmit}\n submitText={editing ? 'Save changes' : 'Create infrastructure'}\n isSubmitting={submitting}\n submitDisabled={!form.name.trim() || (cloudAccountRequired && !form.cloudAccountConnectionId)}\n error={formError}\n size=\"md\"\n >\n <FormBody\n form={form}\n setField={setField}\n onProviderChange={handleProviderChange}\n deploymentTypes={deploymentTypes}\n environmentOptions={environmentOptions}\n providerOptions={providerOptions}\n regionOptions={regionOptions}\n showRegion={showRegion}\n showCloudAccount={showCloudAccount}\n cloudAccountRequired={cloudAccountRequired}\n cloudAccountOptions={cloudAccountOptions}\n selectedProviderName={selectedProvider?.name}\n versionOptions={versionOptions}\n />\n </FormDialog>\n </Card>\n )\n}\n\n// --- Create/edit form body (shared by both list + detail entry points) -------\n\ninterface FormBodyProps {\n form: FormState\n setField: <K extends keyof FormState>(key: K, value: FormState[K]) => void\n /** Provider-specific onChange (also clears a now-mismatched cloud account selection). */\n onProviderChange: (value: string) => void\n deploymentTypes: Array<{ value: string; label: string }>\n environmentOptions: Array<{ value: string; label: string }>\n providerOptions: Array<{ value: string; label: string }>\n regionOptions: Array<{ value: string; label: string }>\n showRegion: boolean\n /** Whether the current network mode is BYOC (dedicated/existing) and needs a cloud account. */\n showCloudAccount: boolean\n /** Whether an account MUST be picked (BYOC) vs optional (hosted platform account). */\n cloudAccountRequired: boolean\n /** Verified cloud accounts, narrowed to the selected provider when one is picked. */\n cloudAccountOptions: Array<{ value: string; label: string }>\n /** Selected cloud provider's display name, for the \"no verified account\" note. */\n selectedProviderName?: string\n /** Selected cloud provider's code (aws|azure|gcp|hetzner), for cloud-aware zone naming. */\n providerCode?: string\n /** Software version options (app-supplied); the picker is hidden when empty. */\n versionOptions: Array<{ value: string; label: string }>\n}\n\n/** A labelled sub-group of related fields, so the form reads as scannable sections. */\nconst FormSection: React.FC<{ title: string; description?: string; children: React.ReactNode }> = ({\n title,\n description,\n children,\n}) => (\n <div>\n <p style={{ margin: 0, fontSize: 13, fontWeight: 600, color: tokens.text }}>{title}</p>\n {description ? (\n <p style={{ margin: '2px 0 0', fontSize: 12, color: tokens.muted }}>{description}</p>\n ) : null}\n <div style={{ marginTop: 10, display: 'flex', flexDirection: 'column', gap: 12 }}>{children}</div>\n </div>\n)\n\nconst FormBody: React.FC<FormBodyProps> = ({\n form,\n setField,\n onProviderChange,\n deploymentTypes,\n environmentOptions,\n providerOptions,\n regionOptions,\n showRegion,\n showCloudAccount,\n cloudAccountRequired,\n cloudAccountOptions,\n selectedProviderName,\n providerCode,\n versionOptions,\n}) => (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Input label=\"Name\" value={form.name} onChange={(e) => setField('name', e.target.value)} placeholder=\"e.g. Production cluster\" fullWidth autoFocus />\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>\n <Select label=\"Deployment type\" value={form.deploymentType} onChange={(value) => setField('deploymentType', value)} options={deploymentTypes} />\n <Select label=\"Environment\" value={form.environmentType} onChange={(value) => setField('environmentType', value)} options={environmentOptions} />\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: showRegion ? '1fr 1fr' : '1fr', gap: 12 }}>\n <Select label=\"Provider\" value={form.providerId} onChange={onProviderChange} options={providerOptions} />\n {showRegion ? (\n <Select label=\"Region\" value={form.region} onChange={(value) => setField('region', value)} options={regionOptions} />\n ) : null}\n </div>\n\n <FormSection title=\"Deployment target\">\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>\n <Select\n label=\"Network\"\n value={form.networkMode}\n onChange={(value) => setField('networkMode', value)}\n options={NETWORK_MODE_OPTIONS}\n />\n <Select label=\"DNS\" value={form.dnsMode} onChange={(value) => setField('dnsMode', value)} options={DNS_MODE_OPTIONS} />\n </div>\n {showCloudAccount ? (\n <>\n <Select\n label={cloudAccountRequired ? 'Cloud account *' : 'Cloud account'}\n value={form.cloudAccountConnectionId}\n onChange={(value) => setField('cloudAccountConnectionId', value)}\n options={cloudAccountOptions}\n placeholder={\n cloudAccountOptions.length\n ? 'Select a verified cloud account…'\n : cloudAccountRequired\n ? 'No verified cloud accounts'\n : 'None — use the default provisioning identity'\n }\n disabled={cloudAccountOptions.length === 0}\n helperText={\n cloudAccountRequired\n ? 'Required for a dedicated or existing-network (BYOC) deployment.'\n : 'Optional — the Veltrix-managed account this hosted deployment provisions through.'\n }\n />\n {cloudAccountRequired && cloudAccountOptions.length === 0 ? (\n <Alert variant=\"warning\" title=\"No verified cloud account available\">\n {selectedProviderName\n ? `No verified ${selectedProviderName} cloud account found. Register and verify a cloud account first in Settings → Cloud Accounts.`\n : 'Register and verify a cloud account first in Settings → Cloud Accounts.'}\n </Alert>\n ) : null}\n </>\n ) : null}\n </FormSection>\n\n <FormSection\n title=\"Topology\"\n description={\n form.deploymentType === 'distributed'\n ? 'Distributed deployments need at least 3 indexers and 2 search heads.'\n : 'Number of indexer and search-head nodes to provision.'\n }\n >\n {versionOptions.length > 0 ? (\n <Select\n label=\"Splunk version\"\n value={form.versionId}\n onChange={(value) => setField('versionId', value)}\n options={versionOptions}\n placeholder=\"Use the app's default version\"\n helperText=\"The Splunk release installed on every node. Leave unset to use the app's default installer.\"\n />\n ) : null}\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>\n <Input label=\"Indexers\" type=\"number\" min={1} value={form.indexerCount} onChange={(e) => setField('indexerCount', e.target.value)} fullWidth />\n <Input label=\"Search heads\" type=\"number\" min={1} value={form.searchHeadCount} onChange={(e) => setField('searchHeadCount', e.target.value)} fullWidth />\n </div>\n {form.providerId && form.providerId !== SELF_HOSTED ? (\n <Input\n label=\"Compute size (instance type)\"\n value={form.instanceType}\n onChange={(e) => setField('instanceType', e.target.value)}\n placeholder={INSTANCE_TYPE_EXAMPLES.aws}\n fullWidth\n helperText={`Leave blank for the cloud default (~2 vCPU / 4 GB). Examples: AWS ${INSTANCE_TYPE_EXAMPLES.aws}, Azure ${INSTANCE_TYPE_EXAMPLES.azure}, GCP ${INSTANCE_TYPE_EXAMPLES.gcp}, Hetzner ${INSTANCE_TYPE_EXAMPLES.hetzner}. Applies to every node; you can change it here later.`}\n />\n ) : null}\n {showRegion ? (\n <>\n <ClusterPlacementField\n label=\"Indexer cluster placement\"\n placement={form.indexerPlacement}\n nodeCount={Math.max(1, Number(form.indexerCount) || 1)}\n primaryRegion={form.region}\n providerCode={providerCode}\n regionOptions={regionOptions}\n onChange={(p) => setField('indexerPlacement', p)}\n />\n <ClusterPlacementField\n label=\"Search head cluster placement\"\n placement={form.searchHeadPlacement}\n nodeCount={Math.max(1, Number(form.searchHeadCount) || 1)}\n primaryRegion={form.region}\n providerCode={providerCode}\n regionOptions={regionOptions}\n onChange={(p) => setField('searchHeadPlacement', p)}\n />\n </>\n ) : null}\n </FormSection>\n\n {form.deploymentType === 'distributed' ? (\n <>\n <FormSection\n title=\"Control plane\"\n description=\"How many instances the five management roles run on — fewer instances cut cost, more give isolation and HA.\"\n >\n <Select\n label=\"Consolidation\"\n value={form.controlPlaneLayout}\n onChange={(value) => setField('controlPlaneLayout', value as FormState['controlPlaneLayout'])}\n options={CONTROL_PLANE_LAYOUT_OPTIONS.map((o) => ({ value: o.value, label: `${o.label} — ${o.description}` }))}\n />\n </FormSection>\n\n <FormSection\n title=\"Ingest\"\n description=\"Heavy forwarders for ingest routing. One is provisioned by default; add more for higher throughput.\"\n >\n <Input\n label=\"Heavy forwarders\"\n type=\"number\"\n min={1}\n value={form.heavyForwarderCount}\n onChange={(e) => setField('heavyForwarderCount', e.target.value)}\n fullWidth\n />\n </FormSection>\n </>\n ) : null}\n </div>\n)\n\nexport default ByolInfrastructureManager\n","// ========================================================================\n// @veltrixsecops/app-sdk/ui — the platform's shared component library,\n// exposed to app client bundles.\n//\n// App pages import these instead of hand-rolling raw HTML, so pages render\n// themed inside the Veltrix design system (dark/light + tenant branding via\n// `var(--vx-*)`), consistent with the rest of the portal, and externalized —\n// zero bundle bloat, one React instance. This completes the \"predictable\n// shell, flexible body\" contract: the platform owns the components; apps\n// compose their page body from them.\n//\n// RUNTIME: every export here reads its real implementation off the host at\n// render time — globalThis.__VELTRIX_APP_RUNTIME__.ui.<Name>, populated by\n// the platform from components/shared/* (see\n// client/src/appRuntime/installHostRuntime.ts). At packaging time the CLI's\n// client bundler (and the platform's on-demand esbuild bundle routes) shim\n// the '@veltrixsecops/app-sdk/ui' specifier straight to that `ui` bag, so\n// this module's own render-time lookup only actually executes in\n// non-bundled contexts: local dev, unit tests, a bare `tsc --noEmit`, or\n// Storybook.\n//\n// FALLBACK CONTRACT: outside the platform (host runtime absent, or an older\n// host that predates a given component) every export here renders a\n// minimal, accessible, unstyled fallback instead of throwing — an app page\n// under test or local dev keeps working, just without platform theming.\n// Never throw on render.\n//\n// TYPE FIDELITY: prop types are copied from the platform's real components\n// in client/src/components/shared (see the ADR at\n// _ai_tasks/ui-package/2026-07-10/02_sdk_ui_subpath.md) so app-author\n// typechecking matches what actually renders inside Veltrix. Heavy composite\n// widgets (ConfigurationCanvas, VersionControl, Pipeline) stay out of scope —\n// they carry platform coupling a later phase may expose read-only versions\n// of; see the ADR's \"Non-goals\" section.\n//\n// EXPORTS: Button, Badge, Card (+ CardHeader/CardBody/CardFooter), Input,\n// Textarea, Checkbox, Select, SearchBox, Pagination, FilterBar, SortSelect,\n// FormField, Tabs, EmptyState, Skeleton (+ SkeletonText/SkeletonCard),\n// Tooltip, Spinner, DataTable, StatsCard, FormDialog, useToast,\n// useConfirmDialog.\n//\n// useToast / useConfirmDialog are included because the platform's root\n// App.tsx mounts ToastProvider/ConfirmationDialogProvider around the ENTIRE\n// tree (including every app page, since app pages render inside the host's\n// own React instance) — so the real context-backed hooks resolve correctly\n// from app code with no extra wiring. Outside the platform they degrade to a\n// safe, non-throwing fallback (see each hook's docs below) rather than\n// crashing or silently doing nothing.\n// ========================================================================\n\nimport * as React from 'react'\nimport { getHostRuntime } from '../client'\n\n/** Read one named component off the host's `runtime.ui` bag, or undefined. */\nfunction getHostUi<T>(name: string): T | undefined {\n return getHostRuntime()?.ui?.[name] as T | undefined\n}\n\nconst fallbackNote: React.CSSProperties = { fontFamily: 'inherit' }\n\n// ---------------------------------------------------------------------------\n// Button\n// ---------------------------------------------------------------------------\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'ghost' | 'link'\nexport type ButtonSize = 'sm' | 'md' | 'lg'\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant\n size?: ButtonSize\n isLoading?: boolean\n loadingText?: string\n fullWidth?: boolean\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n}\n\ntype ButtonComponent = React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>\n\n/**\n * Button — delegates to the platform's real Button at render time.\n *\n * @example\n * <Button variant=\"primary\" leftIcon={<RefreshIcon />} onClick={refresh}>Refresh</Button>\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {\n const HostButton = getHostUi<ButtonComponent>('Button')\n if (HostButton) return <HostButton ref={ref} {...props} />\n\n const {\n variant: _variant,\n size: _size,\n isLoading,\n loadingText,\n fullWidth,\n leftIcon,\n rightIcon,\n children,\n disabled,\n type,\n style,\n ...rest\n } = props\n\n return (\n <button\n ref={ref}\n type={type ?? 'button'}\n disabled={disabled || isLoading}\n aria-busy={isLoading || undefined}\n style={{\n ...fallbackNote,\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n padding: '6px 14px',\n borderRadius: 6,\n border: '1px solid currentColor',\n background: 'transparent',\n cursor: disabled || isLoading ? 'not-allowed' : 'pointer',\n width: fullWidth ? '100%' : undefined,\n opacity: disabled || isLoading ? 0.6 : 1,\n justifyContent: 'center',\n ...style,\n }}\n {...rest}\n >\n {leftIcon}\n {isLoading ? loadingText ?? children : children}\n {rightIcon}\n </button>\n )\n})\nButton.displayName = 'Button'\n\n// ---------------------------------------------------------------------------\n// Badge\n// ---------------------------------------------------------------------------\n\nexport type BadgeVariant = 'default' | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info'\nexport type BadgeSize = 'sm' | 'md' | 'lg'\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: BadgeVariant\n size?: BadgeSize\n rounded?: boolean\n dot?: boolean\n}\n\nconst BADGE_FALLBACK_COLORS: Record<BadgeVariant, string> = {\n default: '#6b7280',\n primary: '#4f46e5',\n secondary: '#6b7280',\n success: '#16a34a',\n danger: '#dc2626',\n warning: '#d97706',\n info: '#0284c7',\n}\n\n/**\n * Badge — delegates to the platform's real Badge at render time.\n *\n * @example\n * <Badge variant={row.deployState === 'deployed' ? 'success' : 'warning'}>{row.deployState}</Badge>\n */\nexport const Badge: React.FC<BadgeProps> = ({ variant = 'default', size = 'md', rounded, dot, children, style, ...rest }) => {\n const HostBadge = getHostUi<React.FC<BadgeProps>>('Badge')\n if (HostBadge) return <HostBadge variant={variant} size={size} rounded={rounded} dot={dot} style={style} {...rest}>{children}</HostBadge>\n\n const color = BADGE_FALLBACK_COLORS[variant]\n const fontSize = size === 'sm' ? 11 : size === 'lg' ? 14 : 12\n return (\n <span\n style={{\n ...fallbackNote,\n display: 'inline-flex',\n alignItems: 'center',\n gap: 4,\n padding: size === 'sm' ? '1px 6px' : size === 'lg' ? '3px 10px' : '2px 8px',\n borderRadius: rounded ? 999 : 4,\n border: `1px solid ${color}`,\n color,\n fontSize,\n fontWeight: 500,\n ...style,\n }}\n {...rest}\n >\n {dot && <span aria-hidden=\"true\" style={{ width: 6, height: 6, borderRadius: '50%', background: color }} />}\n {children}\n </span>\n )\n}\nBadge.displayName = 'Badge'\n\n// ---------------------------------------------------------------------------\n// Card (+ Header/Body/Footer)\n// ---------------------------------------------------------------------------\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: 'default' | 'bordered' | 'elevated'\n padding?: 'none' | 'sm' | 'md' | 'lg'\n}\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n actions?: React.ReactNode\n}\nexport type CardBodyProps = React.HTMLAttributes<HTMLDivElement>\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: 'default' | 'bordered'\n}\n\n/** Card — delegates to the platform's real Card at render time. */\nexport const Card: React.FC<CardProps> = ({ children, style, ...rest }) => {\n const HostCard = getHostUi<React.FC<CardProps>>('Card')\n if (HostCard) return <HostCard style={style} {...rest}>{children}</HostCard>\n return (\n <div style={{ ...fallbackNote, border: '1px solid #d1d5db', borderRadius: 8, overflow: 'hidden', ...style }} {...rest}>\n {children}\n </div>\n )\n}\nCard.displayName = 'Card'\n\n/** CardHeader — the header section of a Card, with optional trailing actions. */\nexport const CardHeader: React.FC<CardHeaderProps> = ({ actions, children, style, ...rest }) => {\n const HostCardHeader = getHostUi<React.FC<CardHeaderProps>>('CardHeader')\n if (HostCardHeader) return <HostCardHeader actions={actions} style={style} {...rest}>{children}</HostCardHeader>\n return (\n <div\n style={{\n ...fallbackNote,\n padding: '12px 16px',\n borderBottom: '1px solid #d1d5db',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n ...style,\n }}\n {...rest}\n >\n <div style={{ flex: 1, minWidth: 0 }}>{children}</div>\n {actions && <div>{actions}</div>}\n </div>\n )\n}\nCardHeader.displayName = 'CardHeader'\n\n/** CardBody — the main content area of a Card. */\nexport const CardBody: React.FC<CardBodyProps> = ({ children, style, ...rest }) => {\n const HostCardBody = getHostUi<React.FC<CardBodyProps>>('CardBody')\n if (HostCardBody) return <HostCardBody style={style} {...rest}>{children}</HostCardBody>\n return (\n <div style={{ ...fallbackNote, padding: '12px 16px', ...style }} {...rest}>\n {children}\n </div>\n )\n}\nCardBody.displayName = 'CardBody'\n\n/** CardFooter — the footer section of a Card, typically for actions. */\nexport const CardFooter: React.FC<CardFooterProps> = ({ children, style, ...rest }) => {\n const HostCardFooter = getHostUi<React.FC<CardFooterProps>>('CardFooter')\n if (HostCardFooter) return <HostCardFooter style={style} {...rest}>{children}</HostCardFooter>\n return (\n <div style={{ ...fallbackNote, padding: '12px 16px', borderTop: '1px solid #d1d5db', ...style }} {...rest}>\n {children}\n </div>\n )\n}\nCardFooter.displayName = 'CardFooter'\n\n// ---------------------------------------------------------------------------\n// Input\n// ---------------------------------------------------------------------------\n\nexport type InputSize = 'sm' | 'md' | 'lg'\nexport type InputVariant = 'default' | 'error' | 'success'\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\n label?: string\n error?: string\n helperText?: string\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n variant?: InputVariant\n inputSize?: InputSize\n isSuccess?: boolean\n fullWidth?: boolean\n}\n\ntype InputComponent = React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>\n\n/**\n * Input — delegates to the platform's real Input at render time.\n *\n * @example\n * <Input label=\"Index name\" value={name} onChange={(e) => setName(e.target.value)} error={errors.name} />\n */\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {\n const HostInput = getHostUi<InputComponent>('Input')\n if (HostInput) return <HostInput ref={ref} {...props} />\n\n const { label, error, helperText, leftIcon, rightIcon, fullWidth = true, id, style, ...rest } = props\n const inputId = id ?? (label ? `vx-input-${label.toLowerCase().replace(/\\s+/g, '-')}` : undefined)\n\n return (\n <div style={{ ...fallbackNote, width: fullWidth ? '100%' : undefined }}>\n {label && (\n <label htmlFor={inputId} style={{ display: 'block', fontSize: 13, fontWeight: 500, marginBottom: 4 }}>\n {label}\n </label>\n )}\n <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\n {leftIcon}\n <input\n ref={ref}\n id={inputId}\n aria-invalid={!!error || undefined}\n style={{ flex: 1, padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af', ...style }}\n {...rest}\n />\n {rightIcon}\n </div>\n {error && (\n <p role=\"alert\" style={{ marginTop: 4, fontSize: 12, color: '#dc2626' }}>\n {error}\n </p>\n )}\n {helperText && !error && <p style={{ marginTop: 4, fontSize: 12, color: '#6b7280' }}>{helperText}</p>}\n </div>\n )\n})\nInput.displayName = 'Input'\n\n// ---------------------------------------------------------------------------\n// Textarea\n// ---------------------------------------------------------------------------\n\nexport interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n label?: string\n error?: string\n helperText?: string\n fullWidth?: boolean\n}\n\ntype TextareaComponent = React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>\n\n/**\n * Textarea — delegates to the platform's real Textarea at render time.\n *\n * @example\n * <Textarea label=\"Description\" helperText=\"Markdown is supported.\" />\n */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>((props, ref) => {\n const HostTextarea = getHostUi<TextareaComponent>('Textarea')\n if (HostTextarea) return <HostTextarea ref={ref} {...props} />\n\n const { label, error, helperText, fullWidth = true, id, rows = 4, style, ...rest } = props\n const textareaId = id ?? (label ? `vx-textarea-${label.toLowerCase().replace(/\\s+/g, '-')}` : undefined)\n\n return (\n <div style={{ ...fallbackNote, width: fullWidth ? '100%' : undefined }}>\n {label && (\n <label htmlFor={textareaId} style={{ display: 'block', fontSize: 13, fontWeight: 500, marginBottom: 4 }}>\n {label}\n </label>\n )}\n <textarea\n ref={ref}\n id={textareaId}\n rows={rows}\n aria-invalid={!!error || undefined}\n style={{ width: '100%', padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af', ...style }}\n {...rest}\n />\n {error && (\n <p role=\"alert\" style={{ marginTop: 4, fontSize: 12, color: '#dc2626' }}>\n {error}\n </p>\n )}\n {helperText && !error && <p style={{ marginTop: 4, fontSize: 12, color: '#6b7280' }}>{helperText}</p>}\n </div>\n )\n})\nTextarea.displayName = 'Textarea'\n\n// ---------------------------------------------------------------------------\n// Checkbox\n// ---------------------------------------------------------------------------\n\nexport interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: React.ReactNode\n error?: string\n helperText?: string\n}\n\ntype CheckboxComponent = React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>\n\n/**\n * Checkbox — delegates to the platform's real Checkbox at render time.\n *\n * @example\n * <Checkbox label=\"Enable drift detection\" checked={enabled} onChange={(e) => setEnabled(e.target.checked)} />\n */\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {\n const HostCheckbox = getHostUi<CheckboxComponent>('Checkbox')\n if (HostCheckbox) return <HostCheckbox ref={ref} {...props} />\n\n const { label, error, helperText, id, disabled, ...rest } = props\n const generatedId = React.useId()\n const inputId = id ?? generatedId\n\n return (\n <div style={fallbackNote}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <input ref={ref} id={inputId} type=\"checkbox\" disabled={disabled} aria-invalid={!!error || undefined} {...rest} />\n {label && (\n <label htmlFor={inputId} style={{ fontSize: 13, cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.6 : 1 }}>\n {label}\n </label>\n )}\n </div>\n {error && (\n <p role=\"alert\" style={{ marginTop: 4, fontSize: 12, color: '#dc2626' }}>\n {error}\n </p>\n )}\n {helperText && !error && <p style={{ marginTop: 4, fontSize: 12, color: '#6b7280' }}>{helperText}</p>}\n </div>\n )\n})\nCheckbox.displayName = 'Checkbox'\n\n// ---------------------------------------------------------------------------\n// Select (controlled; onChange receives the new value string)\n// ---------------------------------------------------------------------------\n\nexport type SelectSize = 'sm' | 'md' | 'lg'\n\nexport interface SelectOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface SelectProps {\n options: SelectOption[]\n value?: string\n onChange?: (value: string) => void\n placeholder?: string\n label?: string\n error?: string\n helperText?: string\n size?: SelectSize\n disabled?: boolean\n fullWidth?: boolean\n className?: string\n id?: string\n name?: string\n 'aria-label'?: string\n}\n\n/**\n * Select — delegates to the platform's real (WAI-ARIA listbox) Select at render time.\n * The fallback is a native `<select>` — functionally equivalent, visually plainer.\n *\n * @example\n * <Select label=\"Environment\" value={env} onChange={setEnv} options={[{ value: 'prod', label: 'Production' }]} />\n */\nexport const Select: React.FC<SelectProps> = (props) => {\n const HostSelect = getHostUi<React.FC<SelectProps>>('Select')\n if (HostSelect) return <HostSelect {...props} />\n\n const { options, value, onChange, placeholder = 'Select…', label, error, helperText, disabled, fullWidth = true, id, name, className } = props\n const selectId = id ?? (label ? `vx-select-${label.toLowerCase().replace(/\\s+/g, '-')}` : undefined)\n\n return (\n <div className={className} style={{ ...fallbackNote, width: fullWidth ? '100%' : undefined }}>\n {label && (\n <label htmlFor={selectId} style={{ display: 'block', fontSize: 13, fontWeight: 500, marginBottom: 4 }}>\n {label}\n </label>\n )}\n <select\n id={selectId}\n name={name}\n aria-label={props['aria-label']}\n aria-invalid={!!error || undefined}\n disabled={disabled}\n value={value ?? ''}\n onChange={(event) => onChange?.(event.target.value)}\n style={{ width: '100%', padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af' }}\n >\n {placeholder && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n {error && (\n <p role=\"alert\" style={{ marginTop: 4, fontSize: 12, color: '#dc2626' }}>\n {error}\n </p>\n )}\n {helperText && !error && <p style={{ marginTop: 4, fontSize: 12, color: '#6b7280' }}>{helperText}</p>}\n </div>\n )\n}\nSelect.displayName = 'Select'\n\n// ---------------------------------------------------------------------------\n// SearchBox\n// ---------------------------------------------------------------------------\n\nexport type SearchBoxSize = 'sm' | 'md' | 'lg'\n\nexport interface SearchBoxProps {\n /** Controlled search text. */\n value: string\n /** Called with the new text — debounced by `debounceMs` when set. */\n onChange: (value: string) => void\n placeholder?: string\n disabled?: boolean\n size?: SearchBoxSize\n /** Debounces `onChange` by this many ms; omit (or `0`) to call on every keystroke. */\n debounceMs?: number\n className?: string\n 'aria-label'?: string\n}\n\n/**\n * SearchBox — delegates to the platform's real SearchBox at render time (leading search icon,\n * a clear button once there's text, optional debounce). The fallback is a bare\n * `<input type=\"search\">` wired straight to `value`/`onChange` — no icon, no debounce, no\n * clear button — but functionally sufficient for typing and clearing.\n *\n * @example\n * <SearchBox value={search} onChange={setSearch} placeholder=\"Search apps…\" debounceMs={250} />\n */\nexport const SearchBox: React.FC<SearchBoxProps> = (props) => {\n const HostSearchBox = getHostUi<React.FC<SearchBoxProps>>('SearchBox')\n if (HostSearchBox) return <HostSearchBox {...props} />\n\n const { value, onChange, placeholder, disabled, className, 'aria-label': ariaLabel } = props\n return (\n <input\n type=\"search\"\n value={value}\n onChange={(event) => onChange(event.target.value)}\n placeholder={placeholder}\n disabled={disabled}\n aria-label={ariaLabel ?? placeholder ?? 'Search'}\n className={className}\n style={{ ...fallbackNote, width: '100%', padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af' }}\n />\n )\n}\nSearchBox.displayName = 'SearchBox'\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\nexport interface PaginationProps {\n /** 1-based current page. */\n page: number\n pageSize: number\n totalItems: number\n onPageChange: (page: number) => void\n /** Renders a page-size selector when provided together with `pageSizeOptions`. */\n onPageSizeChange?: (size: number) => void\n pageSizeOptions?: number[]\n disabled?: boolean\n className?: string\n}\n\n/**\n * Pagination — delegates to the platform's real Pagination at render time: a \"Showing X–Y of\n * N\" summary, numbered pages with ellipsis for large ranges, an optional page-size Select, and\n * `aria-current=\"page\"` on the active page — visually consistent with DataTable's built-in\n * pagination footer. The fallback is a plain Prev/Next pair with \"page X of Y\" text.\n *\n * @example\n * <Pagination page={page} pageSize={20} totalItems={total} onPageChange={setPage} />\n */\nexport const Pagination: React.FC<PaginationProps> = (props) => {\n const HostPagination = getHostUi<React.FC<PaginationProps>>('Pagination')\n if (HostPagination) return <HostPagination {...props} />\n\n const { page, pageSize, totalItems, onPageChange, disabled, className } = props\n const pageCount = Math.max(1, Math.ceil(totalItems / pageSize))\n const canGoPrev = !disabled && page > 1\n const canGoNext = !disabled && page < pageCount\n\n return (\n <nav aria-label=\"Pagination\" className={className} style={{ ...fallbackNote, display: 'flex', alignItems: 'center', gap: 12 }}>\n <button type=\"button\" onClick={() => onPageChange(page - 1)} disabled={!canGoPrev} style={{ padding: '4px 10px' }}>\n Prev\n </button>\n <span>\n page {page} of {pageCount}\n </span>\n <button type=\"button\" onClick={() => onPageChange(page + 1)} disabled={!canGoNext} style={{ padding: '4px 10px' }}>\n Next\n </button>\n </nav>\n )\n}\nPagination.displayName = 'Pagination'\n\n// ---------------------------------------------------------------------------\n// FilterBar\n// ---------------------------------------------------------------------------\n\nexport interface FilterOption {\n value: string\n label: string\n}\n\nexport interface FilterDefinition {\n /** Stable identifier; also the React key for this filter's dropdown. */\n key: string\n /** Shown as the dropdown's placeholder/aria-label, and as its entry in the \"Add filter\" menu. */\n label: string\n options: FilterOption[]\n /** `null` (not `''`) represents \"no selection\" — the value FilterBar clears back to. */\n value: string | null\n onChange: (value: string | null) => void\n /** Always rendered when true. Omit/false to make this filter addable/removable via the \"Add filter\" menu. */\n alwaysVisible?: boolean\n}\n\nexport interface FilterBarSearchProps {\n value: string\n onChange: (value: string) => void\n placeholder?: string\n}\n\nexport interface FilterBarProps {\n filters: FilterDefinition[]\n /** Renders a SearchBox ahead of the filter dropdowns when provided. */\n search?: FilterBarSearchProps\n /**\n * Called by \"Clear all\" instead of FilterBar's own clearing logic. Omit it to let FilterBar\n * clear every filter with a value itself (`filter.onChange(null)` for each).\n */\n onClearAll?: () => void\n addFilterLabel?: string\n className?: string\n}\n\n/**\n * FilterBar — delegates to the platform's real FilterBar at render time: an optional\n * SearchBox, always-visible filter dropdowns, and optional filters the user can add/remove via\n * an \"Add filter\" menu (a filter with a non-null `value` is always treated as visible, even\n * before the user explicitly adds it). The fallback renders every filter as a plain,\n * always-visible native `<select>` — no add/remove menu, no styled search box — so an app page\n * under test still exposes every filter's full behavior via `onChange`.\n *\n * @example\n * <FilterBar\n * search={{ value: search, onChange: setSearch, placeholder: 'Search apps…' }}\n * filters={[\n * { key: 'vendor', label: 'Vendor', options: vendorOptions, value: vendor, onChange: setVendor, alwaysVisible: true },\n * { key: 'category', label: 'Category', options: categoryOptions, value: category, onChange: setCategory },\n * ]}\n * />\n */\nexport const FilterBar: React.FC<FilterBarProps> = (props) => {\n const HostFilterBar = getHostUi<React.FC<FilterBarProps>>('FilterBar')\n if (HostFilterBar) return <HostFilterBar {...props} />\n\n const { filters, search, className } = props\n return (\n <div className={className} style={{ ...fallbackNote, display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>\n {search && (\n <input\n type=\"search\"\n aria-label={search.placeholder ?? 'Search'}\n placeholder={search.placeholder}\n value={search.value}\n onChange={(event) => search.onChange(event.target.value)}\n style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af' }}\n />\n )}\n {filters.map((filter) => (\n <label key={filter.key} style={{ display: 'flex', flexDirection: 'column', fontSize: 12 }}>\n {filter.label}\n <select\n aria-label={filter.label}\n value={filter.value ?? ''}\n onChange={(event) => filter.onChange(event.target.value === '' ? null : event.target.value)}\n style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af' }}\n >\n <option value=\"\">{filter.label}</option>\n {filter.options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n ))}\n </div>\n )\n}\nFilterBar.displayName = 'FilterBar'\n\n// ---------------------------------------------------------------------------\n// SortSelect\n// ---------------------------------------------------------------------------\n\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface SortOption {\n value: string\n label: string\n}\n\nexport interface SortSelectProps {\n /** Sortable fields, e.g. `[{ value: 'name', label: 'Name' }, { value: 'updatedAt', label: 'Updated' }]`. */\n options: SortOption[]\n /** Selected field key. */\n value: string\n direction: SortDirection\n /** Called with the field and direction together, whichever one the interaction changed. */\n onChange: (value: string, direction: SortDirection) => void\n disabled?: boolean\n className?: string\n}\n\n/**\n * SortSelect — delegates to the platform's real SortSelect at render time: a labeled field\n * Select paired with an asc/desc direction toggle button, styled to sit in the same toolbar\n * row as FilterBar. The standalone sort control for list/card surfaces that aren't a\n * DataTable (which has its own column-header sort). The fallback is a native `<select>` for\n * the field plus a button that flips direction.\n *\n * @example\n * <SortSelect\n * options={[{ value: 'name', label: 'Name' }, { value: 'updatedAt', label: 'Last updated' }]}\n * value={sortField}\n * direction={sortDirection}\n * onChange={(field, direction) => { setSortField(field); setSortDirection(direction) }}\n * />\n */\nexport const SortSelect: React.FC<SortSelectProps> = (props) => {\n const HostSortSelect = getHostUi<React.FC<SortSelectProps>>('SortSelect')\n if (HostSortSelect) return <HostSortSelect {...props} />\n\n const { options, value, direction, onChange, disabled, className } = props\n const directionLabel = direction === 'asc' ? 'Sort ascending' : 'Sort descending'\n\n return (\n <div className={className} style={{ ...fallbackNote, display: 'flex', alignItems: 'center', gap: 6 }}>\n <select\n aria-label=\"Sort by\"\n value={value}\n disabled={disabled}\n onChange={(event) => onChange(event.target.value, direction)}\n style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af' }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n disabled={disabled}\n onClick={() => onChange(value, direction === 'asc' ? 'desc' : 'asc')}\n aria-label={directionLabel}\n style={{ padding: '4px 10px' }}\n >\n {direction === 'asc' ? '↑' : '↓'}\n </button>\n </div>\n )\n}\nSortSelect.displayName = 'SortSelect'\n\n// ---------------------------------------------------------------------------\n// FormField — generic label + control + error/hint wrapper\n// ---------------------------------------------------------------------------\n\nexport interface FormFieldProps {\n label?: string\n htmlFor?: string\n error?: string\n hint?: string\n required?: boolean\n className?: string\n children: React.ReactNode\n}\n\n/**\n * FormField — wraps a custom control (not already self-labeling like Input/Select) with\n * the platform's label + error/hint visual language.\n *\n * @example\n * <FormField label=\"Allowed IP ranges\" htmlFor=\"cidrs\" hint=\"One CIDR block per line\">\n * <textarea id=\"cidrs\" />\n * </FormField>\n */\nexport const FormField: React.FC<FormFieldProps> = (props) => {\n const HostFormField = getHostUi<React.FC<FormFieldProps>>('FormField')\n if (HostFormField) return <HostFormField {...props} />\n\n const { label, htmlFor, error, hint, required, className, children } = props\n return (\n <div className={className} style={fallbackNote}>\n {label && (\n <label htmlFor={htmlFor} style={{ display: 'block', fontSize: 13, fontWeight: 500, marginBottom: 4 }}>\n {label}\n {required && (\n <span aria-hidden=\"true\" style={{ color: '#dc2626', marginLeft: 2 }}>\n *\n </span>\n )}\n </label>\n )}\n {children}\n {error && (\n <p role=\"alert\" style={{ marginTop: 4, fontSize: 12, color: '#dc2626' }}>\n {error}\n </p>\n )}\n {hint && !error && <p style={{ marginTop: 4, fontSize: 12, color: '#6b7280' }}>{hint}</p>}\n </div>\n )\n}\nFormField.displayName = 'FormField'\n\n// ---------------------------------------------------------------------------\n// Tabs\n// ---------------------------------------------------------------------------\n\nexport interface TabItem {\n key?: string\n label: string\n content: React.ReactNode\n disabled?: boolean\n}\n\nexport interface TabsProps {\n tabs: TabItem[]\n defaultActiveIndex?: number\n activeIndex?: number\n onTabChange?: (index: number) => void\n children?: React.ReactNode\n className?: string\n}\n\n/**\n * Tabs — delegates to the platform's real (WAI-ARIA tabs pattern) Tabs at render time.\n *\n * @example\n * <Tabs tabs={[{ key: 'indexes', label: 'Indexes', content: <IndexesPanel /> }]} />\n */\nexport const Tabs: React.FC<TabsProps> = (props) => {\n const HostTabs = getHostUi<React.FC<TabsProps>>('Tabs')\n if (HostTabs) return <HostTabs {...props} />\n\n const { tabs, defaultActiveIndex = 0, activeIndex, onTabChange, children, className } = props\n const [internalIndex, setInternalIndex] = React.useState(defaultActiveIndex)\n const isControlled = activeIndex !== undefined\n const currentIndex = isControlled ? activeIndex : internalIndex\n const activeTab = tabs[currentIndex]\n\n const selectTab = (index: number) => {\n if (tabs[index]?.disabled) return\n if (!isControlled) setInternalIndex(index)\n onTabChange?.(index)\n }\n\n return (\n <div className={className} style={fallbackNote}>\n <div role=\"tablist\" style={{ display: 'flex', gap: 4, borderBottom: '1px solid #d1d5db' }}>\n {tabs.map((tab, index) => (\n <button\n key={tab.key ?? index}\n type=\"button\"\n role=\"tab\"\n aria-selected={index === currentIndex}\n disabled={tab.disabled}\n onClick={() => selectTab(index)}\n style={{\n padding: '6px 12px',\n border: 'none',\n borderBottom: index === currentIndex ? '2px solid currentColor' : '2px solid transparent',\n background: 'transparent',\n cursor: tab.disabled ? 'not-allowed' : 'pointer',\n fontWeight: index === currentIndex ? 600 : 400,\n opacity: tab.disabled ? 0.5 : 1,\n }}\n >\n {tab.label}\n </button>\n ))}\n </div>\n <div role=\"tabpanel\" style={{ padding: 12 }}>\n {children || activeTab?.content}\n </div>\n </div>\n )\n}\nTabs.displayName = 'Tabs'\n\n// ---------------------------------------------------------------------------\n// EmptyState\n// ---------------------------------------------------------------------------\n\nexport interface EmptyStateProps {\n icon?: React.ReactNode\n title: string\n description?: string\n action?: React.ReactNode\n className?: string\n}\n\n/** EmptyState — delegates to the platform's real EmptyState at render time. */\nexport const EmptyState: React.FC<EmptyStateProps> = (props) => {\n const HostEmptyState = getHostUi<React.FC<EmptyStateProps>>('EmptyState')\n if (HostEmptyState) return <HostEmptyState {...props} />\n\n const { icon, title, description, action, className } = props\n return (\n <div className={className} style={{ ...fallbackNote, textAlign: 'center', padding: '32px 16px' }}>\n {icon && <div style={{ marginBottom: 12 }}>{icon}</div>}\n <p style={{ fontWeight: 600, marginBottom: description ? 4 : 0 }}>{title}</p>\n {description && <p style={{ fontSize: 13, color: '#6b7280', marginBottom: action ? 12 : 0 }}>{description}</p>}\n {action}\n </div>\n )\n}\nEmptyState.displayName = 'EmptyState'\n\n// ---------------------------------------------------------------------------\n// Skeleton (+ Text/Card)\n// ---------------------------------------------------------------------------\n\nexport type SkeletonVariant = 'text' | 'circular' | 'rectangular'\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: SkeletonVariant\n width?: string | number\n height?: string | number\n animation?: 'pulse' | 'wave' | 'none'\n}\n\nconst skeletonRadius: Record<SkeletonVariant, number | string> = { text: 4, circular: '50%', rectangular: 8 }\n\n/** Skeleton — delegates to the platform's real Skeleton at render time. */\nexport const Skeleton: React.FC<SkeletonProps> = (props) => {\n const HostSkeleton = getHostUi<React.FC<SkeletonProps>>('Skeleton')\n if (HostSkeleton) return <HostSkeleton {...props} />\n\n const { variant = 'text', width, height, style, ...rest } = props\n return (\n <div\n aria-hidden=\"true\"\n style={{\n background: '#e5e7eb',\n borderRadius: skeletonRadius[variant],\n width: width ?? (variant === 'text' ? '100%' : undefined),\n height: height ?? (variant === 'text' ? 14 : undefined),\n ...style,\n }}\n {...rest}\n />\n )\n}\nSkeleton.displayName = 'Skeleton'\n\nexport interface SkeletonTextProps {\n lines?: number\n width?: string | number\n lastLineWidth?: string | number\n className?: string\n}\n\n/** SkeletonText — a multi-line text skeleton, delegating to the platform's real one. */\nexport const SkeletonText: React.FC<SkeletonTextProps> = (props) => {\n const HostSkeletonText = getHostUi<React.FC<SkeletonTextProps>>('SkeletonText')\n if (HostSkeletonText) return <HostSkeletonText {...props} />\n\n const { lines = 3, width = '100%', lastLineWidth = '80%', className } = props\n return (\n <div className={className} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {Array.from({ length: lines }).map((_, index) => (\n <Skeleton key={index} variant=\"text\" width={index === lines - 1 ? lastLineWidth : width} />\n ))}\n </div>\n )\n}\nSkeletonText.displayName = 'SkeletonText'\n\nexport interface SkeletonCardProps {\n hasAvatar?: boolean\n hasActions?: boolean\n className?: string\n}\n\n/** SkeletonCard — a card-shaped skeleton, delegating to the platform's real one. */\nexport const SkeletonCard: React.FC<SkeletonCardProps> = (props) => {\n const HostSkeletonCard = getHostUi<React.FC<SkeletonCardProps>>('SkeletonCard')\n if (HostSkeletonCard) return <HostSkeletonCard {...props} />\n\n const { hasAvatar, hasActions, className } = props\n return (\n <div className={className} style={{ border: '1px solid #e5e7eb', borderRadius: 8, padding: 16 }}>\n <div style={{ display: 'flex', gap: 12 }}>\n {hasAvatar && <Skeleton variant=\"circular\" width={40} height={40} />}\n <div style={{ flex: 1 }}>\n <Skeleton variant=\"text\" width=\"60%\" />\n <div style={{ marginTop: 8 }}>\n <SkeletonText lines={2} />\n </div>\n </div>\n </div>\n {hasActions && (\n <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>\n <Skeleton variant=\"rectangular\" width={72} height={30} />\n <Skeleton variant=\"rectangular\" width={72} height={30} />\n </div>\n )}\n </div>\n )\n}\nSkeletonCard.displayName = 'SkeletonCard'\n\n// ---------------------------------------------------------------------------\n// Tooltip\n// ---------------------------------------------------------------------------\n\nexport type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right'\n\nexport interface TooltipProps {\n content?: React.ReactNode\n placement?: TooltipPlacement\n delayDuration?: number\n disabled?: boolean\n className?: string\n children: React.ReactNode\n}\n\n/**\n * Tooltip — delegates to the platform's real Tooltip at render time. The fallback uses the\n * browser's native `title` attribute (only works when `content` is plain text).\n */\nexport const Tooltip: React.FC<TooltipProps> = (props) => {\n const HostTooltip = getHostUi<React.FC<TooltipProps>>('Tooltip')\n if (HostTooltip) return <HostTooltip {...props} />\n\n const { content, disabled, className, children } = props\n const titleText = typeof content === 'string' ? content : undefined\n if (disabled || !titleText) return <>{children}</>\n return (\n <span className={className} title={titleText} style={{ display: 'inline-flex' }}>\n {children}\n </span>\n )\n}\nTooltip.displayName = 'Tooltip'\n\n// ---------------------------------------------------------------------------\n// Spinner\n// ---------------------------------------------------------------------------\n\nexport type SpinnerSize = 'sm' | 'md' | 'lg'\n\nexport interface SpinnerProps {\n size?: SpinnerSize\n className?: string\n label?: string\n}\n\nconst spinnerDiameter: Record<SpinnerSize, number> = { sm: 16, md: 24, lg: 32 }\n\n/** Spinner — delegates to the platform's real Spinner at render time. */\nexport const Spinner: React.FC<SpinnerProps> = (props) => {\n const HostSpinner = getHostUi<React.FC<SpinnerProps>>('Spinner')\n if (HostSpinner) return <HostSpinner {...props} />\n\n const { size = 'md', className, label } = props\n const diameter = spinnerDiameter[size]\n return (\n <div className={className} role=\"status\" aria-live=\"polite\" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>\n <div\n aria-hidden=\"true\"\n style={{\n width: diameter,\n height: diameter,\n borderRadius: '50%',\n border: '2px solid currentColor',\n borderTopColor: 'transparent',\n animation: 'vx-sdk-spin 0.8s linear infinite',\n }}\n />\n {label && <p style={{ marginTop: 8, fontSize: 12, color: '#6b7280' }}>{label}</p>}\n <span style={{ position: 'absolute', width: 1, height: 1, overflow: 'hidden', clip: 'rect(0 0 0 0)' }}>{label || 'Loading'}</span>\n <style>{'@keyframes vx-sdk-spin { to { transform: rotate(360deg) } }'}</style>\n </div>\n )\n}\nSpinner.displayName = 'Spinner'\n\n// ---------------------------------------------------------------------------\n// DataTable (generic)\n// ---------------------------------------------------------------------------\n\nexport type DataTableAlign = 'left' | 'center' | 'right'\nexport type DataTableSortOrder = 'asc' | 'desc'\n\nexport interface DataTableSort {\n field: string\n order: DataTableSortOrder\n}\n\nexport interface DataTableColumn<T> {\n key: string\n header: React.ReactNode\n render?: (row: T) => React.ReactNode\n sortable?: boolean\n align?: DataTableAlign\n width?: string\n className?: string\n}\n\nexport interface DataTableEmptyState {\n icon?: React.ReactNode\n title: string\n description?: string\n action?: React.ReactNode\n}\n\nexport interface DataTablePaginationState {\n page: number\n pageSize: number\n total: number\n}\n\nexport interface DataTableProps<T> {\n columns: DataTableColumn<T>[]\n data: T[]\n rowKey: (row: T) => string\n isLoading?: boolean\n emptyState?: DataTableEmptyState\n sort?: DataTableSort\n onSortChange?: (sort: DataTableSort) => void\n pagination?: DataTablePaginationState\n onPageChange?: (page: number) => void\n onRowClick?: (row: T) => void\n rowActions?: (row: T) => React.ReactNode\n className?: string\n}\n\ntype DataTableComponent = (<T>(props: DataTableProps<T>) => React.ReactElement) & { displayName?: string }\n\nfunction FallbackDataTable<T>(props: DataTableProps<T>): React.ReactElement {\n const { columns, data, rowKey, isLoading, emptyState, onRowClick, rowActions, className } = props\n const showEmpty = !isLoading && data.length === 0\n\n return (\n <div className={className} style={fallbackNote}>\n <table style={{ width: '100%', borderCollapse: 'collapse' }}>\n <thead>\n <tr>\n {columns.map((column) => (\n <th key={column.key} style={{ textAlign: column.align ?? 'left', padding: '8px 10px', borderBottom: '1px solid #d1d5db' }}>\n {column.header}\n </th>\n ))}\n {rowActions && <th style={{ padding: '8px 10px', borderBottom: '1px solid #d1d5db' }} />}\n </tr>\n </thead>\n <tbody>\n {isLoading && (\n <tr>\n <td colSpan={Math.max(columns.length + (rowActions ? 1 : 0), 1)} style={{ padding: '12px 10px' }}>\n Loading…\n </td>\n </tr>\n )}\n {showEmpty && (\n <tr>\n <td colSpan={Math.max(columns.length + (rowActions ? 1 : 0), 1)}>\n <EmptyState title={emptyState?.title ?? 'No data'} description={emptyState?.description} icon={emptyState?.icon} action={emptyState?.action} />\n </td>\n </tr>\n )}\n {!isLoading &&\n !showEmpty &&\n data.map((row) => (\n <tr\n key={rowKey(row)}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n style={{ cursor: onRowClick ? 'pointer' : undefined, borderBottom: '1px solid #e5e7eb' }}\n >\n {columns.map((column) => (\n <td key={column.key} style={{ textAlign: column.align ?? 'left', padding: '8px 10px' }}>\n {column.render ? column.render(row) : String((row as Record<string, unknown>)[column.key] ?? '')}\n </td>\n ))}\n {rowActions && (\n <td style={{ padding: '8px 10px' }} onClick={(event) => event.stopPropagation()}>\n {rowActions(row)}\n </td>\n )}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * DataTable — delegates to the platform's real, server-driven DataTable at render time.\n *\n * @example\n * <DataTable\n * columns={[{ key: 'name', header: 'Name' }, { key: 'deployState', header: 'Status', render: (r) => <Badge>{r.deployState}</Badge> }]}\n * data={indexes}\n * rowKey={(row) => row.id}\n * />\n */\nexport function DataTable<T>(props: DataTableProps<T>): React.ReactElement {\n const HostDataTable = getHostUi<DataTableComponent>('DataTable')\n if (HostDataTable) return <HostDataTable {...props} />\n return <FallbackDataTable {...props} />\n}\n\n// ---------------------------------------------------------------------------\n// StatsCard\n// ---------------------------------------------------------------------------\n\nexport type StatsCardVariant = 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'\n\nexport interface StatsCardDelta {\n value: string\n direction: 'up' | 'down' | 'neutral'\n label?: string\n}\n\nexport interface StatsCardProps {\n label: string\n value: React.ReactNode\n icon?: React.ReactNode\n delta?: StatsCardDelta\n variant?: StatsCardVariant\n isLoading?: boolean\n onClick?: () => void\n className?: string\n}\n\nconst DELTA_FALLBACK_COLOR: Record<StatsCardDelta['direction'], string> = {\n up: '#16a34a',\n down: '#dc2626',\n neutral: '#6b7280',\n}\n\n/**\n * StatsCard — delegates to the platform's real StatsCard at render time.\n *\n * @example\n * <StatsCard label=\"Indexes\" value={indexes.length} delta={{ value: '+2', direction: 'up' }} />\n */\nexport const StatsCard: React.FC<StatsCardProps> = (props) => {\n const HostStatsCard = getHostUi<React.FC<StatsCardProps>>('StatsCard')\n if (HostStatsCard) return <HostStatsCard {...props} />\n\n const { label, value, icon, delta, isLoading, onClick, className } = props\n const isClickable = Boolean(onClick)\n\n return (\n <div\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n onClick={onClick}\n onKeyDown={\n isClickable\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onClick?.()\n }\n }\n : undefined\n }\n className={className}\n style={{\n ...fallbackNote,\n border: '1px solid #d1d5db',\n borderRadius: 8,\n padding: 16,\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 12,\n cursor: isClickable ? 'pointer' : undefined,\n }}\n >\n <div style={{ minWidth: 0, flex: 1 }}>\n <p style={{ fontSize: 13, color: '#6b7280', margin: 0 }}>{label}</p>\n <p style={{ fontSize: 28, fontWeight: 700, margin: '4px 0 0' }}>{isLoading ? '…' : value}</p>\n {delta && !isLoading && (\n <p style={{ fontSize: 13, color: DELTA_FALLBACK_COLOR[delta.direction], margin: '4px 0 0' }}>\n {delta.value} {delta.label}\n </p>\n )}\n </div>\n {icon && <div aria-hidden=\"true\">{icon}</div>}\n </div>\n )\n}\nStatsCard.displayName = 'StatsCard'\n\n// ---------------------------------------------------------------------------\n// FormDialog\n// ---------------------------------------------------------------------------\n\nexport type FormDialogSize = 'sm' | 'md' | 'lg'\n\nexport interface FormDialogProps {\n isOpen: boolean\n onClose: () => void\n title: string\n description?: string\n children: React.ReactNode\n onSubmit: () => void | Promise<void>\n submitText?: string\n cancelText?: string\n isSubmitting?: boolean\n error?: string | null\n size?: FormDialogSize\n disableBackdropClose?: boolean\n submitDisabled?: boolean\n}\n\nconst FORM_DIALOG_MAX_WIDTH: Record<FormDialogSize, number> = { sm: 420, md: 520, lg: 680 }\n\n/**\n * FormDialog — delegates to the platform's real FormDialog at render time. The fallback is\n * a minimal, accessible modal shell (role=\"dialog\", Escape-to-close, backdrop click) without\n * the host's focus-trap polish.\n *\n * @example\n * <FormDialog isOpen={isOpen} onClose={close} title=\"Add index\" onSubmit={handleSubmit}>\n * <Input label=\"Name\" value={name} onChange={(e) => setName(e.target.value)} />\n * </FormDialog>\n */\nexport const FormDialog: React.FC<FormDialogProps> = (props) => {\n const HostFormDialog = getHostUi<React.FC<FormDialogProps>>('FormDialog')\n if (HostFormDialog) return <HostFormDialog {...props} />\n\n const {\n isOpen,\n onClose,\n title,\n description,\n children,\n onSubmit,\n submitText = 'Save',\n cancelText = 'Cancel',\n isSubmitting = false,\n error = null,\n size = 'md',\n disableBackdropClose = false,\n submitDisabled = false,\n } = props\n\n React.useEffect(() => {\n if (!isOpen) return\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !isSubmitting) onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, isSubmitting, onClose])\n\n if (!isOpen) return null\n\n const requestClose = () => {\n if (!isSubmitting) onClose()\n }\n\n return (\n <div\n style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 50 }}\n onClick={disableBackdropClose ? undefined : requestClose}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n style={{ background: 'white', color: 'black', borderRadius: 8, width: '100%', maxWidth: FORM_DIALOG_MAX_WIDTH[size], maxHeight: '80vh', overflow: 'auto', ...fallbackNote }}\n onClick={(event) => event.stopPropagation()}\n >\n <form\n onSubmit={(event) => {\n event.preventDefault()\n void onSubmit()\n }}\n >\n <div style={{ padding: 16, borderBottom: '1px solid #d1d5db' }}>\n <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{title}</h3>\n {description && <p style={{ margin: '4px 0 0', fontSize: 13, color: '#6b7280' }}>{description}</p>}\n </div>\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>\n {error && (\n <p role=\"alert\" style={{ margin: 0, fontSize: 13, color: '#dc2626' }}>\n {error}\n </p>\n )}\n {children}\n </div>\n <div style={{ padding: 16, borderTop: '1px solid #d1d5db', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>\n <Button type=\"button\" variant=\"secondary\" onClick={requestClose} disabled={isSubmitting}>\n {cancelText}\n </Button>\n <Button type=\"submit\" variant=\"primary\" isLoading={isSubmitting} disabled={submitDisabled}>\n {submitText}\n </Button>\n </div>\n </form>\n </div>\n </div>\n )\n}\nFormDialog.displayName = 'FormDialog'\n\n// ---------------------------------------------------------------------------\n// Modal\n// ---------------------------------------------------------------------------\n\nexport type ModalSize = 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface ModalProps {\n /** Controls visibility. Renders nothing when `false`. */\n isOpen: boolean\n /** Called on backdrop click (unless disabled), Escape, and the X button. */\n onClose: () => void\n /** Heading rendered at the top of the modal. */\n title?: React.ReactNode\n /** Secondary line rendered under the title. */\n subtitle?: React.ReactNode\n /** Modal body. */\n children: React.ReactNode\n /** Optional footer content (e.g. action buttons), rendered in a tinted bar. */\n footer?: React.ReactNode\n size?: ModalSize\n /** When true, clicking the backdrop no longer closes the modal. */\n disableBackdropClose?: boolean\n /** When true, Escape no longer closes the modal. */\n disableEscapeClose?: boolean\n /** Hide the top-right close (X) button. */\n hideCloseButton?: boolean\n /** Accessible label for the close button. Defaults to \"Close\". */\n closeLabel?: string\n className?: string\n}\n\nconst MODAL_MAX_WIDTH: Record<ModalSize, number> = { sm: 420, md: 520, lg: 680, xl: 896 }\n\n/**\n * Modal — delegates to the platform's real Modal at render time: a coordinated\n * overlay shell with a `title` + `subtitle` header, a scrollable body, and an\n * optional `footer` action bar. The general-purpose sibling of {@link FormDialog}\n * (form) and the confirm dialog (yes/no) — use it for detail/wizard/picker\n * overlays. Selects and other popovers rendered inside it float above the body,\n * so their menus are never clipped. The fallback is a minimal, accessible,\n * non-throwing shell for local dev / tests.\n *\n * @example\n * <Modal isOpen={open} onClose={close} title=\"Choose a region\" subtitle=\"Where should this live?\"\n * footer={<Button onClick={close}>Done</Button>}>\n * <Select label=\"Region\" options={regions} value={region} onChange={setRegion} />\n * </Modal>\n */\nexport const Modal: React.FC<ModalProps> = (props) => {\n const HostModal = getHostUi<React.FC<ModalProps>>('Modal')\n if (HostModal) return <HostModal {...props} />\n\n const {\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n footer,\n size = 'md',\n disableBackdropClose = false,\n disableEscapeClose = false,\n hideCloseButton = false,\n closeLabel = 'Close',\n className,\n } = props\n\n React.useEffect(() => {\n if (!isOpen) return\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !disableEscapeClose) onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, disableEscapeClose, onClose])\n\n if (!isOpen) return null\n\n const hasHeader = title != null || subtitle != null || !hideCloseButton\n\n return (\n <div\n style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 50 }}\n onClick={disableBackdropClose ? undefined : onClose}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n style={{ background: 'white', color: 'black', borderRadius: 8, width: '100%', maxWidth: MODAL_MAX_WIDTH[size], maxHeight: '80vh', overflow: 'auto', ...fallbackNote }}\n className={className}\n onClick={(event) => event.stopPropagation()}\n >\n {hasHeader && (\n <div style={{ padding: 16, borderBottom: '1px solid #d1d5db', display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16 }}>\n <div style={{ minWidth: 0 }}>\n {title != null && <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{title}</h3>}\n {subtitle != null && <p style={{ margin: '4px 0 0', fontSize: 13, color: '#6b7280' }}>{subtitle}</p>}\n </div>\n {!hideCloseButton && (\n <button type=\"button\" onClick={onClose} aria-label={closeLabel} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 18, lineHeight: 1 }}>\n ×\n </button>\n )}\n </div>\n )}\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>{children}</div>\n {footer != null && (\n <div style={{ padding: 16, borderTop: '1px solid #d1d5db', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>{footer}</div>\n )}\n </div>\n </div>\n )\n}\nModal.displayName = 'Modal'\n\n// ---------------------------------------------------------------------------\n// Alert\n// ---------------------------------------------------------------------------\n\nexport type AlertVariant = 'info' | 'success' | 'warning' | 'danger'\n\nexport interface AlertProps {\n /** Severity — drives color and default icon. Defaults to `info`. */\n variant?: AlertVariant\n /** Optional bold heading above the message. */\n title?: React.ReactNode\n /** The message body. */\n children?: React.ReactNode\n /** Override the default icon, or pass `false` to hide it. */\n icon?: React.ReactNode | false\n /** When provided, renders a dismiss (X) button that calls this. */\n onDismiss?: () => void\n /** Optional trailing action (e.g. a link or button). */\n action?: React.ReactNode\n className?: string\n}\n\nconst ALERT_FALLBACK_COLORS: Record<AlertVariant, { bg: string; fg: string; border: string }> = {\n info: { bg: '#eff6ff', fg: '#1e40af', border: '#93c5fd' },\n success: { bg: '#ecfdf5', fg: '#065f46', border: '#6ee7b7' },\n warning: { bg: '#fffbeb', fg: '#92400e', border: '#fcd34d' },\n danger: { bg: '#fef2f2', fg: '#991b1b', border: '#fca5a5' },\n}\n\n/**\n * Alert — delegates to the platform's real Alert at render time: an inline,\n * static severity banner for warnings, errors, tips and success notices in the\n * page/form body. For transient pop-up notifications use {@link useToast}\n * instead (its `variant` supports the same `warning`/`error`/`success`/`info`).\n * The fallback is a minimal, accessible colored banner for local dev / tests.\n *\n * @example\n * <Alert variant=\"warning\" title=\"Heads up\">\n * Distributed deployments need at least 3 indexers.\n * </Alert>\n */\nexport const Alert: React.FC<AlertProps> = (props) => {\n const HostAlert = getHostUi<React.FC<AlertProps>>('Alert')\n if (HostAlert) return <HostAlert {...props} />\n\n const { variant = 'info', title, children, icon, onDismiss, action, className } = props\n const c = ALERT_FALLBACK_COLORS[variant]\n const role = variant === 'danger' || variant === 'warning' ? 'alert' : 'status'\n\n return (\n <div\n role={role}\n className={className}\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n gap: 10,\n border: `1px solid ${c.border}`,\n background: c.bg,\n color: c.fg,\n borderRadius: 8,\n padding: '12px 16px',\n ...fallbackNote,\n }}\n >\n {icon !== false && icon != null && <span style={{ flexShrink: 0 }}>{icon}</span>}\n <div style={{ minWidth: 0, flex: 1 }}>\n {title != null && <p style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>{title}</p>}\n {children != null && (\n <div style={{ fontSize: 14, marginTop: title != null ? 2 : 0 }}>{children}</div>\n )}\n </div>\n {action != null && <div style={{ flexShrink: 0 }}>{action}</div>}\n {onDismiss && (\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n style={{ flexShrink: 0, background: 'none', border: 'none', cursor: 'pointer', color: 'inherit', opacity: 0.7 }}\n >\n ×\n </button>\n )}\n </div>\n )\n}\nAlert.displayName = 'Alert'\n\n// ---------------------------------------------------------------------------\n// MultiSelect\n// ---------------------------------------------------------------------------\n\nexport type MultiSelectSize = 'sm' | 'md' | 'lg'\n\nexport interface MultiSelectOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface MultiSelectProps {\n options: MultiSelectOption[]\n /** Currently selected values. */\n value?: string[]\n /** Called with the new list of selected values. */\n onChange?: (values: string[]) => void\n placeholder?: string\n label?: string\n error?: string\n helperText?: string\n size?: MultiSelectSize\n disabled?: boolean\n fullWidth?: boolean\n /** Show a filter box inside the dropdown. Defaults to true. */\n searchable?: boolean\n /** How many chips to show in the trigger before \"+N more\". Defaults to 3. */\n maxTagCount?: number\n className?: string\n name?: string\n 'aria-label'?: string\n}\n\n/**\n * MultiSelect — delegates to the platform's real searchable multi-selection\n * dropdown at render time (selected values as removable chips, a filter box,\n * select-all / clear). The fallback is a native `<select multiple>` for local\n * dev / tests. Use for any multi-value picker (environments, tags, targets…).\n *\n * @example\n * <MultiSelect label=\"Environments\" value={ids} onChange={setIds}\n * options={envs.map(e => ({ value: e.id, label: e.name }))} />\n */\nexport const MultiSelect: React.FC<MultiSelectProps> = (props) => {\n const HostMultiSelect = getHostUi<React.FC<MultiSelectProps>>('MultiSelect')\n if (HostMultiSelect) return <HostMultiSelect {...props} />\n\n const { options, value = [], onChange, label, disabled, fullWidth = true, name } = props\n return (\n <label style={{ ...fallbackNote, display: 'block', width: fullWidth ? '100%' : undefined }}>\n {label && <span style={{ display: 'block', marginBottom: 4, fontSize: 14, fontWeight: 500 }}>{label}</span>}\n <select\n multiple\n name={name}\n disabled={disabled}\n value={value}\n aria-label={props['aria-label']}\n onChange={(e) => onChange?.(Array.from(e.target.selectedOptions, (o) => o.value))}\n style={{ width: '100%', minHeight: 96, padding: '6px 10px', borderRadius: 6, border: '1px solid #9ca3af' }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n )\n}\nMultiSelect.displayName = 'MultiSelect'\n\n\n//\n// Unlike the components above, these are HOOKS the host backs with real React\n// context (ToastContext / ConfirmationDialogContext), whose providers the\n// platform's root App.tsx mounts around the entire tree — including app\n// pages, since they render inside the host's own React instance. So inside\n// Veltrix these resolve to the real, working implementation with no extra\n// wiring. Outside the platform (no host, or an older host) they degrade to a\n// safe, non-throwing fallback instead of crashing: `toast()` logs to the\n// console and `confirm()` resolves to `false` (fails closed — no destructive\n// action proceeds without an explicit user confirmation the fallback cannot\n// provide).\n// ---------------------------------------------------------------------------\n\nexport type ToastVariant = 'success' | 'error' | 'warning' | 'info'\n\nexport interface ToastOptions {\n variant?: ToastVariant\n duration?: number\n action?: { label: string; onClick: () => void }\n}\n\nexport interface Toast {\n id: string\n message: string\n variant: ToastVariant\n duration?: number\n action?: { label: string; onClick: () => void }\n}\n\nexport interface ToastContextValue {\n toasts: Toast[]\n toast: (message: string, options?: ToastOptions) => string\n success: (message: string, duration?: number) => string\n error: (message: string, duration?: number) => string\n warning: (message: string, duration?: number) => string\n info: (message: string, duration?: number) => string\n promise: <T>(\n promise: Promise<T>,\n messages: { loading: string; success: string | ((data: T) => string); error: string | ((error: unknown) => string) },\n ) => Promise<T>\n dismiss: (id: string) => void\n dismissAll: () => void\n}\n\nfunction fallbackToast(message: string, options?: ToastOptions): string {\n // eslint-disable-next-line no-console -- deliberate: this IS the fallback surface.\n console.warn(`[@veltrixsecops/app-sdk/ui] Toast (${options?.variant ?? 'info'}): ${message}`)\n return 'fallback-toast'\n}\n\nconst fallbackToastContext: ToastContextValue = {\n toasts: [],\n toast: fallbackToast,\n success: (message) => fallbackToast(message, { variant: 'success' }),\n error: (message) => fallbackToast(message, { variant: 'error' }),\n warning: (message) => fallbackToast(message, { variant: 'warning' }),\n info: (message) => fallbackToast(message, { variant: 'info' }),\n promise: (promise) => promise,\n dismiss: () => {},\n dismissAll: () => {},\n}\n\n/**\n * useToast — delegates to the platform's real toast system when running inside Veltrix.\n * Outside it, `toast()`/`success()`/etc. log to the console instead of throwing.\n *\n * @example\n * const toast = useToast()\n * toast.success('Index saved')\n */\nexport function useToast(): ToastContextValue {\n const hostUseToast = getHostUi<() => ToastContextValue>('useToast')\n // eslint-disable-next-line react-hooks/rules-of-hooks -- `hostUseToast` IS the real hook;\n // its presence is fixed for the app's lifetime (the host runtime installs once at boot),\n // so this never actually violates the \"same hooks every render\" invariant in practice.\n if (hostUseToast) return hostUseToast()\n return fallbackToastContext\n}\n\nexport type ConfirmationVariant = 'danger' | 'warning' | 'info'\n\nexport interface ConfirmationOptions {\n title: string\n message: string\n confirmText?: string\n cancelText?: string\n variant?: ConfirmationVariant\n}\n\nexport interface ConfirmationDialogContextValue {\n confirm: (options: ConfirmationOptions) => Promise<boolean>\n}\n\nconst fallbackConfirmationContext: ConfirmationDialogContextValue = {\n confirm: (options) => {\n // eslint-disable-next-line no-console -- deliberate: this IS the fallback surface.\n console.warn(\n `[@veltrixsecops/app-sdk/ui] ConfirmationDialog is only available inside the Veltrix platform — ` +\n `\"${options.title}\" auto-resolved to \"not confirmed\" (fail closed).`,\n )\n return Promise.resolve(false)\n },\n}\n\n/**\n * useConfirmDialog — delegates to the platform's real confirmation dialog when running\n * inside Veltrix. Outside it, `confirm()` resolves to `false` (fails closed) rather than\n * throwing, so a guarded destructive action simply never proceeds instead of crashing.\n *\n * @example\n * const { confirm } = useConfirmDialog()\n * if (await confirm({ title: 'Delete index', message: 'This cannot be undone.', variant: 'danger' })) {\n * await deleteIndex(id)\n * }\n */\nexport function useConfirmDialog(): ConfirmationDialogContextValue {\n const hostUseConfirmDialog = getHostUi<() => ConfirmationDialogContextValue>('useConfirmDialog')\n // eslint-disable-next-line react-hooks/rules-of-hooks -- see useToast's note above.\n if (hostUseConfirmDialog) return hostUseConfirmDialog()\n return fallbackConfirmationContext\n}\n","// =============================================================================\n// Shared types for the BYOL infrastructure manager + detail view.\n// =============================================================================\n\n/** A region association satellite row (indexer / search-head placement). */\nexport interface ByolRegion {\n id: string\n region: string\n}\n\n/**\n * Control-plane consolidation layout. Trades HA/isolation for cost by combining\n * management roles onto fewer instances:\n * - `dedicated` — 5 instances, one role each (LM, CM, SH-deployer, DS, MC).\n * - `consolidated`— ~3 instances; CM and SH-deployer stay isolated, the rest combine.\n * - `single` — 1 manager node running every management role (small / non-HA).\n * Applies to distributed deployments; single-instance deployments ignore it.\n */\nexport type ControlPlaneLayout = 'dedicated' | 'consolidated' | 'single'\n\n/** How a cluster's sites are addressed: availability zones (same region) or regions. */\nexport type PlacementGranularity = 'az' | 'region'\n\n/** One placement target with its share of the cluster's nodes. */\nexport interface PlacementSite {\n /** AZ id (e.g. `us-east-1a`) when granularity is `az`, or a region code (e.g. `us-west-2`) when `region`. */\n site: string\n /** Percent of the cluster's nodes placed on this site. Percents across a cluster's sites sum to 100. */\n percent: number\n}\n\n/**\n * Placement of a single cluster tier. `single` keeps every node in the standard\n * main region/zone; `multi-site` spreads nodes across `sites` by percent.\n * ONLY the indexer and search-head tiers accept multi-site placement — every\n * other tier is always single-site in the main region.\n */\nexport interface ClusterPlacement {\n mode: 'single' | 'multi-site'\n granularity?: PlacementGranularity\n sites?: PlacementSite[]\n}\n\n/** Default single-site placement (all nodes in the main region). */\nexport const SINGLE_SITE_PLACEMENT: ClusterPlacement = { mode: 'single' }\n\n/** Minimum heavy forwarders in a distributed ingest tier. */\nexport const MIN_HEAVY_FORWARDERS = 1\n\nexport interface ByolInfrastructure {\n id: string\n name: string\n deploymentType?: string\n environmentType?: string\n indexerCount?: number\n searchHeadCount?: number\n status?: string\n hosting_type?: string\n cloudProviderId?: string | null\n region?: string | null\n indexerRegions?: ByolRegion[]\n searchHeadRegions?: ByolRegion[]\n /** Deployment target: platform-hosted network, or a customer-owned VPC. Defaults to 'shared'. */\n networkMode?: 'shared' | 'dedicated' | 'existing' | string\n /** DNS strategy for the deployment. Defaults to 'managed'. */\n dnsMode?: 'managed' | 'delegated' | 'private-only' | string\n /** Platform cloud account connection backing a BYOC (dedicated/existing) deployment. */\n cloudAccountConnectionId?: string | null\n /** Control-plane consolidation layout (distributed only). Defaults to 'dedicated'. */\n controlPlaneLayout?: ControlPlaneLayout\n /** Heavy forwarder count in the ingest tier (distributed only). Defaults to 1. */\n heavyForwarderCount?: number\n /** Compute size override for every node (e.g. AWS `t2.medium`); empty = cloud default. */\n instanceType?: string | null\n /** Placement of the indexer cluster — single-site or multi-site by percent. */\n indexerPlacement?: ClusterPlacement\n /** Placement of the search-head cluster — single-site or multi-site by percent. */\n searchHeadPlacement?: ClusterPlacement\n /** Selected software version (app catalog entry id) to install on every node. */\n versionId?: string\n updatedAt?: string\n createdAt?: string\n}\n\n/** A persisted resource row (from GET /byol/:id/resources). */\nexport interface ByolResource {\n id: string\n infrastructureId: string\n tier: string\n kind: string\n name: string\n role: string | null\n region: string | null\n /** Availability zone within `region` for a multi-AZ-placed node; null otherwise. */\n zone?: string | null\n /** Management roles a consolidated control-plane instance runs; null otherwise. */\n roles?: string[] | null\n status: string\n externalRef: string | null\n message: string | null\n planKey: string\n sortOrder: number\n}\n\n/** A deployment step (from GET /byol/:id/deployments → steps). */\nexport interface ByolDeploymentStep {\n id: string\n deploymentId: string\n stepOrder: number\n key: string\n title: string\n status: string\n detail: string | null\n logs: string | null\n startedAt: string | null\n completedAt: string | null\n}\n\n/** A deployment run (from GET /byol/:id/deployments). */\nexport interface ByolDeployment {\n id: string\n infrastructureId: string\n action: string\n status: string\n message: string | null\n startedAt: string\n completedAt: string | null\n steps: ByolDeploymentStep[]\n}\n\n/** Platform tag — the customer's environment tags feed the Environment picker. */\nexport interface Tag {\n id: string\n name: string\n}\n\n/** Platform cloud provider — feeds the \"Provider\" picker (plus Self-Hosted). */\nexport interface CloudProvider {\n id: string\n name: string\n code?: string\n isActive?: boolean\n}\n\nexport interface CloudRegion {\n id: string\n name: string\n code: string\n isActive?: boolean\n}\n\n/**\n * Platform cloud account connection — feeds the \"Cloud account\" picker shown\n * for BYOC (dedicated/existing network) deployment targets. Sourced from\n * `GET /api/cloud-accounts`. Only `VERIFIED` accounts matching the selected\n * cloud provider are offered.\n */\nexport interface CloudAccount {\n id: string\n provider: 'aws' | 'azure' | 'gcp' | 'hetzner' | string\n name: string\n status: 'UNVERIFIED' | 'VERIFIED' | 'ERROR' | string\n authMethod?: string\n /**\n * 'customer' — the tenant's own account (BYOC / dedicated / existing).\n * 'platform' — a Veltrix-managed account a hosted (shared) deployment provisions\n * through. The form offers platform accounts for hosted, customer accounts for BYOC.\n */\n scope?: 'customer' | 'platform' | string\n}\n\nexport interface FormState {\n name: string\n deploymentType: string\n environmentType: string\n /** A cloud provider id, or the SELF_HOSTED sentinel. */\n providerId: string\n region: string\n indexerCount: string\n searchHeadCount: string\n /** Deployment target: 'shared' (Veltrix-hosted), 'dedicated', or 'existing' (BYOC). */\n networkMode: string\n /** DNS strategy: 'managed', 'delegated', or 'private-only'. */\n dnsMode: string\n /** Platform cloud account connection id, required when networkMode is BYOC. */\n cloudAccountConnectionId: string\n /** Control-plane consolidation layout (distributed only). */\n controlPlaneLayout: ControlPlaneLayout\n /** Heavy forwarder count as a form string (distributed only, min 1). */\n heavyForwarderCount: string\n /** Compute size override for every node; empty = cloud default (t2.medium-class). */\n instanceType: string\n /** Placement of the indexer cluster. */\n indexerPlacement: ClusterPlacement\n /** Placement of the search-head cluster. */\n searchHeadPlacement: ClusterPlacement\n /** Selected software version (app catalog entry id); empty = app-default. */\n versionId: string\n}\n\n/**\n * A link surfaced in the detail view's Configuration section. The app supplies\n * these (the SDK stays app-agnostic). When `configTypeId` + `configBase` are\n * present the link resolves to `<configBase>/<configTypeId>`; otherwise `href`\n * is used verbatim.\n */\nexport interface ByolConfigLink {\n key: string\n title: string\n description: string\n configTypeId?: string\n href?: string\n}\n\nexport interface ByolInfrastructureManagerProps {\n /** Base URL of the app's BYOL routes, e.g. `/api/apps/splunk-enterprise/byol`. */\n apiBase: string\n /** Card title. Defaults to \"BYOL Infrastructure\". */\n title?: string\n /** Deployment topology options. Defaults to Single instance + Distributed. */\n deploymentTypes?: Array<{ value: string; label: string }>\n /**\n * Optional base path to this app's configuration canvases, e.g.\n * `/apps/splunk-enterprise/config`. Combined with each link's `configTypeId`\n * to deep-link the detail view's Configuration section.\n */\n configBase?: string\n /** Configuration links to surface in the detail view (app-supplied). */\n configLinks?: ByolConfigLink[]\n /**\n * Software version options for the \"Splunk version\" form picker (app-supplied —\n * the SDK has no notion of Splunk). Omit or pass an empty array to hide the\n * picker entirely (e.g. an app with no version catalog).\n */\n versionOptions?: Array<{ value: string; label: string }>\n /**\n * Version id a NEW infrastructure's form should default to (typically the\n * catalog's \"latest\" entry). Ignored when `versionOptions` is empty. Existing\n * rows always reflect their own stored `versionId`, never this default.\n */\n defaultVersionId?: string\n}\n\n// --- Constants --------------------------------------------------------------\n\n/** Sentinel provider value for a customer-managed (non-cloud) deployment. */\nexport const SELF_HOSTED = 'self-hosted'\nexport const SELF_HOSTED_LABEL = 'Self-Hosted'\n\nexport const DEFAULT_DEPLOYMENT_TYPES = [\n { value: 'single', label: 'Single instance' },\n { value: 'distributed', label: 'Distributed' },\n]\n\n/**\n * Network mode options for the \"Deployment target\" form section. Dedicated is listed\n * first because it is the default: OpenTofu provisions a self-contained VPC. 'shared'\n * requires a platform-managed base network to attach to (not yet provisioned), so it\n * is offered but not the default.\n */\nexport const NETWORK_MODE_OPTIONS = [\n { value: 'dedicated', label: 'Dedicated — your cloud (BYOC)' },\n { value: 'existing', label: 'Existing network — your cloud (BYOC)' },\n { value: 'shared', label: 'Veltrix-hosted (shared)' },\n]\n\n/** DNS mode options for the \"Deployment target\" form section. */\nexport const DNS_MODE_OPTIONS = [\n { value: 'managed', label: 'Managed' },\n { value: 'delegated', label: 'Delegated' },\n { value: 'private-only', label: 'Private only' },\n]\n\n/** Network modes that require a customer-owned (BYOC) cloud account connection. */\nexport const BYOC_NETWORK_MODES = new Set(['dedicated', 'existing'])\n\n/** Control-plane consolidation options for the \"Control plane\" form section. */\nexport const CONTROL_PLANE_LAYOUT_OPTIONS: Array<{\n value: ControlPlaneLayout\n label: string\n description: string\n}> = [\n { value: 'dedicated', label: 'Dedicated', description: '5 servers — one management role each (highest isolation).' },\n { value: 'consolidated', label: 'Consolidated', description: '~3 servers — cluster manager and SH deployer isolated, rest combined.' },\n { value: 'single', label: 'Single node', description: '1 server running every management role (lowest cost, non-HA).' },\n]\n\n/** Placement granularity options for a cluster's \"Placement\" form section. */\nexport const PLACEMENT_GRANULARITY_OPTIONS: Array<{ value: PlacementGranularity; label: string }> = [\n { value: 'az', label: 'Availability zones (same region)' },\n { value: 'region', label: 'Regions (multi-region)' },\n]\n\n/**\n * Map a persisted infrastructure record back into the editable form state, so\n * \"Edit topology\" renders the accurate current values (placement, consolidation,\n * forwarders, instance size, network target, …). Missing fields fall back to the\n * same defaults a new form uses, so a legacy row (created before these fields\n * existed) opens cleanly. Pure — safe to unit test.\n */\nexport function editFormState(row: ByolInfrastructure): FormState {\n const providerId = row.cloudProviderId\n ? row.cloudProviderId\n : row.hosting_type === SELF_HOSTED_LABEL\n ? SELF_HOSTED\n : ''\n return {\n name: row.name ?? '',\n deploymentType: row.deploymentType ?? 'single',\n environmentType: row.environmentType ?? '',\n providerId,\n region: row.region ?? '',\n indexerCount: String(row.indexerCount ?? 1),\n searchHeadCount: String(row.searchHeadCount ?? 1),\n networkMode: row.networkMode ?? 'shared',\n dnsMode: row.dnsMode ?? 'managed',\n cloudAccountConnectionId: row.cloudAccountConnectionId ?? '',\n controlPlaneLayout: row.controlPlaneLayout ?? 'dedicated',\n heavyForwarderCount: String(row.heavyForwarderCount ?? 1),\n instanceType: row.instanceType ?? '',\n indexerPlacement: row.indexerPlacement ?? { mode: 'single' },\n searchHeadPlacement: row.searchHeadPlacement ?? { mode: 'single' },\n versionId: row.versionId ?? '',\n }\n}\n\nexport const BLANK_FORM: FormState = {\n name: '',\n deploymentType: 'single',\n environmentType: '',\n providerId: '',\n region: '',\n indexerCount: '1',\n searchHeadCount: '1',\n // New cloud infra defaults to 'dedicated' — OpenTofu creates its own VPC and the\n // deployment depends on nothing pre-existing. 'shared' attaches to a Veltrix-managed\n // base network that must be provisioned by a separate platform tofu stack; until that\n // stack exists, defaulting to 'shared' produces \"no matching VPC\" at apply time.\n networkMode: 'dedicated',\n dnsMode: 'managed',\n cloudAccountConnectionId: '',\n controlPlaneLayout: 'dedicated',\n heavyForwarderCount: '1',\n instanceType: '',\n indexerPlacement: { mode: 'single' },\n searchHeadPlacement: { mode: 'single' },\n versionId: '',\n}\n\n/**\n * Example compute sizes per cloud (~2 vCPU / 4 GB), shown as form guidance. An\n * empty instanceType uses the module default, which is the first of each here.\n */\nexport const INSTANCE_TYPE_EXAMPLES: Record<string, string> = {\n aws: 't2.medium',\n azure: 'Standard_B2s',\n gcp: 'e2-medium',\n hetzner: 'cx22',\n}\n","// =============================================================================\n// BYOL infrastructure status model — the single place the lifecycle states, their\n// human labels, and their Badge variants are defined. Shared by the list and the\n// detail view so a status renders identically everywhere.\n//\n// Lifecycle: not_started → provisioning → running, with degraded / stopped /\n// failed / destroying as off-happy-path states. `active`/`error` are legacy\n// synonyms emitted by the provisioning hooks (onEvent/onWebhook) and mapped here\n// so old and new values render consistently.\n// =============================================================================\n\nimport type { BadgeVariant } from '../ui'\n\nexport type ByolInfraStatus =\n | 'not_started'\n | 'provisioning'\n | 'running'\n | 'active'\n | 'degraded'\n | 'stopped'\n | 'failed'\n | 'error'\n | 'destroying'\n\nconst VARIANTS: Record<string, BadgeVariant> = {\n not_started: 'default',\n provisioning: 'info',\n running: 'success',\n active: 'success',\n degraded: 'warning',\n stopped: 'warning',\n failed: 'danger',\n error: 'danger',\n destroying: 'info',\n}\n\nconst LABELS: Record<string, string> = {\n not_started: 'Not Started',\n provisioning: 'Provisioning',\n running: 'Running',\n active: 'Running',\n degraded: 'Degraded',\n stopped: 'Stopped',\n failed: 'Failed',\n error: 'Failed',\n destroying: 'Destroying',\n}\n\n/** Badge variant for an infrastructure status (falls back to neutral). */\nexport function statusVariant(status?: string): BadgeVariant {\n return (status && VARIANTS[status]) || 'default'\n}\n\n/** Human label for an infrastructure status (Title-Cases anything unknown). */\nexport function statusLabel(status?: string): string {\n if (!status) return 'Unknown'\n return LABELS[status] || status.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase())\n}\n\n/** Whether the environment is actively running (running/active). */\nexport function isRunning(status?: string): boolean {\n return status === 'running' || status === 'active'\n}\n\n/** Whether a deploy has never been requested yet. */\nexport function isNotStarted(status?: string): boolean {\n return !status || status === 'not_started'\n}\n\n// --- Resource statuses (per-resource rows in the Resources tab) --------------\n\nconst RESOURCE_VARIANTS: Record<string, BadgeVariant> = {\n ready: 'success',\n provisioning: 'info',\n attention: 'warning',\n failed: 'danger',\n not_started: 'default',\n}\n\nconst RESOURCE_LABELS: Record<string, string> = {\n ready: 'Ready',\n provisioning: 'Provisioning',\n attention: 'Attention',\n failed: 'Failed',\n not_started: 'Not started',\n}\n\nexport function resourceStatusVariant(status?: string): BadgeVariant {\n return (status && RESOURCE_VARIANTS[status]) || 'default'\n}\n\nexport function resourceStatusLabel(status?: string): string {\n if (!status) return 'Not started'\n return RESOURCE_LABELS[status] || status.replace(/_/g, ' ')\n}\n\n// --- Deployment step statuses (Activity timeline) ---------------------------\n\nconst STEP_VARIANTS: Record<string, BadgeVariant> = {\n done: 'success',\n running: 'info',\n failed: 'danger',\n pending: 'default',\n}\n\nexport function stepStatusVariant(status?: string): BadgeVariant {\n return (status && STEP_VARIANTS[status]) || 'default'\n}\n","import React from 'react'\nimport { Badge } from '../../ui'\nimport { statusVariant, statusLabel, resourceStatusVariant, resourceStatusLabel } from '../status'\nimport type { ByolResource } from '../types'\n\n// Themed tokens — bound to the platform design-system contract in\n// `client/src/styles/tokens.css`. Those `--color-*` variables live on\n// `:root`/`.dark`, cascade into the app subtree, and flip with light/dark, so\n// consuming them here is what makes BYOL follow the active theme automatically.\n//\n// Two rules that the previous version got wrong:\n// 1. The design tokens are *space-separated RGB triples* (e.g. `17 24 39`),\n// meant to be wrapped in `rgb(...)` — not used as bare colours.\n// 2. The real names are `--color-surface[-raised/-sunken]`, `--color-border`,\n// and the `--color-content-*` text family — not `--color-text*` /\n// `--color-surface-secondary`, which never existed (so those silently fell\n// back to hardcoded light hex and never darkened).\n// The triple inside each `var()` fallback keeps the component legible when it\n// renders outside the platform (design tokens undefined → light theme).\n//\n// `primary` is the exception: `--veltrix-app-primary` is a *hex* variable the\n// host injects per app (AppShell brand scope), so it is used directly.\nconst rgbToken = (name: string, fallback: string): string => `rgb(var(${name}, ${fallback}))`\n\nexport const tokens = {\n border: rgbToken('--color-border', '229 231 235'),\n borderStrong: rgbToken('--color-border-strong', '209 213 219'),\n surface: rgbToken('--color-surface-raised', '255 255 255'), // cards / panels / active nav\n surface2: rgbToken('--color-surface', '249 250 251'), // page surface — sidebar / insets\n text: rgbToken('--color-content-primary', '17 24 39'),\n muted: rgbToken('--color-content-secondary', '75 85 99'),\n faint: rgbToken('--color-content-tertiary', '156 163 175'),\n primary: 'var(--veltrix-app-primary, #FF6600)',\n danger: rgbToken('--color-danger', '220 38 38'),\n success: rgbToken('--color-success', '22 163 74'),\n info: rgbToken('--color-info', '14 116 144'),\n warning: rgbToken('--color-warning', '161 98 7'),\n}\n\n/** Overall infrastructure status badge. */\nexport const StatusPill: React.FC<{ status?: string }> = ({ status }) => (\n <Badge variant={statusVariant(status)}>{statusLabel(status)}</Badge>\n)\n\n/** Per-resource status badge. */\nexport const ResourcePill: React.FC<{ status?: string }> = ({ status }) => (\n <Badge variant={resourceStatusVariant(status)} size=\"sm\">\n {resourceStatusLabel(status)}\n </Badge>\n)\n\n/** A labelled key/value pair used across the detail sections. */\nexport const Meta: React.FC<{ label: string; children: React.ReactNode }> = ({ label, children }) => (\n <div>\n <div style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '.05em', color: tokens.faint }}>{label}</div>\n <div style={{ fontWeight: 600, color: tokens.text, marginTop: 2 }}>{children}</div>\n </div>\n)\n\n/** Maps a resource status to a bar colour for the progress meter. */\nfunction barColor(status: string): string {\n switch (status) {\n case 'ready':\n return tokens.success\n case 'provisioning':\n return tokens.info\n case 'attention':\n return tokens.warning\n case 'failed':\n return tokens.danger\n default:\n return tokens.borderStrong\n }\n}\n\n/**\n * Segmented deployment-progress meter: one coloured segment per resource state,\n * plus a \"N / M ready\" readout. Falls back to an empty track when there are no\n * resources yet (never deployed).\n */\nexport const ProgressMeter: React.FC<{ resources: ByolResource[] }> = ({ resources }) => {\n const total = resources.length\n const ready = resources.filter((r) => r.status === 'ready').length\n const counts = new Map<string, number>()\n for (const r of resources) counts.set(r.status, (counts.get(r.status) ?? 0) + 1)\n const order = ['ready', 'provisioning', 'attention', 'failed', 'not_started']\n\n return (\n <div style={{ width: 300, maxWidth: '48vw' }}>\n <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, color: tokens.muted, marginBottom: 6 }}>\n <span>Deployment progress</span>\n <span style={{ fontVariantNumeric: 'tabular-nums' }}>\n {total === 0 ? 'Not deployed' : `${ready} / ${total} resources ready`}\n </span>\n </div>\n <div style={{ height: 8, borderRadius: 999, background: tokens.surface2, overflow: 'hidden', display: 'flex' }}>\n {total === 0\n ? null\n : order.map((s) => {\n const n = counts.get(s) ?? 0\n if (!n) return null\n return <div key={s} style={{ width: `${(n / total) * 100}%`, background: barColor(s), height: '100%' }} />\n })}\n </div>\n </div>\n )\n}\n\n/** A lightweight titled panel (used where a full Card header is overkill). */\nexport const Panel: React.FC<{ title?: string; actions?: React.ReactNode; children: React.ReactNode }> = ({\n title,\n actions,\n children,\n}) => (\n <div style={{ border: `1px solid ${tokens.border}`, borderRadius: 12, background: tokens.surface, overflow: 'hidden' }}>\n {(title || actions) && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n padding: '12px 16px',\n borderBottom: `1px solid ${tokens.border}`,\n }}\n >\n {title ? <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600, color: tokens.text }}>{title}</h3> : <span />}\n {actions}\n </div>\n )}\n <div style={{ padding: 16 }}>{children}</div>\n </div>\n)\n","// =============================================================================\n// BYOL fetch + formatting helpers. All calls go through the SDK's authFetch so\n// they carry the tenant's auth against the app's own `/byol` routes.\n// =============================================================================\n\nimport { authFetch } from '../client'\nimport type { ByolInfrastructure, ByolResource, ByolDeployment } from './types'\nimport type { ByolPlan } from './diffPlan'\n\n/** Best-effort extraction of an error message from a failed Response. */\nexport async function errorText(res: Response): Promise<string> {\n return res\n .json()\n .then((b: { error?: string }) => b?.error || `HTTP ${res.status}`)\n .catch(() => `HTTP ${res.status}`)\n}\n\nexport function formatDate(value?: string | null): string {\n if (!value) return '—'\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? '—' : date.toLocaleDateString()\n}\n\nexport function formatDateTime(value?: string | null): string {\n if (!value) return '—'\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString()\n}\n\nasync function json<T>(res: Response): Promise<T> {\n if (!res.ok) throw new Error(await errorText(res))\n return res.json() as Promise<T>\n}\n\n/** Re-fetch a single infrastructure record. */\nexport function getInfra(apiBase: string, id: string): Promise<ByolInfrastructure> {\n return authFetch(`${apiBase}/${id}`).then((r) => json<ByolInfrastructure>(r))\n}\n\nexport function getResources(apiBase: string, id: string): Promise<ByolResource[]> {\n return authFetch(`${apiBase}/${id}/resources`).then((r) => json<ByolResource[]>(r))\n}\n\nexport function getDeployments(apiBase: string, id: string): Promise<ByolDeployment[]> {\n return authFetch(`${apiBase}/${id}/deployments`).then((r) => json<ByolDeployment[]>(r))\n}\n\n/**\n * Dry-run the deployment plan — a side-effect-free diff of the desired topology\n * against the currently persisted resources. Powers the Plan modal shown before\n * Apply. Writes nothing; the subsequent Apply is the existing `deployInfra`.\n */\nexport function getPlan(apiBase: string, id: string): Promise<ByolPlan> {\n return authFetch(`${apiBase}/${id}/plan`).then((r) => json<ByolPlan>(r))\n}\n\n/** Request an end-to-end deploy. Returns the updated infra + the new run. */\nexport function deployInfra(\n apiBase: string,\n id: string,\n): Promise<{ infrastructure: ByolInfrastructure; deployment: ByolDeployment; resources: ByolResource[] }> {\n return authFetch(`${apiBase}/${id}/deploy`, { method: 'POST' }).then((r) =>\n json<{ infrastructure: ByolInfrastructure; deployment: ByolDeployment; resources: ByolResource[] }>(r),\n )\n}\n\n/** Tear down every resource in the plan. */\nexport function destroyInfra(apiBase: string, id: string): Promise<{ infrastructure: ByolInfrastructure }> {\n return authFetch(`${apiBase}/${id}/destroy`, { method: 'POST' }).then((r) =>\n json<{ infrastructure: ByolInfrastructure }>(r),\n )\n}\n\n/** Start / stop / restart a running environment. */\nexport function lifecycleInfra(\n apiBase: string,\n id: string,\n action: 'start' | 'stop' | 'restart',\n): Promise<ByolInfrastructure> {\n return authFetch(`${apiBase}/${id}/${action}`, { method: 'POST' }).then((r) => json<ByolInfrastructure>(r))\n}\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Button, Spinner, useConfirmDialog } from '../ui'\nimport { buildByolResourcePlan } from './topology'\nimport { isRunning, isNotStarted } from './status'\nimport {\n getInfra,\n getResources,\n getDeployments,\n getPlan,\n deployInfra,\n destroyInfra,\n lifecycleInfra,\n errorText,\n formatDate,\n} from './api'\nimport type { ByolInfrastructure, ByolResource, ByolDeployment, ByolConfigLink } from './types'\nimport { SELF_HOSTED_LABEL } from './types'\nimport type { ByolPlan } from './diffPlan'\nimport { tokens, StatusPill, Meta, ProgressMeter } from './detail/shared'\nimport { OverviewTab } from './detail/OverviewTab'\nimport { ResourcesTab } from './detail/ResourcesTab'\nimport { ActivityTab } from './detail/ActivityTab'\nimport { AccessTab } from './detail/AccessTab'\nimport { ConfigurationTab } from './detail/ConfigurationTab'\nimport { SettingsTab } from './detail/SettingsTab'\nimport { ByolPlanModal } from './detail/ByolPlanModal'\nimport { DestroyPlanModal } from './detail/DestroyPlanModal'\nimport {\n OverviewIcon,\n ResourcesIcon,\n ActivityIcon,\n AccessIcon,\n ConfigurationIcon,\n SettingsIcon,\n type IconProps,\n} from './detail/icons'\n\n/** How often the detail view re-polls while a deployment is in flight. */\nconst PROVISIONING_POLL_MS = 4000\n\ntype Section = 'overview' | 'resources' | 'activity' | 'access' | 'config' | 'settings'\n\n// Inline-SVG icons (font-independent) rather than Unicode glyphs, which failed\n// to render in the platform shell font — see detail/icons.tsx.\nconst SECTIONS: Array<{ key: Section; label: string; Icon: React.FC<IconProps> }> = [\n { key: 'overview', label: 'Overview', Icon: OverviewIcon },\n { key: 'resources', label: 'Resources', Icon: ResourcesIcon },\n { key: 'activity', label: 'Activity', Icon: ActivityIcon },\n { key: 'access', label: 'Access', Icon: AccessIcon },\n { key: 'config', label: 'Configuration', Icon: ConfigurationIcon },\n { key: 'settings', label: 'Settings', Icon: SettingsIcon },\n]\n\nexport interface ByolInfrastructureDetailProps {\n apiBase: string\n /** The row the user clicked — rendered instantly, then refreshed from the API. */\n initialInfra: ByolInfrastructure\n configBase?: string\n configLinks?: ByolConfigLink[]\n onBack: () => void\n onEdit: (infra: ByolInfrastructure) => void\n onDeleted: () => void\n /** Called after any mutation so the parent list can refresh statuses. */\n onChanged: () => void\n /** Bumped by the parent (e.g. after an edit via the shared form) to force a reload. */\n reloadSignal?: number\n}\n\n/** Derive pseudo-resources from topology for the pre-deploy plan view. */\nfunction derivePlan(infra: ByolInfrastructure): ByolResource[] {\n const plan = buildByolResourcePlan({\n deploymentType: infra.deploymentType,\n indexerCount: infra.indexerCount,\n searchHeadCount: infra.searchHeadCount,\n hostingType: infra.hosting_type,\n isCloud: Boolean(infra.cloudProviderId),\n region: infra.region ?? null,\n indexerRegions: (infra.indexerRegions ?? []).map((r) => r.region),\n searchHeadRegions: (infra.searchHeadRegions ?? []).map((r) => r.region),\n })\n return plan.map((p) => ({\n id: p.planKey,\n infrastructureId: infra.id,\n tier: p.tier,\n kind: p.kind,\n name: p.name,\n role: p.role,\n region: p.region,\n status: 'not_started',\n externalRef: null,\n message: null,\n planKey: p.planKey,\n sortOrder: p.sortOrder,\n }))\n}\n\nfunction readSectionFromUrl(): Section | null {\n if (typeof window === 'undefined') return null\n const s = new URLSearchParams(window.location.search).get('section')\n return SECTIONS.some((x) => x.key === s) ? (s as Section) : null\n}\n\nexport const ByolInfrastructureDetail: React.FC<ByolInfrastructureDetailProps> = ({\n apiBase,\n initialInfra,\n configBase,\n configLinks,\n onBack,\n onEdit,\n onDeleted,\n onChanged,\n reloadSignal = 0,\n}) => {\n const [infra, setInfra] = useState<ByolInfrastructure>(initialInfra)\n const [resources, setResources] = useState<ByolResource[]>([])\n const [deployments, setDeployments] = useState<ByolDeployment[]>([])\n const [section, setSection] = useState<Section>(readSectionFromUrl() ?? 'overview')\n const [collapsed, setCollapsed] = useState(false)\n const [loading, setLoading] = useState(true)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // --- Plan → Apply modal state ---\n const [planOpen, setPlanOpen] = useState(false)\n const [plan, setPlan] = useState<ByolPlan | null>(null)\n const [planLoading, setPlanLoading] = useState(false)\n const [planError, setPlanError] = useState<string | null>(null)\n const [applying, setApplying] = useState(false)\n\n // --- Destroy plan modal state ---\n // Mirrors the Plan → Apply flow above: \"Destroy infrastructure\" opens a modal\n // that previews exactly what will be torn down (every current resource, as a\n // destroy plan) rather than a generic yes/no text confirmation.\n const [destroyOpen, setDestroyOpen] = useState(false)\n const [destroyResources, setDestroyResources] = useState<ByolResource[] | null>(null)\n const [destroyLoading, setDestroyLoading] = useState(false)\n const [destroyError, setDestroyError] = useState<string | null>(null)\n const [destroying, setDestroying] = useState(false)\n\n // Danger-zone confirmation for Delete — the platform's real confirmation dialog\n // (portaled to document.body, themed via the host's brand tokens) when running\n // inside Veltrix; fails closed (no destructive action proceeds) outside it.\n // Replaces the native window.confirm() this view used to call directly. Destroy\n // uses the richer DestroyPlanModal below instead of this text confirmation.\n const { confirm } = useConfirmDialog()\n\n const id = initialInfra.id\n\n // Keep the latest list row available as a fallback without churning `load`.\n const initialRef = useRef(initialInfra)\n initialRef.current = initialInfra\n\n const load = useCallback(async () => {\n setError(null)\n try {\n const [freshInfra, res, deps] = await Promise.all([\n getInfra(apiBase, id).catch(() => initialRef.current),\n getResources(apiBase, id).catch(() => [] as ByolResource[]),\n getDeployments(apiBase, id).catch(() => [] as ByolDeployment[]),\n ])\n setInfra(freshInfra)\n setResources(res)\n setDeployments(deps)\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setLoading(false)\n }\n }, [apiBase, id])\n\n useEffect(() => {\n void load()\n // reloadSignal is an explicit parent-driven refresh trigger.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [load, reloadSignal])\n\n // Reflect the open detail + section in the URL for refresh / deep-link.\n useEffect(() => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n params.set('infra', id)\n params.set('section', section)\n window.history.replaceState(null, '', `${window.location.pathname}?${params.toString()}`)\n }, [id, section])\n\n const refresh = useCallback(async () => {\n await load()\n onChanged()\n }, [load, onChanged])\n\n // While a deployment (or teardown) is in flight, re-poll so the persisted\n // resource/step rows — and thus the ProgressMeter — animate toward terminal\n // state without the user having to hit Refresh. Cleared on unmount or as soon\n // as the status leaves the transient state.\n const transient = infra.status === 'provisioning' || infra.status === 'destroying'\n useEffect(() => {\n if (!transient) return\n let active = true\n const timer = setInterval(() => {\n if (active) void refresh()\n }, PROVISIONING_POLL_MS)\n return () => {\n active = false\n clearInterval(timer)\n }\n }, [transient, refresh])\n\n const runAction = useCallback(\n async (fn: () => Promise<unknown>) => {\n setBusy(true)\n setError(null)\n try {\n await fn()\n await refresh()\n } catch (e) {\n setError((e as Error).message)\n } finally {\n setBusy(false)\n }\n },\n [refresh],\n )\n\n // Deploy is now a two-phase flow: open the plan modal and fetch the dry-run\n // diff (spinner in the modal); Apply is what actually POSTs /deploy.\n const openPlan = useCallback(() => {\n setPlanOpen(true)\n setPlan(null)\n setPlanError(null)\n setPlanLoading(true)\n getPlan(apiBase, id)\n .then((p) => setPlan(p))\n .catch((e) => setPlanError((e as Error).message))\n .finally(() => setPlanLoading(false))\n }, [apiBase, id])\n\n const closePlan = useCallback(() => {\n if (applying) return\n setPlanOpen(false)\n }, [applying])\n\n const onApply = useCallback(async () => {\n setApplying(true)\n setPlanError(null)\n try {\n await deployInfra(apiBase, id)\n setPlanOpen(false)\n setSection('activity')\n await refresh()\n } catch (e) {\n setPlanError((e as Error).message)\n } finally {\n setApplying(false)\n }\n }, [apiBase, id, refresh])\n\n // Destroy is a two-phase flow, mirroring Deploy: open the destroy-plan modal\n // (a fresh resource fetch so the preview reflects reality even if `resources`\n // is stale), and only POST /destroy when the user confirms inside the modal.\n const openDestroy = useCallback(() => {\n setDestroyOpen(true)\n setDestroyError(null)\n setDestroyResources(null)\n setDestroyLoading(true)\n getResources(apiBase, id)\n .then((res) => setDestroyResources(res))\n // A failed refetch must never block Destroy — fall back to whatever the\n // detail view already has loaded (possibly empty; the modal handles that).\n .catch(() => setDestroyResources(resources))\n .finally(() => setDestroyLoading(false))\n }, [apiBase, id, resources])\n\n const closeDestroy = useCallback(() => {\n if (destroying) return\n setDestroyOpen(false)\n }, [destroying])\n\n const confirmDestroy = useCallback(async () => {\n setDestroying(true)\n setDestroyError(null)\n try {\n await destroyInfra(apiBase, id)\n setDestroyOpen(false)\n setSection('activity')\n await refresh()\n } catch (e) {\n setDestroyError((e as Error).message)\n } finally {\n setDestroying(false)\n }\n }, [apiBase, id, refresh])\n\n const onLifecycle = (action: 'start' | 'stop' | 'restart') => runAction(() => lifecycleInfra(apiBase, id, action))\n const onDelete = async () => {\n const ok = await confirm({\n title: 'Delete infrastructure record',\n message: `Delete \"${infra.name}\"? This cannot be undone.`,\n confirmText: 'Delete',\n cancelText: 'Cancel',\n variant: 'danger',\n })\n if (!ok) return\n setBusy(true)\n setError(null)\n try {\n const res = await import('../client').then(({ authFetch }) => authFetch(`${apiBase}/${id}`, { method: 'DELETE' }))\n if (!res.ok && res.status !== 204) throw new Error(await errorText(res))\n onDeleted()\n } catch (e) {\n setError((e as Error).message)\n setBusy(false)\n }\n }\n\n const status = infra.status\n const notStarted = isNotStarted(status)\n const failed = status === 'failed' || status === 'error'\n const provisioning = status === 'provisioning' || status === 'destroying'\n const running = isRunning(status)\n // A torn-down environment can be stood up again — re-provisioning re-runs the plan\n // against the now-empty state (resources were reset to not_started on teardown).\n const deprovisioned = status === 'deprovisioned' || status === 'decommissioned'\n\n // `deployments` is ordered newest-first (see `listDeployments` — ORDER BY\n // started_at DESC), so [0] is the run that produced the current failed\n // status. A failed *destroy* must retry the teardown, not re-provision —\n // defaults to the deploy retry path when no runs have loaded yet.\n const latestRunAction = deployments[0]?.action\n const failedDestroy = failed && latestRunAction === 'destroy'\n\n // Persisted plan when it exists; otherwise the derived plan (pre-deploy).\n const derived = resources.length === 0\n const displayResources = useMemo(\n () => (derived ? derivePlan(infra) : resources),\n [derived, infra, resources],\n )\n\n const provider = infra.hosting_type || (infra.cloudProviderId ? 'Cloud' : SELF_HOSTED_LABEL)\n\n const primaryAction = (() => {\n if (notStarted) return <Button variant=\"primary\" size=\"sm\" onClick={openPlan} disabled={busy}>Deploy environment</Button>\n if (deprovisioned) return <Button variant=\"primary\" size=\"sm\" onClick={openPlan} disabled={busy}>Re-provision</Button>\n if (failedDestroy) return <Button variant=\"danger\" size=\"sm\" onClick={openDestroy} disabled={busy}>Retry Destroy</Button>\n if (failed) return <Button variant=\"primary\" size=\"sm\" onClick={openPlan} disabled={busy}>Retry deployment</Button>\n if (provisioning) return <Button variant=\"primary\" size=\"sm\" onClick={() => setSection('activity')}>View progress</Button>\n return null\n })()\n\n const content = (() => {\n switch (section) {\n case 'overview':\n return <OverviewTab infra={infra} resources={displayResources} />\n case 'resources':\n return <ResourcesTab resources={displayResources} derived={derived} />\n case 'activity':\n return <ActivityTab deployments={deployments} />\n case 'access':\n return <AccessTab infra={infra} resources={resources} />\n case 'config':\n return <ConfigurationTab links={configLinks ?? []} configBase={configBase} />\n case 'settings':\n return (\n <SettingsTab\n infra={infra}\n busy={busy}\n onEdit={() => onEdit(infra)}\n onDestroy={openDestroy}\n onDelete={onDelete}\n />\n )\n }\n })()\n\n return (\n <div>\n <button\n onClick={onBack}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 7,\n color: tokens.muted,\n fontSize: 13,\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n padding: 0,\n marginBottom: 12,\n }}\n >\n ‹ Back to infrastructure\n </button>\n\n <div style={{ border: `1px solid ${tokens.border}`, borderRadius: 12, background: tokens.surface, overflow: 'hidden' }}>\n {/* summary header */}\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '18px 24px', alignItems: 'flex-start', justifyContent: 'space-between', padding: 20 }}>\n <div style={{ minWidth: 260, flex: 1 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>\n <h2 style={{ margin: 0, fontSize: 21, letterSpacing: '-.01em', color: tokens.text }}>{infra.name}</h2>\n <StatusPill status={status} />\n {loading ? <Spinner size=\"sm\" /> : null}\n </div>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px 20px', marginTop: 12 }}>\n <Meta label=\"Environment\">{infra.environmentType || '—'}</Meta>\n <Meta label=\"Deployment\">{infra.deploymentType ?? '—'}</Meta>\n <Meta label=\"Provider\">{provider}</Meta>\n <Meta label=\"Region\">{infra.region || '—'}</Meta>\n <Meta label=\"Updated\">{formatDate(infra.updatedAt)}</Meta>\n </div>\n <div style={{ marginTop: 14 }}>\n <ProgressMeter resources={displayResources} />\n </div>\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 10 }}>\n {primaryAction}\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end' }}>\n {running ? (\n <>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onLifecycle('stop')} disabled={busy}>Stop</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onLifecycle('restart')} disabled={busy}>Restart</Button>\n </>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onEdit(infra)} disabled={busy}>Edit topology</Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void refresh()} disabled={busy}>Refresh</Button>\n </div>\n </div>\n </div>\n\n {error ? (\n <div style={{ padding: '0 20px 12px', color: tokens.danger, fontSize: 13 }}>{error}</div>\n ) : null}\n\n {/* secondary expandable sidebar + content */}\n <div style={{ display: 'flex', borderTop: `1px solid ${tokens.border}`, alignItems: 'stretch' }}>\n <aside\n style={{\n flex: `0 0 ${collapsed ? 56 : 220}px`,\n width: collapsed ? 56 : 220,\n borderRight: `1px solid ${tokens.border}`,\n background: tokens.surface2,\n padding: '14px 12px',\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n transition: 'flex-basis .12s, width .12s',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: collapsed ? 'center' : 'space-between', padding: '2px 6px 10px' }}>\n {collapsed ? null : (\n <span style={{ fontSize: 11, letterSpacing: '.1em', textTransform: 'uppercase', color: tokens.faint, fontWeight: 700 }}>\n This infrastructure\n </span>\n )}\n <button\n onClick={() => setCollapsed((c) => !c)}\n title={collapsed ? 'Expand' : 'Collapse'}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n style={{\n border: `1px solid ${tokens.border}`,\n background: tokens.surface,\n color: tokens.muted,\n borderRadius: 6,\n width: 24,\n height: 24,\n cursor: 'pointer',\n lineHeight: 1,\n }}\n >\n {collapsed ? '»' : '«'}\n </button>\n </div>\n {SECTIONS.map((s) => {\n const active = s.key === section\n const { Icon } = s\n return (\n <button\n key={s.key}\n onClick={() => setSection(s.key)}\n title={s.label}\n style={{\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n justifyContent: collapsed ? 'center' : 'flex-start',\n gap: 11,\n padding: collapsed ? '9px 0' : '9px 10px',\n borderRadius: 8,\n border: 'none',\n background: active ? tokens.surface : 'transparent',\n color: active ? tokens.primary : tokens.muted,\n fontWeight: 600,\n fontSize: 13,\n cursor: 'pointer',\n textAlign: 'left',\n width: '100%',\n }}\n >\n {active ? (\n <span style={{ position: 'absolute', left: 0, top: 8, bottom: 8, width: 3, borderRadius: '0 3px 3px 0', background: tokens.primary }} />\n ) : null}\n <span style={{ width: 18, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}>\n <Icon size={16} />\n </span>\n {collapsed ? null : <span style={{ flex: 1 }}>{s.label}</span>}\n {!collapsed && s.key === 'resources' && displayResources.length > 0 ? (\n <span style={{ fontSize: 11, fontWeight: 600, color: tokens.faint }}>{displayResources.length}</span>\n ) : null}\n {!collapsed && s.key === 'activity' && provisioning ? (\n <span style={{ width: 7, height: 7, borderRadius: '50%', background: tokens.info }} />\n ) : null}\n </button>\n )\n })}\n </aside>\n\n <div style={{ flex: 1, minWidth: 0, padding: '22px 24px' }}>{content}</div>\n </div>\n </div>\n\n <ByolPlanModal\n isOpen={planOpen}\n onClose={closePlan}\n plan={plan}\n loading={planLoading}\n error={planError}\n applying={applying}\n onApply={onApply}\n infraName={infra.name}\n allowApplyWithoutChanges={infra.status === 'failed' || infra.status === 'error' || infra.status === 'not_started'}\n />\n\n <DestroyPlanModal\n isOpen={destroyOpen}\n onClose={closeDestroy}\n resources={destroyResources}\n loading={destroyLoading}\n error={destroyError}\n destroying={destroying}\n onConfirm={confirmDestroy}\n infraName={infra.name}\n />\n </div>\n )\n}\n\nexport default ByolInfrastructureDetail\n","// =============================================================================\n// Cluster placement: percent → integer node allocation.\n//\n// Shared by the topology builder (derives per-node site assignment) and the\n// form (live \"→ N nodes\" preview) so both agree exactly. Only the indexer and\n// search-head tiers use this; every other tier is single-site (main region).\n// =============================================================================\n\nimport type { ClusterPlacement, PlacementSite } from './types'\n\nexport interface SiteAllocation {\n site: string\n count: number\n /** The requested percent for this site (echoed for display / audit). */\n percent: number\n}\n\n/**\n * Allocate `totalNodes` across a cluster's sites by percent.\n *\n * Rules:\n * - Every listed site receives at least one node (a site in the plan must be real).\n * - The remaining nodes are distributed by percent using the largest-remainder\n * method, so the counts sum to exactly `totalNodes`.\n * - Deterministic: ties in the remainder are broken by site order (no RNG).\n *\n * Callers must ensure `sites.length <= totalNodes` (see {@link validatePlacement});\n * when that does not hold this still returns one node per site until it runs out,\n * so it never returns a negative count.\n */\nexport function allocateNodesBySite(totalNodes: number, sites: PlacementSite[]): SiteAllocation[] {\n const n = Math.max(0, Math.floor(totalNodes))\n const list = sites ?? []\n if (list.length === 0) return []\n\n // Floor of one per site, capped at the node budget.\n const base = list.map(() => 0)\n let assigned = 0\n for (let i = 0; i < list.length && assigned < n; i++) {\n base[i] = 1\n assigned++\n }\n\n const remaining = n - assigned\n if (remaining > 0) {\n // Largest-remainder distribution of the remaining nodes by percent.\n const totalPercent = list.reduce((sum, s) => sum + Math.max(0, s.percent), 0) || 1\n const ideal = list.map((s) => (Math.max(0, s.percent) / totalPercent) * remaining)\n const floors = ideal.map((v) => Math.floor(v))\n let leftover = remaining - floors.reduce((a, b) => a + b, 0)\n\n const order = list\n .map((_, i) => ({ i, frac: ideal[i] - floors[i] }))\n .sort((a, b) => b.frac - a.frac || a.i - b.i)\n\n for (let k = 0; k < order.length && leftover > 0; k++) {\n floors[order[k].i]++\n leftover--\n }\n for (let i = 0; i < list.length; i++) base[i] += floors[i]\n }\n\n return list.map((s, i) => ({ site: s.site, count: base[i], percent: s.percent }))\n}\n\n/**\n * Validate a cluster placement against a node count. Returns a human-readable\n * error string, or `null` when the placement is deployable.\n */\nexport function validatePlacement(placement: ClusterPlacement | undefined, totalNodes: number): string | null {\n if (!placement || placement.mode === 'single') return null\n const sites = placement.sites ?? []\n if (sites.length < 2) return 'Multi-site placement needs at least two sites.'\n\n const seen = new Set<string>()\n for (const s of sites) {\n if (!s.site || !s.site.trim()) return 'Every site must be selected.'\n if (seen.has(s.site)) return `Site \"${s.site}\" is listed more than once.`\n seen.add(s.site)\n if (!(s.percent > 0)) return `Site \"${s.site}\" must have a percent greater than zero.`\n }\n\n const sumPercent = sites.reduce((sum, s) => sum + s.percent, 0)\n if (Math.round(sumPercent) !== 100) return `Site percentages must total 100 (currently ${Math.round(sumPercent)}).`\n\n if (sites.length > Math.floor(totalNodes)) {\n return `Too many sites (${sites.length}) for ${totalNodes} node${totalNodes === 1 ? '' : 's'} — each site needs at least one node.`\n }\n return null\n}\n\n/**\n * Resolve the placement actually used for a tier: multi-site placement is only\n * honored for eligible (indexer / search-head) tiers; everything else collapses\n * to single-site so callers can treat the result uniformly.\n */\nexport function effectivePlacement(placement: ClusterPlacement | undefined, eligible: boolean): ClusterPlacement {\n if (!eligible || !placement || placement.mode !== 'multi-site') return { mode: 'single' }\n if (!placement.sites || placement.sites.length < 2) return { mode: 'single' }\n return placement\n}\n","// =============================================================================\n// BYOL resource-plan topology (pure, React-free).\n//\n// Given the shape of a BYOL infrastructure (deployment type, node counts,\n// provider, regions), this derives the FULL set of resources needed to stand up\n// and run an end-to-end Splunk environment — grouped into tiers, in provisioning\n// order. It is the single source of truth for \"what gets deployed\":\n//\n// • the app SERVER imports it (via the React-free root SDK entry) to SEED\n// `splunk_byol_resource` rows when a deployment is requested, and\n// • the app CLIENT renders it as the derived plan BEFORE the first deploy,\n// then swaps to the persisted rows once they exist.\n//\n// Keeping it here (and re-exported from the root entry) is what keeps both sides\n// DRY without the app duplicating the topology rules.\n// =============================================================================\n\nimport type { ClusterPlacement, ControlPlaneLayout } from './types'\nimport { effectivePlacement, allocateNodesBySite } from './placement'\n\n/** Coarse grouping used to lay the plan out by tier in the UI and DB. */\nexport type ByolResourceTier = 'foundation' | 'control-plane' | 'data' | 'search' | 'ingest'\n\n/** Lifecycle state of a single planned/provisioned resource. */\nexport type ByolResourceStatus = 'not_started' | 'provisioning' | 'ready' | 'attention' | 'failed'\n\n/** A stable machine kind for a resource, used for icons + worker correlation. */\nexport type ByolResourceKind =\n | 'network'\n | 'load-balancer'\n | 'dns'\n | 'tls'\n | 'storage'\n | 'secrets'\n | 'license-file'\n | 'license-manager'\n | 'cluster-manager'\n | 'sh-deployer'\n | 'deployment-server'\n | 'monitoring-console'\n | 'indexer'\n | 'search-head'\n | 'hec'\n | 'heavy-forwarder'\n | 'standalone'\n // A single instance running several combined control-plane management roles.\n | 'management-node'\n\n/** One resource in the plan. `planKey` is a stable identity for idempotent seeding. */\nexport interface ByolResourcePlanItem {\n planKey: string\n tier: ByolResourceTier\n kind: ByolResourceKind\n name: string\n role: string\n region: string | null\n /** Availability zone within `region` (multi-AZ placement); null otherwise. */\n zone?: string | null\n /** Machine-readable roles this instance runs — drives control-plane bring-up. */\n roles?: string[]\n}\n\nexport interface ByolTopologyInput {\n deploymentType?: string\n indexerCount?: number\n searchHeadCount?: number\n /** Display provider name, e.g. \"AWS\" or \"Self-Hosted\". */\n hostingType?: string\n /** Whether the deployment targets a cloud provider (vs Self-Hosted). */\n isCloud?: boolean\n /** Primary region + any per-node regions, in preference order. */\n region?: string | null\n indexerRegions?: string[]\n searchHeadRegions?: string[]\n /** Control-plane consolidation layout (distributed only). Defaults to 'dedicated'. */\n controlPlaneLayout?: ControlPlaneLayout\n /** Heavy forwarder count (distributed only). Defaults to 1. */\n heavyForwarderCount?: number\n /** Multi-site placement of the indexer cluster (indexer/search tiers only). */\n indexerPlacement?: ClusterPlacement | null\n /** Multi-site placement of the search-head cluster. */\n searchHeadPlacement?: ClusterPlacement | null\n}\n\n/** A control-plane management role that can be dedicated or combined onto a node. */\ntype ControlPlaneRole =\n | 'license-manager'\n | 'cluster-manager'\n | 'sh-deployer'\n | 'deployment-server'\n | 'monitoring-console'\n\nconst CONTROL_PLANE_ROLE_META: Record<ControlPlaneRole, { kind: ByolResourceKind; name: string; role: string }> = {\n 'license-manager': { kind: 'license-manager', name: 'License Manager', role: 'Serves BYOL license pool' },\n 'cluster-manager': { kind: 'cluster-manager', name: 'Cluster Manager', role: 'Indexer cluster coordinator' },\n 'sh-deployer': { kind: 'sh-deployer', name: 'SH Deployer', role: 'Search head cluster deployer' },\n 'deployment-server': { kind: 'deployment-server', name: 'Deployment Server', role: 'Forwarder app distribution' },\n 'monitoring-console': { kind: 'monitoring-console', name: 'Monitoring Console', role: 'Fleet health & DMC' },\n}\n\n/**\n * Group the five management roles into instances per consolidation layout.\n * The cluster manager and SH deployer stay isolated when consolidating (they\n * coordinate the indexer/search-head clusters and must not co-locate with the\n * peers or each other under HA); only the lighter roles combine.\n */\nfunction controlPlaneGroups(layout: ControlPlaneLayout): ControlPlaneRole[][] {\n switch (layout) {\n case 'single':\n return [['license-manager', 'cluster-manager', 'sh-deployer', 'deployment-server', 'monitoring-console']]\n case 'consolidated':\n return [['cluster-manager'], ['sh-deployer'], ['license-manager', 'deployment-server', 'monitoring-console']]\n case 'dedicated':\n default:\n return [['license-manager'], ['cluster-manager'], ['sh-deployer'], ['deployment-server'], ['monitoring-console']]\n }\n}\n\n/** Build the control-plane instances for a layout (each running one or more roles). */\nfunction buildControlPlane(layout: ControlPlaneLayout, region: string | null): ByolResourcePlanItem[] {\n return controlPlaneGroups(layout).map((roles) => {\n if (roles.length === 1) {\n const meta = CONTROL_PLANE_ROLE_META[roles[0]]\n return { planKey: `control-plane/${roles[0]}`, tier: 'control-plane', kind: meta.kind, name: meta.name, role: meta.role, region, roles: [roles[0]] }\n }\n const label = roles.map((r) => CONTROL_PLANE_ROLE_META[r].name).join(' · ')\n return {\n planKey: 'control-plane/management',\n tier: 'control-plane',\n kind: 'management-node',\n name: roles.length >= 5 ? 'Management node (all roles)' : 'Management node',\n role: label,\n region,\n roles: [...roles],\n }\n })\n}\n\ninterface NodeSite {\n region: string | null\n zone: string | null\n}\n\n/**\n * Resolve the per-node region/zone for a cluster tier. Multi-site placement\n * (indexer/search only) spreads nodes across sites by percent: AZ granularity\n * keeps the main region and varies the zone; region granularity varies the\n * region. Falls back to the legacy per-node region round-robin otherwise.\n */\nfunction assignNodeSites(\n count: number,\n placement: ClusterPlacement | null | undefined,\n primaryRegion: string | null,\n legacyRegions: string[] | undefined,\n): NodeSite[] {\n const eff = effectivePlacement(placement ?? undefined, true)\n if (eff.mode === 'multi-site' && eff.sites && eff.sites.length >= 2) {\n const granularity = eff.granularity ?? 'az'\n const out: NodeSite[] = []\n for (const alloc of allocateNodesBySite(count, eff.sites)) {\n for (let k = 0; k < alloc.count; k++) {\n out.push(granularity === 'az' ? { region: primaryRegion, zone: alloc.site } : { region: alloc.site, zone: null })\n }\n }\n return out\n }\n const out: NodeSite[] = []\n for (let i = 0; i < count; i++) out.push({ region: pickRegion(legacyRegions, i, primaryRegion), zone: null })\n return out\n}\n\nexport const TIER_LABELS: Record<ByolResourceTier, string> = {\n foundation: 'Foundation',\n 'control-plane': 'Control plane',\n data: 'Data tier — indexer cluster',\n search: 'Search tier — search head cluster',\n ingest: 'Ingest & access',\n}\n\n/** Provisioning order the tiers deploy in (also the display order). */\nexport const TIER_ORDER: ByolResourceTier[] = ['foundation', 'control-plane', 'data', 'search', 'ingest']\n\nconst DISTRIBUTED = 'distributed'\n\n/** Pick a region for a node: its own region list, else the primary, else null. */\nfunction pickRegion(regions: string[] | undefined, index: number, fallback: string | null): string | null {\n if (regions && regions.length > 0) return regions[index % regions.length]\n return fallback\n}\n\n/**\n * Build the ordered resource plan for a BYOL infrastructure.\n *\n * A single-instance deployment collapses to an all-in-one Splunk node plus the\n * foundation. A distributed deployment expands to the full topology: control\n * plane (license/cluster managers, deployment server, monitoring console, SH\n * deployer), an N-peer indexer cluster, an M-member search-head cluster, and the\n * ingest path (HEC + heavy forwarders).\n */\nexport function buildByolResourcePlan(input: ByolTopologyInput): ByolResourcePlanItemWithOrder[] {\n const distributed = (input.deploymentType ?? 'single') === DISTRIBUTED\n const primaryRegion = input.region ?? null\n const isCloud = input.isCloud ?? false\n const items: ByolResourcePlanItem[] = []\n\n // --- Foundation ----------------------------------------------------------\n items.push({ planKey: 'foundation/network', tier: 'foundation', kind: 'network', name: 'Network', role: 'VPC · subnets · security groups', region: primaryRegion })\n if (distributed && isCloud) {\n items.push({ planKey: 'foundation/load-balancer', tier: 'foundation', kind: 'load-balancer', name: 'Load balancer', role: 'Search + HEC ingress', region: primaryRegion })\n items.push({ planKey: 'foundation/dns', tier: 'foundation', kind: 'dns', name: 'DNS', role: 'Public + private records', region: 'global' })\n }\n items.push({ planKey: 'foundation/tls', tier: 'foundation', kind: 'tls', name: 'TLS certificates', role: 'Web + inter-node (S2S)', region: null })\n items.push({ planKey: 'foundation/storage', tier: 'foundation', kind: 'storage', name: 'Storage', role: distributed ? 'SmartStore + hot/warm volumes' : 'Index volumes', region: primaryRegion })\n items.push({ planKey: 'foundation/secrets', tier: 'foundation', kind: 'secrets', name: 'Secrets', role: 'Admin password · pass4SymmKey', region: null })\n items.push({ planKey: 'foundation/license-file', tier: 'foundation', kind: 'license-file', name: 'BYOL license file', role: 'Uploaded & validated', region: null })\n\n if (!distributed) {\n // --- Single instance: all-in-one node --------------------------------\n items.push({ planKey: 'data/standalone', tier: 'data', kind: 'standalone', name: 'Splunk instance', role: 'All-in-one (indexer + search head + web)', region: primaryRegion })\n items.push({ planKey: 'ingest/hec', tier: 'ingest', kind: 'hec', name: 'HTTP Event Collector', role: 'Token endpoint', region: primaryRegion })\n return items.map((it, i) => stampOrder(it, i))\n }\n\n // --- Control plane -------------------------------------------------------\n // Always in the main region; consolidation only changes how many instances the\n // management roles run on.\n items.push(...buildControlPlane(input.controlPlaneLayout ?? 'dedicated', primaryRegion))\n\n // --- Data tier: indexer cluster -----------------------------------------\n // Only this tier and the search tier accept multi-site placement; every other\n // tier stays in the main region.\n const indexerCount = Math.max(1, input.indexerCount ?? 1)\n const indexerSites = assignNodeSites(indexerCount, input.indexerPlacement, primaryRegion, input.indexerRegions)\n for (let i = 0; i < indexerCount; i++) {\n items.push({\n planKey: `data/indexer-${i + 1}`,\n tier: 'data',\n kind: 'indexer',\n name: `Indexer peer ${i + 1}`,\n role: 'Cluster peer node',\n region: indexerSites[i].region,\n zone: indexerSites[i].zone,\n })\n }\n\n // --- Search tier: search head cluster -----------------------------------\n const searchHeadCount = Math.max(1, input.searchHeadCount ?? 1)\n const searchHeadSites = assignNodeSites(searchHeadCount, input.searchHeadPlacement, primaryRegion, input.searchHeadRegions)\n for (let i = 0; i < searchHeadCount; i++) {\n items.push({\n planKey: `search/search-head-${i + 1}`,\n tier: 'search',\n kind: 'search-head',\n name: `Search head ${i + 1}`,\n role: i === 0 ? 'SHC captain candidate' : 'SHC member',\n region: searchHeadSites[i].region,\n zone: searchHeadSites[i].zone,\n })\n }\n\n // --- Ingest & access -----------------------------------------------------\n // Ingest is always main-region. Heavy forwarders default to 1; more on demand.\n items.push({ planKey: 'ingest/hec', tier: 'ingest', kind: 'hec', name: 'HTTP Event Collector', role: 'Token endpoint via LB', region: primaryRegion })\n const heavyForwarderCount = Math.max(1, input.heavyForwarderCount ?? 1)\n for (let i = 0; i < heavyForwarderCount; i++) {\n items.push({\n planKey: `ingest/heavy-forwarder-${i + 1}`,\n tier: 'ingest',\n kind: 'heavy-forwarder',\n name: `Heavy Forwarder ${i + 1}`,\n role: 'Ingest routing / props',\n region: primaryRegion,\n })\n }\n\n return items.map((it, i) => stampOrder(it, i))\n}\n\n/** Attach the plan's stable sort order (kept separate so callers can persist it). */\nfunction stampOrder(item: ByolResourcePlanItem, index: number): ByolResourcePlanItem & { sortOrder: number } {\n return { ...item, sortOrder: index }\n}\n\nexport type ByolResourcePlanItemWithOrder = ReturnType<typeof stampOrder>\n\n/**\n * The ordered high-level steps a deployment run advances through. Mirrors the\n * tier order plus the post-deploy phases. Workers report progress against these.\n */\nexport const DEPLOYMENT_STEPS: Array<{ key: string; title: string; detail: string }> = [\n { key: 'plan', title: 'Plan created', detail: 'Resources planned from topology; desired state recorded.' },\n { key: 'foundation', title: 'Provision foundation', detail: 'Network, load balancer, DNS, TLS, storage and secrets.' },\n { key: 'license', title: 'License Manager online · license applied', detail: 'BYOL license validated and pool published.' },\n { key: 'cluster', title: 'Cluster Manager online', detail: 'Indexer cluster policy (RF/SF) published.' },\n { key: 'indexers', title: 'Indexer peers joining cluster', detail: 'Indexer peers boot and register with the cluster manager.' },\n { key: 'search-heads', title: 'Search head cluster forming', detail: 'Deployer pushes the SHC bundle; captain election.' },\n { key: 'services', title: 'Deployment server & monitoring console', detail: 'Ancillary control-plane services come online.' },\n { key: 'post-config', title: 'Post-deploy configuration', detail: 'Apply indexes, HEC tokens and Splunk apps.' },\n { key: 'health', title: 'End-to-end health check', detail: 'Verify search, ingest and replication end to end.' },\n]\n","import React from 'react'\nimport { StatsCard } from '../../ui'\nimport type { ByolInfrastructure, ByolResource } from '../types'\nimport { tokens, Panel } from './shared'\n\nexport interface OverviewTabProps {\n infra: ByolInfrastructure\n resources: ByolResource[]\n}\n\n/** At-a-glance stats + a plain-language summary of what the environment comprises. */\nexport const OverviewTab: React.FC<OverviewTabProps> = ({ infra, resources }) => {\n const distributed = infra.deploymentType === 'distributed'\n const regionCount = new Set(\n resources.map((r) => r.region).filter((r): r is string => Boolean(r) && r !== 'global'),\n ).size\n const readyCount = resources.filter((r) => r.status === 'ready').length\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 12 }}>\n <StatsCard label=\"Indexer peers\" value={infra.indexerCount ?? '—'} />\n <StatsCard label=\"Search heads\" value={infra.searchHeadCount ?? '—'} />\n <StatsCard label=\"Regions\" value={regionCount || (infra.region ? 1 : '—')} />\n <StatsCard\n label={resources.length ? 'Resources ready' : 'Resources planned'}\n value={resources.length ? `${readyCount} / ${resources.length}` : '—'}\n />\n </div>\n\n <Panel title=\"What gets deployed\">\n <p style={{ margin: 0, fontSize: 13, lineHeight: 1.6, color: tokens.muted }}>\n {distributed ? (\n <>\n A distributed BYOL environment provisions a full Splunk topology: a foundation tier (network, load balancing,\n DNS, TLS, storage/SmartStore, secrets and your license file), a control plane (license manager, cluster\n manager, deployment server, monitoring console and search-head deployer), an{' '}\n {infra.indexerCount}-peer indexer cluster, a {infra.searchHeadCount}-member search-head cluster, and the ingest\n path (HEC + heavy forwarders).\n </>\n ) : (\n <>\n A single-instance BYOL environment provisions the foundation (network, TLS, storage, secrets and your license\n file) plus one all-in-one Splunk node (indexer + search head + web) and an HTTP Event Collector endpoint.\n </>\n )}{' '}\n See the <strong>Resources</strong> tab for the live plan and <strong>Activity</strong> for the run log.\n </p>\n </Panel>\n </div>\n )\n}\n","import React from 'react'\nimport { EmptyState } from '../../ui'\nimport { TIER_ORDER, TIER_LABELS, type ByolResourceTier } from '../topology'\nimport type { ByolResource } from '../types'\nimport { tokens, ResourcePill } from './shared'\n\nconst STRIPE: Record<string, string> = {\n ready: tokens.success,\n provisioning: tokens.info,\n attention: tokens.warning,\n failed: tokens.danger,\n not_started: tokens.borderStrong,\n}\n\nconst LEGEND: Array<{ status: string; label: string }> = [\n { status: 'ready', label: 'Ready' },\n { status: 'provisioning', label: 'Provisioning' },\n { status: 'attention', label: 'Attention' },\n { status: 'failed', label: 'Failed' },\n { status: 'not_started', label: 'Not started' },\n]\n\nconst ResourceCard: React.FC<{ resource: ByolResource }> = ({ resource }) => (\n <div\n style={{\n position: 'relative',\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n background: tokens.surface,\n padding: '12px 13px',\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n overflow: 'hidden',\n }}\n >\n <span style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 3, background: STRIPE[resource.status] ?? STRIPE.not_started }} />\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>\n <span style={{ fontWeight: 600, fontSize: 13, color: tokens.text }}>{resource.name}</span>\n <ResourcePill status={resource.status} />\n </div>\n {resource.role ? <div style={{ fontSize: 11, color: tokens.faint }}>{resource.role}</div> : null}\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, fontSize: 11, color: tokens.muted }}>\n <span>{resource.zone ? `${resource.region ?? ''} · ${resource.zone}` : resource.region || '—'}</span>\n <span style={{ fontFamily: 'var(--font-mono, ui-monospace, monospace)', color: tokens.faint }}>\n {resource.externalRef || '—'}\n </span>\n </div>\n </div>\n)\n\nexport interface ResourcesTabProps {\n resources: ByolResource[]\n /** True when the plan is derived from topology (never deployed yet). */\n derived: boolean\n}\n\n/**\n * The full end-to-end resource plan, grouped by tier in provisioning order. Each\n * card shows a resource's role, region, status and (once provisioned) its\n * external reference. Before the first deploy this shows the DERIVED plan — what\n * WILL be provisioned — with a hint to deploy.\n */\nexport const ResourcesTab: React.FC<ResourcesTabProps> = ({ resources, derived }) => {\n if (resources.length === 0) {\n return (\n <EmptyState\n title=\"No resources planned\"\n description=\"This infrastructure has no derivable topology yet. Check the deployment type and node counts in Settings.\"\n />\n )\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>\n {derived ? (\n <div\n style={{\n fontSize: 13,\n color: tokens.muted,\n background: tokens.surface2,\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n padding: '10px 14px',\n }}\n >\n This is the plan derived from the topology — the resources that <strong>will</strong> be provisioned. Deploy the\n environment to begin creating them.\n </div>\n ) : null}\n\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 14, fontSize: 12, color: tokens.muted }}>\n {LEGEND.map((l) => (\n <span key={l.status} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>\n <span style={{ width: 8, height: 8, borderRadius: '50%', background: STRIPE[l.status] }} />\n {l.label}\n </span>\n ))}\n </div>\n\n {TIER_ORDER.map((tier) => {\n const inTier = resources.filter((r) => r.tier === (tier as ByolResourceTier))\n if (inTier.length === 0) return null\n const ready = inTier.filter((r) => r.status === 'ready').length\n return (\n <div key={tier}>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginBottom: 9 }}>\n <h3\n style={{\n margin: 0,\n fontSize: 12,\n letterSpacing: '.08em',\n textTransform: 'uppercase',\n color: tokens.primary,\n }}\n >\n {TIER_LABELS[tier as ByolResourceTier]}\n </h3>\n <span style={{ fontSize: 12, color: tokens.faint, fontVariantNumeric: 'tabular-nums' }}>\n {inTier.length} {inTier.length === 1 ? 'resource' : 'resources'}\n {!derived ? ` · ${ready} ready` : ''}\n </span>\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(232px, 1fr))', gap: 10 }}>\n {inTier.map((r) => (\n <ResourceCard key={r.planKey} resource={r} />\n ))}\n </div>\n </div>\n )\n })}\n </div>\n )\n}\n","import React from 'react'\nimport { EmptyState, Badge } from '../../ui'\nimport { formatDateTime } from '../api'\nimport { stepStatusVariant } from '../status'\nimport type { ByolDeployment, ByolDeploymentStep } from '../types'\nimport { tokens } from './shared'\n\nconst NODE_COLOR: Record<string, string> = {\n done: tokens.success,\n running: tokens.info,\n failed: tokens.danger,\n pending: tokens.borderStrong,\n}\n\nconst StepNode: React.FC<{ step: ByolDeploymentStep; last: boolean }> = ({ step, last }) => (\n <div style={{ position: 'relative', paddingBottom: last ? 0 : 20 }}>\n <span\n style={{\n position: 'absolute',\n left: -24,\n top: 2,\n width: 16,\n height: 16,\n borderRadius: '50%',\n background: NODE_COLOR[step.status] ?? NODE_COLOR.pending,\n border: `3px solid ${tokens.surface}`,\n boxShadow: `0 0 0 1px ${tokens.border}`,\n }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>\n <span style={{ fontWeight: 600, fontSize: 14, color: tokens.text }}>{step.title}</span>\n <Badge variant={stepStatusVariant(step.status)} size=\"sm\">\n {step.status}\n </Badge>\n <span style={{ fontSize: 12, color: tokens.faint }}>\n {step.completedAt ? formatDateTime(step.completedAt) : step.startedAt ? formatDateTime(step.startedAt) : ''}\n </span>\n </div>\n {step.detail ? <div style={{ fontSize: 13, color: tokens.muted, marginTop: 3 }}>{step.detail}</div> : null}\n {step.logs ? (\n <pre\n style={{\n marginTop: 8,\n background: tokens.surface2,\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n padding: '9px 12px',\n fontFamily: 'var(--font-mono, ui-monospace, monospace)',\n fontSize: 11.5,\n color: tokens.muted,\n whiteSpace: 'pre-wrap',\n overflowX: 'auto',\n }}\n >\n {step.logs}\n </pre>\n ) : null}\n </div>\n)\n\nconst RunTimeline: React.FC<{ run: ByolDeployment }> = ({ run }) => (\n <div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14, flexWrap: 'wrap' }}>\n <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600, color: tokens.text, textTransform: 'capitalize' }}>\n {run.action} run\n </h3>\n <Badge variant={run.status === 'succeeded' ? 'success' : run.status === 'failed' ? 'danger' : 'info'} size=\"sm\">\n {run.status}\n </Badge>\n <span style={{ fontSize: 12, color: tokens.faint }}>started {formatDateTime(run.startedAt)}</span>\n </div>\n <div style={{ position: 'relative', paddingLeft: 26 }}>\n <span style={{ position: 'absolute', left: 8, top: 4, bottom: 4, width: 2, background: tokens.border }} />\n {run.steps.map((s, i) => (\n <StepNode key={s.id || s.key} step={s} last={i === run.steps.length - 1} />\n ))}\n </div>\n </div>\n)\n\nexport interface ActivityTabProps {\n deployments: ByolDeployment[]\n}\n\n/** The deployment run log: the latest run as a live timeline, older runs below. */\nexport const ActivityTab: React.FC<ActivityTabProps> = ({ deployments }) => {\n if (deployments.length === 0) {\n return (\n <EmptyState\n title=\"No deployment activity yet\"\n description=\"When you deploy this environment, each provisioning step will stream here.\"\n />\n )\n }\n const [latest, ...previous] = deployments\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 28 }}>\n <RunTimeline run={latest} />\n {previous.length > 0 ? (\n <div>\n <h4 style={{ margin: '0 0 10px', fontSize: 12, letterSpacing: '.06em', textTransform: 'uppercase', color: tokens.faint }}>\n Earlier runs\n </h4>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {previous.map((run) => (\n <div\n key={run.id}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 10,\n padding: '10px 14px',\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n background: tokens.surface,\n fontSize: 13,\n }}\n >\n <span style={{ textTransform: 'capitalize', color: tokens.text }}>{run.action}</span>\n <span style={{ color: tokens.faint }}>{formatDateTime(run.startedAt)}</span>\n <Badge variant={run.status === 'succeeded' ? 'success' : run.status === 'failed' ? 'danger' : 'info'} size=\"sm\">\n {run.status}\n </Badge>\n </div>\n ))}\n </div>\n </div>\n ) : null}\n </div>\n )\n}\n","import React from 'react'\nimport { EmptyState } from '../../ui'\nimport { isRunning } from '../status'\nimport type { ByolInfrastructure, ByolResource } from '../types'\nimport { tokens, Panel } from './shared'\n\nconst mono = 'var(--font-mono, ui-monospace, monospace)'\n\n/**\n * Resolve a usable network host from a resource's external ref. The provisioner\n * reports the managed DNS FQDN (`foundation/dns`) and the load balancer's DNS\n * name (`ingest/hec` → the ALB `dns_name`) as real hostnames; other refs are\n * ARNs, ids, or — before real provisioning has reported anything — placeholders.\n * Only a value that is genuinely a hostname or URL is returned; everything else\n * yields null so the UI never presents a non-reachable string as an endpoint.\n */\nfunction asHost(ref: string | null | undefined): string | null {\n if (!ref) return null\n const v = ref.trim()\n if (/^https?:\\/\\//i.test(v)) {\n try {\n return new URL(v).host\n } catch {\n return null\n }\n }\n // A DNS hostname: dot-separated labels, alphanumerics/hyphens, TLD ≥ 2 chars.\n const HOSTNAME = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,}$/i\n return HOSTNAME.test(v) ? v : null\n}\n\nconst Row: React.FC<{ label: string; value: string }> = ({ label, value }) => (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: '180px 1fr',\n gap: 16,\n alignItems: 'center',\n padding: '11px 0',\n borderBottom: `1px solid ${tokens.border}`,\n fontSize: 13,\n }}\n >\n <span style={{ color: tokens.muted }}>{label}</span>\n <span style={{ fontFamily: mono, fontSize: 12.5, color: tokens.text, overflowWrap: 'anywhere' }}>{value}</span>\n </div>\n)\n\nexport interface AccessTabProps {\n infra: ByolInfrastructure\n resources: ByolResource[]\n}\n\n/**\n * How to reach the environment once it is running. Every endpoint is derived\n * from the REAL external references the provisioning worker writes onto the\n * resource rows (the managed DNS name, the load balancer, the indexer peers) —\n * nothing is fabricated. Until the worker has reported a reachable endpoint, the\n * tab says so plainly rather than inventing a placeholder host.\n */\nexport const AccessTab: React.FC<AccessTabProps> = ({ infra, resources }) => {\n if (!isRunning(infra.status)) {\n return (\n <EmptyState\n title=\"Endpoints appear once the environment is running\"\n description=\"Deploy the environment; when the search tier is up, its Splunk Web, management and HEC endpoints show here.\"\n />\n )\n }\n\n const refOf = (planKey: string): string | null =>\n resources.find((r) => r.planKey === planKey)?.externalRef ?? null\n\n // Managed DNS FQDN is the friendly host for Splunk Web + management; the ALB\n // DNS name (reported on ingest/hec) is where HEC lives and a fallback host.\n const dnsHost = asHost(refOf('foundation/dns'))\n const albHost = asHost(refOf('ingest/hec'))\n const webHost = dnsHost ?? albHost\n const hecHost = albHost ?? dnsHost\n\n // Forwarder targets: only indexer peers that have reported a real address.\n const indexerTargets = resources\n .filter((r) => r.kind === 'indexer')\n .map((r) => asHost(r.externalRef))\n .filter((h): h is string => Boolean(h))\n .map((h) => `${h}:9997`)\n\n const endpoints: Array<{ label: string; value: string }> = []\n if (webHost) {\n endpoints.push({ label: 'Splunk Web (search)', value: `https://${webHost}` })\n endpoints.push({ label: 'Management API', value: `https://${webHost}:8089` })\n }\n if (hecHost) {\n endpoints.push({ label: 'HTTP Event Collector', value: `https://${hecHost}:8088/services/collector` })\n }\n\n // Running, but the worker hasn't published a reachable endpoint yet (e.g. the\n // load balancer / DNS name is still settling). Be honest — no invented host.\n if (endpoints.length === 0) {\n return (\n <Panel title=\"Endpoints\">\n <p style={{ margin: 0, fontSize: 13, lineHeight: 1.6, color: tokens.muted }}>\n The environment is running, but the provisioner has not reported a reachable endpoint yet.\n Splunk Web, the management API and the HTTP Event Collector URL appear here as soon as the\n load balancer and DNS name are published. Check the <strong>Resources</strong> tab for each\n component&rsquo;s external reference.\n </p>\n </Panel>\n )\n }\n\n const tcpoutGroup = infra.name.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'veltrix_splunk'\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Panel title=\"Endpoints\">\n {endpoints.map((e) => (\n <Row key={e.label} label={e.label} value={e.value} />\n ))}\n </Panel>\n\n <Panel title=\"Point a forwarder at this environment\">\n {indexerTargets.length > 0 ? (\n <>\n <p style={{ margin: '0 0 12px', fontSize: 13, color: tokens.muted }}>\n Add this to a universal forwarder&rsquo;s <span style={{ fontFamily: mono }}>outputs.conf</span>:\n </p>\n <pre\n style={{\n margin: 0,\n background: tokens.surface2,\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n padding: '13px 15px',\n fontFamily: mono,\n fontSize: 12,\n color: tokens.text,\n overflowX: 'auto',\n }}\n >\n {`[tcpout]\ndefaultGroup = ${tcpoutGroup}\n\n[tcpout:${tcpoutGroup}]\nserver = ${indexerTargets.join(', ')}\nsslVerifyServerCert = true`}\n </pre>\n </>\n ) : (\n <p style={{ margin: 0, fontSize: 13, color: tokens.muted }}>\n Forwarder targets appear here once the indexer peers report their addresses.\n </p>\n )}\n </Panel>\n </div>\n )\n}\n","import React from 'react'\nimport { EmptyState } from '../../ui'\nimport type { ByolConfigLink } from '../types'\nimport { tokens } from './shared'\n\nexport interface ConfigurationTabProps {\n /** App-supplied configuration links (the SDK stays app-agnostic). */\n links: ByolConfigLink[]\n /** Base path to config canvases, e.g. `/apps/splunk-enterprise/config`. */\n configBase?: string\n}\n\n/** Deep-links to the app's configuration surfaces — configure the running env. */\nexport const ConfigurationTab: React.FC<ConfigurationTabProps> = ({ links, configBase }) => {\n if (!links || links.length === 0) {\n return (\n <EmptyState\n title=\"No configuration surfaces linked\"\n description=\"This app has not surfaced any configuration links for its BYOL environments.\"\n />\n )\n }\n\n const resolve = (link: ByolConfigLink): string | undefined => {\n if (configBase && link.configTypeId) return `${configBase}/${link.configTypeId}`\n return link.href\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>\n <p style={{ margin: 0, fontSize: 13, color: tokens.muted }}>\n Once the environment is running, configure it as code. These open the app&rsquo;s configuration surfaces.\n </p>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 12 }}>\n {links.map((link) => {\n const url = resolve(link)\n const inner = (\n <>\n <h4 style={{ margin: '0 0 4px', fontSize: 13, display: 'flex', justifyContent: 'space-between', color: tokens.text }}>\n {link.title}\n <span style={{ color: tokens.faint }} aria-hidden>\n ↗\n </span>\n </h4>\n <p style={{ margin: 0, fontSize: 12, color: tokens.muted }}>{link.description}</p>\n </>\n )\n const cardStyle: React.CSSProperties = {\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n padding: 14,\n background: tokens.surface,\n textDecoration: 'none',\n color: 'inherit',\n display: 'block',\n cursor: url ? 'pointer' : 'default',\n opacity: url ? 1 : 0.7,\n }\n return url ? (\n <a key={link.key} href={url} style={cardStyle}>\n {inner}\n </a>\n ) : (\n <div key={link.key} style={cardStyle} title=\"This link is unavailable here\">\n {inner}\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport { Button } from '../../ui'\nimport { SELF_HOSTED_LABEL, type ByolInfrastructure } from '../types'\nimport { isNotStarted } from '../status'\nimport { tokens, Panel } from './shared'\n\nconst Row: React.FC<{ label: string; value: React.ReactNode }> = ({ label, value }) => (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: '200px 1fr',\n gap: 16,\n padding: '11px 0',\n borderBottom: `1px solid ${tokens.border}`,\n fontSize: 13,\n }}\n >\n <span style={{ color: tokens.muted }}>{label}</span>\n <span style={{ color: tokens.text, fontWeight: 600 }}>{value}</span>\n </div>\n)\n\nexport interface SettingsTabProps {\n infra: ByolInfrastructure\n busy: boolean\n onEdit: () => void\n onDestroy: () => void\n onDelete: () => void\n}\n\n/** Topology summary + the danger zone (destroy / delete). */\nexport const SettingsTab: React.FC<SettingsTabProps> = ({ infra, busy, onEdit, onDestroy, onDelete }) => {\n const provider = infra.hosting_type || (infra.cloudProviderId ? 'Cloud' : SELF_HOSTED_LABEL)\n const neverDeployed = isNotStarted(infra.status)\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Panel\n title=\"Topology\"\n actions={\n <Button variant=\"ghost\" size=\"sm\" onClick={onEdit} disabled={busy}>\n Edit\n </Button>\n }\n >\n <Row label=\"Name\" value={infra.name} />\n <Row label=\"Deployment type\" value={infra.deploymentType ?? '—'} />\n <Row label=\"Indexers / Search heads\" value={`${infra.indexerCount ?? '—'} / ${infra.searchHeadCount ?? '—'}`} />\n <Row label=\"Provider\" value={provider} />\n <Row label=\"Region\" value={infra.region || '—'} />\n <Row label=\"Environment\" value={infra.environmentType || '—'} />\n </Panel>\n\n <div style={{ border: `1px solid ${tokens.danger}`, borderRadius: 12, padding: '16px 18px' }}>\n <h3 style={{ margin: '0 0 4px', fontSize: 14, color: tokens.danger }}>Danger zone</h3>\n <p style={{ margin: '0 0 12px', fontSize: 13, color: tokens.muted }}>\n {neverDeployed\n ? 'This environment has not been deployed. Deleting removes the record and its plan.'\n : 'Destroy tears down every resource in the plan — instances, storage, network. This cannot be undone.'}\n </p>\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>\n {!neverDeployed ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={onDestroy} disabled={busy}>\n Destroy infrastructure\n </Button>\n ) : null}\n <Button variant=\"danger\" size=\"sm\" onClick={onDelete} disabled={busy}>\n Delete record\n </Button>\n </div>\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport { Modal, Button, Badge, Spinner } from '../../ui'\nimport { planHasChanges, type ByolPlan } from '../diffPlan'\nimport { tokens } from './shared'\nimport { PlanGroup } from './planLines'\n\n// =============================================================================\n// ByolPlanModal — a Terraform-style \"Plan\" preview shown before Apply.\n//\n// Renders the side-effect-free plan returned by `GET /byol/:id/plan`: header\n// summary chips (`+N to add · ~M to change · −Z to destroy`), then every\n// resource line grouped by tier in provisioning order, each tagged with a\n// +/~/− action glyph. The footer's primary Apply button triggers the real\n// deploy (the caller wires it to POST /deploy) and is disabled when the plan is\n// a no-op. App-agnostic: no app-specific strings live here.\n// =============================================================================\n\nexport interface ByolPlanModalProps {\n isOpen: boolean\n onClose: () => void\n /** The computed plan, or null while it is still loading. */\n plan: ByolPlan | null\n /** True while the plan is being fetched. */\n loading?: boolean\n /** A plan-fetch or apply error to surface inline. */\n error?: string | null\n /** True while Apply is in flight. */\n applying?: boolean\n /** Invoked by the primary Apply button. */\n onApply: () => void\n /** Optional environment name, shown in the subtitle. */\n infraName?: string\n /**\n * Allow Apply even when the plan has no add/change/destroy — for a redeployable\n * environment (a failed or never-deployed infra) where the user is RE-running\n * the same plan rather than making a change.\n */\n allowApplyWithoutChanges?: boolean\n}\n\n/** A titled, bordered panel matching the modal's card styling. */\nconst InfoPanel: React.FC<{ title: string; children: React.ReactNode }> = ({ title, children }) => (\n <div style={{ border: `1px solid ${tokens.border}`, borderRadius: 8, background: tokens.surface2, overflow: 'hidden' }}>\n <div\n style={{\n padding: '8px 12px',\n borderBottom: `1px solid ${tokens.border}`,\n fontSize: 11,\n letterSpacing: '.08em',\n textTransform: 'uppercase',\n color: tokens.primary,\n fontWeight: 700,\n }}\n >\n {title}\n </div>\n <div style={{ padding: '10px 12px' }}>{children}</div>\n </div>\n)\n\n/** Network panel: the subnet the allocator will carve, or a soft-unavailable note. */\nconst NetworkPanel: React.FC<{ plan: ByolPlan }> = ({ plan }) => {\n if (!plan.network) {\n if (!plan.networkUnavailable) return null\n return (\n <InfoPanel title=\"Network\">\n <div style={{ fontSize: 13, color: tokens.muted }}>\n Subnet allocation preview is temporarily unavailable — the CIDR is reserved when you apply.\n </div>\n </InfoPanel>\n )\n }\n return (\n <InfoPanel title=\"Network\">\n <div style={{ fontSize: 13, color: tokens.text }}>\n Subnet{' '}\n <code style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', color: tokens.primary }}>\n {plan.network.subnetCidr}\n </code>{' '}\n will be allocated in{' '}\n <code style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', color: tokens.text }}>\n {plan.network.networkRef}\n </code>\n .\n </div>\n </InfoPanel>\n )\n}\n\n/** Tags panel: every canonical cost/tenant tag each resource will carry. */\nconst TagsPanel: React.FC<{ plan: ByolPlan }> = ({ plan }) => {\n const entries = plan.tags ? Object.entries(plan.tags) : []\n if (entries.length === 0) return null\n return (\n <InfoPanel title=\"Tags applied to every resource\">\n <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '4px 12px', fontSize: 12 }}>\n {entries.map(([key, value]) => (\n <React.Fragment key={key}>\n <span\n style={{\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n color: tokens.muted,\n whiteSpace: 'nowrap',\n }}\n >\n {key}\n </span>\n <span style={{ color: tokens.text, wordBreak: 'break-all' }}>{value}</span>\n </React.Fragment>\n ))}\n </div>\n </InfoPanel>\n )\n}\n\nconst SummaryChips: React.FC<{ plan: ByolPlan }> = ({ plan }) => {\n const { add, change, destroy } = plan.summary\n return (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>\n <Badge variant=\"success\" size=\"sm\">+{add} to add</Badge>\n <Badge variant=\"warning\" size=\"sm\">~{change} to change</Badge>\n <Badge variant=\"danger\" size=\"sm\">−{destroy} to destroy</Badge>\n {plan.summary.noop > 0 ? (\n <span style={{ fontSize: 12, color: tokens.faint }}>{plan.summary.noop} unchanged</span>\n ) : null}\n </div>\n )\n}\n\nconst PlanBody: React.FC<{\n plan: ByolPlan | null\n loading?: boolean\n error?: string | null\n allowApplyWithoutChanges?: boolean\n}> = ({ plan, loading, error, allowApplyWithoutChanges }) => {\n if (loading) {\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '24px 0', color: tokens.muted, fontSize: 13 }}>\n <Spinner size=\"sm\" /> Computing plan…\n </div>\n )\n }\n if (error) {\n return <div style={{ padding: '12px 0', color: tokens.danger, fontSize: 13 }}>{error}</div>\n }\n if (!plan) return null\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <SummaryChips plan={plan} />\n <NetworkPanel plan={plan} />\n <TagsPanel plan={plan} />\n {!planHasChanges(plan.summary) ? (\n <div\n style={{\n fontSize: 13,\n color: tokens.muted,\n background: tokens.surface2,\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n padding: '10px 14px',\n }}\n >\n {allowApplyWithoutChanges\n ? 'No plan changes — the previous run did not complete. Apply to re-run the deployment with the same plan.'\n : 'No changes. Infrastructure is up to date.'}\n </div>\n ) : (\n plan.groups.map((group) => <PlanGroup key={group.tier} tier={group.tier} items={group.items} />)\n )}\n </div>\n )\n}\n\n/**\n * The Plan modal. Fetch the plan into `plan` (showing `loading` first), then let\n * the user Apply. Apply is disabled while loading, while applying, and when the\n * plan has no add/change/destroy.\n */\nexport const ByolPlanModal: React.FC<ByolPlanModalProps> = ({\n isOpen,\n onClose,\n plan,\n loading,\n error,\n applying,\n onApply,\n infraName,\n allowApplyWithoutChanges,\n}) => {\n const noChanges = !plan || !planHasChanges(plan.summary)\n const applyDisabled = loading || applying || (noChanges && !allowApplyWithoutChanges)\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n size=\"lg\"\n title=\"Review deployment plan\"\n subtitle={infraName ? `Changes that will be applied to ${infraName}.` : 'Changes that will be applied to this environment.'}\n disableBackdropClose={applying}\n footer={\n <>\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose} disabled={applying}>\n Cancel\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={onApply} isLoading={applying} disabled={applyDisabled}>\n Apply\n </Button>\n </>\n }\n >\n <PlanBody plan={plan} loading={loading} error={error} allowApplyWithoutChanges={allowApplyWithoutChanges} />\n </Modal>\n )\n}\n\nexport default ByolPlanModal\n","// =============================================================================\n// BYOL plan diff (pure, React-free).\n//\n// Terraform-style \"what will change\" arithmetic: given the CURRENT persisted\n// resource rows and the DESIRED plan derived from topology, classify every\n// resource by `planKey` into add / change / destroy / noop. This is the exact,\n// non-mutating mirror of the set arithmetic `seedResources` performs when it\n// persists a plan (delete rows not in the plan + upsert the rest) — so a Plan\n// preview and the subsequent Apply agree by construction.\n//\n// It is the single source of truth for the Plan → Apply UX:\n// • the app SERVER computes it for `GET /byol/:id/plan` (a side-effect-free\n// dry-run), returning `buildByolPlan(current, desired)`, and\n// • the SDK renders the returned `ByolPlan` in the Plan modal.\n//\n// Kept React-free (no imports beyond the topology tier order) so it can run on\n// either side. NOTE: like the topology, the app server keeps its OWN copy\n// (apps/<id>/lib/byolPlanDiff.ts) rather than importing this at runtime — an app\n// must not depend on a root/byol SDK export that may be absent in the pinned\n// @veltrixsecops/app-sdk version. Keep the two in sync.\n// =============================================================================\n\nimport { TIER_ORDER } from './topology'\nimport type { ByolTags } from './tags'\n\n/** A single resource's disposition in a plan. */\nexport type PlanAction = 'add' | 'change' | 'destroy' | 'noop'\n\n/** The minimal shape of a CURRENT persisted resource row diffPlan compares. */\nexport interface PlanDiffCurrent {\n planKey: string\n tier: string\n kind: string\n name: string\n role: string | null\n region: string | null\n /** A `failed`/`attention` row is always re-planned as a change. */\n status?: string\n}\n\n/** The minimal shape of a DESIRED topology plan item diffPlan compares. */\nexport interface PlanDiffDesired {\n planKey: string\n tier: string\n kind: string\n name: string\n role: string | null\n region: string | null\n sortOrder?: number\n}\n\n/** The four buckets of a diff, keyed by `planKey`. add/change/noop hold the\n * desired item (the target state); destroy holds the current row being removed. */\nexport interface PlanDiff {\n add: PlanDiffDesired[]\n change: PlanDiffDesired[]\n destroy: PlanDiffCurrent[]\n noop: PlanDiffDesired[]\n}\n\n/** Count of each action — the header summary of the Plan modal. */\nexport interface ByolPlanSummary {\n add: number\n change: number\n destroy: number\n noop: number\n}\n\n/** One resource line in the plan, tagged with its action for the modal. */\nexport interface ByolPlanItem {\n planKey: string\n action: PlanAction\n name: string\n role: string | null\n region: string | null\n kind: string\n}\n\n/** Plan lines grouped by tier, in provisioning order. */\nexport interface ByolPlanGroup {\n tier: string\n items: ByolPlanItem[]\n}\n\n/** The subnet the platform network allocator previewed / reserved for a stack. */\nexport interface ByolPlanNetwork {\n /** Opaque handle to the shared per-(provider,region) Network (VPC/VNet/…). */\n networkRef: string\n /** The /24 subnet CIDR carved for this stack, e.g. `10.20.4.0/24`. */\n subnetCidr: string\n}\n\n/**\n * The full `GET /byol/:id/plan` response contract.\n *\n * The core diff (`summary` + `groups`) is computed by `buildByolPlan`; the app\n * server ENRICHES the response with `network` (a dry-run subnet peek) + `tags`\n * (the canonical tenant/cost tag set). Both are optional so the modal degrades\n * gracefully: `networkUnavailable` flags that the allocator was unreachable, and\n * `network` is simply absent for a self-hosted stack where it does not apply.\n */\nexport interface ByolPlan {\n summary: ByolPlanSummary\n groups: ByolPlanGroup[]\n /** Subnet the allocator would carve for this stack (peek), when applicable. */\n network?: ByolPlanNetwork\n /** Canonical tenant / cost-allocation tags every resource will carry. */\n tags?: ByolTags\n /** Soft flag: the network allocator was unreachable, so `network` is absent. */\n networkUnavailable?: boolean\n}\n\nconst nz = (v: string | null | undefined): string | null => (v == null ? null : v)\n\n/** True when a current row's identifying fields differ from the desired item. */\nfunction differs(current: PlanDiffCurrent, desired: PlanDiffDesired): boolean {\n return (\n current.tier !== desired.tier ||\n current.kind !== desired.kind ||\n current.name !== desired.name ||\n nz(current.role) !== nz(desired.role) ||\n nz(current.region) !== nz(desired.region)\n )\n}\n\n/** A row that failed / needs attention is re-planned (Retry re-provisions it). */\nfunction needsReplan(status?: string): boolean {\n return status === 'failed' || status === 'attention'\n}\n\n/**\n * Diff the desired topology plan against the current persisted rows.\n *\n * • add — desired keys with no current row\n * • change — desired keys whose current row differs (tier/kind/name/role/\n * region) or is failed/attention\n * • destroy — current rows whose key is no longer desired\n * • noop — desired keys whose current row already matches\n *\n * Pure and non-mutating: it never touches its inputs.\n */\nexport function diffPlan(current: PlanDiffCurrent[], desired: PlanDiffDesired[]): PlanDiff {\n const currentByKey = new Map(current.map((c) => [c.planKey, c]))\n const desiredKeys = new Set(desired.map((d) => d.planKey))\n\n const add: PlanDiffDesired[] = []\n const change: PlanDiffDesired[] = []\n const noop: PlanDiffDesired[] = []\n\n for (const item of desired) {\n const existing = currentByKey.get(item.planKey)\n if (!existing) add.push(item)\n else if (differs(existing, item) || needsReplan(existing.status)) change.push(item)\n else noop.push(item)\n }\n\n const destroy = current.filter((c) => !desiredKeys.has(c.planKey))\n\n return { add, change, destroy, noop }\n}\n\n/** Order a tier by its provisioning position (unknown tiers sort last). */\nfunction tierRank(tier: string): number {\n const idx = (TIER_ORDER as readonly string[]).indexOf(tier)\n return idx === -1 ? TIER_ORDER.length : idx\n}\n\n/**\n * Compute the full plan response from current + desired: the action counts plus\n * every resource line grouped by tier in provisioning order. Destroyed rows are\n * appended within their tier (they retain their tier but not a desired order).\n */\nexport function buildByolPlan(current: PlanDiffCurrent[], desired: PlanDiffDesired[]): ByolPlan {\n const diff = diffPlan(current, desired)\n const summary: ByolPlanSummary = {\n add: diff.add.length,\n change: diff.change.length,\n destroy: diff.destroy.length,\n noop: diff.noop.length,\n }\n\n const action = new Map<string, PlanAction>()\n for (const d of diff.add) action.set(d.planKey, 'add')\n for (const d of diff.change) action.set(d.planKey, 'change')\n for (const d of diff.noop) action.set(d.planKey, 'noop')\n\n type Ranked = ByolPlanItem & { tier: string; rank: number }\n const lines: Ranked[] = []\n\n desired.forEach((d, i) => {\n lines.push({\n tier: d.tier,\n rank: d.sortOrder ?? i,\n planKey: d.planKey,\n action: action.get(d.planKey) ?? 'noop',\n name: d.name,\n role: nz(d.role),\n region: nz(d.region),\n kind: d.kind,\n })\n })\n // Destroyed rows have no desired order; place them after the desired items.\n const tail = desired.length\n diff.destroy.forEach((c, i) => {\n lines.push({\n tier: c.tier,\n rank: tail + i,\n planKey: c.planKey,\n action: 'destroy',\n name: c.name,\n role: nz(c.role),\n region: nz(c.region),\n kind: c.kind,\n })\n })\n\n lines.sort((a, b) => tierRank(a.tier) - tierRank(b.tier) || a.rank - b.rank)\n\n const groups: ByolPlanGroup[] = []\n const byTier = new Map<string, ByolPlanGroup>()\n for (const line of lines) {\n let group = byTier.get(line.tier)\n if (!group) {\n group = { tier: line.tier, items: [] }\n byTier.set(line.tier, group)\n groups.push(group)\n }\n group.items.push({\n planKey: line.planKey,\n action: line.action,\n name: line.name,\n role: line.role,\n region: line.region,\n kind: line.kind,\n })\n }\n\n return { summary, groups }\n}\n\n/** Whether a plan has any actionable change (drives the modal's Apply gate). */\nexport function planHasChanges(summary: ByolPlanSummary): boolean {\n return summary.add + summary.change + summary.destroy > 0\n}\n","import React from 'react'\nimport { TIER_LABELS, type ByolResourceTier } from '../topology'\nimport type { PlanAction, ByolPlan } from '../diffPlan'\nimport { tokens } from './shared'\n\n// =============================================================================\n// planLines — the resource-row rendering shared by every Terraform-style plan\n// preview: the Apply-plan modal (`ByolPlanModal`, add/change/destroy/noop) and\n// the Destroy-plan modal (`DestroyPlanModal`, destroy-only). Kept in one place\n// so the two stay pixel-identical and neither duplicates the other's markup.\n// =============================================================================\n\n/** Per-action visual language: glyph + colour + short label. */\nexport const ACTION_META: Record<PlanAction, { glyph: string; color: string; label: string }> = {\n add: { glyph: '+', color: tokens.success, label: 'add' },\n change: { glyph: '~', color: tokens.warning, label: 'change' },\n destroy: { glyph: '−', color: tokens.danger, label: 'destroy' },\n noop: { glyph: '·', color: tokens.faint, label: 'no change' },\n}\n\nexport const tierLabel = (tier: string): string =>\n TIER_LABELS[tier as ByolResourceTier] ?? tier.replace(/-/g, ' ')\n\n/** One resource line in a plan, tagged with its +/~/− action glyph. */\nexport const PlanLine: React.FC<{ item: ByolPlan['groups'][number]['items'][number] }> = ({ item }) => {\n const meta = ACTION_META[item.action]\n return (\n <div\n style={{\n position: 'relative',\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n background: tokens.surface,\n padding: '10px 12px 10px 14px',\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n overflow: 'hidden',\n }}\n >\n <span style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 3, background: meta.color }} />\n <span\n aria-hidden\n title={meta.label}\n style={{\n flex: 'none',\n width: 20,\n height: 20,\n borderRadius: 5,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontWeight: 700,\n fontSize: 14,\n lineHeight: 1,\n color: meta.color,\n background: tokens.surface2,\n }}\n >\n {meta.glyph}\n </span>\n <div style={{ minWidth: 0, flex: 1 }}>\n <div style={{ fontWeight: 600, fontSize: 13, color: tokens.text, textDecoration: item.action === 'destroy' ? 'line-through' : 'none' }}>\n {item.name}\n </div>\n {item.role ? <div style={{ fontSize: 11, color: tokens.faint }}>{item.role}</div> : null}\n </div>\n <span style={{ fontSize: 11, color: tokens.muted, flex: 'none' }}>{item.region || '—'}</span>\n </div>\n )\n}\n\n/** A titled group of plan lines for one provisioning tier. */\nexport const PlanGroup: React.FC<{ tier: string; items: ByolPlan['groups'][number]['items'] }> = ({ tier, items }) => (\n <div>\n <h3\n style={{\n margin: '0 0 8px',\n fontSize: 12,\n letterSpacing: '.08em',\n textTransform: 'uppercase',\n color: tokens.primary,\n }}\n >\n {tierLabel(tier)}\n </h3>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {items.map((item) => (\n <PlanLine key={item.planKey} item={item} />\n ))}\n </div>\n </div>\n)\n","import React, { useMemo } from 'react'\nimport { Alert, Badge, Button, Modal, Spinner } from '../../ui'\nimport { buildByolPlan } from '../diffPlan'\nimport type { ByolResource } from '../types'\nimport { tokens } from './shared'\nimport { PlanGroup } from './planLines'\n\n// =============================================================================\n// DestroyPlanModal — the Destroy-side counterpart of `ByolPlanModal`.\n//\n// \"Destroy infrastructure\" used to show a generic \"Destroy all resources? This\n// cannot be undone.\" text confirmation. That hid exactly what would be torn\n// down. This renders a real Terraform-style destroy plan instead: every CURRENT\n// resource as a destroy (−) line, grouped by tier — built by feeding the\n// current resources through `buildByolPlan(current, [])` (an empty desired set\n// means every resource is classified `destroy`), so it shares the exact plan\n// model AND row rendering (`PlanGroup`/`PlanLine`) the Apply-plan modal uses.\n// Only on confirming the in-modal danger Destroy button does the caller invoke\n// the real `/destroy` action — never a native dialog.\n// =============================================================================\n\nexport interface DestroyPlanModalProps {\n isOpen: boolean\n onClose: () => void\n /** The current persisted resources this destroy will tear down; null while (re)loading. */\n resources: ByolResource[] | null\n /** True while the resource inventory is being (re)loaded. */\n loading?: boolean\n /** A destroy-action error (from the `/destroy` call itself) to surface inline. */\n error?: string | null\n /** True while the destroy request is in flight. */\n destroying?: boolean\n /** Invoked by the primary (danger) Destroy button. */\n onConfirm: () => void\n /** Optional environment name, shown in the subtitle. */\n infraName?: string\n}\n\n/**\n * The Destroy modal. Shows every resource in `resources` as a destroy line\n * grouped by tier. Destroy stays enabled even when the inventory hasn't\n * loaded or is empty — the underlying `/destroy` action doesn't depend on this\n * preview, so an unavailable/empty list must never block the user from tearing\n * an environment down, only inform them the resource list itself was unavailable.\n */\nexport const DestroyPlanModal: React.FC<DestroyPlanModalProps> = ({\n isOpen,\n onClose,\n resources,\n loading,\n error,\n destroying,\n onConfirm,\n infraName,\n}) => {\n const plan = useMemo(() => (resources ? buildByolPlan(resources, []) : null), [resources])\n const destroyCount = plan?.summary.destroy ?? 0\n const confirmDisabled = loading || destroying\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n size=\"lg\"\n title=\"Destroy infrastructure\"\n subtitle={\n infraName\n ? `Every resource for \"${infraName}\" will be torn down.`\n : 'Every resource for this environment will be torn down.'\n }\n disableBackdropClose={destroying}\n footer={\n <>\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose} disabled={destroying}>\n Cancel\n </Button>\n <Button variant=\"danger\" size=\"sm\" onClick={onConfirm} isLoading={destroying} disabled={confirmDisabled}>\n Destroy\n </Button>\n </>\n }\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Alert variant=\"danger\" title=\"This cannot be undone\">\n Destroying removes every instance, storage volume, and network resource provisioned for this environment.\n </Alert>\n\n {error ? <div style={{ fontSize: 13, color: tokens.danger }}>{error}</div> : null}\n\n {loading ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 0', color: tokens.muted, fontSize: 13 }}>\n <Spinner size=\"sm\" /> Loading current resources…\n </div>\n ) : (\n <>\n <Badge variant=\"danger\" size=\"sm\">−{destroyCount} to destroy</Badge>\n {plan && plan.groups.length > 0 ? (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n {plan.groups.map((group) => (\n <PlanGroup key={group.tier} tier={group.tier} items={group.items} />\n ))}\n </div>\n ) : (\n <div\n style={{\n fontSize: 13,\n color: tokens.muted,\n background: tokens.surface2,\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n padding: '10px 14px',\n }}\n >\n No resource inventory is available for this environment — it will still be destroyed.\n </div>\n )}\n </>\n )}\n </div>\n </Modal>\n )\n}\n\nexport default DestroyPlanModal\n","import React from 'react'\n\n// =============================================================================\n// icons — inline SVG icons for the BYOL infrastructure detail sidebar.\n//\n// These replace the raw Unicode symbol glyphs (◈ ▦ ◷ …) the sidebar used to\n// render. Those glyphs only appeared when the active font happened to contain\n// them; inside the platform shell (Inter) they collapsed to blank/\"tofu\", which\n// is why the section icons \"disappeared\" in production. Inline SVGs are\n// font-independent, render identically everywhere, need no icon dependency, and\n// are CSP-safe (no external asset). They paint with `currentColor`, so each\n// icon automatically tracks its button's colour (active = brand, idle = muted).\n//\n// Paths are the corresponding lucide icons (ISC-licensed), inlined.\n// =============================================================================\n\nexport interface IconProps {\n /** Square edge length in px. */\n size?: number\n /** Extra styles merged onto the <svg> (colour comes from `currentColor`). */\n style?: React.CSSProperties\n}\n\n/** Shared <svg> frame — consistent viewBox, stroke language, and a11y hiding. */\nconst Svg: React.FC<IconProps & { children: React.ReactNode }> = ({ size = 16, style, children }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n focusable={false}\n style={{ display: 'block', flex: 'none', ...style }}\n >\n {children}\n </svg>\n)\n\n/** Overview — dashboard panels. */\nexport const OverviewIcon: React.FC<IconProps> = (p) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"9\" rx=\"1\" />\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"5\" rx=\"1\" />\n <rect x=\"14\" y=\"12\" width=\"7\" height=\"9\" rx=\"1\" />\n <rect x=\"3\" y=\"16\" width=\"7\" height=\"5\" rx=\"1\" />\n </Svg>\n)\n\n/** Resources — stacked servers (the provisioned infrastructure). */\nexport const ResourcesIcon: React.FC<IconProps> = (p) => (\n <Svg {...p}>\n <rect x=\"2\" y=\"2\" width=\"20\" height=\"8\" rx=\"2\" />\n <rect x=\"2\" y=\"14\" width=\"20\" height=\"8\" rx=\"2\" />\n <line x1=\"6\" y1=\"6\" x2=\"6.01\" y2=\"6\" />\n <line x1=\"6\" y1=\"18\" x2=\"6.01\" y2=\"18\" />\n </Svg>\n)\n\n/** Activity — the deployment/event pulse. */\nexport const ActivityIcon: React.FC<IconProps> = (p) => (\n <Svg {...p}>\n <path d=\"M22 12h-4l-3 9L9 3l-3 9H2\" />\n </Svg>\n)\n\n/** Access — a key (credentials / who can reach it). */\nexport const AccessIcon: React.FC<IconProps> = (p) => (\n <Svg {...p}>\n <circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\" />\n <path d=\"m21 2-9.6 9.6\" />\n <path d=\"m15.5 7.5 3 3L22 7l-3-3\" />\n </Svg>\n)\n\n/** Configuration — sliders (tunable settings that link out to config pages). */\nexport const ConfigurationIcon: React.FC<IconProps> = (p) => (\n <Svg {...p}>\n <line x1=\"21\" y1=\"4\" x2=\"14\" y2=\"4\" />\n <line x1=\"10\" y1=\"4\" x2=\"3\" y2=\"4\" />\n <line x1=\"21\" y1=\"12\" x2=\"12\" y2=\"12\" />\n <line x1=\"8\" y1=\"12\" x2=\"3\" y2=\"12\" />\n <line x1=\"21\" y1=\"20\" x2=\"16\" y2=\"20\" />\n <line x1=\"12\" y1=\"20\" x2=\"3\" y2=\"20\" />\n <line x1=\"14\" y1=\"2\" x2=\"14\" y2=\"6\" />\n <line x1=\"8\" y1=\"10\" x2=\"8\" y2=\"14\" />\n <line x1=\"16\" y1=\"18\" x2=\"16\" y2=\"22\" />\n </Svg>\n)\n\n/** Settings — a cog (record-level settings + danger zone). */\nexport const SettingsIcon: React.FC<IconProps> = (p) => (\n <Svg {...p}>\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2Z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </Svg>\n)\n","import React from 'react'\nimport { Button, Input, Select } from '../ui'\nimport { tokens } from './detail/shared'\nimport {\n type ClusterPlacement,\n type PlacementGranularity,\n type PlacementSite,\n PLACEMENT_GRANULARITY_OPTIONS,\n} from './types'\nimport { allocateNodesBySite, validatePlacement } from './placement'\n\n// =============================================================================\n// Per-cluster placement editor: single-site, or multi-site spread by percent\n// across availability zones (same region) or regions. Used for the indexer and\n// search-head clusters only — every other tier is always in the main region.\n// =============================================================================\n\ninterface ClusterPlacementFieldProps {\n label: string\n placement: ClusterPlacement\n /** Node count for this cluster — drives the live \"→ N nodes\" preview. */\n nodeCount: number\n /** The deployment's main region — the single-site home and the AZ prefix. */\n primaryRegion: string\n /** Cloud provider code (aws|azure|gcp|hetzner) — zone naming differs per cloud. */\n providerCode?: string\n /** Cloud regions offered when spreading by region. */\n regionOptions: Array<{ value: string; label: string }>\n onChange: (placement: ClusterPlacement) => void\n}\n\nconst MODE_OPTIONS = [\n { value: 'single', label: 'Single site — all nodes in the main region' },\n { value: 'multi-site', label: 'Multi-site — spread nodes by percent' },\n]\n\n// Availability-zone naming differs per cloud: AWS `us-east-1a`, GCP `us-central1-a`,\n// Azure numeric zones (1/2/3). Hetzner has no in-location AZs — use region granularity.\nconst AWS_AZ_LETTERS = ['a', 'b', 'c', 'd', 'e', 'f']\nconst GCP_AZ_LETTERS = ['a', 'b', 'c', 'd', 'f']\nconst AZURE_ZONES = ['1', '2', '3']\n\nfunction azOptionsFor(providerCode: string | undefined, region: string): Array<{ value: string; label: string }> {\n const code = (providerCode || 'aws').toLowerCase()\n const base = region || 'region'\n if (code === 'azure') return AZURE_ZONES.map((z) => ({ value: z, label: `Zone ${z}` }))\n if (code === 'gcp') return GCP_AZ_LETTERS.map((l) => ({ value: `${base}-${l}`, label: `${base}-${l}` }))\n return AWS_AZ_LETTERS.map((l) => ({ value: `${base}${l}`, label: `${base}${l}` }))\n}\n\n/** Integer percents summing to 100, with the remainder on the first sites. */\nfunction evenPercents(count: number): number[] {\n if (count <= 0) return []\n const base = Math.floor(100 / count)\n const remainder = 100 - base * count\n return Array.from({ length: count }, (_, i) => base + (i < remainder ? 1 : 0))\n}\n\nfunction defaultSites(\n granularity: PlacementGranularity,\n primaryRegion: string,\n providerCode: string | undefined,\n regionOptions: Array<{ value: string; label: string }>,\n): PlacementSite[] {\n const [p0, p1] = evenPercents(2)\n if (granularity === 'az') {\n const az = azOptionsFor(providerCode, primaryRegion)\n return [\n { site: az[0]?.value ?? `${primaryRegion}a`, percent: p0 },\n { site: az[1]?.value ?? `${primaryRegion}b`, percent: p1 },\n ]\n }\n const regions = regionOptions.map((o) => o.value).filter(Boolean)\n const first = primaryRegion || regions[0] || ''\n const second = regions.find((r) => r !== first) ?? ''\n return [\n { site: first, percent: p0 },\n { site: second, percent: p1 },\n ]\n}\n\nexport const ClusterPlacementField: React.FC<ClusterPlacementFieldProps> = ({\n label,\n placement,\n nodeCount,\n primaryRegion,\n providerCode,\n regionOptions,\n onChange,\n}) => {\n const multi = placement.mode === 'multi-site'\n const granularity: PlacementGranularity = placement.granularity ?? 'az'\n const sites = placement.sites ?? []\n const siteOptions = granularity === 'az' ? azOptionsFor(providerCode, primaryRegion) : regionOptions\n\n const emit = (next: PlacementSite[]) => onChange({ mode: 'multi-site', granularity, sites: next })\n\n const setMode = (mode: string) => {\n if (mode !== 'multi-site') return onChange({ mode: 'single' })\n onChange({\n mode: 'multi-site',\n granularity,\n sites: sites.length >= 2 ? sites : defaultSites(granularity, primaryRegion, providerCode, regionOptions),\n })\n }\n\n const setGranularity = (value: string) => {\n const g = value as PlacementGranularity\n // Sites are granularity-specific (AZ ids vs region codes) — reset to defaults.\n onChange({ mode: 'multi-site', granularity: g, sites: defaultSites(g, primaryRegion, providerCode, regionOptions) })\n }\n\n const updateSite = (i: number, patch: Partial<PlacementSite>) =>\n emit(sites.map((s, idx) => (idx === i ? { ...s, ...patch } : s)))\n\n const addSite = () => {\n const used = new Set(sites.map((s) => s.site))\n const nextSite = siteOptions.map((o) => o.value).find((v) => !used.has(v)) ?? ''\n emit([...sites, { site: nextSite, percent: 0 }])\n }\n\n const removeSite = (i: number) => emit(sites.filter((_, idx) => idx !== i))\n\n const distributeEvenly = () => {\n const percents = evenPercents(sites.length)\n emit(sites.map((s, i) => ({ ...s, percent: percents[i] })))\n }\n\n const allocation = multi ? allocateNodesBySite(nodeCount, sites) : []\n const validationError = multi ? validatePlacement(placement, nodeCount) : null\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>\n <Select label={label} value={placement.mode} onChange={setMode} options={MODE_OPTIONS} />\n\n {multi ? (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: 10,\n padding: 12,\n border: `1px solid ${tokens.border}`,\n borderRadius: 8,\n background: tokens.surface2,\n }}\n >\n <Select\n label=\"Spread across\"\n value={granularity}\n onChange={setGranularity}\n options={[...PLACEMENT_GRANULARITY_OPTIONS]}\n />\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n {sites.map((site, i) => (\n <div key={i} style={{ display: 'grid', gridTemplateColumns: '1fr 92px auto auto', gap: 8, alignItems: 'end' }}>\n <Select\n label={i === 0 ? (granularity === 'az' ? 'Zone' : 'Region') : undefined}\n value={site.site}\n onChange={(value) => updateSite(i, { site: value })}\n options={siteOptions}\n placeholder=\"Select…\"\n />\n <Input\n label={i === 0 ? 'Share %' : undefined}\n type=\"number\"\n min={0}\n max={100}\n value={String(site.percent)}\n onChange={(e) => updateSite(i, { percent: Number(e.target.value) || 0 })}\n fullWidth\n />\n <span style={{ fontSize: 12, color: tokens.muted, paddingBottom: 10, whiteSpace: 'nowrap' }}>\n → {allocation[i]?.count ?? 0} node{(allocation[i]?.count ?? 0) === 1 ? '' : 's'}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => removeSite(i)}\n disabled={sites.length <= 2}\n aria-label={`Remove site ${i + 1}`}\n style={{ marginBottom: 4 }}\n >\n ✕\n </Button>\n </div>\n ))}\n </div>\n\n <div style={{ display: 'flex', gap: 8 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={addSite} disabled={sites.length >= siteOptions.length}>\n Add site\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={distributeEvenly}>\n Distribute evenly\n </Button>\n </div>\n\n {validationError ? (\n <p style={{ margin: 0, fontSize: 12, color: tokens.danger }}>{validationError}</p>\n ) : (\n <p style={{ margin: 0, fontSize: 12, color: tokens.muted }}>\n {sites.length} sites · {allocation.reduce((n, a) => n + a.count, 0)} of {nodeCount} nodes placed.\n </p>\n )}\n </div>\n ) : null}\n </div>\n )\n}\n","// =============================================================================\n// BYOL tenant / cost-allocation tag builder (pure, React-free).\n//\n// Every Veltrix-provisioned object (the allocated subnet + every environment\n// resource) is stamped with a CANONICAL tag set so cloud spend can be attributed\n// per customer / per app and tenants stay isolated within the shared Network.\n// These keys are the platform-wide contract — billing reconciliation and the\n// least-privilege IAM policy (`Veltrix:ManagedBy=Veltrix`) rely on them, so an\n// app may ADD its own tags but must never rename or drop these.\n//\n// Derived entirely from context the app already holds (customerId, the infra\n// record, appId) — no I/O, no cloud round-trip — so it runs identically on the\n// Plan preview (`GET /byol/:id/plan`) and the Apply commit\n// (`POST /byol/:id/deploy`), keeping the previewed tags and the applied tags\n// equal by construction. Kept React-free so any BYOL app can reuse it server-side.\n//\n// NOTE: like the topology + plan diff, the app server keeps its OWN copy\n// (apps/<id>/lib/byolTags.ts) rather than importing this at runtime — an app must\n// not depend on a byol/root SDK export that may be absent in the pinned\n// @veltrixsecops/app-sdk version. Keep the two in sync.\n// =============================================================================\n\n/** Context a BYOL tag set is derived from — everything the app already holds. */\nexport interface ByolTagInput {\n /** Tenant id — cost attribution + tenant isolation. */\n customerId: string\n /**\n * Human-readable, unique tenant shortname (set in Settings → Organization).\n * Used as the `Veltrix:Customer` value so cloud tags are legible; falls back\n * to `customerId` when the tenant has not set one.\n */\n customerShortName?: string | null\n /** Unique environment id (the infrastructure record id). */\n infrastructureId: string\n /** Human environment name. */\n name: string\n /** Environment class, e.g. prod / staging / dev. */\n environmentType: string\n /** Owning app, e.g. `splunk-enterprise`. */\n appId: string\n /** Billing account / cost center; falls back to `customerId`. */\n costCenter?: string | null\n /** Initiating user / owner; falls back to `customerId`. */\n owner?: string | null\n}\n\n/** An ordered tag map. Insertion order IS the canonical display order. */\nexport type ByolTags = Record<string, string>\n\n/**\n * The canonical tag keys, in the order they are emitted. Exported so callers +\n * tests can assert against the contract without re-deriving it.\n */\nexport const BYOL_TAG_KEYS = [\n 'Veltrix:Customer',\n 'Veltrix:Environment',\n 'Veltrix:EnvName',\n 'Veltrix:EnvType',\n 'Veltrix:App',\n 'Veltrix:ManagedBy',\n 'CostCenter',\n 'Owner',\n] as const\n\n/** The constant value stamped on `Veltrix:ManagedBy` (drives tag-scoped IAM). */\nexport const MANAGED_BY = 'Veltrix'\n\n/** Coerce a tag value to a trimmed string (tags are always strings). */\nfunction s(value: string | null | undefined): string {\n return String(value ?? '').trim()\n}\n\n/**\n * Build the canonical cost-allocation / tenant-isolation tag set for a BYOL\n * environment. Pure: the same input always yields the same ordered map.\n *\n * Veltrix:Customer = customerShortName ?? customerId\n * Veltrix:Environment = infrastructureId (unique env id)\n * Veltrix:EnvName = name\n * Veltrix:EnvType = environmentType (prod / staging / …)\n * Veltrix:App = appId (splunk-enterprise, …)\n * Veltrix:ManagedBy = Veltrix (constant; tag-scoped IAM)\n * CostCenter = costCenter ?? the customer label\n * Owner = owner ?? the customer label\n */\nexport function buildByolTags(input: ByolTagInput): ByolTags {\n const customerId = s(input.customerId)\n // Prefer the human-readable shortname; fall back to the UUID when unset.\n const customerLabel = s(input.customerShortName) || customerId\n const costCenter = s(input.costCenter) || customerLabel\n const owner = s(input.owner) || customerLabel\n\n // Object literal in canonical key order — string keys preserve insertion order.\n return {\n 'Veltrix:Customer': customerLabel,\n 'Veltrix:Environment': s(input.infrastructureId),\n 'Veltrix:EnvName': s(input.name),\n 'Veltrix:EnvType': s(input.environmentType),\n 'Veltrix:App': s(input.appId),\n 'Veltrix:ManagedBy': MANAGED_BY,\n CostCenter: costCenter,\n Owner: owner,\n }\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","s","import_react","s","out","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","s","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","Row","import_jsx_runtime","import_jsx_runtime","React","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","s","authFetch","import_jsx_runtime","s","import_jsx_runtime"]}