PageSourceSearch

https://zop.dev/zopnight/app/assets/CloudAccountsPage-DJERBCkP.js

js zop.dev collected 2026-09-25 14:34:51 UTC 191,012 bytes, 9 lines download raw bytes

1import{j as e,r as l,L as fs,f as hr,u as fr}from"./react-vendor-CSsSSEML.js";import{u as gs}from"./useUsers-CuI5bcSX.js";import{bl as gr,bm as Yt,B as G,F as B,K as H,R as Xe,z as de,x as fe,y as et,bn as bs,bo as yt,bp as br,bq as me,br as jt,bs as yr,D as Se,I as oe,bt as Ie,bu as ge,bv as ys,bw as Je,bx as jr,by as _t,bz as js,bA as Qe,bB as Rt,bC as Pt,bD as vr,aS as Lt,bE as vs,bF as kr,bG as wr,bH as Nr,S as vt,E as Fe,f as Te,bI as Ar,bJ as Cr,a3 as Sr,bK as Ir,P as $e,r as We,bL as Mr,G as Dt,bM as ks,bN as ws,bO as Ns,bP as As,k as _r,bQ as Rr,bR as Pr,bS as Lr,c as Dr,h as Ze,bT as qe,i as He,bU as Er,bV as Cs,bW as zr,bX as ft,bY as Or,bZ as Tr,b_ as $r,b$ as gt,j as Qt,c0 as Xt,c1 as es,c2 as Fr,c3 as Wr}from"./index-BVsjb7mB.js";import{u as Ss}from"./useTeams-DCi7LYev.js";import{S as Et}from"./SearchInput-DLZe8zNw.js";import{S as Ur}from"./SearchableSelect-BM_5_tjW.js";import{C as Is}from"./Card-BaivSs1M.js";import{C as zt}from"./ConfirmDialog-BvaLv-yh.js";import{r as Gr,D as ts,w as ss}from"./disconnectNextStep-vuXIiiaA.js";import{A as Ms,b as Kr,R as _s,r as Br,a as Zr,c as pt,C as Ot,D as qr,s as Hr,d as Vr}from"./DiscoverySummary--a6RPBsE.js";import{P as Tt}from"./Pagination-BnDSIG0w.js";import{c as Jr,d as tt,b as rs}from"./tanstack-vendor-D2LStv3_.js";import{u as Rs}from"./useResources-Dn15QQUL.js";import{T as Yr}from"./Tabs-i18bnVDL.js";import{I as Ct}from"./InfoTooltip-riKjpznF.js";import{K as Qr}from"./KebabMenu-CVuFmoGR.js";import{u as Ps}from"./usePaginationParams-DdbHn6XS.js";import{u as $t}from"./useDebouncedValue-x0dK07ix.js";import{D as bt}from"./DataTable-CQvcDxIv.js";import{E as Ft}from"./ErrorState-CE1mnLGb.js";import{u as Ls}from"./useCloudAccountPermissions-DTfn7R6n.js";import{I as Xr,u as en,a as Ds,R as tn}from"./IAMImportDrawer-CVt4YFzm.js";import{S as xe}from"./SelectionCard-CIusnYz_.js";(function(){try{var t=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{};t.SENTRY_RELEASE={id:"33b2f1a2eb67da61a8a79f4c3c0fca45c630c2e5"};var s=new t.Error().stack;s&&(t._sentryDebugIds=t._sentryDebugIds||{},t._sentryDebugIds[s]="e693d46c-ae4f-4cd1-b1f4-f1afdcdfb8f9",t._sentryDebugIdIdentifier="sentry-dbid-e693d46c-ae4f-4cd1-b1f4-f1afdcdfb8f9")}catch{}})();const sn=["roles/resourcemanager.projectIamAdmin","roles/serviceusage.serviceUsageAdmin","roles/iam.serviceAccountAdmin","roles/iam.serviceAccountKeyAdmin"],rn=[{action:"Bind roles to the service account",role:"Project IAM Admin"},{action:"Enable required Google Cloud APIs",role:"Service Usage Admin"},{action:"Create a service account (zopnight-sa)",role:"Service Account Admin"},{action:"Generate service account credentials",role:"Service Account Key Admin"}];function nn({permissionLevel:t,onOAuthConnect:s,oauthLoading:r,buttonLabel:a}){const i=new Set(gr("zopnight","gcp")),n=(t==="read_write"?Yt("zopnight","gcp","write"):Yt("zopnight","gcp","read")).filter(o=>!i.has(o));return e.jsxs("div",{className:"py-4 space-y-4",children:[e.jsxs("div",{className:"bg-amber-500/10 border border-amber-500/30 rounded-lg p-3 text-xs space-y-2",children:[e.jsx("p",{className:"font-medium text-amber-400 text-[0.8125rem]",children:"Prerequisites"}),e.jsxs("p",{className:"text-text-secondary",children:["Your Google account needs ",e.jsx("code",{className:"text-text-primary",children:"roles/owner"})," on the project, or roles covering all of these. Any role that carries the same permissions works — including a custom role, or one you inherit from a folder or organisation:"]}),e.jsx("ul",{className:"space-y-0.5 list-disc list-inside text-text-secondary",children:sn.map(o=>e.jsx("li",{children:e.jsx("code",{className:"text-text-primary",children:o})},o))})]}),e.jsxs("div",{className:"bg-surface-tertiary rounded-lg p-3 text-xs text-text-secondary space-y-2",children:[e.jsx("p",{className:"font-medium text-text-primary text-[0.8125rem]",children:"What we'll do on your behalf"}),e.jsx("ul",{className:"space-y-1",children:rn.map(o=>e.jsxs("li",{className:"flex justify-between gap-2",children:[e.jsx("span",{children:o.action}),e.jsx("span",{className:"text-text-muted shrink-0",children:o.role})]},o.action))}),e.jsx("p",{className:"pt-1 text-text-muted",children:"No further authorization will be needed after this step."})]}),e.jsxs("div",{className:"bg-surface-tertiary rounded-lg p-3 text-xs text-text-secondary space-y-1.5",children:[e.jsxs("p",{className:"font-medium text-text-primary text-[0.8125rem]",children:["Roles granted to service account (",t==="read_write"?"read + write":"read only",")"]}),e.jsx("ul",{className:"space-y-0.5 list-disc list-inside",children:n.map(o=>e.jsx("li",{children:e.jsx("code",{className:"text-text-primary",children:o})},o))})]}),e.jsx("div",{className:"text-center",children:e.jsx(G,{onClick:s,disabled:r,children:r?"Redirecting...":a})})]})}const Es={aws:[{value:"assume_role",label:"WIF-Assume Role",recommended:!0,description:"Uses a cross-account IAM role via Workload Identity Federation. No credentials to store, rotate, or leak."},{value:"static_keys",label:"IAM User (Static Keys)",description:"Connects via a long-lived IAM user with access keys. Familiar setup, but requires ongoing key management."},{value:"temporary_credentials",label:"Temporary Credentials",description:"Uses short-lived STS tokens generated from IAM user keys. Credentials expire and must be regenerated periodically."}],gcp:[{value:"oauth",label:"One-Click Connect",recommended:!0,description:"Sign in with Google and grant access — no keys to manage"},{value:"service_account",label:"Service Account Key",description:"Create a service account and download the JSON key"}],azure:[{value:"service_principal",label:"Service Principal",recommended:!0,description:"Register an app and create a client secret"},{value:"workload_identity_federation",label:"Workload Identity Federation",description:"Federated credentials using OIDC — no client secrets"}],snowflake:[{value:"snowflake_key_pair",label:"Key-Pair (RSA)",recommended:!0,description:"Uses an RSA key pair registered on a dedicated service user. No network policy to manage."},{value:"snowflake_pat",label:"Programmatic Access Token",description:"Uses a time-limited access token scoped to a role. Requires a network policy allow-listing ZopNight's IP."}],openshift:[{value:"ocm_service_account",label:"OCM Service Account",recommended:!0,description:"A service account created in the Red Hat Hybrid Cloud Console. One account covers every ROSA cluster in your organisation."}]},Le={provider:"",authMethod:"",permissionLevel:"read_write",openshiftAccess:"",name:"",accessKeyId:"",secretAccessKey:"",sessionToken:"",roleArn:"",gcpServiceAccountKey:"",azureSubscriptionId:"",azureTenantId:"",azureClientId:"",azureClientSecret:"",azureResourceGroups:[],azureScope:"subscription",snowflakeAccount:"",snowflakeUser:"",snowflakePrivateKey:"",snowflakePassphrase:"",snowflakePAT:"",snowflakeRole:"",snowflakeWarehouse:"",openshiftClientId:"",openshiftClientSecret:"",databricksAccountId:"",databricksClientId:"",databricksClientSecret:"",databricksHost:"",databricksCloud:"",databricksKind:""}
1,ns={aws:"accounts.cloud.databricks.com",gcp:"accounts.gcp.databricks.com",azure:"accounts.azuredatabricks.net"};function zs(t){return ns[t]??ns.aws}function an(t){return{host:t.databricksHost?.trim()||zs(t.provider),accountId:t.databricksAccountId?.trim()??"",clientId:t.databricksClientId?.trim()??"",clientSecret:t.databricksClientSecret?.trim()??""}}const on=/^[A-Za-z0-9-]{3,}\.[A-Za-z0-9-]{3,}(\.[A-Za-z0-9]+)?$/,ze=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,cn=/^arn:aws:iam::\d{12}:role\/.+$/;function Ce(t){const s={};if(t.provider==="aws"&&(t.authMethod==="static_keys"&&(t.accessKeyId?(!/^(AKIA|ASIA)/.test(t.accessKeyId)||t.accessKeyId.length!==20)&&(s.accessKeyId="Access Key IDs start with AKIA (or ASIA for temporary) and are 20 characters."):s.accessKeyId="Required",t.secretAccessKey?t.secretAccessKey.length!==40&&(s.secretAccessKey="Secret Access Keys are 40 characters long."):s.secretAccessKey="Required"),t.authMethod==="assume_role"&&(t.roleArn?cn.test(t.roleArn)||(s.roleArn="Role ARN should look like arn:aws:iam::123456789012:role/RoleName"):s.roleArn="Required"),t.authMethod==="temporary_credentials"&&(t.accessKeyId?/^ASIA/.test(t.accessKeyId)||(s.accessKeyId="Temporary credentials start with ASIA, not AKIA."):s.accessKeyId="Required",t.secretAccessKey?t.secretAccessKey.length!==40&&(s.secretAccessKey="Secret Access Keys are 40 characters long."):s.secretAccessKey="Required",t.sessionToken||(s.sessionToken="Session token is required for temporary credentials."))),t.provider==="gcp"&&t.authMethod==="service_account")if(!t.gcpServiceAccountKey)s.gcpServiceAccountKey="Required";else try{const r=JSON.parse(t.gcpServiceAccountKey);r.project_id?r.private_key?r.type!=="service_account"&&(s.gcpServiceAccountKey="This doesn't look like a service account key."):s.gcpServiceAccountKey="Missing private_key. The key file appears incomplete.":s.gcpServiceAccountKey="Missing project_id. Make sure this is a service account key."}catch{s.gcpServiceAccountKey="Invalid JSON format. Paste the entire key file."}return t.provider==="azure"&&(t.authMethod==="service_principal"&&(t.azureTenantId?ze.test(t.azureTenantId)||(s.azureTenantId="Must be a valid UUID"):s.azureTenantId="Required",t.azureClientId?ze.test(t.azureClientId)||(s.azureClientId="Must be a valid UUID"):s.azureClientId="Required",t.azureClientSecret||(s.azureClientSecret="Required")),t.authMethod==="workload_identity_federation"&&(t.azureScope!=="tenant"&&(t.azureSubscriptionId?ze.test(t.azureSubscriptionId)||(s.azureSubscriptionId="Must be a valid UUID (e.g., xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)"):s.azureSubscriptionId="Required"),t.azureTenantId?ze.test(t.azureTenantId)||(s.azureTenantId="Must be a valid UUID"):s.azureTenantId="Required",t.azureClientId?ze.test(t.azureClientId)||(s.azureClientId="Must be a valid UUID"):s.azureClientId="Required")),t.provider==="snowflake"&&(t.snowflakeAccount?on.test(t.snowflakeAccount)||(s.snowflakeAccount="Account identifier should look like xy12345.us-east-1.aws (locator.region.cloud)"):s.snowflakeAccount="Required",t.snowflakeUser||(s.snowflakeUser="Required"),t.authMethod==="snowflake_key_pair"&&(t.snowflakePrivateKey?t.snowflakePrivateKey.includes("PRIVATE KEY")||(s.snowflakePrivateKey="Paste a PEM-encoded PKCS8 RSA private key (begins with -----BEGIN PRIVATE KEY-----)"):s.snowflakePrivateKey="Required"),t.authMethod==="snowflake_pat"&&(t.snowflakePAT||(s.snowflakePAT="Required"))),t.provider==="databricks"&&(t.databricksAccountId?.trim()?ze.test(t.databricksAccountId.trim())||(s.databricksAccountId="Databricks Account IDs are UUIDs (e.g. xxxxxxxx-xxxx-...)."):s.databricksAccountId="Required",t.databricksClientId?.trim()||(s.databricksClientId="Required"),t.databricksClientSecret?.trim()||(s.databricksClientSecret="Required")),t.provider==="openshift"&&(t.openshiftClientId?.trim()?ze.test(t.openshiftClientId.trim())||(s.openshiftClientId="This should be the service account's Client ID, a UUID like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx."):s.openshiftClientId="Required",t.openshiftClientSecret?.trim()||(s.openshiftClientSecret="Required")),t.provider!=="snowflake"&&!t.name?.trim()?s.name="Display name is required":t.name?.length>255&&(s.name="Max 255 characters"),s}function Os(t){if(t.provider==="databricks")return{provider:"databricks",name:t.name,cloudAccountId:t.databricksAccountId?.trim()??"",authMethod:"oauth_m2m",credentials:{clientId:t.databricksClientId?.trim()??"",clientSecret:t.databricksClientSecret?.trim()??"",host:zs(t.databricksCloud)}};if(t.provider==="openshift")return{provider:"openshift",name:t.name,authMethod:"ocm_service_account",credentials:{clientId:t.openshiftClientId?.trim()??"",clientSecret:t.openshiftClientSecret?.trim()??""}};const s={provider:t.provider,name:t.name,authMethod:t.authMethod,permissionLevel:t.permissionLevel};if(t.provider==="aws")t.authMethod==="static_keys"?s.credentials={accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}:t.authMethod==="assume_role"?s.credentials={roleArn:t.roleArn}:t.authMethod==="temporary_credentials"&&(s.credentials={accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken});else if(t.provider==="gcp")t.authMethod==="service_account"&&(s.credentials={serviceAccountKey:t.gcpServiceAccountKey});else if(t.provider==="azure")t.azureScope==="tenant"&&(s.scope="tenant"),t.authMethod==="service_principal"?s.credentials={tenantId:t.azureTenantId,clientId:t.azureClientId,clientSecret:t.azureClientSecret}:t.authMethod==="workload_identity_federation"&&(t.azureScope!=="tenant"&&(s.cloudAccountId=t.azureSubscriptionId),s.credentials={tenantId:t.azureTenantId,clientId:t.azureClientId});else if(t.provider==="snowflake"){s.cloudAccountId=t.snowflakeAccount,!s.name?.trim()&&t.snowflakeAccount&&(s.name=`Snowflake — ${t.snowflakeAccount}`);const r={account:t.snowflakeAccount?.trim(),user:t.snowflakeUser?.trim()};t.snowflakeRole?.trim()&&(r.role=t.snowflakeRole.trim()),t.snowflakeWarehouse?.trim()&&(r.warehouse=t.snowflakeWarehouse.trim()),t.authMethod==="snowflake_key_pair"?(r.privateKey=t.snowflakePrivateKey,t.snowflakePassphrase&&(r.passphrase=t.snowflakePassphrase)):t.authMethod==="snowflake_pat"&&(r.pat=t.snowflakePAT),s.credentials=r}return s}function ln(t){const s={account:t.snowflakeAccount?.trim(),user:t.snowflakeUser?.trim(),privateKey:t.snowflakePrivateKey||void 0,passphrase:t.snowflakePassphrase||void 0,pat:t.snowflakePAT||void 0};return t.snowflakeRole?.trim()&&(s.role=t.snowflakeRole.trim()),t.snowflakeWarehouse?.trim()&&(s.warehouse=t.snowflakeWarehouse.trim()),{provider:"snowflake",authMethod:t.authMethod,snowflake:s}}
1const as={aws:"accounts.cloud.databricks.com",gcp:"accounts.gcp.databricks.com"};function dn(t){const s=a=>e.jsx("strong",{className:"text-text-primary font-medium",children:a}),r=e.jsx("a",{href:`https://${t}`,target:"_blank",rel:"noreferrer",className:"text-primary-600 hover:underline font-medium",children:"account console"});return[e.jsxs(e.Fragment,{children:["Databricks ",r," → your ",s("avatar")," (top-right) → copy ",s("Account ID"),"."]}),e.jsxs(e.Fragment,{children:[s("User management → Service principals → Add service principal")," → name it → ",s("Add"),". Its ",s("Application ID")," = the ",s("Client ID")," below."]}),e.jsxs(e.Fragment,{children:["Open it → ",s("Credentials & secrets")," → ",s("Generate secret")," → copy the ",s("Secret")," (shown once)."]}),e.jsxs(e.Fragment,{children:["Same principal → ",s("Roles")," → enable ",s("Account admin")," (lets ZopNight list every workspace)."]}),e.jsxs(e.Fragment,{children:[s("Workspaces")," → open each → ",s("Permissions → Add permissions")," → select the principal → ",s("Admin access")," → ",s("Add permissions")," (lets ZopNight read + start/stop it)."]})]}function un({host:t}){return e.jsx("ol",{className:"space-y-2 mb-3",children:dn(t).map((s,r)=>e.jsxs("li",{className:"flex gap-2 text-xs text-text-secondary leading-relaxed",children:[e.jsx("span",{className:"shrink-0 w-[18px] h-[18px] mt-px rounded bg-surface-tertiary text-text-muted text-[11px] font-semibold inline-flex items-center justify-center",children:r+1}),e.jsx("span",{children:s})]},r))})}function Ts({values:t,onChange:s,errors:r={},showSteps:a=!0,disabled:i=!1}){return e.jsxs("div",{className:"space-y-3",children:[a&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-xs text-text-secondary leading-relaxed",children:["Create an OAuth ",e.jsx("strong",{className:"text-text-primary font-medium",children:"service principal"})," in your Databricks account console:"]}),e.jsx(un,{host:as[t?.databricksCloud]??as.aws})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[e.jsxs(B,{label:"Databricks Account ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"1a2b3c4d-5e6f-...",autoComplete:"off",value:t?.databricksAccountId??"",onChange:n=>s("databricksAccountId",n.target.value),disabled:i}),r.databricksAccountId&&e.jsx("p",{className:"text-xs text-danger-500 mt-1",children:r.databricksAccountId})]}),e.jsxs(B,{label:"OAuth Client ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"9f8e7d6c-...",autoComplete:"off",value:t?.databricksClientId??"",onChange:n=>s("databricksClientId",n.target.value),disabled:i}),r.databricksClientId&&e.jsx("p",{className:"text-xs text-danger-500 mt-1",children:r.databricksClientId})]}),e.jsxs(B,{label:"OAuth Client Secret",required:!0,children:[e.jsx(H,{type:"password",placeholder:"••••••••••••",autoComplete:"new-password",value:t?.databricksClientSecret??"",onChange:n=>s("databricksClientSecret",n.target.value),disabled:i}),r.databricksClientSecret&&e.jsx("p",{className:"text-xs text-danger-500 mt-1",children:r.databricksClientSecret})]})]})]})}function $s(t){const s=Xe(),r=Jr(),a=et.cloudAccounts.databricksCredential(s,t),i=tt({queryKey:a,queryFn:()=>fe.get(`/cloud-accounts/${t}/databricks-credential`),enabled:!!t,retry:!1}),n=()=>r.invalidateQueries({queryKey:a}),o=rs({mutationFn:d=>fe.put(`/cloud-accounts/${t}/databricks-credential`,d),onSuccess:()=>{de.success("Databricks connected"),n()},onError:d=>de.error(`Couldn't connect Databricks: ${d?.message||"Unknown error"}`)}),c=rs({mutationFn:()=>fe.del(`/cloud-accounts/${t}/databricks-credential`),onSuccess:()=>{de.success("Databricks credential removed"),n()},onError:d=>de.error(`Couldn't remove Databricks credential: ${d?.message||"Unknown error"}`)});return{query:i,save:o,remove:c}}function Fs(){return e.jsx("div",{className:"flex-1 flex items-center justify-center px-6 py-10",children:e.jsxs("div",{role:"status","aria-live":"polite",className:"w-full max-w-sm flex flex-col items-center text-center gap-3 rounded-xl bg-surface-secondary/40 px-6 py-10",children:[e.jsx("div",{className:"w-12 h-12 rounded-full bg-surface-tertiary inline-flex items-center justify-center",children:e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",className:"w-6 h-6 text-text-muted","aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"})})}),e.jsx("p",{className:"text-sm font-medium text-text-primary",children:"Permission status not available yet"}),e.jsx("p",{className:"text-xs text-text-secondary",children:"We re-check this account's permissions every few hours — the results appear here automatically."})]})})}const Ws={aws:"AWS",gcp:"GCP",azure:"Azure",snowflake:"Snowflake",microsoft365:"Microsoft 365"},xn=["zopnight"];function Wt(t){const s=Array.isArray(t)?t.filter(Boolean):[];return s.length===0?"":s.length===1?s[0]:s.length===2?`${s[0]} and ${s[1]}`:`${s.slice(0,-1).join(", ")}, and ${s[s.length-1]}`}function ue(t){return!Array.isArray(t)||t.length===0||t.length>2?"":` for ${Wt(t)}`}function mn(t){if(!t)return null;const s=Date.now()-t;if(s<6e4)return"just now";const r=Math.floor(s/6e4);if(r<60)return`${r}m ago`;const a=Math.floor(r/60);if(a<24)return`${a}h ago`;const i=Math.floor(a/24);if(i<30)return`${i}d ago`;const n=Math.floor(i/30);return n<12?`${n}mo ago`:`${Math.floor(n/12)}y ago`}function Us({open:t,onClose:s,cloudAccountId:r,cloudAccountName:a,provider:i,account:n,featureFilter:o}){const{data:c,isLoading:d,isError:f,error:x,refetch:p}=Ls(t?r:null),u=Xe(),m=n?.authMethod==="assume_role"||n?.provider==="gcp",{data:h}=tt({queryKey:et.cloudAccounts.detail(u,n?.id),queryFn:()=>fe.get(`/cloud-accounts/${n?.id}`),enabled:t&&m&&!!n?.id}),v=l.useMemo(()=>({...n??{},roleName:h?.roleName??n?.roleName,serviceAccountEmail:h?.serviceAccountEmail??n?.serviceAccountEmail}),[n,h]),w=bs(r,{enabled:t&&i==="snowflake"}),R=l.useMemo(()=>{const F=c?.permissions??[];return i==="snowflake"&&w.isLoading?F:yt(F,i,w)},[c,i,w]),$=n?.permissionLevel==="read_only"?"read":null,{featureKeys:g,strategies:k}=l.useMemo(()=>
1{if(!o)return{featureKeys:null,strategies:null};if(o instanceof Set)return{featureKeys:o,strategies:null};if(Array.isArray(o))return{featureKeys:new Set(o),strategies:null};if(typeof o=="object"){let F=null;o.features instanceof Set?F=o.features:Array.isArray(o.features)&&(F=new Set(o.features));const le=o.strategies instanceof Map?o.strategies:null;return{featureKeys:F,strategies:le}}return{featureKeys:null,strategies:null}},[o]),N=l.useMemo(()=>br(R,i,xn,{tier:$,featureKeys:g}),[R,i,$,g]),j=l.useMemo(()=>me(R),[R]),z=j?mn(j):null,T=[Ws[i]??i??"",a].filter(Boolean).join(" — "),S=l.useMemo(()=>jt(R),[R]),_=l.useMemo(()=>yr(R),[R]),D=l.useMemo(()=>R.some(F=>F.status==="granted"||F.status==="denied"),[R]),I=!S&&D&&N.length===0,V=l.useMemo(()=>{if(i!=="azure"||!g)return!1;for(const F of g)if(typeof F=="string"&&F.startsWith("databricks_discovery::"))return!0;return!1},[i,g]),q=l.useMemo(()=>{const F=pn({missingByRole:N,provider:i,account:v,strategies:k,snowflakeObjects:w});return V&&F.push({key:"databricks-workspace-admin",title:"Grant Databricks workspace access",affects:["Databricks discovery"],content:Ms.content}),F},[N,i,v,k,V,w]);return e.jsx(Se,{open:t,onClose:s,half:!0,title:e.jsxs("span",{className:"flex items-center gap-2",children:[i&&e.jsx(oe,{provider:i,className:"w-5 h-5 shrink-0"}),e.jsxs("span",{className:"truncate",children:[T," — Grant access"]})]}),children:d?e.jsx($n,{}):f?e.jsx(Ft,{title:"Couldn't load permission details",error:x,onRetry:p,resource:"permissions"}):S?e.jsx(Tn,{provider:i,errorMessage:_?.errorMessage}):q.length===0?e.jsx(En,{provider:i,hasProbeData:D,allClear:I,missingByRole:N,verifiedLabel:z}):e.jsx(In,{steps:q,verifiedLabel:z})})}function pn({missingByRole:t,provider:s,account:r,strategies:a,snowflakeObjects:i}){if(!t?.length)return[];if(s==="gcp"){const n=[],o=[];for(const d of t)kt(d,a)?n.push(d):o.push(d);const c=[];return t.some(Ks)&&c.push(wn(t)),o.length>0&&c.push(...Nn(o,r,{omitOneClick:n.length>0})),n.length>0&&c.push(...Sn(n,r)),c}return s==="aws"?bn(t,r,a):s==="azure"?fn(t,r,a):s==="snowflake"?hn(t,r,i):t.flatMap(n=>Ut(n,s,r,a))}function hn(t,s,r={}){const a=[...new Set(t.flatMap(o=>o.features?.map(Ie)??[]))].sort(),i=[];for(const o of t){const c=jr(o.perms,o.role,r);c.length!==0&&i.push([`-- ${o.role}`,`CREATE ROLE IF NOT EXISTS ${o.role};`,...c].join(`
2`))}if(i.length===0)return[];const n=["-- ZopNight — grant the missing Snowflake privileges","-- Run as ACCOUNTADMIN in a Snowsight worksheet. Safe to re-run.","","USE ROLE ACCOUNTADMIN;","",i.join(`
3
4`)].join(`
5`);return[{key:"snowflake-grants",title:`Grant access in Snowflake${ue(a)}`,affects:a,intro:"Run the statements below as **ACCOUNTADMIN** in a Snowsight worksheet. They grant only the missing privileges, scoped to your discovered warehouses and databases.",code:{payload:n,lang:"SQL"}}]}function fn(t,s,r){const a=[],i=[];for(const o of t){if(kt(o,r)||Je(o.role)){i.push(o);continue}a.push(o)}const n=[];a.length>0&&n.push(gn(a,s));for(const o of i)n.push(...Ut(o,"azure",s,r));return n}function gn(t,s){const r=ge({provider:"azure",account:s}),a=(c,d)=>d?`[${c}](${d})`:`**${c}**`,i=[...new Set(t.flatMap(c=>Array.from(c.features??[]).map(Ie)))].sort(),n=t.map(c=>c.role),o=s?.cloudAccountId?`subscription \`${s.cloudAccountId}\``:"this subscription";return{key:"azure-builtin-roles",title:`Assign the missing built-in roles${ue(i)}`,affects:i,intro:`Assign these built-in Azure roles to your ZopNight service principal on ${o}.`,rolesList:n,instructions:[`Open ${a("Access control (IAM)",r)} on ${o}.`,"Click **Add**, then **Add role assignment**.","For each role above: search for the role name on the **Role** tab, click **Next**, click **Select members**, pick your ZopNight app, click **Select**, then **Review + assign**."]}}function bn(t,s,r){const a=[],i=[],n=[];for(const c of t){const d=ys({provider:"aws",role:c.role,account:s,missingPerms:c.perms,allPermsInRole:c.allPerms});d&&(d.kind==="copy-json"?n.push(c):d.kind==="console"&&(kt(c,r)?i.push(c):a.push(c)))}const o=[];for(const c of a)o.push(...Ut(c,"aws",s,r));if(n.length>0)n.forEach((c,d)=>{o.push(jn([c],d===0?i:[],s))});else for(const c of i)o.push(Gs(c,s));return o}function kt(t,s){if(!s||s.size===0)return!1;const r=t.featureKeys??[];if(r.length===0)return!1;for(const a of r)if(s.get(a)!=="granular")return!1;return!0}function Ut(t,s,r,a){const i=ys({provider:s,role:t.role,account:r,missingPerms:t.perms,allPermsInRole:t.allPerms});if(!i)return[];if(i.kind==="workspace-admin")return[kn(t,i)];if(i.kind==="console"&&kt(t,a)){if(s==="aws")return[Gs(t,r)];if(s==="azure")return[vn(t,r)]}const n=r?.authMethod==="static_keys"||r?.authMethod==="temporary_credentials";let o;s==="aws"&&(i.kind==="copy-json"?o="policy":n&&(o="user"));const c=ge({provider:s,account:r,kind:o}),d=s!=="aws"?c:n?ge({provider:s,account:r,kind:"user"}):ge({provider:s,account:r}),f=(w,R)=>R?`[${w}](${R})`:`**${w}**`,x=[...new Set(t.features?.map(Ie)??[])].sort(),p=i.payload?{payload:i.payload,lang:Cn(i)}:null,u=[...new Set([...t.grantedPermsForReplace??[],...t.perms??[]])].sort(),m=s==="aws"?{payload:JSON.stringify(_t(u),null,2),lang:"JSON"}:s==="azure"?{payload:js(t.role,r,u),lang:"JSON"}:p;if(i.kind==="copy-json")return yn({role:t,provider:s,account:r,isUserAuth:n,consoleLinkHref:c,applyLinkHref:d,linkOrEmpty:f,affects:x,policyPayload:m});const h=(()=>
5{if(s==="aws")return n?[`Go to ${f("IAM Users",c)} in AWS Console and find your existing ZopNight user (e.g. \`zopnight-service\`).`,"On the **Permissions** tab, click the **Add permissions** button (top-right), then choose **Attach policies directly**.",`Filter by **AWS managed**, tick **${t.role}**, click **Next**, then **Add permissions** to confirm.`]:[r?.roleName?`Go to ${f("IAM Roles",c)} in AWS Console and open the \`${r.roleName}\` role.`:`Go to ${f("IAM Roles",c)} in AWS Console and open your ZopNight role.`,"On the **Permissions** tab, click the **Add permissions** button (top-right), then choose **Attach policies** from the dropdown.",`Filter by **AWS managed**, tick **${t.role}**, then click **Add permissions** to confirm.`];if(s==="azure"){const w=r?.cloudAccountId?`subscription \`${r.cloudAccountId}\``:"this subscription";return[`Open ${f("Access control (IAM)",c)} on ${w}.`,"Click **Add**, then **Add role assignment**.",`On the **Role** tab, search for **${t.role}**, select it, and click **Next**.`,"On the **Members** tab, click **Select members**, search for your ZopNight app, select it, then click **Next**.","Click **Review + assign**."]}return null})(),v=An(i.label,t.role);return[{key:`${t.product}::${t.role}`,verb:v.verb,titleName:v.name,titleSuffix:ue(x),intro:"",affects:x,instructions:h,rationale:t.status==="all-missing"?{perms:t.perms,roleName:t.role,roleFullyMissing:!0}:null,code:p}]}function yn({role:t,provider:s,account:r,isUserAuth:a,consoleLinkHref:i,applyLinkHref:n,linkOrEmpty:o,affects:c,policyPayload:d}){const f=(t?.writeCount??0)>0&&(t?.grantedWriteCount??0)===0;if(s==="aws"){const x=a?`Go to ${o("IAM Users",n)} in AWS Console and find your existing ZopNight user (e.g. \`zopnight-service\`).`:r?.roleName?`Go to ${o("IAM Roles",n)} in AWS Console and open the \`${r.roleName}\` role.`:`Go to ${o("IAM Roles",n)} in AWS Console and open your ZopNight role.`,p=a?"Attach policies directly":"Attach policies",u=a?"Add permissions":"Attach policies",m=f?t.role:dt(t),h={key:"edit",label:"Update existing policy",altLinkText:"Don't have an existing ZopNight policy? Show me how to create a new one instead",instructions:[`Open ${o("AWS IAM Policies",i)} in AWS Console, find your existing ZopNight policy (e.g. \`${t.role}\`), and click **Edit**.`,"Switch to the **JSON** tab and add the highlighted permissions below into the policy.","Click **Next**, then **Save changes**."],newPerms:t.perms,code:d},v={key:"create",label:"Create a new policy",altLinkText:f?void 0:"← Back to updating your existing ZopNight policy",instructions:[`Open ${o("AWS IAM Policies",i)} in AWS Console and click **Create policy**.`,"Switch to the **JSON** tab and replace the contents with the JSON below.",`Click **Next**, name the policy (e.g. \`${m}\`), and click **Create policy**.`,x,`On the **Permissions** tab, click the **Add permissions** button (top-right), then choose **${p}**.`,`Tick the policy you just created, then click **${u}** to confirm.`],code:d};return[{key:`${t.product}::${t.role}`,title:f?`Create your ZopNight policy${ue(c)}`:`Update your ZopNight policy${ue(c)}`,affects:c,defaultTabIdx:0,tabs:f?[v]:[h,v]}]}if(s==="azure"){const x=r?.cloudAccountId?`subscription \`${r.cloudAccountId}\``:"this subscription",p={key:"edit",label:"Update existing custom role",altLinkText:"Don't have an existing ZopNight custom role? Show me how to create a new one instead",instructions:[`Open ${o("Azure Portal",i)}, find your existing ZopNight custom role (e.g. \`${t.role}\`), and click **Edit** → **JSON**.`,"Add the highlighted actions below to the role definition.","Click **Save**."],newPerms:t.perms,code:d},u={key:"create",label:"Create a new custom role",altLinkText:f?void 0:"← Back to updating your existing custom role",instructions:[`Open ${o("Access control (IAM)",n)} on ${x}.`,"Click **Add**, then **Add custom role**.","Switch to the **JSON** tab and click **Edit**.","Replace the entire JSON with the content below, then click **Save**.","Click **Review + create**, then **Create**.","Back on **Access control (IAM)**, click **Add**, then **Add role assignment**.","On the **Role** tab, find the custom role you just created, select it, and click **Next**.","On the **Members** tab, click **Select members**, search for your ZopNight app, select it, then click **Next**.","Click **Review + assign**."],code:d};return[{key:`${t.product}::${t.role}`,verb:f?"Create":"Update",titleName:t.role,titleSuffix:ue(c),affects:c,defaultTabIdx:0,tabs:f?[u]:[p,u]}]}return[]}function dt(t){const s=o=>
5o.split(/[-_:.\s]+/).filter(Boolean).map(c=>c.charAt(0).toUpperCase()+c.slice(1).toLowerCase()).join(""),r=new Set,a=new Set;for(const o of t.featureKeys??[]){const c=o.indexOf("::"),d=c<0?o:o.slice(0,c),f=c<0?"":o.slice(c+2).trim();d&&a.add(d),f&&r.add(f)}const i=o=>[...o].sort()[0]??"",n=s(i(r)||i(a));return n?`ZopNight${n}Perms`:"ZopNightInlinePerms"}function jn(t,s,r){const a=r?.authMethod==="static_keys"||r?.authMethod==="temporary_credentials",i=ge({provider:"aws",account:r,kind:"policy"}),n=ge({provider:"aws",account:r,kind:a?"user":void 0}),o=(j,z)=>z?`[${j}](${z})`:`**${j}**`,c=[...new Set((s??[]).flatMap(j=>j.perms??[]))],d=[...new Set([...t.flatMap(j=>j.perms??[]),...c])].sort(),f=[...new Set([...t,...s??[]].flatMap(j=>j.features?.map(Ie)??[]))].sort(),x=[...new Set(t.flatMap(j=>j.grantedPermsForReplace??[]))],p=[...new Set([...x,...d])].sort(),u={payload:JSON.stringify(_t(p),null,2),lang:"JSON"},m=[...t,...s??[]],h=m.some(j=>(j.writeCount??0)>0)&&m.every(j=>(j.grantedWriteCount??0)===0),v=t[0]?.role??dt(t[0]??s[0]),w=h?v:dt(t[0]??s[0]),R=a?`Go to ${o("IAM Users",n)} in AWS Console and find your existing ZopNight user (e.g. \`zopnight-service\`).`:r?.roleName?`Go to ${o("IAM Roles",n)} in AWS Console and open the \`${r.roleName}\` role.`:`Go to ${o("IAM Roles",n)} in AWS Console and open your ZopNight role.`,$=a?"Attach policies directly":"Attach policies",g=a?"Add permissions":"Attach policies",k={key:"edit",label:"Update existing policy",altLinkText:"Don't have an existing ZopNight policy? Show me how to create a new one instead",instructions:[`Open ${o("AWS IAM Policies",i)} in AWS Console, find your existing ZopNight policy (e.g. \`${v}\`), and click **Edit**.`,"Switch to the **JSON** tab and add the highlighted permissions below into the policy.","Click **Next**, then **Save changes**."],newPerms:d,code:u},N={key:"create",label:"Create a new policy",altLinkText:h?void 0:"← Back to updating your existing ZopNight policy",instructions:[`Open ${o("AWS IAM Policies",i)} in AWS Console and click **Create policy**.`,"Switch to the **JSON** tab and replace the contents with the JSON below.",`Click **Next**, name the policy (e.g. \`${w}\`), and click **Create policy**.`,R,`On the **Permissions** tab, click **Add permissions**, then **${$}**.`,`Find the policy you just created, select it, and click **${g}**.`],code:u};return{key:m.map(j=>`${j.product}::${j.role}`).join("+")+"::pooled",title:h?`Create your ZopNight policy${ue(f)}`:`Update your ZopNight policy${ue(f)}`,affects:f,defaultTabIdx:0,tabs:h?[N]:[k,N]}}function Gs(t,s){const r=s?.authMethod==="static_keys"||s?.authMethod==="temporary_credentials",a=ge({provider:"aws",account:s,kind:r?"user":void 0}),i=(d,f)=>f?`[${d}](${f})`:`**${d}**`,n=r?`Go to ${i("IAM Users",a)} in AWS Console and find your existing ZopNight user (e.g. \`zopnight-service\`).`:s?.roleName?`Go to ${i("IAM Roles",a)} in AWS Console and open the \`${s.roleName}\` role.`:`Go to ${i("IAM Roles",a)} in AWS Console and open your ZopNight role.`,o=dt(t),c=[...new Set(t.features?.map(Ie)??[])].sort();return{key:`${t.product}::${t.role}::granular`,title:`Add a small policy${ue(c)}`,affects:c,instructions:[n,"On the **Permissions** tab, click **Add permissions**, then **Create inline policy**.","Switch to the **JSON** tab and paste the JSON below.",`Click **Next**, give the policy a name (e.g. \`${o}\`), then click **Create policy**.`],rationale:{perms:t.perms,roleName:t.role,noRoleNudge:!0},code:{payload:JSON.stringify(_t(t.perms),null,2),lang:"JSON"}}}function vn(t,s){const r=s?.cloudAccountId?`subscription \`${s.cloudAccountId}\``:"this subscription",a=ge({provider:"azure",account:s}),i=(c,d)=>d?`[${c}](${d})`:`**${c}**`,n=dt(t).replace(/Perms$/,"Custom")||"ZopnightMinimalAccess",o=[...new Set(t.features?.map(Ie)??[])].sort();return{key:`${t.product}::${t.role}::granular`,title:`Create a custom role${ue(o)}`,affects:o,intro:`Create a small custom Azure role with only the missing actions, then assign it to your ZopNight app in place of \`${t.role}\`.`,instructions:[`Open ${i("Access control (IAM)",a)} on ${r}.`,"Click the **Roles** tab, then **+ Add** → **Add custom role**.","Switch to the **JSON** tab and replace the default content with the JSON below.",`Click **Review + create**, then **Create** to save the role (e.g. named \`${n}\`).`,"Back on **Access control (IAM)**, click **+ Add** → **Add role assignment**.","On the **Role** tab, find the custom role you just created, select it, and click **Next**.","On the **Members** tab, click **Select members**, search for your ZopNight app, select it, then click **Next**.","Click **Review + assign**."],code:{payload:js(n,s,t.perms),lang:"JSON"}}}function kn(t,s){const r=[...new Set(t.features?.map(Ie)??[])].sort();return{key:`${t.product}::${t.role}::workspace-admin`,title:`Grant workspace access${ue(r)}`,affects:r,intro:s.helpText,content:Ms.content}}function Ks(t){return t?.features?.includes("cost")||t?.role?.startsWith("roles/bigquery.")}function wn(t){const s=t.filter(Ks),r=[...new Set(s.flatMap(a=>a.features?.map(Ie)??[]))].sort();
5return{key:"gcp-bq-export",title:`Enable BigQuery Cost Export${ue(r)}`,affects:r,intro:"Required for Cost reports to show data.",costNote:"GCP charges for BigQuery storage of the export plus the queries ZopNight runs against it. **$0.02/GB/month** for storage and **$6.25/TB** of data scanned, depending on your billing data volume.",instructions:["Go to [Billing → Billing Export](https://console.cloud.google.com/billing/export) in the GCP Console.","Select the **BigQuery Export** tab.","Click **Edit Settings** and choose a project and dataset for billing data.","Enable **Standard usage cost** export."]}}function Nn(t,s,r={}){const{omitOneClick:a=!1}=r,i=s?.cloudAccountId,n=s?.serviceAccountEmail||(i?`zopnight-sa@${i}.iam.gserviceaccount.com`:"the ZopNight service account"),o=ge({provider:"gcp",account:s}),c=[...new Set(t.flatMap(x=>x.features?.map(Ie)??[]))].sort(),d=t.map(x=>x.role),f=o?[`Go to [IAM & Admin → IAM](${o}) in GCP Console.`,`Find \`${n}\` in the principals list and click the pencil icon to edit it.`,"Click **+ Add another role**, then search for and select each role listed above.","Click **Save**."]:[`Open IAM & Admin → IAM in GCP Console and find \`${n}\` in the principals list.`,"Click the pencil icon to edit it.","Click **+ Add another role**, then search for and select each role listed above.","Click **Save**."];return a?[{key:"gcp-manual",title:`Add roles in GCP Console${ue(c)}`,affects:c,intro:`Add the missing roles to \`${n}\`.`,rolesList:d,instructions:f}]:[{key:"gcp-grant",title:`Grant the missing roles${ue(c)}`,affects:c,tabs:[{key:"oneclick",label:"One-Click",altLinkText:"Prefer to set this up manually in the GCP Console? Show the steps instead",intro:`Authorize ZopNight with Google to add the missing roles to \`${n}\`.`,rolesList:d,oauthReauthorize:!0,accountId:s?.id,oauthRoles:d},{key:"manual",label:"Manual",altLinkText:"← Back to the one-click option",intro:`Add the missing roles to \`${n}\` from the GCP Console.`,rolesList:d,instructions:f}]}]}function An(t,s){if(!t)return{verb:"Update",name:s};const r=["Update","Attach","Assign","Grant"];for(const a of r)if(t.startsWith(`${a} `))return{verb:a,name:t.slice(a.length+1)};return{verb:"",name:t}}function Cn(t){const s=(t?.payload??"").trimStart();return s.startsWith("{")?"JSON":s.startsWith("aws ")?"AWS CLI":s.startsWith("gcloud ")?"gcloud":s.startsWith("az ")?"Azure CLI":"Shell"}function Sn(t,s){const r=s?.cloudAccountId,a=s?.serviceAccountEmail||(r?`zopnight-sa@${r}.iam.gserviceaccount.com`:"the ZopNight service account"),i=r?`https://console.cloud.google.com/iam-admin/roles?project=${encodeURIComponent(r)}`:null,n=ge({provider:"gcp",account:s}),o=(x,p)=>p?`[${x}](${p})`:`**${x}**`,c=[...new Set(t.flatMap(x=>x.perms??[]))].sort(),d=[...new Set(t.flatMap(x=>x.features?.map(Ie)??[]))].sort();return[{key:"gcp-granular",title:`Create a custom role${ue(d)}`,affects:d,intro:`Create a custom GCP role containing only the missing permissions and bind it to \`${a}\`.`,instructions:[`Go to ${o("IAM & Admin → Roles",i)} in GCP Console.`,"Click **+ Create Role** at the top, give it a title (e.g. `zopnightMinimalAccess`), then click **+ Add Permissions**.","Search for and select each permission listed above, then click **Add**.","Click **Create** to save the custom role.",`Go to ${o("IAM & Admin → IAM",n)} and find \`${a}\`. Click the pencil icon to edit it.`,"Click **+ Add another role**, search for the custom role you just created, and select it.","Click **Save**."],rolesList:c}]}function In({steps:t,verifiedLabel:s}){const[r,a]=l.useState(0),[i,n]=l.useState(()=>new Set),o=t.length,c=o>0&&i.size===o,d=u=>{a(m=>m===u?-1:u)},f=u=>{n(m=>{const h=new Set(m);return h.has(u)?h.delete(u):(h.add(u),u+1<t.length?setTimeout(()=>a(u+1),150):setTimeout(()=>a(-1),150)),h})},x=l.useMemo(()=>{const u=new Set;for(const m of t)for(const h of m?.affects??[])u.add(h);return[...u].sort()},[t]),p=Wt(x);return e.jsxs("div",{className:"space-y-4 pb-6",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("h2",{className:"text-sm font-semibold text-text-primary",children:c?"All changes complete":x.length>0?`Grant access for ${p}`:"Grant access"}),c?e.jsx("p",{className:"text-[12px] text-text-muted leading-relaxed",children:x.length>0?`${p}
5 will start working on the next sync.`:"These features will start working on the next sync."}):o>1?e.jsxs("p",{className:"text-[12px] text-text-muted leading-relaxed",children:["Each step grants a different piece of access — complete all ",o," to unblock them."]}):null]}),e.jsx("div",{children:t.map((u,m)=>e.jsx(Mn,{step:u,index:m,isLast:m===t.length-1,totalSteps:o,expanded:r===m,completed:i.has(m),onToggle:()=>d(m),onMarkDone:()=>f(m)},u.key))}),s&&e.jsx("footer",{className:"pt-2 text-center",children:e.jsxs("p",{className:"text-[11px] text-text-muted",children:["Last verified ",s,". ZopNight resyncs permissions automatically."]})})]})}function Mn({step:t,index:s,isLast:r,totalSteps:a,expanded:i,completed:n,onToggle:o,onMarkDone:c}){const d=Array.isArray(t.tabs)&&t.tabs.length>0?t.tabs:null,[f,x]=l.useState(t.defaultTabIdx??0),u=(d?d[Math.min(f,d.length-1)]:null)??t;return e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("div",{className:"flex flex-col items-center pt-0.5",children:[e.jsx("button",{type:"button",onClick:o,className:`relative flex items-center justify-center w-8 h-8 rounded-full text-xs font-bold shrink-0 transition-all duration-200 ${n?"bg-primary-600/15 text-primary-600 border border-primary-600/30":i?"bg-primary-600 text-text-inverse shadow-[0_0_0_3px_rgba(6,182,212,0.15)]":"bg-surface-secondary text-text-muted border border-border hover:border-primary-600/30 hover:text-primary-600"}`,"aria-label":`Step ${s+1}`,children:n?e.jsx(lt,{className:"h-4 w-4"}):s+1}),!r&&e.jsx("div",{className:`w-px flex-1 mt-2 mb-0 transition-colors duration-300 ${n?"bg-primary-600/25":i?"bg-primary-600/20":"bg-border"}`})]}),e.jsxs("div",{className:`flex-1 min-w-0 ${r?"pb-0":"pb-6"}`,children:[e.jsxs("button",{type:"button",onClick:o,className:"flex items-center justify-between w-full text-left group py-1",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("h4",{className:`text-[13px] font-semibold truncate transition-colors ${n||i?"text-primary-600":"text-text-primary group-hover:text-primary-600"}`,children:t.title?t.title:e.jsxs(e.Fragment,{children:[t.verb&&e.jsxs("span",{children:[t.verb," "]}),e.jsx("code",{className:"font-mono text-current",children:t.titleName}),t.titleSuffix&&e.jsx("span",{children:t.titleSuffix})]})}),n&&!i&&e.jsx("span",{className:"text-[10px] text-primary-600/70 font-medium shrink-0",children:"Done"}),!n&&!i&&e.jsxs("span",{className:"text-[10px] text-text-muted/60 font-medium shrink-0",children:[s+1,"/",a]})]}),e.jsx("svg",{className:`h-4 w-4 text-text-muted/50 transition-transform duration-200 shrink-0 ml-2 ${i?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 8.25l-7.5 7.5-7.5-7.5"})})]}),t.affects?.length>2&&e.jsxs("p",{className:"text-[11px] text-text-muted mt-0.5",children:["Unblocks: ",e.jsx("span",{className:"text-text-secondary",children:Wt(t.affects)})]}),i&&e.jsxs("div",{className:"mt-2 rounded-xl border border-border bg-surface-secondary/40 overflow-hidden",children:[d&&d.length>1&&d[f]?.altLinkText&&e.jsx("button",{type:"button",onClick:()=>x((f+1)%d.length),className:"block w-full text-left px-4 py-2.5 text-[12px] text-primary-600 bg-primary-500/[0.06] border-b border-primary-500/20 hover:bg-primary-500/[0.1] transition-colors",children:e.jsx("span",{className:"hover:underline underline-offset-2",children:d[f].altLinkText})}),e.jsx(_n,{step:u}),e.jsxs("div",{className:"px-4 pb-4 flex items-center justify-between",children:[e.jsx("button",{type:"button",onClick:c,className:`inline-flex items-center gap-2 px-4 py-2 text-[12px] font-semibold rounded-lg transition-all ${n?"bg-primary-600/10 text-primary-600 hover:bg-primary-600/15":"bg-surface-tertiary text-text-primary border border-border hover:border-primary-600/30 hover:text-primary-600"}`,children:n?e.jsxs(e.Fragment,{children:[e.jsx(lt,{className:"h-3.5 w-3.5"}),"Completed"]}):r?e.jsxs(e.Fragment,{children:[e.jsx(lt,{className:"h-3.5 w-3.5"}),"Mark as done"]}):e.jsxs(e.Fragment,{children:["Done, next step",e.jsx("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"})})]})}),n&&!r&&e.jsx("span",{className:"text-[11px] text-text-muted",children:"Click the next step to continue"})]})]})]})]})}function _n({step:t}){return e.jsxs("div",{className:"p-4 space-y-3",children:[t.intro&&e.jsx("p",{className:"text-[13px] text-text-secondary leading-relaxed",children:e.jsx(ht,{text:t.intro})}),t.costNote&&e.jsxs("div",{className:"flex items-start gap-2 px-3 py-2 rounded-md bg-blue-500/10 border border-blue-500/20 text-[12px] text-text-secondary",children:[e.jsx("svg",{className:"w-3.5 h-3.5 mt-0.5 shrink-0 text-blue-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})}),e.jsx("span",{children:e.jsx(ht,{text:t.costNote})})]}),t.rolesList?.length>0&&e.jsx("ul",{className:"divide-y divide-border rounded-lg border border-border overflow-hidden",children:t.rolesList.map(s=>e.jsx("li",{className:"px-3 py-2 bg-surface-secondary/30",children:e.jsx("code",{className:"font-mono text-xs text-text-primary truncate block",children:s})}
5,s))}),t.rationale?.perms?.length>0&&e.jsx("div",{className:"rounded-lg border border-primary-500/30 bg-primary-500/[0.05] p-3 space-y-2",children:t.rationale.roleFullyMissing?e.jsxs("p",{className:"text-[12px] text-text-secondary leading-relaxed",children:[e.jsx("code",{className:"font-mono text-text-primary",children:t.rationale.roleName})," is not attached. Attaching it grants the permissions ZopNight needs and any future ones we may add."]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-[12px] text-text-secondary leading-relaxed",children:t.rationale.perms.length===1?"ZopNight needs this permission:":`ZopNight needs these ${t.rationale.perms.length} permissions:`}),e.jsx("ul",{className:"space-y-0.5 max-h-32 overflow-y-auto",children:t.rationale.perms.map(s=>e.jsx("li",{className:"text-[11px] font-mono text-text-primary break-all pl-3 relative before:content-['•'] before:absolute before:left-0 before:text-text-muted",children:s},s))}),!t.rationale.noRoleNudge&&e.jsxs("p",{className:"text-[12px] text-text-secondary leading-relaxed",children:["Attaching"," ",e.jsx("code",{className:"font-mono text-text-primary",children:t.rationale.roleName})," ","covers ",t.rationale.perms.length===1?"it":"them"," and any future permissions ZopNight may need."]})]})}),t.instructions?.length>0&&e.jsx("ol",{className:"text-[13px] text-text-secondary space-y-1.5 list-decimal list-inside marker:text-text-muted marker:font-semibold",children:t.instructions.map((s,r)=>e.jsx("li",{children:e.jsx(ht,{text:s})},r))}),t.content&&e.jsx("div",{className:"text-[13px] text-text-secondary space-y-1.5",children:t.content.split(`
6`).map((s,r)=>s.trim()===""?e.jsx("div",{className:"h-1"},r):e.jsx("p",{className:"leading-relaxed",children:e.jsx(ht,{text:s})},r))}),t.code&&e.jsx(Pn,{code:t.code,highlightPerms:t.newPerms}),t.oauthReauthorize&&e.jsx(Rn,{accountId:t.accountId,roles:t.oauthRoles})]})}function Rn({accountId:t,roles:s}){const[r,a]=l.useState(!1),i=async()=>{if(!(!t||r)){a(!0);try{sessionStorage.setItem("gcp_oauth_upgrade_account_id",t),Array.isArray(s)&&s.length>0?sessionStorage.setItem("gcp_oauth_upgrade_roles",JSON.stringify(s)):sessionStorage.removeItem("gcp_oauth_upgrade_roles");const n=await fe.get("/connect/gcp/oauth-url",{permissionLevel:"read_write",appBasePath:"zopnight/app"});n?.url?window.location.href=n.url:(de.error("Failed to get Google authorization URL."),a(!1))}catch(n){de.error(`Failed to start Google re-authorize: ${n?.message||"Unknown error"}`),a(!1)}}};return e.jsxs("button",{type:"button",onClick:i,disabled:r,className:"inline-flex items-center justify-center gap-2 w-full px-3 py-2.5 rounded-lg bg-primary-600 hover:bg-primary-500 disabled:opacity-60 disabled:cursor-wait transition-colors text-[13px] font-semibold text-text-inverse",children:[e.jsx(Ln,{className:"w-4 h-4"}),r?"Redirecting to Google…":"Re-authorize with Google"]})}function Pn({code:t,highlightPerms:s}){const[r,a]=l.useState(!1),i=async()=>{if(t?.payload)try{await navigator.clipboard.writeText(t.payload),a(!0),setTimeout(()=>a(!1),1500)}catch{}},n=l.useMemo(()=>{if(!t?.payload)return[];const m=t.payload;if(!s?.length)return[{text:m,highlight:!1}];const h=s.map(v=>`"${v}"`);return m.split(`
7`).map(v=>({text:v,highlight:h.some(w=>v.includes(w))}))},[t?.payload,s]),o=s?.length>0,c=l.useMemo(()=>n.reduce((m,h,v)=>
7(h.highlight&&m.push(v),m),[]),[n]),d=l.useRef(null),[f,x]=l.useState({top:0,height:100}),p=()=>{const m=d.current;if(!m)return;const h=Math.max(m.scrollHeight,1);x({top:m.scrollTop/h*100,height:m.clientHeight/h*100})};l.useEffect(()=>{p()},[n]);const u=m=>{const h=d.current;if(!h)return;const v=20,w=m*v-h.clientHeight/2+v/2;h.scrollTo({top:Math.max(0,w),behavior:"smooth"})};return e.jsxs("div",{className:"rounded-lg border border-border overflow-hidden",children:[o&&e.jsxs("div",{className:"px-3 py-2.5 bg-success-500/[0.05] border-b border-border",children:[e.jsxs("p",{className:"flex items-center gap-2 mb-1.5",children:[e.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold uppercase tracking-wider bg-success-500/15 text-success-700",children:[e.jsxs("span",{className:"font-bold",children:["+",s.length]}),e.jsx("span",{children:"new"})]}),e.jsx("span",{className:"text-[11px] text-text-secondary",children:s.length===1?"permission added in the policy below":"permissions added in the policy below"})]}),e.jsx("ul",{className:"space-y-0.5 max-h-36 overflow-y-auto pr-1",children:s.map(m=>e.jsx("li",{className:"text-[11px] font-mono text-text-secondary break-all pl-4 relative before:content-['+'] before:absolute before:left-0 before:text-success-600 before:font-bold",children:m},m))})]}),e.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 bg-surface-tertiary/80 border-b border-border",children:[e.jsx("span",{className:"text-[10px] font-semibold text-text-muted uppercase tracking-wider",children:t.lang}),e.jsxs("button",{type:"button",onClick:i,className:`flex items-center gap-1.5 px-2 py-0.5 text-[11px] font-medium rounded transition-colors ${r?"text-success-700 bg-success-500/10":"text-text-muted hover:text-text-primary hover:bg-surface-secondary"}`,children:[r?e.jsx(lt,{className:"w-3 h-3"}):e.jsx(Wn,{className:"w-3 h-3"}),r?"Copied":"Copy"]})]}),e.jsxs("div",{className:"flex bg-surface-elevated",children:[e.jsx("pre",{ref:d,onScroll:p,className:`flex-1 min-w-0 text-xs font-mono text-text-secondary overflow-x-auto max-h-72 overflow-y-auto leading-5 py-3 ${o&&c.length>0?"[scrollbar-width:none] [&::-webkit-scrollbar]:hidden":""}`,children:n.length===1&&!n[0].highlight?e.jsx("span",{className:"px-3",children:n[0].text}):n.map((m,h)=>e.jsx("div",{className:m.highlight?"px-3 bg-success-500/10 border-l-2 border-success-500/70":"px-3 border-l-2 border-transparent",children:m.text||" "},h))}),o&&c.length>0&&e.jsxs("div",{className:"relative w-2.5 shrink-0 border-l border-border bg-surface-secondary/40","aria-label":"New permission locations",children:[e.jsx("div",{className:"absolute left-0 right-0 bg-text-muted/30 rounded-sm pointer-events-none",style:{top:`${f.top}%`,height:`${Math.max(f.height,4)}%`}}),c.map(m=>e.jsx("button",{type:"button",onClick:()=>u(m),title:`Jump to line ${m+1}`,"aria-label":`Jump to new permission at line ${m+1}`,className:"absolute left-0 right-0 h-[3px] bg-success-500/80 hover:bg-success-500 hover:h-[5px] cursor-pointer transition-all z-10",style:{to
7p:`calc(${m/Math.max(n.length-1,1)*100}% - 1.5px)`}},m))]})]})]})}function Ln({className:t=""}){return e.jsxs("svg",{viewBox:"0 0 48 48",className:t,"aria-hidden":"true",children:[e.jsx("path",{fill:"#EA4335",d:"M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"}),e.jsx("path",{fill:"#4285F4",d:"M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"}),e.jsx("path",{fill:"#FBBC05",d:"M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"}),e.jsx("path",{fill:"#34A853",d:"M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"})]})}const Dn=new Set(["aws","gcp","azure"]);function En({provider:t,hasProbeData:s,allClear:r,missingByRole:a,verifiedLabel:i}){return s&&!r&&a.length>0?e.jsx(zn,{provider:t,missingByRole:a}):r?e.jsx(On,{verifiedLabel:i}):e.jsx(Fs,{})}function zn({provider:t,missingByRole:s}){return e.jsxs("div",{className:"flex-1 px-6 py-6",role:"status","aria-live":"polite",children:[e.jsx("p",{className:"text-sm font-medium text-text-primary",children:"These permissions are missing"}),e.jsx("p",{className:"mt-1 text-xs text-text-secondary",children:Dn.has(t)?`Add them to the role named below in ${Ws[t]}. ZopNight picks up the change on its next permission check.`:"We cannot grant them from here — they are granted where the account was connected, by somebody with administrative access to it."}),s.map(r=>e.jsxs("div",{className:"mt-4 rounded-xl bg-surface-secondary/40 px-4 py-3",children:[e.jsx("p",{className:"text-xs font-medium text-text-primary",children:r.role}),e.jsx("ul",{className:"mt-2 space-y-1",children:r.perms.map(a=>e.jsx("li",{className:"text-[11px] font-mono text-text-secondary break-all",children:a},a))})]},r.role))]})}function On({verifiedLabel:t}){return e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center text-center py-12",children:[e.jsxs("div",{className:"relative w-20 h-20 mb-6",children:[e.jsx("div",{className:"absolute inset-[-30%] rounded-full",style:{background:"radial-gradient(circle at center, rgba(6, 182, 212, 0.12) 0%, transparent 70%)"}}),e.jsx("div",{className:"relative w-20 h-20 inline-flex items-center justify-center rounded-2xl bg-success-500/10 text-success-700",children:e.jsx(lt,{className:"w-9 h-9"})})]}),e.jsx("h2",{className:"text-xl font-bold text-text-primary",children:"All permissions granted"}),e.jsx("p",{className:"mt-2 text-text-secondary max-w-sm text-sm",children:"Every ZopNight feature is operational on this account. No action needed."}),t&&e.jsxs("p",{className:"mt-4 text-[11px] text-text-muted",children:["Last verified ",t,". ZopNight resyncs permissions automatically."]})]})}function Tn({provider:t,errorMessage:s}){const r=t==="aws"?"ReadOnlyAccess":t==="azure"?"Reader":"the read-only role";return e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center text-center py-12 px-6 gap-4 max-w-xl mx-auto",children:[e.jsx("div",{className:"w-12 h-12 rounded-full bg-danger-400/15 text-danger-600 inline-flex items-center justify-center",children:e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"w-6 h-6",children:[e.jsx("circle",{cx:"12",cy:"12",r:"10"}),e.jsx("line",{x1:"12",y1:"8",x2:"12",y2:"12"}),e.jsx("line",{x1:"12",y1:"16",x2:"12.01",y2:"16"})]})}),e.jsx("p",{className:"text-base font-semibold text-text-primary",children:"Permissions check is blocked"}),e.jsxs("p",{className:"text-sm text-text-secondary",children:["We don't have permission to check what's granted on this cloud account. Attach the"," ",e.jsx("span",{className:"font-medium text-text-primary",children:r})," role to the principal we use, and the next sync will pick it up."]}),s&&e.jsxs("div",{className:"w-full text-left",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wider text-text-muted mb-1",children:"Cloud API response"}),e.jsx("pre",{className:"text-[11px] text-text-secondary bg-surface-tertiary border border-border rounded-md p-3 whitespace-pre-wrap break-all",children:s})]})]})}function $n(){return e.jsxs("div",{className:"space-y-4 animate-pulse",children:[e.jsx("div",{className:"h-16 bg-surface-secondary/50 rounded-lg"}),e.jsx("div",{className:"h-32 bg-surface-secondary/50 rounded-xl"}),e.jsx("div",{className:"space-y-1",children:[...Array(6)].map((t,s)=>e.jsx("div",{className:"h-8 bg-surface-secondary/40 rounded"},s))})]})}const Fn=/(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/;function ht({text:t}){return t?t.split(Fn).map((r,a)=>{if(!r)return null;if(r.startsWith("**")&&r.endsWith("**"))return e.jsx("strong",{className:"text-text-primary font-semibold",children:r.slice(2,-2)},a);if(r.startsWith("`")&&r.endsWith("`"))return e.jsx("span",{className:"font-mono text-text-primary text-[11px]",children:r.slice(1,-1)},a);const i=r.match(/^\[([^\]]+)\]\(([^)]+)\)$/);return i?e.jsx("a",{href:i[2],target:"_blank",rel:"noopener noreferrer",className:"text-primary-600 hover:underline font-medium",children:i[1]},a):e.jsx("span",{children:r},a)}):null}function lt({className:t}){return e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",className:t,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"m5 13 4 4L19 7"})})}function Wn({className:t}){return e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:t,children:[e.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),e.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})}
7const Un=/InvalidClientTokenId|UnrecognizedClientException|InvalidAccessKeyId/i,Gn="This account's credentials are invalid, revoked, or expired, so ZopNight cannot read the account.";function Kn(t){return Un.test(typeof t=="string"?t:"")}function Gt(t){const s=(Array.isArray(t)?t:[]).filter(r=>r?.status==="error");return s.length>0&&s.every(r=>r.errorMessage&&Kn(r.errorMessage))}function Bn(){return{summary:Gn}}const Zn={aws:"AWS",gcp:"GCP",azure:"Azure",snowflake:"Snowflake"},is=["zopnight"];function qn(t){if(!t)return null;const s=Date.now()-t;if(s<6e4)return"just now";const r=Math.floor(s/6e4);if(r<60)return`${r}m ago`;const a=Math.floor(r/60);return a<24?`${a}h ago`:`${Math.floor(a/24)}d ago`}function Hn({open:t,onClose:s,provider:r,cloudAccountId:a,cloudAccountName:i,account:n,onUpdateCredentials:o}){const{data:c,isLoading:d,isError:f,error:x,refetch:p}=Ls(t?a:null),u=bs(a,{enabled:t&&r==="snowflake"}),m=l.useMemo(()=>{const E=c?.permissions??[];return r==="snowflake"&&u.isLoading?E:yt(E,r,u)},[c,r,u]),h=l.useMemo(()=>jt(m)&&!Qe(m),[m]),v=l.useMemo(()=>Rt(m,r,is),[m,r]),w=Xe(),R=n?.authMethod==="assume_role"||n?.authMethod==="workload_identity_federation"||n?.provider==="gcp",{data:$}=tt({queryKey:et.cloudAccounts.detail(w,n?.id),queryFn:()=>fe.get(`/cloud-accounts/${n?.id}`),enabled:t&&R&&!!n?.id}),g=l.useMemo(()=>({...n??{},roleName:$?.roleName??n?.roleName,serviceAccountEmail:$?.serviceAccountEmail??n?.serviceAccountEmail}),[n,$]),k=l.useMemo(()=>h?!1:v.length===0?!0:v.every(E=>
7E.status!=="granted"&&E.status!=="denied"&&E.status!=="partial"),[v,h]),N=l.useMemo(()=>Qe(m)?!0:h?!1:Pt(v)&&Gt(v),[m,v,h]),j=n?.permissionLevel==="read_only"?"read":null,z=vr(n?.cloudAccountId,{enabled:t&&r==="azure"}),W=l.useMemo(()=>{if(r!=="azure"||z.length===0)return null;const E=z.every(Z=>(Z?.childCount??0)>0);return{product:"zopnight",feature:"databricks_discovery",resourceType:"",label:"Databricks discovery",description:"Discover Databricks workspaces for cost recommendations.",status:E?"granted":"needs_attention",perms:[],missingPerms:[],roles:[],primaryRole:"",counts:{granted:E?1:0,denied:E?0:1,scpRestricted:0,unknown:0,total:1},workspaceCount:z.length}},[r,z]),T=l.useMemo(()=>{if(!r||h||k)return[];let E=Lt(m,r,is);return j==="read"&&(E=E.filter(Z=>Z.perms.every(ae=>ae.category==="read"))),E},[m,r,j,h,k]),S=l.useMemo(()=>vs(T,n?.permissionLevel),[T,n?.permissionLevel]),_=l.useMemo(()=>W?[...T,W]:T,[T,W]),D=l.useMemo(()=>_.filter(E=>E.status==="needs_attention"),[_]),I=l.useMemo(()=>_.filter(E=>E.status==="granted"),[_]),V=l.useMemo(()=>T.filter(E=>E.status==="cant_verify"),[T]),q=l.useMemo(()=>kr(m),[m]),F=l.useMemo(()=>me(m),[m]),le=F?qn(F):null,[te,Y]=l.useState(!1),[M,O]=l.useState(null),re=E=>{O(E??null),Y(!0)},[J,se]=l.useState(!1),ne=Zn[r]??r??"",ee=e.jsxs("span",{className:"flex items-center gap-2 min-w-0",children:[r&&e.jsx(oe,{provider:r,className:"w-5 h-5 shrink-0"}),e.jsx("span",{className:"truncate text-text-primary font-semibold",children:i??ne}),e.jsx("span",{className:"text-text-muted font-normal shrink-0",children:"— Permissions"})]}),b=!h&&!N&&(!k||!!W),A=I.length>0||D.length>0||V.length>0||!!W||q||S,U=!d&&!f&&!h&&!k?e.jsxs("div",{className:"flex items-center gap-2 text-[11px] text-text-muted",children:[e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"w-3 h-3",children:[e.jsx("polyline",{points:"23 4 23 10 17 10"}),e.jsx("path",{d:"M20.49 15a9 9 0 11-2.12-9.36L23 10"})]}),e.jsx("span",{children:le?`Synced ${le}`:"Not yet synced"})]}):null;return e.jsxs(e.Fragment,{children:[e.jsx(Se,{open:t,onClose:s,half:!0,title:ee,footer:U,children:d?e.jsx(aa,{}):f?e.jsx(Ft,{title:"Couldn't load this account's features",error:x,onRetry:p,resource:"permissions"}):h?e.jsx(la,{provider:r,account:g}):N?e.jsx(oa,{lastTriedLabel:le,onUpdateCredentials:o?()=>o(n):null}):!b||!A?e.jsx(Fs,{}):e.jsxs(e.Fragment,{children:[q&&e.jsx(Jn,{onFix:()=>se(!0)}),S&&e.jsx(Vn,{onGrant:()=>re(null)}),e.jsx(Xn,{working:I,needsAttention:D,cantVerify:V,provider:r,onFix:re})]})}),e.jsx(Us,{open:te,onClose:()=>Y(!1),cloudAccountId:a,cloudAccountName:i,provider:r,account:n,featureFilter:M}),e.jsx(Yn,{open:J,onClose:()=>se(!1),cloudAccountName:i,provider:r})]})}function Vn({onGrant:t}){return e.jsx("div",{className:"mb-4 rounded-lg border border-warning-400/40 bg-warning-400/10 px-4 py-3",children:e.jsxs("div",{className:"flex items-start gap-2.5",children:[e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",className:"w-4 h-4 mt-0.5 shrink-0 text-warning-600",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Write access isn't set up"}),e.jsx("p",{className:"text-sm text-text-secondary mt-0.5",children:"ZopNight has read access on this account, but none of the write permissions are granted, so the features below are all blocked. Grant the write policy to enable them."}),e.jsxs("button",{type:"button",onClick:t,className:"mt-2.5 inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-primary-600 hover:bg-primary-500 text-text-inverse text-xs font-semibold transition-colors",children:["Grant write access",e.jsx("svg",{className:"h-3 w-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M5 12h14M12 5l7 7-7 7"})})]})]})]})})}function Jn({onFix:t}){return e.jsx("div",{className:"mb-4 rounded-lg border border-warning-400/40 bg-warning-400/10 px-4 py-3",children:e.jsxs("div",{className:"flex items-start gap-2.5",children:[e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",className:"w-4 h-4 mt-0.5 shrink-0 text-warning-600",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"An AWS Organizations policy is restricting this account"}),e.jsx("p",{className:"text-sm text-text-secondary mt-0.5",children:"ZopNight couldn't verify some of the permissions below, because a Service Control Policy (SCP) is blocking the check. They likely still work where your SCP allows them, but until it lets ZopNight check, we can't confirm which ones work or flag any that are missing."}),e.jsxs("button",{type:"button",onClick:t,className:"mt-2.5 inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-primary-600 hover:bg-primary-500 text-text-inverse text-xs font-semibold transition-colors",children:["How to fix",e.jsx("svg",{className:"h-3 w-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M5 12h14M12 5l7 7-7 7"})})]})]})]})})}function Yn({open:t,onClose:s,cloudAccountName:r,provider:a}){const i=e.jsxs("span",{className:"flex items-center gap-2 min-w-0",children:[a&&e.jsx(oe,{provider:a,className:"w-5 h-5 shrink-0"}),e.jsx("span",{className:"truncate text-text-primary font-semibold",children:r??"AWS"}),e.jsx("span",{className:"text-text-muted font-normal shrink-0",children:"— Fix access"})]});return e.jsx(Se,{open:t,onClose:s,half:!0,title:i,children:e.jsxs("div",{className:"flex-1 flex flex-col gap-5 py-8 px-6 max-w-2xl mx-auto w-full",children:[e.jsxs("div",{children:[e.jsx("div",{className:"w-10 h-10 shrink-0 rounded-full bg-warning-400/15 text-warning-600 inline-flex items-center justify-center",children:e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",className:"w-5 h-5",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]})}),e.jsx("p",{className:"text-base font-semibold text-text-primary",children:"Let ZopNight verify this account's permissions"}),e.jsx("p",{className:"text-sm text-text-secondary mt-1",children:"An SCP is restricting this account. Once it's removed, these permissions can be verified."})]}),e.jsxs("div",{className:"rounded-lg border border-border bg-surface-secondary/40 px-4 py-3",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wider text-text-muted font-semibold mb-2",children:"What to do"}),e.jsxs(ct,{children:[e.jsxs(ce,{children:["In your ",e.jsx("strong",{children:"management account"}),", open ",e.jsx("strong",{children:"AWS Organizations"})," ","and find the SCP limiting this account. It may be attached to the account, or inherited from a parent OU or the organization root."]}),e.jsx(ce,{children:"Change that SCP so it no longer restricts this account, or remove it. If the same SCP covers other accounts, your change applies to them too."}),e.jsx(ce,{children:"Save the change. ZopNight re-checks on its next sync and updates this account's state here."})]}),e.jsx("p",{className:"text-[12px] text-text-muted mt-3",children:"Only your organization's management account can change SCPs."})]})]})})}
7function Qn({workingCount:t,needsAttentionCount:s,cantVerifyCount:r=0}){return t+s+r===0?null:e.jsxs("div",{className:"flex items-center gap-4 text-xs font-medium",children:[s>0&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-warning-500"}),e.jsxs("span",{className:"text-text-primary font-semibold",children:[s," need more access"]})]}),r>0&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-warning-500"}),e.jsxs("span",{className:"text-text-secondary",children:[r," restricted"]})]}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-success-500"}),e.jsxs("span",{className:"text-text-secondary",children:[t," working"]})]})]})}function St({muted:t=!1,children:s}){return e.jsx("h4",{className:"text-[10px] font-bold uppercase tracking-[0.1em] text-text-muted",children:s})}function Xn({working:t,needsAttention:s,cantVerify:r=[],onFix:a,provider:i}){const n=l.useMemo(()=>t.map(p=>({...p,id:`${p.feature}::${p.resourceType}`})),[t]),o=l.useMemo(()=>r.map(p=>({...p,id:`${p.feature}::${p.resourceType}`})),[r]),[c,d]=l.useState(()=>new Set),f=p=>{d(u=>{const m=new Set(u);return m.has(p)?m.delete(p):m.add(p),m})},x=l.useMemo(()=>[{id:"status",header:"",cell:({row:p})=>e.jsx(ta,{card:p.original}),meta:{width:"24px",className:"text-center"}},{id:"feature",header:"Feature",accessorKey:"label",cell:({row:p})=>e.jsx("span",{className:"text-text-primary whitespace-nowrap",children:p.original.label})},{id:"permissions",header:"Permissions",cell:({row:p})=>e.jsx(sa,{card:p.original}),meta:{width:"180px",className:"text-left"}},{id:"expand",header:"",cell:({row:p})=>e.jsx(Bs,{expanded:c.has(p.original.id)}),meta:{width:"36px",className:"text-center"}}],[c]);return e.jsxs("div",{className:"space-y-5",children:[e.jsx(Qn,{workingCount:t.length,needsAttentionCount:s.length,cantVerifyCount:r.length}),s.length>0&&e.jsx(ea,{cards:s,onFix:a,provider:i}),o.length>0&&e.jsxs("section",{className:"space-y-2",children:[e.jsx(St,{muted:!0,children:"Restricted"}),e.jsx(bt,{columns:x,data:o,expandedRowIds:c,onRowToggle:f,subRowEdgeToEdge:!0,renderSubRow:p=>e.jsx("div",{className:"py-2 bg-surface-tertiary/30",children:e.jsx(cs,{perms:p.perms})})})]}),n.length>0&&e.jsxs("section",{className:"space-y-2",children:[e.jsx(St,{muted:!0,children:"Working"}),e.jsx(bt,{columns:x,data:n,expandedRowIds:c,onRowToggle:f,subRowEdgeToEdge:!0,renderSubRow:p=>p.feature==="databricks_discovery"?e.jsxs("div",{className:"px-5 py-2.5 bg-surface-tertiary/30 text-[12px] text-text-secondary",children:[p.workspaceCount," ",p.workspaceCount===1?"workspace":"workspaces"," ","discovered — access granted."]}):e.jsx("div",{className:"py-2 bg-surface-tertiary/30",children:e.jsx(cs,{perms:p.perms})})})]})]})}function os(t){const s=Array.isArray(t)?t:[],r=new Map;for(const i of s){const n=i.role||"";r.has(n)||r.set(n,{role:n,granted:0,denied:0,deniedPerms:[]});const o=r.get(n);i.status==="granted"||i.status==="partial"||i.status==="scp_restricted"?o.granted++:i.status==="denied"&&(o.denied++,o.deniedPerms.push(i.permission))}const a=[];for(const i of r.values()){if(i.denied===0)continue;const o=!Je(i.role)&&i.role&&i.granted===0;a.push({role:i.role,kind:o?"role-missing":"granular",deniedPerms:i.deniedPerms.sort(),denied:i.denied,granted:i.granted})}return a.sort((i,n)=>{const o=Je(i.role)?1:0,c=Je(n.role)?1:0;return o!==c?o-c:i.role.localeCompare(n.role)}),a}function ea({cards:t,onFix:s,provider:r}){const a=l.useMemo(()=>t.map(g=>`${g.feature}::${g.resourceType}`),[t]),[i,n]=l.useState(()=>new Set(a)),[o,c]=l.useState(()=>new Set),[d,f]=l.useState(()=>new Map);l.useEffect(()=>{n(g=>{const k=new Set;for(const N of a)k.add(N);for(const N of g)a.includes(N)||k.delete(N);return k})},[a.join("|")]);const x=g=>n(k=>{const N=new Set(k);return N.has(g)?N.delete(g):N.add(g),N}),p=g=>c(k=>{const N=new Set(k);return N.has(g)?N.delete(g):N.add(g),N}),u=i.size,m=u===t.length,h=()=>n(m?new Set:new Set(a)),v=(g,k)=>f(N=>{const j=new Map(N);return j.set(g,k),j}),w=()=>{u!==0&&s?.({features:i,strategies:d})},R=l.useMemo(()=>t.map(g=>({...g,id:`${g.feature}::${g.resourceType}`})),[t]),$=l.useMemo(()=>[{id:"select",header:"",cell:({row:g})=>e.jsx("input",{type:"checkbox",checked:i.has(g.original.id),onChange:k=>{k.stopPropagation(),x(g.original.id)},onClick:k=>k.stopPropagation(),className:"w-4 h-4 rounded border-border accent-primary-600","aria-label":`Select ${g.original.label}`}),meta:{width:"24px",className:"text-center"}},{id:"feature",header:"Feature",accessorKey:"label",cell:({row:g})=>{const k=!wr(g.original.feature)&&g.original.feature!=="databricks_discovery",N=g.original.counts?.granted??0,j=k?N>0?"Partial":"Not working":null;return e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-text-primary whitespace-nowrap",children:g.original.label}),j&&e.jsx("span",{className:"shrink-0 inline-flex items-center px-1.5 py-0.5 rounded text-[9px] font-semibold uppercase tracking-wider bg-warning-500/15 text-warning-700",children:j})]})}},{id:"permissions",header:"Permissions",cell:({row:g})=>{if(g.original.feature==="databricks_discovery")return e.jsx("span",{className:"text-xs text-danger-600 font-medium whitespace-nowrap",children:"Worksp
7ace access needed"});const k=os(g.original.perms);if(k.length===0)return null;const N=k.reduce((j,z)=>j+(z.kind==="role-missing"?1:z.denied),0);return e.jsxs("span",{className:"text-xs text-danger-600 font-medium whitespace-nowrap",children:[N," ",N===1?"permission":"permissions"," missing"]})},meta:{width:"180px",className:"text-left"}},{id:"expand",header:"",cell:({row:g})=>e.jsx(Bs,{expanded:o.has(g.original.id)}),meta:{width:"36px",className:"text-center"}}],[o,i]);return e.jsxs("section",{className:"space-y-2",children:[e.jsxs("header",{className:"flex items-center justify-between gap-2",children:[e.jsxs(St,{children:["Needs attention · ",t.length," ",t.length===1?"feature":"features"]}),e.jsx("button",{type:"button",onClick:h,className:"text-[11px] font-medium text-primary-600 hover:underline shrink-0",children:m?"Clear all":"Select all"})]}),e.jsx(bt,{columns:$,data:R,expandedRowIds:o,onRowToggle:p,subRowEdgeToEdge:!0,renderSubRow:g=>{if(g.feature==="databricks_discovery")return e.jsx("div",{className:"px-5 py-3 bg-surface-tertiary/30 text-[12px] text-text-secondary",children:"Found this workspace but couldn't read its contents. Grant ZopNight workspace access in Databricks to read its clusters, jobs, and warehouses."});const k=os(g.perms);if(k.length===0)return null;const N=k.find(S=>S.kind==="granular"&&!Je(S.role)&&S.role),j=N?k.filter(S=>S.role!==N.role&&S.denied>0):[],z=j.reduce((S,_)=>S+_.denied,0),W=N?.denied??0,T=d.get(g.id)??"role";return e.jsxs("div",{className:"px-5 py-3 bg-surface-tertiary/30 space-y-2",children:[k.map(S=>{const _=S.kind==="role-missing"?[S.role]:S.deniedPerms;return _.length===0?null:e.jsxs("div",{className:"space-y-1",children:[e.jsxs("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-text-muted",children:[_.length===1?"Missing permission":"Missing permissions",S.kind==="granular"&&S.role?e.jsxs("span",{className:"text-text-secondary normal-case",children:[" · ",S.role]}):null]}),e.jsx("ul",{className:"space-y-0.5 max-h-40 overflow-y-auto rounded border border-border bg-surface-tertiary/60 px-2 py-1.5",children:_.map(D=>e.jsx("li",{className:"text-[11px] font-mono text-text-secondary break-all",children:D},D))})]},S.role||"granular")}),N&&r==="snowflake"&&e.jsxs("p",{className:"text-[12px] text-text-secondary",children:["To fix, run the grant SQL as ",e.jsx("code",{className:"font-mono",children:"ACCOUNTADMIN"})," in Snowsight — click ",e.jsx("strong",{className:"text-text-primary",children:"Grant access"})," for the script."]}),N&&r!=="snowflake"&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-text-muted",children:"How to fix"}),z>0&&e.jsxs("p",{className:"text-[11px] text-text-secondary",children:["These options cover the ",W," ",W===1?"permission":"permissions"," in"," ",e.jsx("code",{className:"font-mono",children:N.role}),". The remaining"," ",z," ",z===1?"is":"are"," in"," ",j.map((S,_)=>e.jsxs("span",{children:[_>0&&", ",e.jsx("code",{className:"font-mono",children:S.role})]},S.role)),". ",e.jsx("strong",{className:"text-text-primary",children:"Grant access"})," adds a step for"," ",z===1?"it":"them","."]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(ls,{name:`strategy-${g.id}`,value:"role",selected:T==="role",onSelect:()=>v(g.id,"role"),title:e.jsxs(e.Fragment,{children:["Attach ",e.jsx("code",{className:"font-mono",children:N.role})]}),description:z>0?`Grants the ${W} missing ${W===1?"permission":"permissions"} in this policy, plus any new ones ZopNight may need in the future.`:"Covers this and any new permissions ZopNight may need in the future.",badge:"Recommended"}),e.jsx(ls,{name:`strategy-${g.id}`,value:"granular",selected:T==="granular",onSelect:()=>v(g.id,"granular"),title:"Grant only the specific permissions needed",description:z>0?`Adds only the ${W} missing ${W===1?"permission":"permissions"} in this policy. Minimal scope; you'll be prompted again whenever ZopNight needs a new permission.`:"Adds only what's missing. Minimal scope; you'll be prompted again whenever ZopNight needs a new permission."})]})]})]})}}),e.jsxs("footer",{className:"flex items-center justify-between gap-3 pt-1",children:[e.jsxs("span",{className:"text-[11px] text-text-muted",children:[u," of ",t.length," selected"]}),e.jsxs("button",{type:"button",onClick:w,disabled:u===0,className:"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-primary-600 hover:bg-primary-500 text-text-inverse text-xs font-semibold transition-colors disabled:opacity-50 disabled:cursor-not-allowed",children:["Grant access",e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",className:"w-3 h-3",children:[e.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"}),e.jsx("polyline",{points:"12 5 19 12 12 19"})]})]})]})]})}function ta({card:t}){if(t.status==="cant_verify")return e.jsx("span",{className:"inline-block w-2 h-2 rounded-full bg-warning-500"});const s=t.counts?.denied??0,r=t.counts?.granted??0;let a="bg-text-muted";return s===0&&r>0?a="bg-success-500":s>0&&r>0?a="bg-warning-500":s>0&&r===0&&(a="bg-danger-500"),e.jsx("span",{className:`inline-block w-2 h-2 rounded-full ${a}`})}function Bs({expanded:t}){return e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:`w-4 h-4 text-text-muted mx-auto transition-transform ${t?"rotate-180":""}`,children:e.jsx("polyline",{points:"6 9 12 15 18 9"})})}function sa({card:t}){const s=l.useMemo(()=>Zs(t.perms),[t.perms]),r=s.predefinedRoles.length+s.customCount;return r===0?null:e.jsxs("span",{className:"text-xs text-text-secondary whitespace-nowrap",children:[r," ",r===1?"permission":"permissions"]})}function Zs(t){const s=Array.isArray(t)?t:[],r=new Map,a=[];for(const o of s){if(!o.role){a.push(o);continue}if(Je(o.role)){a.push(o);continue}r.has(o.role)||r.set(o.role,{role:o.role,perms:[],granted:0,partial:0,scpRestricted:0,denied:0});const c=r.get(o.role);c.perms.push(o),o.status==="granted"?c.granted++:o.status==="partial"?c.partial++:o.status==="scp_restricted"?c.scpRestricted++:o.status==="denied"&&c.denied++}const i=[...r.values()].sort((o,c)=>o.role.localeCompare(c.role)),n=[...a].sort((o,c)=>o.permission.localeCompare(c.permission));return{predefined:i,customPerms:n,predefinedRoles:i.map(o=>o.role),customCount:a.length}}function cs({perms:t}){const{predefined:s,customPerms:r}=l.useMemo(()=>Zs(t),[t]),a=l.useMemo(()=>{const i=[];for(const n of s){let o;n.denied>0?o=n.granted>0||n.partial>0||n.scpRestricted>0?"partial":"denied":n.scpRestricted>0?o="scp_restricted":n.partial>0?o="partial":o="granted",i.push({key:n.role,name:n.role,status:o,isRole:!0,deniedPerms:n.perms.filter(c=>c.status==="denied").map(c=>c.permission).sort()})}for(const n of r)i.push({key:n.permission,name:n.permission,status:n.status,isRole:!1});return i},[s,r]);return a.length===0?e.jsx("div",{className:"px-5 py-2.5 text-[11px] text-text-secondary",children:"No permissions to display."}):e.jsxs("div",{className:"px-5 py-2 space-y-1",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-text-muted",children:"Permissions"}),e.jsx("ul",{className:"space-y-0.5",children:a.map(i=>e.jsxs("li",{className:"space-y-0.5",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 text-[11px]",children:[e.jsx("code",{className:"font-mono text-text-secondary break-all",children:i.name}),e.jsx(na,{status:i.status})]}),i.isRole&&i.status==="partial"&&i.deniedPerms.length>0&&e.jsx("ul",{className:"pl-3 space-y-0.5",children:i.deniedPerms.map(n=>e.jsxs("li",{className:"text-[11px] font-mono text-danger-600 break-all",children:["• ",n]},n))})]},i.key))})]})}const ra="An AWS Organizations Service Control Policy (SCP) blocked ZopNight from verifying this action. It may still work where your SCP allows it, like certain regions or services.";function na({status:t}){return t==="granted"?e.jsx("span",{className:"font-medium text-success-600 shrink-0",children:"Granted"}):t==="denied"?e.jsx("span",{className:"font-medium text-danger-600 shrink-0",children:"Not attached"}):t==="scp_restricted"?e.jsxs("span",{className:"inline-flex items-center gap-1 shrink-0",children:[e.jsx("span",{className:"font-medium text-warning-600",children:"Restricted"}),e.jsx(Ct,{text:ra,placement:"left",width:"w-[280px]"})]}):e.jsx("span",{className:"font-medium text-warning-600 shrink-0",children:"Partial"})}function ls({name:t,value:s,selected:r,onSelect:a,title:i,description:n,badge:o}){return e.jsxs("label",{className:`block rounded-lg border px-3 py-2.5 cursor-pointer transition-colors ${r?"border-primary-500 bg-primary-500/[0.08]":"border-border bg-surface-tertiary/30 hover:border-primary-500/40"}`,children:[e.jsx("input",{type:"radio",name:t,value:s,checked:r,onChange:a,className:"sr-only"}),e.jsxs("span",{className:"flex items-start gap-2.5",children:[e.jsx("span",{"aria-hidden":!0,
7className:`mt-0.5 w-4 h-4 rounded-full border-2 inline-flex items-center justify-center shrink-0 transition-colors ${r?"border-primary-600":"border-text-muted/60"}`,children:e.jsx("span",{className:`w-1.5 h-1.5 rounded-full bg-primary-600 transition-opacity ${r?"opacity-100":"opacity-0"}`})}),e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsxs("span",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:`text-[12px] font-semibold ${r?"text-primary-600":"text-text-primary"}`,children:i}),o&&e.jsx("span",{className:"text-[9px] font-semibold uppercase tracking-wider text-primary-600 bg-primary-600/15 px-1.5 py-0.5 rounded",children:o})]}),n&&e.jsx("span",{className:"block text-[11px] text-text-muted mt-0.5 leading-relaxed",children:n})]})]})]})}function aa(){return e.jsxs("div",{className:"space-y-3 animate-pulse",children:[e.jsx("div",{className:"h-6 bg-surface-secondary/50 rounded"}),e.jsx("div",{className:"space-y-2",children:[...Array(3)].map((t,s)=>e.jsx("div",{className:"h-20 bg-surface-secondary/40 rounded-lg"},s))}),e.jsx("div",{className:"h-32 bg-surface-secondary/30 rounded-lg"})]})}const ia=["Scheduled start and stop actions will fail","Resource, cost and recommendation data has stopped refreshing"];function oa({lastTriedLabel:t,onUpdateCredentials:s}){const{summary:r}=Bn();return e.jsxs("div",{className:"flex-1 flex flex-col gap-4 py-8 px-6 max-w-3xl mx-auto w-full",children:[e.jsxs(Is,{className:"flex items-start gap-4",children:[e.jsx("div",{className:"w-10 h-10 shrink-0 rounded-full bg-danger-400/15 text-danger-500 inline-flex items-center justify-center",children:e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"w-5 h-5","aria-hidden":"true",children:e.jsx("path",{d:"M12 9v4m0 4h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"})})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"text-base font-semibold text-text-primary",children:"Credentials invalid or expired"}),e.jsx("p",{className:"text-sm text-text-secondary mt-1",children:r}),e.jsx("p",{className:"text-sm text-text-secondary mt-3",children:"Until they're replaced, nothing runs on this account:"}),e.jsx("ul",{className:"mt-2 space-y-1 list-disc list-inside marker:text-danger-500",children:ia.map(a=>e.jsx("li",{className:"text-sm text-text-secondary leading-snug",children:a},a))}),s&&e.jsxs("button",{type:"button",onClick:s,className:"mt-4 inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-primary-600 hover:bg-primary-500 text-text-inverse text-xs font-semibold transition-colors",children:["Update credentials",e.jsx("svg",{className:"h-3 w-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M5 12h14M12 5l7 7-7 7"})})]})]})]}),t&&e.jsxs("p",{className:"text-[11px] text-text-muted",children:["Last checked ",t]})]})}const ca=["Which features are working","What you're missing out on","How to unlock more"];function la({provider:t,account:s}){const r=t==="gcp"?"Once the Cloud Resource Manager API is enabled, you'll see:":"Once ZopNight has access, you'll see:";return e.jsxs("div",{className:"flex-1 flex flex-col gap-5 py-8 px-6 max-w-2xl mx-auto w-full",children:[e.jsxs("div",{children:[e.jsx("div",{className:"w-10 h-10 shrink-0 rounded-full bg-warning-400/15 text-warning-600 inline-flex items-center justify-center",children:e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",className:"w-5 h-5",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]})}),e.jsx("p",{className:"text-base font-semibold text-text-primary",children:"We can't see this account's permissions yet"}),e.jsx("p",{className:"text-sm text-text-secondary mt-1",children:"Everything you've set up still works. However, ZopNight can't read which permissions are granted on this account right now."}),e.jsx("p",{className:"text-sm text-text-secondary mt-3",children:r}),e.jsx("ul",{className:"space-y-1.5 mt-2",children:ca.map(a=>e.jsxs("li",{className:"flex items-start gap-2 text-sm text-text-secondary",children:[e.jsx("svg",{className:"w-4 h-4 mt-0.5 shrink-0 text-success-500",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M20 6 9 17l-5-5"})}),e.jsx("span",{children:a})]},a))})]}),e.jsxs("div",{className:"rounded-lg border border-border bg-surface-secondary/40 px-4 py-3",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wider text-text-muted font-semibold mb-2",children:"How to fix"}),e.jsx(da,{provider:t,account:s})]})]})}function da({provider:t,account:s}){if(t==="aws"){const r=s?.authMethod==="static_keys"||s?.authMethod==="temporary_credentials",a=ge({provider:"aws",account:s,kind:r?"user":void 0});return r?e.jsxs(ct,{children:[e.jsxs(ce,{children:["Go to ",e.jsx(it,{href:a,children:"IAM Users"})," in AWS Console and find your existing ZopNight user (e.g."," ",e.jsx("code",{className:"font-mono text-[12px]",children:"zopnight-service"}),")."]}),e.jsxs(ce,{children:["On the ",e.jsx("strong",{children:"Permissions"})," tab, click the ",e.jsx("strong",{children:"Add permissions"})," ","button, then choose ",e.jsx("strong",{children:"Attach policies directly"}),"."]}),e.jsxs(ce,{children:["Filter by ",e.jsx("strong",{children:"AWS managed"}),", tick ",e.jsx("strong",{children:"ReadOnlyAccess"}),", click"," ",e.jsx("strong",{children:"Next"}),", then ",e.jsx("strong",{children:"Add permissions"})," to confirm."]})]}):e.jsxs(ct,{children:[e.jsx(ce,{children:s?.roleName?e.jsxs(e.Fragment,{children:["Go to ",e.jsx(it,{href:a,children:"IAM Roles"})," in AWS Console and open the"," ",e.jsx("code",{className:"font-mono text-[12px]",children:s.roleName})," role."]}):e.jsxs(e.Fragment,{children:["Go to ",e.jsx(it,{href:a,children:"IAM Roles"})," in AWS Console and open your ZopNight role."]})}),e.jsxs(ce,{children:["On the ",e.jsx("strong",{children:"Permissions"})," tab, click the ",e.jsx("strong",{children:"Add permissions"})," ","button, then choose ",e.jsx("strong",{children:"Attach policies"})," from the dropdown."]}),e.jsxs(ce,{children:["Filter by ",e.jsx("strong",{children:"AWS managed"}),", tick ",e.jsx("strong",{children:"ReadOnlyAccess"}),", then click"," ",e.jsx("strong",{children:"Add permissions"})," to confirm."]})]})}if(t==="azure"){const r=ge({provider:"azure",account:s}),a=s?.cloudAccountId?e.jsxs(e.Fragment,{children:["subscription ",e.jsx("code",{className:"font-mono text-[12px]",children:s.cloudAccountId})]}):"this subscription";return e.jsxs(ct,{children:[e.jsxs(ce,{children:["Open ",e.jsx(it,{href:r,children:"Access control (IAM)"})," on ",a,"."]}),e.jsxs(ce,{children:["Click ",e.jsx("strong",{children:"Add"}),", then ",e.jsx("strong",{children:"Add role assignment"}),"."]}),e.jsxs(ce,{children:["On the ",e.jsx("strong",{children:"Role"})," tab, search for ",e.jsx("strong",{children:"Reader"}),", select it, and click"," ",e.jsx("strong",{children:"Next"}),"."]}),e.jsxs(ce,{children:["On the ",e.jsx("strong",{children:"Members"})," tab, click ",e.jsx("strong",{children:"Select members"}),", search for your ZopNight app, select it, then click ",e.jsx("strong",{children:"Next"}),"."]}),e.jsxs(ce,{children:["Click ",e.jsx("strong",{children:"Review + assign"}),"."]})]})}if(t==="gcp"){const r=s?.cloudAccountId,a=r?`https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview?project=${encodeURIComponent(r)}`:"https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview";return e.jsxs(ct,{children:[e.jsxs(ce,{children:["Open the ",e.jsx(it,{href:a,children:"Cloud Resource Manager API page"})," in GCP Console",r?e.jsxs(e.Fragment,{children:[" ","for project ",e.jsx("code",{className:"font-mono text-[12px]",children:r})]}):null,"."]}),e.jsxs(ce,{children:["Click ",e.jsx("strong",{children:"Enable"}),"."]})]})}return null}function ct({children:t}){const s=[];let r=0;for(const a of Array.isArray(t)?t:[t])a&&(r+=1,s.push({key:a.key??r,n:r,content:a}));return e.jsx("ol",{className:"space-y-2.5",children:s.map(({key:a,n:i,content:n})=>e.jsxs("li",{className:"flex items-start gap-3 text-[13px] text-text-secondary leading-relaxed",children:[e.jsx("span",{className:"shrink-0 w-6 h-6 rounded-full bg-primary-500/10 text-primary-600 text-[11px] font-semibold inline-flex items-center justify-center mt-0.5",children:i}),e.jsx("span",{className:"flex-1",children:n})]},a))})}function ce({children:t}){return t}function it({href:t,children:s}){return t?e.jsx("a",{href:t,target:"_blank",rel:"noreferrer",className:"text-primary-600 hover:text-primary-700 hover:underline font-medium",children:s}):e.jsx("strong",{className:"text-text-primary",children:s})}function ua({account:t,open:s,onClose:r}){const{data:a,isLoading:i,isError:n,error:o}=Rs({type:"databricks",cloud_account_id:t?.cloudAccountId,limit:100,include:"metadata"}),{query:c}
7=$s(t?.id),d=c?.data?.host||"accounts.cloud.databricks.com",f=Nr(a?.items),x=f.filter(v=>v.accessStatus!=="accessible"),p=f.filter(v=>v.accessStatus==="accessible"),[u,m]=l.useState(!1),h=e.jsxs("span",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(oe,{provider:"databricks",className:"w-5 h-5 shrink-0"}),e.jsx("span",{className:"truncate text-text-primary font-semibold",children:t?.name||t?.cloudAccountId||"Databricks"}),e.jsx("span",{className:"text-text-muted font-normal shrink-0",children:"— Workspace access"})]});return e.jsxs(e.Fragment,{children:[e.jsx(Se,{open:s,onClose:r,title:h,children:i?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(vt,{})}):n?e.jsx("div",{className:"text-center py-16",children:e.jsx("p",{className:"text-sm text-danger-500",children:o?.message||"Failed to load workspace access."})}):f.length===0?e.jsx(Fe,{message:"No workspaces discovered yet for this connection."}):e.jsxs("div",{className:"space-y-5",children:[e.jsx(ma,{needsAttentionCount:x.length,workingCount:p.length}),x.length>0&&e.jsxs("section",{className:"space-y-3",children:[e.jsx(us,{children:"Needs attention"}),e.jsx(xs,{workspaces:x,status:"needs_attention"}),e.jsx("div",{className:"flex justify-end pt-1",children:e.jsxs("button",{type:"button",onClick:()=>m(!0),className:"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-primary-600 hover:bg-primary-500 text-text-inverse text-xs font-semibold transition-colors",children:["Grant access",e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",className:"w-3 h-3",children:[e.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"}),e.jsx("polyline",{points:"12 5 19 12 12 19"})]})]})})]}),p.length>0&&e.jsxs("section",{className:"space-y-2",children:[e.jsx(us,{children:"Working"}),e.jsx(xs,{workspaces:p,status:"accessible"})]})]})}),e.jsx(xa,{account:t,consoleHost:d,open:u,onClose:()=>m(!1)})]})}function xa({account:t,consoleHost:s,open:r,onClose:a}){const[i,n]=l.useState(!1),[o,c]=l.useState(!0),d=l.useMemo(()=>Kr(s),[s]),f=e.jsxs("span",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(oe,{provider:"databricks",className:"w-5 h-5 shrink-0"}),e.jsx("span",{className:"truncate text-text-primary font-semibold",children:t?.name||t?.cloudAccountId||"Databricks"}),e.jsx("span",{className:"text-text-muted font-normal shrink-0",children:"— Grant access"})]});return e.jsx(Se,{open:r,onClose:a,half:!0,title:f,children:e.jsxs("div",{className:"space-y-4 pb-6",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("h2",{className:"text-sm font-semibold text-text-primary",children:"Grant access"}),e.jsx("p",{className:"text-[12px] text-text-muted leading-relaxed",children:"Give the ZopNight service principal workspace-admin access so it can read the workspace's clusters, jobs, and SQL warehouses."})]}),e.jsxs("div",{className:"flex gap-4",children:[e.jsx("div",{className:"flex flex-col items-center pt-0.5",children:e.jsx("button",{type:"button",onClick:()=>c(x=>!x),className:`relative flex items-center justify-center w-8 h-8 rounded-full text-xs font-bold shrink-0 transition-all duration-200 ${i?"bg-primary-600/15 text-primary-600 border border-primary-600/30":o?"bg-primary-600 text-text-inverse shadow-[0_0_0_3px_rgba(6,182,212,0.15)]":"bg-surface-secondary text-text-muted border border-border hover:border-primary-600/30 hover:text-primary-600"}`,"aria-label":"Step 1",children:i?e.jsx(ds,{className:"h-4 w-4"}):1})}),e.jsxs("div",{className:"flex-1 min-w-0 pb-0",children:[e.jsxs("button",{type:"button",onClick:()=>c(x=>!x),className:"flex items-center justify-between w-full text-left group py-1",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("h4",{className:`text-[13px] font-semibold truncate transition-colors ${i||o?"text-primary-600":"text-text-primary group-hover:text-primary-600"}`,children:d.title}),i&&!o&&e.jsx("span",{className:"text-[10px] text-primary-600/70 font-medium shrink-0",children:"Done"})]}),e.jsx("svg",{className:`h-4 w-4 text-text-muted/50 transition-transform duration-200 shrink-0 ml-2 ${o?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 8.25l-7.5 7.5-7.5-7.5"})})]}),o&&e.jsxs("div",{className:"mt-2 rounded-xl border border-border bg-surface-secondary/40 overflow-hidden",children:[e.jsx("div",{className:"p-4",children:e.jsx(_s,{content:d.content})}),e.jsx("div",{className:"px-4 pb-4",children:e.jsxs("button",{type:"button",onClick:()=>n(x=>!x),className:`inline-flex items-center gap-2 px-4 py-2 text-[12px] font-semibold rounded-lg transition-all ${i?"bg-primary-600/10 text-primary-600 hover:bg-primary-600/15":"bg-surface-tertiary text-text-primary border border-border hover:border-primary-600/30 hover:text-primary-600"}`,children:[e.jsx(ds,{className:"h-3.5 w-3.5"}),i?"Completed":"Mark as done"]})})]})]})]})]})})}function ds({className:t=""}){return e.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:t,children:e.jsx("path",{d:"M20 6 9 17l-5-5"})})}function ma({needsAttentionCount:t,workingCount:s}){return e.jsxs("div",{className:"flex items-center gap-4 text-xs font-medium",children:[t>0&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(It,{className:"bg-warning-500"}),e.jsxs("span",{className:"text-text-primary font-semibold",children:[t," need more access"]})]}),s>0&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(It,{className:"bg-success-500"}),e.jsxs("span",{className:"text-text-secondary",children:[s," working"]})]})]})}function us({children:t}){return e.jsx("h4",{className:"text-[10px] font-bold uppercase tracking-[0.1em] text-text-muted",children:t})}function It({className:t=""}){return e.jsx("span",{className:`inline-block w-2 h-2 rounded-full ${t}`})}const pa={needs_attention:{dot:"bg-warning-500",label:"Needs access",labelClass:"text-warning-600"},accessible:{dot:"bg-success-500",label:"Working",labelClass:"text-success-600"}};function xs({workspaces:t,status:s}){const r=l.useMemo(()=>{const a=pa[s];return[{id:"status",header:"",cell:()=>e.jsx(It,{className:a.dot}),meta:{width:"24px",className:"text-center"}},{id:"workspace",header:"Workspace",accessorKey:"name",cell:({row:i})=>e.jsx("span",{className:"text-text-primary whitespace-nowrap",children:i.original.n
7ame})},{id:"access",header:"Access",cell:()=>e.jsx("span",{className:`font-medium ${a.labelClass}`,children:a.label}),meta:{width:"140px",className:"text-left"}}]},[s]);return e.jsx(bt,{columns:r,data:t})}const ha=t=>{if(!t)return{};if(typeof t=="string")try{return JSON.parse(t)}catch{return{}}return t};function fa({account:t,open:s,onClose:r}){const a=t?.cloudAccountId??t?.id,i=Te($e.CLOUD_ACCOUNT_UPDATE),{data:n,isLoading:o,isError:c,error:d,refetch:f}=Ar(a,s),{data:x,isError:p}=Cr(a,s),u=Sr(),m=Ir(),[h,v]=l.useState(null),w=n?.items??n?.resources??[],R=x?.managedAccessDenied??!1,$=l.useMemo(()=>{const g=new Map;for(const k of x?.clusters??[])g.set(k.resourceUid,k.method);return g},[x]);return e.jsxs(e.Fragment,{children:[e.jsxs(Se,{open:s,onClose:r,title:"Manage clusters",wide:!0,children:[e.jsx("p",{className:"text-[13px] text-text-secondary mb-4",children:"ZopNight can list these clusters already. Connecting one lets it read the workloads inside."}),p&&!o&&!c&&w.length>0?e.jsxs("div",{className:"mb-4 rounded-lg border border-warning-500/40 bg-warning-500/5 px-4 py-3",children:[e.jsx("p",{className:"text-sm font-medium text-text-primary",children:"Could not read which clusters are connected"}),e.jsx("p",{className:"text-xs text-text-muted mt-1",children:"The clusters below are still listed, but connecting them from here is unavailable until this check succeeds. Open a cluster to set it up individually."})]}):null,o?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(vt,{})}):c?e.jsx(Ft,{error:d,onRetry:f}):w.length===0?e.jsx(Fe,{message:"No ROSA clusters found in this Red Hat organization."}):e.jsx("div",{className:"space-y-1.5",children:w.map(g=>e.jsx(ga,{cluster:g,method:$.get(g.uid),accessUnknown:p,managedAccessDenied:R,busy:u.isPending&&u.variables?.clusterResId===g.id||m.isPending&&m.variables?.clusterResId===g.id,canUpdate:i,onConnect:()=>u.mutate({clusterResId:g.id,method:"managed"}),onDisconnect:()=>v(g)},g.id))})]}),e.jsx(zt,{open:!!h,onClose:()=>v(null),onConfirm:()=>{h&&m.mutate({clusterResId:h.id},{onSettled:()=>v(null)})},title:"Disconnect cluster",message:h?`ZopNight will give up its access to ${h.name} and stop showing what runs inside it. The cluster itself keeps running, and you can connect it again at any time.`:"",confirmLabel:"Disconnect",variant:"delete",isLoading:m.isPending,confirmDisabled:!i})]})}function ga({cluster:t,method:s,accessUnknown:r,managedAccessDenied:a,busy:i,canUpdate:n,onConnect:o,onDisconnect:c}){const d=ha(t.metadata),f=!r&&!!s,x=!r&&!a&&!d.externalAuth,p=n?void 0:"You do not have permission to connect clusters.";return e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-border px-3.5 py-2.5 hover:border-border-strong hover:bg-surface-secondary/50 transition-all",children:[e.jsx("span",{className:`w-1.5 h-1.5 rounded-full shrink-0 ${f?"bg-success-600":"bg-text-muted/40"}`,"aria-hidden":"true"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("p",{className:"text-sm font-medium text-text-primary truncate",children:t.name}),d.openshiftVersion&&e.jsxs(We,{variant:"neutral",children:["v",d.openshiftVersion]})]}),t.region&&e.jsx("p",{className:"text-xs text-text-muted font-mono mt-0.5",children:t.region})]}),f?e.jsxs(e.Fragment,{children:[e.jsx(We,{variant:"success",children:"Connected"}),e.jsx(G,{variant:"secondary",size:"sm",onClick:c,disabled:i||!n,title:p,children:i?"Working…":"Disconnect"})]}):x?e.jsx(G,{size:"sm",onClick:o,disabled:i||!n,title:p,children:i?"Connecting…":"Connect"}):e.jsx(fs,{to:`/k8s/clusters/${t.id}`,className:"text-[12.5px] font-semibold text-primary-500 hover:underline shrink-0",children:"Set up →"})]})}function qs(t,s){if(!t)return"—";const r=new Date(t);if(isNaN(r.getTime()))return"—";const a=new Date;if(r.getDate()===a.getDate()&&r.getMonth()===a.getMonth()&&r.getFullYear()===a.getFullYear())return"today";const n=a-r,o=Math.floor(n/864e5);if(o<=0)return"today";if(o===1)return"1 day ago";if(o<30)return`${o} days ago`;const c=Math.floor(o/30);if(c===1)return"1 month ago";if(c<12)return`${c} months ago`;const d=Math.floor(c/12);
7return d===1?"1 year ago":`${d} years ago`}const Hs=[{value:"aws",label:"Amazon Web Services",description:"EC2, RDS, EKS, Lambda, S3, and more"},{value:"gcp",label:"Google Cloud Platform",description:"Compute Engine, GKE, Cloud SQL, Cloud Run"},{value:"azure",label:"Microsoft Azure",description:"VMs, AKS, SQL Database, Functions"},{value:"snowflake",label:"Snowflake",description:"Warehouses, databases, tables, materialized views, stages, pipes"},{value:"databricks",label:"Databricks",description:"Clusters, SQL Warehouses, Instance Pools, Jobs"},{value:"openshift",label:"Red Hat OpenShift",description:"ROSA clusters and machine pools across your Red Hat organization"}],De={aws:"AWS",gcp:"GCP",azure:"Azure",snowflake:"Snowflake",databricks:"Databricks",openshift:"OpenShift",microsoft365:"Microsoft 365"};function ba({type:t,className:s="w-6 h-6"}){return t==="assume_role"||t==="workload_identity_federation"?e.jsx("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M15.75 5.25a3 3 0 0 1 3 3m-3-3a3 3 0 0 0-3 3m3-3V3M12.75 8.25a3 3 0 0 0 .879 2.121L15 11.743a3 3 0 0 1 .879 2.121V15M18.75 8.25a3 3 0 0 1-.879 2.121L16.5 11.743a3 3 0 0 0-.879 2.121V15m0 0v3.375c0 .621-.504 1.125-1.125 1.125h-1.5a1.125 1.125 0 0 1-1.125-1.125V15m3.75 0h-3.75"})}):t==="static_keys"||t==="service_principal"?e.jsx("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z"})}):t==="temporary_credentials"?e.jsx("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0z"})}):t==="oauth"?e.jsx("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M13.5 10.5V6.75a4.5 4.5 0 1 1 9 0v3.75M3.75 21.75h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H3.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25z"})}):t==="service_account"?e.jsx("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M15.75 5.25a3 3 0 0 1 3 3m-3-3a3 3 0 0 0-3 3m3-3V3M12.75 8.25a3 3 0 0 0 .879 2.121L15 11.743a3 3 0 0 1 .879 2.121V15M18.75 8.25a3 3 0 0 1-.879 2.121L16.5 11.743a3 3 0 0 0-.879 2.121V15m0 0v3.375c0 .621-.504 1.125-1.125 1.125h-1.5a1.125 1.125 0 0 1-1.125-1.125V15m3.75 0h-3.75"})}):t==="snowflake_key_pair"?e.jsxs("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M15 7a4 4 0 1 1-3.464 6L4 20.5V22h2.5l1-1v-1.5h1.5v-1.5h1.5L13 14.464A4 4 0 0 1 15 7z"}),e.jsx("circle",{cx:"16",cy:"8",r:"1",fill:"currentColor"})]}):t==="snowflake_pat"?e.jsxs("svg",{className:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M3 7v4a2 2 0 0 1 0 4v4a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1v-4a2 2 0 0 1 0-4V7a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1z"}),e.jsx("path",{d:"M9 8v8M13 8v8M16 8v8",strokeOpacity:"0.6"})]}):null}const Kt={static_keys:"IAM User (Static Keys)",assume_role:"WIF-Assume Role",temporary_credentials:"Temporary Credentials",service_account:"Service Account",oauth:"OAuth",service_principal:"Service Principal",workload_identity_federation:"Workload Identity"},Vs={read_only:"Read Only",read_write:"Read + Write"};function ya(t){return Vs[t]||t}const Js=["Resource Discovery — auto-detect all cloud resources","Cost Reports — track spending trends and breakdowns","Recommendations — get optimization suggestions","Dashboards — visualize resource inventory and cost data"],Ys=["Scheduling (start/stop) & Auto Scaling","Overrides (temporary on/off)","Automated execution of recommendations"],Qs=["Scheduling — automated start/stop schedules for resources","Auto Scaling — metric-driven autoscaling for VM groups (ASG, VMSS, MIG)","Overrides — temporary on/off for maintenance or emergencie
7s","Resource Groups — batch actions across related resources","Execute Recommendations — one-click apply for optimization","Notifications — alerts for scheduled actions and failures"],At=["Feature Comparison","Update Permissions","Confirm & Upgrade"],ja=new Set(["assume_role","workload_identity_federation","service_account","static_keys","service_principal","temporary_credentials"]);function va(t){switch(t){case"assume_role":return"IAM role";case"static_keys":return"IAM user";case"temporary_credentials":return"IAM user";case"service_account":return"service account";case"service_principal":return"service principal";case"workload_identity_federation":return"IAM role";case"oauth":return"OAuth connection";default:return"credentials"}}function Xs({selected:t,onSelect:s}){return e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:"Choose the cloud provider you want to connect."}),e.jsx("div",{className:"grid gap-3",children:Hs.map(r=>e.jsx(xe,{selected:t===r.value,onClick:()=>s(r.value),children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(oe,{provider:r.value,className:"w-8 h-8"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:r.label}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:r.description})]})]})},r.value))})]})}function Bt({provider:t,selected:s,onSelect:r,currentMethod:a}){const i=Es[t]||[];return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Choose how ZopNight will authenticate with your ",De[t]," account."]}),e.jsx("div",{className:"grid gap-3",children:i.map(n=>e.jsx(xe,{selected:s===n.value,onClick:()=>r(n.value),children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"flex items-center justify-center w-9 h-9 rounded-lg bg-surface-tertiary text-text-muted shrink-0",children:e.jsx(ba,{type:n.value,className:"w-5 h-5"})}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:n.label}),a===n.value&&e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider bg-primary-400/10 text-primary-600 rounded",children:"Current"}),n.recommended&&a!==n.value&&e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider bg-success-400/15 text-success-600 rounded",children:"Recommended"})]}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:n.description})]})]})},n.value))})]})}function Ye({items:t,included:s}){return e.jsx("ul",{className:"space-y-1.5 mt-2",children:t.map(r=>e.jsxs("li",{className:"flex items-start gap-2 text-xs",children:[s?e.jsx("svg",{className:"h-3.5 w-3.5 text-success-500 shrink-0 mt-0.5",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z",clipRule:"evenodd"})}):e.jsx("svg",{className:"h-3.5 w-3.5 text-text-muted shrink-0 mt-0.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12"})}),e.jsx("span",{className:s?"text-text-secondary":"text-text-muted line-through",children:r})]},r))})}function er({selected:t,onSelect:s,provider:r,azureScope:a,onScopeChange:i}){return e.jsxs("div",{className:"space-y-3",children:[r==="azure"&&e.jsx("div",{className:"pb-3 border-b border-border",children:e.jsx(ka,{value:a,onChange:i})}),e.jsx("p",{className:"text-sm text-text-secondary",children:"Choose what level of access ZopNight should have."}),e.jsxs("div",{className:"grid gap-3",children:[e.jsxs(xe,{selected:t==="read_write",onClick:()=>s("read_write"),recommended:!0,children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Read + Write"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"Full cloud cost optimization — discover, schedule, and automate resource management."}),e.jsx("p",{className:"text-xs text-text-muted mt-2 italic",children:"Everything in Read Only, plus:"}),e.jsx(Ye,{items:Qs,included:!0})]}),e.jsxs(xe,{selected:t==="read_only",onClick:()=>s("read_only"),children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Read Only"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"Monitor and optimize your cloud costs without making any changes to your resources."}),e.jsx(Ye,{items:Js,included:!0}),e.jsxs("div",{className:"mt-2 pt-2 border-t border-border",children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wider text-text-muted font-semibold mb-1",children:"Not included"}),e.jsx(Ye,{items:Ys,included:!1})]})]})]})]})}function tr({selected:t,onSelect:s}){return e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:"Choose how much you want ZopNight to do for you."}),e.jsxs("div",{className:"grid gap-3",children:[e.jsxs(xe,{selected:t==="admin",onClick:()=>s("admin"),children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Grant admin access"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"ZopNight connects each cluster for you, in one click. Needs the OCM Organization Administrator role."})]}),e.jsxs(xe,{selected:t==="readonly",onClick:()=>s("readonly"),children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Grant read-only access"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"ZopNight lists your cluster
7s but cannot touch them. You give it access on each cluster yourself, one at a time."})]})]})]})}function Zt({provider:t,authMethod:s,permissionLevel:r,orgId:a,azureScope:i,form:n,onAllComplete:o}){return e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-text-secondary mb-4",children:"Follow these steps to create credentials with the required permissions."}),e.jsx(Ot,{provider:t,authMethod:s,permissionLevel:r,orgId:a,azureScope:i,databricksCloud:n?.databricksCloud,openshiftAccess:n?.openshiftAccess,onAllComplete:o})]})}function X({error:t}){return t?e.jsx("p",{className:"text-xs text-danger-500 mt-1",children:t}):null}function ka({value:t,onChange:s}){return e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-sm font-medium text-text-primary",children:"Discovery Scope"}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(xe,{selected:t==="subscription",onClick:()=>s("subscription"),children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Single Subscription"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"Connect one Azure subscription"})]}),e.jsxs(xe,{selected:t==="tenant",onClick:()=>s("tenant"),children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Entire Tenant"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"Discover all subscriptions in the tenant automatically"})]})]})]})}function qt({provider:t,authMethod:s,form:r,onChange:a,errors:i,onBlurValidate:n,onOAuthConnect:o,oauthLoading:c,permissionLevel:d,accountLocked:f=!1}){const[x,p]=l.useState(!1);return e.jsxs(e.Fragment,{children:[t==="aws"&&s==="static_keys"&&e.jsxs(e.Fragment,{children:[e.jsxs(B,{label:"Access Key ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"AKIA...",autoComplete:"off",value:r.accessKeyId,onChange:u=>a("accessKeyId",u.target.value),onBlur:()=>n?.("accessKeyId")}),e.jsx(X,{error:i.accessKeyId})]}),e.jsxs(B,{label:"Secret Access Key",required:!0,children:[e.jsx(H,{type:"password",placeholder:"Secret access key",autoComplete:"new-password",value:r.secretAccessKey,onChange:u=>a("secretAccessKey",u.target.value),onBlur:()=>n?.("secretAccessKey")}),e.jsx(X,{error:i.secretAccessKey})]}),e.jsx("p",{className:"text-xs text-text-muted",children:"Account ID will be detected automatically."})]}),t==="aws"&&s==="assume_role"&&e.jsx(e.Fragment,{children:e.jsxs(B,{label:"Role ARN",required:!0,children:[e.jsx(H,{type:"text",placeholder:"arn:aws:iam::123456789012:role/ZopNightRole-ZopNightRole-Ab12Cd34Ef56",autoComplete:"off",value:r.roleArn,onChange:u=>a("roleArn",u.target.value),onBlur:()=>n?.("roleArn")}),e.jsx(X,{error:i.roleArn})]})}),t==="aws"&&s==="temporary_credentials"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-start gap-2.5 p-3 rounded-lg bg-warning-400/10 border border-warning-400/30",children:[e.jsx("svg",{className:"h-4 w-4 flex-shrink-0 mt-0.5 text-warning-600",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"})}),e.jsxs("p",{className:"text-xs text-warning-600 leading-relaxed",children:[e.jsx("span",{className:"font-semibold",children:"Heads up —"})," these credentials are temporary. When they expire, you'll need to add a fresh set to keep syncing."]})]}),e.jsxs(B,{label:"Access Key ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"ASIA...",autoComplete:"off",value:r.accessKeyId,onChange:u=>a("accessKeyId",u.target.value),onBlur:()=>n?.("accessKeyId")}),e.jsx(X,{error:i.accessKeyId})]}),e.jsxs(B,{label:"Secret Access Key",required:!0,children:[e.jsx(H,{type:"password",placeholder:"Secret access key",autoComplete:"new-password",value:r.secretAccessKey,onChange:u=>a("secretAccessKey",u.target.value),onBlur:()=>n?.("secretAccessKey")}),e.jsx(X,{error:i.secretAccessKey})]}),e.jsxs(B,{label:"Session Token",required:!0,children:[e.jsx("textarea",{autoComplete:"off",placeholder:"Paste the session token...",value:r.sessionToken,onChange:u=>a("sessionToken",u.target.value),rows:9,className:"w-full px-3 py-2 bg-surface-tertiary border border-border-strong rounded-lg text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-primary-600/30 focus:border-primary-600/40 transition-all duration-fast resize-none font-mono text-xs"}),e.jsx(X,{error:i.sessionToken})]})]}),t==="gcp"&&s==="oauth"&&e.jsx(nn,{permissionLevel:d,onOAuthConnect:o,oauthLoading:c,buttonLabel:"Connect with Google"}),t==="gcp"&&s==="service_account"&&e.jsxs(B,{label:"Service Account Key (JSON)",required:!0,children:[e.jsx("textarea",{autoComplete:"off",placeholder:"Paste the entire JSON key file contents...",value:r.gcpServiceAccountKey,onChange:u=>a("gcpServiceAccountKey",u.target.value),rows:6,className:"w-full px-3 py-2 bg-surface-tertiary border border-border-strong rounded-lg text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-primary-600/30 focus:border-primary-600/40 transition-all duration-fast resize-none font-mono text-xs"}),e.jsx(X,{error:i.gcpServiceAccountKey}),e.jsx("p",{className:"text-xs text-text-muted mt-1",children:"Project ID will be extracted automatically from the key."})]}),t==="azure"&&s==="service_principal"&&e.jsxs(e.Fragment,{children:[e.jsxs(B,{label:"Tenant ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"Tenant ID",autoComplete:"off",value:r.azureTenantId,onChange:u=>a("azureTenantId",u.target.value),onBlur:()=>n?.("azureTenantId")}),e.jsx(X,{error:i.azureTenantId})]}),e.jsxs(B,{label:"Client ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"App registration client ID",autoComplete:"off",value:r.azureClientId,onChange:u=>a("azureClientId",u.target.value),onBlur:()=>n?.("azureClientId")}),e.jsx(X,{error:i.azureClientId})]}),e.jsxs(B,{label:"Client Secret",required:!0,children:[e.jsx(H,{type:"password",placeholder:"Client secret",autoComplete:"new-password",value:r.azureClientSecret,onChange:u=>a("azureClientSecret",u.target.value),onBlur:()=>n?.("azureClientSecret")}),e.jsx(X,{error:i.azureClientSecret})]}),e.jsx("p",{className:"text-xs text-text-muted",children:r.azureScope==="tenant"?"All accessible subscriptions will be discovered automatically.":"Subscription ID will be detected automatically from credentials."})]}),t==="azure"&&s==="workload_identity_federation"&&e.jsxs(e.Fragment,{children:[r.azureScope!=="tenant"&&e.jsxs(B,{label:"Subscription ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",autoComplete:"off",value:r.azureSubscriptionId,onChange:u=>a("azureSubscriptionId",u.target.value),onBlur:()=>n?.("azureSubscriptionId")}),e.jsx(X,{error:i.azureSubscriptionId})]}),e.jsxs(B,{label:"Tenant ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"Tenant ID",autoComplete:"off",value:r.azureTenantId,onChange:u=>a("azureTenantId",u.target.value),onBlur:()=>n?.("azureTenantId")}),e.jsx(X,{error:i.azureTenantId})]}),e.jsxs(B,{label:"Client ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"App registration client ID",autoComplete:"off",value:r.azureClientId,onChange:u=>a("azureClientId",u.target.value),onBlur:()=>n?.("azureClientId")}),e.jsx(X,{error:i.azureClientId})]}),e.jsx("p",{className:"text-xs text-text-muted",children:"No client secret needed — authentication uses federated identity."})]}),t==="openshift"&&e.jsxs(e.Fragment,{children:[e.jsxs(B,{label:"Client ID",required:!0,children:[e.jsx(H,{type:"text",placeholder:"e.g. 1a2b3
7c4d-5e6f-7890-abcd-ef1234567890",autoComplete:"off",value:r.openshiftClientId,onChange:u=>a("openshiftClientId",u.target.value),onBlur:()=>n?.("openshiftClientId")}),e.jsx(X,{error:i.openshiftClientId})]}),e.jsxs(B,{label:"Client Secret",required:!0,children:[e.jsx(H,{type:"password",placeholder:"Service account client secret",autoComplete:"new-password",value:r.openshiftClientSecret,onChange:u=>a("openshiftClientSecret",u.target.value),onBlur:()=>n?.("openshiftClientSecret")}),e.jsx(X,{error:i.openshiftClientSecret})]}),e.jsx("p",{className:"text-xs text-text-muted",children:"One service account covers every ROSA cluster in your Red Hat organization. We read the organization ID from the credential — you don't need to enter it."})]}),t==="snowflake"&&e.jsxs(e.Fragment,{children:[e.jsxs(B,{label:"Snowflake Account URL",required:!0,children:[e.jsx(H,{type:"text",placeholder:"xy12345.us-east-1.aws",autoComplete:"off",value:r.snowflakeAccount,onChange:u=>a("snowflakeAccount",u.target.value),onBlur:()=>n?.("snowflakeAccount"),readOnly:f,disabled:f}),e.jsx(X,{error:i.snowflakeAccount}),f&&e.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"Fixed for this connection — to use a different Snowflake account, add a new one."})]}),e.jsxs(B,{label:"Username",required:!0,children:[e.jsx(H,{type:"text",placeholder:"e.g. ZOPNIGHT_SVC",autoComplete:"off",value:r.snowflakeUser,onChange:u=>a("snowflakeUser",u.target.value),onBlur:()=>n?.("snowflakeUser")}),e.jsx(X,{error:i.snowflakeUser})]})]}),t==="snowflake"&&s==="snowflake_key_pair"&&e.jsxs(e.Fragment,{children:[e.jsxs(B,{label:"Private Key (PKCS8 PEM)",required:!0,children:[e.jsx("textarea",{className:"w-full px-3 py-2 bg-surface-tertiary border border-border-strong rounded-lg text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-primary-600/30 focus:border-primary-600/40 transition-all duration-fast resize-none font-mono text-xs",rows:8,placeholder:`-----BEGIN PRIVATE KEY-----
8MIIE...
9-----END PRIVATE KEY-----`,value:r.snowflakePrivateKey,onChange:u=>a("snowflakePrivateKey",u.target.value),onBlur:()=>n?.("snowflakePrivateKey"),spellCheck:!1}),e.jsx(X,{error:i.snowflakePrivateKey})]}),e.jsx(B,{label:"Passphrase (optional)",children:e.jsx(H,{type:"password",placeholder:"Only if the private key is encrypted",autoComplete:"new-password",value:r.snowflakePassphrase,onChange:u=>a("snowflakePassphrase",u.target.value)})}),e.jsx("p",{className:"text-xs text-text-muted",children:"Encrypted at rest in our vault."})]}),t==="snowflake"&&s==="snowflake_pat"&&e.jsx(e.Fragment,{children:e.jsxs(B,{label:"Programmatic Access Token",required:!0,children:[e.jsx(H,{type:"password",placeholder:"Paste the token Snowsight generated",autoComplete:"new-password",value:r.snowflakePAT,onChange:u=>a("snowflakePAT",u.target.value),onBlur:()=>n?.("snowflakePAT")}),e.jsx(X,{error:i.snowflakePAT})]})}),t==="snowflake"&&e.jsxs("div",{className:"pt-2",children:[e.jsxs("button",{type:"button",className:"inline-flex items-center gap-2 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors",onClick:()=>p(u=>!u),"aria-expanded":x,children:[e.jsx("svg",{className:`w-4 h-4 transition-transform ${x?"rotate-90":""}`,viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{d:"M7 5l6 5-6 5V5z"})}),"Advanced settings (optional)"]}),x&&e.jsxs("div",{className:"mt-3 grid grid-cols-2 gap-3",children:[e.jsxs(B,{label:e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:["Role override",e.jsx(Ct,{text:"The Snowflake role ZopNight connects as — it decides what ZopNight can see and do (discovery, cost, start/stop). Leave blank to use the service user's default role.",width:"w-[280px]"})]}),children:[e.jsx(H,{type:"text",placeholder:"Leave blank to use user's default",autoComplete:"off",value:r.snowflakeRole,onChange:u=>a("snowflakeRole",u.target.value)}),e.jsxs("p",{className:"mt-1 text-xs text-text-muted",children:["Only set if you need to override the user's ",e.jsx("code",{children:"DEFAULT_ROLE"}),"."]})]}),e.jsxs(B,{label:e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:["Warehouse override",e.jsx(Ct,{text:"The Snowflake warehouse ZopNight uses to run its own queries (e.g. reading ACCOUNT_USAGE) — not the warehouses it monitors. Leave blank to use the service user's default warehouse.",width:"w-[280px]"})]}),children:[e.jsx(H,{type:"text",placeholder:"Leave blank to use user's default",autoComplete:"off",value:r.snowflakeWarehouse,onChange:u=>a("snowflakeWarehouse",u.target.value)}),e.jsxs("p",{className:"mt-1 text-xs text-text-muted",children:["Only set if you need to override the user's ",e.jsx("code",{children:"DEFAULT_WAREHOUSE"}),"."]})]})]})]})]})}function Ht({form:t,onChange:s,errors:r,connectionError:a,onOAuthConnect:i,oauthLoading:n,onBlurValidate:o}){const c=t.provider==="gcp"&&t.authMethod==="oauth";return e.jsxs("div",{className:"space-y-4",children:[!c&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-text-secondary",children:"Enter the credentials you created in the previous step."}),e.jsxs(B,{label:"Display Name",required:!0,children:[e.jsx(H,{type:"text",placeholder:`e.g. Production ${De[t.provider]||""}`,value:t.name,onChange:d=>s("name",d.target.value),onBlur:()=>o?.("name")}
9),e.jsx(X,{error:r.name}),t.name.length>200&&e.jsxs("p",{className:`text-xs mt-1 ${t.name.length>255?"text-red-500":"text-text-muted"}`,children:[t.name.length,"/255"]})]})]}),e.jsx(qt,{provider:t.provider,authMethod:t.authMethod,form:t,onChange:s,errors:r,onBlurValidate:o,onOAuthConnect:i,oauthLoading:n,permissionLevel:t.permissionLevel}),a&&e.jsx("div",{className:"p-4 rounded-lg bg-danger-500/10 border border-danger-500/20",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("svg",{className:"h-5 w-5 text-danger-500 shrink-0 mt-0.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium text-danger-500",children:"Connection Failed"}),e.jsx("p",{className:"text-xs text-text-secondary mt-1",children:a})]})]})})]})}const ot=["Select Provider","Auth Method","Permission Level","Setup Guide","Enter Credentials","Cost Export","Discovery Summary","Azure Databricks","Cloud","Access Level"],he=3,ke=4,Ve=5,_e=6,Pe=7,je=8,ve=9;function wa(t,s){return t==="gcp"?[0,1,2,he,ke,Ve,_e]:t==="databricks"?s==="azure"?[0,1,Pe]:[0,1,je,he,ke,_e]:t==="openshift"?[0,ve,he,ke,_e]:[0,1,2,he,ke,_e]}function sr({form:t,onChange:s}){const r=()=>{s("databricksKind","databricks"),s("databricksCloud","aws")},a=()=>{s("databricksKind","azure"),s("databricksCloud","azure")};return e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:"Which flavor of Databricks are you connecting?"}),e.jsxs("div",{className:"grid gap-3",children:[e.jsx(xe,{selected:t.databricksKind==="databricks",onClick:r,children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(oe,{provider:"databricks",className:"w-8 h-8"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Databricks"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Runs on AWS or GCP — connect with an account OAuth service principal."})]})]})}),e.jsx(xe,{selected:t.databricksKind==="azure",onClick:a,children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(oe,{provider:"azure",className:"w-8 h-8"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Azure Databricks"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Runs on Microsoft Azure — discovered via your Azure subscription."})]})]})})]})]})}function rr({form:t,onChange:s}){return e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:"Which cloud does your Databricks account run on?"}),e.jsxs("div",{className:"grid gap-3",children:[e.jsx(xe,{selected:t.databricksCloud==="aws",onClick:()=>s("databricksCloud","aws"),children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(oe,{provider:"aws",className:"w-8 h-8"}),e.jsx("div",{children:e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Amazon Web Services"})})]})}),e.jsx(xe,{selected:t.databricksCloud==="gcp",onClick:()=>s("databricksCloud","gcp"),children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(oe,{provider:"gcp",className:"w-8 h-8"}),e.jsx("div",{children:e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Google Cloud Platform"})})]})})]})]})}function ms(){return e.jsxs("div",{className:"pt-2 border-t border-border",children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary mb-1",children:"Grant Databricks workspace access"}),e.jsx("p",{className:"text-xs text-text-muted mb-3",children:"Grant the service principal workspace-admin in each Databricks workspace so ZopNight can discover them."}),e.jsx(_s,{content:Vr})]})}function nr({activeTab:t,onTabChange:s}){const{data:r=[],isLoading:a,isError:i,refetch:n}=Dt(),c=r.filter(f=>f.provider==="azure").length>0;if(a)return e.jsx("div",{className:"flex items-center justify-center py-10",children:e.jsx(vt,{})});if(i)return e.jsxs("div",{className:"space-y-3 py-4",children:[e.jsx("p",{className:"text-sm text-danger-500",children:"Couldn't load your cloud accounts."}),e.jsx(G,{variant:"secondary",onClick:()=>n(),children:"Retry"})]});const d=[{value:"existing",label:"Existing account"},{value:"new",label:"New account"}];return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(oe,{provider:"azure",className:"w-8 h-8"}),e.jsx("h3",{className:"text-base font-semibold text-text-primary",children:"Discover Databricks in your Azure account"})]}),e.jsx(Yr,{tabs:d,active:t,onChange:s}),t==="existing"?e.jsx("div",{className:"space-y-4",children:c?e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-text-secondary leading-relaxed",children:"Azure Databricks is discovered through your Azure subscription's service principal — there's no separate credential to add. ZopNight picks up your Databricks workspaces on its next discovery sweep of your connected Azure account."}),e.jsx(ms,{})]}):e.jsx("p",{className:"text-sm text-text-secondary leading-relaxed",children:"No Azure accounts connected yet — use the New account tab."})}):e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-text-secondary leading-relaxed",children:"To monitor Azure Databricks, first connect an Azure cloud account to ZopNight, then grant the service principal workspace-admin access in each Databricks workspace. There's no separate Databricks credential."}),e.jsx(ms,{})]})]})}function ar({form:t,onChange:s,errors:r,connectionError:a,onBlurValidate:i}){return e.jsxs("div",{className:"space-y-5",children:[e.jsxs(B,{label:"Display name",required:!0,children:[e.jsx(H,{value:t.name,onChange:n=>s("name",n.target.value),onBlur:()=>i?.("name"),placeholder:"e.g. Prod Databricks"}),r.name&&e.jsx("p",{className:"text-xs text-danger-500 mt-1",children:r.name})]}),e.jsx(Ts,{values:t,onChange:s,errors:r,showSteps:!1}),a&&e.jsx("p",{className:"text-sm text-danger-500",children:a})]})}function Na(){try{sessionStorage.removeItem("gcp_oauth_switch_project"),sessionStorage.removeItem("gcp_oauth_switch_name"),sessionStorage.removeItem("gcp_oauth_upgrade_account_id"),sessionStorage.removeItem("gcp_oauth_upgrade_roles")}catch{}}function ps(t){const s=t.current;return!s.provider||!s.redirecting?!1:(s.redirecting=!1,!0)}function ir({open:t,onClose:s,onSubmit:r,isLoading:a,onManageCluster
9s:i}){const[n,o]=l.useState(0),[c,d]=l.useState(Le),[f,x]=l.useState({}),[p,u]=l.useState(null),[m,h]=l.useState(!1),[v,w]=l.useState(null),[R,$]=l.useState(!1),g=l.useRef(!1),[k,N]=l.useState(null),j=l.useRef({provider:null,startedAt:0,failures:0,lastFailureReason:null,redirecting:!1}),z=fr();l.useEffect(()=>{R&&n===he&&!g.current?(g.current=!0,o(ke)):R||(g.current=!1)},[R,n,o]);const T=Dr(b=>b.tenants)?.[0]?.id??"",S=l.useCallback((b,A)=>{d(L=>({...L,[b]:A})),x(L=>({...L,[b]:void 0})),u(null)},[]),_=b=>{const A=j.current;A.provider&&(A.redirecting||(Ze(He.CLOUD_ACCOUNT_CONNECT_ABANDONED,{provider:A.provider,at_step:ot[n],abandon_reason:b,duration_ms:Date.now()-A.startedAt,failed_attempts:A.failures,last_failure_reason:A.lastFailureReason??void 0}),j.current={provider:null,startedAt:0,failures:0,lastFailureReason:null,redirecting:!1},pt()))},D=l.useRef(null);D.current=b=>_(b),l.useEffect(()=>{const b=Br();b&&!j.current.provider&&(Ze(He.CLOUD_ACCOUNT_CONNECT_ABANDONED,{provider:Zr(),abandon_reason:qe.HANDOFF_NOT_RETURNED,duration_ms:Date.now()-b}),pt());const A=()=>D.current?.(qe.PAGE_HIDDEN);window.addEventListener("pagehide",A);const L=U=>{U?.persisted&&ps(j)};return window.addEventListener("pageshow",L),()=>{window.removeEventListener("pagehide",A),window.removeEventListener("pageshow",L),D.current?.(qe.NAVIGATED_AWAY)}},[]);const I=()=>{_(qe.WIZARD_CLOSED),j.current.redirecting||pt(),o(0),d(Le),x({}),u(null),w(null),$(!1),g.current=!1,N(null),s()},V=b=>{S("provider",b);const A=(Es[b]||[]).find(Z=>Z.recommended);d(Z=>({...Z,provider:b,authMethod:A?.value??""})),$(!1),g.current=!1;const L=j.current.provider===b,U=ps(j);if(!U&&L)return;_(U&&L?qe.OAUTH_REDIRECT_RETURNED:qe.PROVIDER_SWITCHED);const E=Date.now();j.current={provider:b,startedAt:E,failures:0,lastFailureReason:null,redirecting:!1},Hr(E,b),Ze(He.CLOUD_ACCOUNT_CONNECT_STARTED,{provider:b,auth_method:A?.value??""})},q=Er(),F=()=>{const b=Ce(c);if(Object.keys(b).length>0){x(b);return}u(null),q.mutate(ln(c),{onSuccess:A=>{const L=[A?.version&&`v${A.version}
9`,A?.region,A?.role].filter(Boolean);de.success(L.length?`Connected to Snowflake — ${L.join(" · ")}`:"Snowflake connection succeeded")},onError:A=>{const L=A?.message||"Connection failed";u(L),de.error(`Snowflake connection failed: ${L}`)}})},le=()=>{const b=Ce(c);if(Object.keys(b).length>0){x(b);return}const A=j.current,L=c.authMethod||"",U=ot[n],E=()=>j.current===A&&A.provider;r(Os(c),{onSuccess:Z=>{E()&&(Ze(He.CLOUD_ACCOUNT_CONNECT_SUCCEEDED,{provider:A.provider,auth_method:L,duration_ms:Date.now()-A.startedAt,failed_attempts:A.failures}),j.current={provider:null,startedAt:0,failures:0,lastFailureReason:null,redirecting:!1},pt()),u(null),w(Z),o(c.provider==="gcp"?Ve:_e)},onError:Z=>{if(E()){const ae=Xt(Z);A.failures+=1,A.lastFailureReason=ae,Ze(He.CLOUD_ACCOUNT_CONNECT_FAILED,{provider:A.provider,auth_method:L,failure_reason:ae,http_status:es(Z),attempt:A.failures,at_step:U,duration_ms:A.startedAt?Date.now()-A.startedAt:void 0})}u(Z?.message||"Something went wrong. Please try again.")}})},te=(b,A,L)=>{const U=L??j.current;U.provider&&(U.failures+=1,U.lastFailureReason=b,Ze(He.CLOUD_ACCOUNT_CONNECT_FAILED,{provider:U.provider,auth_method:"oauth",failure_reason:b,http_status:A,attempt:U.failures,at_step:ot[n],duration_ms:U.startedAt?Date.now()-U.startedAt:void 0}))},Y=async()=>{h(!0);const b=j.current,A=()=>j.current===b&&b.provider;try{const L=await fe.get("/connect/gcp/oauth-url",{permissionLevel:c.permissionLevel,appBasePath:"zopnight/app"});L?.url?(Na(),A()&&(b.redirecting=!0),window.location.href=L.url):(te(Fr.OAUTH_URL_MISSING,void 0,b),de.error("Failed to get Google authorization URL."),h(!1))}catch(L){b.redirecting=!1,te(Xt(L),es(L),b),de.error(`Failed to start Google connect: ${L?.message||"Unknown error"}`),h(!1)}},M=()=>{if(n===0)return c.provider!=="";if(n===1)return c.provider==="databricks"?c.databricksKind!=="":c.authMethod!=="";if(n===je)return c.databricksCloud==="aws"||c.databricksCloud==="gcp";if(n===2)return c.permissionLevel!=="";if(n===ve)return c.openshiftAccess!=="";if(n===he)return!0;if(n===ke){if(c.provider==="gcp"&&c.authMethod==="oauth")return!1;const b=Ce(c);return Object.keys(b).length===0}return!1},O=l.useCallback(b=>{const A=Ce(c);A[b]&&x(L=>({...L,[b]:A[b]}))},[c]),re=c.provider==="databricks"&&c.databricksCloud==="azure",{data:J=[]}=Dt(),se=J.some(b=>b.provider==="azure"),ne=k??(se?"existing":"new"),ee=e.jsxs(e.Fragment,{children:[(n>0&&n<Ve||n===Pe||n===je||n===ve)&&e.jsx(G,{variant:"secondary",onClick:()=>o(b=>b===Pe||b===je?1:b===he&&c.provider==="databricks"?je:b===he&&c.provider==="openshift"?ve:b===ve?0:b-1),children:"Back"}),e.jsx("div",{className:"flex-1"}),(n<Ve||n===Pe||n===je||n===ve)&&e.jsx(G,{variant:"secondary",onClick:I,children:"Cancel"}),(n<ke||n===je||n===ve)&&e.jsx(G,{onClick:()=>o(b=>b===1&&c.provider==="databricks"?re?Pe:je:b===je?he:b===0&&c.provider==="openshift"?ve:b===ve?he:b+1),disabled:!M(),children:n===he?"Skip guide":"Next"}),n===ke&&c.provider==="snowflake"&&e.jsx(G,{variant:"secondary",onClick:F,disabled:!M()||q.isPending||a,children:q.isPending?"Testing…":"Test connection"}),n===ke&&!(c.provider==="gcp"&&c.authMethod==="oauth")&&e.jsx(G,{onClick:le,disabled:!M()||a,children:a?"Connecting...":"Connect Account"}),n===Pe&&(ne==="existing"?e.jsx(G,{onClick:I,children:"Done"}):e.jsx(G,{onClick:()=>{V("azure"),o(1)},children:"Connect Azure account"})),n===Ve&&e.jsx(G,{onClick:()=>o(_e),children:"Continue"}),n===_e&&e.jsx(e.Fragment,{children:c.provider==="openshift"&&v?.cloudAccountId?e.jsxs(e.Fragment,{children:[e.jsx(G,{variant:"secondary",onClick:I,children:"Later"}),e.jsx(G,{onClick:()=>{I(),i?.(v)},children:"Connect clusters"})]}):e.jsxs(e.Fragment,{children:[e.jsx(G,{onClick:I,children:"Done"}),v?.cloudAccountId&&e.jsx(G,{variant:"secondary",onClick:()=>{I(),z("/resources")},children:"View Resources"})]})})]});return e.jsxs(Se,{open:t,onClose:I,title:c.provider==="databricks"&&n===1?"Databricks":ot[n],half:!0,footer:ee,children:[(n<_e||n===Pe||n===je||n===ve)&&e.jsx("div",{className:"flex items-center gap-1 mb-6",children:(()=>{const b=wa(c.provider,c.databricksKind).filter(L=>L!==6),A=b.indexOf(n);return b.map((L,U,E)=>{const Z=c.provider==="databricks"&&L===1?"Databricks":ot[L],ae=A>-1&&U<A,be=n===L;return e.jsxs("div",{className:"flex items-center gap-1 flex-1",children:[e.jsx("div",{className:`flex items-center justify-center w-7 h-7 rounded-full text-[10px] font-bold shrink-0 transition-all ${ae?"bg-success-500 text-white":be?"bg-primary-600 text-white ring-2 ring-primary-600/30":"bg-surface-tertiary text-text-muted"}`,children:ae?e.jsx("svg",{className:"h-3.5 w-3.5",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z",clipRule:"evenodd"})}):U+1}),e.jsx("span",{className:`text-[10px] hidden sm:inline truncate ${be?"text-text-primary font-medium":ae?"text-success-600":"text-text-muted"}`,children:Z}),U<E.length-1&&e.jsx("div",{className:`flex-1 h-px transition-colors ${ae?"bg-success-500":"bg-border"}`})]},Z)})})()}),e.jsxs("div",{className:"animate-fade-in",children:[n===0&&e.jsx(Xs,{selected:c.provider,onSelect:V}),n===1&&c.provider==="databricks"&&e.jsx(sr,{form:c,onChange:S}),n===1&&c.provider!=="databricks"&&e.jsx(Bt,{provider:c.provider,selected:c.authMethod,onSelect:b=>S("authMethod",b)}),n===2&&e.jsx(er,{selected:c.permissionLevel,onSelect:b=>S("permissionLevel",b),provider:c.provider,azureScope:c.azureScope,onScopeChange:b=>S("azureScope",b)}),n===he&&e.jsx(Zt,{provider:c.provider,authMethod:c.authMethod,permissionLevel:c.permissionLevel,orgId:T,azureScope:c.azureScope,onAllComplete:$,form:c,onChange:S}),n===ke&&c.provider==="databricks"&&e.jsx(ar,{form:c,onChange:S,errors:f,connectionError:p,onBlurValidate:O}),n===ke&&c.provider!=="databricks"&&e.jsx(Ht,{form:c,onChange:S,errors:f,connectionError:p,onOAuthConnect:Y,oauthLoading:m,onBlurValidate:O}),n===Ve&&c.provider==="gcp"&&e.jsx(Ot,{provider:"gcp",phase:"post-credentials"}),n===_e&&e.jsx(qr,{caID:v?.id,cloudAccountId:v?.cloudAccountId,provider:c.provider}),n===ve&&e.jsx(tr,{selected:c.openshiftAccess,onSelect:b=>S("openshiftAccess",b)}),n===je&&e.jsx(rr,{form:c,onChange:S}),n===Pe&&e.jsx(nr,{activeTab:ne,onTabChange:N})]},n)]})}function Mt(t){return Os(t).credentials}function or({account:t,open:s,onClose:r,iamImported:a=!1,startInCredentialFlow:i=!1}){const n=Cs(),o=$s(t?.provider==="databricks"?t?.id:null),c=zr(t?.provider==="snowflake"?t?.id:null),d=en(),f=Ds(),x=a&&(t?.provider==="aws"||t?.provider==="gcp"||t?.provider==="azure"),{data:p}=Ss({enabled:x}),{data:u}=gs({enabled:x}),m=Te($e.CLOUD_ACCOUNT_UPDATE),[h,v]=l.useState(t?.name??""),[w,R]=l.useState(t?.permissionLevel??"read_write"),[$,g]=l.useState(!1),[k,N]=l.useState(!1),[j,z]=l.useState(()=>i?{...Le,provider:t?.provider,authMethod:t?.authMethod,azureSubscriptionId:t?.provider==="azure"&&t?.scope!=="tenant"?t?.cloudAccountId??"":""}:{...Le}),[W,T]=l.useState({}),[S,_]=l.useState(!1),D=Xe(),[I,V]=l.useState(i?t?.authMethod??null:null),[q,F]=l.useState("method"),[le,te]=l.useState(null),Y=l.useMemo(()=>
9{if(!t?.id)return ft;const C=Array.isArray(p)?p:p?.items??p?.data??[],K=Array.isArray(u)?u:u?.items??u?.data??[];for(const Me of[K,C])for(const Ne of Me){const Ee=Or(Ne,t.id);if(Tr(Ee))return Ee}return C.some(Me=>$r(Me?.metadata)?.importedFrom?.cloudAccountId===t.id)?gt:ft},[p,u,t?.id]),[M,O]=l.useState(Y);l.useEffect(()=>{O(Y)},[Y]);const re=o.query?.data;l.useEffect(()=>{t?.provider==="databricks"&&z(C=>({...C,databricksAccountId:re?.accountId??t?.cloudAccountId??"",databricksClientId:re?.clientId??"",databricksHost:re?.host??"",databricksCloud:re?.host?.includes(".gcp.databricks.com")?"gcp":"aws"}))},[t?.provider,t?.cloudAccountId,re]);const J=c?.data;l.useEffect(()=>{t?.provider==="snowflake"&&z(C=>({...C,snowflakeAccount:J?.account??t?.cloudAccountId??"",snowflakeUser:J?.user??"",snowflakeRole:J?.role??"",snowflakeWarehouse:J?.warehouse??""}))},[t?.provider,t?.cloudAccountId,J]);const se=l.useMemo(()=>({...j,provider:t?.provider??"",authMethod:t?.authMethod??"",azureScope:t?.scope==="tenant"?"tenant":"subscription",name:h||t?.name||""}),[j,t,h]),ne=l.useCallback((C,K)=>{z(Q=>({...Q,[C]:K})),T(Q=>({...Q,[C]:void 0}))},[]),ee=l.useCallback((C,K)=>{if(C==="name"){v(K),T(Q=>({...Q,name:void 0}));return}ne(C,K)},[ne]),b=async()=>{_(!0);try{const C=await fe.get("/connect/gcp/oauth-url",{permissionLevel:w,appBasePath:"zopnight/app"});C?.url?window.location.href=C.url:(de.error("Failed to get Google authorization URL."),_(!1))}catch(C){de.error(`Failed to start Google connect: ${C?.message||"Unknown error"}`),_(!1)}},A=()=>{t&&(sessionStorage.removeItem("gcp_oauth_upgrade_account_id"),sessionStorage.removeItem("gcp_oauth_upgrade_roles"),sessionStorage.setItem("gcp_oauth_switch_project",t.cloudAccountId),sessionStorage.setItem("gcp_oauth_switch_name",t.name||""),b())},L=C=>{N(C==="read_only"&&t?.permissionLevel==="read_write"),R(C)},[U,E]=l.useState(""),Z=()=>{if(!h.trim()){E("Display name is required");return}if(h.length>255){E("Max 255 characters");return}if(E(""),t.provider==="databricks"){const Ae=h!==t.name;if($){const Be=Ce(se);if(Object.keys(Be).length>0){T(Be);return}o.save.mutate(an(se),{onSuccess:()=>{Ae||r()}})}Ae?n.mutate({id:t.id,name:h},{onSuccess:r}):$||r();return}const C={id:t.id};h!==t.name&&(C.name=h),w!==t.permissionLevel&&(C.permissionLevel=w);const K=t.provider!=="aws"&&t.provider!=="azure";if($&&K&&!(t.provider==="gcp"&&t.authMethod==="oauth")){const Ae=Ce(se);if(Object.keys(Ae).length>0){T(Ae);return}C.credentials=Mt(se)}const Q=a&&M!==Y&&M===gt,Me=a&&M!==Y&&M===ft,Ne=()=>{Q?d.mutate({cloudAccountId:t.id,provider:t.provider,mode:gt},{onSettled:()=>r()}):Me?f.mutate({cloudAccountId:t.id,scope:"teams"},{onSettled:()=>r()}):r()};C.name||C.permissionLevel||C.credentials?n.mutate(C,{onSuccess:Ne}):Ne()},ae=n.isPending||d.isPending||f.isPending||o.save.isPending,be=I!=null&&I!==t?.authMethod,ye={...j,provider:t?.provider,authMethod:I,azureScope:t?.scope==="tenant"?"tenant":"subscription",name:h??""},Ue=()=>t?.provider==="azure"&&t?.scope!=="tenant"?t?.cloudAccountId??"":"",st=()=>{V(t?.authMethod),F("method"),z({...Le,provider:t?.provider,authMethod:t?.authMethod,azureSubscriptionId:Ue()}),T({}),te(null)},ut=C=>{V(C),z({...Le,provider:t?.provider,authMethod:C,azureSubscriptionId:Ue()}),T({}),te(null)},xt=()=>{V(null),F("method"),T({}),te(null)},Ge=()=>{const C=Ce(ye);if(Object.keys(C).length>0){T(C);return}te(null);const K={id:t.id,credentials:Mt(ye)};t.provider==="azure"&&t.scope!=="tenant"&&ye.azureSubscriptionId&&(K.credentials={...K.credentials,subscriptionId:ye.azureSubscriptionId}),be&&(K.authMethod=I),w!==t.permissionLevel&&(K.permissionLevel=w),h&&h!==t.name&&(K.name=h),n.mutate(K,{onSuccess:r,onError:Q=>te(Q?.message||"Something went wrong. Please try again.")})},wt=()=>{te(null),q==="credentials"?F("guide"):q==="guide"?F("method"):xt()},rt=e.jsxs(e.Fragment,{children:[e.jsx(G,{variant:"secondary",onClick:wt,children:"Back"}),e.jsx("div",{className:"flex-1"}),e.jsx(G,{variant:"secondary",onClick:r,children:"Cancel"}),q==="method"?e.jsx(G,{onClick:()=>F("guide"),disabled:!I||!m,title:m?void 0:"You don't have permission. Contact your admin.",children:"Next"}):q==="guide"?e.jsx(G,{onClick:()=>F("credentials"),disabled:!m,title:m?void 0:"You don't have permission. Contact your admin.",children:"Skip guide"}):t?.provider==="gcp"&&I==="oauth"?e.jsx("div",{}):e.jsx(G,{onClick:Ge,disabled:ae||!m,title:m?void 0:"You don't have permission. Contact your admin.",children:ae?"Saving...":"Save Changes"})]}),nt=!$&&h===(t?.name??"")&&w===(t?.permissionLevel??"read_write")&&!(a&&M!==Y),Ke=e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex-1"}),e.jsx(G,{variant:"secondary",onClick:r,children:"Cancel"}),e.jsx(G,{onClick:Z,disabled:ae||!m||nt,title:m?void 0:"You don't have permission. Contact your admin.",children:ae?"Saving...":"Save Changes"})]}),we=I?rt:Ke;
9return t?e.jsx(Se,{open:s,onClose:r,title:I?"Edit Cloud Account — Update credentials":"Edit Cloud Account",footer:we,children:I?e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-1",children:["Auth Method","Setup Guide","Enter Credentials"].map((C,K)=>{const Q=q==="method"?0:q==="guide"?1:2;return e.jsxs("div",{className:"flex items-center gap-1 flex-1",children:[e.jsx("div",{className:`flex items-center justify-center w-6 h-6 rounded-full text-[10px] font-bold shrink-0 transition-all ${K<Q?"bg-success-500 text-white":K===Q?"bg-primary-600 text-white ring-2 ring-primary-600/30":"bg-surface-tertiary text-text-muted"}`,children:K<Q?e.jsx("svg",{className:"h-3 w-3",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z",clipRule:"evenodd"})}):K+1}),e.jsx("span",{className:`text-xs truncate ${K===Q?"text-text-primary font-medium":K<Q?"text-success-600":"text-text-muted"}`,children:C}),K<2&&e.jsx("div",{className:`flex-1 h-0.5 rounded-full transition-colors ${K<Q?"bg-success-500":"bg-surface-tertiary"}`})]},C)})}),e.jsx("div",{className:"animate-fade-in",children:q==="method"?e.jsx(Bt,{provider:t.provider,selected:I,onSelect:ut,currentMethod:t.authMethod}):q==="guide"?e.jsx(Zt,{provider:t.provider,authMethod:I,permissionLevel:w,orgId:D,azureScope:t.scope,form:ye}):e.jsx(Ht,{form:ye,onChange:ee,errors:W,connectionError:le,onOAuthConnect:A,oauthLoading:S})},q),be&&q!=="guide"&&e.jsx("div",{className:"p-3 rounded-lg bg-primary-400/10 border border-primary-400/20",children:e.jsxs("p",{className:"text-xs text-primary-600 leading-relaxed",children:["Please ensure the new credentials belong to the same cloud account,"," ",e.jsx("span",{className:"font-semibold text-primary-700",children:t.name})," (",e.jsx("span",{className:"font-mono font-semibold text-primary-700",children:t.cloudAccountId}),"). Credentials for a different account will be rejected."]})})]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-3 p-3 rounded-lg bg-surface-secondary border border-border",children:[e.jsx(oe,{provider:t.provider,className:"w-6 h-6"}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-sm font-medium text-text-primary",children:[De[t.provider]," —"," ",Kt[t.authMethod]||t.authMethod]}),e.jsx("p",{className:"text-xs text-text-muted font-mono",children:t.cloudAccountId})]})]}),e.jsxs(B,{label:"Display Name",required:!0,children:[e.jsx(H,{type:"text",placeholder:`e.g. Production ${De[t.provider]||""}`,autoComplete:"off",value:h,onChange:C=>{v(C.target.value),E("")}}),e.jsx(X,{error:U}),h.length>200&&e.jsxs("p",{className:`text-xs mt-1 ${h.length>255?"text-red-500":"text-text-muted"}`,children:[h.length,"/255"]})]}),t.provider!=="databricks"&&t.provider!=="openshift"&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-text-primary mb-2",children:"Permission Level"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:["read_only","read_write"].map(C=>e.jsx("button",{type:"button",onClick:()=>L(C),className:`p-3 rounded-lg border text-left transition-all ${w===C?"border-primary-600 bg-primary-600/5 ring-1 ring-primary-600/20":"border-border-strong hover:border-primary-500/50"}`,children:e.jsx("p",{className:"text-sm font-medium text-text-primary",children:Vs[C]})},C))}),k&&w==="read_only"&&e.jsx("div",{className:"mt-2 p-3 rounded-lg bg-warning-400/10 border border-warning-400/20",children:e.jsx("p",{className:"text-xs text-warning-600",children:"Active schedules on this account will no longer execute with read-only permissions."})}),w!==t?.permissionLevel&&e.jsx("div",{className:"mt-2 p-3 rounded-lg bg-primary-400/10 border border-primary-400/20",children:e.jsx("p",{className:"text-xs text-primary-600",children:w==="read_write"?"To enable scheduling and auto scaling, update your credentials below or add write permissions to your IAM role/service account in your cloud provider console.":"To restrict access, update your credentials below or remove write permissions from your IAM role/service account in your cloud provider console."})})]}),t.provider==="aws"||t.provider==="azure"||t.provider==="gcp"?e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-text-secondary mb-2",children:"Authentication"}),e.jsxs("button",{type:"button",onClick:st,disabled:!m,title:m?void 0:"You don't have permission. Contact your admin.",className:`group w-full p-3 rounded-lg border text-left transition-all flex items-center gap-3 border-border-strong hover:border-primary-500/50 ${m?"":"opacity-50 cursor-not-allowed"}`,children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-text-primary",children:"Update credentials"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"Rotate this account's credentials, or switch to a different method."})]}),e.jsx("svg",{className:"h-4 w-4 shrink-0 text-text-muted transition-colors group-hover:text-primary-600",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,"aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.25 4.5l7.5 7.5-7.5 7.5"})})]})]}):e.jsxs("div",{children:[e.jsxs("button",{type:"button",onClick:()=>g(C=>(C&&T({}),!C)),className:"flex items-center gap-2 text-sm font-medium text-text-primary hover:text-primary-600 transition-colors",children:[e.jsx("svg",{className:`h-4 w-4 transition-transform ${$?"rotate-90":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.25 4.5l7.5 7.5-7.5 7.5"})}),"Update Credentials"]}),$&&e.jsx("div",{className:"mt-5 space-y-5",children:t.provider==="databricks"?e.jsx(Ts,{values:se,onChange:ne,errors:W,showSteps:!1}):e.jsx(qt,{provider:t.provider,authMethod:t.authMethod,form:se,onChange:ne,errors:W,onOAuthConnect:b,oauthLoading:S,permissionLevel:w,accountLocked:t.provider==="snowflake"})})]}),(t.provider==="aws"||t.provider==="gcp"||t.provider==="azure")&&t.status==="active"&&a&&e.jsx(Ca,{caID:t.id,provider:t.provider,onDisconnected:r,pendingMode:M,onPendingModeChange:O})]})}):null}const Aa=[{value:ft,label:"Users only"},{value:gt,label:"Users + Teams"}];function Ca({caID:t,provider:s,onDisconnected:r,pendingMode:a,onPendingModeChange:i}){const n=Te($e.CLOUD_ACCOUNT_UPDATE),o=Ds(),[c,d]=l.useState(!1),f=a,x=p=>{p!==f&&i?.(p)};return e.jsxs("div",{className:"rounded-xl border border-border-strong/60 bg-surface-elevated p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("svg",{className:"h-4 w-4 text-primary-600",fill:"none",stroke:"currentColor",strokeWidth:1.8,viewBox:"0 0 24 24",children:[e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}),e.jsx("circle",{cx:"9",cy:"7",r:"4"}),e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"m21 11-3 3-1.5-1.5"})]}),e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"Edit IAM"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-text-primary mb-2",children:"IAM sync mode"}),e.jsx("p",{className:"text-xs text-text-muted mb-2",children:"Choose which cloud principals get imported on the next sync. Re-open the import wizard to apply this mode."}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:Aa.map(p=>e.jsx("button",{type:"button",disabled:!n,onClick:()=>
9x(p.value),className:`p-3 rounded-lg border text-left transition-all ${f===p.value?"border-primary-600 bg-primary-600/5 ring-1 ring-primary-600/20":"border-border hover:border-border-strong"} ${n?"":"opacity-50 cursor-not-allowed"}`,children:e.jsx("p",{className:"text-sm font-medium text-text-primary",children:p.label})},p.value))}),e.jsx("div",{className:"mt-3",children:e.jsx(tn,{provider:s,mode:f,collapsible:!0})})]}),e.jsxs("div",{className:"flex items-center justify-between pt-2 border-t border-border",children:[e.jsx("p",{className:"text-xs text-text-muted",children:"Stop pulling IAM data from this cloud account."}),e.jsx("button",{type:"button",disabled:!n||o.isPending,onClick:()=>d(!0),className:"px-3 py-1.5 text-xs font-medium rounded border border-danger-500/60 text-danger-500 hover:bg-danger-500/10 disabled:opacity-50 disabled:cursor-not-allowed",children:o.isPending?"Disconnecting…":"Disconnect"})]}),e.jsx(zt,{open:c,onClose:()=>d(!1),onConfirm:()=>o.mutate({cloudAccountId:t},{onSuccess:()=>{d(!1),r?.()}}),title:"Disconnect IAM?",message:"This removes every user, team, role, and role assignment imported from this cloud account. The cloud account itself stays connected. You can re-import any time.",confirmLabel:"Disconnect",variant:"delete"})]})}function Sa({account:t,open:s,onClose:r}){const a=Cs(),i=Xe(),{data:n}=tt({queryKey:et.cloudAccounts.detail(i,t?.id),queryFn:()=>fe.get(`/cloud-accounts/${t?.id}`),enabled:s&&t?.authMethod==="assume_role"&&!!t?.id}),[o,c]=l.useState(0),[d,f]=l.useState(!1),[x,p]=l.useState({...Le}),[u,m]=l.useState({}),[h,v]=l.useState(null),[w,R]=l.useState(!1),$=ja.has(t?.authMethod),g=va(t?.authMethod),k=l.useMemo(()=>({...x,provider:t?.provider??"",authMethod:t?.authMethod??"",azureScope:t?.scope==="tenant"?"tenant":"subscription",name:t?.name??""}),[x,t]),N=l.useCallback((D,I)=>{p(V=>({...V,[D]:I})),m(V=>({...V,[D]:void 0})),v(null)},[]),j=l.useCallback(D=>{const I=Ce(k);I[D]&&m(V=>({...V,[D]:I[D]}))},[k]),z=async()=>{R(!0);try{const D=await fe.get("/connect/gcp/oauth-url",{permissionLevel:"read_write",appBasePath:"zopnight/app"});D?.url?window.location.href=D.url:(de.error("Failed to get Google authorization URL."),R(!1))}catch(D){de.error(`Failed to start Google connect: ${D?.message||"Unknown error"}`),R(!1)}},W=()=>{c(0),f(!1),p({...Le}),m({}),v(null),r()},T=()=>o<2||!d?!0:Object.keys(Ce(k)).length===0,S=()=>{const D={id:t.id,permissionLevel:"read_write"};if(d){const I=Ce(k);if(Object.keys(I).length>0){m(I);return}D.credentials=Mt(k)}a.mutate(D,{onSuccess:()=>{de.success("Account upgraded to Read + Write"),W()},onError:I=>{v(I?.message||"Upgrade failed. Please verify your permissions and try again.")}})},_=e.jsxs(e.Fragment,{children:[o>0&&e.jsx(G,{variant:"secondary",onClick:()=>c(D=>D-1),children:"Back"}),e.jsx("div",{className:"flex-1"}),e.jsx(G,{variant:"secondary",onClick:W,children:"Cancel"}),o<2&&e.jsx(G,{onClick:()=>c(D=>D+1),disabled:!T(),children:"Next"}),o===2&&e.jsx(G,{onClick:S,disabled:!T()||a.isPending,children:a.isPending?"Upgrading...":"Upgrade"})]});return t?e.jsxs(Se,{open:s,onClose:W,title:At[o],half:!0,footer:_,children:[e.jsx("div",{className:"flex items-center gap-1 mb-6",children:At.map((D,I)=>e.jsxs("div",{className:"flex items-center gap-1 flex-1",children:[e.jsx("div",{className:`flex items-center justify-center w-7 h-7 rounded-full text-[10px] font-bold shrink-0 transition-all ${I<o?"bg-success-500 text-white":I===o?"bg-primary-600 text-white ring-2 ring-primary-600/30":"bg-surface-tertiary text-text-muted"}`,children:I<o?e.jsx("svg",{className:"h-3.5 w-3.5",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z",clipRule:"evenodd"})}):I+1}),e.jsx("span",{className:`text-[10px] hidden sm:inline truncate ${I===o?"text-text-primary font-medium":I<o?"text-success-600":"text-text-muted"}`,children:D}),I<At.length-1&&e.jsx("div",{className:`flex-1 h-px transition-colors ${I<o?"bg-success-500":"bg-border"}`})]},D))}),e.jsxs("div",{className:"animate-fade-in",children:[o===0&&e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"p-3 rounded-lg bg-surface-secondary border border-border",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(oe,{provider:t.provider,className:"w-6 h-6"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-text-primary",children:t.name||t.cloudAccountId}),e.jsxs("p",{className:"text-xs text-text-muted",children:["Currently"," ",e.jsx(We,{variant:"neutral",className:"ml-1",children:"Read Only"})]})]})]})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary mb-1",children:"Your current features"}),e.jsx(Ye,{items:Js,included:!0}),e.jsxs("div",{className:"mt-2 pt-2 border-t border-border",children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wider text-text-muted font-semibold mb-1",children:"Not included"}),e.jsx(Ye,{items:Ys,included:!1})]})]}),e.jsxs("div",{className:"p-3 rounded-lg border-2 border-primary-600/30 bg-primary-600/5",children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary mb-1",children:"By upgrading to Read + Write"}),e.jsx("p",{className:"text-xs text-text-muted mb-2",children:"Everything in Read Only, plus:"}),e.jsx(Ye,{items:Qs,included:!0})]})]}),o===1&&e.jsxs("div",{children:[e.jsx("div",{className:"p-3 rounded-lg bg-primary-400/10 border border-primary-400/20 mb-4",children:e.jsxs("p",{className:"text-xs text-primary-600",children:["Update your existing ",g," in your ",De[t.provider]," console. You don't need to create a new ",g," — just add the write permissions shown below."]})}),e.jsx(Ot,{provider:t.provider,authMethod:t.authMethod,permissionLevel:"read_write",orgId:i,isUpgrade:!0,roleName:n?.roleName??t?.roleName,azureScope:t.scope||"subscription"})]}),o===2&&e.jsxs("div",{className:"space-y-4",children:[h&&e.jsx("div",{className:"p-3 rounded-lg bg-danger-500/10 border border-danger-500/20",children:e.jsx("p",{className:"text-xs text-danger-500",children:h})}),t.authMethod==="oauth"?e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"p-4 rounded-lg bg-primary-400/10 border border-primary-400/20",children:[e.jsx("p",{className:"text-sm font-medium text-primary-600 mb-1",children:"Connect with Google"}),e.jsx("p",{className:"text-xs text-text-secondary",children:"Click the button below to sign in with Google and grant ZopNight write access to your project. This will add scheduling permissions to your existing service account."})]}),e.jsx(G,{onClick:()=>{sessionStorage.setItem("gcp_oauth_upgrade_account_id",t.id),z()},disabled:w,className:"w-full",children:w?"Redirecting...":"Connect with Google"})]}):$?e.jsxs("div",{className:"p-4 rounded-lg bg-success-400/10 border border-success-400/20",children:[e.jsx("p",{className:"text-sm font-medium text-success-600 mb-1",children:"No new credentials needed"}),e.jsxs("p",{className:"text-xs text-text-secondary",children:["Since you're using ",Kt[t.authMethod],", your existing"," ",g," will automatically pick up the new permissions once you've updated them in your ",De[t.provider]," console."]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["How did you update your ",g,"?"]}),e.jsxs("div",{className:"grid gap-3",children:[e.jsxs(xe,{selected:!d,onClick:()=>f(!1),children:[e.jsxs("p",{className:"text-sm font-semibold text-text-primary",children:["I updated my existing ",g]}),e.jsxs("p",{className:"text-xs text-text-muted mt-0.5",children:["Write permissions were added to the same ",g," — no new keys needed."]})]}),e.jsxs(xe,{selected:d,onClick:()=>f(!0),children:[e.jsx("p",{className:"text-sm font-semibold text-text-primary",children:"I have new credentials"}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:"I created new credentials and need to enter them."})]})]}),d&&e.jsx("div",{className:"mt-3 space-y-4",children:e.jsx(qt,{provider:t.provider,authMethod:t.authMethod,form:k,onChange:N,errors:u,onOAuthConnect:z,oauthLoading:w,permissionLevel:"read_write",onBlurValidate:j})})]})]})]},o)]}):null}const Ia={shield:e.jsx("svg",{className:"h-3.5 w-3.5 shrink-0",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"})}),"credit-card":e.jsxs("svg",{className:"h-3.5 w-3.5 shrink-0",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"1",y:"4",width:"22",height:"16",rx:"2",ry:"2"}),e.jsx("line",{x1:"1",y1:"10",x2:"23",y2:"10"})]})};function Ma({name:t}){return Ia[t]??null}function cr(t){const{data:s,isError:r,isLoading:a}=Rs({type:"databricks",cloud_account_id:t.cloudAccountId,limit:100,include:"metadata"}),i=Wr(s?.items),n=s?.items?.find(o=>o?.provider)?.provider??null;return{...i,cloud:n,isError:r,isLoading:a,showAttention:!r&&!a&&i.needsAttention}}function lr({account:t,onOpen:s}){const{showAttention:r,isLoading:a,denied:i}=cr(t);return a?e.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-surface-tertiary text-[11px] text-text-muted",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-text-muted animate-pulse"}),"Checking workspace access…"]}):r?e.jsxs("button",{type:"button",onClick:s,"aria-label":`View permissions for ${t.name||"this Databricks connection"}`,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-warning-400/15 border border-warning-400/40 text-[11px] font-medium text-warning-700 hover:bg-warning-400/25 transition-colors",children:[e.jsx("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v4m0 4h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"})}),i," ",i===1?"workspace needs":"workspaces need"," access",e.jsx(Oe,{})]}):e.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-success-500/10 border border-success-500/30 text-[11px] font-medium text-success-700",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-success-500"}),"All features working"]})}function dr({account:t,onOpen:s}){const{total:r,accessible:a,showAttention:i,cloud:n}=cr(t),o=t.createdAt?qs(t.createdAt):null,c=i?`${a} of ${r}
9 workspaces accessible`:`${r} ${r===1?"workspace":"workspaces"}`;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"border-t border-border px-4 py-2.5 flex items-center justify-between gap-2",children:[n?e.jsxs(We,{variant:"neutral",className:"gap-1.5",children:[e.jsx(oe,{provider:n,className:"w-3.5 h-3.5"}),De[n]||n]}):e.jsx("span",{}),e.jsx("button",{type:"button",onClick:s,className:"text-xs text-primary-600 hover:underline font-medium",children:"View Permissions"})]}),e.jsxs("div",{className:"px-4 py-2 flex items-center justify-between gap-2 flex-wrap text-xs",children:[e.jsx("span",{className:"text-text-muted",children:c}),o&&e.jsxs("div",{className:"shrink-0 text-right",children:[e.jsx("span",{className:"text-text-muted",children:"Connected "}),e.jsx("span",{className:"text-text-secondary",children:o})]})]})]})}function ur({account:t,onEdit:s,onDelete:r,canEdit:a,canRemove:i,onViewPermissions:n,onViewResourceGroups:o,onUpgrade:c,onViewSubscriptions:d,fmtDate:f,onImportIAM:x,canImportIAM:p,iamImported:u,missingPermsCount:m=0,lastCheckedMs:h=null,healthLoaded:v=!1,probeBlocked:w=!1,probeFailed:R=!1,probeUnchecked:$=!1,writeNotGranted:g=!1,scpRestricted:k=!1,onManageClusters:N}){const[j,z]=l.useState(!1),W=t.status==="active",T=[{key:"write",label:"Upgrade to Read + Write",icon:"shield",show:t.permissionLevel==="read_only"&&!!c,onClick:()=>c(t)}].filter(_=>_.show),S=t.provider==="openshift"&&W&&e.jsx("button",{type:"button",onClick:()=>N?.(t),className:"text-left font-medium text-primary-600 hover:underline",children:"Manage clusters →"})||["aws","gcp","azure"].includes(t.provider)&&W&&(u?e.jsx(fs,{to:`/cloud-iam/${t.id}`,className:"text-primary-600 hover:underline font-medium",children:"Edit IAM →"}):x?e.jsx("button",{type:"button",disabled:!p,onClick:()=>p&&x(t),className:`text-left font-medium ${p?"text-primary-600 hover:underline":"text-text-muted opacity-50 cursor-not-allowed"}`,title:p?void 0:"You don't have permission. Contact your admin.",children:"Import IAM →"}):null)||null;return e.jsxs("div",{className:"border rounded-xl bg-surface shadow-card transition-all duration-normal hover:shadow-card-hover border-border-strong relative overflow-hidden flex flex-col",children:[e.jsxs("div",{className:"p-4 flex-1",children:[e.jsxs("div",{className:"flex justify-between items-start",children:[e.jsxs("div",{className:"min-w-0 flex-1 flex items-center gap-3",children:[e.jsx(oe,{provider:t.provider,className:"w-6 h-6 shrink-0"}),e.jsx("div",{className:"min-w-0",children:e.jsx("div",{className:"flex items-center gap-2",children:e.jsx("h3",{className:"font-semibold text-text-primary truncate",children:t.name||"—"})})})]}),e.jsx(Qr,{items:[{label:"Edit",onClick:()=>s(t),disabled:!a,disabledTitle:"You don't have permission. Contact your admin."},o&&{label:"Resource Groups",onClick:()=>o(t)},t.provider==="openshift"&&W&&{label:"Manage clusters",onClick:()=>N?.(t)},{label:"Remove",danger:!0,onClick:()=>r(t),disabled:!i,disabledTitle:"You don't have permission. Contact your admin."}]})]}),t.scope!=="tenant"&&t.provider!=="databricks"&&t.provider!=="openshift"&&e.jsx("div",{className:"mt-3",children:e.jsx(_a,{loaded:v,missingCount:m,blocked:w,checkFailed:R,unchecked:$,writeNotSetUp:g,scpRestricted:k,onClick:()=>n?.(t)})}),t.provider==="databricks"&&e.jsx("div",{className:"mt-3",children:e.jsx(lr,{account:t,onOpen:()=>z(!0)})}),e.jsxs("div",{className:"mt-3 flex items-center gap-2 text-[11px] text-text-muted min-w-0",children:[e.jsx(Qt,{content:t.cloudAccountId,onlyOnOverflow:!0,children:e.jsx("span",{className:"font-mono text-text-secondary truncate",children:t.cloudAccountId})}),t.provider!=="databricks"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-text-muted",children:"·"}),e.jsx("span",{className:"shrink-0",children:Kt[t.authMethod]||t.authMethod})]}),t.scope==="tenant"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-text-muted",children:"·"}),e.jsx(We,{variant:"neutral",children:"Tenant"})]})]}),T.length>0&&e.jsx("div",{className:"mt-3 flex flex-col gap-1.5",children:T.map(_=>e.jsxs("button",{type:"button",onClick:_.onClick,className:"group flex items-center gap-2 px-2.5 py-1.5 rounded-md text-xs text-primary-600 hover:bg-primary-400/10 transition-colors",children:[e.jsx(Ma,{name:_.icon}),e.jsx("span",{children:_.label}),e.jsx("svg",{className:"h-3 w-3 shrink-0 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"M5 12h14M12 5l7 7-7 7"})})]},_.key))})]}),t.provider==="databricks"?e.jsx(dr,{account:t,onOpen:()=>z(!0)}):t.provider==="openshift"?null:e.jsxs("div",{className:"border-t border-border px-4 py-2.5 flex items-center justify-between gap-2 flex-wrap",children:[e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:e.jsx(We,{variant:t.permissionLevel==="read_write"?"success":"neutral",children:ya(t.permissionLevel)})}),t.scope==="tenant"?e.jsx("button",{type:"button",onClick:()=>d?.(t),className:"text-xs text-primary-600 hover:underline font-medium",children:"View Subscriptions"}):e.jsx("button",{type:"button",onClick:()=>n?.(t),className:"text-xs text-primary-600 hover:underline font-medium",children:"View Permissions"})]}),t.provider!=="databricks"&&(S||h||t.createdAt)&&e.jsxs("div",{className:`px-4 py-2 flex items-center gap-3 text-xs ${S?"justify-between":""}${t.provider==="openshift"?" border-t border-border":""}`,children:[S&&e.jsx("div",{className:"min-w-0",children:S}),(h||t.createdAt)&&e.jsx("div",{className:`shrink-0${S?" text-right":""}`,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-text-muted",children:"Last checked "}
9),e.jsx(Qt,{content:new Date(h).toLocaleString(),children:e.jsx("span",{className:"text-text-secondary",children:Ra(h)})})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-text-muted",children:"Connected "}),e.jsx("span",{className:"text-text-secondary",children:qs(t.createdAt)})]})})]}),t.provider==="databricks"&&e.jsx(ua,{account:t,open:j,onClose:()=>z(!1)})]})}function _a({loaded:t,missingCount:s,blocked:r,checkFailed:a,unchecked:i,writeNotSetUp:n,scpRestricted:o,onClick:c}){return t?r?e.jsxs("button",{type:"button",onClick:c,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-warning-400/15 border border-warning-400/40 text-[11px] font-medium text-warning-700 hover:bg-warning-400/25 transition-colors",children:[e.jsxs("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]}),"Feature status unknown",e.jsx(Oe,{})]}):a?e.jsxs("button",{type:"button",onClick:c,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-danger-400/15 border border-danger-400/40 text-[11px] font-medium text-danger-500 hover:bg-danger-400/25 transition-colors",children:[e.jsx("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v4m0 4h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"})}),"Credentials invalid or expired",e.jsx(Oe,{})]}):i?e.jsxs("button",{type:"button",onClick:c,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-neutral-500/10 border border-neutral-500/30 text-[11px] font-medium text-neutral-600 hover:bg-neutral-500/20 transition-colors",children:[e.jsxs("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("circle",{cx:"12",cy:"12",r:"9"}),e.jsx("path",{d:"M12 8h.01M11 12h1v4h1"})]}),"Couldn't check permissions",e.jsx(Oe,{})]}
9):n?e.jsxs("button",{type:"button",onClick:c,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-warning-400/15 border border-warning-400/40 text-[11px] font-medium text-warning-700 hover:bg-warning-400/25 transition-colors",children:[e.jsxs("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]}),"Write access not set up",e.jsx(Oe,{})]}):s>0?e.jsxs("button",{type:"button",onClick:c,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-warning-400/15 border border-warning-400/40 text-[11px] font-medium text-warning-700 hover:bg-warning-400/25 transition-colors",children:[e.jsx("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v4m0 4h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"})}),s," ",s===1?"feature needs":"features need"," more access",e.jsx(Oe,{})]}):o?e.jsxs("button",{type:"button",onClick:c,className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-warning-400/15 border border-warning-400/40 text-[11px] font-medium text-warning-700 hover:bg-warning-400/25 transition-colors",children:[e.jsxs("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"3.5",y:"10.5",width:"17",height:"11",rx:"2"}),e.jsx("path",{d:"M7 10.5V7a5 5 0 0 1 10 0v3.5"})]}),"Some features restricted",e.jsx(Oe,{})]}):e.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-success-500/10 border border-success-500/30 text-[11px] font-medium text-success-700",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-success-500"}),"All features working"]}):e.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-surface-tertiary text-[11px] text-text-muted",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-text-muted animate-pulse"}),"Checking permissions…"]})}function xr(t,s,r){const a=r==="read_only",i=n=>!(a&&n.perms.some(o=>o.category==="write"));return{count:t.filter(n=>n.status==="needs_attention"&&i(n)).length,scpRestricted:t.some(n=>n.status==="cant_verify"&&i(n)),writeNotGranted:vs(t,r),lastCheckedMs:me(s),loaded:!0}}function Oe(){return e.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",className:"w-3 h-3",children:[e.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"}),e.jsx("polyline",{points:"12 5 19 12 12 19"})]})}function Ra(t){if(!t)return"—";const s=Date.now()-t;if(s<6e4)return"just now";const r=Math.floor(s/6e4);if(r<60)return`${r}m ago`;const a=Math.floor(r/60);if(a<24)return`${a}h ago`;const i=Math.floor(a/24);if(i<30)return`${i}d ago`;const n=Math.floor(i/30);return n<12?`${n}mo ago`:`${Math.floor(n/12)}y ago`}const hs=20;function Pa({account:t,open:s,onClose:r}){const a=t?.cloudAccountId??t?.id,[i,n]=l.useState(""),[o,c]=l.useState(1),d=$t(i,300),f=l.useCallback(R=>{n(R),c(1)},[]),x={type:"resource-group",cloud_account_id:a,limit:hs,page:o};d&&(x.search=d);const{data:p,isLoading:u,isError:m,error:h}=tt({queryKey:et.resources.list(x),queryFn:()=>fe.get("/resources",x),enabled:s&&!!a,keepPreviousData:!0}),v=p?.items??(Array.isArray(p)?p:[]),w=p?.hasMore??!1;return e.jsxs(Se,{open:s,onClose:r,title:"Resource Groups",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(oe,{provider:t?.provider,className:"w-5 h-5 shrink-0"}),e.jsx("p",{className:"text-sm text-text-secondary truncate",children:t?.name||t?.cloudAccountId})]}),e.jsx(Et,{placeholder:"Search resource groups...",value:i,onChange:f,className:"mb-4",size:"sm"}),u&&v.length===0?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(vt,{})}):m?e.jsx("div",{className:"text-center py-16",children:e.jsx("p",{className:"text-sm text-danger-500",children:h?.message||"Failed to load resource groups"})}):v.length===0?e.jsx(Fe,{message:d?`No resource groups matching "${d}
9".`:"No resource groups found. Run a discovery first."}):e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"space-y-1.5",children:v.map(R=>e.jsxs("div",{className:"group flex items-center gap-3 rounded-lg border border-border px-3.5 py-2.5 hover:border-border-strong hover:bg-surface-secondary/50 transition-all duration-fast",children:[e.jsx("div",{className:"w-1.5 h-1.5 rounded-full bg-primary-600/60 group-hover:bg-primary-600 transition-colors duration-fast shrink-0"}),e.jsx("div",{className:"min-w-0 flex-1",children:e.jsx("p",{className:"text-sm font-medium text-text-primary truncate",children:R.name})}),e.jsx(We,{variant:"neutral",children:R.region})]},R.uid||R.id))}),(w||o>1)&&e.jsx(Tt,{page:o,hasMore:w,label:"resource groups",onPageChange:c,pageSize:hs})]})]})}const La=12;function Da({tenant:t,onBack:s,onEdit:r,onDelete:a,onViewPermissions:i,onViewResourceGroups:n,onUpgrade:o,canEdit:c,canDelete:d,fmtDate:f,onImportIAM:x,canImportIAM:p,iamImportedCAIds:u}){const m=Xe(),{page:h,pageSize:v,setPage:w,setPageSize:R}=Ps({defaultPageSize:La}),[$,g]=l.useState(""),k=$t($,300),N={page:h,limit:v};k&&(N.search=k);const{data:j,isLoading:z,isError:W,error:T,refetch:S}=tt({queryKey:et.cloudAccounts.subscriptions(m,t.id,N),queryFn:()=>fe.get("/cloud-accounts",{...N,parent_account_id:t.id}),keepPreviousData:!0}),_=j?.items??(Array.isArray(j)?j:[]),D=j?.hasMore??!1,I=l.useMemo(()=>[...new Set(_.map(M=>M.cloudAccountId).filter(Boolean))],[_]),{byAccount:V}=ks(I),{byAccount:q}=ws(_),F=l.useMemo(()=>_.some(M=>M.provider==="snowflake"),[_]),{lookup:le,isLoading:te}=Ns({enabled:F}),Y=l.useMemo(()=>{const M={};for(const O of _){const re=V[O.cloudAccountId];if(!re||re.loading){M[O.id]={count:0,lastCheckedMs:null,loaded:!1};continue}if(O.provider==="snowflake"&&te){M[O.id]={count:0,lastCheckedMs:null,loaded:!1};continue}const J=yt(re.permissions??[],O.provider,le(O.cloudAccountId));if(jt(J)&&!Qe(J)){M[O.id]={count:0,lastCheckedMs:me(J),loaded:!0,blocked:!0};continue}if(Qe(J)){M[O.id]={count:0,lastCheckedMs:me(J),loaded:!0,checkFailed:!0};continue}const se=Rt(J,O.provider);if(se.length===0){M[O.id]={count:0,lastCheckedMs:me(J),loaded:!0,unchecked:!0};continue}const ne=Pt(se);if(ne&&Gt(se)){M[O.id]={count:0,lastCheckedMs:me(J),loaded:!0,checkFailed:!0};continue}if(ne){M[O.id]={count:0,lastCheckedMs:me(J),loaded:!0,unchecked:!0};continue}if(As(O.cloudAccountId)){M[O.id]={count:0,lastCheckedMs:null,loaded:!0};continue}const ee=Lt(J,O.provider,["zopnight"]),b=xr(ee,J,O.permissionLevel),A=q[O.id];O.provider==="azure"&&A?.loaded&&A.needsAttention&&(b.count=(b.count??0)+1),M[O.id]=b}return M},[_,V,q,le,te]);return e.jsxs("div",{className:"flex-1 flex flex-col",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx("button",{type:"button",onClick:s,className:"p-1.5 rounded-lg hover:bg-surface-elevated transition-colors text-text-muted hover:text-text-primary",children:e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:"w-5 h-5",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"})})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("h2",{className:"text-lg font-semibold text-text-primary truncate",children:t.name}),e.jsx("p",{className:"text-xs text-text-muted font-mono",children:t.cloudAccountId})]})]}),e.jsx("div",{className:"flex items-center gap-3 mb-4",children:e.jsx(Et,{placeholder:"Search subscriptions...",value:$,onChange:M=>{g(M),w(1)},className:"max-w-xs",size:"sm"})}),z?e.jsx("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:[1,2,3].map(M=>e.jsxs("div",{className:"border rounded-xl border-border-strong overflow-hidden",children:[e.jsx("div",{className:"p-4 space-y-3",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded bg-surface-tertiary animate-shimmer"}),e.jsxs("div",{className:"space-y-1.5 flex-1",children:[e.jsx("div",{className:"h-4 w-1/2 roun
9ded bg-surface-tertiary animate-shimmer"}),e.jsx("div",{className:"h-3 w-1/4 rounded bg-surface-tertiary animate-shimmer"})]})]})}),e.jsx("div",{className:"border-t border-border px-4 py-2.5",children:e.jsx("div",{className:"h-5 w-16 rounded-full bg-surface-tertiary animate-shimmer"})})]},`sub-skeleton-${M}`))}):W?e.jsx(Fe,{title:"Failed to load subscriptions",description:T?.message||"An error occurred while loading subscriptions.",action:e.jsx(G,{onClick:()=>S(),children:"Retry"})}):_.length===0?e.jsx(Fe,{title:"No subscriptions",description:k?`No subscriptions matching "${k}".`:"No subscriptions connected for this tenant yet."}):e.jsxs("div",{children:[e.jsx("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:_.map(M=>e.jsx(ur,{account:M,onEdit:r,onDelete:a,canEdit:c,canRemove:d,onViewPermissions:i,onUpgrade:o,onViewResourceGroups:M.provider==="azure"?n:void 0,fmtDate:f,onImportIAM:x,canImportIAM:p,iamImported:u?.has?.(M.id),missingPermsCount:Y[M.id]?.count??0,lastCheckedMs:Y[M.id]?.lastCheckedMs??null,healthLoaded:Y[M.id]?.loaded??!1,probeBlocked:Y[M.id]?.blocked??!1,probeFailed:Y[M.id]?.checkFailed??!1,probeUnchecked:Y[M.id]?.unchecked??!1,writeNotGranted:Y[M.id]?.writeNotGranted??!1,scpRestricted:Y[M.id]?.scpRestricted??!1},M.id))}),e.jsx("div",{className:"mt-4",children:e.jsx(Tt,{page:h,hasMore:D,count:_.length,label:"subscriptions",onPageChange:w,pageSize:v,onPageSizeChange:R,pageSizeOptions:[12,24,48]})})]})]})}function Ea(){const{page:t,pageSize:s,setPage:r,setPageSize:a,resetPage:i}=Ps({defaultPageSize:12}),[n,o]=l.useState(""),c=$t(n,300),{data:d,isLoading:f}=Mr({page:t,limit:s,search:c}),x=Array.isArray(d)?d:d?.items??[],p=Array.isArray(d)?!1:d?.hasMore??!1,{data:u=[]}=Dt(),m=u.length,h=l.useMemo(()=>[...new Set(x.map(y=>y.cloudAccountId).filter(Boolean))],[x]),{byAccount:v}=ks(h),{byAccount:w}=ws(x),R=l.useMemo(()=>x.some(y=>y.provider==="snowflake"),[x]),{lookup:$,isLoading:g}=Ns({enabled:R}),k=l.useMemo(()=>{const y={};for(const P of x){const pe=v[P.cloudAccountId];if(!pe||pe.loading){y[P.id]={count:0,lastCheckedMs:null,loaded:!1};continue}if(P.provider==="snowflake"&&g){y[P.id]={count:0,lastCheckedMs:null,loaded:!1};continue}const ie=yt(pe.permissions??[],P.provider,$(P.cloudAccountId));if(jt(ie)&&!Qe(ie)){y[P.id]={count:0,lastCheckedMs:me(ie),loaded:!0,blocked:!0};continue}if(Qe(ie)){y[P.id]={count:0,lastCheckedMs:me(ie),loaded:!0,checkFailed:!0};continue}const at=Rt(ie,P.provider);if(at.length===0){y[P.id]={count:0,lastCheckedMs:me(ie),loaded:!0,unchecked:!0};continue}const Re=Pt(at);if(Re&&Gt(at)){y[P.id]={count:0,lastCheckedMs:me(ie),loaded:!0,checkFailed:!0};continue}if(Re){y[P.id]={count:0,lastCheckedMs:me(ie),loaded:!0,unchecked:!0};continue}if(As(P.cloudAccountId)){y[P.id]={count:0,lastCheckedMs:null,loaded:!0};continue}const mt=Lt(ie,P.provider,["zopnight"]),Nt=xr(mt,ie,P.permissionLevel),Jt=w[P.id];P.provider==="azure"&&Jt?.loaded&&Jt.needsAttention&&(Nt.count=(Nt.count??0)+1),y[P.id]=Nt}return y},[x,v,w,$,g]),N=l.useMemo(()=>{const y={};for(const[P,pe]of Object.entries(k))y[P]=pe.count;return y},[k]),{fmtDate:j}=_r(),z=Rr(),W=Pr(),[T,S]=l.useState(Gr),_=Te($e.CLOUD_ACCOUNT_CREATE),D=Te($e.CLOUD_ACCOUNT_UPDATE),I=Te($e.CLOUD_ACCOUNT_DELETE),V=Te($e.CLOUD_ACCOUNT_UPDATE),{data:q}=gs(),{data:F}=Lr(),{data:le}=Ss(),te=l.useMemo(()=>{const y=new Set,P=pe=>{const ie=Array.isArray(pe)?pe:pe?.items??pe?.data??[];for(const at of ie){let Re=at?.metadata;if(typeof Re=="string")try{Re=JSON.parse(Re)}catch{Re=null}const mt=Re?.importedFrom?.cloudAccountId;mt&&y.add(mt)}};return P(q),P(F),P(le),y},[q,F,le]),[Y,M]=l.useState(!1),[O,re]=l.useState(null),[J,se]=l.useState(!1),ne=(y,{credentialFlow:P=!1}={})=>{se(P),re(y)},[ee,b]=l.useState(null),[A,L]=l.useState(null),[U,E]=l.useState(null),[Z,ae]=l.useState(null),[be,ye]=l.useState(null),[Ue,st]=l.useState(null),[ut,xt]=l.useState(null),[Ge,wt]=l.useState(""),[rt,nt]=l.useState(null),[Ke,we]=hr(),C=Ke.get("edit"),K=l.useMemo(()=>!C||x.length===0?null:x.find(y=>y.cloudAccountId===C||y.id===C)??null,[C,x]);l.useEffect(()=>{if(K&&!O){const y=requestAnimationFrame(()=>{ne(K),we(P=>(P.delete("edit"),P),{replace:!0})});return()=>cancelAnimationFrame(y)}},[K,O,we]);const Q=Ke.get("upgrade"),Me=l.useMemo(()=>!Q||x.length===0?null:x.find(y=>y.cloudAccountId===Q||y.id===Q)??null,[Q,x]);l.useEffect(()=>{if(Me&&!be){const y=requestAnimationFrame(()=>{ye(Me),we(P=>(P.delete("upgrade"),P),{replace:!0})});return()=>cancelAnimationFrame(y)}},[Me,be,we]);const Ne=Ke.get("viewPermissions"),Ee=l.useMemo(()=>!Ne||x.length===0?null:x.find(y=>y.cloudAccountId===Ne||y.id===Ne)??null,[Ne,x]);l.useEffect(()=>{if(Ee&&!U){const y=requestAnimationFrame(()=>{E(Ee),we(P=>(P.delete("viewPermissions"),P),{replace:!0})});return()=>cancelAnimationFrame(y)}},[Ee,U,we]);const Ae=Ke.get("fixPermissions"),Be=l.useMemo(()=>!Ae||x.length===0?null:x.find(y=>y.cloudAccountId===Ae||y.id===Ae)??null,[Ae,x]);l.useEffect(()=>{if(Be&&!Z){const y=requestAnimationFrame(()=>{ae(Be),we(P=>(P.delete("fixPermissions"),P),{replace:!0})});return()=>cancelAnimationFrame(y)}},[Be,Z,we]);const Vt=l.useMemo(()=>Ge?x.filter(y=>y.provider===Ge):x,[x,Ge]),mr=(y,{onSuccess:P,onError:pe})=>{z.mutate(y,{onSuccess:ie=>P(ie),onError:ie=>pe?.(ie)})},pr=()=>{if(!ee)return;const y=ee.disconnectNextStep??null;W.mutate(ee.id,{onSuccess:()=>{ss(y),S(y),b(null)}})};return e.jsxs("div",{className:"flex-1 flex flex-col",children:[e.jsx(ts,{step:T,onDismiss:()=>{ss(null),S(null)}}),ut?e.jsx(Da,{tenant:ut,onBack:()=>{xt(null),i()},onEdit:ne,onDelete:b,onViewPermissions:E,onViewResourceGroups:st,onUpgrade:ye,canEdit:D,canDelete:I,fmtDate:j,onImportIAM:nt,canImportIAM:V,iamImportedCAIds:te}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-x-3 gap-y-2 bg-surface-secondary rounded-lg px-3 py-2.5 border border-border",children:[e.jsx(Et,{placeholder:"Search accounts...",value:n,onChange:y=>{o(y),r(1)},className:"w-full sm:max-w-xs",size:"sm"}),x.length>=3&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"hidden sm:block w-px h-5 bg-border-strong"}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-xs font-medium text-text-muted shrink-0",children:"Provider"}),e.jsx(Ur,{options:[{value:"",label:"All Providers"},{value:"aws",label:"AWS"},{value:"gcp",label:"GCP"},{value:"azure",label:"Azure"},{value:"microsoft365",label:"Microsoft 365"}],value:Ge,onChange:y=>wt(y.target.value),placeholder:"All Providers",size:"sm",className:"min-w-[150px]"})]})]}),e.jsx(G,{disabled:!_,title:_?void 0:"You don't have permission. Contact your admin.",onClick:()=>M(!0),className:"whitespace-nowrap shrink-0 ml-auto",children:"+ Add Cloud Account"})]}),f?e.jsx("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:[1,2,3].map(y=>e.jsxs("div",{className:"border rounded-xl border-border-strong overflow-hidden",children:[e.jsxs("div",{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded bg-surface-tertiary animate-shimmer"}),e.jsxs("div",{className:"space-y-1.5 flex-1",children:[e.jsx("div",{className:"h-4 w-1/2 roun
9ded bg-surface-tertiary animate-shimmer"}),e.jsx("div",{className:"h-3 w-1/4 rounded bg-surface-tertiary animate-shimmer"})]})]}),e.jsxs("div",{className:"space-y-2 pt-1",children:[e.jsx("div",{className:"h-3 w-full rounded bg-surface-tertiary animate-shimmer"}),e.jsx("div",{className:"h-3 w-3/4 rounded bg-surface-tertiary animate-shimmer"})]})]}),e.jsx("div",{className:"border-t border-border px-4 py-2.5",children:e.jsx("div",{className:"h-5 w-16 rounded-full bg-surface-tertiary animate-shimmer"})})]},`skeleton-${y}`))}):x.length===0&&!c?e.jsx(Is,{children:e.jsx(Fe,{icon:e.jsx("div",{className:"flex items-center justify-center gap-4",children:e.jsx("svg",{className:"h-10 w-10 text-text-muted",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.25 15a4.5 4.5 0 0 0 4.5 4.5H18a3.75 3.75 0 0 0 1.332-7.257 3 3 0 0 0-3.758-3.848 5.25 5.25 0 0 0-10.233 2.33A4.502 4.502 0 0 0 2.25 15Z"})})}),title:"No cloud accounts connected",description:"Add a cloud account to start discovering and scheduling resources.",action:e.jsxs("div",{children:[e.jsx("div",{className:"flex justify-center gap-3 mb-4",children:Hs.map(y=>e.jsx(oe,{provider:y.value,className:"w-6 h-6 opacity-40"},y.value))}),e.jsx(G,{disabled:!_,title:_?void 0:"You don't have permission. Contact your admin.",onClick:()=>M(!0),children:"+ Add Cloud Account"})]})})}):Vt.length===0?e.jsx(Fe,{message:c?`No accounts matching "${c}".`:"No accounts match the selected filter."}):e.jsxs("div",{children:[e.jsx("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:Vt.map(y=>e.jsx(ur,{account:y,onEdit:ne,onDelete:b,canEdit:D,canRemove:I,onViewPermissions:E,onManageClusters:L,onUpgrade:ye,onViewResourceGroups:y.provider==="azure"&&y.scope!=="tenant"?st:void 0,onViewSubscriptions:y.scope==="tenant"?P=>{xt(P),i()}:void 0,fmtDate:j,onImportIAM:nt,canImportIAM:V,iamImported:te?.has?.(y.id),missingPermsCount:N[y.id]??0,lastCheckedMs:k[y.id]?.lastCheckedMs??null,healthLoaded:k[y.id]?.loaded??!1,probeBlocked:k[y.id]?.blocked??!1,probeFailed:k[y.id]?.checkFailed??!1,probeUnchecked:k[y.id]?.unchecked??!1,writeNotGranted:k[y.id]?.writeNotGranted??!1,scpRestricted:k[y.id]?.scpRestricted??!1},y.id))}),e.jsx("div",{className:"mt-4",children:e.jsx(Tt,{page:t,hasMore:p,total:m,label:"accounts",onPageChange:r,pageSize:s,onPageSizeChange:a,pageSizeOptions:[12,24,48]})})]})]}),e.jsx(ir,{open:Y,onClose:()=>M(!1),onSubmit:mr,isLoading:z.isPending,onManageClusters:L}),A&&e.jsx(fa,{account:A,open:!!A,onClose:()=>L(null)}),e.jsx(or,{account:O,open:!!O,onClose:()=>{re(null),se(!1)},iamImported:O?te?.has?.(O.id):!1,startInCredentialFlow:J},`${O?.id}:${J}`),e.jsx(zt,{open:!!ee,onClose:()=>b(null),onConfirm:pr,title:"Remove Cloud Account",message:ee?.scope==="tenant"?`Remove "${ee?.name}" and all its connected subscriptions? This will stop all discovery and scheduled actions for every subscription in this tenant.`:`Remove "${ee?.name||ee?.cloudAccountId}" (${De[ee?.provider]||ee?.provider})? This will stop all discovery and scheduled actions for this account.`,confirmLabel:"Remove",isLoading:W.isPending,children:e.jsx(ts,{step:ee?.disconnectNextStep})}),e.jsx(Hn,{open:!!U,onClose:()=>E(null),cloudAccountId:U?.cloudAccountId??U?.id,cloudAccountName:U?.name,provider:U?.provider,account:U,onUpdateCredentials:y=>{E(null),ne(y,{credentialFlow:!0})}}),e.jsx(Us,{open:!!Z,onClose:()=>ae(null),cloudAccountId:Z?.cloudAccountId??Z?.id,cloudAccountName:Z?.name,provider:Z?.provider,account:Z}),e.jsx(Sa,{account:be,open:!!be,onClose:()=>ye(null)},be?.id),e.jsx(Pa,{account:Ue,open:!!Ue,onClose:()=>st(null)},Ue?.id),e.jsx(Xr,{open:!!rt,onClose:()=>nt(null),cloudAccount:rt},rt?.id)]})}const ai=Object.freeze(Object.defineProperty({__proto__:null,AddCloudAccountWizard:ir,DatabricksCardFooter:dr,DatabricksConnectionStatus:lr,EditCloudAccountDrawer:or,StepAuthMethod:Bt,StepConnectDatabricks:ar,StepCredentials:Ht,StepDatabricksAzure:nr,StepDatabricksCloud:sr,StepDatabricksProvider:rr,StepOpenShiftAccess:tr,StepPermissionLevel:er,StepSelectProvider:Xs,StepSetupGuide:Zt,default:Ea},Symbol.toStringTag,{value:"Module"}));
9export{Es as A,ai as C,Le as I,Xs as S,Bt as a,sr as b,rr as c,tr as d,er as e,Zt as f,ar as g,Ht as h,nr as i,Os as j,Ce as v};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.