@stacksjs/ts-cloud 0.16.26 → 0.16.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/aws/client.d.ts +6 -0
  2. package/dist/aws/index.js +1 -1
  3. package/dist/bin/{chunk-w23en85y.js → chunk-13htvxgc.js} +1 -1
  4. package/dist/bin/chunk-2ar52zq0.js +1 -0
  5. package/dist/bin/{chunk-4xfwb21f.js → chunk-2chec65b.js} +1 -1
  6. package/dist/bin/{chunk-8tp6srfc.js → chunk-45v1azhc.js} +1 -1
  7. package/dist/bin/{chunk-f4rp62j4.js → chunk-494fg5c6.js} +1 -1
  8. package/dist/bin/chunk-4fwbwjjj.js +1 -0
  9. package/dist/bin/chunk-57f4mqzk.js +1 -0
  10. package/dist/bin/{chunk-qsyna6ng.js → chunk-5810132y.js} +1 -1
  11. package/dist/bin/{chunk-ccykpema.js → chunk-66f51kn2.js} +1 -1
  12. package/dist/bin/chunk-ank4fmbx.js +1 -0
  13. package/dist/bin/{chunk-y6rgvb7r.js → chunk-az5vvf5d.js} +1 -1
  14. package/dist/bin/chunk-azcxgwhm.js +1 -0
  15. package/dist/bin/{chunk-3rzabz10.js → chunk-b4p9zknk.js} +1 -1
  16. package/dist/bin/{chunk-r2ft7vek.js → chunk-djtt70tn.js} +1 -1
  17. package/dist/bin/chunk-f922vrbs.js +1 -0
  18. package/dist/bin/{chunk-5ky6qf18.js → chunk-ffyhp5tk.js} +2 -2
  19. package/dist/bin/chunk-k0akp8k0.js +1 -0
  20. package/dist/bin/{chunk-4r46kw46.js → chunk-k545r9bk.js} +1 -1
  21. package/dist/bin/chunk-k6dxgzm6.js +1 -0
  22. package/dist/bin/{chunk-fjxsj9z9.js → chunk-kbwczaa8.js} +1 -1
  23. package/dist/bin/{chunk-dh6kj6ce.js → chunk-kcprsn33.js} +1 -1
  24. package/dist/bin/{chunk-0apv4e8e.js → chunk-kfj4w903.js} +2 -2
  25. package/dist/bin/{chunk-92rhkvpx.js → chunk-ne5zevtf.js} +2 -2
  26. package/dist/bin/{chunk-z3962as2.js → chunk-qfgvvwmb.js} +1 -1
  27. package/dist/bin/{chunk-1j9vy88a.js → chunk-qx05kccj.js} +1 -1
  28. package/dist/bin/{chunk-6nm91cfw.js → chunk-s5hq7v1h.js} +1 -1
  29. package/dist/bin/chunk-s7gk1qx2.js +1 -0
  30. package/dist/bin/{chunk-3jjggqfj.js → chunk-st7s9k78.js} +1 -1
  31. package/dist/bin/chunk-t644w5rw.js +1 -0
  32. package/dist/bin/chunk-twq6s0nd.js +1 -0
  33. package/dist/bin/chunk-vknq0ap2.js +1 -0
  34. package/dist/bin/{chunk-85733wwc.js → chunk-vsgq1d3s.js} +3 -3
  35. package/dist/bin/{chunk-h3shxxh4.js → chunk-x6y663t7.js} +1 -1
  36. package/dist/bin/{chunk-q3xwh0r8.js → chunk-y5e7dmvc.js} +4 -4
  37. package/dist/bin/{chunk-2q27v6vz.js → chunk-ypsgkj91.js} +1 -1
  38. package/dist/bin/chunk-za9np4pg.js +1 -0
  39. package/dist/bin/chunk-zqa6jarz.js +1 -0
  40. package/dist/bin/{chunk-hwqvx1zb.js → chunk-zrjf1pqy.js} +1 -1
  41. package/dist/bin/cli.js +81 -81
  42. package/dist/bin/dashboard-server.js +1 -1
  43. package/dist/chunk-2p85fnx5.js +1 -0
  44. package/dist/chunk-3q242cqb.js +1 -0
  45. package/dist/{chunk-7p1653g6.js → chunk-4ka2s5d8.js} +2 -2
  46. package/dist/{chunk-wrpnnrdf.js → chunk-55yda01s.js} +4 -4
  47. package/dist/{chunk-mte9da2p.js → chunk-6eqx6gt8.js} +2 -2
  48. package/dist/{chunk-0p7ddjt6.js → chunk-818d8w7e.js} +1 -1
  49. package/dist/{chunk-x9bpm5s1.js → chunk-bx1znp1q.js} +1 -1
  50. package/dist/chunk-cykr6zyj.js +1 -0
  51. package/dist/{chunk-setpnrtg.js → chunk-cymsceq6.js} +1 -1
  52. package/dist/{chunk-3zv0e36t.js → chunk-dygr8ewz.js} +1 -1
  53. package/dist/{chunk-mdqnpbbc.js → chunk-fvgk05df.js} +1 -1
  54. package/dist/{chunk-e4z4tfh6.js → chunk-h5gvh859.js} +1 -1
  55. package/dist/chunk-mqscxx2z.js +1 -0
  56. package/dist/{chunk-k75jv8s6.js → chunk-ne0e6484.js} +5 -5
  57. package/dist/{chunk-5db32a4x.js → chunk-njz7scff.js} +1 -1
  58. package/dist/{chunk-2nma0bd8.js → chunk-q70pfhcn.js} +1 -1
  59. package/dist/{chunk-08tswmb3.js → chunk-qx6nwvgn.js} +1 -1
  60. package/dist/{chunk-e44ajkha.js → chunk-twj83txn.js} +1 -1
  61. package/dist/{chunk-tvwrthfq.js → chunk-wyfpz6be.js} +1 -1
  62. package/dist/{chunk-dm6kyz6e.js → chunk-ys5318bg.js} +1 -1
  63. package/dist/deploy/index.js +1 -1
  64. package/dist/dns/index.js +1 -1
  65. package/dist/drivers/index.js +1 -1
  66. package/dist/index.js +1 -1
  67. package/dist/ui/404.html +1 -1
  68. package/dist/ui/accept-invitation.html +1 -1
  69. package/dist/ui/access-denied.html +1 -1
  70. package/dist/ui/account/automation.html +6 -6
  71. package/dist/ui/account/security.html +2 -2
  72. package/dist/ui/applications/compose.html +6 -6
  73. package/dist/ui/applications/new.html +1 -1
  74. package/dist/ui/data/backups.html +5 -5
  75. package/dist/ui/data/services.html +6 -6
  76. package/dist/ui/data/volumes.html +6 -6
  77. package/dist/ui/index.html +6 -6
  78. package/dist/ui/infrastructure/topology.html +5 -5
  79. package/dist/ui/integrations.html +1 -1
  80. package/dist/ui/operations/alerts.html +6 -6
  81. package/dist/ui/operations/configuration.html +6 -6
  82. package/dist/ui/operations/jobs.html +5 -5
  83. package/dist/ui/operations/maintenance.html +5 -5
  84. package/dist/ui/operations/observability.html +5 -5
  85. package/dist/ui/operations/previews.html +6 -6
  86. package/dist/ui/operations/queue.html +6 -6
  87. package/dist/ui/operations/regions.html +5 -5
  88. package/dist/ui/operations/releases.html +6 -6
  89. package/dist/ui/operations/spend.html +6 -6
  90. package/dist/ui/operations/workloads.html +6 -6
  91. package/dist/ui/security.html +2 -2
  92. package/dist/ui/server/actions.html +6 -6
  93. package/dist/ui/server/activity.html +1 -1
  94. package/dist/ui/server/capacity.html +5 -5
  95. package/dist/ui/server/database.html +6 -6
  96. package/dist/ui/server/deployments.html +5 -5
  97. package/dist/ui/server/diagnostics.html +1 -1
  98. package/dist/ui/server/firewall.html +6 -6
  99. package/dist/ui/server/fleet.html +6 -6
  100. package/dist/ui/server/logs.html +5 -5
  101. package/dist/ui/server/metrics.html +5 -5
  102. package/dist/ui/server/security.html +2 -2
  103. package/dist/ui/server/services.html +2 -2
  104. package/dist/ui/server/sites.html +6 -6
  105. package/dist/ui/server/ssh-keys.html +6 -6
  106. package/dist/ui/server/team.html +6 -6
  107. package/dist/ui/server/terminal.html +2 -2
  108. package/dist/ui/serverless/alarms.html +6 -6
  109. package/dist/ui/serverless/assets.html +2 -2
  110. package/dist/ui/serverless/cost.html +2 -2
  111. package/dist/ui/serverless/data.html +6 -6
  112. package/dist/ui/serverless/deployments.html +2 -2
  113. package/dist/ui/serverless/firewall.html +1 -1
  114. package/dist/ui/serverless/functions.html +6 -6
  115. package/dist/ui/serverless/logs.html +6 -6
  116. package/dist/ui/serverless/metrics.html +1 -1
  117. package/dist/ui/serverless/queues.html +6 -6
  118. package/dist/ui/serverless/secrets.html +6 -6
  119. package/dist/ui/serverless/traces.html +6 -6
  120. package/dist/ui/serverless.html +6 -6
  121. package/package.json +3 -3
  122. package/dist/bin/chunk-08hxbrmv.js +0 -1
  123. package/dist/bin/chunk-0cwbg3pf.js +0 -1
  124. package/dist/bin/chunk-19tmmwmt.js +0 -1
  125. package/dist/bin/chunk-2qrr4ydb.js +0 -1
  126. package/dist/bin/chunk-4jgespb7.js +0 -1
  127. package/dist/bin/chunk-8hnph1yy.js +0 -1
  128. package/dist/bin/chunk-aqreqn37.js +0 -1
  129. package/dist/bin/chunk-eh3235zq.js +0 -1
  130. package/dist/bin/chunk-ff888cnm.js +0 -1
  131. package/dist/bin/chunk-kxmq7r53.js +0 -1
  132. package/dist/bin/chunk-mh172wt8.js +0 -1
  133. package/dist/bin/chunk-swnef46q.js +0 -1
  134. package/dist/bin/chunk-v95b2dy0.js +0 -1
  135. package/dist/bin/chunk-wjwxtz68.js +0 -1
  136. package/dist/chunk-31qham3c.js +0 -1
  137. package/dist/chunk-7fbfmpyx.js +0 -1
  138. package/dist/chunk-dschvakr.js +0 -1
  139. package/dist/chunk-nkd35khb.js +0 -1
@@ -1,4 +1,4 @@
1
- import{Ws,et,A,H,C,F,De,Wt}from"./chunk-4a8qt6e8.js";import{se,on,te,sn,h,Ir,Hs}from"./chunk-817q3s2p.js";import{Oe,b,ts,pr,Qn,Yn,pt,Gr,Ua,_t,Kr,We,Le,Ge,Ba,gt,mr,Me,Ke,Zn,ei,Vi,zi,Je,Jr,hr,ft,m,Qi,fs,hs}from"./chunk-8k87zpnp.js";import{Ft,u}from"./chunk-q3xwh0r8.js";import{g}from"./chunk-2q27v6vz.js";import{me}from"./chunk-fjxsj9z9.js";import{Tr,Tt,Er,wr,Cr,Ar,nn}from"./chunk-cgyqnbcm.js";import{ze,ar,Li,O,qr,_a,xa,Dt,Kn,Jn}from"./chunk-5ky6qf18.js";import{v}from"./chunk-qsyna6ng.js";import{ie,W,qn}from"./chunk-h3shxxh4.js";import{w}from"./chunk-f4rp62j4.js";import{V}from"./chunk-8tp6srfc.js";import{R}from"./chunk-1j9vy88a.js";import{J,P,U,br,ho,vr,en}from"./chunk-e3tjy3wg.js";import{ao}from"./chunk-2857cbf1.js";import{K,ws,Cs,po,Mt,z,As}from"./chunk-0apv4e8e.js";import{Ds,ks}from"./chunk-0hbrkdrc.js";import{es}from"./chunk-7412q5cz.js";import{Wr}from"./chunk-xss6yj73.js";import{x,k,Vs}from"./chunk-eshss5qy.js";import{createHash as FT}from"node:crypto";import{existsSync as go,mkdtempSync as cp,readdirSync as cb,rmSync as ys,statSync as Sb}from"node:fs";import{readFile as Ui,writeFile as gs}from"node:fs/promises";import{tmpdir as kd}from"node:os";import{dirname as UT,extname as Ga,join as Et,normalize as zT,relative as VT,resolve as qT,sep as JT}from"node:path";import{fileURLToPath as GT}from"node:url";class Md extends Error{status;code;requestId;constructor(e,t,r,n){super(r);this.status=e;this.code=t;this.requestId=n}}class Di{options;baseUrl;fetchFn;constructor(e){this.options=e;this.baseUrl=e.baseUrl.replace(/\/$/,""),this.fetchFn=e.fetch??fetch}async request(e,t={}){let r=await this.fetchFn(`${this.baseUrl}${e}`,{...t,headers:{accept:"application/json",authorization:`Bearer ${this.options.token}`,...t.headers}}),n=await r.json().catch(()=>({}));if(!r.ok)throw new Md(r.status,n.error?.code??"api_error",n.error?.message??"API request failed.",n.error?.requestId??r.headers.get("x-request-id")??void 0);return n}listProjects(e={}){return this.request(`/api/v1/projects?${new URLSearchParams(Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0).map(([t,r])=>[t,String(r)])))}`)}listEnvironments(e,t={}){return this.request(`/api/v1/projects/${encodeURIComponent(e)}/environments?${new URLSearchParams(Object.fromEntries(Object.entries(t).filter(([,r])=>r!==void 0).map(([r,n])=>[r,String(n)])))}`)}listServices(e,t){return this.request(`/api/v1/services?${new URLSearchParams({projectId:e,...t?{environmentId:t}:{}})}`)}listOperations(e){return this.request(`/api/v1/operations${e?`?projectId=${encodeURIComponent(e)}`:""}`)}listComposeTemplates(){return this.request("/api/v1/compose-templates")}listComposeApplications(e,t){return this.request(`/api/v1/compose-applications?${new URLSearchParams({projectId:e,...t?{environmentId:t}:{}})}`)}previewCompose(e){return this.request("/api/v1/compose-applications/preview",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createComposeApplication(e){return this.request("/api/v1/compose-applications",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}composeServices(e){return this.request(`/api/v1/compose-applications/${encodeURIComponent(e)}/services`)}composeAction(e,t,r={}){return this.request(`/api/v1/compose-applications/${encodeURIComponent(e)}/${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r)})}releaseCapabilities(e,t={}){return this.request(`/api/v1/releases/capabilities?${new URLSearchParams({kind:e,health:String(!!t.health),replicas:String(t.replicas??1)})}`)}listReleases(e,t={}){return this.request(`/api/v1/releases?${new URLSearchParams({projectId:e,...t})}`)}createReleaseArtifact(e){return this.request("/api/v1/release-artifacts",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createRelease(e){return this.request("/api/v1/releases",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}releaseAction(e,t,r={}){return this.request(`/api/v1/releases/${encodeURIComponent(e)}/${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r)})}createDeployment(e,t){return this.request("/api/v1/deployments",{method:"POST",headers:{"content-type":"application/json","idempotency-key":t},body:JSON.stringify(e)})}detectApplication(e){return this.request("/api/v1/application-detections",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}planApplication(e){return this.request("/api/v1/application-plans",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}listApplicationDrafts(e){return this.request(`/api/v1/application-drafts?projectId=${encodeURIComponent(e)}`)}createApplicationDraft(e){return this.request("/api/v1/application-drafts",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}updateApplicationDraft(e){return this.request("/api/v1/application-drafts",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createApplication(e,t){return this.request("/api/v1/applications",{method:"POST",headers:{"content-type":"application/json","idempotency-key":t},body:JSON.stringify(e)})}uploadApplicationArtifact(e,t,r){return this.request("/api/v1/application-artifacts",{method:"POST",headers:{"content-type":"application/octet-stream","x-project-id":e,"x-artifact-filename":t},body:r})}listRegistryConnections(){return this.request("/api/v1/registry-connections")}createRegistryConnection(e){return this.request("/api/v1/registry-connections",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}updateRegistryConnection(e){return this.request("/api/v1/registry-connections",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}disconnectRegistryConnection(e){return this.request("/api/v1/registry-connections",{method:"DELETE",headers:{"content-type":"application/json"},body:JSON.stringify({id:e})})}listQueue(e={}){let t=new URLSearchParams(Object.entries(e).filter(([,r])=>r!==void 0).map(([r,n])=>[r,String(n)]));return this.request(`/api/v1/queue?${t}`)}operationLogs(e,t={}){let r=new URLSearchParams(Object.entries(t).filter(([,n])=>n!==void 0).map(([n,i])=>[n,String(i)]));return this.request(`/api/v1/operations/${encodeURIComponent(e)}/logs?${r}`)}streamOperationLogs(e,t=0){return this.fetchFn(`${this.baseUrl}/api/v1/operations/${encodeURIComponent(e)}/logs/stream`,{headers:{accept:"text/event-stream",authorization:`Bearer ${this.options.token}`,"last-event-id":String(t)}})}cancelOperation(e){return this.request(`/api/v1/operations/${encodeURIComponent(e)}/cancel`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"})}retryOperation(e,t,r=0){return this.request(`/api/v1/operations/${encodeURIComponent(e)}/retry`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({errorClass:t,delayMs:r})})}queueSettings(){return this.request("/api/v1/queue/settings")}updateQueueSettings(e){return this.request("/api/v1/queue/settings",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({confirm:"update queue limits",concurrency:e})})}listPreviews(e){return this.request(`/api/v1/previews${e?`?projectId=${encodeURIComponent(e)}`:""}`)}listPreviewDefinitions(e){return this.request(`/api/v1/preview-definitions?projectId=${encodeURIComponent(e)}`)}createPreviewDefinition(e){return this.request("/api/v1/preview-definitions",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createPreview(e){return this.request("/api/v1/previews",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}destroyPreview(e,t){return this.request(`/api/v1/previews/${encodeURIComponent(e)}/destroy`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({confirm:t})})}extendPreview(e,t){return this.request(`/api/v1/previews/${encodeURIComponent(e)}/extend`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({hours:t})})}rebuildPreview(e){return this.request(`/api/v1/previews/${encodeURIComponent(e)}/rebuild`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"})}usage(e={}){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(n)t.set(r,String(n));return this.request(`/api/v1/usage${t.size>0?`?${t}`:""}`)}usageRollups(e){let t=new URLSearchParams({from:e.from,to:e.to});if(e.projectId)t.set("projectId",e.projectId);if(e.environmentId)t.set("environmentId",e.environmentId);if(e.limit)t.set("limit",String(e.limit));for(let r of e.meters??[])t.append("meter",r);return this.request(`/api/v1/usage/rollups?${t}`)}allowance(e="deploy",t={}){let r=new URLSearchParams({operation:e});if(t.projectId)r.set("projectId",t.projectId);if(t.environmentId)r.set("environmentId",t.environmentId);return this.request(`/api/v1/spend/allowance?${r}`)}budgets(e={}){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(n)t.set(r,String(n));return this.request(`/api/v1/spend/budgets${t.size>0?`?${t}`:""}`)}anomalies(e={}){let t=new URLSearchParams;if(e.projectId)t.set("projectId",e.projectId);if(e.since)t.set("since",e.since);if(e.unacknowledged)t.set("unacknowledged","true");return this.request(`/api/v1/spend/anomalies${t.size>0?`?${t}`:""}`)}}import{createHash as TS}from"node:crypto";import{lstatSync as Nb,readdirSync as $b,readFileSync as Mb}from"node:fs";import{relative as Lb,resolve as xp,sep as Bb}from"node:path";function jb(e){return new Map(e.map((t)=>[t.path.replace(/^\.\//,"").replace(/\\/g,"/"),t]))}function Vo(e,t,r){return{path:e,reason:t,weight:r}}function Dp(e){try{return e?.content?JSON.parse(e.content):{}}catch{return{}}}function Ts(e,t,r,n,i,o){return{framework:e,strategy:t,confidence:r,evidence:n,defaults:{build:i,runtime:{target:t==="static"?"serverless":t==="serverless"?"serverless":t==="dockerfile"||t==="prebuilt_image"?"container":"server",architecture:"x86_64",port:t==="static"||t==="serverless"?void 0:3000,healthCheck:t==="static"?void 0:{protocol:"http",path:"/health"}}},description:o}}function Rt(e){let t=jb(e.slice(0,1e4)),r=[];if(t.has("Dockerfile"))r.push(Ts("dockerfile","dockerfile",0.99,[Vo("Dockerfile","A root Dockerfile defines an explicit reproducible build.",1)],{kind:"dockerfile",context:".",dockerfile:"Dockerfile"},"Build the repository with its Dockerfile and run the resulting OCI image."));let n=Dp(t.get("composer.json"));if(t.has("artisan")&&n.require?.["laravel/framework"])r.push(Ts("laravel","server",0.98,[Vo("artisan","Laravel Artisan entrypoint is present.",0.45),Vo("composer.json","Requires laravel/framework.",0.55)],{kind:"server",runtime:"php",runtimeVersion:"8.3",installCommand:"composer install --no-dev --prefer-dist --optimize-autoloader",buildCommand:"php artisan config:cache && php artisan route:cache && php artisan view:cache",startCommand:"php artisan serve --host=0.0.0.0 --port=$PORT"},"Install a production Composer tree, warm Laravel caches, and run the HTTP application."));else if(t.has("composer.json"))r.push(Ts("php","server",0.82,[Vo("composer.json","Composer metadata identifies a PHP application.",0.8)],{kind:"server",runtime:"php",runtimeVersion:"8.3",installCommand:"composer install --no-dev --prefer-dist --optimize-autoloader",startCommand:"php -S 0.0.0.0:$PORT -t public"},"Install Composer dependencies and run the configured PHP document root."));let i=Dp(t.get("package.json"));if(t.has("package.json")){let o=t.has("bun.lock")||t.has("bun.lockb")||i.engines?.bun,s=o?"bun":"node",c=o?"bun":"node",l=[Vo("package.json",`Defines ${i.scripts?.build?"build and ":""}${i.scripts?.start?"start ":""}scripts.`,0.55)];if(o)l.push(Vo(t.has("bun.lock")?"bun.lock":t.has("bun.lockb")?"bun.lockb":"package.json","Pins the Bun package manager/runtime.",0.35));let a=!!(i.dependencies?.vite||i.devDependencies?.vite||i.dependencies?.["@stacksjs/bunpress"]||i.devDependencies?.["@stacksjs/bunpress"])&&!i.scripts?.start,f=a?{kind:"static",installCommand:`${s} install --frozen-lockfile`,buildCommand:`${s} run build`,publishDirectory:"dist"}:{kind:"server",runtime:s,installCommand:`${s} install --frozen-lockfile`,buildCommand:i.scripts?.build?`${s} run build`:void 0,startCommand:i.scripts?.start?`${s} run start`:s==="bun"?"bun run index.ts":"node index.js"};r.push(Ts(c,f.kind,Math.min(0.94,l.reduce((E,D)=>E+D.weight,0)),l,f,a?"Install dependencies, build static assets, and publish the output directory.":`Install dependencies, build if configured, and start the ${s} server.`))}if(!r.length&&(t.has("index.html")||t.has("public/index.html")))r.push(Ts("static","static",0.78,[Vo(t.has("index.html")?"index.html":"public/index.html","A static HTML entrypoint is present.",0.78)],{kind:"static",publishDirectory:t.has("index.html")?".":"public"},"Publish the static directory without a runtime process."));if(!r.length)r.push(Ts("unknown","buildpack",0.2,[],{kind:"buildpack",runtime:"node"},"No supported framework signature was conclusive; choose commands and runtime manually."));return r.sort((o,s)=>s.confidence-o.confidence||o.framework.localeCompare(s.framework))}function xn(e,t={}){let r=xp(e),n=t.maxFiles??1e4,i=t.maxContentBytes??262144,o=[],s=new Set(["Dockerfile","package.json","composer.json","index.html","public/index.html","bun.lock","bun.lockb","artisan"]),c=new Set([".git",".ts-cloud",".cache",".next",".nuxt",".output",".turbo",".bun","node_modules","vendor","pantry","dist","build","coverage"]),l=(a)=>{for(let f of $b(a).sort()){if(c.has(f))continue;let E=xp(a,f),D=Lb(r,E).split(Bb).join("/");if(!D||D.startsWith("../"))throw Error("Detection path escaped the application root");let N=Nb(E);if(N.isSymbolicLink())throw Error(`Detection refuses symbolic links: ${D}`);if(N.isDirectory())l(E);else if(N.isFile()){if(o.length>=n)throw Error("Application file-count limit exceeded");let G={path:D,size:N.size};if(s.has(D)&&N.size<=i)G.content=Mb(E,"utf8");o.push(G)}}};return l(r),o}function Bd(e){if(Array.isArray(e))return`[${e.map(Bd).join(",")}]`;if(e&&typeof e==="object")return`{${Object.entries(e).filter(([,t])=>t!==void 0).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>`${JSON.stringify(t)}:${Bd(r)}`).join(",")}}`;return JSON.stringify(e)??"null"}function pa(e){return!!e&&!e.startsWith("/")&&!e.split("/").includes("..")&&!/[\0\r\n]/.test(e)}function Wn(e,t,r,n){return{path:e,code:t,message:r,alternatives:n}}function Ld(e){return JSON.parse(JSON.stringify(e))}function Fb(e){let t=Object.fromEntries(Object.entries(e.environment??{}).map(([r,n])=>[r,typeof n==="string"?n:`\${${n.secretRef}}`]));if(e.build.kind==="prebuilt_image"||e.build.kind==="dockerfile")return Ld({infrastructure:{containers:{[e.slug]:{source:e.source,build:e.build,port:e.runtime.port,cpu:e.runtime.cpu,memory:e.runtime.memoryMb,architecture:e.runtime.architecture,healthCheck:e.runtime.healthCheck,environment:t}}}});if(e.runtime.target==="serverless"||e.build.kind==="serverless")return Ld({serverless:{apps:{[e.slug]:{source:e.source,build:e.build,architecture:e.runtime.architecture,environment:t,domain:e.domain}}}});return Ld({sites:{[e.slug]:{source:e.source,build:e.build,port:e.runtime.port,architecture:e.runtime.architecture,healthCheck:e.runtime.healthCheck,env:t,domain:e.domain?.hostname}}})}function ce(e,t=[]){let r=[],n=(G)=>/(?:secret|token|password|passwd|private[_-]?key|api[_-]?key)/i.test(G),i=Object.fromEntries(Object.entries(e.environment??{}).map(([G,Y])=>{if(typeof Y==="string"&&n(G))return r.push(Wn(`environment.${G}`,"write_only_secret_required",`${G} must be supplied through the write-only secrets boundary.`)),[G,{secretRef:G}];return[G,Y]})),o=e.build;if(e.build.kind==="dockerfile"&&e.build.buildArgs){let G=Object.fromEntries(Object.entries(e.build.buildArgs).map(([Y,ee])=>{if(n(Y))return r.push(Wn(`build.buildArgs.${Y}`,"write_only_build_secret_required",`${Y} must be declared in secretNames instead of buildArgs.`)),[Y,"[REDACTED]"];return[Y,ee]}));o={...e.build,buildArgs:G}}if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.slug))r.push(Wn("slug","invalid_slug","Slug must contain 2-63 lowercase letters, numbers, or hyphens."));if(!pa((e.source.kind==="git"?e.source.monorepoRoot:e.source.kind==="local"?e.source.root:".")??"."))r.push(Wn("source","unsafe_source_root","Source root must stay inside the source tree."));if(e.source.kind==="git"&&e.source.sparsePaths?.some((G)=>!pa(G)))r.push(Wn("source.sparsePaths","unsafe_sparse_path","Sparse checkout paths must stay inside the repository."));if(e.build.kind==="dockerfile"&&(!pa(e.build.context)||!pa(e.build.dockerfile)))r.push(Wn("build","unsafe_docker_path","Docker context and Dockerfile must stay inside the source tree."));if(e.build.kind==="static"&&!pa(e.build.publishDirectory))r.push(Wn("build.publishDirectory","invalid_publish_directory","A safe static publish directory is required."));if(e.build.kind==="server"&&!e.build.startCommand.trim())r.push(Wn("build.startCommand","missing_start_command","A server start command is required.",["Use static output","Use a Dockerfile"]));if(e.source.kind==="image"&&e.build.kind!=="prebuilt_image")r.push(Wn("build.kind","image_requires_prebuilt","An OCI image source must use the prebuilt-image strategy.",["Select prebuilt image"]));if(e.build.kind==="prebuilt_image"&&e.runtime.target!=="container")r.push(Wn("runtime.target","image_requires_container","Prebuilt images require the container runtime target.",["Select container target"]));if(e.runtime.target==="serverless"&&e.build.kind==="dockerfile")r.push(Wn("runtime.target","unsupported_serverless_dockerfile","Dockerfile builds currently target the container service path.",["Select container target","Select serverless package"]));if(e.runtime.port!==void 0&&(!Number.isInteger(e.runtime.port)||e.runtime.port<1||e.runtime.port>65535))r.push(Wn("runtime.port","invalid_port","Port must be an integer from 1 to 65535."));let s=e.runtime.healthCheck;if(s&&s.protocol!=="tcp"&&(!s.path||!s.path.startsWith("/")||/[\r\n]/.test(s.path)))r.push(Wn("runtime.healthCheck.path","invalid_health_path","HTTP health checks require a path beginning with /."));if(e.domain?.hostname&&(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i.test(e.domain.hostname)||e.domain.hostname.includes("..")))r.push(Wn("domain.hostname","invalid_domain","Domain must be a valid DNS hostname."));let c=Object.values(i).flatMap((G)=>typeof G==="object"?[G.secretRef]:[]),l=[...new Set([...e.requiredSecretNames??[],...e.build.kind==="dockerfile"?e.build.secretNames??[]:[],...c])].sort(),a=new Set(t),f=l.filter((G)=>!a.has(G)),E={apiVersion:"ts-cloud.dev/v1",kind:"Application",metadata:{name:e.name,slug:e.slug,projectId:e.projectId,environmentId:e.environmentId},spec:{source:e.source,build:o,runtime:e.runtime,environment:i,domain:e.domain}},D=[...new Set([e.source.kind==="git"?"git:read":e.source.kind==="image"?"registry:pull":e.source.kind==="artifact"?"artifact:inspect":"filesystem:read",e.runtime.target==="container"?"containers":e.runtime.target==="serverless"?"serverless":"servers",e.domain?"dns":""])].filter(Boolean).sort(),N=[...new Set([e.runtime.target,e.runtime.cpu?`${e.runtime.cpu} vCPU`:"",e.runtime.memoryMb?`${e.runtime.memoryMb} MB memory`:"",(e.runtime.minInstances??0)>0?`${e.runtime.minInstances} minimum instances`:"scales from zero where supported",e.domain?"managed DNS/TLS":""])].filter(Boolean);return{valid:r.length===0&&f.length===0,issues:r,missingSecrets:f,manifest:E,configPatch:Fb({...e,build:o,environment:i}),capabilityRequirements:D,costDrivers:N,serializedManifest:`${Bd(E)}
1
+ import{Ws,et,A,H,C,F,De,Wt}from"./chunk-4a8qt6e8.js";import{se,on,te,sn,h,Ir,Hs}from"./chunk-817q3s2p.js";import{Oe,b,ts,pr,Qn,Yn,pt,Gr,Ua,_t,Kr,We,Le,Ge,Ba,gt,mr,Me,Ke,Zn,ei,Vi,zi,Je,Jr,hr,ft,m,Qi,fs,hs}from"./chunk-8k87zpnp.js";import{Ft,u}from"./chunk-y5e7dmvc.js";import{g}from"./chunk-ypsgkj91.js";import{me}from"./chunk-kbwczaa8.js";import{Tr,Tt,Er,wr,Cr,Ar,nn}from"./chunk-cgyqnbcm.js";import{ze,ar,Li,O,qr,_a,xa,Dt,Kn,Jn}from"./chunk-ffyhp5tk.js";import{v}from"./chunk-5810132y.js";import{ie,W,qn}from"./chunk-x6y663t7.js";import{w}from"./chunk-494fg5c6.js";import{V}from"./chunk-45v1azhc.js";import{R}from"./chunk-qx05kccj.js";import{J,P,U,br,ho,vr,en}from"./chunk-e3tjy3wg.js";import{ao}from"./chunk-2857cbf1.js";import{K,ws,Cs,po,Mt,z,As}from"./chunk-kfj4w903.js";import{Ds,ks}from"./chunk-0hbrkdrc.js";import{es}from"./chunk-7412q5cz.js";import{Wr}from"./chunk-xss6yj73.js";import{x,k,Vs}from"./chunk-eshss5qy.js";import{createHash as FT}from"node:crypto";import{existsSync as go,mkdtempSync as cp,readdirSync as cb,rmSync as ys,statSync as Sb}from"node:fs";import{readFile as Ui,writeFile as gs}from"node:fs/promises";import{tmpdir as kd}from"node:os";import{dirname as UT,extname as Ga,join as Et,normalize as zT,relative as VT,resolve as qT,sep as JT}from"node:path";import{fileURLToPath as GT}from"node:url";class Md extends Error{status;code;requestId;constructor(e,t,r,n){super(r);this.status=e;this.code=t;this.requestId=n}}class Di{options;baseUrl;fetchFn;constructor(e){this.options=e;this.baseUrl=e.baseUrl.replace(/\/$/,""),this.fetchFn=e.fetch??fetch}async request(e,t={}){let r=await this.fetchFn(`${this.baseUrl}${e}`,{...t,headers:{accept:"application/json",authorization:`Bearer ${this.options.token}`,...t.headers}}),n=await r.json().catch(()=>({}));if(!r.ok)throw new Md(r.status,n.error?.code??"api_error",n.error?.message??"API request failed.",n.error?.requestId??r.headers.get("x-request-id")??void 0);return n}listProjects(e={}){return this.request(`/api/v1/projects?${new URLSearchParams(Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0).map(([t,r])=>[t,String(r)])))}`)}listEnvironments(e,t={}){return this.request(`/api/v1/projects/${encodeURIComponent(e)}/environments?${new URLSearchParams(Object.fromEntries(Object.entries(t).filter(([,r])=>r!==void 0).map(([r,n])=>[r,String(n)])))}`)}listServices(e,t){return this.request(`/api/v1/services?${new URLSearchParams({projectId:e,...t?{environmentId:t}:{}})}`)}listOperations(e){return this.request(`/api/v1/operations${e?`?projectId=${encodeURIComponent(e)}`:""}`)}listComposeTemplates(){return this.request("/api/v1/compose-templates")}listComposeApplications(e,t){return this.request(`/api/v1/compose-applications?${new URLSearchParams({projectId:e,...t?{environmentId:t}:{}})}`)}previewCompose(e){return this.request("/api/v1/compose-applications/preview",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createComposeApplication(e){return this.request("/api/v1/compose-applications",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}composeServices(e){return this.request(`/api/v1/compose-applications/${encodeURIComponent(e)}/services`)}composeAction(e,t,r={}){return this.request(`/api/v1/compose-applications/${encodeURIComponent(e)}/${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r)})}releaseCapabilities(e,t={}){return this.request(`/api/v1/releases/capabilities?${new URLSearchParams({kind:e,health:String(!!t.health),replicas:String(t.replicas??1)})}`)}listReleases(e,t={}){return this.request(`/api/v1/releases?${new URLSearchParams({projectId:e,...t})}`)}createReleaseArtifact(e){return this.request("/api/v1/release-artifacts",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createRelease(e){return this.request("/api/v1/releases",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}releaseAction(e,t,r={}){return this.request(`/api/v1/releases/${encodeURIComponent(e)}/${t}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r)})}createDeployment(e,t){return this.request("/api/v1/deployments",{method:"POST",headers:{"content-type":"application/json","idempotency-key":t},body:JSON.stringify(e)})}detectApplication(e){return this.request("/api/v1/application-detections",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}planApplication(e){return this.request("/api/v1/application-plans",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}listApplicationDrafts(e){return this.request(`/api/v1/application-drafts?projectId=${encodeURIComponent(e)}`)}createApplicationDraft(e){return this.request("/api/v1/application-drafts",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}updateApplicationDraft(e){return this.request("/api/v1/application-drafts",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createApplication(e,t){return this.request("/api/v1/applications",{method:"POST",headers:{"content-type":"application/json","idempotency-key":t},body:JSON.stringify(e)})}uploadApplicationArtifact(e,t,r){return this.request("/api/v1/application-artifacts",{method:"POST",headers:{"content-type":"application/octet-stream","x-project-id":e,"x-artifact-filename":t},body:r})}listRegistryConnections(){return this.request("/api/v1/registry-connections")}createRegistryConnection(e){return this.request("/api/v1/registry-connections",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}updateRegistryConnection(e){return this.request("/api/v1/registry-connections",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}disconnectRegistryConnection(e){return this.request("/api/v1/registry-connections",{method:"DELETE",headers:{"content-type":"application/json"},body:JSON.stringify({id:e})})}listQueue(e={}){let t=new URLSearchParams(Object.entries(e).filter(([,r])=>r!==void 0).map(([r,n])=>[r,String(n)]));return this.request(`/api/v1/queue?${t}`)}operationLogs(e,t={}){let r=new URLSearchParams(Object.entries(t).filter(([,n])=>n!==void 0).map(([n,i])=>[n,String(i)]));return this.request(`/api/v1/operations/${encodeURIComponent(e)}/logs?${r}`)}streamOperationLogs(e,t=0){return this.fetchFn(`${this.baseUrl}/api/v1/operations/${encodeURIComponent(e)}/logs/stream`,{headers:{accept:"text/event-stream",authorization:`Bearer ${this.options.token}`,"last-event-id":String(t)}})}cancelOperation(e){return this.request(`/api/v1/operations/${encodeURIComponent(e)}/cancel`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"})}retryOperation(e,t,r=0){return this.request(`/api/v1/operations/${encodeURIComponent(e)}/retry`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({errorClass:t,delayMs:r})})}queueSettings(){return this.request("/api/v1/queue/settings")}updateQueueSettings(e){return this.request("/api/v1/queue/settings",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({confirm:"update queue limits",concurrency:e})})}listPreviews(e){return this.request(`/api/v1/previews${e?`?projectId=${encodeURIComponent(e)}`:""}`)}listPreviewDefinitions(e){return this.request(`/api/v1/preview-definitions?projectId=${encodeURIComponent(e)}`)}createPreviewDefinition(e){return this.request("/api/v1/preview-definitions",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}createPreview(e){return this.request("/api/v1/previews",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})}destroyPreview(e,t){return this.request(`/api/v1/previews/${encodeURIComponent(e)}/destroy`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({confirm:t})})}extendPreview(e,t){return this.request(`/api/v1/previews/${encodeURIComponent(e)}/extend`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({hours:t})})}rebuildPreview(e){return this.request(`/api/v1/previews/${encodeURIComponent(e)}/rebuild`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"})}usage(e={}){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(n)t.set(r,String(n));return this.request(`/api/v1/usage${t.size>0?`?${t}`:""}`)}usageRollups(e){let t=new URLSearchParams({from:e.from,to:e.to});if(e.projectId)t.set("projectId",e.projectId);if(e.environmentId)t.set("environmentId",e.environmentId);if(e.limit)t.set("limit",String(e.limit));for(let r of e.meters??[])t.append("meter",r);return this.request(`/api/v1/usage/rollups?${t}`)}allowance(e="deploy",t={}){let r=new URLSearchParams({operation:e});if(t.projectId)r.set("projectId",t.projectId);if(t.environmentId)r.set("environmentId",t.environmentId);return this.request(`/api/v1/spend/allowance?${r}`)}budgets(e={}){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(n)t.set(r,String(n));return this.request(`/api/v1/spend/budgets${t.size>0?`?${t}`:""}`)}anomalies(e={}){let t=new URLSearchParams;if(e.projectId)t.set("projectId",e.projectId);if(e.since)t.set("since",e.since);if(e.unacknowledged)t.set("unacknowledged","true");return this.request(`/api/v1/spend/anomalies${t.size>0?`?${t}`:""}`)}}import{createHash as TS}from"node:crypto";import{lstatSync as Nb,readdirSync as $b,readFileSync as Mb}from"node:fs";import{relative as Lb,resolve as xp,sep as Bb}from"node:path";function jb(e){return new Map(e.map((t)=>[t.path.replace(/^\.\//,"").replace(/\\/g,"/"),t]))}function Vo(e,t,r){return{path:e,reason:t,weight:r}}function Dp(e){try{return e?.content?JSON.parse(e.content):{}}catch{return{}}}function Ts(e,t,r,n,i,o){return{framework:e,strategy:t,confidence:r,evidence:n,defaults:{build:i,runtime:{target:t==="static"?"serverless":t==="serverless"?"serverless":t==="dockerfile"||t==="prebuilt_image"?"container":"server",architecture:"x86_64",port:t==="static"||t==="serverless"?void 0:3000,healthCheck:t==="static"?void 0:{protocol:"http",path:"/health"}}},description:o}}function Rt(e){let t=jb(e.slice(0,1e4)),r=[];if(t.has("Dockerfile"))r.push(Ts("dockerfile","dockerfile",0.99,[Vo("Dockerfile","A root Dockerfile defines an explicit reproducible build.",1)],{kind:"dockerfile",context:".",dockerfile:"Dockerfile"},"Build the repository with its Dockerfile and run the resulting OCI image."));let n=Dp(t.get("composer.json"));if(t.has("artisan")&&n.require?.["laravel/framework"])r.push(Ts("laravel","server",0.98,[Vo("artisan","Laravel Artisan entrypoint is present.",0.45),Vo("composer.json","Requires laravel/framework.",0.55)],{kind:"server",runtime:"php",runtimeVersion:"8.3",installCommand:"composer install --no-dev --prefer-dist --optimize-autoloader",buildCommand:"php artisan config:cache && php artisan route:cache && php artisan view:cache",startCommand:"php artisan serve --host=0.0.0.0 --port=$PORT"},"Install a production Composer tree, warm Laravel caches, and run the HTTP application."));else if(t.has("composer.json"))r.push(Ts("php","server",0.82,[Vo("composer.json","Composer metadata identifies a PHP application.",0.8)],{kind:"server",runtime:"php",runtimeVersion:"8.3",installCommand:"composer install --no-dev --prefer-dist --optimize-autoloader",startCommand:"php -S 0.0.0.0:$PORT -t public"},"Install Composer dependencies and run the configured PHP document root."));let i=Dp(t.get("package.json"));if(t.has("package.json")){let o=t.has("bun.lock")||t.has("bun.lockb")||i.engines?.bun,s=o?"bun":"node",c=o?"bun":"node",l=[Vo("package.json",`Defines ${i.scripts?.build?"build and ":""}${i.scripts?.start?"start ":""}scripts.`,0.55)];if(o)l.push(Vo(t.has("bun.lock")?"bun.lock":t.has("bun.lockb")?"bun.lockb":"package.json","Pins the Bun package manager/runtime.",0.35));let a=!!(i.dependencies?.vite||i.devDependencies?.vite||i.dependencies?.["@stacksjs/bunpress"]||i.devDependencies?.["@stacksjs/bunpress"])&&!i.scripts?.start,f=a?{kind:"static",installCommand:`${s} install --frozen-lockfile`,buildCommand:`${s} run build`,publishDirectory:"dist"}:{kind:"server",runtime:s,installCommand:`${s} install --frozen-lockfile`,buildCommand:i.scripts?.build?`${s} run build`:void 0,startCommand:i.scripts?.start?`${s} run start`:s==="bun"?"bun run index.ts":"node index.js"};r.push(Ts(c,f.kind,Math.min(0.94,l.reduce((E,D)=>E+D.weight,0)),l,f,a?"Install dependencies, build static assets, and publish the output directory.":`Install dependencies, build if configured, and start the ${s} server.`))}if(!r.length&&(t.has("index.html")||t.has("public/index.html")))r.push(Ts("static","static",0.78,[Vo(t.has("index.html")?"index.html":"public/index.html","A static HTML entrypoint is present.",0.78)],{kind:"static",publishDirectory:t.has("index.html")?".":"public"},"Publish the static directory without a runtime process."));if(!r.length)r.push(Ts("unknown","buildpack",0.2,[],{kind:"buildpack",runtime:"node"},"No supported framework signature was conclusive; choose commands and runtime manually."));return r.sort((o,s)=>s.confidence-o.confidence||o.framework.localeCompare(s.framework))}function xn(e,t={}){let r=xp(e),n=t.maxFiles??1e4,i=t.maxContentBytes??262144,o=[],s=new Set(["Dockerfile","package.json","composer.json","index.html","public/index.html","bun.lock","bun.lockb","artisan"]),c=new Set([".git",".ts-cloud",".cache",".next",".nuxt",".output",".turbo",".bun","node_modules","vendor","pantry","dist","build","coverage"]),l=(a)=>{for(let f of $b(a).sort()){if(c.has(f))continue;let E=xp(a,f),D=Lb(r,E).split(Bb).join("/");if(!D||D.startsWith("../"))throw Error("Detection path escaped the application root");let N=Nb(E);if(N.isSymbolicLink())throw Error(`Detection refuses symbolic links: ${D}`);if(N.isDirectory())l(E);else if(N.isFile()){if(o.length>=n)throw Error("Application file-count limit exceeded");let G={path:D,size:N.size};if(s.has(D)&&N.size<=i)G.content=Mb(E,"utf8");o.push(G)}}};return l(r),o}function Bd(e){if(Array.isArray(e))return`[${e.map(Bd).join(",")}]`;if(e&&typeof e==="object")return`{${Object.entries(e).filter(([,t])=>t!==void 0).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>`${JSON.stringify(t)}:${Bd(r)}`).join(",")}}`;return JSON.stringify(e)??"null"}function pa(e){return!!e&&!e.startsWith("/")&&!e.split("/").includes("..")&&!/[\0\r\n]/.test(e)}function Wn(e,t,r,n){return{path:e,code:t,message:r,alternatives:n}}function Ld(e){return JSON.parse(JSON.stringify(e))}function Fb(e){let t=Object.fromEntries(Object.entries(e.environment??{}).map(([r,n])=>[r,typeof n==="string"?n:`\${${n.secretRef}}`]));if(e.build.kind==="prebuilt_image"||e.build.kind==="dockerfile")return Ld({infrastructure:{containers:{[e.slug]:{source:e.source,build:e.build,port:e.runtime.port,cpu:e.runtime.cpu,memory:e.runtime.memoryMb,architecture:e.runtime.architecture,healthCheck:e.runtime.healthCheck,environment:t}}}});if(e.runtime.target==="serverless"||e.build.kind==="serverless")return Ld({serverless:{apps:{[e.slug]:{source:e.source,build:e.build,architecture:e.runtime.architecture,environment:t,domain:e.domain}}}});return Ld({sites:{[e.slug]:{source:e.source,build:e.build,port:e.runtime.port,architecture:e.runtime.architecture,healthCheck:e.runtime.healthCheck,env:t,domain:e.domain?.hostname}}})}function ce(e,t=[]){let r=[],n=(G)=>/(?:secret|token|password|passwd|private[_-]?key|api[_-]?key)/i.test(G),i=Object.fromEntries(Object.entries(e.environment??{}).map(([G,Y])=>{if(typeof Y==="string"&&n(G))return r.push(Wn(`environment.${G}`,"write_only_secret_required",`${G} must be supplied through the write-only secrets boundary.`)),[G,{secretRef:G}];return[G,Y]})),o=e.build;if(e.build.kind==="dockerfile"&&e.build.buildArgs){let G=Object.fromEntries(Object.entries(e.build.buildArgs).map(([Y,ee])=>{if(n(Y))return r.push(Wn(`build.buildArgs.${Y}`,"write_only_build_secret_required",`${Y} must be declared in secretNames instead of buildArgs.`)),[Y,"[REDACTED]"];return[Y,ee]}));o={...e.build,buildArgs:G}}if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.slug))r.push(Wn("slug","invalid_slug","Slug must contain 2-63 lowercase letters, numbers, or hyphens."));if(!pa((e.source.kind==="git"?e.source.monorepoRoot:e.source.kind==="local"?e.source.root:".")??"."))r.push(Wn("source","unsafe_source_root","Source root must stay inside the source tree."));if(e.source.kind==="git"&&e.source.sparsePaths?.some((G)=>!pa(G)))r.push(Wn("source.sparsePaths","unsafe_sparse_path","Sparse checkout paths must stay inside the repository."));if(e.build.kind==="dockerfile"&&(!pa(e.build.context)||!pa(e.build.dockerfile)))r.push(Wn("build","unsafe_docker_path","Docker context and Dockerfile must stay inside the source tree."));if(e.build.kind==="static"&&!pa(e.build.publishDirectory))r.push(Wn("build.publishDirectory","invalid_publish_directory","A safe static publish directory is required."));if(e.build.kind==="server"&&!e.build.startCommand.trim())r.push(Wn("build.startCommand","missing_start_command","A server start command is required.",["Use static output","Use a Dockerfile"]));if(e.source.kind==="image"&&e.build.kind!=="prebuilt_image")r.push(Wn("build.kind","image_requires_prebuilt","An OCI image source must use the prebuilt-image strategy.",["Select prebuilt image"]));if(e.build.kind==="prebuilt_image"&&e.runtime.target!=="container")r.push(Wn("runtime.target","image_requires_container","Prebuilt images require the container runtime target.",["Select container target"]));if(e.runtime.target==="serverless"&&e.build.kind==="dockerfile")r.push(Wn("runtime.target","unsupported_serverless_dockerfile","Dockerfile builds currently target the container service path.",["Select container target","Select serverless package"]));if(e.runtime.port!==void 0&&(!Number.isInteger(e.runtime.port)||e.runtime.port<1||e.runtime.port>65535))r.push(Wn("runtime.port","invalid_port","Port must be an integer from 1 to 65535."));let s=e.runtime.healthCheck;if(s&&s.protocol!=="tcp"&&(!s.path||!s.path.startsWith("/")||/[\r\n]/.test(s.path)))r.push(Wn("runtime.healthCheck.path","invalid_health_path","HTTP health checks require a path beginning with /."));if(e.domain?.hostname&&(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i.test(e.domain.hostname)||e.domain.hostname.includes("..")))r.push(Wn("domain.hostname","invalid_domain","Domain must be a valid DNS hostname."));let c=Object.values(i).flatMap((G)=>typeof G==="object"?[G.secretRef]:[]),l=[...new Set([...e.requiredSecretNames??[],...e.build.kind==="dockerfile"?e.build.secretNames??[]:[],...c])].sort(),a=new Set(t),f=l.filter((G)=>!a.has(G)),E={apiVersion:"ts-cloud.dev/v1",kind:"Application",metadata:{name:e.name,slug:e.slug,projectId:e.projectId,environmentId:e.environmentId},spec:{source:e.source,build:o,runtime:e.runtime,environment:i,domain:e.domain}},D=[...new Set([e.source.kind==="git"?"git:read":e.source.kind==="image"?"registry:pull":e.source.kind==="artifact"?"artifact:inspect":"filesystem:read",e.runtime.target==="container"?"containers":e.runtime.target==="serverless"?"serverless":"servers",e.domain?"dns":""])].filter(Boolean).sort(),N=[...new Set([e.runtime.target,e.runtime.cpu?`${e.runtime.cpu} vCPU`:"",e.runtime.memoryMb?`${e.runtime.memoryMb} MB memory`:"",(e.runtime.minInstances??0)>0?`${e.runtime.minInstances} minimum instances`:"scales from zero where supported",e.domain?"managed DNS/TLS":""])].filter(Boolean);return{valid:r.length===0&&f.length===0,issues:r,missingSecrets:f,manifest:E,configPatch:Fb({...e,build:o,environment:i}),capabilityRequirements:D,costDrivers:N,serializedManifest:`${Bd(E)}
2
2
  `}}function Op(e){let t=e.replace(/\\/g,"/");return!!t&&!t.startsWith("/")&&!/^[A-Za-z]:\//.test(t)&&!t.split("/").includes("..")&&!/[\0\r\n]/.test(t)}function _p(e,t,r={}){let n=r.maxBytes??104857600,i=r.maxEntries??1e4,o=r.maxExpandedBytes??524288000;if(e.byteLength>n)throw Error("Archive exceeds the compressed size limit");let s=new DataView(e.buffer,e.byteOffset,e.byteLength),c=[],l=0;if(t.toLowerCase().endsWith(".zip")||e[0]===80&&e[1]===75){let f=0;while(f+30<=e.length){let E=s.getUint32(f,!0);if(E===33639248||E===101010256)break;if(E!==67324752)throw Error("Malformed ZIP local header");let D=s.getUint16(f+6,!0),N=s.getUint32(f+18,!0),G=s.getUint32(f+22,!0),Y=s.getUint16(f+26,!0),ee=s.getUint16(f+28,!0);if(D&8)throw Error("ZIP data descriptors are not accepted for uploaded artifacts");let oe=new TextDecoder().decode(e.subarray(f+30,f+30+Y));if(!Op(oe))throw Error(`Unsafe archive path: ${oe}`);if(c.push(oe),l+=G,c.length>i||l>o)throw Error("Archive expansion limit exceeded");f+=30+Y+ee+N}return{format:"zip",entries:c.length,expandedBytes:l,paths:c}}if(!t.toLowerCase().match(/\.(?:tar|tar\.gz|tgz)$/))throw Error("Only ZIP and uncompressed TAR artifacts are supported");let a=0;while(a+512<=e.length){let f=e.subarray(a,a+512);if(f.every((Y)=>Y===0))break;let E=(Y,ee)=>new TextDecoder().decode(f.subarray(Y,Y+ee)).replace(/\0.*$/,""),D=`${E(345,155)}${E(345,155)?"/":""}${E(0,100)}`,N=Number.parseInt(E(124,12).trim()||"0",8),G=String.fromCharCode(f[156]??0);if(!Op(D))throw Error(`Unsafe archive path: ${D}`);if(G==="1"||G==="2")throw Error(`Archive links are not accepted: ${D}`);if(!Number.isFinite(N)||N<0)throw Error("Malformed TAR entry size");if(c.push(D),l+=N,c.length>i||l>o)throw Error("Archive expansion limit exceeded");a+=512+Math.ceil(N/512)*512}return{format:"tar",entries:c.length,expandedBytes:l,paths:c}}var Np=new Set(["source","build","runtime","environment","domain","review"]);function $p(e,t){try{return typeof e==="string"?JSON.parse(e):t}catch{return t}}function Mp(e){return/(?:secret|token|password|passwd|private[_-]?key|api[_-]?key)/i.test(e)}function Lp(e){for(let[r,n]of Object.entries(e.environment??{}))if(typeof n==="string"&&Mp(r)&&n)throw Error(`${r} must be stored through the write-only secrets boundary`);if(e.build.kind==="dockerfile"){for(let[r,n]of Object.entries(e.build.buildArgs??{}))if(Mp(r)&&n)throw Error(`${r} must be declared as a build secret name`)}let t=JSON.stringify(e);if(/https?:\/\/[^/@\s]+:[^/@\s]+@/i.test(t))throw Error("Drafts cannot contain credential-bearing URLs")}function Bp(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),schemaVersion:Number(e.schema_version),name:String(e.name),step:String(e.step),input:$p(e.input,{}),suppliedSecretNames:$p(e.supplied_secret_names,[]),status:String(e.status),version:Number(e.version),createdByActorId:e.created_by_actor_id?String(e.created_by_actor_id):void 0,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}class $n{controlPlane;nowFn;idFn;constructor(e,t={}){this.controlPlane=e;this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID())}now(){return this.nowFn().toISOString()}create(e){if(Lp(e.draft),e.draft.projectId!==e.projectId)throw Error("Draft project does not match its storage scope");let t=this.controlPlane.getProject(e.projectId);if(!t||t.organizationId!==e.organizationId)throw Error("Draft project was not found");let r=this.idFn(),n=this.now(),i=e.step??"source";if(!Np.has(i))throw Error("Invalid draft step");let o=[...new Set(e.suppliedSecretNames??[])].sort(),s=ce(e.draft,o).valid?"ready":"draft";return this.controlPlane.database.run("INSERT INTO application_drafts (id, organization_id, project_id, schema_version, name, step, input, supplied_secret_names, status, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?)",[r,e.organizationId,e.projectId,e.name.trim().slice(0,100),i,JSON.stringify(e.draft),JSON.stringify(o),s,e.actorId??null,n,n]),this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,actorId:e.actorId,type:"application.draft.created",payload:{draftId:r,step:i,status:s,requiredSecretNames:e.draft.requiredSecretNames??[]}}),this.get(r)}get(e){let t=this.controlPlane.database.query("SELECT * FROM application_drafts WHERE id=?").get(e);return t?Bp(t):void 0}list(e){return this.controlPlane.database.query("SELECT * FROM application_drafts WHERE project_id=? ORDER BY updated_at DESC").all(e).map(Bp)}update(e,t,r){let n=this.get(e);if(!n||n.version!==t)throw Error(`Application draft ${e} changed since version ${t}`);if(!Np.has(r.step))throw Error("Invalid draft step");if(r.draft.projectId!==n.projectId)throw Error("Draft project cannot be changed");Lp(r.draft);let i=[...new Set(r.suppliedSecretNames??n.suppliedSecretNames)].sort(),o=ce(r.draft,i).valid?"ready":"draft",s=this.now();if(this.controlPlane.database.run("UPDATE application_drafts SET name=?, step=?, input=?, supplied_secret_names=?, status=?, version=version+1, updated_at=? WHERE id=? AND version=?",[r.draft.name.slice(0,100),r.step,JSON.stringify(r.draft),JSON.stringify(i),o,s,e,t]).changes!==1)throw Error(`Application draft ${e} changed since version ${t}`);return this.controlPlane.appendEvent({organizationId:n.organizationId,projectId:n.projectId,actorId:r.actorId,type:"application.draft.updated",payload:{draftId:e,fromVersion:t,toVersion:t+1,step:r.step,status:o}}),this.get(e)}markApplied(e,t,r){let n=this.get(e);if(!n||n.version!==t)throw Error(`Application draft ${e} changed since version ${t}`);let i=ce(n.input,n.suppliedSecretNames);if(!i.valid)throw Error(`Draft is not deployable: ${[...i.issues.map((s)=>s.message),...i.missingSecrets.map((s)=>`Missing secret ${s}`)].join("; ")}`);let o=this.now();return this.controlPlane.database.run("UPDATE application_drafts SET status='applied', step='review', version=version+1, updated_at=? WHERE id=? AND version=?",[o,e,t]),this.controlPlane.appendEvent({organizationId:n.organizationId,projectId:n.projectId,actorId:r,type:"application.draft.applied",payload:h({draftId:e,manifest:i.manifest})}),this.get(e)}}import{createCipheriv as Ub,createDecipheriv as zb,createHash as Up,randomBytes as Vb}from"node:crypto";function ga(e){return typeof e==="string"&&e?e:void 0}function jd(e){return Up("sha256").update(e).digest("hex").slice(0,16)}function jp(e){let t=new URL(e.includes("://")?e:`https://${e}`);if(t.protocol!=="https:"&&!["localhost","127.0.0.1","::1"].includes(t.hostname))throw Error("Registry host must use HTTPS");if(t.username||t.password||t.search||t.hash)throw Error("Registry host cannot contain credentials");return`${t.protocol}//${t.host}`}function qb(e){return{id:String(e.id),organizationId:String(e.organization_id),provider:String(e.provider),name:String(e.name),host:String(e.host),credentialConfigured:!!e.credential_ciphertext,credentialFingerprint:ga(e.credential_fingerprint),credentialExpiresAt:ga(e.credential_expires_at),status:String(e.status),healthMessage:ga(e.health_message),lastTestedAt:ga(e.last_tested_at),version:Number(e.version),createdByActorId:ga(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}class On{controlPlane;key;nowFn;idFn;constructor(e,t){this.controlPlane=e;if(!t.encryptionKey)throw Error("Registry encryption key is required");this.key=Up("sha256").update(`ts-cloud:registry:${t.encryptionKey}`).digest(),this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID())}now(){return this.nowFn().toISOString()}encrypt(e){let t=Vb(12),r=Ub("aes-256-gcm",this.key,t),n=Buffer.concat([r.update(e,"utf8"),r.final()]);return`v1.${t.toString("base64url")}.${r.getAuthTag().toString("base64url")}.${n.toString("base64url")}`}decrypt(e){let[t,r,n,i]=e.split(".");if(t!=="v1"||!r||!n||!i)throw Error("Registry credential envelope is invalid");let o=zb("aes-256-gcm",this.key,Buffer.from(r,"base64url"));return o.setAuthTag(Buffer.from(n,"base64url")),Buffer.concat([o.update(Buffer.from(i,"base64url")),o.final()]).toString("utf8")}current(e){let t=qb(e);return t.status!=="disconnected"&&t.credentialExpiresAt&&new Date(t.credentialExpiresAt).getTime()<=this.nowFn().getTime()?{...t,status:"expired",healthMessage:"Registry credential expired; rotate it before pulling images."}:t}create(e){if(!["docker_hub","ghcr","ecr","gcr","generic"].includes(e.provider))throw Error("A supported registry provider is required");let t=e.credential?JSON.stringify(e.credential):void 0,r=this.idFn(),n=this.now();return this.controlPlane.database.run("INSERT INTO registry_connections (id, organization_id, provider, name, host, credential_ciphertext, credential_fingerprint, credential_expires_at, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[r,e.organizationId,e.provider,e.name.trim().slice(0,80),jp(e.host),t?this.encrypt(t):null,t?jd(t):null,e.credentialExpiresAt??null,e.actorId??null,n,n]),this.controlPlane.appendEvent({organizationId:e.organizationId,actorId:e.actorId,type:"registry.connection.created",payload:{connectionId:r,provider:e.provider,host:jp(e.host),credentialConfigured:!!t}}),this.get(r)}get(e){let t=this.controlPlane.database.query("SELECT * FROM registry_connections WHERE id=?").get(e);return t?this.current(t):void 0}list(e){return this.controlPlane.database.query("SELECT * FROM registry_connections WHERE organization_id=? ORDER BY name").all(e).map((t)=>this.current(t))}credential(e){let t=this.controlPlane.database.query("SELECT credential_ciphertext FROM registry_connections WHERE id=?").get(e);return t?.credential_ciphertext?JSON.parse(this.decrypt(String(t.credential_ciphertext))):void 0}rotate(e,t,r={}){let n=this.get(e);if(!n||n.status==="disconnected")throw Error("Registry connection was not found");let i=JSON.stringify(t);return this.controlPlane.database.run("UPDATE registry_connections SET credential_ciphertext=?, credential_fingerprint=?, credential_expires_at=?, status='pending', health_message=NULL, version=version+1, updated_at=? WHERE id=?",[this.encrypt(i),jd(i),r.expiresAt??null,this.now(),e]),this.controlPlane.appendEvent({organizationId:n.organizationId,actorId:r.actorId,type:"registry.credential.rotated",payload:{connectionId:e,fingerprint:jd(i),expiresAt:r.expiresAt??null}}),this.get(e)}disconnect(e,t){let r=this.get(e);if(!r)throw Error("Registry connection was not found");return this.controlPlane.database.run("UPDATE registry_connections SET credential_ciphertext=NULL, credential_fingerprint=NULL, status='disconnected', health_message='Disconnected by an administrator', version=version+1, updated_at=? WHERE id=?",[this.now(),e]),this.controlPlane.appendEvent({organizationId:r.organizationId,actorId:t,type:"registry.connection.disconnected",level:"warning",payload:{connectionId:e}}),this.get(e)}async test(e,t={}){let r=this.get(e);if(!r||["disconnected","expired"].includes(r.status))throw Error("Active registry connection was not found");let n=this.credential(e),i=t.fetch??fetch,o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??15000),c=n?.token?`Bearer ${n.token}`:n?.username||n?.password?`Basic ${Buffer.from(`${n.username??""}:${n.password??""}`).toString("base64")}`:void 0;try{let l=await i(`${r.host}/v2/`,{method:"GET",redirect:"error",signal:o.signal,headers:c?{Authorization:c}:void 0}),a=l.headers.get("www-authenticate")??"";if(l.status===401&&a.startsWith("Bearer ")&&n){let D=Object.fromEntries([...a.slice(7).matchAll(/(\w+)="([^"]+)"/g)].map((oe)=>[oe[1],oe[2]])),N=new URL(D.realm??"");if(N.protocol!=="https:")throw Error("Registry authentication realm must use HTTPS");if(D.service)N.searchParams.set("service",D.service);if(t.image)N.searchParams.set("scope",`repository:${zp(t.image).repository}:pull`);let G=await i(N,{signal:o.signal,redirect:"error",headers:c?{Authorization:c}:void 0});if(!G.ok)throw Error(`Registry authentication failed (${G.status})`);let Y=await G.json(),ee=Y.token??Y.access_token;if(!ee)throw Error("Registry did not return an access token");l=t.image?await Fp(i,r.host,t.image,ee,o.signal):await i(`${r.host}/v2/`,{signal:o.signal,redirect:"error",headers:{Authorization:`Bearer ${ee}`}})}else if(l.ok&&t.image)l=await Fp(i,r.host,t.image,n?.token,o.signal,c);let f=l.ok?"healthy":"degraded",E=l.ok?t.image?"Registry image is readable.":"Registry connection is healthy.":`Registry request failed (${l.status})`;return this.controlPlane.database.run("UPDATE registry_connections SET status=?, health_message=?, last_tested_at=?, version=version+1, updated_at=? WHERE id=?",[f,E,this.now(),this.now(),e]),this.get(e)}catch(l){let a=o.signal.aborted?"Registry request timed out.":l instanceof Error?l.message:"Registry test failed";return this.controlPlane.database.run("UPDATE registry_connections SET status='degraded', health_message=?, last_tested_at=?, version=version+1, updated_at=? WHERE id=?",[a.slice(0,1000),this.now(),this.now(),e]),this.get(e)}finally{clearTimeout(s)}}}function zp(e){let t=e.replace(/^https?:\/\//,""),r=t.indexOf("/");if(r<1)throw Error("Image must include registry/repository");let n=t.slice(r+1),i=n.lastIndexOf("@"),o=n.lastIndexOf(":"),s=i>=0?i:o>n.lastIndexOf("/")?o:-1,c=s>=0?n.slice(0,s):n,l=s>=0?n.slice(s+1):"latest";if(!/^[A-Za-z0-9_.\/-]+$/.test(c)||!/^[A-Za-z0-9_.:+-]+$/.test(l))throw Error("Image reference is invalid");return{repository:c,reference:l}}async function Fp(e,t,r,n,i,o){let s=zp(r);return e(`${t}/v2/${s.repository}/manifests/${encodeURIComponent(s.reference)}`,{method:"HEAD",redirect:"error",signal:i,headers:{Accept:"application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json",...n?{Authorization:`Bearer ${n}`}:o?{Authorization:o}:{}}})}import{createHash as Jb}from"node:crypto";import{chmodSync as Vp,existsSync as qp,mkdirSync as Gb,renameSync as Wb,unlinkSync as Jp,writeFileSync as Hb}from"node:fs";import{basename as Kb,join as Qb}from"node:path";function Fd(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),filename:String(e.filename),sha256:String(e.sha256),size:Number(e.size),format:String(e.format),entryCount:Number(e.entry_count),expandedBytes:Number(e.expanded_bytes),createdByActorId:e.created_by_actor_id?String(e.created_by_actor_id):void 0,createdAt:String(e.created_at)}}class Ln{controlPlane;root;idFn;nowFn;constructor(e,t){this.controlPlane=e;this.root=A(t.cwd,"artifacts"),this.idFn=t.id??(()=>crypto.randomUUID()),this.nowFn=t.now??(()=>new Date)}create(e){let t=this.controlPlane.getProject(e.projectId);if(!t||t.organizationId!==e.organizationId)throw Error("Artifact project was not found");let r=Kb(e.filename).slice(0,200);if(!r||r!==e.filename)throw Error("Artifact filename must not contain a path");let n=_p(e.bytes,r),i=Jb("sha256").update(e.bytes).digest("hex"),o=this.controlPlane.database.query("SELECT * FROM application_artifacts WHERE project_id=? AND sha256=?").get(e.projectId,i);if(o)return Fd(o);let s=this.idFn();Gb(this.root,{recursive:!0,mode:448}),Vp(this.root,448);let c=Qb(this.root,`${s}.archive`),l=`${c}.partial`;try{Hb(l,e.bytes,{mode:384,flag:"wx"}),Wb(l,c),Vp(c,384),this.controlPlane.database.run("INSERT INTO application_artifacts (id, organization_id, project_id, filename, storage_path, sha256, size, format, entry_count, expanded_bytes, created_by_actor_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[s,e.organizationId,e.projectId,r,c,i,e.bytes.byteLength,n.format,n.entries,n.expandedBytes,e.actorId??null,this.nowFn().toISOString()])}catch(a){if(qp(l))Jp(l);if(qp(c))Jp(c);throw a}return this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,actorId:e.actorId,type:"application.artifact.created",payload:{artifactId:s,filename:r,sha256:i,size:e.bytes.byteLength,entries:n.entries}}),this.get(s)}get(e){let t=this.controlPlane.database.query("SELECT * FROM application_artifacts WHERE id=?").get(e);return t?Fd(t):void 0}list(e){return this.controlPlane.database.query("SELECT * FROM application_artifacts WHERE project_id=? ORDER BY created_at DESC").all(e).map(Fd)}}function xr(e){let t=e.drafts.get(e.draftId);if(!t||t.version!==e.expectedVersion)throw Error(`Application draft ${e.draftId} changed since version ${e.expectedVersion}`);if(t.status==="applied")throw Error("Application draft was already applied");let r=e.controlPlane.getProject(t.projectId),n=r?e.controlPlane.listEnvironments(r.id).find((a)=>a.id===t.input.environmentId):void 0;if(!r||!n||n.projectId!==r.id||r.organizationId!==t.organizationId)throw Error("Draft deployment scope was not found");if(e.confirmEnvironment!==n.slug)throw Error(`Type ${n.slug} to confirm this deployment target`);let i=ce(t.input,t.suppliedSecretNames);if(!i.valid)throw Error(`Application plan is invalid: ${[...i.issues.map((a)=>a.message),...i.missingSecrets.map((a)=>`Missing secret ${a}`)].join("; ")}`);let o=e.controlPlane.listResources(r.id,n.id).find((a)=>a.kind==="application"&&a.slug===t.input.slug),s=JSON.parse(JSON.stringify({manifest:i.manifest,configPatch:i.configPatch})),c=o?e.controlPlane.updateResource(o.id,o.version,{name:t.input.name,desiredState:s}):e.controlPlane.createResource({projectId:r.id,environmentId:n.id,kind:"application",slug:t.input.slug,name:t.input.name,desiredState:s,metadata:{source:"application-onboarding",draftId:t.id}}),l=new b(e.controlPlane).enqueue({projectId:r.id,environmentId:n.id,resourceId:c.id,actorId:e.actorId,kind:"application.create",idempotencyKey:`application-draft:${t.id}:v${t.version}`,correlationId:`application-draft:${t.id}`,input:s,lockKey:`resource:${c.id}`,providerKey:c.provider??"default",buildSlot:t.input.build.kind!=="prebuilt_image",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return e.drafts.markApplied(t.id,t.version,e.actorId),e.controlPlane.appendEvent({organizationId:t.organizationId,projectId:r.id,resourceId:c.id,operationId:l.id,actorId:e.actorId,type:"application.create.queued",payload:{draftId:t.id,environment:n.slug,strategy:t.input.build.kind,costDrivers:i.costDrivers}}),{plan:i,resource:c,operation:l}}function rr(e){let t=["static","compute","serverless_zip","serverless_image"].includes(e.kind),r=["container","compose"].includes(e.kind)&&(e.replicas??1)>1,n=e.kind==="container"||e.kind==="serverless_zip"||e.kind==="serverless_image",i=(o,s)=>s&&(o==="atomic"?e.kind==="static"||e.hasHealthGate:e.hasHealthGate);return[{strategy:"atomic",supported:i("atomic",t),explanation:t?e.hasHealthGate||e.kind==="static"?"Activate an immutable version with an atomic pointer/alias switch.":"Atomic activation needs a readiness gate for this runtime.":"This driver has no atomic pointer or alias primitive.",capacityMultiplier:1,costImpact:"none",rollback:"Switch the pointer/alias back to the previous immutable release."},{strategy:"rolling",supported:i("rolling",r),explanation:r?e.hasHealthGate?"Replace healthy replicas within the configured capacity envelope.":"Rolling activation requires a health/readiness gate.":"Rolling activation requires a capable container/Compose driver and at least two replicas.",capacityMultiplier:1.5,costImpact:"temporary",rollback:"Stop replacement and restore the prior task/service definition."},{strategy:"blue_green",supported:i("blue_green",n),explanation:n?e.hasHealthGate?"Provision a complete green target and switch traffic after health passes.":"Blue-green requires a health gate before traffic can switch.":"The provider does not expose two traffic-addressable revisions.",capacityMultiplier:2,costImpact:"temporary",rollback:"Return all traffic to the preserved blue target."},{strategy:"canary",supported:i("canary",n),explanation:n?e.hasHealthGate?"Shift bounded traffic steps while evaluating health.":"Canary requires a health gate and measurable traffic target.":"The provider does not expose weighted traffic primitives.",capacityMultiplier:1.25,costImpact:"temporary",rollback:"Set canary weight to zero and preserve its diagnostics."}]}function ec(e,t){let r=rr(e).find((n)=>n.strategy===t);if(!r.supported)throw Error(`${t} is unavailable: ${r.explanation}`);return r}import{createHash as Yb}from"node:crypto";var Xb=/^sha256:[a-f0-9]{64}$/,Zb=/^[a-f0-9]{40,64}$/i;function _i(e){return typeof e==="string"&&e?e:void 0}function qo(e,t){try{return JSON.parse(String(e))}catch{return t}}function Gp(e){return{id:String(e.id),organizationId:String(e.organization_id),digest:String(e.digest),kind:String(e.kind),uri:String(e.uri),size:Number(e.size),mediaType:String(e.media_type),provenance:qo(e.provenance,{}),attestation:qo(e.attestation,{}),verifiedAt:String(e.verified_at),createdAt:String(e.created_at)}}function Wp(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:String(e.environment_id),resourceId:String(e.resource_id),artifactId:String(e.artifact_id),kind:String(e.kind),sourceSha:_i(e.source_sha),configHash:String(e.config_hash),manifest:qo(e.manifest,{}),provenance:qo(e.provenance,{}),strategy:String(e.strategy),status:String(e.status),healthGate:e.health_gate==null?void 0:qo(e.health_gate,void 0),hooks:qo(e.hooks,{migrations:"none",preActivate:[],postActivate:[]}),drainSeconds:Number(e.drain_seconds),graceSeconds:Number(e.grace_seconds),automaticRollback:Number(e.automatic_rollback)===1,rollbackAttempts:Number(e.rollback_attempts),previousReleaseId:_i(e.previous_release_id),promotedFromReleaseId:_i(e.promoted_from_release_id),actorId:_i(e.actor_id),trigger:String(e.trigger),pinned:Number(e.pinned)===1,pinReason:_i(e.pin_reason),activatedAt:_i(e.activated_at),failedAt:_i(e.failed_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function eS(e){return{sequence:Number(e.sequence),id:String(e.id),releaseId:String(e.release_id),fromStatus:_i(e.from_status),toStatus:String(e.to_status),trafficPercent:e.traffic_percent==null?void 0:Number(e.traffic_percent),health:qo(e.health,{}),message:String(e.message),operationId:_i(e.operation_id),createdAt:String(e.created_at)}}function tS(e,t){let r=[],n=(i,o,s)=>{if(JSON.stringify(o)===JSON.stringify(s))return;if(o&&s&&typeof o==="object"&&typeof s==="object"&&!Array.isArray(o)&&!Array.isArray(s)){for(let c of[...new Set([...Object.keys(o),...Object.keys(s)])].sort())n(i?`${i}.${c}`:c,o[c],s[c]);return}r.push({path:i,...o!==void 0?{before:o}:{},...s!==void 0?{after:s}:{}})};return n("",e,t),r}class Ud{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}registerArtifact(e){if(!Xb.test(e.digest)||!/^(?:s3|https|oci|file):/.test(e.uri)||!Number.isInteger(e.size)||e.size<0)throw Error("Artifact requires a SHA-256 digest, supported immutable URI, and non-negative byte size");let t=this.controlPlane.database.query("SELECT * FROM release_artifacts WHERE organization_id=? AND digest=?").get(e.organizationId,e.digest);if(t)return Gp(t);let r=this.id(),n=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO release_artifacts (id, organization_id, digest, kind, uri, size, media_type, provenance, attestation, verified_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[r,e.organizationId,e.digest,e.kind,e.uri,e.size,e.mediaType??"application/octet-stream",JSON.stringify(h(e.provenance??{})),JSON.stringify(h(e.attestation??{})),n,n]),this.getArtifact(r)}getArtifact(e){let t=this.controlPlane.database.query("SELECT * FROM release_artifacts WHERE id=?").get(e);return t?Gp(t):void 0}create(e){let t=this.getArtifact(e.artifactId),r=this.controlPlane.getResource(e.resourceId),n=this.controlPlane.listEnvironments(e.projectId).find((E)=>E.id===e.environmentId);if(!t||t.organizationId!==e.organizationId||t.kind!==e.kind)throw Error("Release artifact does not match the organization and deployable kind");if(!r||r.projectId!==e.projectId||r.environmentId!==e.environmentId||!n)throw Error("Release target scope does not match the resource");if(e.sourceSha&&!Zb.test(e.sourceSha))throw Error("Release source must be an immutable commit SHA");ec({kind:e.kind,provider:r.provider,hasHealthGate:!!e.healthGate,replicas:e.replicas},e.strategy);let i=h(e.config),o=Yb("sha256").update(JSON.stringify(i)).digest("hex"),s=this.active(e.resourceId),c=this.id(),l=this.now().toISOString(),a=e.approvalRequired?"awaiting_approval":"built",f=e.hooks??{migrations:"none",preActivate:[],postActivate:[]};return this.controlPlane.database.run("INSERT INTO releases (id, organization_id, project_id, environment_id, resource_id, artifact_id, kind, source_sha, config_hash, manifest, provenance, strategy, status, health_gate, hooks, drain_seconds, grace_seconds, automatic_rollback, previous_release_id, promoted_from_release_id, actor_id, trigger, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[c,e.organizationId,e.projectId,e.environmentId,e.resourceId,e.artifactId,e.kind,e.sourceSha??null,o,JSON.stringify(h(e.manifest)),JSON.stringify(h(e.provenance??{})),e.strategy,a,e.healthGate?JSON.stringify(e.healthGate):null,JSON.stringify(f),Math.max(0,Math.min(3600,Math.floor(e.drainSeconds??30))),Math.max(0,Math.min(3600,Math.floor(e.graceSeconds??30))),e.automaticRollback===!1?0:1,s?.id??null,e.promotedFromReleaseId??null,e.actorId??null,e.trigger??"manual",l,l]),this.recordTransition(c,void 0,a,{message:e.promotedFromReleaseId?"Immutable artifact promoted without rebuild.":"Immutable release record created."}),this.get(c)}get(e){let t=this.controlPlane.database.query("SELECT * FROM releases WHERE id=?").get(e);return t?Wp(t):void 0}list(e={}){return this.controlPlane.database.query("SELECT * FROM releases ORDER BY created_at DESC, rowid DESC").all().map(Wp).filter((t)=>(!e.projectId||t.projectId===e.projectId)&&(!e.environmentId||t.environmentId===e.environmentId)&&(!e.resourceId||t.resourceId===e.resourceId)&&(!e.status||t.status===e.status))}active(e){return this.list({resourceId:e,status:"active"})[0]}transitions(e){return this.controlPlane.database.query("SELECT * FROM release_transitions WHERE release_id=? ORDER BY sequence").all(e).map(eS)}recordTransition(e,t,r,n){this.controlPlane.database.run("INSERT INTO release_transitions (id, release_id, from_status, to_status, traffic_percent, health, message, operation_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",[this.id(),e,t??null,r,n.trafficPercent??null,JSON.stringify(h(n.health??{})),n.message.slice(0,1000),n.operationId??null,this.now().toISOString()])}progress(e,t){let r=this.get(e);if(!r)throw Error(`Release ${e} was not found`);return this.recordTransition(e,r.status,r.status,t),this.transitions(e).at(-1)}transition(e,t,r){let n=this.get(e);if(!n)throw Error(`Release ${e} was not found`);if(!{built:["awaiting_approval","activating","failed"],awaiting_approval:["built","failed"],activating:["active","failed","rolled_back"],active:["superseded","failed","rolled_back"],failed:["activating","rolled_back"],rolled_back:["activating"],superseded:["activating"]}[n.status].includes(t))throw Error(`Invalid release transition ${n.status} → ${t}`);let o=this.now().toISOString();if(t==="active"){let s=this.active(n.resourceId);if(s&&s.id!==e)this.controlPlane.database.run("UPDATE releases SET status='superseded', updated_at=? WHERE id=?",[o,s.id]),this.recordTransition(s.id,"active","superseded",{message:`Superseded by ${e}.`,operationId:r.operationId})}return this.controlPlane.database.run("UPDATE releases SET status=?, rollback_attempts=rollback_attempts+?, activated_at=CASE WHEN ?='active' THEN ? ELSE activated_at END, failed_at=CASE WHEN ?='failed' THEN ? ELSE failed_at END, updated_at=? WHERE id=?",[t,t==="rolled_back"?1:0,t,o,t,o,o,e]),this.recordTransition(e,n.status,t,r),this.get(e)}approve(e,t){let r=this.get(e);if(!r||r.status!=="awaiting_approval")throw Error("Release is not awaiting approval");let n=this.id(),i=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO release_approvals (id, release_id, environment_id, decision, actor_id, comment, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[n,e,r.environmentId,t.decision,t.actorId,t.comment?.slice(0,1000)??null,i]),this.transition(e,t.decision==="approved"?"built":"failed",{message:t.decision==="approved"?"Environment gate approved.":"Environment gate rejected."})}approvals(e){return this.controlPlane.database.query("SELECT * FROM release_approvals WHERE release_id=? ORDER BY created_at").all(e).map((t)=>({id:String(t.id),releaseId:String(t.release_id),environmentId:String(t.environment_id),decision:String(t.decision),actorId:String(t.actor_id),comment:_i(t.comment),createdAt:String(t.created_at)}))}promote(e,t){let r=this.get(e);if(!r||!["active","superseded"].includes(r.status))throw Error("Only a tested active/superseded release can be promoted");return this.create({organizationId:r.organizationId,projectId:r.projectId,environmentId:t.targetEnvironmentId,resourceId:t.targetResourceId,artifactId:r.artifactId,kind:r.kind,sourceSha:r.sourceSha,config:t.config,manifest:r.manifest,provenance:r.provenance,strategy:t.strategy??r.strategy,healthGate:t.healthGate??r.healthGate,hooks:r.hooks,drainSeconds:r.drainSeconds,graceSeconds:r.graceSeconds,automaticRollback:r.automaticRollback,promotedFromReleaseId:r.id,actorId:t.actorId,trigger:"promotion",approvalRequired:t.approvalRequired})}compare(e,t){let r=this.get(e),n=this.get(t);if(!r||!n)throw Error("Both releases are required for comparison");return{artifactChanged:r.artifactId!==n.artifactId,sourceChanged:r.sourceSha!==n.sourceSha,configChanged:r.configHash!==n.configHash,manifestChanges:tS(r.manifest,n.manifest),dataCaveat:n.hooks.migrations==="none"?"No database migration is recorded.":`Database hooks are ${n.hooks.migrations}; release rollback does not roll back data.`}}pin(e,t,r){if(!this.get(e))throw Error("Release was not found");return this.controlPlane.database.run("UPDATE releases SET pinned=?, pin_reason=?, updated_at=? WHERE id=?",[t?1:0,t?r?.slice(0,500)??"operator":null,this.now().toISOString(),e]),this.get(e)}retentionCandidates(e){let t=Math.max(1,Math.min(100,Math.floor(e.keepPerResource??10))),r=new Map;for(let n of this.list()){let i=r.get(n.resourceId)??[];i.push(n),r.set(n.resourceId,i)}return[...r.values()].flatMap((n)=>n.slice(t)).filter((n)=>new Date(n.createdAt)<e.before&&!n.pinned&&!["active","activating","awaiting_approval"].includes(n.status)&&!this.list().some((i)=>i.previousReleaseId===n.id&&["active","activating"].includes(i.status)))}}class ot{controlPlane;releases;queue;constructor(e){this.controlPlane=e;this.releases=new Ud(e),this.queue=new b(e)}enqueueActivation(e,t={}){let r=this.releases.get(e.id);if(!r)throw Error("Release was not found");if(!["built","failed","rolled_back","superseded"].includes(r.status))throw Error(`Release ${r.status} cannot be activated`);let n=t.action??"activate",i=this.queue.enqueue({projectId:r.projectId,environmentId:r.environmentId,resourceId:r.resourceId,actorId:t.actorId,kind:`release.${n}`,idempotencyKey:`release:${r.id}:${n}:${r.rollbackAttempts}`,correlationId:`release:${r.id}`,input:{releaseId:r.id,targetReleaseId:t.targetReleaseId??null},lockKey:`resource:${r.resourceId}`,providerKey:this.controlPlane.getResource(r.resourceId)?.provider??"default",maxAttempts:r.automaticRollback?2:1,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:365}).operation;return this.releases.transition(r.id,"activating",{message:`${n} queued.`,operationId:i.id,trafficPercent:0}),i}completeHealthGate(e,t){let r=this.releases.get(e);if(!r||r.status!=="activating")throw Error("Release is not activating");if(t.healthy)return{release:this.releases.transition(r.id,"active",{message:t.message??"Health gate passed; activation completed.",operationId:t.operationId,trafficPercent:100,health:t.health})};let n=this.releases.transition(r.id,"failed",{message:t.message??"Health gate failed.",operationId:t.operationId,trafficPercent:0,health:t.health}),i=r.previousReleaseId?this.releases.get(r.previousReleaseId):void 0;if(!r.automaticRollback||r.rollbackAttempts>=1||!i)return{release:n};let o=this.queue.enqueue({projectId:r.projectId,environmentId:r.environmentId,resourceId:r.resourceId,kind:"release.rollback",idempotencyKey:`release:${r.id}:automatic-rollback`,correlationId:`release:${r.id}`,input:{releaseId:r.id,targetReleaseId:i.id,automatic:!0},lockKey:`resource:${r.resourceId}`,providerKey:this.controlPlane.getResource(r.resourceId)?.provider??"default",maxAttempts:1,retryClasses:[],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:365}).operation;return{release:n,rollbackOperation:o}}enqueueRollback(e,t={}){let r=this.releases.get(e.id);if(!r||r.status!=="active")throw Error("Only the active release can be rolled back");let n=t.targetReleaseId?this.releases.get(t.targetReleaseId):r.previousReleaseId?this.releases.get(r.previousReleaseId):void 0;if(!n||n.resourceId!==r.resourceId||!["superseded","active"].includes(n.status))throw Error("Rollback requires a preserved prior release for the same resource");return this.queue.enqueue({projectId:r.projectId,environmentId:r.environmentId,resourceId:r.resourceId,actorId:t.actorId,kind:"release.rollback",idempotencyKey:`release:${r.id}:manual-rollback:${n.id}`,correlationId:`release:${r.id}`,input:{releaseId:r.id,targetReleaseId:n.id,automatic:!1},lockKey:`resource:${r.resourceId}`,providerKey:this.controlPlane.getResource(r.resourceId)?.provider??"default",maxAttempts:1,retryClasses:[],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:365}).operation}}function rS(e){if(e.strategy==="canary")return[5,25,50,100].map((t,r)=>({step:`canary-${t}`,trafficPercent:t,waitSeconds:r===3?e.drainSeconds:e.graceSeconds,requiresHealth:!0}));if(e.strategy==="blue_green")return[{step:"green-health",trafficPercent:0,waitSeconds:e.graceSeconds,requiresHealth:!0},{step:"traffic-switch",trafficPercent:100,waitSeconds:e.drainSeconds,requiresHealth:!0}];if(e.strategy==="rolling")return[{step:"rolling-replacement",trafficPercent:50,waitSeconds:e.graceSeconds,requiresHealth:!0},{step:"rolling-complete",trafficPercent:100,waitSeconds:e.drainSeconds,requiresHealth:!0}];return[{step:"immutable-switch",trafficPercent:100,waitSeconds:e.drainSeconds,requiresHealth:!!e.healthGate}]}async function Hp(e,t){if(t.release.artifactId!==t.artifact.id)throw Error("Release activation artifact identity changed");ec({kind:t.release.kind,hasHealthGate:!!t.release.healthGate,replicas:Number(t.release.manifest?.replicas)||void 0},t.release.strategy);let r=e.capability(t);if(!r.supported)throw Error(`${t.release.strategy} is unavailable in ${e.name}: ${r.explanation}`);return e.activate({...t,transitions:rS(t.release)})}async function Kp(e,t){if(!t.previous)throw Error("Rollback requires the preserved previous release");return e.rollback({...t,transitions:[{step:"rollback",trafficPercent:0,waitSeconds:t.release.drainSeconds,requiresHealth:!0}]})}var nS=["release.activate","release.rollback"];function iS(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function Qp(e){let t=new ot(e.store),r=async(n)=>{let i=iS(n.operation.input),o=typeof i.releaseId==="string"?i.releaseId:"",s=t.releases.get(o);if(!s)throw Error(`Queued release ${o||"(missing)"} was not found`);if(s.projectId!==n.operation.projectId||s.environmentId!==n.operation.environmentId||s.resourceId!==n.operation.resourceId)throw Error("Queued release does not match the operation scope");let c=t.releases.getArtifact(s.artifactId);if(!c||c.digest!==t.releases.getArtifact(s.artifactId)?.digest)throw Error("Immutable release artifact is unavailable");let l=typeof i.targetReleaseId==="string"&&i.targetReleaseId?i.targetReleaseId:s.previousReleaseId,a=l?t.releases.get(l):void 0;if(a&&(a.resourceId!==s.resourceId||a.artifactId===s.artifactId&&a.id===s.id))throw Error("Rollback target does not match the release resource");let f=await e.resolveDriver(s);n.checkpoint("verify",`Verifying ${c.digest} and ${s.configHash} for ${f.name}.`),n.log(`Artifact ${c.digest}; source ${s.sourceSha??"not recorded"}; config ${s.configHash}.`,{stream:"system"}),n.throwIfCancellationRequested();let E;try{E=n.operation.kind==="release.rollback"?await Kp(f,{release:s,artifact:c,previous:a}):await Hp(f,{release:s,artifact:c,previous:a})}catch(D){if(n.operation.kind==="release.activate"&&t.releases.get(s.id)?.status==="activating")t.completeHealthGate(s.id,{healthy:!1,operationId:n.operation.id,message:D instanceof Error?D.message:String(D)});throw D}for(let D of E.transitions)t.releases.progress(s.id,{message:`${n.operation.kind==="release.rollback"?"Rollback":"Activation"} traffic at ${D.trafficPercent}%.`,trafficPercent:D.trafficPercent,health:D.observed,operationId:n.operation.id}),n.log(`Traffic ${D.trafficPercent}%: ${D.healthy?"healthy":"unhealthy"}.`,{stream:D.healthy?"step":"stderr",step:"health"});if(n.checkpoint("health","Evaluating the provider health result."),!E.activated||!E.healthy){if(n.operation.kind==="release.activate"&&t.releases.get(s.id)?.status==="activating")t.completeHealthGate(s.id,{healthy:!1,operationId:n.operation.id,health:{resourceVersions:E.resourceVersions},message:E.error??"Provider health gate failed."});throw Error(E.error??`${f.name} reported an unhealthy release`)}if(n.operation.kind==="release.activate"&&s.healthGate?.name){if(!e.resolveHealthGate)throw t.completeHealthGate(s.id,{healthy:!1,operationId:n.operation.id,message:`Named health gate ${s.healthGate.name} is not available to this worker.`}),Error(`Named health gate ${s.healthGate.name} is unavailable`);n.checkpoint("named-health-gate",`Waiting on ${s.healthGate.name}.`);let D=await e.resolveHealthGate(s.healthGate.name,s);if(n.log(`${s.healthGate.name}: ${D.healthy?"healthy":"unhealthy"}${D.message?` — ${D.message}`:""}.`,{stream:D.healthy?"step":"stderr",step:"health"}),!D.healthy)throw t.completeHealthGate(s.id,{healthy:!1,operationId:n.operation.id,health:D.evidence,message:D.message??`Named health gate ${s.healthGate.name} failed.`}),Error(D.message??`Named health gate ${s.healthGate.name} failed`)}if(n.operation.kind==="release.rollback"){let D=t.releases.get(s.id);if(D.status!=="rolled_back")t.releases.transition(D.id,"rolled_back",{message:`Traffic restored through ${f.name}.`,operationId:n.operation.id,trafficPercent:0,health:{resourceVersions:E.resourceVersions}});if(a&&a.status!=="active"){let N=a.status==="activating"?a:t.releases.transition(a.id,"activating",{message:"Rollback target restoring traffic.",operationId:n.operation.id,trafficPercent:0});t.releases.transition(N.id,"active",{message:"Previous immutable release restored.",operationId:n.operation.id,trafficPercent:100,health:{resourceVersions:E.resourceVersions}})}}else t.completeHealthGate(s.id,{healthy:!0,operationId:n.operation.id,health:{providerVersion:E.providerVersion??null,resourceVersions:E.resourceVersions},message:"Provider activation and health gates completed."});return n.checkpoint("finalize","Persisted the terminal release state."),{releaseId:s.id,artifactDigest:c.digest,provider:f.name,providerVersion:E.providerVersion??null,resourceVersions:E.resourceVersions,status:t.releases.get(s.id).status}};return Object.fromEntries(nS.map((n)=>[n,r]))}import{createCipheriv as oS,createDecipheriv as sS,createHash as tg,randomBytes as zd}from"node:crypto";var rg={github:{repositories:!0,branches:!0,tags:!0,webhooks:!0,pullRequests:!0,tokenRefresh:!0,deployKeys:!0},gitlab:{repositories:!0,branches:!0,tags:!0,webhooks:!0,pullRequests:!0,tokenRefresh:!0,deployKeys:!0},bitbucket:{repositories:!0,branches:!0,tags:!0,webhooks:!0,pullRequests:!0,tokenRefresh:!0,deployKeys:!0},gitea:{repositories:!0,branches:!0,tags:!0,webhooks:!0,pullRequests:!0,tokenRefresh:!1,deployKeys:!0},generic_https:{repositories:!1,branches:!0,tags:!0,webhooks:!1,pullRequests:!1,tokenRefresh:!1,deployKeys:!1},generic_ssh:{repositories:!1,branches:!0,tags:!0,webhooks:!1,pullRequests:!1,tokenRefresh:!1,deployKeys:!0}};function xt(e){return typeof e==="string"&&e?e:void 0}function Go(e,t){try{return typeof e==="string"?JSON.parse(e):t}catch{return t}}function $i(e){return JSON.stringify(h(e))}function Jo(e){return tg("sha256").update(e).digest("hex")}function Yp(e){let t=e.trim().replace(/\/$/,""),r=new URL(t.includes("://")?t:`https://${t}`);if(r.username||r.password||r.search||r.hash)throw Error("Source host cannot contain credentials, a query, or a fragment");if(r.protocol!=="https:"&&!(r.protocol==="http:"&&["localhost","127.0.0.1","::1"].includes(r.hostname)))throw Error("Source host must use HTTPS");return`${r.protocol}//${r.host}${r.pathname.replace(/\/$/,"")}`}function Xp(e){let t=e.trim();if(t.length<2||t.length>80)throw Error("Connection name must contain 2-80 characters");return t}function Vd(e){let t=e.trim().replace(/^\/+|\/+$/g,"");if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(t))throw Error("Repository must use owner/name format");return t}function Zp(e){let t=e.trim()||".";if(t.startsWith("/")||t.split("/").includes("..")||/[\0\r\n]/.test(t))throw Error("Monorepo root must stay inside the repository");return t.replace(/^\.\//,"")||"."}function tc(e){return[...new Set((e??[]).map((t)=>t.trim()).filter(Boolean))].slice(0,100)}function aS(e){let t=e.trim();if(/\r|\n/.test(t)||/https?:\/\/[^/@\s]+:[^/@\s]+@/i.test(t))throw Error("Clone URL cannot contain credentials or control characters");if(!/^(?:https?:\/\/|ssh:\/\/|git@[A-Za-z0-9.-]+:)/.test(t))throw Error("Clone URL must use HTTPS or SSH");return t}function cS(e){return{id:String(e.id),organizationId:String(e.organization_id),provider:String(e.provider),name:String(e.name),host:String(e.host),owner:xt(e.owner),authKind:String(e.auth_kind),credentialConfigured:!!e.credential_ciphertext,credentialFingerprint:xt(e.credential_fingerprint),grantedScopes:Go(e.granted_scopes,[]),capabilities:Go(e.capabilities,rg[String(e.provider)]),status:String(e.status),healthMessage:xt(e.health_message),lastTestedAt:xt(e.last_tested_at),lastSyncedAt:xt(e.last_synced_at),credentialExpiresAt:xt(e.credential_expires_at),version:Number(e.version),createdByActorId:xt(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function qd(e){return{id:String(e.id),connectionId:String(e.connection_id),providerRepositoryId:String(e.provider_repository_id),fullName:String(e.full_name),cloneUrl:String(e.clone_url),defaultBranch:String(e.default_branch),visibility:String(e.visibility),archived:Number(e.archived)===1,metadata:Go(e.metadata,{}),syncedAt:String(e.synced_at)}}function eg(e){return{id:String(e.id),projectId:String(e.project_id),environmentId:xt(e.environment_id),resourceId:xt(e.resource_id),connectionId:String(e.connection_id),repositoryId:xt(e.repository_id),repositoryFullName:String(e.repository_full_name),defaultBranch:String(e.default_branch),branchRule:xt(e.branch_rule),tagRule:xt(e.tag_rule),monorepoRoot:String(e.monorepo_root),includePaths:Go(e.include_paths,[]),excludePaths:Go(e.exclude_paths,[]),submodules:Number(e.submodules)===1,cloneDepth:e.clone_depth==null?void 0:Number(e.clone_depth),deployKeyId:xt(e.deploy_key_id),autoDeploy:Number(e.auto_deploy)===1,pullRequestPreviews:Number(e.pull_request_previews)===1,status:String(e.status),disabledReason:xt(e.disabled_reason),version:Number(e.version),createdByActorId:xt(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Jd(e){return{id:String(e.id),connectionId:String(e.connection_id),name:String(e.name),publicKey:String(e.public_key),publicKeyFingerprint:String(e.public_key_fingerprint),host:String(e.host),hostKey:String(e.host_key),hostKeyFingerprint:String(e.host_key_fingerprint),createdByActorId:xt(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Gd(e){return{id:String(e.id),connectionId:String(e.connection_id),repositoryId:xt(e.repository_id),repositoryFullName:String(e.repository_full_name),providerWebhookId:xt(e.provider_webhook_id),events:Go(e.events,[]),status:String(e.status),healthMessage:xt(e.health_message),lastDeliveryAt:xt(e.last_delivery_at),lastReconciledAt:xt(e.last_reconciled_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Wd(e){return{id:String(e.id),connectionId:String(e.connection_id),webhookId:String(e.webhook_id),providerDeliveryId:String(e.provider_delivery_id),event:String(e.event),action:xt(e.action),commitSha:xt(e.commit_sha),signatureStatus:String(e.signature_status),status:String(e.status),payloadSummary:Go(e.payload_summary,{}),operationId:xt(e.operation_id),error:xt(e.error),receivedAt:String(e.received_at),processedAt:xt(e.processed_at)}}class Yt{controlPlane;key;nowFn;idFn;constructor(e,t={}){this.controlPlane=e;this.key=t.encryptionKey?tg("sha256").update(t.encryptionKey).digest():void 0,this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID())}now(){return this.nowFn().toISOString()}run(e,t){this.controlPlane.database.run(e,t)}encrypt(e){if(!this.key)throw Error("Source credential encryption key is not configured");let t=zd(12),r=oS("aes-256-gcm",this.key,t),n=Buffer.concat([r.update(e,"utf8"),r.final()]);return`v1.${t.toString("base64url")}.${r.getAuthTag().toString("base64url")}.${n.toString("base64url")}`}decrypt(e){if(!this.key)throw Error("Source credential encryption key is not configured");let[t,r,n,i]=e.split(".");if(t!=="v1"||!r||!n||!i)throw Error("Encrypted source credential is unavailable");let o=sS("aes-256-gcm",this.key,Buffer.from(r,"base64url"));return o.setAuthTag(Buffer.from(n,"base64url")),Buffer.concat([o.update(Buffer.from(i,"base64url")),o.final()]).toString("utf8")}createConnection(e){if(!this.controlPlane.getOrganization(e.organizationId))throw Error("Source connection organization was not found");let t=this.now(),r=this.idFn(),n=e.credential?JSON.stringify(e.credential):void 0;return this.run(`INSERT INTO source_connections (id, organization_id, provider, name, host, owner, auth_kind, credential_ciphertext, credential_fingerprint, granted_scopes, capabilities, status, credential_expires_at, created_by_actor_id, created_at, updated_at)
3
3
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, ?, ?)`,[r,e.organizationId,e.provider,Xp(e.name),Yp(e.host),e.owner?.trim()||null,e.authKind??(n?"access_token":"none"),n?this.encrypt(n):null,n?Jo(n).slice(0,16):null,$i([...new Set(e.grantedScopes??[])].sort()),$i(rg[e.provider]),e.credentialExpiresAt??null,e.createdByActorId??null,t,t]),this.controlPlane.appendEvent({organizationId:e.organizationId,actorId:e.createdByActorId,type:"source.connection.created",payload:{connectionId:r,provider:e.provider,host:Yp(e.host),owner:e.owner??null,scopes:e.grantedScopes??[]}}),this.getConnection(r)}getConnection(e){let t=this.controlPlane.database.query("SELECT * FROM source_connections WHERE id = ?").get(e);return t?this.currentConnection(t):void 0}listConnections(e){return this.controlPlane.database.query("SELECT * FROM source_connections WHERE organization_id = ? ORDER BY name").all(e).map((t)=>this.currentConnection(t))}currentConnection(e){let t=cS(e);if(t.status!=="disconnected"&&t.credentialExpiresAt&&new Date(t.credentialExpiresAt).getTime()<=this.nowFn().getTime())return{...t,status:"expired",healthMessage:"Source credential expired; rotate it before deploying."};return t}getCredential(e){let t=this.controlPlane.database.query("SELECT credential_ciphertext FROM source_connections WHERE id = ?").get(e);return t?.credential_ciphertext?JSON.parse(this.decrypt(String(t.credential_ciphertext))):void 0}rotateCredential(e,t,r={}){let n=this.getConnection(e);if(!n||n.status==="disconnected")throw Error("Active source connection was not found");let i=JSON.stringify(t);return this.run("UPDATE source_connections SET credential_ciphertext = ?, credential_fingerprint = ?, credential_expires_at = ?, status = 'pending', health_message = NULL, version = version + 1, updated_at = ? WHERE id = ?",[this.encrypt(i),Jo(i).slice(0,16),r.expiresAt??null,this.now(),e]),this.controlPlane.appendEvent({organizationId:n.organizationId,actorId:r.actorId,type:"source.credential.rotated",payload:{connectionId:e,fingerprint:Jo(i).slice(0,16),expiresAt:r.expiresAt??null}}),this.getConnection(e)}updateHealth(e,t){let r=this.getConnection(e);if(!r||["disconnected","expired"].includes(r.status))throw Error("Active source connection was not found");let n=this.now(),i=t.grantedScopes?[...new Set(t.grantedScopes.map((o)=>o.trim()).filter(Boolean))].sort():void 0;if(this.run("UPDATE source_connections SET status = ?, health_message = ?, granted_scopes = COALESCE(?, granted_scopes), last_tested_at = COALESCE(?, last_tested_at), last_synced_at = COALESCE(?, last_synced_at), version = version + 1, updated_at = ? WHERE id = ?",[t.status,t.message?.slice(0,1000)??null,i?$i(i):null,t.tested?n:null,t.synced?n:null,n,e]),i&&JSON.stringify(i)!==JSON.stringify([...r.grantedScopes].sort()))this.controlPlane.appendEvent({organizationId:r.organizationId,type:"source.connection.scopes_updated",payload:{connectionId:e,grantedScopes:i}});return this.getConnection(e)}upsertRepository(e){let t=this.getConnection(e.connectionId);if(!t||["disconnected","expired"].includes(t.status))throw Error("Active source connection was not found");let r=this.now(),n=this.controlPlane.database.query("SELECT id FROM source_repositories WHERE connection_id = ? AND provider_repository_id = ?").get(e.connectionId,e.providerRepositoryId),i=n?String(n.id):this.idFn();return this.run(`INSERT INTO source_repositories (id, connection_id, provider_repository_id, full_name, clone_url, default_branch, visibility, archived, metadata, synced_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
4
4
  ON CONFLICT(connection_id, provider_repository_id) DO UPDATE SET full_name=excluded.full_name, clone_url=excluded.clone_url, default_branch=excluded.default_branch, visibility=excluded.visibility, archived=excluded.archived, metadata=excluded.metadata, synced_at=excluded.synced_at`,[i,e.connectionId,e.providerRepositoryId,Vd(e.fullName),aS(e.cloneUrl),e.defaultBranch.trim()||"main",e.visibility,e.archived?1:0,$i(e.metadata),r]),qd(this.controlPlane.database.query("SELECT * FROM source_repositories WHERE id = ?").get(i))}listRepositories(e,t,r=100){let n=t?.trim().toLowerCase();return(n?this.controlPlane.database.query("SELECT * FROM source_repositories WHERE connection_id = ? AND lower(full_name) LIKE ? ORDER BY full_name LIMIT ?").all(e,`%${n}%`,Math.min(500,r)):this.controlPlane.database.query("SELECT * FROM source_repositories WHERE connection_id = ? ORDER BY full_name LIMIT ?").all(e,Math.min(500,r))).map(qd)}getRepository(e){let t=this.controlPlane.database.query("SELECT * FROM source_repositories WHERE id = ?").get(e);return t?qd(t):void 0}createDeployKey(e){let t=this.getConnection(e.connectionId);if(!t||["disconnected","expired"].includes(t.status)||!t.capabilities.deployKeys)throw Error("An active deploy-key capable source connection is required");if(!/^ssh-(?:ed25519|rsa)\s+[A-Za-z0-9+/=]+/.test(e.publicKey.trim()))throw Error("A valid SSH public key is required");if(!/BEGIN (?:OPENSSH|RSA) PRIVATE KEY/.test(e.privateKey))throw Error("A valid SSH private key is required");if(!/^(?:ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp\d+)\s+[A-Za-z0-9+/=]+/.test(e.hostKey.trim()))throw Error("A pinned SSH host key is required");let r=this.idFn(),n=this.now(),i=`sha256:${Jo(e.publicKey.trim())}`,o=`sha256:${Jo(e.hostKey.trim())}`;return this.run("INSERT INTO source_deploy_keys (id, connection_id, name, public_key, public_key_fingerprint, private_key_ciphertext, host, host_key, host_key_fingerprint, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[r,e.connectionId,Xp(e.name),e.publicKey.trim(),i,this.encrypt(e.privateKey),e.host.trim().toLowerCase(),e.hostKey.trim(),o,e.actorId??null,n,n]),this.controlPlane.appendEvent({organizationId:t.organizationId,actorId:e.actorId,type:"source.deploy_key.created",payload:{connectionId:e.connectionId,deployKeyId:r,publicFingerprint:i,hostFingerprint:o}}),Jd(this.controlPlane.database.query("SELECT * FROM source_deploy_keys WHERE id = ?").get(r))}getDeployKey(e){let t=this.controlPlane.database.query("SELECT * FROM source_deploy_keys WHERE id = ?").get(e);return t?Jd(t):void 0}listDeployKeys(e){return this.controlPlane.database.query("SELECT * FROM source_deploy_keys WHERE connection_id = ? ORDER BY name, created_at").all(e).map(Jd)}revokeDeployKey(e,t){let r=this.getDeployKey(e),n=r?this.getConnection(r.connectionId):void 0;if(!r||!n)throw Error("Deploy key was not found");let i=this.listBindings({connectionId:n.id}).filter((s)=>s.deployKeyId===e),o=this.now();return this.controlPlane.database.transaction(()=>{this.run("UPDATE source_bindings SET deploy_key_id=NULL, status='disabled', auto_deploy=0, disabled_reason='Source deploy key was revoked', version=version+1, updated_at=? WHERE deploy_key_id=?",[o,e]),this.run("DELETE FROM source_deploy_keys WHERE id=?",[e])})(),this.controlPlane.appendEvent({organizationId:n.organizationId,actorId:t,type:"source.deploy_key.revoked",level:"warning",payload:{connectionId:n.id,deployKeyId:e,affectedBindingIds:i.map((s)=>s.id)}}),{affectedBindings:i}}getDeployPrivateKey(e){let t=this.controlPlane.database.query("SELECT private_key_ciphertext FROM source_deploy_keys WHERE id = ?").get(e);if(!t)throw Error("Deploy key was not found");return this.decrypt(String(t.private_key_ciphertext))}createBinding(e){let t=this.getConnection(e.connectionId);if(!t||["disconnected","expired"].includes(t.status))throw Error("Active source connection was not found");if(e.repositoryId&&this.getRepository(e.repositoryId)?.connectionId!==t.id)throw Error("Repository does not belong to this connection");if(e.deployKeyId&&this.getDeployKey(e.deployKeyId)?.connectionId!==t.id)throw Error("Deploy key does not belong to this connection");let r=this.idFn(),n=this.now();return this.run(`INSERT INTO source_bindings (id, project_id, environment_id, resource_id, connection_id, repository_id, repository_full_name, default_branch, branch_rule, tag_rule, monorepo_root, include_paths, exclude_paths, submodules, clone_depth, deploy_key_id, auto_deploy, pull_request_previews, status, created_by_actor_id, created_at, updated_at)
@@ -30,7 +30,7 @@ data: ${JSON.stringify(rt)}
30
30
  default_role = ?, enabled = ?, enforce_sso = ?, updated_at = ? WHERE id = ?`,[t,r,n,i,e.clientSecret?this.encrypt(e.clientSecret):null,JSON.stringify(o),JSON.stringify(s),e.defaultRole??c.defaultRole,e.enabled??c.enabled?1:0,e.enforceSso??c.enforceSso?1:0,l,c.id]),this.getOidcProvider(c.id)}if(!e.clientSecret)throw Error("OIDC client secret is required for a new provider");let a=e.id??this.idFn();return this.run(`INSERT INTO auth_oidc_providers (id, organization_id, slug, name, issuer, client_id,
31
31
  client_secret_ciphertext, scopes, allowed_domains, default_role, enabled, enforce_sso, created_at, updated_at)
32
32
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[a,e.organizationId,t,r,n,i,this.encrypt(e.clientSecret),JSON.stringify(o),JSON.stringify(s),e.defaultRole??"viewer",e.enabled===!1?0:1,e.enforceSso?1:0,l,l]),this.getOidcProvider(a)}getOidcProvider(e){let t=this.controlPlane.database.query("SELECT * FROM auth_oidc_providers WHERE id = ?").get(e);return t?sc(t):void 0}getOidcProviderBySlug(e){let t=this.controlPlane.database.query("SELECT * FROM auth_oidc_providers WHERE slug = ? COLLATE NOCASE").get(e.trim());return t?sc(t):void 0}listOidcProviders(e,t={}){return(e?this.controlPlane.database.query("SELECT * FROM auth_oidc_providers WHERE organization_id = ? ORDER BY name COLLATE NOCASE").all(e):this.controlPlane.database.query("SELECT * FROM auth_oidc_providers ORDER BY name COLLATE NOCASE").all()).map(sc).filter((n)=>t.includeDisabled||n.enabled)}setOidcProviderEnabled(e,t){let r=this.now();if(this.controlPlane.database.run("UPDATE auth_oidc_providers SET enabled = ?, enforce_sso = CASE WHEN ? = 0 THEN 0 ELSE enforce_sso END, updated_at = ? WHERE id = ?",[t?1:0,t?1:0,r,e]).changes!==1)throw Error("OIDC provider was not found");if(!t)this.run("UPDATE auth_oidc_transactions SET consumed_at = ? WHERE provider_id = ? AND consumed_at IS NULL",[r,e]);return this.getOidcProvider(e)}getOidcProviderCredentials(e){let t=this.controlPlane.database.query("SELECT * FROM auth_oidc_providers WHERE id = ?").get(e);if(!t||typeof t.client_secret_ciphertext!=="string")throw Error("OIDC provider credentials are unavailable");return{provider:sc(t),clientSecret:this.decrypt(t.client_secret_ciphertext)}}beginOidcTransaction(e,t,r){if(!this.getOidcProvider(e)?.enabled)throw Error("OIDC provider is unavailable");let i=this.idFn(),o=Wi(32).toString("base64url"),s=Wi(32).toString("base64url"),c=Wi(64).toString("base64url"),l=this.now(),a=new Date(this.nowFn().getTime()+Ag).toISOString();return this.run(`INSERT INTO auth_oidc_transactions (id, provider_id, state_hash, nonce_ciphertext, verifier_ciphertext,
33
- redirect_uri, return_path, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[i,e,yi(o),this.encrypt(s),this.encrypt(c),t,r,a,l]),{transaction:this.getOidcTransaction(i),state:o,nonce:s,verifier:c}}getOidcTransaction(e){let t=this.controlPlane.database.query("SELECT * FROM auth_oidc_transactions WHERE id = ?").get(e);return t?wg(t,this.now()):void 0}consumeOidcTransaction(e,t){return this.controlPlane.transaction(()=>{let r=this.controlPlane.database.query("SELECT * FROM auth_oidc_transactions WHERE provider_id = ? AND state_hash = ?").get(e,yi(t));if(!r)throw Error("OIDC transaction is invalid");let n=wg(r,this.now());if(n.state!=="pending")throw Error(`OIDC transaction is ${n.state}`);if(this.controlPlane.database.run("UPDATE auth_oidc_transactions SET consumed_at = ? WHERE id = ? AND consumed_at IS NULL AND expires_at > ?",[this.now(),n.id,this.now()]).changes!==1)throw Error("OIDC transaction is no longer available");return{transaction:this.getOidcTransaction(n.id),nonce:this.decrypt(String(r.nonce_ciphertext)),verifier:this.decrypt(String(r.verifier_ciphertext))}})}getOidcSubject(e,t){let r=this.controlPlane.database.query("SELECT * FROM auth_oidc_subjects WHERE provider_id = ? AND subject = ?").get(e,t);return r?LS(r):void 0}linkOidcSubject(e,t,r,n){let i=this.getOidcProvider(e),o=this.getIdentity(t);if(!i||!o)throw Error("OIDC provider or identity was not found");let s=ru(n);if(!r.trim()||r.length>512)throw Error("OIDC subject is invalid");let c=this.getOidcSubject(e,r);if(c&&c.identityId!==t)throw Error("OIDC subject is already linked to another identity");let l=this.now();if(c)return this.run("UPDATE auth_oidc_subjects SET email = ?, last_login_at = ? WHERE id = ?",[s,l,c.id]),this.getOidcSubject(e,r);let a=this.idFn();return this.run("INSERT INTO auth_oidc_subjects (id, provider_id, identity_id, subject, email, linked_at, last_login_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[a,e,t,r,s,l,l]),this.getOidcSubject(e,r)}purgeExpired(){let e=this.now(),t=this.controlPlane.database.run("DELETE FROM auth_action_tokens WHERE expires_at < ? OR consumed_at IS NOT NULL",[e]).changes,r=this.controlPlane.database.run("DELETE FROM auth_sessions WHERE revoked_at IS NOT NULL OR idle_expires_at < ? OR absolute_expires_at < ?",[e,e]).changes;return this.controlPlane.database.run("DELETE FROM auth_mfa_challenges WHERE consumed_at IS NOT NULL OR expires_at < ?",[e]),this.controlPlane.database.run("DELETE FROM auth_oidc_transactions WHERE consumed_at IS NOT NULL OR expires_at < ?",[e]),{actionTokens:t,sessions:r}}}async function ba(e,t){let r=e.notifications?.email?.from;if(!r)return!1;try{let{EmailClient:n}=await import("./chunk-8hnph1yy.js");return await new n({region:e.project.region,defaultFrom:r}).send(t),!0}catch{return!1}}import{randomBytes as BS}from"node:crypto";import{chmodSync as jS,existsSync as FS,mkdirSync as US,readFileSync as zS,writeFileSync as VS}from"node:fs";import{dirname as qS}from"node:path";function _(e){let t=process.env.TS_CLOUD_AUTH_ENCRYPTION_KEY?.trim();if(t)return t;let r=A(e,"auth-encryption-key");try{if(FS(r)){let i=zS(r,"utf8").trim();if(i)return i}}catch{}let n=BS(32).toString("base64url");try{US(qS(r),{recursive:!0,mode:448}),VS(r,`${n}
33
+ redirect_uri, return_path, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[i,e,yi(o),this.encrypt(s),this.encrypt(c),t,r,a,l]),{transaction:this.getOidcTransaction(i),state:o,nonce:s,verifier:c}}getOidcTransaction(e){let t=this.controlPlane.database.query("SELECT * FROM auth_oidc_transactions WHERE id = ?").get(e);return t?wg(t,this.now()):void 0}consumeOidcTransaction(e,t){return this.controlPlane.transaction(()=>{let r=this.controlPlane.database.query("SELECT * FROM auth_oidc_transactions WHERE provider_id = ? AND state_hash = ?").get(e,yi(t));if(!r)throw Error("OIDC transaction is invalid");let n=wg(r,this.now());if(n.state!=="pending")throw Error(`OIDC transaction is ${n.state}`);if(this.controlPlane.database.run("UPDATE auth_oidc_transactions SET consumed_at = ? WHERE id = ? AND consumed_at IS NULL AND expires_at > ?",[this.now(),n.id,this.now()]).changes!==1)throw Error("OIDC transaction is no longer available");return{transaction:this.getOidcTransaction(n.id),nonce:this.decrypt(String(r.nonce_ciphertext)),verifier:this.decrypt(String(r.verifier_ciphertext))}})}getOidcSubject(e,t){let r=this.controlPlane.database.query("SELECT * FROM auth_oidc_subjects WHERE provider_id = ? AND subject = ?").get(e,t);return r?LS(r):void 0}linkOidcSubject(e,t,r,n){let i=this.getOidcProvider(e),o=this.getIdentity(t);if(!i||!o)throw Error("OIDC provider or identity was not found");let s=ru(n);if(!r.trim()||r.length>512)throw Error("OIDC subject is invalid");let c=this.getOidcSubject(e,r);if(c&&c.identityId!==t)throw Error("OIDC subject is already linked to another identity");let l=this.now();if(c)return this.run("UPDATE auth_oidc_subjects SET email = ?, last_login_at = ? WHERE id = ?",[s,l,c.id]),this.getOidcSubject(e,r);let a=this.idFn();return this.run("INSERT INTO auth_oidc_subjects (id, provider_id, identity_id, subject, email, linked_at, last_login_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[a,e,t,r,s,l,l]),this.getOidcSubject(e,r)}purgeExpired(){let e=this.now(),t=this.controlPlane.database.run("DELETE FROM auth_action_tokens WHERE expires_at < ? OR consumed_at IS NOT NULL",[e]).changes,r=this.controlPlane.database.run("DELETE FROM auth_sessions WHERE revoked_at IS NOT NULL OR idle_expires_at < ? OR absolute_expires_at < ?",[e,e]).changes;return this.controlPlane.database.run("DELETE FROM auth_mfa_challenges WHERE consumed_at IS NOT NULL OR expires_at < ?",[e]),this.controlPlane.database.run("DELETE FROM auth_oidc_transactions WHERE consumed_at IS NOT NULL OR expires_at < ?",[e]),{actionTokens:t,sessions:r}}}async function ba(e,t){let r=e.notifications?.email?.from;if(!r)return!1;try{let{EmailClient:n}=await import("./chunk-ank4fmbx.js");return await new n({region:e.project.region,defaultFrom:r}).send(t),!0}catch{return!1}}import{randomBytes as BS}from"node:crypto";import{chmodSync as jS,existsSync as FS,mkdirSync as US,readFileSync as zS,writeFileSync as VS}from"node:fs";import{dirname as qS}from"node:path";function _(e){let t=process.env.TS_CLOUD_AUTH_ENCRYPTION_KEY?.trim();if(t)return t;let r=A(e,"auth-encryption-key");try{if(FS(r)){let i=zS(r,"utf8").trim();if(i)return i}}catch{}let n=BS(32).toString("base64url");try{US(qS(r),{recursive:!0,mode:448}),VS(r,`${n}
34
34
  `,{mode:384}),jS(r,384)}catch{}return n}import{constants as JS,createHash as ou,createPublicKey as GS,createVerify as WS,timingSafeEqual as HS}from"node:crypto";var Pg=new Set(["RS256","PS256","ES256"]),Rg=60;function ac(e,t){let r=new URL(e),n=["127.0.0.1","::1","localhost"].includes(r.hostname);if(r.protocol!=="https:"&&!(r.protocol==="http:"&&n))throw Error(`${t} must use HTTPS`);if(r.username||r.password||r.hash)throw Error(`${t} contains unsupported URL components`);return r}function su(e,t){if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`${t} is invalid`);return e}async function au(e,t){if(!e.ok)throw Error(`${t} failed with HTTP ${e.status}`);if(!(e.headers.get("content-type")??"").toLowerCase().includes("application/json"))throw Error(`${t} returned an unsupported content type`);if(Number(e.headers.get("content-length")??0)>1048576)throw Error(`${t} response is too large`);let i=await e.text();if(i.length>1048576)throw Error(`${t} response is too large`);try{return su(JSON.parse(i),t)}catch(o){if(o instanceof Error&&o.message===`${t} is invalid`)throw o;throw Error(`${t} returned invalid JSON`)}}function KS(e,t){let r=ou("sha256").update(e).digest(),n=ou("sha256").update(t).digest();return HS(r,n)}function xg(e){if(!e)return"/";let t=e.trim();if(!t.startsWith("/")||t.startsWith("//")||t.includes("\\")||/[\r\n]/.test(t))return"/";try{let r=new URL(t,"https://local.invalid");return r.origin==="https://local.invalid"?`${r.pathname}${r.search}${r.hash}`:"/"}catch{return"/"}}async function mn(e,t=fetch){let r=ac(e.issuer,"OIDC issuer"),n=new URL(`${r.pathname.replace(/\/$/,"")}/.well-known/openid-configuration`,r.origin),i=await au(await t(n,{headers:{accept:"application/json"},redirect:"error",signal:AbortSignal.timeout(1e4)}),"OIDC discovery");if(i.issuer!==e.issuer)throw Error("OIDC discovery issuer does not match the configured issuer");for(let s of["authorization_endpoint","token_endpoint","jwks_uri"]){if(typeof i[s]!=="string")throw Error(`OIDC discovery is missing ${s}`);ac(i[s],`OIDC ${s}`)}if(Array.isArray(i.response_types_supported)&&!i.response_types_supported.includes("code"))throw Error("OIDC provider does not support authorization code flow");if(Array.isArray(i.code_challenge_methods_supported)&&!i.code_challenge_methods_supported.includes("S256"))throw Error("OIDC provider does not support PKCE S256");let o=Array.isArray(i.id_token_signing_alg_values_supported)?i.id_token_signing_alg_values_supported.filter((s)=>typeof s==="string"):[];if(o.length>0&&!o.some((s)=>Pg.has(s)))throw Error("OIDC provider does not offer a supported ID-token signing algorithm");return i}async function cu(e,t,r,n,i=fetch){let o=e.getOidcProviderBySlug(t);if(!o?.enabled)throw Error("OIDC provider is unavailable");let s=ac(r,"Application origin").origin,c=await mn(o,i),l=`${s}/auth/oidc/${encodeURIComponent(o.slug)}/callback`,a=e.beginOidcTransaction(o.id,l,xg(n)),f=new URL(c.authorization_endpoint);return f.searchParams.set("response_type","code"),f.searchParams.set("client_id",o.clientId),f.searchParams.set("redirect_uri",l),f.searchParams.set("scope",o.scopes.join(" ")),f.searchParams.set("state",a.state),f.searchParams.set("nonce",a.nonce),f.searchParams.set("code_challenge",ou("sha256").update(a.verifier).digest("base64url")),f.searchParams.set("code_challenge_method","S256"),{authorizationUrl:f.href,expiresAt:a.transaction.expiresAt}}function QS(e){if(e.length>32768)throw Error("OIDC ID token is too large");let t=e.split(".");if(t.length!==3||t.some((r)=>!r))throw Error("OIDC ID token is malformed");try{return{header:su(JSON.parse(Buffer.from(t[0],"base64url").toString("utf8")),"OIDC ID-token header"),claims:su(JSON.parse(Buffer.from(t[1],"base64url").toString("utf8")),"OIDC ID-token claims"),signingInput:`${t[0]}.${t[1]}`,signature:Buffer.from(t[2],"base64url")}}catch(r){if(r instanceof Error&&r.message.startsWith("OIDC"))throw r;throw Error("OIDC ID token is malformed")}}async function YS(e,t,r){let n=QS(e),i=typeof n.header.alg==="string"?n.header.alg:"",o=typeof n.header.kid==="string"?n.header.kid:"";if(!Pg.has(i)||!o)throw Error("OIDC ID token uses an unsupported signing key");if(t.id_token_signing_alg_values_supported&&!t.id_token_signing_alg_values_supported.includes(i))throw Error("OIDC ID-token algorithm was not advertised by the provider");let s=await au(await r(t.jwks_uri,{headers:{accept:"application/json"},redirect:"error",signal:AbortSignal.timeout(1e4)}),"OIDC signing-key request");if(!Array.isArray(s.keys))throw Error("OIDC signing-key response is invalid");let c=s.keys.find((E)=>{if(!E||typeof E!=="object"||Array.isArray(E))return!1;let D=E;return D.kid===o&&(!D.alg||D.alg===i)&&(!D.use||D.use==="sig")});if(!c)throw Error("OIDC ID-token signing key was not found");let l=GS({key:c,format:"jwk"}),a=WS("SHA256").update(n.signingInput).end();if(!(i==="PS256"?a.verify({key:l,padding:JS.RSA_PKCS1_PSS_PADDING,saltLength:32},n.signature):i==="ES256"?a.verify({key:l,dsaEncoding:"ieee-p1363"},n.signature):a.verify(l,n.signature)))throw Error("OIDC ID-token signature is invalid");return n.claims}function XS(e,t,r,n){if(e.iss!==t.issuer)throw Error("OIDC ID-token issuer is invalid");let i=typeof e.aud==="string"?[e.aud]:Array.isArray(e.aud)?e.aud.filter((l)=>typeof l==="string"):[];if(!i.includes(t.clientId))throw Error("OIDC ID-token audience is invalid");if((i.length>1||e.azp!==void 0)&&e.azp!==t.clientId)throw Error("OIDC ID-token authorized party is invalid");let o=Math.floor(n.getTime()/1000);if(typeof e.exp!=="number"||e.exp<o-Rg)throw Error("OIDC ID token is expired");if(typeof e.iat!=="number"||e.iat>o+Rg)throw Error("OIDC ID-token issued-at time is invalid");if(typeof e.nonce!=="string"||!KS(e.nonce,r))throw Error("OIDC ID-token nonce is invalid");if(typeof e.sub!=="string"||!e.sub||e.sub.length>512)throw Error("OIDC ID-token subject is invalid");if(e.email_verified!==!0||typeof e.email!=="string")throw Error("OIDC provider did not return a verified email address");let s=e.email.trim().toLowerCase();if(s.length>254||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s))throw Error("OIDC provider returned an invalid email address");let c=s.split("@")[1];if(!c||!t.allowedDomains.includes(c))throw Error("OIDC email domain is not allowed for this organization");return{provider:t,subject:e.sub,email:s,name:typeof e.name==="string"?e.name.slice(0,120):void 0,claims:e}}async function du(e,t,r=fetch){let n=e.getOidcProviderBySlug(t.providerSlug);if(!n?.enabled)throw Error("OIDC provider is unavailable");if(!t.state||t.state.length>512||!t.code||t.code.length>4096)throw Error("OIDC callback is incomplete");let i=ac(t.origin,"Application origin").origin,o=e.consumeOidcTransaction(n.id,t.state),s=`${i}/auth/oidc/${encodeURIComponent(n.slug)}/callback`;if(o.transaction.redirectUri!==s)throw Error("OIDC callback redirect URI does not match the original request");let{clientSecret:c}=e.getOidcProviderCredentials(n.id),l=await mn(n,r),a=new URLSearchParams({grant_type:"authorization_code",code:t.code,redirect_uri:o.transaction.redirectUri,code_verifier:o.verifier}),f={accept:"application/json","content-type":"application/x-www-form-urlencoded"},E=l.token_endpoint_auth_methods_supported??["client_secret_basic"];if(E.includes("client_secret_basic")){let G=(ee)=>new URLSearchParams({value:ee}).toString().slice(6),Y=`${G(n.clientId)}:${G(c)}`;f.authorization=`Basic ${Buffer.from(Y).toString("base64")}`}else if(E.includes("client_secret_post"))a.set("client_id",n.clientId),a.set("client_secret",c);else throw Error("OIDC provider does not support a configured client authentication method");let D=await au(await r(l.token_endpoint,{method:"POST",headers:f,body:a,redirect:"error",signal:AbortSignal.timeout(1e4)}),"OIDC token exchange");if(typeof D.id_token!=="string")throw Error("OIDC token response did not include an ID token");let N=await YS(D.id_token,l,r);return{identity:XS(N,n,o.nonce,t.now??new Date),returnPath:o.transaction.returnPath}}import{createHash as ZS,randomBytes as ev}from"node:crypto";var Og=new Set(se),_g=7776000000,Ng=31536000000,$g=86400000;function Hi(e){return typeof e==="string"?e:void 0}function Dg(e){return ZS("sha256").update(e).digest("hex")}function tv(e){try{let t=JSON.parse(String(e));return Array.isArray(t)?t.filter((r)=>typeof r==="string"&&Og.has(r)):[]}catch{return[]}}function rv(e){let t=String(e.scope_type);return t==="organization"?{type:t}:{type:t,id:String(e.scope_id)}}function uu(e){let t=Hi(e.disabled_at);return{id:String(e.id),organizationId:String(e.organization_id),actorId:String(e.actor_id),slug:String(e.slug),name:String(e.name),description:Hi(e.description),createdByActorId:Hi(e.created_by_actor_id),disabledAt:t,createdAt:String(e.created_at),updatedAt:String(e.updated_at),state:t?"disabled":"active"}}function lu(e,t){let r=Hi(e.revoked_at),n=String(e.expires_at);return{id:String(e.id),serviceAccountId:String(e.service_account_id),name:String(e.name),prefix:String(e.token_prefix),capabilities:tv(e.capabilities),scope:rv(e),expiresAt:n,lastUsedAt:Hi(e.last_used_at),lastNetworkHint:Hi(e.last_network_hint),revokedAt:r,rotatedFromTokenId:Hi(e.rotated_from_token_id),createdByActorId:Hi(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at),state:r?"revoked":n<=t?"expired":"active"}}function nv(e){let t={};try{t=JSON.parse(String(e.response_body))}catch{}return{id:String(e.id),tokenId:String(e.token_id),key:String(e.idempotency_key),requestHash:String(e.request_hash),operationId:Hi(e.operation_id),responseStatus:Number(e.response_status),responseBody:t,expiresAt:String(e.expires_at),createdAt:String(e.created_at)}}class je{controlPlane;nowFn;idFn;constructor(e,t={}){this.controlPlane=e;this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID())}now(){return this.nowFn().toISOString()}run(e,t){this.controlPlane.database.run(e,t)}createServiceAccount(e){if(!this.controlPlane.getOrganization(e.organizationId))throw Error("Service-account organization was not found");let t=e.slug.trim().toLowerCase();if(!/^[a-z0-9][a-z0-9-]{1,47}$/.test(t))throw Error("Service-account slug must be 2-48 lowercase letters, numbers or dashes");let r=e.name.trim().slice(0,100);if(!r)throw Error("Service-account name is required");let n=this.controlPlane.createActor({kind:"service_account",externalId:`service-account:${e.organizationId}:${t}`,displayName:r,metadata:{source:"api",serviceAccountSlug:t}}),i=this.idFn(),o=this.now();this.run(`INSERT INTO service_accounts (id, organization_id, actor_id, slug, name, description, created_by_actor_id, created_at, updated_at)
35
35
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[i,e.organizationId,n.id,t,r,e.description?.trim().slice(0,500)||null,e.createdByActorId??null,o,o]);let s=this.controlPlane.createMembership({organizationId:e.organizationId,actorId:n.id,roleTemplate:e.roleTemplate,scope:e.scope,source:"manual",performedByActorId:e.createdByActorId}),c=e.scope??{type:"organization"};return this.controlPlane.appendEvent({organizationId:e.organizationId,actorId:e.createdByActorId,type:"api.service_account.created",payload:{serviceAccountId:i,roleTemplate:e.roleTemplate,scope:{type:c.type,id:c.id??null}}}),{serviceAccount:this.getServiceAccount(i),membership:s}}getServiceAccount(e){let t=this.controlPlane.database.query("SELECT * FROM service_accounts WHERE id = ?").get(e);return t?uu(t):void 0}getServiceAccountBySlug(e,t){let r=this.controlPlane.database.query("SELECT * FROM service_accounts WHERE organization_id = ? AND slug = ? COLLATE NOCASE").get(e,t.trim());return r?uu(r):void 0}listServiceAccounts(e,t={}){return this.controlPlane.database.query("SELECT * FROM service_accounts WHERE organization_id = ? ORDER BY name COLLATE NOCASE").all(e).map(uu).filter((r)=>t.includeDisabled||r.state==="active")}disableServiceAccount(e,t){let r=this.getServiceAccount(e);if(!r)throw Error("Service account was not found");let n=this.now();return this.controlPlane.transaction(()=>{this.run("UPDATE service_accounts SET disabled_at = ?, updated_at = ? WHERE id = ?",[n,n,e]),this.run("UPDATE api_tokens SET revoked_at = ?, updated_at = ? WHERE service_account_id = ? AND revoked_at IS NULL",[n,n,e]);let i=this.controlPlane.getMembershipForActor(r.organizationId,r.actorId);if(i?.status==="active")this.controlPlane.revokeMembership(i.id)}),this.controlPlane.appendEvent({organizationId:r.organizationId,actorId:t,type:"api.service_account.disabled",payload:{serviceAccountId:e}}),this.getServiceAccount(e)}createToken(e){let t=this.getServiceAccount(e.serviceAccountId);if(!t||t.state!=="active")throw Error("Service account is unavailable");let r=this.controlPlane.getMembershipForActor(t.organizationId,t.actorId);if(!r||r.status!=="active")throw Error("Service-account membership is unavailable");let n=[...new Set(e.capabilities)];if(n.length===0||n.some((D)=>!Og.has(D)))throw Error("API token requires valid explicit capabilities");let i=e.scope??r.scope,o=this.controlPlane.resolveAuthorizationTarget(t.organizationId,i);if(!o)throw Error("API token scope was not found in this organization");for(let D of n)if(!te({membership:r,grants:this.controlPlane.listGrants(r.id),capability:D,target:o}).allowed)throw Error(`Service-account membership does not grant ${D} at the token scope`);let s=e.expiresAt?new Date(e.expiresAt):new Date(this.nowFn().getTime()+_g);if(!Number.isFinite(s.getTime())||s.getTime()<=this.nowFn().getTime()+60000||s.getTime()>this.nowFn().getTime()+Ng)throw Error("API token expiry must be between one minute and one year from now");let c=this.idFn(),l=ev(32).toString("base64url"),a=`tsc_v1.${c}.${l}`,f=`tsc_v1.${c.slice(0,8)}`,E=this.now();return this.run(`INSERT INTO api_tokens (id, service_account_id, name, token_hash, token_prefix, capabilities, scope_type, scope_id,
36
36
  expires_at, rotated_from_token_id, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[c,t.id,e.name.trim().slice(0,100)||"API token",Dg(a),f,JSON.stringify(n.sort()),i.type,i.type==="organization"?null:i.id??null,s.toISOString(),e.rotatedFromTokenId??null,e.createdByActorId??null,E,E]),this.controlPlane.appendEvent({organizationId:t.organizationId,actorId:e.createdByActorId,type:"api.token.created",payload:{serviceAccountId:t.id,tokenId:c,prefix:f,capabilities:n,scope:{type:i.type,id:i.id??null},expiresAt:s.toISOString(),rotatedFromTokenId:e.rotatedFromTokenId??null}}),{token:this.getToken(c),secret:a}}getToken(e){let t=this.controlPlane.database.query("SELECT * FROM api_tokens WHERE id = ?").get(e);return t?lu(t,this.now()):void 0}listTokens(e,t={}){return this.controlPlane.database.query("SELECT * FROM api_tokens WHERE service_account_id = ? ORDER BY created_at DESC").all(e).map((r)=>lu(r,this.now())).filter((r)=>t.includeInactive||r.state==="active")}verifyToken(e,t){let r=/^tsc_v1\.([^.]+)\.[A-Za-z0-9_-]{40,}$/.exec(e);if(!r)return;let n=this.controlPlane.database.query("SELECT * FROM api_tokens WHERE id = ? AND token_hash = ?").get(r[1],Dg(e));if(!n)return;let i=lu(n,this.now()),o=this.getServiceAccount(i.serviceAccountId);if(!o||o.state!=="active"||i.state!=="active")return;let s=this.controlPlane.getActor(o.actorId),c=this.controlPlane.getMembershipForActor(o.organizationId,o.actorId);if(!s||s.disabledAt||!c||c.status!=="active")return;let l=this.now(),a=!i.lastUsedAt||this.nowFn().getTime()-new Date(i.lastUsedAt).getTime()>=3600000;if(this.run("UPDATE api_tokens SET last_used_at = ?, last_network_hint = ?, updated_at = ? WHERE id = ?",[l,t?.slice(0,128)??null,l,i.id]),a)this.controlPlane.appendEvent({organizationId:o.organizationId,actorId:s.id,type:"api.token.used",payload:{serviceAccountId:o.id,tokenId:i.id,prefix:i.prefix}});return{serviceAccount:o,token:this.getToken(i.id),actor:s,membership:c}}rotateToken(e,t){let r=this.getToken(e);if(!r||r.state!=="active")throw Error("Active API token was not found");let n=this.createToken({serviceAccountId:r.serviceAccountId,name:`${r.name} (rotated)`,capabilities:r.capabilities,scope:r.scope,expiresAt:r.expiresAt,createdByActorId:t,rotatedFromTokenId:r.id}),i=this.getServiceAccount(r.serviceAccountId);return this.controlPlane.appendEvent({organizationId:i?.organizationId,actorId:t,type:"api.token.rotated",payload:{serviceAccountId:r.serviceAccountId,previousTokenId:r.id,tokenId:n.token.id}}),n}revokeToken(e,t){let r=this.getToken(e);if(!r)throw Error("API token was not found");if(r.state==="active"){let n=this.now();this.run("UPDATE api_tokens SET revoked_at = ?, updated_at = ? WHERE id = ?",[n,n,e]);let i=this.getServiceAccount(r.serviceAccountId);this.controlPlane.appendEvent({organizationId:i?.organizationId,actorId:t,type:"api.token.revoked",payload:{serviceAccountId:r.serviceAccountId,tokenId:e}})}return this.getToken(e)}getIdempotency(e,t){let r=this.controlPlane.database.query("SELECT * FROM api_idempotency_records WHERE token_id = ? AND idempotency_key = ? AND expires_at > ?").get(e,t,this.now());return r?nv(r):void 0}saveIdempotency(e){if(!/^[A-Za-z0-9._:-]{8,128}$/.test(e.key))throw Error("Idempotency-Key must contain 8-128 safe characters");let t=this.getIdempotency(e.tokenId,e.key);if(t){if(t.requestHash!==e.requestHash)throw Error("Idempotency-Key was already used for a different request");return t}let r=this.idFn(),n=this.now(),i=new Date(this.nowFn().getTime()+$g).toISOString();return this.run(`INSERT INTO api_idempotency_records (id, token_id, idempotency_key, request_hash, operation_id, response_status, response_body, expires_at, created_at)
@@ -474,7 +474,7 @@ data: ${JSON.stringify({cursor:o,at:new Date().toISOString()})}
474
474
  ${c}
475
475
  ${l}`);return null}return n}catch(i){if(n)ys(n,{recursive:!0,force:!0});if(process.env.TSCLOUD_DASHBOARD_VERBOSE)console.warn(`ts-cloud dashboard: live UI build errored; serving the pre-built UI. ${i.message}`);return null}}function fA(e){let t=e.infrastructure?.compute?.managedServices?JSON.parse(JSON.stringify(e.infrastructure.compute.managedServices)):void 0;if(t?.vitess?.password)t.vitess.password="";return{project:{name:e.project?.name,slug:e.project?.slug,region:e.project?.region},provider:e.provider,environments:Object.keys(e.environments??{}),compute:e.infrastructure?.compute?{provider:e.infrastructure.compute.provider,runtime:e.infrastructure.compute.runtime,webServer:e.infrastructure.compute.webServer,proxy:e.infrastructure.compute.proxy?{engine:e.infrastructure.compute.proxy.engine,onDemandTls:e.infrastructure.compute.proxy.onDemandTls,cdn:!!e.infrastructure.compute.proxy.cdn}:void 0,managedServices:t,sshKeys:Dt(da(e)).map((r)=>({name:r.name,type:r.type,fingerprint:r.fingerprint,added:r.added}))}:void 0,sites:Object.fromEntries(Object.entries(e.sites??{}).map(([r,n])=>[r,{domain:n.domain,path:n.path,type:n.type,deploy:n.deploy,root:n.root,port:n.port,ssl:n.ssl}]))}}function wb(e){return[{id:"status",label:"Refresh Cloud Status",description:"Runs the local ts-cloud status checks against configured providers.",command:["status","--env",e],mutates:!1},{id:"doctor",label:"Run Doctor",description:"Checks local tooling, credentials, and provider access.",command:["doctor"],mutates:!1},{id:"security-scan",label:"Security Scan",description:"Runs the pre-deploy scanner from this checkout.",command:["deploy:security-scan","--source",".","--fail-on","critical"],mutates:!1},{id:"deploy",label:"Deploy Environment",description:"Deploys the selected environment from the local checkout.",command:["deploy","--env",e,"--yes"],mutates:!0,confirm:"deploy"}]}function hA(e,t){return wb(t).find((r)=>r.id===e)}function gb(e){if(e.length<=db)return e;return`${e.slice(0,db)}
476
476
 
477
- [output truncated]`}async function mb(e,t,r){let n=e.getReader(),i=new TextDecoder,o="";while(!0){let{done:c,value:l}=await n.read();if(c)break;let a=i.decode(l,{stream:!0});if(o+=a,a)r?.(t,a)}let s=i.decode();if(s)o+=s,r?.(t,s);return o}async function ap(e,t){let r=Bun.spawn([process.execPath,t.cliEntry,...e.command],{cwd:t.cwd,stdout:"pipe",stderr:"pipe",env:{...process.env,...t.env}}),n=()=>{try{r.kill()}catch{}};if(t.signal?.aborted)n();else t.signal?.addEventListener("abort",n,{once:!0});try{let[i,o,s]=await Promise.all([mb(r.stdout,"stdout",t.onOutput),mb(r.stderr,"stderr",t.onOutput),r.exited]);return{action:e.id,command:["cloud",...e.command].join(" "),exitCode:s,ok:s===0,stdout:gb(i),stderr:gb(o)}}finally{t.signal?.removeEventListener("abort",n)}}function yA(){return Object.entries(process.env).filter(([e,t])=>!!t&&t.length>=8&&/(?:secret|token|password|passwd|private|credential|api.?key|access.?key)/i.test(e)).map(([,e])=>e)}var bA=new Set(["/server/sites","/server/deployments","/server/logs","/integrations","/applications/new","/applications/compose","/operations/queue","/operations/previews","/operations/releases","/operations/workloads","/operations/observability","/operations/alerts","/operations/jobs","/data/backups","/account/security","/security","/access-denied"]);function SA(e){let t=Ga(e);if(t&&t!==".html")return!1;let r=e.replace(/\.html$/,"").replace(/\/+$/,"")||"/";if(r==="/")return!1;return!bA.has(r)}var vA={"/":"runtime:read","/server/activity":"audit:read","/server/sites":"project:read","/server/deployments":"deployments:read","/server/logs":"runtime:logs","/server/metrics":"runtime:read","/server/services":"runtime:read","/data/backups":"backups:read","/data/volumes":"data:read","/server/fleet":"fleet:read","/server/capacity":"fleet:read","/server/actions":"runtime:restart","/server/database":"data:read","/server/firewall":"fleet:read","/infrastructure/topology":"fleet:read","/server/security":"security:read","/security":"security:read","/integrations":"sources:read","/applications/new":"applications:read","/applications/compose":"applications:read","/operations/queue":"deployments:read","/operations/previews":"deployments:read","/operations/releases":"deployments:read","/operations/regions":"deployments:read","/operations/maintenance":"deployments:read","/operations/workloads":"runtime:read","/operations/observability":"runtime:logs","/operations/alerts":"runtime:read","/operations/jobs":"automation:read","/operations/configuration":"config:read","/server/ssh-keys":"fleet:read","/server/terminal":"runtime:terminal","/server/team":"users:read","/account/security":"project:read","/account/automation":"users:read","/serverless":"project:read","/serverless/deployments":"deployments:read","/serverless/logs":"runtime:logs","/serverless/metrics":"runtime:read","/serverless/traces":"runtime:read","/serverless/functions":"config:read","/serverless/queues":"data:read","/serverless/data":"data:read","/serverless/assets":"project:read","/serverless/secrets":"secrets:read","/serverless/firewall":"fleet:read","/serverless/alarms":"runtime:read","/serverless/cost":"project:read"};function fb(e,t){if(t.role==="admin")return!0;let r=Ga(e);if(r&&r!==".html")return!0;if(t.organizationSource==="legacy")return!SA(e);let n=e.replace(/\.html$/,"").replace(/\/+$/,"")||"/";if(n==="/access-denied")return!0;let i=vA[n];return!!i&&!!t.capabilities?.includes(i)}function wA(e,t){let r=decodeURIComponent(t).replace(/^\/+/,""),i=zT(r===""?"index.html":r);if(i.startsWith("..")||i.includes("/../"))return null;let o=Et(e,i);if(go(o)&&!Sb(o).isDirectory())return o;if(!Ga(o)&&go(`${o}.html`))return`${o}.html`;if(!Ga(o)&&go(Et(o,"index.html")))return Et(o,"index.html");return null}async function hb(e,t){let r=wA(e,t);if(!r){let o=Et(e,"404.html");if(go(o))return new Response(await Ui(o),{status:404,headers:{"content-type":"text/html; charset=utf-8"}});return Rd("Not found",404)}if(Sb(r).isDirectory())return Rd("Not found",404);let n=await Ui(r),i=YT[Ga(r)]??"application/octet-stream";return new Response(n,{headers:{"content-type":i}})}var Ad=["observe","backup","restore","restart","resize","version","rotate","expose","delete","logs","slow_queries","users","databases"],yb=new WeakMap;async function bb(e){let t=yb.get(e);if(t)return t;let r=await import("./chunk-x2r1zm2r.js"),n=new r.SpendStore(e),i={store:n,service:new r.SpendService(n),gate:new r.SpendGate(e)};return yb.set(e,i),i}async function ir(e={}){QT();let t=e.cwd??process.cwd(),r=e.host??WT,n=e.port??HT,i=e.cliEntry??process.argv[1];if(e.box)process.env.TS_CLOUD_DASHBOARD_BOX="1";await oA(t);let o=e.config??await Pi(),s=process.env.TS_CLOUD_DASHBOARD_DB_PASSWORD,c=C(o);if(s&&c&&!c.password)c.password=s;let l=o.infrastructure?.compute?.managedServices?.vitess;if(s&&l&&typeof l==="object"&&!l.password)l.password=s;let a=y(t,o);if(a.reconciliation.failed>0)console.warn(` ts-cloud dashboard: marked ${a.reconciliation.failed} orphaned operation(s) as failed after restart.`);let f=Object.keys(o.environments??{}),E=nA(o,e.environment),D=sA(t),N=await ms(o,E),G=new Map([[E,N]]),Y=new Map([[E,Date.now()]]),ee=new Map([[E,Date.now()]]),oe=new Map,be=Math.min(300000,Math.max(5000,Number(process.env.TS_CLOUD_DASHBOARD_REFRESH_MS)||30000)),re=Math.min(1800000,Math.max(60000,Number(process.env.TS_CLOUD_DASHBOARD_SITE_REFRESH_MS)||300000)),_e=H(o)!=="serverless",tt=(I)=>{let Te=G.get(I);if(Te&&!ub(Y.get(I),Date.now(),be))return Promise.resolve(Te);let Ne=oe.get(I);if(Ne)return Ne;let Ce=!_e||ub(ee.get(I),Date.now(),re),qe=ms(o,I,{includeSiteHealth:Ce}).then((ht)=>{let L=G.get(I),Yr=Ce?ht:pA(L,ht);if(G.set(I,Yr),Y.set(I,Date.now()),Ce)ee.set(I,Date.now());if(L?._serverReachable!==Yr._serverReachable||L?._metricsStatus!==Yr._metricsStatus||(L?.sitesDetail?.length??0)!==(Yr.sitesDetail?.length??0))hi();return Yr}).finally(()=>oe.delete(I));return oe.set(I,qe),qe},Ue=ao(t),Gt=process.env.TS_CLOUD_DASHBOARD_TELEMETRY?.trim();if(e.box&&Gt!=="0"&&(Gt==="1"||!o.cloud?.attachTo)){let I=!1,Te=Date.now()+300000,Ne=async()=>{if(I)return;I=!0;try{let qe=Date.now(),ht=qe>=Te;if(ht)Te=qe+300000;let L=a.environments.get(E);await Hn({controlPlane:a.store,projectId:a.project.id,environmentId:L?.id,config:o,environment:E,force:!0,lightweight:!0,includeSiteHealth:ht})}catch(qe){if(e.verbose)console.warn(` ts-cloud dashboard: background telemetry collection failed: ${qe instanceof Error?qe.message:String(qe)}`)}finally{I=!1}};Ne(),setInterval(()=>void Ne(),60000).unref?.()}let ke=new Map,Ye=new Map,At=new Set,Ti=0;function mo(I,Te){if(I.role==="admin"&&!a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`))return I;let Ne=a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`),Ce=Ne?a.store.getMembershipForActor(a.organization.id,Ne.id):void 0;if(!Ce||Ce.status!=="active")return{...I,role:"member",sites:{},capabilities:[]};let qe=a.store.listGrants(Ce.id),ht=a.store.resolveAuthorizationTarget(a.organization.id,Ce.scope)??a.store.resolveAuthorizationTarget(a.organization.id,{type:"project",id:a.project.id}),L=sn({membership:Ce,grants:qe,target:ht});if(Ce.roleTemplate==="owner"||Ce.roleTemplate==="admin")return{...I,role:"admin",sites:{},organizationRole:Ce.roleTemplate,organizationSource:Ce.source,capabilities:L};let Yr=a.environments.get(Te),or={};for(let Xe of a.store.listResources(a.project.id,Yr?.id).filter((ct)=>ct.kind==="application")){let ct=a.store.resolveAuthorizationTarget(a.organization.id,{type:"resource",id:Xe.id});if(!ct||!te({membership:Ce,grants:qe,capability:"project:read",target:ct}).allowed)continue;or[Xe.slug]=te({membership:Ce,grants:qe,capability:"config:write",target:ct}).allowed?"owner":"collaborator"}return{...I,role:"member",sites:or,organizationRole:Ce.roleTemplate,organizationSource:Ce.source,capabilities:L}}function hi(){Ti+=1,ke.clear();for(let I of At)ys(I,{recursive:!0,force:!0});At.clear()}let Ai=(I,Te)=>`${Te}:${I.role==="admin"?"admin":`member:${Object.entries(I.sites).sort(([Ne],[Ce])=>Ne.localeCompare(Ce)).map(([Ne,Ce])=>`${Ne}=${Ce}`).join(",")}`}:${[...I.capabilities??[]].sort().join(",")}`;async function ki(I,Te){let Ne=mo(I,Te),Ce=Ai(Ne,Te),qe=ke.get(Ce);if(qe)return qe;let ht=Ye.get(Ce);if(ht)return ht;let L=Ti,Yr=(async()=>{let or=G.get(Te)??await ms(o,Te);G.set(Te,or);let Xe={...Hl(or,{user:Ne,slug:o.project.slug}),viewer:{role:Ne.role,organizationRole:Ne.organizationRole,organizationSource:Ne.organizationSource,capabilities:Ne.capabilities??[]}},ct=await mA(t,Xe);if(ct&&L!==Ti)return ys(ct,{recursive:!0,force:!0}),Ue?.uiRoot;if(ct)At.add(ct);let Nr=ct??Ue?.uiRoot;if(Nr)ke.set(Ce,Nr);return Nr})();Ye.set(Ce,Yr);try{return await Yr}finally{Ye.delete(Ce)}}let Ri=await ki({username:"",passwordHash:"",role:"admin",sites:{}},E);if(!Ri)throw Error("ts-cloud dashboard UI not found. Run `bun run build` in ts-cloud or reinstall the package.");let Q=new WeakMap,ge=process.env.TS_CLOUD_DASHBOARD_TERMINAL!=="0",Ee=process.env.TS_CLOUD_DASHBOARD_AUTH==="0";if(Ee&&e.box)throw Error("TS_CLOUD_DASHBOARD_AUTH=0 is refused in box mode: the dashboard is internet-facing there, and disabling auth would expose a root shell.");let Re=!Ee,$t=ny(t),Ht=Re?ay(t,process.env.TS_CLOUD_UI_USERNAME?.trim()||"admin"):void 0,Ie=new xe(a.store,{encryptionKey:_(t)}),lt=new je(a.store),rt=new Nt(a.store),Ve=new Yt(a.store,{encryptionKey:_(t)}),Qr=new $n(a.store),bs=new Ln(a.store,{cwd:t}),xi=new On(a.store,{encryptionKey:_(t)}),kt=new b(a.store,{workerId:`dashboard:${process.pid}`}),Lt=new Xt(a.store),qi=new Qt(a.store,_(t)),fo=new Tr(a.store),Wa=new kr(Lt,kt,qi),yo=o.project?.region??"us-east-1",dp=_(t),Gn=new Ar(fo,{encryptionKey:dp,backends:[new Tt(a.store,dp),new Er(new K(yo),yo),new wr(new ze(yo),yo),new Cr]});await nn(Gn,a,o);let Pd=new me(yo),Ib={aws_rds:new An(new Dn(Pd)),aws_aurora:new In(new kn(Pd)),aws_elasticache:new Rn(new _n(new ne(yo))),server:new Pn(new it),container:new Nn(new it)},up=(I)=>Ib[I.provider],sr=new Vn(a.store),Bo=new Br(sr,kt),lp=new zn(qi),Cb={managed_database:new yu(Lt,Pd),logical_database:new Iu(Lt,qi),volume:new Eu,files:new wu(t),control_plane:new Au(a.store,t),infrastructure:new Ru(new Sa(yo))},Eb=(I)=>Cb[I.resourceKind],Tb=(I)=>I.provider==="aws_backup"?void 0:lp,xd=new pt(a.store),Dd=[new _t,new Kr(A(t,"volumes"))],Ji=new Gr(xd,Dd,kt),ua=new Pe(a.store),Oi=new hn(ua,[new nt("aws"),new nt("hetzner"),new nt("ssh")],kt),bo=new yn(a.store),pp=new Sn(bo,ua),jo=new bn(a.store),gp=new vn(jo,kt),Gi=new Tn(a.store),Od=new En(Gi,kt),mp=["releases","artifacts","operations","logs","previews","snapshots","orphaned_resources"].map((I)=>new wn(I,a.store,a.project.id,a.organization.id)),Rr=new Mr(a.store),fp=new jn(Rr,{queue:kt}),Kt=new Ge(a.store),So=new We(a.store),ai=new ot(a.store),Qe=new gt(a.store,{encryptionKey:_(t)}),Ab=()=>bb(a.store);for(let I of a.environments.values())Ur(Rr,o,{organization:a.organization,project:a.project,environment:I,resources:a.store.listResources(a.project.id,I.id)});let ci=new mr(Qe,{emailImpl:async(I)=>{let{email:Te}=await import("./chunk-8hnph1yy.js");return Te.send(I)}}),hp=async(I)=>{let Te=Jr(Qe,a.project.id,I),Ne=[];for(let Ce of Te.filter((qe)=>qe.notify&&qe.alert))Ne.push(...await ci.deliverAll(ci.enqueue(a.organization.id,Ce.alert,Ce.transition)));return Ne.push(...await ci.deliverAll(ci.enqueueRemindersAndEscalations(a.organization.id,Qe.listAlerts(a.project.id,{environmentId:I,states:["firing"]})))),Ne.push(...await ci.retryDue()),{evaluations:Te,deliveries:Ne}},_d=!1,kb=async()=>{if(_d)return;_d=!0;try{for(let I of a.environments.values())for(let Te of Qe.listHealthChecks(a.project.id,I.id).filter((Ne)=>Ne.enabled)){let Ne=Qe.listHealthResults(Te.id,1)[0];if(Ne&&Date.now()-new Date(Ne.checkedAt).getTime()<Te.intervalSeconds*1000)continue;let Ce=await new Me(Qe).runAndEvaluate(Te);for(let qe of Ce.evaluations.filter((ht)=>ht.notify&&ht.alert))await ci.deliverAll(ci.enqueue(a.organization.id,qe.alert,qe.transition))}}finally{_d=!1}},yp=setInterval(()=>{for(let I of a.environments.values())hp(I.id).catch((Te)=>console.error("ts-cloud alert evaluation failed:",Te))},60000);yp.unref?.();let bp=setInterval(()=>{kb().catch((I)=>console.error("ts-cloud health check evaluation failed:",I))},30000);bp.unref?.();let Sp=setInterval(()=>{try{fp.tick()}catch(I){console.error("ts-cloud scheduled job evaluation failed:",I)}},30000);Sp.unref?.();let vp=setInterval(()=>{try{Bo.enqueueDue(),Bo.enqueueRetention()}catch(I){console.error("ts-cloud backup policy evaluation failed:",I)}},30000);vp.unref?.(),Kt.cleanup();let wp=setInterval(()=>{try{Kt.cleanup()}catch(I){console.error("ts-cloud preview cleanup failed:",I)}},3600000);wp.unref?.();let Rb=e.queueWorker??!0,Pb=yA(),xb=async(I,Te)=>{let Ce=(I.environmentId?a.store.listEnvironments(I.projectId).find((qe)=>qe.id===I.environmentId):void 0)?.slug??String(E);if(Te.kind==="dashboard_operation"&&Te.operationId){let qe=G.get(Ce)??N,ht=Mn(Te.operationId,o,qe);if(!ht||ht.danger||!["scheduler","backup","worker"].includes(ht.group))return{ok:!1,stderr:"The allowlisted dashboard operation is no longer available."};let L=await Or(o,Ce,ht);return{ok:L.ok,stdout:L.stdout,stderr:L.stderr??L.error,retryable:/temporar|unavailable|timeout|network/i.test(L.stderr??L.error??""),output:{command:L.command??null,operation:L.operation}}}if(Te.kind==="serverless_scheduler"){let qe=await rp(o,Ce,"run");return{ok:qe.ok,stdout:qe.stdout,stderr:qe.error,retryable:/temporar|unavailable|timeout|network/i.test(qe.error??""),output:{command:qe.command??null,operation:"serverless_scheduler"}}}return{ok:!1,stderr:`No safe executor is configured for ${Te.kind}.`}},Ha=Rb?new ts(kt,{...Ba({store:a.store,execute:async(I,Te)=>{let Ne=Te.operation.input&&typeof Te.operation.input==="object"&&!Array.isArray(Te.operation.input)?Te.operation.input:{},Ce=Ne.source&&typeof Ne.source==="object"?Ne.source:void 0,qe=t,ht,L,Yr;try{if(Ce?.bindingId&&Ce?.connectionId&&Ce?.commitSha){let Xe=Ve.getBinding(String(Ce.bindingId)),ct=Ve.getConnection(String(Ce.connectionId));if(!Xe||!ct||Xe.connectionId!==ct.id)throw Error("Queued source binding is no longer available");let yr=(Xe.repositoryId?Ve.getRepository(Xe.repositoryId):Ve.listRepositories(ct.id).find((Is)=>Is.fullName.toLowerCase()===Xe.repositoryFullName.toLowerCase()))?.cloneUrl;if(!yr&&ct.provider==="generic_ssh")yr=`git@${new URL(ct.host).hostname}:${Xe.repositoryFullName}.git`;if(!yr)yr=new URL(`/${Xe.repositoryFullName}.git`,ct.host.endsWith("/")?ct.host:`${ct.host}/`).href;let Se=Xe.deployKeyId?Ve.getDeployKey(Xe.deployKeyId):void 0,Bt=Se&&Xe.deployKeyId?{...Se,privateKey:Ve.getDeployPrivateKey(Xe.deployKeyId)}:void 0;if(["github","gitlab","bitbucket","gitea"].includes(ct.provider)&&I.target.previewId){let Is=Eo(ct,Ve.getCredential(ct.id)),ue=Kt.previews.getInstance(I.target.previewId);Yr=async(di,Za)=>{try{await Is.setCommitStatus(Xe.repositoryFullName,String(Ce.commitSha),{state:di,url:ue?.url,description:Za})}catch(Es){Te.log(`Could not publish source status: ${Es instanceof Error?Es.message:String(Es)}`,{stream:"stderr"})}},await Yr("pending",`Preview deployment started for ${String(Ce.commitSha).slice(0,12)}`)}ht=cp(Et(kd(),"ts-cloud-queued-source-")),Te.log(`Checking out immutable source commit ${Ce.commitSha}.`,{stream:"system"}),qe=(await Qd({remote:yr,binding:Xe,destination:Et(ht,"checkout"),ref:String(Ce.branch??Xe.defaultBranch),commitSha:String(Ce.commitSha)},{credential:Ve.getCredential(ct.id),deployKey:Bt})).directory}if(Te.operation.kind!=="preview.destroy"){let Xe=I.target.previewId?Kt.previews.getInstance(I.target.previewId):void 0,ct=Xe?Kt.previews.getDefinition(Xe.definitionId):void 0,Nr=Te.operation.resourceId?a.store.getResource(Te.operation.resourceId):void 0;if(L=await Gn.resolve({projectId:a.project.id,environmentId:Te.operation.environmentId,resourceId:Te.operation.resourceId,functionId:Nr?.kind==="function"?Nr.id:void 0,previewId:Xe?.id,trustedPreview:!!Xe&&!Xe.fork,allowedPreviewSecrets:ct?.inheritedSecrets}),L.warnings.some((yr)=>yr.code==="missing_required"))throw Error(`Required deployment configuration is unavailable: ${L.warnings.filter((yr)=>yr.code==="missing_required").map((yr)=>yr.key).join(", ")}`);if(Te.operation.resourceId)for(let yr of Object.values(L.entries))fo.setDependency({entryId:yr.id,resourceId:Te.operation.resourceId,injectionTarget:"environment",required:yr.required,requiresRedeploy:!0});Te.log(`Resolved configuration ${L.configurationHash.slice(0,18)} for ${Object.keys(L.values).length} keys.`,{stream:"system"})}let or=await ap(I,{cwd:qe,cliEntry:i,signal:Te.signal,env:L?.values,onOutput:(Xe,ct)=>Te.log(ct,{stream:Xe,step:"execute",secrets:[...Pb,...Object.entries(L?.entries??{}).filter(([,Nr])=>Nr.kind==="secret").map(([Nr])=>L.values[Nr]).filter(Boolean)]})});if(or.ok&&Te.operation.resourceId&&L)for(let Xe of Object.values(L.entries))fo.setDependency({entryId:Xe.id,resourceId:Te.operation.resourceId,injectionTarget:"environment",required:Xe.required,requiresRedeploy:!1,lastDeployedVersion:Xe.version});return await Yr?.(or.ok?"success":"failure",or.ok?`Preview is ready at ${String(Ce?.commitSha).slice(0,12)}`:`Preview deployment failed at ${String(Ce?.commitSha).slice(0,12)}`),or}catch(or){throw await Yr?.("error",`Preview deployment could not complete at ${String(Ce?.commitSha).slice(0,12)}`),or}finally{if(ht)ys(ht,{recursive:!0,force:!0})}}}),...Vg({store:Rr,executor:xb}),...em({store:Lt,secrets:qi,resolveAdapter:up}),...Uf(ua,Oi.drivers),...ch(jo,[new Cl("aws","AWS regional execution requires an injected AwsRegionalTransport; topology and plans were preserved without provider mutation.")]),...eh({store:Gi,cleanup:mp}),...Ua(xd,Dd),...Yg({store:sr,queue:kt,resolveSource:Eb,resolveDestination:Tb,validateHealth:async(I,Te)=>{if(!I.healthCheckId)return{healthy:!0,mode:"adapter"};let Ne=Qe.getHealthCheck(I.healthCheckId);if(!Ne||Ne.projectId!==I.projectId)return{healthy:!1,error:"Configured restore health check was not found."};let Ce=await new Me(Qe).runAndEvaluate(Ne);return{healthy:Ce.result.status==="healthy",healthCheckId:Ne.id,healthResultId:Ce.result.id,target:Te}}}),...Qp({store:a.store,resolveDriver:e.releaseDriver??((I)=>({name:`${a.store.getResource(I.resourceId)?.provider??"provider"} release driver`,capability:()=>({strategy:I.strategy,supported:!1,explanation:"This dashboard process has no immutable activation driver configured for the target provider.",capacityMultiplier:1,costImpact:"none",rollback:"The previous release remains preserved; configure a release driver before retrying."}),activate:async()=>{throw Error("Immutable activation driver is not configured")},rollback:async()=>{throw Error("Immutable rollback driver is not configured")}})),resolveHealthGate:async(I,Te)=>{let Ne=Qe.listHealthChecks(Te.projectId,Te.environmentId).find((qe)=>qe.enabled&&qe.name===I&&(!qe.resourceId||qe.resourceId===Te.resourceId));if(!Ne)return{healthy:!1,message:`Named health gate ${I} was not found for this release.`};let Ce=await new Me(Qe).runAndEvaluate(Ne);return{healthy:Ce.result.status==="healthy",evidence:{healthCheckId:Ne.id,healthResultId:Ce.result.id,status:Ce.result.status,timings:Ce.result.timings},message:Ce.result.message}}})},{parallelism:e.queueParallelism??(Number(process.env.TS_CLOUD_QUEUE_PARALLELISM)||8),onError:(I)=>console.error("ts-cloud deployment queue worker failed:",I)}):void 0;if(Un(a),dd(rt,le(a,String(E)),N),Ht)ud(a,Ht.users),uy(Ie,a,Ht.users);let Ut=cy({cwd:t,enabled:Re,secret:$t,authentication:Ie,authorization:{store:a.store,organizationId:a.organization.id,projectId:a.project.id,defaultEnvironment:String(E)}}),cr=new Al,Ip=setInterval(()=>cr.sweep(),60000);Ip.unref?.();let Ka=new za,Nd=new za(3,900000,900000),Qa=new za(8,900000,900000),Cp=setInterval(()=>Ka.prune(),300000),Ep=setInterval(()=>Nd.prune(),300000),Tp=setInterval(()=>Qa.prune(),300000);if(Cp.unref?.(),Ep.unref?.(),Tp.unref?.(),Re){if(Ht?.generated)console.warn(`
477
+ [output truncated]`}async function mb(e,t,r){let n=e.getReader(),i=new TextDecoder,o="";while(!0){let{done:c,value:l}=await n.read();if(c)break;let a=i.decode(l,{stream:!0});if(o+=a,a)r?.(t,a)}let s=i.decode();if(s)o+=s,r?.(t,s);return o}async function ap(e,t){let r=Bun.spawn([process.execPath,t.cliEntry,...e.command],{cwd:t.cwd,stdout:"pipe",stderr:"pipe",env:{...process.env,...t.env}}),n=()=>{try{r.kill()}catch{}};if(t.signal?.aborted)n();else t.signal?.addEventListener("abort",n,{once:!0});try{let[i,o,s]=await Promise.all([mb(r.stdout,"stdout",t.onOutput),mb(r.stderr,"stderr",t.onOutput),r.exited]);return{action:e.id,command:["cloud",...e.command].join(" "),exitCode:s,ok:s===0,stdout:gb(i),stderr:gb(o)}}finally{t.signal?.removeEventListener("abort",n)}}function yA(){return Object.entries(process.env).filter(([e,t])=>!!t&&t.length>=8&&/(?:secret|token|password|passwd|private|credential|api.?key|access.?key)/i.test(e)).map(([,e])=>e)}var bA=new Set(["/server/sites","/server/deployments","/server/logs","/integrations","/applications/new","/applications/compose","/operations/queue","/operations/previews","/operations/releases","/operations/workloads","/operations/observability","/operations/alerts","/operations/jobs","/data/backups","/account/security","/security","/access-denied"]);function SA(e){let t=Ga(e);if(t&&t!==".html")return!1;let r=e.replace(/\.html$/,"").replace(/\/+$/,"")||"/";if(r==="/")return!1;return!bA.has(r)}var vA={"/":"runtime:read","/server/activity":"audit:read","/server/sites":"project:read","/server/deployments":"deployments:read","/server/logs":"runtime:logs","/server/metrics":"runtime:read","/server/services":"runtime:read","/data/backups":"backups:read","/data/volumes":"data:read","/server/fleet":"fleet:read","/server/capacity":"fleet:read","/server/actions":"runtime:restart","/server/database":"data:read","/server/firewall":"fleet:read","/infrastructure/topology":"fleet:read","/server/security":"security:read","/security":"security:read","/integrations":"sources:read","/applications/new":"applications:read","/applications/compose":"applications:read","/operations/queue":"deployments:read","/operations/previews":"deployments:read","/operations/releases":"deployments:read","/operations/regions":"deployments:read","/operations/maintenance":"deployments:read","/operations/workloads":"runtime:read","/operations/observability":"runtime:logs","/operations/alerts":"runtime:read","/operations/jobs":"automation:read","/operations/configuration":"config:read","/server/ssh-keys":"fleet:read","/server/terminal":"runtime:terminal","/server/team":"users:read","/account/security":"project:read","/account/automation":"users:read","/serverless":"project:read","/serverless/deployments":"deployments:read","/serverless/logs":"runtime:logs","/serverless/metrics":"runtime:read","/serverless/traces":"runtime:read","/serverless/functions":"config:read","/serverless/queues":"data:read","/serverless/data":"data:read","/serverless/assets":"project:read","/serverless/secrets":"secrets:read","/serverless/firewall":"fleet:read","/serverless/alarms":"runtime:read","/serverless/cost":"project:read"};function fb(e,t){if(t.role==="admin")return!0;let r=Ga(e);if(r&&r!==".html")return!0;if(t.organizationSource==="legacy")return!SA(e);let n=e.replace(/\.html$/,"").replace(/\/+$/,"")||"/";if(n==="/access-denied")return!0;let i=vA[n];return!!i&&!!t.capabilities?.includes(i)}function wA(e,t){let r=decodeURIComponent(t).replace(/^\/+/,""),i=zT(r===""?"index.html":r);if(i.startsWith("..")||i.includes("/../"))return null;let o=Et(e,i);if(go(o)&&!Sb(o).isDirectory())return o;if(!Ga(o)&&go(`${o}.html`))return`${o}.html`;if(!Ga(o)&&go(Et(o,"index.html")))return Et(o,"index.html");return null}async function hb(e,t){let r=wA(e,t);if(!r){let o=Et(e,"404.html");if(go(o))return new Response(await Ui(o),{status:404,headers:{"content-type":"text/html; charset=utf-8"}});return Rd("Not found",404)}if(Sb(r).isDirectory())return Rd("Not found",404);let n=await Ui(r),i=YT[Ga(r)]??"application/octet-stream";return new Response(n,{headers:{"content-type":i}})}var Ad=["observe","backup","restore","restart","resize","version","rotate","expose","delete","logs","slow_queries","users","databases"],yb=new WeakMap;async function bb(e){let t=yb.get(e);if(t)return t;let r=await import("./chunk-x2r1zm2r.js"),n=new r.SpendStore(e),i={store:n,service:new r.SpendService(n),gate:new r.SpendGate(e)};return yb.set(e,i),i}async function ir(e={}){QT();let t=e.cwd??process.cwd(),r=e.host??WT,n=e.port??HT,i=e.cliEntry??process.argv[1];if(e.box)process.env.TS_CLOUD_DASHBOARD_BOX="1";await oA(t);let o=e.config??await Pi(),s=process.env.TS_CLOUD_DASHBOARD_DB_PASSWORD,c=C(o);if(s&&c&&!c.password)c.password=s;let l=o.infrastructure?.compute?.managedServices?.vitess;if(s&&l&&typeof l==="object"&&!l.password)l.password=s;let a=y(t,o);if(a.reconciliation.failed>0)console.warn(` ts-cloud dashboard: marked ${a.reconciliation.failed} orphaned operation(s) as failed after restart.`);let f=Object.keys(o.environments??{}),E=nA(o,e.environment),D=sA(t),N=await ms(o,E),G=new Map([[E,N]]),Y=new Map([[E,Date.now()]]),ee=new Map([[E,Date.now()]]),oe=new Map,be=Math.min(300000,Math.max(5000,Number(process.env.TS_CLOUD_DASHBOARD_REFRESH_MS)||30000)),re=Math.min(1800000,Math.max(60000,Number(process.env.TS_CLOUD_DASHBOARD_SITE_REFRESH_MS)||300000)),_e=H(o)!=="serverless",tt=(I)=>{let Te=G.get(I);if(Te&&!ub(Y.get(I),Date.now(),be))return Promise.resolve(Te);let Ne=oe.get(I);if(Ne)return Ne;let Ce=!_e||ub(ee.get(I),Date.now(),re),qe=ms(o,I,{includeSiteHealth:Ce}).then((ht)=>{let L=G.get(I),Yr=Ce?ht:pA(L,ht);if(G.set(I,Yr),Y.set(I,Date.now()),Ce)ee.set(I,Date.now());if(L?._serverReachable!==Yr._serverReachable||L?._metricsStatus!==Yr._metricsStatus||(L?.sitesDetail?.length??0)!==(Yr.sitesDetail?.length??0))hi();return Yr}).finally(()=>oe.delete(I));return oe.set(I,qe),qe},Ue=ao(t),Gt=process.env.TS_CLOUD_DASHBOARD_TELEMETRY?.trim();if(e.box&&Gt!=="0"&&(Gt==="1"||!o.cloud?.attachTo)){let I=!1,Te=Date.now()+300000,Ne=async()=>{if(I)return;I=!0;try{let qe=Date.now(),ht=qe>=Te;if(ht)Te=qe+300000;let L=a.environments.get(E);await Hn({controlPlane:a.store,projectId:a.project.id,environmentId:L?.id,config:o,environment:E,force:!0,lightweight:!0,includeSiteHealth:ht})}catch(qe){if(e.verbose)console.warn(` ts-cloud dashboard: background telemetry collection failed: ${qe instanceof Error?qe.message:String(qe)}`)}finally{I=!1}};Ne(),setInterval(()=>void Ne(),60000).unref?.()}let ke=new Map,Ye=new Map,At=new Set,Ti=0;function mo(I,Te){if(I.role==="admin"&&!a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`))return I;let Ne=a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`),Ce=Ne?a.store.getMembershipForActor(a.organization.id,Ne.id):void 0;if(!Ce||Ce.status!=="active")return{...I,role:"member",sites:{},capabilities:[]};let qe=a.store.listGrants(Ce.id),ht=a.store.resolveAuthorizationTarget(a.organization.id,Ce.scope)??a.store.resolveAuthorizationTarget(a.organization.id,{type:"project",id:a.project.id}),L=sn({membership:Ce,grants:qe,target:ht});if(Ce.roleTemplate==="owner"||Ce.roleTemplate==="admin")return{...I,role:"admin",sites:{},organizationRole:Ce.roleTemplate,organizationSource:Ce.source,capabilities:L};let Yr=a.environments.get(Te),or={};for(let Xe of a.store.listResources(a.project.id,Yr?.id).filter((ct)=>ct.kind==="application")){let ct=a.store.resolveAuthorizationTarget(a.organization.id,{type:"resource",id:Xe.id});if(!ct||!te({membership:Ce,grants:qe,capability:"project:read",target:ct}).allowed)continue;or[Xe.slug]=te({membership:Ce,grants:qe,capability:"config:write",target:ct}).allowed?"owner":"collaborator"}return{...I,role:"member",sites:or,organizationRole:Ce.roleTemplate,organizationSource:Ce.source,capabilities:L}}function hi(){Ti+=1,ke.clear();for(let I of At)ys(I,{recursive:!0,force:!0});At.clear()}let Ai=(I,Te)=>`${Te}:${I.role==="admin"?"admin":`member:${Object.entries(I.sites).sort(([Ne],[Ce])=>Ne.localeCompare(Ce)).map(([Ne,Ce])=>`${Ne}=${Ce}`).join(",")}`}:${[...I.capabilities??[]].sort().join(",")}`;async function ki(I,Te){let Ne=mo(I,Te),Ce=Ai(Ne,Te),qe=ke.get(Ce);if(qe)return qe;let ht=Ye.get(Ce);if(ht)return ht;let L=Ti,Yr=(async()=>{let or=G.get(Te)??await ms(o,Te);G.set(Te,or);let Xe={...Hl(or,{user:Ne,slug:o.project.slug}),viewer:{role:Ne.role,organizationRole:Ne.organizationRole,organizationSource:Ne.organizationSource,capabilities:Ne.capabilities??[]}},ct=await mA(t,Xe);if(ct&&L!==Ti)return ys(ct,{recursive:!0,force:!0}),Ue?.uiRoot;if(ct)At.add(ct);let Nr=ct??Ue?.uiRoot;if(Nr)ke.set(Ce,Nr);return Nr})();Ye.set(Ce,Yr);try{return await Yr}finally{Ye.delete(Ce)}}let Ri=await ki({username:"",passwordHash:"",role:"admin",sites:{}},E);if(!Ri)throw Error("ts-cloud dashboard UI not found. Run `bun run build` in ts-cloud or reinstall the package.");let Q=new WeakMap,ge=process.env.TS_CLOUD_DASHBOARD_TERMINAL!=="0",Ee=process.env.TS_CLOUD_DASHBOARD_AUTH==="0";if(Ee&&e.box)throw Error("TS_CLOUD_DASHBOARD_AUTH=0 is refused in box mode: the dashboard is internet-facing there, and disabling auth would expose a root shell.");let Re=!Ee,$t=ny(t),Ht=Re?ay(t,process.env.TS_CLOUD_UI_USERNAME?.trim()||"admin"):void 0,Ie=new xe(a.store,{encryptionKey:_(t)}),lt=new je(a.store),rt=new Nt(a.store),Ve=new Yt(a.store,{encryptionKey:_(t)}),Qr=new $n(a.store),bs=new Ln(a.store,{cwd:t}),xi=new On(a.store,{encryptionKey:_(t)}),kt=new b(a.store,{workerId:`dashboard:${process.pid}`}),Lt=new Xt(a.store),qi=new Qt(a.store,_(t)),fo=new Tr(a.store),Wa=new kr(Lt,kt,qi),yo=o.project?.region??"us-east-1",dp=_(t),Gn=new Ar(fo,{encryptionKey:dp,backends:[new Tt(a.store,dp),new Er(new K(yo),yo),new wr(new ze(yo),yo),new Cr]});await nn(Gn,a,o);let Pd=new me(yo),Ib={aws_rds:new An(new Dn(Pd)),aws_aurora:new In(new kn(Pd)),aws_elasticache:new Rn(new _n(new ne(yo))),server:new Pn(new it),container:new Nn(new it)},up=(I)=>Ib[I.provider],sr=new Vn(a.store),Bo=new Br(sr,kt),lp=new zn(qi),Cb={managed_database:new yu(Lt,Pd),logical_database:new Iu(Lt,qi),volume:new Eu,files:new wu(t),control_plane:new Au(a.store,t),infrastructure:new Ru(new Sa(yo))},Eb=(I)=>Cb[I.resourceKind],Tb=(I)=>I.provider==="aws_backup"?void 0:lp,xd=new pt(a.store),Dd=[new _t,new Kr(A(t,"volumes"))],Ji=new Gr(xd,Dd,kt),ua=new Pe(a.store),Oi=new hn(ua,[new nt("aws"),new nt("hetzner"),new nt("ssh")],kt),bo=new yn(a.store),pp=new Sn(bo,ua),jo=new bn(a.store),gp=new vn(jo,kt),Gi=new Tn(a.store),Od=new En(Gi,kt),mp=["releases","artifacts","operations","logs","previews","snapshots","orphaned_resources"].map((I)=>new wn(I,a.store,a.project.id,a.organization.id)),Rr=new Mr(a.store),fp=new jn(Rr,{queue:kt}),Kt=new Ge(a.store),So=new We(a.store),ai=new ot(a.store),Qe=new gt(a.store,{encryptionKey:_(t)}),Ab=()=>bb(a.store);for(let I of a.environments.values())Ur(Rr,o,{organization:a.organization,project:a.project,environment:I,resources:a.store.listResources(a.project.id,I.id)});let ci=new mr(Qe,{emailImpl:async(I)=>{let{email:Te}=await import("./chunk-ank4fmbx.js");return Te.send(I)}}),hp=async(I)=>{let Te=Jr(Qe,a.project.id,I),Ne=[];for(let Ce of Te.filter((qe)=>qe.notify&&qe.alert))Ne.push(...await ci.deliverAll(ci.enqueue(a.organization.id,Ce.alert,Ce.transition)));return Ne.push(...await ci.deliverAll(ci.enqueueRemindersAndEscalations(a.organization.id,Qe.listAlerts(a.project.id,{environmentId:I,states:["firing"]})))),Ne.push(...await ci.retryDue()),{evaluations:Te,deliveries:Ne}},_d=!1,kb=async()=>{if(_d)return;_d=!0;try{for(let I of a.environments.values())for(let Te of Qe.listHealthChecks(a.project.id,I.id).filter((Ne)=>Ne.enabled)){let Ne=Qe.listHealthResults(Te.id,1)[0];if(Ne&&Date.now()-new Date(Ne.checkedAt).getTime()<Te.intervalSeconds*1000)continue;let Ce=await new Me(Qe).runAndEvaluate(Te);for(let qe of Ce.evaluations.filter((ht)=>ht.notify&&ht.alert))await ci.deliverAll(ci.enqueue(a.organization.id,qe.alert,qe.transition))}}finally{_d=!1}},yp=setInterval(()=>{for(let I of a.environments.values())hp(I.id).catch((Te)=>console.error("ts-cloud alert evaluation failed:",Te))},60000);yp.unref?.();let bp=setInterval(()=>{kb().catch((I)=>console.error("ts-cloud health check evaluation failed:",I))},30000);bp.unref?.();let Sp=setInterval(()=>{try{fp.tick()}catch(I){console.error("ts-cloud scheduled job evaluation failed:",I)}},30000);Sp.unref?.();let vp=setInterval(()=>{try{Bo.enqueueDue(),Bo.enqueueRetention()}catch(I){console.error("ts-cloud backup policy evaluation failed:",I)}},30000);vp.unref?.(),Kt.cleanup();let wp=setInterval(()=>{try{Kt.cleanup()}catch(I){console.error("ts-cloud preview cleanup failed:",I)}},3600000);wp.unref?.();let Rb=e.queueWorker??!0,Pb=yA(),xb=async(I,Te)=>{let Ce=(I.environmentId?a.store.listEnvironments(I.projectId).find((qe)=>qe.id===I.environmentId):void 0)?.slug??String(E);if(Te.kind==="dashboard_operation"&&Te.operationId){let qe=G.get(Ce)??N,ht=Mn(Te.operationId,o,qe);if(!ht||ht.danger||!["scheduler","backup","worker"].includes(ht.group))return{ok:!1,stderr:"The allowlisted dashboard operation is no longer available."};let L=await Or(o,Ce,ht);return{ok:L.ok,stdout:L.stdout,stderr:L.stderr??L.error,retryable:/temporar|unavailable|timeout|network/i.test(L.stderr??L.error??""),output:{command:L.command??null,operation:L.operation}}}if(Te.kind==="serverless_scheduler"){let qe=await rp(o,Ce,"run");return{ok:qe.ok,stdout:qe.stdout,stderr:qe.error,retryable:/temporar|unavailable|timeout|network/i.test(qe.error??""),output:{command:qe.command??null,operation:"serverless_scheduler"}}}return{ok:!1,stderr:`No safe executor is configured for ${Te.kind}.`}},Ha=Rb?new ts(kt,{...Ba({store:a.store,execute:async(I,Te)=>{let Ne=Te.operation.input&&typeof Te.operation.input==="object"&&!Array.isArray(Te.operation.input)?Te.operation.input:{},Ce=Ne.source&&typeof Ne.source==="object"?Ne.source:void 0,qe=t,ht,L,Yr;try{if(Ce?.bindingId&&Ce?.connectionId&&Ce?.commitSha){let Xe=Ve.getBinding(String(Ce.bindingId)),ct=Ve.getConnection(String(Ce.connectionId));if(!Xe||!ct||Xe.connectionId!==ct.id)throw Error("Queued source binding is no longer available");let yr=(Xe.repositoryId?Ve.getRepository(Xe.repositoryId):Ve.listRepositories(ct.id).find((Is)=>Is.fullName.toLowerCase()===Xe.repositoryFullName.toLowerCase()))?.cloneUrl;if(!yr&&ct.provider==="generic_ssh")yr=`git@${new URL(ct.host).hostname}:${Xe.repositoryFullName}.git`;if(!yr)yr=new URL(`/${Xe.repositoryFullName}.git`,ct.host.endsWith("/")?ct.host:`${ct.host}/`).href;let Se=Xe.deployKeyId?Ve.getDeployKey(Xe.deployKeyId):void 0,Bt=Se&&Xe.deployKeyId?{...Se,privateKey:Ve.getDeployPrivateKey(Xe.deployKeyId)}:void 0;if(["github","gitlab","bitbucket","gitea"].includes(ct.provider)&&I.target.previewId){let Is=Eo(ct,Ve.getCredential(ct.id)),ue=Kt.previews.getInstance(I.target.previewId);Yr=async(di,Za)=>{try{await Is.setCommitStatus(Xe.repositoryFullName,String(Ce.commitSha),{state:di,url:ue?.url,description:Za})}catch(Es){Te.log(`Could not publish source status: ${Es instanceof Error?Es.message:String(Es)}`,{stream:"stderr"})}},await Yr("pending",`Preview deployment started for ${String(Ce.commitSha).slice(0,12)}`)}ht=cp(Et(kd(),"ts-cloud-queued-source-")),Te.log(`Checking out immutable source commit ${Ce.commitSha}.`,{stream:"system"}),qe=(await Qd({remote:yr,binding:Xe,destination:Et(ht,"checkout"),ref:String(Ce.branch??Xe.defaultBranch),commitSha:String(Ce.commitSha)},{credential:Ve.getCredential(ct.id),deployKey:Bt})).directory}if(Te.operation.kind!=="preview.destroy"){let Xe=I.target.previewId?Kt.previews.getInstance(I.target.previewId):void 0,ct=Xe?Kt.previews.getDefinition(Xe.definitionId):void 0,Nr=Te.operation.resourceId?a.store.getResource(Te.operation.resourceId):void 0;if(L=await Gn.resolve({projectId:a.project.id,environmentId:Te.operation.environmentId,resourceId:Te.operation.resourceId,functionId:Nr?.kind==="function"?Nr.id:void 0,previewId:Xe?.id,trustedPreview:!!Xe&&!Xe.fork,allowedPreviewSecrets:ct?.inheritedSecrets}),L.warnings.some((yr)=>yr.code==="missing_required"))throw Error(`Required deployment configuration is unavailable: ${L.warnings.filter((yr)=>yr.code==="missing_required").map((yr)=>yr.key).join(", ")}`);if(Te.operation.resourceId)for(let yr of Object.values(L.entries))fo.setDependency({entryId:yr.id,resourceId:Te.operation.resourceId,injectionTarget:"environment",required:yr.required,requiresRedeploy:!0});Te.log(`Resolved configuration ${L.configurationHash.slice(0,18)} for ${Object.keys(L.values).length} keys.`,{stream:"system"})}let or=await ap(I,{cwd:qe,cliEntry:i,signal:Te.signal,env:L?.values,onOutput:(Xe,ct)=>Te.log(ct,{stream:Xe,step:"execute",secrets:[...Pb,...Object.entries(L?.entries??{}).filter(([,Nr])=>Nr.kind==="secret").map(([Nr])=>L.values[Nr]).filter(Boolean)]})});if(or.ok&&Te.operation.resourceId&&L)for(let Xe of Object.values(L.entries))fo.setDependency({entryId:Xe.id,resourceId:Te.operation.resourceId,injectionTarget:"environment",required:Xe.required,requiresRedeploy:!1,lastDeployedVersion:Xe.version});return await Yr?.(or.ok?"success":"failure",or.ok?`Preview is ready at ${String(Ce?.commitSha).slice(0,12)}`:`Preview deployment failed at ${String(Ce?.commitSha).slice(0,12)}`),or}catch(or){throw await Yr?.("error",`Preview deployment could not complete at ${String(Ce?.commitSha).slice(0,12)}`),or}finally{if(ht)ys(ht,{recursive:!0,force:!0})}}}),...Vg({store:Rr,executor:xb}),...em({store:Lt,secrets:qi,resolveAdapter:up}),...Uf(ua,Oi.drivers),...ch(jo,[new Cl("aws","AWS regional execution requires an injected AwsRegionalTransport; topology and plans were preserved without provider mutation.")]),...eh({store:Gi,cleanup:mp}),...Ua(xd,Dd),...Yg({store:sr,queue:kt,resolveSource:Eb,resolveDestination:Tb,validateHealth:async(I,Te)=>{if(!I.healthCheckId)return{healthy:!0,mode:"adapter"};let Ne=Qe.getHealthCheck(I.healthCheckId);if(!Ne||Ne.projectId!==I.projectId)return{healthy:!1,error:"Configured restore health check was not found."};let Ce=await new Me(Qe).runAndEvaluate(Ne);return{healthy:Ce.result.status==="healthy",healthCheckId:Ne.id,healthResultId:Ce.result.id,target:Te}}}),...Qp({store:a.store,resolveDriver:e.releaseDriver??((I)=>({name:`${a.store.getResource(I.resourceId)?.provider??"provider"} release driver`,capability:()=>({strategy:I.strategy,supported:!1,explanation:"This dashboard process has no immutable activation driver configured for the target provider.",capacityMultiplier:1,costImpact:"none",rollback:"The previous release remains preserved; configure a release driver before retrying."}),activate:async()=>{throw Error("Immutable activation driver is not configured")},rollback:async()=>{throw Error("Immutable rollback driver is not configured")}})),resolveHealthGate:async(I,Te)=>{let Ne=Qe.listHealthChecks(Te.projectId,Te.environmentId).find((qe)=>qe.enabled&&qe.name===I&&(!qe.resourceId||qe.resourceId===Te.resourceId));if(!Ne)return{healthy:!1,message:`Named health gate ${I} was not found for this release.`};let Ce=await new Me(Qe).runAndEvaluate(Ne);return{healthy:Ce.result.status==="healthy",evidence:{healthCheckId:Ne.id,healthResultId:Ce.result.id,status:Ce.result.status,timings:Ce.result.timings},message:Ce.result.message}}})},{parallelism:e.queueParallelism??(Number(process.env.TS_CLOUD_QUEUE_PARALLELISM)||8),onError:(I)=>console.error("ts-cloud deployment queue worker failed:",I)}):void 0;if(Un(a),dd(rt,le(a,String(E)),N),Ht)ud(a,Ht.users),uy(Ie,a,Ht.users);let Ut=cy({cwd:t,enabled:Re,secret:$t,authentication:Ie,authorization:{store:a.store,organizationId:a.organization.id,projectId:a.project.id,defaultEnvironment:String(E)}}),cr=new Al,Ip=setInterval(()=>cr.sweep(),60000);Ip.unref?.();let Ka=new za,Nd=new za(3,900000,900000),Qa=new za(8,900000,900000),Cp=setInterval(()=>Ka.prune(),300000),Ep=setInterval(()=>Nd.prune(),300000),Tp=setInterval(()=>Qa.prune(),300000);if(Cp.unref?.(),Ep.unref?.(),Tp.unref?.(),Re){if(Ht?.generated)console.warn(`
478
478
  ts-cloud dashboard: created the first admin.
479
479
  username: ${Ht.generated.username}
480
480
  password: ${Ht.generated.password}
@@ -1,3 +1,3 @@
1
- import{De,Wt}from"./chunk-4a8qt6e8.js";import{u,N}from"./chunk-q3xwh0r8.js";import{v}from"./chunk-qsyna6ng.js";import{vt,g}from"./chunk-2q27v6vz.js";import{R}from"./chunk-1j9vy88a.js";import{V}from"./chunk-8tp6srfc.js";import{Mt,z}from"./chunk-0apv4e8e.js";import{$a}from"./chunk-xss6yj73.js";class W{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u(vt(t))}async query(e){let t=new URLSearchParams(N({Version:"2010-08-01",...e})).toString();return this.client.request({service:"monitoring",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t})}async getMetricStatistics(e){let t={Action:"GetMetricStatistics",Namespace:e.Namespace,MetricName:e.MetricName,StartTime:e.StartTime.toISOString(),EndTime:e.EndTime.toISOString(),Period:e.Period};(e.Statistics??[]).forEach((o,f)=>{t[`Statistics.member.${f+1}`]=o}),(e.ExtendedStatistics??[]).forEach((o,f)=>{t[`ExtendedStatistics.member.${f+1}`]=o}),(e.Dimensions??[]).forEach((o,f)=>{t[`Dimensions.member.${f+1}.Name`]=o.Name,t[`Dimensions.member.${f+1}.Value`]=o.Value});let r=await this.query(t),s=(r.GetMetricStatisticsResult||r)?.Datapoints?.member??[];if(!Array.isArray(s))s=s?[s]:[];return s.map((o)=>{let f={},m=o.ExtendedStatistics?.entry;if(m){if(!Array.isArray(m))m=[m];for(let p of m)if(p?.key!=null)f[p.key]=Number(p.value)}return{Timestamp:o.Timestamp,Sum:o.Sum!=null?Number(o.Sum):void 0,Average:o.Average!=null?Number(o.Average):void 0,Maximum:o.Maximum!=null?Number(o.Maximum):void 0,Minimum:o.Minimum!=null?Number(o.Minimum):void 0,Percentiles:Object.keys(f).length?f:void 0,Unit:o.Unit}})}async getMetricSeries(e){let t=/^p\d/.test(e.Stat);return(await this.getMetricStatistics({Namespace:e.Namespace,MetricName:e.MetricName,Dimensions:e.Dimensions,StartTime:e.StartTime,EndTime:e.EndTime,Period:e.Period,Statistics:t?[]:[e.Stat],ExtendedStatistics:t?[e.Stat]:[]})).slice().sort((a,s)=>new Date(a.Timestamp??0).getTime()-new Date(s.Timestamp??0).getTime()).map((a)=>t?a.Percentiles?.[e.Stat]??0:a[e.Stat]??0)}async describeAlarms(e){let t={Action:"DescribeAlarms"};if(e?.AlarmNamePrefix)t.AlarmNamePrefix=e.AlarmNamePrefix;if(e?.MaxRecords)t.MaxRecords=e.MaxRecords;let r=await this.query(t),s=(r.DescribeAlarmsResult||r)?.MetricAlarms?.member??[];if(!Array.isArray(s))s=s?[s]:[];return s.map((o)=>({AlarmName:o.AlarmName,StateValue:o.StateValue,MetricName:o.MetricName,ComparisonOperator:o.ComparisonOperator,Threshold:o.Threshold!=null?Number(o.Threshold):void 0,Namespace:o.Namespace}))}async putMetricAlarm(e){let t={Action:"PutMetricAlarm",AlarmName:e.AlarmName,Namespace:e.Namespace,MetricName:e.MetricName,ComparisonOperator:e.ComparisonOperator,Threshold:e.Threshold,EvaluationPeriods:e.EvaluationPeriods,Period:e.Period,Statistic:e.Statistic};if(e.AlarmDescription)t.AlarmDescription=e.AlarmDescription;(e.Dimensions??[]).forEach((r,a)=>{t[`Dimensions.member.${a+1}.Name`]=r.Name,t[`Dimensions.member.${a+1}.Value`]=r.Value}),(e.AlarmActions??[]).forEach((r,a)=>{t[`AlarmActions.member.${a+1}`]=r}),await this.query(t)}async deleteAlarms(e){if(!e.length)return;let t={Action:"DeleteAlarms"};e.forEach((r,a)=>{t[`AlarmNames.member.${a+1}`]=r}),await this.query(t)}}class ie{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u(void 0,{profile:t})}async createLogGroup(e,t){await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.CreateLogGroup","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({logGroupName:e,...t?{tags:t}:{}})})}async putRetentionPolicy(e,t){if(![1,3,5,7,14,30,60,90,120,150,180,365,400,545,731,1096,1827,2192,2557,2922,3288,3653].includes(t))throw Error("Unsupported CloudWatch Logs retention period");await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.PutRetentionPolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({logGroupName:e,retentionInDays:t})})}async describeLogStreams(e){let t={logGroupName:e.logGroupName};if(e.logStreamNamePrefix)t.logStreamNamePrefix=e.logStreamNamePrefix;if(e.orderBy)t.orderBy=e.orderBy;if(e.descending!==void 0)t.descending=e.descending;if(e.limit)t.limit=e.limit;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.DescribeLogStreams","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async getLogEvents(e){let t={logGroupName:e.logGroupName,logStreamName:e.logStreamName};if(e.startTime)t.startTime=e.startTime;if(e.endTime)t.endTime=e.endTime;if(e.limit)t.limit=e.limit;if(e.startFromHead!==void 0)t.startFromHead=e.startFromHead;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.GetLogEvents","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async describeLogGroups(e){let t={};if(e?.logGroupNamePrefix)t.logGroupNamePrefix=e.logGroupNamePrefix;if(e?.limit)t.limit=e.limit;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.DescribeLogGroups","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async deleteLogGroup(e){await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.DeleteLogGroup","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({logGroupName:e})})}async filterLogEvents(e){let t={logGroupName:e.logGroupName};if(e.logStreamNames)t.logStreamNames=e.logStreamNames;if(e.startTime)t.startTime=e.startTime;if(e.endTime)t.endTime=e.endTime;if(e.filterPattern)t.filterPattern=e.filterPattern;if(e.limit)t.limit=e.limit;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.FilterLogEvents","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}}import{createHash as le}from"node:crypto";import{existsSync as se,mkdirSync as de,readdirSync as ge,readFileSync as pe,rmSync as he,writeFileSync as ye}from"node:fs";import{homedir as fe}from"node:os";import{join as G}from"node:path";var ae=1,ne=3600000,Se=24*ne,Ce=ne,Te=30*Se;function X(){let e=process.env.XDG_CACHE_HOME;return G(e&&e.trim()?e:G(fe(),".cache"),"ts-cloud","cost-explorer")}function Q(e){return G(X(),e??"__default__")}function oe(e){let t={s:e.start,e:e.end,g:e.granularity,m:[...e.metrics].sort(),gb:[...e.groupBy].map((r)=>`${r.Type}:${r.Key}`).sort(),f:e.filter??null};return le("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}function be(e,t){let r=Date.parse(`${t}T00:00:00Z`);if(Number.isNaN(r))return!1;let a=new Date,s=Date.UTC(a.getUTCFullYear(),a.getUTCMonth(),1);return r<=s}function Ne(e){return be(e.start,e.end)?Te:Ce}function me(e,t){let r=G(Q(e),`${oe(t)}.json`);if(!se(r))return null;let a;try{a=JSON.parse(pe(r,"utf-8"))}catch{return null}if(a.schema!==ae)return null;let s=Date.now()-a.savedAt;if(s<0||s>Ne(t))return null;return{response:a.response,ageSeconds:Math.floor(s/1000)}}function ce(e,t,r){let a=Q(e);de(a,{recursive:!0});let s={schema:ae,savedAt:Date.now(),key:t,response:r};ye(G(a,`${oe(t)}.json`),JSON.stringify(s))}function Na(e){let t=e===void 0?X():Q(e);if(!se(t))return{deletedFiles:0,scope:e??"all profiles"};let r=0;function a(s){for(let o of ge(s,{withFileTypes:!0})){let f=G(s,o.name);if(o.isDirectory())a(f);else if(o.isFile()&&o.name.endsWith(".json"))r++}}return a(t),he(t,{recursive:!0,force:!0}),{deletedFiles:r,scope:e??"all profiles"}}function Da(e){return e===void 0?X():Q(e)}class Ve{client;profile;useCache;lastCacheAgeSeconds=null;constructor(e,t){this.profile=e,this.useCache=t?.useCache??!0,this.client=new u(vt(e))}async getCostByService(e){return(await this.getCostByDimension({...e,dimension:"SERVICE"})).map((r)=>({service:r.key,amount:r.amount,unit:r.unit}))}async getCostByDimension(e){let{start:t,end:r,dimension:a,granularity:s="MONTHLY",filter:o}=e,f=["UnblendedCost"],m=[{Type:"DIMENSION",Key:a}],p={start:t,end:r,granularity:s,metrics:f,groupBy:m,filter:o};if(this.useCache){let b=me(this.profile,p);if(b)return this.lastCacheAgeSeconds=b.ageSeconds,b.response}this.lastCacheAgeSeconds=null;let y=new Map,i;do{let b={TimePeriod:{Start:t,End:r},Granularity:s,Metrics:f,GroupBy:m};if(o)b.Filter=o;if(i)b.NextPageToken=i;let E=await this.client.request({service:"ce",region:"us-east-1",method:"POST",path:"/",headers:{"content-type":"application/x-amz-json-1.1","x-amz-target":"AWSInsightsIndexService.GetCostAndUsage"},body:JSON.stringify(b)});for(let K of E?.ResultsByTime??[])for(let A of K?.Groups??[]){let F=A.Keys?.[0]??"Unknown",H=Number.parseFloat(A.Metrics?.UnblendedCost?.Amount??"0"),Y=A.Metrics?.UnblendedCost?.Unit??"USD",O=y.get(F);y.set(F,{key:F,amount:(O?.amount??0)+H,unit:Y})}i=E?.NextPageToken||void 0}while(i);let I=[...y.values()].filter((b)=>b.amount>0).sort((b,E)=>E.amount-b.amount);if(this.useCache)ce(this.profile,p,I);return I}async getDailyTotals(e){return((await this.client.request({service:"ce",region:"us-east-1",method:"POST",path:"/",headers:{"content-type":"application/x-amz-json-1.1","x-amz-target":"AWSInsightsIndexService.GetCostAndUsage"},body:JSON.stringify({TimePeriod:{Start:e.start,End:e.end},Granularity:"DAILY",Metrics:["UnblendedCost"]})}))?.ResultsByTime??[]).map((a)=>Number.parseFloat(a.Total?.UnblendedCost?.Amount??"0"))}}class Z{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}async describeFileSystems(e){let t=[];if(e?.FileSystemId)t.push(`FileSystemId=${encodeURIComponent(e.FileSystemId)}`);if(e?.CreationToken)t.push(`CreationToken=${encodeURIComponent(e.CreationToken)}`);let r=`/2015-02-01/file-systems${t.length>0?`?${t.join("&")}`:""}`;return{FileSystems:((await this.client.request({service:"elasticfilesystem",region:this.region,method:"GET",path:r,headers:{"Content-Type":"application/json"}})).FileSystems||[]).map((s)=>({FileSystemId:s.FileSystemId,Name:s.Name,CreationTime:s.CreationTime,LifeCycleState:s.LifeCycleState,NumberOfMountTargets:s.NumberOfMountTargets,SizeInBytes:s.SizeInBytes?{Value:s.SizeInBytes.Value,Timestamp:s.SizeInBytes.Timestamp}:void 0,PerformanceMode:s.PerformanceMode,Encrypted:s.Encrypted,ThroughputMode:s.ThroughputMode,Tags:s.Tags}))}}}class ee{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}async call(e,t){return this.client.request({service:"wafv2",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`AWSWAF_20190729.${e}`},body:JSON.stringify(t)})}async listWebACLs(e="REGIONAL"){return(await this.call("ListWebACLs",{Scope:e,Limit:100}))?.WebACLs??[]}async getWebACLRules(e,t,r="REGIONAL"){return((await this.call("GetWebACL",{Name:e,Id:t,Scope:r}))?.WebACL?.Rules??[]).map((o)=>({Name:o.Name,Priority:o.Priority,Action:o.Action?Object.keys(o.Action)[0]:o.OverrideAction?Object.keys(o.OverrideAction)[0]:"count"}))}}function ue(e){return String(e).padStart(2,"0")}function _(e){return`${e.getUTCFullYear()}-${ue(e.getUTCMonth()+1)}-${ue(e.getUTCDate())}`}function Ae(e){let t=Math.max(0,Math.round((Date.now()-e)/1000));if(t<60)return`${t}s ago`;let r=Math.round(t/60);if(r<60)return`${r}m ago`;let a=Math.round(r/60);if(a<48)return`${a}h ago`;return`${Math.round(a/24)}d ago`}async function B(e,t,r,a,s,o){let f=await e.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:r,Dimensions:[{Name:"FunctionName",Value:t}],StartTime:s,EndTime:o,Period:86400,Statistics:[a]}).catch(()=>[]);if(!f.length)return 0;if(a==="Sum")return f.reduce((m,p)=>m+(p.Sum??0),0);if(a==="Maximum")return Math.max(...f.map((m)=>m.Maximum??0));return f.reduce((m,p)=>m+(p.Average??0),0)/f.length}async function j(e,t,r,a,s,o,f){let m=await e.getMetricStatistics({Namespace:t,MetricName:r,Dimensions:a,StartTime:o,EndTime:f,Period:86400,Statistics:[s]}).catch(()=>[]);if(!m.length)return 0;if(s==="Sum")return m.reduce((p,y)=>p+(y.Sum??0),0);if(s==="Maximum")return Math.max(...m.map((p)=>p.Maximum??0));return m.reduce((p,y)=>p+(y.Average??0),0)/m.length}async function te(e,t,r,a,s){let o=await e.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Duration",Dimensions:[{Name:"FunctionName",Value:t}],StartTime:a,EndTime:s,Period:86400,ExtendedStatistics:[r]}).catch(()=>[]);return Math.round(o.reduce((f,m)=>f+(m.Percentiles?.[r]??0),0))}async function qn(e,t){let r=await z(e,t),a=r.region,s=new W(a),o=new R(a),f=new ie(a),m=new Date,p=new Date(m.getTime()-86400000),y=e.environments?.[t]?.app,i={};i.app={name:r.slug,env:t,region:a,runtime:y?.kind==="php"?`php-${y?.phpVersion??"8.3"} (fpm)`:y?.kind??"node",url:r.endpoint??"",build:r.lastRelease?.sha?.slice(0,7)??"—",deployedAt:r.lastRelease?.timestamp??"—"},i.maintenance={enabled:!1},i.scheduler={enabled:r.scheduler!=="off",expression:r.scheduler==="sub-minute"?"rate(1 minute) · sub-minute":"rate(1 minute)",lastRun:"—"};let I=0,b=0,E=0,K=[],A=[],F=[];for(let n of r.functions){let[l,d,c,C,h,T,M,x,L]=await Promise.all([B(s,n.name,"Invocations","Sum",p,m),B(s,n.name,"Errors","Sum",p,m),B(s,n.name,"Throttles","Sum",p,m),B(s,n.name,"Duration","Average",p,m),o.getFunction(n.name).catch(()=>null),te(s,n.name,"p50",p,m),te(s,n.name,"p95",p,m),te(s,n.name,"p99",p,m),s.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:n.name}],StartTime:new Date(m.getTime()-43200000),EndTime:m,Period:3600,Stat:"Sum"}).catch(()=>[])]);I+=l,b+=d,E=Math.max(E,C);let U=h?.Configuration?.MemorySize??0,D=Object.keys(h?.Configuration?.Environment?.Variables??{}),q=[],S=0;try{let{events:J=[]}=await f.filterLogEvents({logGroupName:`/aws/lambda/${n.name}`,startTime:p.getTime(),limit:120});for(let w of J){let k=(w.message??"").trim(),re=/Max Memory Used:\s*(\d+)\s*MB/.exec(k);if(re)S=Math.max(S,Number(re[1]));if(k&&!/^(?:START|END|REPORT|INIT_START)/.test(k))F.push({source:n.mode||n.name,timestamp:new Date(w.timestamp??0).toISOString(),when:Ae(w.timestamp??0),message:k.slice(0,400),level:/error|exception|fatal|panic|traceback/i.test(k)?"error":/warn|warning|timeout|retr(?:y|ies)|throttl/i.test(k)?"warn":"info"})}q=J.filter((w)=>!/^(?:START|END|REPORT|INIT_START)/.test((w.message??"").trim())).slice(-6).map((w)=>({ts:new Date(w.timestamp??0).toISOString().slice(11,19),msg:(w.message??"").trim().slice(0,120),err:/error|exception|fatal/i.test(w.message??"")}))}catch{}let P=Math.max(1,...L);K.push({key:n.mode,name:n.name,version:n.version,memory:U,timeout:h?.Configuration?.Timeout??0,runtime:h?.Configuration?.Runtime??"provided.al2023",invocations:Math.round(l),errors:Math.round(d),p95:M||Math.round(C),status:"active",provisioned:n.provisioned?`${n.provisioned.allocated}/${n.provisioned.requested}`:void 0}),A.push({key:n.mode,name:n.name,runtime:h?.Configuration?.Runtime??"provided.al2023",arch:h?.Configuration?.Architectures?.[0]??"x86_64",memory:U,timeout:h?.Configuration?.Timeout??0,ephemeral:h?.Configuration?.EphemeralStorage?.Size??512,version:n.version,concurrency:y?.concurrency??"—",invocations:Math.round(l),errors:Math.round(d),throttles:Math.round(c),p50:T||Math.round(C),p95:M||Math.round(C),p99:x||Math.round(C),maxMem:S,spark:L.length?L.map((J)=>Math.round(J/P*100)):[0],env:D.length?D:["(none)"],recent:q.length?q:[{ts:"—",msg:"no recent events",err:!1}]})}i.functions=K,i.functionsDetail=A,i.serverlessLogs=F.sort((n,l)=>String(l.timestamp).localeCompare(String(n.timestamp))).slice(0,600),i.serverlessLogsEmptyReason=F.length?void 0:"No recent function logs were found in CloudWatch for this environment.";let H=I?Number((b/I*100).toFixed(2)):0,Y=Math.round(await B(s,r.functions[0]?.name??"","ConcurrentExecutions","Maximum",p,m));i.metrics={invocations:Math.round(I),errorRatePct:H,p95Ms:Math.round(E),coldStartPct:void 0,concurrency:Y,estCostUsd:void 0};try{let n=new V(a),l=[],d=[],c=0;try{let{QueueUrl:h}=await n.getQueueUrl(`${r.slug}-${t}-dlq`),{Attributes:T}=await n.getQueueAttributes(h);c=Number(T.ApproximateNumberOfMessages??0)}catch{}let C=y?Wt(y,r.slug,t):[];for(let h of C){let T=h.name.replace(`${r.slug}-${t}-`,""),M=0,x=0;try{let{QueueUrl:U}=await n.getQueueUrl(h.name),{Attributes:D}=await n.getQueueAttributes(U);M=Number(D.ApproximateNumberOfMessages??0),x=Number(D.ApproximateNumberOfMessagesNotVisible??0)}catch{}let L=Math.round(await j(s,"AWS/SQS","NumberOfMessagesDeleted",[{Name:"QueueName",Value:h.name}],"Sum",p,m));l.push({name:T,visible:M,inFlight:x,processed:L,dlq:c}),d.push({name:h.name,short:T,visible:M,inFlight:x,delayed:0,processed:L,oldestSec:0,concurrency:h.concurrency??y?.queueConcurrency??"—",tries:y?.queueTries??3,visTimeout:(y?.queueTimeout??120)*6,dlq:c})}if(l.length)i.queues=l;if(d.length)i.queuesDetail=d;i.dlqItems=[]}catch{}try{let n=new v(a),{Stacks:l}=await n.describeStacks({stackName:De(e,t)}),d={};for(let c of l?.[0]?.Outputs??[])if(c.OutputKey)d[c.OutputKey]=c.OutputValue??"";if(y?.database?.connection==="aurora-serverless"){let c=`${r.slug}-${t}-db`,C=[{Name:"DBClusterIdentifier",Value:c}],[h,T]=await Promise.all([j(s,"AWS/RDS","ServerlessDatabaseCapacity",C,"Average",p,m),j(s,"AWS/RDS","DatabaseConnections",C,"Maximum",p,m)]);if(i.aurora={id:c,engine:"aurora-mysql",minAcu:y?.database?.minCapacity??0.5,maxAcu:y?.database?.maxCapacity??4,currentAcu:h?Number(h.toFixed(1)):y?.database?.minCapacity??0.5,database:"app",connections:Math.round(T),status:d.DbEndpoint?"available":"creating"},y?.rdsProxy)i.proxy={name:`${r.slug}-${t}-proxy`,endpoint:d.DbProxyEndpoint??"—",pooledConns:Math.round(T),status:"available"}}if(y?.cache?.driver==="elasticache"){let c=`${r.slug}-${t}-cache`,C=[{Name:"CacheClusterId",Value:`${c}-001`}],[h,T]=await Promise.all([j(s,"AWS/ElastiCache","CacheHits",C,"Sum",p,m),j(s,"AWS/ElastiCache","CacheMisses",C,"Sum",p,m)]),M=h+T>0?Number((h/(h+T)*100).toFixed(1)):0;i.redis={id:c,node:"cache.t4g.micro",engine:"redis",hitRate:M,status:d.CacheEndpoint?"available":"creating"}}if(y?.efs){let c=0;try{if(d.EfsFileSystemId){let C=new Z(a),{FileSystems:h}=await C.describeFileSystems({FileSystemId:d.EfsFileSystemId});c=Number(((h?.[0]?.SizeInBytes?.Value??0)/1048576).toFixed(1))}}catch{}i.efs={id:d.EfsFileSystemId??"efs",mount:"/mnt/local",sizeMb:c,status:"available"}}i.assetsInfo=d.AssetsCdnDomain?{bucket:d.AssetsBucketName??`${r.slug}-${t}-assets`,cdn:d.AssetsCdnDomain,customDomain:y?.assetDomain??"—",assetUrl:r.assetUrl??"—",files:0,sizeMb:0,cacheHitPct:0,build:i.app.build}:void 0}catch{}if(i.assetsInfo)try{let l=await new g(a).list({bucket:i.assetsInfo.bucket,maxKeys:1000});i.assetsInfo.files=l.length,i.assetsInfo.sizeMb=Number((l.reduce((d,c)=>d+(c.Size??0),0)/1048576).toFixed(1)),i.assetsRecent=l.slice(0,8).map((d)=>({path:`/${d.Key}`,size:`${Math.max(1,Math.round((d.Size??0)/1024))} KB`,type:d.Key.split(".").pop()??""}))}catch{}try{if(y?.secrets){let n=Array.isArray(y.secrets)?y.secrets.map((l)=>({key:l.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),source:l})):Object.entries(y.secrets).map(([l,d])=>({key:l,source:String(d)}));i.secretsList=n.map((l)=>({...l,updated:"—"}))}}catch{}try{let n=new g(a),l=`${r.slug}-${t}-deployments`,d=await n.getObjectJson(l,`deployments/${r.slug}/${t}/history.json`).catch(()=>null);if(d?.records?.length)i.deploymentsDetail=d.records.slice(-12).reverse().map((c)=>({sha:(c.sha??"").slice(0,7),status:c.status??"success",when:c.timestamp??"—",took:c.took??"—",by:c.by??"—",version:c.version??"—",hooks:c.hooks??[]}))}catch{}i.metricsTotals={invocations:i.metrics.invocations,errors:Math.round(b),errorRatePct:H,p95Ms:i.metrics.p95Ms,throttles:A.reduce((n,l)=>n+l.throttles,0),coldStartPct:void 0,estCostUsd:void 0,concurrency:Y},i.metricsPerFn=A.map((n)=>({key:n.key,invocations:n.invocations,errors:n.errors,throttles:n.throttles,avgMs:n.p50,maxMs:n.p99,costUsd:void 0}));try{i.invSpark=await s.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:r.functions.find((n)=>n.mode==="http")?.name??""}],StartTime:new Date(m.getTime()-86400000),EndTime:m,Period:3600,Stat:"Sum"})}catch{}try{let n=new Ve,l=m,d=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),1)),c=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth()-1,1)),[C,h]=await Promise.all([n.getCostByService({start:_(d),end:_(l),granularity:"MONTHLY"}).catch(()=>[]),n.getCostByService({start:_(c),end:_(d),granularity:"MONTHLY"}).catch(()=>[])]);if(C.length){let T=C.reduce((S,P)=>S+P.amount,0),M=h.reduce((S,P)=>S+P.amount,0),x=l.getUTCDate(),L=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth()+1,0)).getUTCDate();i.costSummary={monthToDateUsd:Number(T.toFixed(2)),projectedUsd:Number((T/x*L).toFixed(2)),lastMonthUsd:Number(M.toFixed(2)),dailyAvgUsd:Number((T/x).toFixed(2))},i.costServices=C.filter((S)=>S.amount>0).sort((S,P)=>P.amount-S.amount).slice(0,12).map((S)=>({name:S.service,usd:Number(S.amount.toFixed(2)),note:""})),i.metrics.estCostUsd=Number((T/x).toFixed(2)),i.metricsTotals.estCostUsd=i.metrics.estCostUsd,i.costTrend=await n.getDailyTotals({start:_(d),end:_(l)}).catch(()=>[]);let U=C.find((S)=>/lambda/i.test(S.service))?.amount??0,D=(S)=>S.invocations*(S.p50/1000)*(S.memory/1024),q=A.reduce((S,P)=>S+D(P),0)||1;i.costPerFn=A.map((S)=>({key:S.key,requests:S.invocations,gbSec:Math.round(D(S)),usd:Number((U*(D(S)/q)).toFixed(2))}))}}catch{}if(y?.firewall)try{let n=await s.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"BlockedRequests",StartTime:p,EndTime:m,Period:86400,Statistics:["Sum"]}).catch(()=>[]),l=await s.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"AllowedRequests",StartTime:p,EndTime:m,Period:86400,Statistics:["Sum"]}).catch(()=>[]);i.waf={enabled:!0,scope:"REGIONAL",acl:`${r.slug}-${t}-waf`,allowed24h:Math.round(l.reduce((d,c)=>d+(c.Sum??0),0)),blocked24h:Math.round(n.reduce((d,c)=>d+(c.Sum??0),0))};try{let d=new ee(a),c=await d.listWebACLs("REGIONAL"),C=c.find((h)=>h.Name?.includes(`${r.slug}-${t}`))??c[0];if(C?.Name&&C.Id){i.waf.acl=C.Name;let h=await d.getWebACLRules(C.Name,C.Id,"REGIONAL");if(h.length)i.wafRules=h.map((T)=>({name:T.Name??"—",detail:`priority ${T.Priority??0}`,action:T.Action??"count",blocked24h:0}))}}catch{}}catch{}let O=[];if(i.aurora)O.push({name:"Aurora Serverless v2",detail:`${i.aurora.id} · ${i.aurora.minAcu}-${i.aurora.maxAcu} ACU`,status:i.aurora.status});if(i.proxy)O.push({name:"RDS Proxy",detail:i.proxy.name,status:i.proxy.status});if(i.redis)O.push({name:`ElastiCache (${i.redis.engine})`,detail:`${i.redis.node} · ${i.redis.hitRate}% hit rate`,status:i.redis.status});if(i.efs)O.push({name:"EFS",detail:`${i.efs.mount} · ${i.efs.sizeMb} MB`,status:i.efs.status});if(O.length)i.dataServices=O;if(r.scheduler!=="off"&&y?.kind==="php")try{let n=await Mt(e,t,"schedule:list"),l=[];for(let d of(n||"").split(`
1
+ import{De,Wt}from"./chunk-4a8qt6e8.js";import{u,N}from"./chunk-y5e7dmvc.js";import{v}from"./chunk-5810132y.js";import{vt,g}from"./chunk-ypsgkj91.js";import{R}from"./chunk-qx05kccj.js";import{V}from"./chunk-45v1azhc.js";import{Mt,z}from"./chunk-kfj4w903.js";import{$a}from"./chunk-xss6yj73.js";class W{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u(vt(t))}async query(e){let t=new URLSearchParams(N({Version:"2010-08-01",...e})).toString();return this.client.request({service:"monitoring",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t})}async getMetricStatistics(e){let t={Action:"GetMetricStatistics",Namespace:e.Namespace,MetricName:e.MetricName,StartTime:e.StartTime.toISOString(),EndTime:e.EndTime.toISOString(),Period:e.Period};(e.Statistics??[]).forEach((o,f)=>{t[`Statistics.member.${f+1}`]=o}),(e.ExtendedStatistics??[]).forEach((o,f)=>{t[`ExtendedStatistics.member.${f+1}`]=o}),(e.Dimensions??[]).forEach((o,f)=>{t[`Dimensions.member.${f+1}.Name`]=o.Name,t[`Dimensions.member.${f+1}.Value`]=o.Value});let r=await this.query(t),s=(r.GetMetricStatisticsResult||r)?.Datapoints?.member??[];if(!Array.isArray(s))s=s?[s]:[];return s.map((o)=>{let f={},m=o.ExtendedStatistics?.entry;if(m){if(!Array.isArray(m))m=[m];for(let p of m)if(p?.key!=null)f[p.key]=Number(p.value)}return{Timestamp:o.Timestamp,Sum:o.Sum!=null?Number(o.Sum):void 0,Average:o.Average!=null?Number(o.Average):void 0,Maximum:o.Maximum!=null?Number(o.Maximum):void 0,Minimum:o.Minimum!=null?Number(o.Minimum):void 0,Percentiles:Object.keys(f).length?f:void 0,Unit:o.Unit}})}async getMetricSeries(e){let t=/^p\d/.test(e.Stat);return(await this.getMetricStatistics({Namespace:e.Namespace,MetricName:e.MetricName,Dimensions:e.Dimensions,StartTime:e.StartTime,EndTime:e.EndTime,Period:e.Period,Statistics:t?[]:[e.Stat],ExtendedStatistics:t?[e.Stat]:[]})).slice().sort((a,s)=>new Date(a.Timestamp??0).getTime()-new Date(s.Timestamp??0).getTime()).map((a)=>t?a.Percentiles?.[e.Stat]??0:a[e.Stat]??0)}async describeAlarms(e){let t={Action:"DescribeAlarms"};if(e?.AlarmNamePrefix)t.AlarmNamePrefix=e.AlarmNamePrefix;if(e?.MaxRecords)t.MaxRecords=e.MaxRecords;let r=await this.query(t),s=(r.DescribeAlarmsResult||r)?.MetricAlarms?.member??[];if(!Array.isArray(s))s=s?[s]:[];return s.map((o)=>({AlarmName:o.AlarmName,StateValue:o.StateValue,MetricName:o.MetricName,ComparisonOperator:o.ComparisonOperator,Threshold:o.Threshold!=null?Number(o.Threshold):void 0,Namespace:o.Namespace}))}async putMetricAlarm(e){let t={Action:"PutMetricAlarm",AlarmName:e.AlarmName,Namespace:e.Namespace,MetricName:e.MetricName,ComparisonOperator:e.ComparisonOperator,Threshold:e.Threshold,EvaluationPeriods:e.EvaluationPeriods,Period:e.Period,Statistic:e.Statistic};if(e.AlarmDescription)t.AlarmDescription=e.AlarmDescription;(e.Dimensions??[]).forEach((r,a)=>{t[`Dimensions.member.${a+1}.Name`]=r.Name,t[`Dimensions.member.${a+1}.Value`]=r.Value}),(e.AlarmActions??[]).forEach((r,a)=>{t[`AlarmActions.member.${a+1}`]=r}),await this.query(t)}async deleteAlarms(e){if(!e.length)return;let t={Action:"DeleteAlarms"};e.forEach((r,a)=>{t[`AlarmNames.member.${a+1}`]=r}),await this.query(t)}}class ie{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u(void 0,{profile:t})}async createLogGroup(e,t){await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.CreateLogGroup","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({logGroupName:e,...t?{tags:t}:{}})})}async putRetentionPolicy(e,t){if(![1,3,5,7,14,30,60,90,120,150,180,365,400,545,731,1096,1827,2192,2557,2922,3288,3653].includes(t))throw Error("Unsupported CloudWatch Logs retention period");await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.PutRetentionPolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({logGroupName:e,retentionInDays:t})})}async describeLogStreams(e){let t={logGroupName:e.logGroupName};if(e.logStreamNamePrefix)t.logStreamNamePrefix=e.logStreamNamePrefix;if(e.orderBy)t.orderBy=e.orderBy;if(e.descending!==void 0)t.descending=e.descending;if(e.limit)t.limit=e.limit;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.DescribeLogStreams","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async getLogEvents(e){let t={logGroupName:e.logGroupName,logStreamName:e.logStreamName};if(e.startTime)t.startTime=e.startTime;if(e.endTime)t.endTime=e.endTime;if(e.limit)t.limit=e.limit;if(e.startFromHead!==void 0)t.startFromHead=e.startFromHead;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.GetLogEvents","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async describeLogGroups(e){let t={};if(e?.logGroupNamePrefix)t.logGroupNamePrefix=e.logGroupNamePrefix;if(e?.limit)t.limit=e.limit;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.DescribeLogGroups","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async deleteLogGroup(e){await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.DeleteLogGroup","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({logGroupName:e})})}async filterLogEvents(e){let t={logGroupName:e.logGroupName};if(e.logStreamNames)t.logStreamNames=e.logStreamNames;if(e.startTime)t.startTime=e.startTime;if(e.endTime)t.endTime=e.endTime;if(e.filterPattern)t.filterPattern=e.filterPattern;if(e.limit)t.limit=e.limit;return await this.client.request({service:"logs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"Logs_20140328.FilterLogEvents","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}}import{createHash as le}from"node:crypto";import{existsSync as se,mkdirSync as de,readdirSync as ge,readFileSync as pe,rmSync as he,writeFileSync as ye}from"node:fs";import{homedir as fe}from"node:os";import{join as G}from"node:path";var ae=1,ne=3600000,Se=24*ne,Ce=ne,Te=30*Se;function X(){let e=process.env.XDG_CACHE_HOME;return G(e&&e.trim()?e:G(fe(),".cache"),"ts-cloud","cost-explorer")}function Q(e){return G(X(),e??"__default__")}function oe(e){let t={s:e.start,e:e.end,g:e.granularity,m:[...e.metrics].sort(),gb:[...e.groupBy].map((r)=>`${r.Type}:${r.Key}`).sort(),f:e.filter??null};return le("sha256").update(JSON.stringify(t)).digest("hex").slice(0,24)}function be(e,t){let r=Date.parse(`${t}T00:00:00Z`);if(Number.isNaN(r))return!1;let a=new Date,s=Date.UTC(a.getUTCFullYear(),a.getUTCMonth(),1);return r<=s}function Ne(e){return be(e.start,e.end)?Te:Ce}function me(e,t){let r=G(Q(e),`${oe(t)}.json`);if(!se(r))return null;let a;try{a=JSON.parse(pe(r,"utf-8"))}catch{return null}if(a.schema!==ae)return null;let s=Date.now()-a.savedAt;if(s<0||s>Ne(t))return null;return{response:a.response,ageSeconds:Math.floor(s/1000)}}function ce(e,t,r){let a=Q(e);de(a,{recursive:!0});let s={schema:ae,savedAt:Date.now(),key:t,response:r};ye(G(a,`${oe(t)}.json`),JSON.stringify(s))}function Na(e){let t=e===void 0?X():Q(e);if(!se(t))return{deletedFiles:0,scope:e??"all profiles"};let r=0;function a(s){for(let o of ge(s,{withFileTypes:!0})){let f=G(s,o.name);if(o.isDirectory())a(f);else if(o.isFile()&&o.name.endsWith(".json"))r++}}return a(t),he(t,{recursive:!0,force:!0}),{deletedFiles:r,scope:e??"all profiles"}}function Da(e){return e===void 0?X():Q(e)}class Ve{client;profile;useCache;lastCacheAgeSeconds=null;constructor(e,t){this.profile=e,this.useCache=t?.useCache??!0,this.client=new u(vt(e))}async getCostByService(e){return(await this.getCostByDimension({...e,dimension:"SERVICE"})).map((r)=>({service:r.key,amount:r.amount,unit:r.unit}))}async getCostByDimension(e){let{start:t,end:r,dimension:a,granularity:s="MONTHLY",filter:o}=e,f=["UnblendedCost"],m=[{Type:"DIMENSION",Key:a}],p={start:t,end:r,granularity:s,metrics:f,groupBy:m,filter:o};if(this.useCache){let b=me(this.profile,p);if(b)return this.lastCacheAgeSeconds=b.ageSeconds,b.response}this.lastCacheAgeSeconds=null;let y=new Map,i;do{let b={TimePeriod:{Start:t,End:r},Granularity:s,Metrics:f,GroupBy:m};if(o)b.Filter=o;if(i)b.NextPageToken=i;let E=await this.client.request({service:"ce",region:"us-east-1",method:"POST",path:"/",headers:{"content-type":"application/x-amz-json-1.1","x-amz-target":"AWSInsightsIndexService.GetCostAndUsage"},body:JSON.stringify(b)});for(let K of E?.ResultsByTime??[])for(let A of K?.Groups??[]){let F=A.Keys?.[0]??"Unknown",H=Number.parseFloat(A.Metrics?.UnblendedCost?.Amount??"0"),Y=A.Metrics?.UnblendedCost?.Unit??"USD",O=y.get(F);y.set(F,{key:F,amount:(O?.amount??0)+H,unit:Y})}i=E?.NextPageToken||void 0}while(i);let I=[...y.values()].filter((b)=>b.amount>0).sort((b,E)=>E.amount-b.amount);if(this.useCache)ce(this.profile,p,I);return I}async getDailyTotals(e){return((await this.client.request({service:"ce",region:"us-east-1",method:"POST",path:"/",headers:{"content-type":"application/x-amz-json-1.1","x-amz-target":"AWSInsightsIndexService.GetCostAndUsage"},body:JSON.stringify({TimePeriod:{Start:e.start,End:e.end},Granularity:"DAILY",Metrics:["UnblendedCost"]})}))?.ResultsByTime??[]).map((a)=>Number.parseFloat(a.Total?.UnblendedCost?.Amount??"0"))}}class Z{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}async describeFileSystems(e){let t=[];if(e?.FileSystemId)t.push(`FileSystemId=${encodeURIComponent(e.FileSystemId)}`);if(e?.CreationToken)t.push(`CreationToken=${encodeURIComponent(e.CreationToken)}`);let r=`/2015-02-01/file-systems${t.length>0?`?${t.join("&")}`:""}`;return{FileSystems:((await this.client.request({service:"elasticfilesystem",region:this.region,method:"GET",path:r,headers:{"Content-Type":"application/json"}})).FileSystems||[]).map((s)=>({FileSystemId:s.FileSystemId,Name:s.Name,CreationTime:s.CreationTime,LifeCycleState:s.LifeCycleState,NumberOfMountTargets:s.NumberOfMountTargets,SizeInBytes:s.SizeInBytes?{Value:s.SizeInBytes.Value,Timestamp:s.SizeInBytes.Timestamp}:void 0,PerformanceMode:s.PerformanceMode,Encrypted:s.Encrypted,ThroughputMode:s.ThroughputMode,Tags:s.Tags}))}}}class ee{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}async call(e,t){return this.client.request({service:"wafv2",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`AWSWAF_20190729.${e}`},body:JSON.stringify(t)})}async listWebACLs(e="REGIONAL"){return(await this.call("ListWebACLs",{Scope:e,Limit:100}))?.WebACLs??[]}async getWebACLRules(e,t,r="REGIONAL"){return((await this.call("GetWebACL",{Name:e,Id:t,Scope:r}))?.WebACL?.Rules??[]).map((o)=>({Name:o.Name,Priority:o.Priority,Action:o.Action?Object.keys(o.Action)[0]:o.OverrideAction?Object.keys(o.OverrideAction)[0]:"count"}))}}function ue(e){return String(e).padStart(2,"0")}function _(e){return`${e.getUTCFullYear()}-${ue(e.getUTCMonth()+1)}-${ue(e.getUTCDate())}`}function Ae(e){let t=Math.max(0,Math.round((Date.now()-e)/1000));if(t<60)return`${t}s ago`;let r=Math.round(t/60);if(r<60)return`${r}m ago`;let a=Math.round(r/60);if(a<48)return`${a}h ago`;return`${Math.round(a/24)}d ago`}async function B(e,t,r,a,s,o){let f=await e.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:r,Dimensions:[{Name:"FunctionName",Value:t}],StartTime:s,EndTime:o,Period:86400,Statistics:[a]}).catch(()=>[]);if(!f.length)return 0;if(a==="Sum")return f.reduce((m,p)=>m+(p.Sum??0),0);if(a==="Maximum")return Math.max(...f.map((m)=>m.Maximum??0));return f.reduce((m,p)=>m+(p.Average??0),0)/f.length}async function j(e,t,r,a,s,o,f){let m=await e.getMetricStatistics({Namespace:t,MetricName:r,Dimensions:a,StartTime:o,EndTime:f,Period:86400,Statistics:[s]}).catch(()=>[]);if(!m.length)return 0;if(s==="Sum")return m.reduce((p,y)=>p+(y.Sum??0),0);if(s==="Maximum")return Math.max(...m.map((p)=>p.Maximum??0));return m.reduce((p,y)=>p+(y.Average??0),0)/m.length}async function te(e,t,r,a,s){let o=await e.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Duration",Dimensions:[{Name:"FunctionName",Value:t}],StartTime:a,EndTime:s,Period:86400,ExtendedStatistics:[r]}).catch(()=>[]);return Math.round(o.reduce((f,m)=>f+(m.Percentiles?.[r]??0),0))}async function qn(e,t){let r=await z(e,t),a=r.region,s=new W(a),o=new R(a),f=new ie(a),m=new Date,p=new Date(m.getTime()-86400000),y=e.environments?.[t]?.app,i={};i.app={name:r.slug,env:t,region:a,runtime:y?.kind==="php"?`php-${y?.phpVersion??"8.3"} (fpm)`:y?.kind??"node",url:r.endpoint??"",build:r.lastRelease?.sha?.slice(0,7)??"—",deployedAt:r.lastRelease?.timestamp??"—"},i.maintenance={enabled:!1},i.scheduler={enabled:r.scheduler!=="off",expression:r.scheduler==="sub-minute"?"rate(1 minute) · sub-minute":"rate(1 minute)",lastRun:"—"};let I=0,b=0,E=0,K=[],A=[],F=[];for(let n of r.functions){let[l,d,c,C,h,T,M,x,L]=await Promise.all([B(s,n.name,"Invocations","Sum",p,m),B(s,n.name,"Errors","Sum",p,m),B(s,n.name,"Throttles","Sum",p,m),B(s,n.name,"Duration","Average",p,m),o.getFunction(n.name).catch(()=>null),te(s,n.name,"p50",p,m),te(s,n.name,"p95",p,m),te(s,n.name,"p99",p,m),s.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:n.name}],StartTime:new Date(m.getTime()-43200000),EndTime:m,Period:3600,Stat:"Sum"}).catch(()=>[])]);I+=l,b+=d,E=Math.max(E,C);let U=h?.Configuration?.MemorySize??0,D=Object.keys(h?.Configuration?.Environment?.Variables??{}),q=[],S=0;try{let{events:J=[]}=await f.filterLogEvents({logGroupName:`/aws/lambda/${n.name}`,startTime:p.getTime(),limit:120});for(let w of J){let k=(w.message??"").trim(),re=/Max Memory Used:\s*(\d+)\s*MB/.exec(k);if(re)S=Math.max(S,Number(re[1]));if(k&&!/^(?:START|END|REPORT|INIT_START)/.test(k))F.push({source:n.mode||n.name,timestamp:new Date(w.timestamp??0).toISOString(),when:Ae(w.timestamp??0),message:k.slice(0,400),level:/error|exception|fatal|panic|traceback/i.test(k)?"error":/warn|warning|timeout|retr(?:y|ies)|throttl/i.test(k)?"warn":"info"})}q=J.filter((w)=>!/^(?:START|END|REPORT|INIT_START)/.test((w.message??"").trim())).slice(-6).map((w)=>({ts:new Date(w.timestamp??0).toISOString().slice(11,19),msg:(w.message??"").trim().slice(0,120),err:/error|exception|fatal/i.test(w.message??"")}))}catch{}let P=Math.max(1,...L);K.push({key:n.mode,name:n.name,version:n.version,memory:U,timeout:h?.Configuration?.Timeout??0,runtime:h?.Configuration?.Runtime??"provided.al2023",invocations:Math.round(l),errors:Math.round(d),p95:M||Math.round(C),status:"active",provisioned:n.provisioned?`${n.provisioned.allocated}/${n.provisioned.requested}`:void 0}),A.push({key:n.mode,name:n.name,runtime:h?.Configuration?.Runtime??"provided.al2023",arch:h?.Configuration?.Architectures?.[0]??"x86_64",memory:U,timeout:h?.Configuration?.Timeout??0,ephemeral:h?.Configuration?.EphemeralStorage?.Size??512,version:n.version,concurrency:y?.concurrency??"—",invocations:Math.round(l),errors:Math.round(d),throttles:Math.round(c),p50:T||Math.round(C),p95:M||Math.round(C),p99:x||Math.round(C),maxMem:S,spark:L.length?L.map((J)=>Math.round(J/P*100)):[0],env:D.length?D:["(none)"],recent:q.length?q:[{ts:"—",msg:"no recent events",err:!1}]})}i.functions=K,i.functionsDetail=A,i.serverlessLogs=F.sort((n,l)=>String(l.timestamp).localeCompare(String(n.timestamp))).slice(0,600),i.serverlessLogsEmptyReason=F.length?void 0:"No recent function logs were found in CloudWatch for this environment.";let H=I?Number((b/I*100).toFixed(2)):0,Y=Math.round(await B(s,r.functions[0]?.name??"","ConcurrentExecutions","Maximum",p,m));i.metrics={invocations:Math.round(I),errorRatePct:H,p95Ms:Math.round(E),coldStartPct:void 0,concurrency:Y,estCostUsd:void 0};try{let n=new V(a),l=[],d=[],c=0;try{let{QueueUrl:h}=await n.getQueueUrl(`${r.slug}-${t}-dlq`),{Attributes:T}=await n.getQueueAttributes(h);c=Number(T.ApproximateNumberOfMessages??0)}catch{}let C=y?Wt(y,r.slug,t):[];for(let h of C){let T=h.name.replace(`${r.slug}-${t}-`,""),M=0,x=0;try{let{QueueUrl:U}=await n.getQueueUrl(h.name),{Attributes:D}=await n.getQueueAttributes(U);M=Number(D.ApproximateNumberOfMessages??0),x=Number(D.ApproximateNumberOfMessagesNotVisible??0)}catch{}let L=Math.round(await j(s,"AWS/SQS","NumberOfMessagesDeleted",[{Name:"QueueName",Value:h.name}],"Sum",p,m));l.push({name:T,visible:M,inFlight:x,processed:L,dlq:c}),d.push({name:h.name,short:T,visible:M,inFlight:x,delayed:0,processed:L,oldestSec:0,concurrency:h.concurrency??y?.queueConcurrency??"—",tries:y?.queueTries??3,visTimeout:(y?.queueTimeout??120)*6,dlq:c})}if(l.length)i.queues=l;if(d.length)i.queuesDetail=d;i.dlqItems=[]}catch{}try{let n=new v(a),{Stacks:l}=await n.describeStacks({stackName:De(e,t)}),d={};for(let c of l?.[0]?.Outputs??[])if(c.OutputKey)d[c.OutputKey]=c.OutputValue??"";if(y?.database?.connection==="aurora-serverless"){let c=`${r.slug}-${t}-db`,C=[{Name:"DBClusterIdentifier",Value:c}],[h,T]=await Promise.all([j(s,"AWS/RDS","ServerlessDatabaseCapacity",C,"Average",p,m),j(s,"AWS/RDS","DatabaseConnections",C,"Maximum",p,m)]);if(i.aurora={id:c,engine:"aurora-mysql",minAcu:y?.database?.minCapacity??0.5,maxAcu:y?.database?.maxCapacity??4,currentAcu:h?Number(h.toFixed(1)):y?.database?.minCapacity??0.5,database:"app",connections:Math.round(T),status:d.DbEndpoint?"available":"creating"},y?.rdsProxy)i.proxy={name:`${r.slug}-${t}-proxy`,endpoint:d.DbProxyEndpoint??"—",pooledConns:Math.round(T),status:"available"}}if(y?.cache?.driver==="elasticache"){let c=`${r.slug}-${t}-cache`,C=[{Name:"CacheClusterId",Value:`${c}-001`}],[h,T]=await Promise.all([j(s,"AWS/ElastiCache","CacheHits",C,"Sum",p,m),j(s,"AWS/ElastiCache","CacheMisses",C,"Sum",p,m)]),M=h+T>0?Number((h/(h+T)*100).toFixed(1)):0;i.redis={id:c,node:"cache.t4g.micro",engine:"redis",hitRate:M,status:d.CacheEndpoint?"available":"creating"}}if(y?.efs){let c=0;try{if(d.EfsFileSystemId){let C=new Z(a),{FileSystems:h}=await C.describeFileSystems({FileSystemId:d.EfsFileSystemId});c=Number(((h?.[0]?.SizeInBytes?.Value??0)/1048576).toFixed(1))}}catch{}i.efs={id:d.EfsFileSystemId??"efs",mount:"/mnt/local",sizeMb:c,status:"available"}}i.assetsInfo=d.AssetsCdnDomain?{bucket:d.AssetsBucketName??`${r.slug}-${t}-assets`,cdn:d.AssetsCdnDomain,customDomain:y?.assetDomain??"—",assetUrl:r.assetUrl??"—",files:0,sizeMb:0,cacheHitPct:0,build:i.app.build}:void 0}catch{}if(i.assetsInfo)try{let l=await new g(a).list({bucket:i.assetsInfo.bucket,maxKeys:1000});i.assetsInfo.files=l.length,i.assetsInfo.sizeMb=Number((l.reduce((d,c)=>d+(c.Size??0),0)/1048576).toFixed(1)),i.assetsRecent=l.slice(0,8).map((d)=>({path:`/${d.Key}`,size:`${Math.max(1,Math.round((d.Size??0)/1024))} KB`,type:d.Key.split(".").pop()??""}))}catch{}try{if(y?.secrets){let n=Array.isArray(y.secrets)?y.secrets.map((l)=>({key:l.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),source:l})):Object.entries(y.secrets).map(([l,d])=>({key:l,source:String(d)}));i.secretsList=n.map((l)=>({...l,updated:"—"}))}}catch{}try{let n=new g(a),l=`${r.slug}-${t}-deployments`,d=await n.getObjectJson(l,`deployments/${r.slug}/${t}/history.json`).catch(()=>null);if(d?.records?.length)i.deploymentsDetail=d.records.slice(-12).reverse().map((c)=>({sha:(c.sha??"").slice(0,7),status:c.status??"success",when:c.timestamp??"—",took:c.took??"—",by:c.by??"—",version:c.version??"—",hooks:c.hooks??[]}))}catch{}i.metricsTotals={invocations:i.metrics.invocations,errors:Math.round(b),errorRatePct:H,p95Ms:i.metrics.p95Ms,throttles:A.reduce((n,l)=>n+l.throttles,0),coldStartPct:void 0,estCostUsd:void 0,concurrency:Y},i.metricsPerFn=A.map((n)=>({key:n.key,invocations:n.invocations,errors:n.errors,throttles:n.throttles,avgMs:n.p50,maxMs:n.p99,costUsd:void 0}));try{i.invSpark=await s.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:r.functions.find((n)=>n.mode==="http")?.name??""}],StartTime:new Date(m.getTime()-86400000),EndTime:m,Period:3600,Stat:"Sum"})}catch{}try{let n=new Ve,l=m,d=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),1)),c=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth()-1,1)),[C,h]=await Promise.all([n.getCostByService({start:_(d),end:_(l),granularity:"MONTHLY"}).catch(()=>[]),n.getCostByService({start:_(c),end:_(d),granularity:"MONTHLY"}).catch(()=>[])]);if(C.length){let T=C.reduce((S,P)=>S+P.amount,0),M=h.reduce((S,P)=>S+P.amount,0),x=l.getUTCDate(),L=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth()+1,0)).getUTCDate();i.costSummary={monthToDateUsd:Number(T.toFixed(2)),projectedUsd:Number((T/x*L).toFixed(2)),lastMonthUsd:Number(M.toFixed(2)),dailyAvgUsd:Number((T/x).toFixed(2))},i.costServices=C.filter((S)=>S.amount>0).sort((S,P)=>P.amount-S.amount).slice(0,12).map((S)=>({name:S.service,usd:Number(S.amount.toFixed(2)),note:""})),i.metrics.estCostUsd=Number((T/x).toFixed(2)),i.metricsTotals.estCostUsd=i.metrics.estCostUsd,i.costTrend=await n.getDailyTotals({start:_(d),end:_(l)}).catch(()=>[]);let U=C.find((S)=>/lambda/i.test(S.service))?.amount??0,D=(S)=>S.invocations*(S.p50/1000)*(S.memory/1024),q=A.reduce((S,P)=>S+D(P),0)||1;i.costPerFn=A.map((S)=>({key:S.key,requests:S.invocations,gbSec:Math.round(D(S)),usd:Number((U*(D(S)/q)).toFixed(2))}))}}catch{}if(y?.firewall)try{let n=await s.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"BlockedRequests",StartTime:p,EndTime:m,Period:86400,Statistics:["Sum"]}).catch(()=>[]),l=await s.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"AllowedRequests",StartTime:p,EndTime:m,Period:86400,Statistics:["Sum"]}).catch(()=>[]);i.waf={enabled:!0,scope:"REGIONAL",acl:`${r.slug}-${t}-waf`,allowed24h:Math.round(l.reduce((d,c)=>d+(c.Sum??0),0)),blocked24h:Math.round(n.reduce((d,c)=>d+(c.Sum??0),0))};try{let d=new ee(a),c=await d.listWebACLs("REGIONAL"),C=c.find((h)=>h.Name?.includes(`${r.slug}-${t}`))??c[0];if(C?.Name&&C.Id){i.waf.acl=C.Name;let h=await d.getWebACLRules(C.Name,C.Id,"REGIONAL");if(h.length)i.wafRules=h.map((T)=>({name:T.Name??"—",detail:`priority ${T.Priority??0}`,action:T.Action??"count",blocked24h:0}))}}catch{}}catch{}let O=[];if(i.aurora)O.push({name:"Aurora Serverless v2",detail:`${i.aurora.id} · ${i.aurora.minAcu}-${i.aurora.maxAcu} ACU`,status:i.aurora.status});if(i.proxy)O.push({name:"RDS Proxy",detail:i.proxy.name,status:i.proxy.status});if(i.redis)O.push({name:`ElastiCache (${i.redis.engine})`,detail:`${i.redis.node} · ${i.redis.hitRate}% hit rate`,status:i.redis.status});if(i.efs)O.push({name:"EFS",detail:`${i.efs.mount} · ${i.efs.sizeMb} MB`,status:i.efs.status});if(O.length)i.dataServices=O;if(r.scheduler!=="off"&&y?.kind==="php")try{let n=await Mt(e,t,"schedule:list"),l=[];for(let d of(n||"").split(`
2
2
  `)){let c=/^\s*([\d*/,\-\s]+?)\s{2,}(.+?)(?:\s{2,}Next Due.*)?$/.exec(d);if(c&&/[*\d]/.test(c[1])&&c[1].trim().split(/\s+/).length===5)l.push({command:c[2].trim().replace(/^php artisan /,""),cron:c[1].trim(),desc:"",lastRun:"—",lastStatus:"ok"})}if(l.length)i.schedulerTasks=l}catch{}return i.topology=$a(i,{project:e.project.name,environment:t}),i}
3
3
  export{ie,W,Na,Da,Ve,qn};